File indexing completed on 2024-12-08 08:10:31

0001 /***************************************************************************
0002  *   Copyright (C) 2005 by David Saxton                                    *
0003  *   david@bluehaze.org                                                    *
0004  *                                                                         *
0005  *   This program is free software; you can redistribute it and/or modify  *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  ***************************************************************************/
0010 
0011 #include "picprogrammer.h"
0012 #include "languagemanager.h"
0013 #include "logview.h"
0014 
0015 #include <KLocalizedString>
0016 #include <KMessageBox>
0017 #include <KProcess>
0018 #include <KSharedConfig>
0019 #include <KShell>
0020 
0021 #include <QApplication>
0022 #include <QFile>
0023 #include <QRegExp>
0024 #include <QTextStream>
0025 
0026 #include <stdio.h>
0027 
0028 #include <ktlconfig.h>
0029 #include <ktechlab_debug.h>
0030 
0031 // BEGIN class ProgrammerConfig
0032 ProgrammerConfig::ProgrammerConfig()
0033 {
0034 }
0035 
0036 void ProgrammerConfig::reset()
0037 {
0038     initCommand = QString();
0039     readCommand = QString();
0040     writeCommand = QString();
0041     verifyCommand = QString();
0042     blankCheckCommand = QString();
0043     eraseCommand = QString();
0044 }
0045 // END class ProgrammerConfig
0046 
0047 // BEGIN class PicProgrammerSettings
0048 bool PicProgrammerSettings::m_bDoneStaticConfigsInit = false;
0049 ProgrammerConfigMap PicProgrammerSettings::m_staticConfigs = ProgrammerConfigMap();
0050 
0051 PicProgrammerSettings::PicProgrammerSettings()
0052 {
0053     if (!m_bDoneStaticConfigsInit)
0054         initStaticConfigs();
0055 }
0056 
0057 void PicProgrammerSettings::initStaticConfigs()
0058 {
0059     m_bDoneStaticConfigsInit = true;
0060     ProgrammerConfig config;
0061 
0062     config.description = i18n("Supported programmers: %1", QString("JuPic, PICStart Plus, Warp-13"));
0063     config.description += i18n("<br>Interface: Serial Port");
0064     config.initCommand = "";
0065     config.readCommand = "picp %port %device -rp %file";
0066     config.writeCommand = "picp %port %device -wp %file";
0067     config.verifyCommand = "";
0068     config.blankCheckCommand = "picp %port %device -b";
0069     config.eraseCommand = "picp %port %device -e";
0070     //  config.executable = "picp";
0071     m_staticConfigs["PICP"] = config;
0072 
0073     config.description = i18n("Supported programmers: %1", QString("Epic Plus"));
0074     config.description += i18n("<br>Interface: Parallel Port");
0075     config.initCommand = "odyssey init";
0076     config.readCommand = "odyssey %device read %file";
0077     config.writeCommand = "odyssey %device write %file";
0078     config.verifyCommand = "odyssey %device verify %file";
0079     config.blankCheckCommand = "odyssey %device blankcheck";
0080     config.eraseCommand = "odyssey %device erase";
0081     //  config.executable = "odyssey";
0082     m_staticConfigs["Odyssey"] = config;
0083 
0084     config.description = i18n("Supported programmers: %1", QString("JDM PIC-Programmer 2, PIC-PG2C"));
0085     config.description += i18n("<br>Interface: Serial Port");
0086     config.initCommand = "";
0087     config.readCommand = "picprog --output %file --pic %port";
0088     config.writeCommand = "picprog --burn --input %file --pic %port --device %device";
0089     config.verifyCommand = "";
0090     config.blankCheckCommand = "";
0091     config.eraseCommand = "picprog --erase --pic %device";
0092     m_staticConfigs["PICProg"] = config;
0093 
0094     config.description = i18n("Supported programmers: %1", QString("Epic Plus"));
0095     config.description += i18n("<br>Interface: Parallel Port");
0096     config.initCommand = "";
0097     config.readCommand = "dump84 --dump-all --output=%file";
0098     config.writeCommand = "prog84 --intel16=%file";
0099     config.verifyCommand = "";
0100     config.blankCheckCommand = "";
0101     config.eraseCommand = "prog84 --clear";
0102     m_staticConfigs["prog84"] = config;
0103 
0104     config.description = i18n("Supported programmers: %1", QString("Kit 149, Kit 150"));
0105     config.description += i18n("<br>Interface: USB Port");
0106     config.initCommand = "";
0107     config.readCommand = "pp -d %device -r %file";
0108     config.writeCommand = "pp -d %device -w %file";
0109     config.verifyCommand = "pp -d %device -v %file";
0110     config.blankCheckCommand = "";
0111     config.eraseCommand = "pp -d %device -e";
0112     m_staticConfigs["PP"] = config;
0113 
0114     config.description = i18n("Supported programmers: %1", QString("Wisp628"));
0115     config.description += i18n("<br>Interface: Serial Port");
0116     config.initCommand = "";
0117     config.readCommand = "xwisp ID %device PORT %device DUMP";
0118     config.writeCommand = "xwisp ID %device PORT %device WRITE %file";
0119     config.verifyCommand = "";
0120     config.blankCheckCommand = "";
0121     config.eraseCommand = "xwisp ID %device PORT %device ERASE";
0122     m_staticConfigs["XWisp"] = config;
0123 
0124 #if 0
0125     config.description = i18n("Supported programmers: %1", QString("Epic Plus, JDM PIC-Programmer 2, PICCOLO, PICCOLO Grande, Trivial HVP Programmer"));
0126     config.description += i18n("<br>Interface: Serial Port and Parallel Port");
0127     config.initCommand = "";
0128     config.readCommand = "";
0129     config.writeCommand = "";
0130     config.verifyCommand = "";
0131     config.blankCheckCommand = "";
0132     config.eraseCommand = "";
0133     config.executable = "pkp";
0134     m_staticConfigs[ "PiKdev" ] = config;
0135     config.executable = "";
0136 
0137 
0138     config.description = i18n("Supported programmers: %1", QString("Trivial LVP programmer, Trivial HVP Programmer"));
0139     config.description += i18n("<br>Interface: Parallel Port");
0140     config.initCommand = "";
0141     config.readCommand = "";
0142     config.writeCommand = "";
0143     config.verifyCommand = "";
0144     config.blankCheckCommand = "";
0145     config.eraseCommand = "";
0146     m_staticConfigs[ "PicPrg2" ] = config;
0147 
0148 
0149     config.description = i18n("Supported programmers: %1", QString("El Cheapo"));
0150     config.description += i18n("<br>Interface: Parallel Port");
0151     config.initCommand = "";
0152     config.readCommand = "";
0153     config.writeCommand = "";
0154     config.verifyCommand = "";
0155     config.blankCheckCommand = "";
0156     config.eraseCommand = "";
0157     m_staticConfigs[ "PP06" ] = config;
0158 
0159 
0160     config.description = i18n("Supported programmers: %1", QString("NOPPP"));
0161     config.description += i18n("<br>Interface: Parallel Port");
0162     config.initCommand = "";
0163     config.readCommand = "";
0164     config.writeCommand = "";
0165     config.verifyCommand = "";
0166     config.blankCheckCommand = "";
0167     config.eraseCommand = "";
0168     m_staticConfigs[ "NOPPP" ] = config;
0169 
0170 
0171     config.description = i18n("Supported programmers: %1", QString("SNOPPP"));
0172     config.description += i18n("<br>Interface: Parallel Port");
0173     config.initCommand = "";
0174     config.readCommand = "";
0175     config.writeCommand = "";
0176     config.verifyCommand = "";
0177     config.blankCheckCommand = "";
0178     config.eraseCommand = "";
0179     m_staticConfigs[ "SNOPPP" ] = config;
0180 #endif
0181 }
0182 
0183 void PicProgrammerSettings::load(KConfig *config)
0184 {
0185     QStringList oldCustomProgrammers = config->groupList().filter("CustomProgrammer_");
0186     QStringList::iterator ocpEnd = oldCustomProgrammers.end();
0187     for (QStringList::iterator it = oldCustomProgrammers.begin(); it != ocpEnd; ++it) {
0188         // The CustomProgrammer_ string we searched for might appear half way through... (don't want)
0189         if ((*it).startsWith("CustomProgrammer_")) {
0190             // config->setGroup(*it);
0191             KConfigGroup grProg = config->group(*it);
0192 
0193             ProgrammerConfig pc;
0194             pc.initCommand = grProg.readEntry("InitCommand");
0195             pc.readCommand = grProg.readEntry("ReadCommand");
0196             pc.writeCommand = grProg.readEntry("WriteCommand");
0197             pc.verifyCommand = grProg.readEntry("VerifyCommand");
0198             pc.blankCheckCommand = grProg.readEntry("BlankCheckCommand");
0199             pc.eraseCommand = grProg.readEntry("EraseCommand");
0200 
0201             QString name = grProg.readEntry("Name");
0202             m_customConfigs[name] = pc;
0203         }
0204     }
0205 }
0206 
0207 void PicProgrammerSettings::save(KConfig *config)
0208 {
0209     QStringList oldCustomProgrammers = config->groupList().filter("CustomProgrammer_");
0210     QStringList::iterator ocpEnd = oldCustomProgrammers.end();
0211     for (QStringList::iterator it = oldCustomProgrammers.begin(); it != ocpEnd; ++it) {
0212         // The CustomProgrammer_ string we searched for might appear half way through... (don't want)
0213         if ((*it).startsWith("CustomProgrammer_"))
0214             config->deleteGroup(*it);
0215     }
0216 
0217     int at = 0;
0218     ProgrammerConfigMap::iterator end = m_customConfigs.end();
0219     for (ProgrammerConfigMap::iterator it = m_customConfigs.begin(); it != end; ++it) {
0220         // config->setGroup( QString("CustomProgrammer_%1").arg(at++) );
0221         QString grName = QString("CustomProgrammer_%1").arg(at++);
0222         KConfigGroup gr = config->group(grName);
0223 
0224         gr.writeEntry("Name", it.key());
0225         gr.writeEntry("InitCommand", it.value().initCommand);
0226         gr.writeEntry("ReadCommand", it.value().readCommand);
0227         gr.writeEntry("WriteCommand", it.value().writeCommand);
0228         gr.writeEntry("VerifyCommand", it.value().verifyCommand);
0229         gr.writeEntry("BlankCheckCommand", it.value().blankCheckCommand);
0230         gr.writeEntry("EraseCommand", it.value().eraseCommand);
0231     }
0232 }
0233 
0234 ProgrammerConfig PicProgrammerSettings::config(const QString &name)
0235 {
0236     if (name.isEmpty())
0237         return ProgrammerConfig();
0238 
0239     QString l = name.toLower();
0240 
0241     ProgrammerConfigMap::const_iterator end = m_customConfigs.end();
0242     for (ProgrammerConfigMap::const_iterator it = m_customConfigs.begin(); it != end; ++it) {
0243         if (it.key().toLower() == l)
0244             return *it;
0245     }
0246 
0247     end = m_staticConfigs.end();
0248     for (ProgrammerConfigMap::const_iterator it = m_staticConfigs.begin(); it != end; ++it) {
0249         if (it.key().toLower() == l)
0250             return *it;
0251     }
0252 
0253     return m_customConfigs[name];
0254 }
0255 
0256 void PicProgrammerSettings::removeConfig(const QString &name)
0257 {
0258     if (isPredefined(name)) {
0259         qCWarning(KTL_LOG) << "Cannot remove a predefined PIC programmer configuration.";
0260         return;
0261     }
0262 
0263     QString l = name.toLower();
0264 
0265     ProgrammerConfigMap::iterator end = m_customConfigs.end();
0266     for (ProgrammerConfigMap::iterator it = m_customConfigs.begin(); it != end; ++it) {
0267         if (it.key().toLower() == l) {
0268             m_customConfigs.erase(it);
0269             return;
0270         }
0271     }
0272 }
0273 
0274 void PicProgrammerSettings::saveConfig(const QString &name, const ProgrammerConfig &config)
0275 {
0276     if (isPredefined(name)) {
0277         qCWarning(KTL_LOG) << "Cannot save to a predefined PIC programmer configuration.";
0278         return;
0279     }
0280 
0281     QString l = name.toLower();
0282 
0283     ProgrammerConfigMap::iterator end = m_customConfigs.end();
0284     for (ProgrammerConfigMap::iterator it = m_customConfigs.begin(); it != end; ++it) {
0285         if (it.key().toLower() == l) {
0286             *it = config;
0287             return;
0288         }
0289     }
0290 
0291     m_customConfigs[name] = config;
0292 }
0293 
0294 QStringList PicProgrammerSettings::configNames(bool makeLowercase) const
0295 {
0296     if (!makeLowercase)
0297         return m_customConfigs.keys() + m_staticConfigs.keys();
0298 
0299     QStringList names;
0300 
0301     ProgrammerConfigMap::const_iterator end = m_customConfigs.end();
0302     for (ProgrammerConfigMap::const_iterator it = m_customConfigs.begin(); it != end; ++it)
0303         names << it.key().toLower();
0304 
0305     end = m_staticConfigs.end();
0306     for (ProgrammerConfigMap::const_iterator it = m_staticConfigs.begin(); it != end; ++it)
0307         names << it.key().toLower();
0308 
0309     return names;
0310 }
0311 
0312 bool PicProgrammerSettings::isPredefined(const QString &name) const
0313 {
0314     QString l = name.toLower();
0315 
0316     ProgrammerConfigMap::const_iterator end = m_staticConfigs.end();
0317     for (ProgrammerConfigMap::const_iterator it = m_staticConfigs.begin(); it != end; ++it) {
0318         if (it.key().toLower() == l)
0319             return true;
0320     }
0321 
0322     return false;
0323 }
0324 // END class PicProgrammerSettings
0325 
0326 // BEGIN class PicProgrammer
0327 PicProgrammer::PicProgrammer(ProcessChain *processChain)
0328     : ExternalLanguage(processChain, "PicProgrammer")
0329 {
0330     m_successfulMessage = i18n("*** Programming successful ***");
0331     m_failedMessage = i18n("*** Programming failed ***");
0332 }
0333 
0334 PicProgrammer::~PicProgrammer()
0335 {
0336 }
0337 
0338 void PicProgrammer::processInput(ProcessOptions options)
0339 {
0340     resetLanguageProcess();
0341     m_processOptions = options;
0342 
0343     PicProgrammerSettings settings;
0344     // settings.load( kapp->config() );
0345     KSharedConfigPtr cfgPtr = KSharedConfig::openConfig();
0346     settings.load(cfgPtr.data());
0347 
0348     QString program = options.m_program;
0349     if (!settings.configNames(true).contains(program.toLower())) {
0350         qCCritical(KTL_LOG) << "Invalid program";
0351         finish(false);
0352         return;
0353     }
0354 
0355     ProgrammerConfig config = settings.config(program);
0356 
0357     QString command = config.writeCommand;
0358     command.replace("%port", options.m_port);
0359     command.replace("%device", QString(options.m_picID).remove("P"));
0360     command.replace("%file", KShell::quoteArg(options.inputFiles().first()));
0361 
0362     // m_languageProcess->setUseShell( true ); // 2017.10.08 - port to KProcess
0363     //*m_languageProcess << command;
0364     m_languageProcess->setShellCommand(command);
0365 
0366     if (!start()) {
0367         //      KMessageBox::error( LanguageManager::self()->logView(), i18n("Could not program PIC.") );
0368         processInitFailed();
0369         return;
0370     }
0371 }
0372 
0373 bool PicProgrammer::isError(const QString &message) const
0374 {
0375     return message.contains("Error", Qt::CaseInsensitive);
0376 }
0377 
0378 bool PicProgrammer::isWarning(const QString &message) const
0379 {
0380     return message.contains("Warning", Qt::CaseInsensitive);
0381 }
0382 
0383 ProcessOptions::ProcessPath::Path PicProgrammer::outputPath(ProcessOptions::ProcessPath::Path inputPath) const
0384 {
0385     switch (inputPath) {
0386     case ProcessOptions::ProcessPath::PIC_AssemblyAbsolute:
0387     case ProcessOptions::ProcessPath::Program_PIC:
0388         return ProcessOptions::ProcessPath::None;
0389 
0390     case ProcessOptions::ProcessPath::AssemblyAbsolute_PIC:
0391     case ProcessOptions::ProcessPath::AssemblyAbsolute_Program:
0392     case ProcessOptions::ProcessPath::AssemblyRelocatable_Library:
0393     case ProcessOptions::ProcessPath::AssemblyRelocatable_Object:
0394     case ProcessOptions::ProcessPath::AssemblyRelocatable_PIC:
0395     case ProcessOptions::ProcessPath::AssemblyRelocatable_Program:
0396     case ProcessOptions::ProcessPath::C_AssemblyRelocatable:
0397     case ProcessOptions::ProcessPath::C_Library:
0398     case ProcessOptions::ProcessPath::C_Object:
0399     case ProcessOptions::ProcessPath::C_PIC:
0400     case ProcessOptions::ProcessPath::C_Program:
0401     case ProcessOptions::ProcessPath::FlowCode_AssemblyAbsolute:
0402     case ProcessOptions::ProcessPath::FlowCode_Microbe:
0403     case ProcessOptions::ProcessPath::FlowCode_PIC:
0404     case ProcessOptions::ProcessPath::FlowCode_Program:
0405     case ProcessOptions::ProcessPath::Microbe_AssemblyAbsolute:
0406     case ProcessOptions::ProcessPath::Microbe_PIC:
0407     case ProcessOptions::ProcessPath::Microbe_Program:
0408     case ProcessOptions::ProcessPath::Object_Disassembly:
0409     case ProcessOptions::ProcessPath::Object_Library:
0410     case ProcessOptions::ProcessPath::Object_PIC:
0411     case ProcessOptions::ProcessPath::Object_Program:
0412     case ProcessOptions::ProcessPath::Program_Disassembly:
0413     case ProcessOptions::ProcessPath::Invalid:
0414     case ProcessOptions::ProcessPath::None:
0415         return ProcessOptions::ProcessPath::Invalid;
0416     }
0417 
0418     return ProcessOptions::ProcessPath::Invalid;
0419 }
0420 // END class PicProgrammer