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