Merge branch 'master' of github.com:john30/ebusd
This commit is contained in:
@@ -574,7 +574,7 @@ result_t BusHandler::handleSymbol() {
|
|||||||
setState(bs_skip, result);
|
setState(bs_skip, result);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
clockGettime(&sentTime); // for measuring arbitration delay in enhanced protocol
|
clockGettime(&sentTime); // for measuring arbitration delay in enhanced protocol
|
||||||
}
|
}
|
||||||
|
|
||||||
// receive next symbol (optionally check reception of sent symbol)
|
// receive next symbol (optionally check reception of sent symbol)
|
||||||
@@ -658,7 +658,7 @@ result_t BusHandler::handleSymbol() {
|
|||||||
setState(m_state, RESULT_ERR_BUS_LOST);
|
setState(m_state, RESULT_ERR_BUS_LOST);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: // only as_none
|
default: // only as_none
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (sentAutoSyn && !sending) {
|
if (sentAutoSyn && !sending) {
|
||||||
@@ -1013,7 +1013,7 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit
|
|||||||
m_currentRequest = nullptr;
|
m_currentRequest = nullptr;
|
||||||
}
|
}
|
||||||
if (state == bs_skip) {
|
if (state == bs_skip) {
|
||||||
m_device->startArbitration(SYN); // reset arbitration state
|
m_device->startArbitration(SYN); // reset arbitration state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1049,7 +1049,6 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit
|
|||||||
} else if (m_state == bs_noSignal) {
|
} else if (m_state == bs_noSignal) {
|
||||||
logNotice(lf_bus, "signal acquired");
|
logNotice(lf_bus, "signal acquired");
|
||||||
}
|
}
|
||||||
// logDebug(lf_bus, "state: from %s to %s with %s", getStateCode(m_state), getStateCode(state), getResultCode(result));
|
|
||||||
m_state = state;
|
m_state = state;
|
||||||
|
|
||||||
if (state == bs_ready || state == bs_skip) {
|
if (state == bs_ready || state == bs_skip) {
|
||||||
|
|||||||
+9
-9
@@ -297,12 +297,12 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
|||||||
opt->initialSend = true;
|
opt->initialSend = true;
|
||||||
break;
|
break;
|
||||||
case O_DEVLAT: // --latency=10
|
case O_DEVLAT: // --latency=10
|
||||||
value = parseInt(arg, 10, 0, 200000, &result); // backwards compatible (micros)
|
value = parseInt(arg, 10, 0, 200000, &result); // backwards compatible (micros)
|
||||||
if (result != RESULT_OK || (value<=1000 && value>200)) { // backwards compatible (micros)
|
if (result != RESULT_OK || (value <= 1000 && value > 200)) { // backwards compatible (micros)
|
||||||
argp_error(state, "invalid latency");
|
argp_error(state, "invalid latency");
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
opt->extraLatency = value > 1000 ? value/1000 : value; // backwards compatible (micros)
|
opt->extraLatency = value > 1000 ? value/1000 : value; // backwards compatible (micros)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Message configuration options:
|
// Message configuration options:
|
||||||
@@ -379,12 +379,12 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
|||||||
opt->answer = true;
|
opt->answer = true;
|
||||||
break;
|
break;
|
||||||
case O_ACQTIM: // --acquiretimeout=10
|
case O_ACQTIM: // --acquiretimeout=10
|
||||||
value = parseInt(arg, 10, 1, 100000, &result); // backwards compatible (micros)
|
value = parseInt(arg, 10, 1, 100000, &result); // backwards compatible (micros)
|
||||||
if (result != RESULT_OK || (value<=1000 && value>100)) { // backwards compatible (micros)
|
if (result != RESULT_OK || (value <= 1000 && value > 100)) { // backwards compatible (micros)
|
||||||
argp_error(state, "invalid acquiretimeout");
|
argp_error(state, "invalid acquiretimeout");
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
opt->acquireTimeout = value > 1000 ? value/1000 : value; // backwards compatible (micros)
|
opt->acquireTimeout = value > 1000 ? value/1000 : value; // backwards compatible (micros)
|
||||||
break;
|
break;
|
||||||
case O_ACQRET: // --acquireretries=3
|
case O_ACQRET: // --acquireretries=3
|
||||||
opt->acquireRetries = parseInt(arg, 10, 0, 10, &result);
|
opt->acquireRetries = parseInt(arg, 10, 0, 10, &result);
|
||||||
@@ -401,12 +401,12 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case O_RCVTIM: // --receivetimeout=25
|
case O_RCVTIM: // --receivetimeout=25
|
||||||
value = parseInt(arg, 10, 1, 100000, &result); // backwards compatible (micros)
|
value = parseInt(arg, 10, 1, 100000, &result); // backwards compatible (micros)
|
||||||
if (result != RESULT_OK || (value<=1000 && value>100)) { // backwards compatible (micros)
|
if (result != RESULT_OK || (value <= 1000 && value > 100)) { // backwards compatible (micros)
|
||||||
argp_error(state, "invalid receivetimeout");
|
argp_error(state, "invalid receivetimeout");
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
opt->receiveTimeout = value > 1000 ? value/1000 : value; // backwards compatible (micros)
|
opt->receiveTimeout = value > 1000 ? value/1000 : value; // backwards compatible (micros)
|
||||||
break;
|
break;
|
||||||
case O_MASCNT: // --numbermasters=0
|
case O_MASCNT: // --numbermasters=0
|
||||||
opt->masterCount = parseInt(arg, 10, 0, 25, &result);
|
opt->masterCount = parseInt(arg, 10, 0, 25, &result);
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ void MainLoop::run() {
|
|||||||
lastScanAddress = 0;
|
lastScanAddress = 0;
|
||||||
scanStatus = "finished";
|
scanStatus = "finished";
|
||||||
} else {
|
} else {
|
||||||
if (scanStatus!="running") {
|
if (scanStatus != "running") {
|
||||||
scanStatus = "running";
|
scanStatus = "running";
|
||||||
}
|
}
|
||||||
nextCheckRun = now + CHECK_INITIAL_DELAY;
|
nextCheckRun = now + CHECK_INITIAL_DELAY;
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ static error_t mqtt_parse_opt(int key, char *arg, struct argp_state *state) {
|
|||||||
}
|
}
|
||||||
g_keypass = replaceSecret(arg);
|
g_keypass = replaceSecret(arg);
|
||||||
break;
|
break;
|
||||||
case O_INSE: //--mqttinsecure
|
case O_INSE: //--mqttinsecure
|
||||||
g_insecure = true;
|
g_insecure = true;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@@ -647,19 +647,25 @@ void MqttHandler::notifyTopic(const string& topic, const string& data) {
|
|||||||
if (isList) {
|
if (isList) {
|
||||||
logOtherInfo("mqtt", "received list topic for %s %s", circuit.c_str(), name.c_str());
|
logOtherInfo("mqtt", "received list topic for %s %s", circuit.c_str(), name.c_str());
|
||||||
deque<Message*> messages;
|
deque<Message*> messages;
|
||||||
bool circuitPrefix = circuit.length()>0 && circuit.find_last_of('*')==circuit.length()-1;
|
bool circuitPrefix = circuit.length()>0 && circuit.find_last_of('*') == circuit.length()-1;
|
||||||
if (circuitPrefix) {
|
if (circuitPrefix) {
|
||||||
circuit = circuit.substr(0, circuit.length()-1);
|
circuit = circuit.substr(0, circuit.length()-1);
|
||||||
}
|
}
|
||||||
bool namePrefix = name.length()>0 && name.find_last_of('*')==name.length()-1;
|
bool namePrefix = name.length()>0 && name.find_last_of('*') == name.length()-1;
|
||||||
if (namePrefix) {
|
if (namePrefix) {
|
||||||
name = name.substr(0, name.length()-1);
|
name = name.substr(0, name.length()-1);
|
||||||
}
|
}
|
||||||
m_messages->findAll(circuit, name, m_levels, !(circuitPrefix || namePrefix), true, true, true, true, true, 0, 0, false, &messages);
|
m_messages->findAll(circuit, name, m_levels, !(circuitPrefix || namePrefix), true, true,
|
||||||
|
true, true, true, 0, 0, false, &messages);
|
||||||
bool onlyWithData = !data.empty();
|
bool onlyWithData = !data.empty();
|
||||||
for (const auto message : messages) {
|
for (const auto message : messages) {
|
||||||
if (circuitPrefix && (message->getCircuit().substr(0, circuit.length())!=circuit || !namePrefix && name.length()>0 && message->getName()!=name)
|
if ((circuitPrefix && (
|
||||||
|| namePrefix && (message->getName().substr(0, name.length())!=name || !circuitPrefix && circuit.length()>0 && message->getCircuit()!=circuit)) {
|
message->getCircuit().substr(0, circuit.length()) != circuit
|
||||||
|
|| (!namePrefix && name.length() > 0 && message->getName() != name)))
|
||||||
|
|| (namePrefix && (
|
||||||
|
message->getName().substr(0, name.length()) != name
|
||||||
|
|| (!circuitPrefix && circuit.length() > 0 && message->getCircuit() != circuit)))
|
||||||
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
time_t lastup = message->getLastUpdateTime();
|
time_t lastup = message->getLastUpdateTime();
|
||||||
@@ -806,7 +812,7 @@ void MqttHandler::run() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
publishTopic(signalTopic, "false", true);
|
publishTopic(signalTopic, "false", true);
|
||||||
publishTopic(m_globalTopic+"scan", "", true); // clear retain of scan status
|
publishTopic(m_globalTopic+"scan", "", true); // clear retain of scan status
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MqttHandler::handleTraffic(bool allowReconnect) {
|
bool MqttHandler::handleTraffic(bool allowReconnect) {
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ class MqttHandler : public DataSink, public DataSource, public WaitThread {
|
|||||||
// @copydoc
|
// @copydoc
|
||||||
void notifyScanStatus(const string& scanStatus) override;
|
void notifyScanStatus(const string& scanStatus) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// @copydoc
|
// @copydoc
|
||||||
void run() override;
|
void run() override;
|
||||||
|
|
||||||
|
|||||||
+14
-12
@@ -39,6 +39,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <ios>
|
#include <ios>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
@@ -103,13 +104,13 @@ Device* Device::create(const char* name, unsigned int extraLatency, bool checkDe
|
|||||||
char* addrpos = in;
|
char* addrpos = in;
|
||||||
char* portpos = strchr(addrpos, ':');
|
char* portpos = strchr(addrpos, ':');
|
||||||
if (!enhanced && portpos >= addrpos+3 && strncmp(addrpos, "enh", 3) == 0) {
|
if (!enhanced && portpos >= addrpos+3 && strncmp(addrpos, "enh", 3) == 0) {
|
||||||
enhanced = true; // support enhtcp:<ip>:<port> and enhudp:<ip>:<port>
|
enhanced = true; // support enhtcp:<ip>:<port> and enhudp:<ip>:<port>
|
||||||
addrpos += 3;
|
addrpos += 3;
|
||||||
if (portpos == addrpos) {
|
if (portpos == addrpos) {
|
||||||
addrpos++;
|
addrpos++;
|
||||||
portpos = strchr(addrpos, ':');
|
portpos = strchr(addrpos, ':');
|
||||||
}
|
}
|
||||||
} // else: support enh:<ip>:<port> defaulting to TCP
|
} // else: support enh:<ip>:<port> defaulting to TCP
|
||||||
if (portpos == addrpos+3 && (strncmp(addrpos, "tcp", 3) == 0 || (udp=(strncmp(addrpos, "udp", 3) == 0)))) {
|
if (portpos == addrpos+3 && (strncmp(addrpos, "tcp", 3) == 0 || (udp=(strncmp(addrpos, "udp", 3) == 0)))) {
|
||||||
addrpos += 4;
|
addrpos += 4;
|
||||||
portpos = strchr(addrpos, ':');
|
portpos = strchr(addrpos, ':');
|
||||||
@@ -141,7 +142,7 @@ result_t Device::open() {
|
|||||||
result_t Device::afterOpen() {
|
result_t Device::afterOpen() {
|
||||||
m_bufLen = 0;
|
m_bufLen = 0;
|
||||||
if (m_enhancedProto) {
|
if (m_enhancedProto) {
|
||||||
symbol_t buf[2] = makeEnhancedSequence(ENH_REQ_INIT, 0); // TODO define additional feature flags
|
symbol_t buf[2] = makeEnhancedSequence(ENH_REQ_INIT, 0); // TODO define additional feature flags
|
||||||
if (::write(m_fd, buf, 2) != 2) {
|
if (::write(m_fd, buf, 2) != 2) {
|
||||||
return RESULT_ERR_SEND;
|
return RESULT_ERR_SEND;
|
||||||
}
|
}
|
||||||
@@ -210,7 +211,7 @@ bool Device::cancelRunningArbitration(ArbitrationState* arbitrationState) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result_t Device::recv(unsigned int timeout, symbol_t* value, ArbitrationState* arbitrationState) {
|
result_t Device::recv(unsigned int timeout, symbol_t* value, ArbitrationState* arbitrationState) {
|
||||||
if (m_arbitrationMaster!=SYN) {
|
if (m_arbitrationMaster != SYN) {
|
||||||
*arbitrationState = as_running;
|
*arbitrationState = as_running;
|
||||||
}
|
}
|
||||||
if (!isValid()) {
|
if (!isValid()) {
|
||||||
@@ -320,7 +321,7 @@ result_t Device::recv(unsigned int timeout, symbol_t* value, ArbitrationState* a
|
|||||||
result_t Device::startArbitration(symbol_t masterAddress) {
|
result_t Device::startArbitration(symbol_t masterAddress) {
|
||||||
if (m_arbitrationCheck) {
|
if (m_arbitrationCheck) {
|
||||||
if (masterAddress != SYN) {
|
if (masterAddress != SYN) {
|
||||||
return RESULT_ERR_ARB_RUNNING; // should not occur
|
return RESULT_ERR_ARB_RUNNING; // should not occur
|
||||||
}
|
}
|
||||||
m_arbitrationCheck = false;
|
m_arbitrationCheck = false;
|
||||||
m_arbitrationMaster = SYN;
|
m_arbitrationMaster = SYN;
|
||||||
@@ -439,7 +440,7 @@ bool Device::read(symbol_t* value, bool isAvailable, ArbitrationState* arbitrati
|
|||||||
}
|
}
|
||||||
#ifdef DEBUG_RAW_TRAFFIC
|
#ifdef DEBUG_RAW_TRAFFIC
|
||||||
fprintf(stdout, "raw <");
|
fprintf(stdout, "raw <");
|
||||||
for (int pos=0; pos<size; pos++) {
|
for (int pos=0; pos < size; pos++) {
|
||||||
fprintf(stdout, " %2.2x", m_buffer[m_bufLen+pos]);
|
fprintf(stdout, " %2.2x", m_buffer[m_bufLen+pos]);
|
||||||
}
|
}
|
||||||
fprintf(stdout, "\n");
|
fprintf(stdout, "\n");
|
||||||
@@ -467,8 +468,8 @@ bool Device::read(symbol_t* value, bool isAvailable, ArbitrationState* arbitrati
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
uint8_t kind = ch&ENH_BYTE_MASK;
|
uint8_t kind = ch&ENH_BYTE_MASK;
|
||||||
if (kind == ENH_BYTE1 && m_bufLen<2) {
|
if (kind == ENH_BYTE1 && m_bufLen < 2) {
|
||||||
return false; // transfer not complete yet
|
return false; // transfer not complete yet
|
||||||
}
|
}
|
||||||
m_bufPos = (m_bufPos+1)%m_bufSize;
|
m_bufPos = (m_bufPos+1)%m_bufSize;
|
||||||
m_bufLen--;
|
m_bufLen--;
|
||||||
@@ -488,8 +489,8 @@ bool Device::read(symbol_t* value, bool isAvailable, ArbitrationState* arbitrati
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
symbol_t data = (symbol_t)(((ch&0x03)<<6) | (ch2&0x3f));
|
symbol_t data = (symbol_t)(((ch&0x03) << 6) | (ch2&0x3f));
|
||||||
symbol_t cmd = (ch>>2)&0xf;
|
symbol_t cmd = (ch >> 2)&0xf;
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case ENH_RES_STARTED:
|
case ENH_RES_STARTED:
|
||||||
*arbitrationState = as_won;
|
*arbitrationState = as_won;
|
||||||
@@ -527,7 +528,7 @@ bool Device::read(symbol_t* value, bool isAvailable, ArbitrationState* arbitrati
|
|||||||
case ENH_RES_ERROR_HOST:
|
case ENH_RES_ERROR_HOST:
|
||||||
if (m_listener != nullptr) {
|
if (m_listener != nullptr) {
|
||||||
ostringstream stream;
|
ostringstream stream;
|
||||||
stream << (cmd==ENH_RES_ERROR_EBUS ? "eBUS comm error: " : "host comm error: ");
|
stream << (cmd == ENH_RES_ERROR_EBUS ? "eBUS comm error: " : "host comm error: ");
|
||||||
switch (data) {
|
switch (data) {
|
||||||
case ENH_ERR_FRAMING:
|
case ENH_ERR_FRAMING:
|
||||||
stream << "framing";
|
stream << "framing";
|
||||||
@@ -547,7 +548,8 @@ bool Device::read(symbol_t* value, bool isAvailable, ArbitrationState* arbitrati
|
|||||||
default:
|
default:
|
||||||
if (m_listener != nullptr) {
|
if (m_listener != nullptr) {
|
||||||
ostringstream stream;
|
ostringstream stream;
|
||||||
stream << "unexpected enhanced command 0x" << std::setw(2) << std::setfill('0') << std::hex << static_cast<unsigned>(cmd);
|
stream << "unexpected enhanced command 0x" << std::setw(2) << std::setfill('0') << std::hex
|
||||||
|
<< static_cast<unsigned>(cmd);
|
||||||
string str = stream.str();
|
string str = stream.str();
|
||||||
m_listener->notifyStatus(true, str.c_str());
|
m_listener->notifyStatus(true, str.c_str());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ class RotateFile {
|
|||||||
* @param textMode whether to write each byte with prefixed timestamp and direction as text.
|
* @param textMode whether to write each byte with prefixed timestamp and direction as text.
|
||||||
* @param flushBuffer the size of the flush buffer.
|
* @param flushBuffer the size of the flush buffer.
|
||||||
*/
|
*/
|
||||||
RotateFile(const string fileName, const unsigned int maxSize, const bool textMode = false, const unsigned int flushBuffer = 16)
|
RotateFile(const string fileName, const unsigned int maxSize, const bool textMode = false,
|
||||||
|
const unsigned int flushBuffer = 16)
|
||||||
: m_enabled(false), m_fileName(fileName), m_maxSize(maxSize), m_textMode(textMode), m_stream(), m_fileSize(0),
|
: m_enabled(false), m_fileName(fileName), m_maxSize(maxSize), m_textMode(textMode), m_stream(), m_fileSize(0),
|
||||||
m_flushSize(0), m_flushBuffer(flushBuffer) {}
|
m_flushSize(0), m_flushBuffer(flushBuffer) {}
|
||||||
|
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ string fetchData(ebusd::TCPSocket* socket, bool listening) {
|
|||||||
}
|
}
|
||||||
} else if (newInput) {
|
} else if (newInput) {
|
||||||
getline(cin, message);
|
getline(cin, message);
|
||||||
if (message.length()==0) {
|
if (message.length() == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sendmessage = message+'\n';
|
sendmessage = message+'\n';
|
||||||
|
|||||||
+140
-122
@@ -1,5 +1,21 @@
|
|||||||
#include <iostream>
|
/*
|
||||||
#include <fstream>
|
* ebusd - daemon for communication with eBUS heating systems.
|
||||||
|
* Copyright (C) 2020-2021 John Baier <ebusd@ebusd.eu>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@@ -7,11 +23,13 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <argp.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <argp.h>
|
|
||||||
#include "intelhex/intelhexclass.h"
|
#include "intelhex/intelhexclass.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -106,7 +124,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
|||||||
ip = strdup(arg);
|
ip = strdup(arg);
|
||||||
part = strtok(ip, ".");
|
part = strtok(ip, ".");
|
||||||
|
|
||||||
for (pos=0; part && pos<4; pos++) {
|
for (pos=0; part && pos < 4; pos++) {
|
||||||
if (!parseByte(part, 0, 255, setIpAddress+pos)) {
|
if (!parseByte(part, 0, 255, setIpAddress+pos)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -114,7 +132,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
|||||||
part = strtok(nullptr, ".");
|
part = strtok(nullptr, ".");
|
||||||
}
|
}
|
||||||
free(ip);
|
free(ip);
|
||||||
if (pos!=4 || part || sum==0) {
|
if (pos != 4 || part || sum == 0) {
|
||||||
argp_error(state, "invalid IP address");
|
argp_error(state, "invalid IP address");
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
@@ -175,10 +193,10 @@ typedef union
|
|||||||
uint16_t data_length;
|
uint16_t data_length;
|
||||||
uint8_t EE_key_1;
|
uint8_t EE_key_1;
|
||||||
uint8_t EE_key_2;
|
uint8_t EE_key_2;
|
||||||
uint8_t address_L;
|
uint8_t address_L;
|
||||||
uint8_t address_H;
|
uint8_t address_H;
|
||||||
uint8_t address_U;
|
uint8_t address_U;
|
||||||
uint8_t address_unused;
|
uint8_t address_unused;
|
||||||
uint8_t data[2*WRITE_FLASH_BLOCKSIZE];
|
uint8_t data[2*WRITE_FLASH_BLOCKSIZE];
|
||||||
};
|
};
|
||||||
uint8_t buffer[2*WRITE_FLASH_BLOCKSIZE+9];
|
uint8_t buffer[2*WRITE_FLASH_BLOCKSIZE+9];
|
||||||
@@ -198,9 +216,9 @@ typedef union
|
|||||||
#define RESET_DEVICE 9
|
#define RESET_DEVICE 9
|
||||||
#define CALC_CRC 10
|
#define CALC_CRC 10
|
||||||
|
|
||||||
#define MINOR_VERSION 0x08 // Version
|
#define MINOR_VERSION 0x08 // Version
|
||||||
#define MAJOR_VERSION 0x00
|
#define MAJOR_VERSION 0x00
|
||||||
//#define STX 0x55 // Actually code 0x55 is 'U' But this is what the autobaud feature of the PIC16F1 EUSART is looking for
|
//#define STX 0x55 // Actually code 0x55 is 'U' But this is what the autobaud feature of the PIC16F1 EUSART is looking for
|
||||||
#define ERROR_ADDRESS_OUT_OF_RANGE 0xFE
|
#define ERROR_ADDRESS_OUT_OF_RANGE 0xFE
|
||||||
#define ERROR_INVALID_COMMAND 0xFF
|
#define ERROR_INVALID_COMMAND 0xFF
|
||||||
#define COMMAND_SUCCESS 0x01
|
#define COMMAND_SUCCESS 0x01
|
||||||
@@ -308,7 +326,7 @@ ssize_t sendReceiveFrame(int fd, frame_t& frame, size_t sendDataLen, ssize_t fix
|
|||||||
}
|
}
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
if (cnt==0) {
|
if (cnt == 0) {
|
||||||
if (!hideErrors) {
|
if (!hideErrors) {
|
||||||
std::cerr << "write data timed out" << std::endl;
|
std::cerr << "write data timed out" << std::endl;
|
||||||
}
|
}
|
||||||
@@ -323,13 +341,13 @@ ssize_t sendReceiveFrame(int fd, frame_t& frame, size_t sendDataLen, ssize_t fix
|
|||||||
}
|
}
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
if (cnt==0) {
|
if (cnt == 0) {
|
||||||
if (!hideErrors) {
|
if (!hideErrors) {
|
||||||
std::cerr << "read sync timed out" << std::endl;
|
std::cerr << "read sync timed out" << std::endl;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (ch!=STX) {
|
if (ch != STX) {
|
||||||
if (!hideErrors) {
|
if (!hideErrors) {
|
||||||
std::cerr << "did not receive sync: 0x" << std::setfill('0') << std::setw(2) << std::hex
|
std::cerr << "did not receive sync: 0x" << std::setfill('0') << std::setw(2) << std::hex
|
||||||
<< static_cast<unsigned>(ch) << std::endl;
|
<< static_cast<unsigned>(ch) << std::endl;
|
||||||
@@ -346,14 +364,14 @@ ssize_t sendReceiveFrame(int fd, frame_t& frame, size_t sendDataLen, ssize_t fix
|
|||||||
}
|
}
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
if (cnt==0) {
|
if (cnt == 0) {
|
||||||
if (!hideErrors) {
|
if (!hideErrors) {
|
||||||
std::cerr << "read data timed out" << std::endl;
|
std::cerr << "read data timed out" << std::endl;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
pos += cnt;
|
pos += cnt;
|
||||||
if (pos==FRAME_HEADER_LEN) {
|
if (pos == FRAME_HEADER_LEN) {
|
||||||
if (fixReceiveDataLen<0) {
|
if (fixReceiveDataLen<0) {
|
||||||
len += frame.data_length;
|
len += frame.data_length;
|
||||||
} else {
|
} else {
|
||||||
@@ -364,7 +382,7 @@ ssize_t sendReceiveFrame(int fd, frame_t& frame, size_t sendDataLen, ssize_t fix
|
|||||||
}
|
}
|
||||||
uint8_t dummy[4];
|
uint8_t dummy[4];
|
||||||
waitRead(fd, dummy, 4, WAIT_BYTE_TRANSFERRED_MILLIS); // read away potential nonsense tail
|
waitRead(fd, dummy, 4, WAIT_BYTE_TRANSFERRED_MILLIS); // read away potential nonsense tail
|
||||||
if (frame.command!=writeCommand) {
|
if (frame.command != writeCommand) {
|
||||||
if (!hideErrors) {
|
if (!hideErrors) {
|
||||||
std::cerr << "unexpected answer" << std::endl;
|
std::cerr << "unexpected answer" << std::endl;
|
||||||
}
|
}
|
||||||
@@ -378,69 +396,69 @@ int readVersion(int fd, bool verbose=true) {
|
|||||||
memset(frame.buffer, 0, FRAME_MAX_LEN);
|
memset(frame.buffer, 0, FRAME_MAX_LEN);
|
||||||
frame.command = READ_VERSION;
|
frame.command = READ_VERSION;
|
||||||
ssize_t ret = sendReceiveFrame(fd, frame, 0, 16);
|
ssize_t ret = sendReceiveFrame(fd, frame, 0, 16);
|
||||||
if (ret!=0) {
|
if (ret != 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (frame.data[0] != MINOR_VERSION || frame.data[1] != MAJOR_VERSION) {
|
if (frame.data[0] != MINOR_VERSION || frame.data[1] != MAJOR_VERSION) {
|
||||||
std::cerr<<"unexpected version"<<std::endl;
|
std::cerr << "unexpected version" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
std::cout << "Max packet size: " << static_cast<unsigned>(frame.data[2] | (frame.data[3] << 8)) << std::endl;
|
std::cout << "Max packet size: " << static_cast<unsigned>(frame.data[2] | (frame.data[3] << 8)) << std::endl;
|
||||||
}
|
}
|
||||||
std::cout<<"Device ID: "<<std::setfill('0')<<std::setw(4)<<std::hex<<static_cast<unsigned>(frame.data[6] | (frame.data[7]<<8));
|
std::cout << "Device ID: " << std::setfill('0') << std::setw(4) << std::hex << static_cast<unsigned>(frame.data[6] | (frame.data[7] << 8));
|
||||||
if (frame.data[6]==0xb0 && frame.data[7]==0x30) {
|
if (frame.data[6] == 0xb0 && frame.data[7] == 0x30) {
|
||||||
std::cout<<" (PIC16F15356)";
|
std::cout << " (PIC16F15356)";
|
||||||
}
|
}
|
||||||
std::cout<<std::endl;
|
std::cout << std::endl;
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
std::cout<<"Blocksize erase: "<<std::dec<<static_cast<unsigned>(frame.data[10])<<std::endl;
|
std::cout << "Blocksize erase: " << std::dec << static_cast<unsigned>(frame.data[10]) << std::endl;
|
||||||
std::cout<<"Blocksize write: "<<std::dec<<static_cast<unsigned>(frame.data[11])<<std::endl;
|
std::cout << "Blocksize write: " << std::dec << static_cast<unsigned>(frame.data[11]) << std::endl;
|
||||||
std::cout<<"User ID 1: "<<std::setfill('0')<<std::setw(2)<<std::hex<<static_cast<unsigned>(frame.data[12])<<std::endl;
|
std::cout << "User ID 1: " << std::setfill('0') << std::setw(2) << std::hex << static_cast<unsigned>(frame.data[12]) << std::endl;
|
||||||
std::cout<<"User ID 2: "<<std::setfill('0')<<std::setw(2)<<std::hex<<static_cast<unsigned>(frame.data[13])<<std::endl;
|
std::cout << "User ID 2: " << std::setfill('0') << std::setw(2) << std::hex << static_cast<unsigned>(frame.data[13]) << std::endl;
|
||||||
std::cout<<"User ID 3: "<<std::setfill('0')<<std::setw(2)<<std::hex<<static_cast<unsigned>(frame.data[14])<<std::endl;
|
std::cout << "User ID 3: " << std::setfill('0') << std::setw(2) << std::hex << static_cast<unsigned>(frame.data[14]) << std::endl;
|
||||||
std::cout<<"User ID 4: "<<std::setfill('0')<<std::setw(2)<<std::hex<<static_cast<unsigned>(frame.data[15])<<std::endl;
|
std::cout << "User ID 4: " << std::setfill('0') << std::setw(2) << std::hex << static_cast<unsigned>(frame.data[15]) << std::endl;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int printFrameData(frame_t frame, bool skipHigh) {
|
int printFrameData(frame_t frame, bool skipHigh) {
|
||||||
uint16_t address = (frame.address_H<<8)|frame.address_L;
|
uint16_t address = (frame.address_H << 8)|frame.address_L;
|
||||||
int pos;
|
int pos;
|
||||||
std::cout<<std::hex;
|
std::cout << std::hex;
|
||||||
for (pos = 0; pos<frame.data_length;) {
|
for (pos = 0; pos<frame.data_length;) {
|
||||||
if ((pos%16)==0) {
|
if ((pos%16) == 0) {
|
||||||
std::cout<<std::setw(4)<<static_cast<unsigned>(address)<<":";
|
std::cout << std::setw(4) << static_cast<unsigned>(address) << ":";
|
||||||
}
|
}
|
||||||
std::cout<<" "<<std::setw(2)<<static_cast<unsigned>(frame.data[pos++]);
|
std::cout << " " << std::setw(2) << static_cast<unsigned>(frame.data[pos++]);
|
||||||
if (skipHigh) {
|
if (skipHigh) {
|
||||||
pos++;
|
pos++;
|
||||||
} else if (pos<frame.data_length) {
|
} else if (pos<frame.data_length) {
|
||||||
std::cout<<" "<<std::setw(2)<<static_cast<unsigned>(frame.data[pos++]);
|
std::cout << " " << std::setw(2) << static_cast<unsigned>(frame.data[pos++]);
|
||||||
}
|
}
|
||||||
address++;
|
address++;
|
||||||
if ((pos%16)==0) {
|
if ((pos%16) == 0) {
|
||||||
std::cout<<std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((pos%16)!=0) {
|
if ((pos%16) != 0) {
|
||||||
std::cout<<std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int printFrame(frame_t frame) {
|
int printFrame(frame_t frame) {
|
||||||
std::cout<<"command: 0x"<<std::setfill('0')<<std::setw(2)<<std::hex<<static_cast<unsigned>(frame.command)<<std::endl;
|
std::cout << "command: 0x" << std::setfill('0') << std::setw(2) << std::hex << static_cast<unsigned>(frame.command) << std::endl;
|
||||||
std::cout<<"data_length: "<<std::dec<<static_cast<unsigned>(frame.data_length)<<std::endl;
|
std::cout << "data_length: " << std::dec << static_cast<unsigned>(frame.data_length) << std::endl;
|
||||||
std::cout<<"address: 0x"<<std::setw(2)<<std::hex<<static_cast<unsigned>(frame.address_H)<<std::setw(2)<<std::hex<<static_cast<unsigned>(frame.address_L);
|
std::cout << "address: 0x" << std::setw(2) << std::hex << static_cast<unsigned>(frame.address_H) << std::setw(2) << std::hex << static_cast<unsigned>(frame.address_L);
|
||||||
for (int pos = 0; pos<frame.data_length; ) {
|
for (int pos = 0; pos<frame.data_length; ) {
|
||||||
if ((pos%16)==0) {
|
if ((pos%16) == 0) {
|
||||||
std::cout<<std::endl<<std::setw(4)<<static_cast<unsigned>(pos)<<":"<<std::endl;
|
std::cout << std::endl << std::setw(4) << static_cast<unsigned>(pos) << ":" << std::endl;
|
||||||
}
|
}
|
||||||
std::cout<<" "<<std::setw(2)<<static_cast<unsigned>(frame.data[pos++]);
|
std::cout << " " << std::setw(2) << static_cast<unsigned>(frame.data[pos++]);
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
std::cout<<std::endl;
|
std::cout << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,7 +470,7 @@ int readConfig(int fd, uint16_t address, uint16_t len, bool skipHigh=false, bool
|
|||||||
frame.address_L = address&0xff;
|
frame.address_L = address&0xff;
|
||||||
frame.address_H = (address>>8)&0xff;
|
frame.address_H = (address>>8)&0xff;
|
||||||
ssize_t ret = sendReceiveFrame(fd, frame, 0, len);
|
ssize_t ret = sendReceiveFrame(fd, frame, 0, len);
|
||||||
if (ret!=0) {
|
if (ret != 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (print) {
|
if (print) {
|
||||||
@@ -475,10 +493,10 @@ int writeConfig(int fd, uint16_t address, uint16_t len, uint8_t* data) {
|
|||||||
frame.address_H = (address>>8)&0xff;
|
frame.address_H = (address>>8)&0xff;
|
||||||
memcpy(frame.data, data, len);
|
memcpy(frame.data, data, len);
|
||||||
ssize_t ret = sendReceiveFrame(fd, frame, len, 1, 50);
|
ssize_t ret = sendReceiveFrame(fd, frame, len, 1, 50);
|
||||||
if (ret!=0) {
|
if (ret != 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (frame.data[0]!=COMMAND_SUCCESS) {
|
if (frame.data[0] != COMMAND_SUCCESS) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -492,7 +510,7 @@ int readFlash(int fd, uint16_t address, bool skipHigh=false, bool print=true, ui
|
|||||||
frame.address_L = address&0xff;
|
frame.address_L = address&0xff;
|
||||||
frame.address_H = (address>>8)&0xff;
|
frame.address_H = (address>>8)&0xff;
|
||||||
ssize_t ret = sendReceiveFrame(fd, frame, 0, -1);
|
ssize_t ret = sendReceiveFrame(fd, frame, 0, -1);
|
||||||
if (ret!=0) {
|
if (ret != 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (print) {
|
if (print) {
|
||||||
@@ -515,10 +533,10 @@ int writeFlash(int fd, uint16_t address, uint16_t len, uint8_t* data, bool hideE
|
|||||||
frame.address_H = (address>>8)&0xff;
|
frame.address_H = (address>>8)&0xff;
|
||||||
memcpy(frame.data, data, len);
|
memcpy(frame.data, data, len);
|
||||||
ssize_t ret = sendReceiveFrame(fd, frame, len, 1, len*30, hideErrors);
|
ssize_t ret = sendReceiveFrame(fd, frame, len, 1, len*30, hideErrors);
|
||||||
if (ret!=0) {
|
if (ret != 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (frame.data[0]!=COMMAND_SUCCESS) {
|
if (frame.data[0] != COMMAND_SUCCESS) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -534,10 +552,10 @@ int eraseFlash(int fd, uint16_t address, uint16_t len) {
|
|||||||
frame.address_L = address&0xff;
|
frame.address_L = address&0xff;
|
||||||
frame.address_H = (address>>8)&0xff;
|
frame.address_H = (address>>8)&0xff;
|
||||||
ssize_t ret = sendReceiveFrame(fd, frame, 0, 1, frame.data_length*5);
|
ssize_t ret = sendReceiveFrame(fd, frame, 0, 1, frame.data_length*5);
|
||||||
if (ret!=0) {
|
if (ret != 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (frame.data[0]!=COMMAND_SUCCESS) {
|
if (frame.data[0] != COMMAND_SUCCESS) {
|
||||||
return -frame.data[0]-1;
|
return -frame.data[0]-1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -551,10 +569,10 @@ int calcChecksum(int fd, uint16_t address, uint16_t len) {
|
|||||||
frame.address_L = address&0xff;
|
frame.address_L = address&0xff;
|
||||||
frame.address_H = (address>>8)&0xff;
|
frame.address_H = (address>>8)&0xff;
|
||||||
ssize_t ret = sendReceiveFrame(fd, frame, 0, 2, len*30);
|
ssize_t ret = sendReceiveFrame(fd, frame, 0, 2, len*30);
|
||||||
if (ret!=0) {
|
if (ret != 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
return frame.data[0] | (frame.data[1]<<8);
|
return frame.data[0] | (frame.data[1] << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
int resetDevice(int fd) {
|
int resetDevice(int fd) {
|
||||||
@@ -562,10 +580,10 @@ int resetDevice(int fd) {
|
|||||||
memset(frame.buffer, 0, FRAME_MAX_LEN);
|
memset(frame.buffer, 0, FRAME_MAX_LEN);
|
||||||
frame.command = RESET_DEVICE;
|
frame.command = RESET_DEVICE;
|
||||||
ssize_t ret = sendReceiveFrame(fd, frame, 0, 1);
|
ssize_t ret = sendReceiveFrame(fd, frame, 0, 1);
|
||||||
if (ret!=0) {
|
if (ret != 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (frame.data[0]!=COMMAND_SUCCESS) {
|
if (frame.data[0] != COMMAND_SUCCESS) {
|
||||||
return -frame.data[0]-1;
|
return -frame.data[0]-1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -577,13 +595,13 @@ int openSerial(std::string port) {
|
|||||||
// open serial port
|
// open serial port
|
||||||
int fd = open(port.c_str(), O_RDWR | O_NOCTTY | O_NDELAY); // non-blocking IO: | O_NONBLOCK);
|
int fd = open(port.c_str(), O_RDWR | O_NOCTTY | O_NDELAY); // non-blocking IO: | O_NONBLOCK);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
std::cerr<<"unable to open "<<port<<std::endl;
|
std::cerr << "unable to open " << port << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flock(fd, LOCK_EX|LOCK_NB)) {
|
if (flock(fd, LOCK_EX|LOCK_NB)) {
|
||||||
close(fd);
|
close(fd);
|
||||||
std::cerr<<"unable to lock "<<port<<std::endl;
|
std::cerr << "unable to lock " << port << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -594,8 +612,8 @@ int openSerial(std::string port) {
|
|||||||
struct termios termios;
|
struct termios termios;
|
||||||
memset(&termios, 0, sizeof(termios));
|
memset(&termios, 0, sizeof(termios));
|
||||||
|
|
||||||
if (cfsetspeed(&termios, lowSpeed ? BAUDRATE_LOW : BAUDRATE_HIGH)!=0) {
|
if (cfsetspeed(&termios, lowSpeed ? BAUDRATE_LOW : BAUDRATE_HIGH) != 0) {
|
||||||
std::cerr<<"unable to set speed "<<std::endl;
|
std::cerr << "unable to set speed " << std::endl;
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -605,8 +623,8 @@ int openSerial(std::string port) {
|
|||||||
termios.c_lflag |= 0;
|
termios.c_lflag |= 0;
|
||||||
termios.c_cc[VMIN] = 1;
|
termios.c_cc[VMIN] = 1;
|
||||||
termios.c_cc[VTIME] = 0;
|
termios.c_cc[VTIME] = 0;
|
||||||
if (tcsetattr(fd, TCSANOW, &termios)!=0) {
|
if (tcsetattr(fd, TCSANOW, &termios) != 0) {
|
||||||
std::cerr<<"unable to set serial "<<std::endl;
|
std::cerr << "unable to set serial " << std::endl;
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -622,28 +640,28 @@ int calcFileChecksum(uint8_t* storeFirstBlock=nullptr) {
|
|||||||
std::ifstream inStream;
|
std::ifstream inStream;
|
||||||
inStream.open(flashFile, ifstream::in);
|
inStream.open(flashFile, ifstream::in);
|
||||||
if (!inStream.good()) {
|
if (!inStream.good()) {
|
||||||
std::cerr<<"unable to open file"<<std::endl;
|
std::cerr << "unable to open file" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
intelhex ih;
|
intelhex ih;
|
||||||
inStream >> ih;
|
inStream >> ih;
|
||||||
if (ih.getNoErrors()>0 || ih.getNoWarnings()>0) {
|
if (ih.getNoErrors()>0 || ih.getNoWarnings()>0) {
|
||||||
std::cerr<<"unable to read file"<<std::endl;
|
std::cerr << "unable to read file" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
unsigned long startAddr = 0, endAddr = 0;
|
unsigned long startAddr = 0, endAddr = 0;
|
||||||
if (!ih.startAddress(&startAddr) || !ih.endAddress(&endAddr)) {
|
if (!ih.startAddress(&startAddr) || !ih.endAddress(&endAddr)) {
|
||||||
std::cerr<<"unable to read file"<<std::endl;
|
std::cerr << "unable to read file" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (startAddr<END_BOOT_BYTES || endAddr>=END_FLASH_BYTES || endAddr<startAddr || (startAddr&0xf)!=0) {
|
if (startAddr<END_BOOT_BYTES || endAddr>=END_FLASH_BYTES || endAddr<startAddr || (startAddr&0xf) != 0) {
|
||||||
std::cerr<<"invalid address range"<<std::endl;
|
std::cerr << "invalid address range" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ih.begin();
|
ih.begin();
|
||||||
unsigned long nextAddr = ih.currentAddress();
|
unsigned long nextAddr = ih.currentAddress();
|
||||||
if (nextAddr!=END_BOOT_BYTES) {
|
if (nextAddr != END_BOOT_BYTES) {
|
||||||
std::cerr<<"unexpected start address in file."<<std::endl;
|
std::cerr << "unexpected start address in file." << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
unsigned long blockStart = END_BOOT_BYTES;
|
unsigned long blockStart = END_BOOT_BYTES;
|
||||||
@@ -651,14 +669,14 @@ int calcFileChecksum(uint8_t* storeFirstBlock=nullptr) {
|
|||||||
while (blockStart<END_FLASH_BYTES && nextAddr<END_FLASH_BYTES) {
|
while (blockStart<END_FLASH_BYTES && nextAddr<END_FLASH_BYTES) {
|
||||||
for (int pos = 0; pos < WRITE_FLASH_BLOCKSIZE; pos++, nextAddr++) {
|
for (int pos = 0; pos < WRITE_FLASH_BLOCKSIZE; pos++, nextAddr++) {
|
||||||
unsigned long addr = ih.currentAddress();
|
unsigned long addr = ih.currentAddress();
|
||||||
uint8_t value = (pos&0x1)==1?0x3f:0xff;
|
uint8_t value = (pos&0x1) == 1 ? 0x3f : 0xff;
|
||||||
if (addr == nextAddr && ih.getData(&value)) {
|
if (addr == nextAddr && ih.getData(&value)) {
|
||||||
ih.incrementAddress();
|
ih.incrementAddress();
|
||||||
}
|
}
|
||||||
if (storeFirstBlock && nextAddr<END_BOOT_BYTES+0x10) {
|
if (storeFirstBlock && nextAddr<END_BOOT_BYTES+0x10) {
|
||||||
storeFirstBlock[pos] = value;
|
storeFirstBlock[pos] = value;
|
||||||
}
|
}
|
||||||
checkSum += ((uint16_t)value)<<((pos&0x1)*8);
|
checkSum += ((uint16_t)value) << ((pos&0x1)*8);
|
||||||
}
|
}
|
||||||
blockStart += WRITE_FLASH_BLOCKSIZE;
|
blockStart += WRITE_FLASH_BLOCKSIZE;
|
||||||
}
|
}
|
||||||
@@ -669,7 +687,7 @@ void printFileChecksum() {
|
|||||||
uint8_t data[0x10];
|
uint8_t data[0x10];
|
||||||
int checkSum = calcFileChecksum(data);
|
int checkSum = calcFileChecksum(data);
|
||||||
int newFirmwareVersion = -1;
|
int newFirmwareVersion = -1;
|
||||||
if (data[0x2*2]==0xae && data[0x2*2+1]==0x34 && data[0x3*2+1]==0x34) {
|
if (data[0x2*2] == 0xae && data[0x2*2+1] == 0x34 && data[0x3*2+1] == 0x34) {
|
||||||
newFirmwareVersion = data[0x3*2];
|
newFirmwareVersion = data[0x3*2];
|
||||||
}
|
}
|
||||||
std::cout
|
std::cout
|
||||||
@@ -681,7 +699,7 @@ bool flashPic(int fd) {
|
|||||||
std::ifstream inStream;
|
std::ifstream inStream;
|
||||||
inStream.open(flashFile, ifstream::in);
|
inStream.open(flashFile, ifstream::in);
|
||||||
if (!inStream.good()) {
|
if (!inStream.good()) {
|
||||||
std::cerr<<"unable to open file"<<std::endl;
|
std::cerr << "unable to open file" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
intelhex ih;
|
intelhex ih;
|
||||||
@@ -690,19 +708,19 @@ bool flashPic(int fd) {
|
|||||||
// }
|
// }
|
||||||
inStream >> ih;
|
inStream >> ih;
|
||||||
if (ih.getNoErrors()>0 || ih.getNoWarnings()>0) {
|
if (ih.getNoErrors()>0 || ih.getNoWarnings()>0) {
|
||||||
std::cerr<<"errors or warnings while reading the file:"<<std::endl;
|
std::cerr << "errors or warnings while reading the file:" << std::endl;
|
||||||
string str;
|
string str;
|
||||||
while (ih.popNextWarning(str)) {
|
while (ih.popNextWarning(str)) {
|
||||||
std::cerr<<"warning: "<<str<<std::endl;
|
std::cerr << "warning: " << str << std::endl;
|
||||||
}
|
}
|
||||||
while (ih.popNextError(str)) {
|
while (ih.popNextError(str)) {
|
||||||
std::cerr<<"error: "<<str<<std::endl;
|
std::cerr << "error: " << str << std::endl;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
unsigned long startAddr = 0, endAddr = 0;
|
unsigned long startAddr = 0, endAddr = 0;
|
||||||
if (!ih.startAddress(&startAddr) || !ih.endAddress(&endAddr)) {
|
if (!ih.startAddress(&startAddr) || !ih.endAddress(&endAddr)) {
|
||||||
std::cerr<<"unable to read file"<<std::endl;
|
std::cerr << "unable to read file" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
@@ -712,22 +730,22 @@ bool flashPic(int fd) {
|
|||||||
<< std::hex << std::setfill('0') << std::setw(4) << static_cast<unsigned>(endAddr)
|
<< std::hex << std::setfill('0') << std::setw(4) << static_cast<unsigned>(endAddr)
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
if (startAddr<END_BOOT_BYTES || endAddr>=END_FLASH_BYTES || endAddr<startAddr || (startAddr&0xf)!=0) {
|
if (startAddr<END_BOOT_BYTES || endAddr>=END_FLASH_BYTES || endAddr<startAddr || (startAddr&0xf) != 0) {
|
||||||
std::cerr<<"invalid address range"<<std::endl;
|
std::cerr << "invalid address range" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ih.begin();
|
ih.begin();
|
||||||
uint8_t buf[WRITE_FLASH_BLOCKSIZE];
|
uint8_t buf[WRITE_FLASH_BLOCKSIZE];
|
||||||
unsigned long nextAddr = ih.currentAddress();
|
unsigned long nextAddr = ih.currentAddress();
|
||||||
if (nextAddr!=END_BOOT_BYTES) {
|
if (nextAddr != END_BOOT_BYTES) {
|
||||||
std::cerr<<"unexpected start address in file: 0x"<<std::hex<<std::setfill('0')<<std::setw(4)<<static_cast<unsigned>(nextAddr)<<std::endl;
|
std::cerr << "unexpected start address in file: 0x" << std::hex << std::setfill('0') << std::setw(4) << static_cast<unsigned>(nextAddr) << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
unsigned long blockStart = END_BOOT_BYTES;
|
unsigned long blockStart = END_BOOT_BYTES;
|
||||||
uint16_t checkSum = 0;
|
uint16_t checkSum = 0;
|
||||||
int eraseRes = eraseFlash(fd, blockStart/2, (endAddr-blockStart)/2);
|
int eraseRes = eraseFlash(fd, blockStart/2, (endAddr-blockStart)/2);
|
||||||
if (eraseRes!=0) {
|
if (eraseRes != 0) {
|
||||||
std::cerr << "erasing flash failed: "<< static_cast<signed>(-eraseRes-1)<<std::endl;
|
std::cerr << "erasing flash failed: " << static_cast<signed>(-eraseRes-1) << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::cout << "erasing flash: done." << std::endl;
|
std::cout << "erasing flash: done." << std::endl;
|
||||||
@@ -738,27 +756,27 @@ bool flashPic(int fd) {
|
|||||||
bool blank = true;
|
bool blank = true;
|
||||||
for (int pos = 0; pos < WRITE_FLASH_BLOCKSIZE; pos++, nextAddr++) {
|
for (int pos = 0; pos < WRITE_FLASH_BLOCKSIZE; pos++, nextAddr++) {
|
||||||
unsigned long addr = ih.currentAddress();
|
unsigned long addr = ih.currentAddress();
|
||||||
uint8_t value = (pos&0x1)==1?0x3f:0xff;
|
uint8_t value = (pos&0x1) == 1 ? 0x3f : 0xff;
|
||||||
if (addr == nextAddr && ih.getData(&value)) {
|
if (addr == nextAddr && ih.getData(&value)) {
|
||||||
ih.incrementAddress();
|
ih.incrementAddress();
|
||||||
blank = false;
|
blank = false;
|
||||||
}
|
}
|
||||||
buf[pos] = value;
|
buf[pos] = value;
|
||||||
checkSum += ((uint16_t)value)<<((pos&0x1)*8);
|
checkSum += ((uint16_t)value) << ((pos&0x1)*8);
|
||||||
}
|
}
|
||||||
if (!blank) {
|
if (!blank) {
|
||||||
if (blocks==0) {
|
if (blocks == 0) {
|
||||||
std::cout<<std::endl<<"0x"<<std::hex<<std::setfill('0')<<std::setw(4)<<static_cast<unsigned>(blockStart/2)<<" ";
|
std::cout << std::endl << "0x" << std::hex << std::setfill('0') << std::setw(4) << static_cast<unsigned>(blockStart/2) << " ";
|
||||||
}
|
}
|
||||||
if (writeFlash(fd, blockStart/2, WRITE_FLASH_BLOCKSIZE, buf, true)!=0) {
|
if (writeFlash(fd, blockStart/2, WRITE_FLASH_BLOCKSIZE, buf, true) != 0) {
|
||||||
// repeat once silently:
|
// repeat once silently:
|
||||||
if (writeFlash(fd, blockStart/2, WRITE_FLASH_BLOCKSIZE, buf)!=0) {
|
if (writeFlash(fd, blockStart/2, WRITE_FLASH_BLOCKSIZE, buf) != 0) {
|
||||||
std::cerr << "unable to write flash at 0x" << std::hex << std::setfill('0') << std::setw(4)
|
std::cerr << "unable to write flash at 0x" << std::hex << std::setfill('0') << std::setw(4)
|
||||||
<< static_cast<unsigned>(blockStart/2) << std::endl;
|
<< static_cast<unsigned>(blockStart/2) << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout<<".";
|
std::cout << ".";
|
||||||
if (++blocks>=64) {
|
if (++blocks>=64) {
|
||||||
blocks = 0;
|
blocks = 0;
|
||||||
}
|
}
|
||||||
@@ -766,17 +784,17 @@ bool flashPic(int fd) {
|
|||||||
}
|
}
|
||||||
blockStart += WRITE_FLASH_BLOCKSIZE;
|
blockStart += WRITE_FLASH_BLOCKSIZE;
|
||||||
}
|
}
|
||||||
std::cout<<std::endl<<"flashing finished."<<std::endl;
|
std::cout << std::endl << "flashing finished." << std::endl;
|
||||||
int picSum = calcChecksum(fd, startAddr/2, blockStart-startAddr);
|
int picSum = calcChecksum(fd, startAddr/2, blockStart-startAddr);
|
||||||
if (picSum<0) {
|
if (picSum<0) {
|
||||||
std::cout<<"unable to read checksum."<<std::endl;
|
std::cout << "unable to read checksum." << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (picSum!=checkSum) {
|
if (picSum != checkSum) {
|
||||||
std::cout<<"unexpected checksum."<<std::endl;
|
std::cout << "unexpected checksum." << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::cout<<"flashing succeeded."<<std::endl;
|
std::cout << "flashing succeeded." << std::endl;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -787,7 +805,7 @@ void readIpSettings(int fd) {
|
|||||||
uint8_t maskLen = 0;
|
uint8_t maskLen = 0;
|
||||||
uint8_t configData[8];
|
uint8_t configData[8];
|
||||||
readConfig(fd, 0x0000, 8, false, false, configData); // User ID
|
readConfig(fd, 0x0000, 8, false, false, configData); // User ID
|
||||||
useMUI = (configData[1]&0x20)!=0; // if highest bit is set, then use MUI. if cleared, use User ID
|
useMUI = (configData[1]&0x20) != 0; // if highest bit is set, then use MUI. if cleared, use User ID
|
||||||
maskLen = configData[1]&0x1f;
|
maskLen = configData[1]&0x1f;
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
ip[i] = configData[i*2];
|
ip[i] = configData[i*2];
|
||||||
@@ -803,32 +821,32 @@ void readIpSettings(int fd) {
|
|||||||
mac[3+i] = configData[i*2];
|
mac[3+i] = configData[i*2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout<<"MAC address:";
|
std::cout << "MAC address:";
|
||||||
for (int i=0; i<6; i++) {
|
for (int i=0; i<6; i++) {
|
||||||
std::cout<<(i==0?' ':':')<<std::hex<<std::setw(2)<<std::setfill('0')<<static_cast<unsigned>(mac[i]);
|
std::cout << (i == 0?' ':':') << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned>(mac[i]);
|
||||||
}
|
}
|
||||||
std::cout<<std::endl;
|
std::cout << std::endl;
|
||||||
if (maskLen==0x1f || (ip[0]|ip[1]|ip[2]|ip[3])==0) {
|
if (maskLen == 0x1f || (ip[0]|ip[1]|ip[2]|ip[3]) == 0) {
|
||||||
std::cout<<"IP address: DHCP"<<std::endl;
|
std::cout << "IP address: DHCP" << std::endl;
|
||||||
} else {
|
} else {
|
||||||
std::cout<<"IP address:";
|
std::cout << "IP address:";
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
std::cout<<(i==0?' ':'.')<<std::dec<<static_cast<unsigned>(ip[i]);
|
std::cout << (i == 0?' ':'.') << std::dec << static_cast<unsigned>(ip[i]);
|
||||||
}
|
}
|
||||||
std::cout<<"/"<<std::dec<<static_cast<unsigned>(maskLen)<<std::endl;
|
std::cout << "/" << std::dec << static_cast<unsigned>(maskLen) << std::endl;
|
||||||
/*
|
/*
|
||||||
// build gateway
|
// build gateway
|
||||||
for (uint8_t pos=0; pos<4; pos++) {
|
for (uint8_t pos=0; pos<4; pos++) {
|
||||||
mask[pos] = maskLen>=8 ? 255 : maskLen<=0 ? 0 : (255^((1<<(8-maskLen))-1));
|
mask[pos] = maskLen>=8 ? 255 : maskLen<=0 ? 0 : (255^((1 << (8-maskLen))-1));
|
||||||
ip[pos] &= mask[pos];
|
ip[pos] &= mask[pos];
|
||||||
maskLen = maskLen>=8 ? maskLen-8 : 0;
|
maskLen = maskLen>=8 ? maskLen-8 : 0;
|
||||||
}
|
}
|
||||||
ip[3] |= 1; // first address in network is used as gateway (not needed anyway))
|
ip[3] |= 1; // first address in network is used as gateway (not needed anyway))
|
||||||
std::cout<<"IP gateway:";
|
std::cout << "IP gateway:";
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
std::cout<<(i==0?' ':'.')<<std::dec<<static_cast<unsigned>(ip[i]);
|
std::cout << (i == 0?' ':'.') << std::dec << static_cast<unsigned>(ip[i]);
|
||||||
}
|
}
|
||||||
std::cout<<std::endl;
|
std::cout << std::endl;
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -859,12 +877,12 @@ int main(int argc, char* argv[]) {
|
|||||||
setenv("ARGP_HELP_FMT", "no-dup-args-note", 0);
|
setenv("ARGP_HELP_FMT", "no-dup-args-note", 0);
|
||||||
|
|
||||||
if (argp_parse(&aargp, argc, argv, ARGP_IN_ORDER, &arg_index, nullptr) != 0) {
|
if (argp_parse(&aargp, argc, argv, ARGP_IN_ORDER, &arg_index, nullptr) != 0) {
|
||||||
std::cerr<<"invalid arguments"<<std::endl;
|
std::cerr << "invalid arguments" << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setIp != setMask || (setMacFromIp && !setIp)) {
|
if (setIp != setMask || (setMacFromIp && !setIp)) {
|
||||||
std::cerr<<"incomplete IP arguments"<<std::endl;
|
std::cerr << "incomplete IP arguments" << std::endl;
|
||||||
arg_index = argc; // force help output
|
arg_index = argc; // force help output
|
||||||
}
|
}
|
||||||
if (argc-arg_index<1) {
|
if (argc-arg_index<1) {
|
||||||
@@ -883,7 +901,7 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// read version
|
// read version
|
||||||
if (readVersion(fd, verbose)!=0) {
|
if (readVersion(fd, verbose) != 0) {
|
||||||
closeSerial(fd);
|
closeSerial(fd);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@@ -894,43 +912,43 @@ int main(int argc, char* argv[]) {
|
|||||||
std::cout << "Rev ID, Device ID:" << std::endl;
|
std::cout << "Rev ID, Device ID:" << std::endl;
|
||||||
}
|
}
|
||||||
readConfig(fd, 0x0005, 4, false, verbose, data); // Rev ID and Device ID
|
readConfig(fd, 0x0005, 4, false, verbose, data); // Rev ID and Device ID
|
||||||
std::cout << "Device revision: " << static_cast<unsigned>(((data[1]&0xf)<<2) | ((data[0]&0xc0)>>6))
|
std::cout << "Device revision: " << static_cast<unsigned>(((data[1]&0xf) << 2) | ((data[0]&0xc0)>>6))
|
||||||
<< "." << static_cast<unsigned>(data[0]&0x3f) << std::endl;
|
<< "." << static_cast<unsigned>(data[0]&0x3f) << std::endl;
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
std::cout << "Configuration words:" << std::endl;
|
std::cout << "Configuration words:" << std::endl;
|
||||||
readConfig(fd, 0x0007, 5*2); // Configuration Words
|
readConfig(fd, 0x0007, 5*2); // Configuration Words
|
||||||
std::cout << "MUI:" << std::endl;
|
std::cout << "MUI:" << std::endl;
|
||||||
readConfig(fd, 0x0100, 9*2, true); // MUI
|
readConfig(fd, 0x0100, 9*2, true); // MUI
|
||||||
std::cout<<"EUI:"<<std::endl;
|
std::cout << "EUI:"<< std::endl;
|
||||||
readConfig(fd, 0x010a, 8*2); // EUI
|
readConfig(fd, 0x010a, 8*2); // EUI
|
||||||
}
|
}
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
std::cout<<"Flash:"<<std::endl;
|
std::cout << "Flash:" << std::endl;
|
||||||
}
|
}
|
||||||
readFlash(fd, 0x0000, false, false, data);
|
readFlash(fd, 0x0000, false, false, data);
|
||||||
int bootloaderVersion = -1;
|
int bootloaderVersion = -1;
|
||||||
if (data[0x2*2]==0xab && data[0x2*2+1]==0x34 && data[0x3*2+1]==0x34) {
|
if (data[0x2*2] == 0xab && data[0x2*2+1] == 0x34 && data[0x3*2+1] == 0x34) {
|
||||||
bootloaderVersion = data[0x3*2];
|
bootloaderVersion = data[0x3*2];
|
||||||
int picSum = calcChecksum(fd, 0x0000, END_BOOT_BYTES);
|
int picSum = calcChecksum(fd, 0x0000, END_BOOT_BYTES);
|
||||||
std::cout
|
std::cout
|
||||||
<< "Bootloader version: " << static_cast<unsigned>(bootloaderVersion)
|
<< "Bootloader version: " << static_cast<unsigned>(bootloaderVersion)
|
||||||
<< " [" << std::hex << std::setw (4) << std::setfill('0') << static_cast<signed>(picSum) << "]" << std::endl;
|
<< " [" << std::hex << std::setw (4) << std::setfill('0') << static_cast<signed>(picSum) << "]" << std::endl;
|
||||||
} else {
|
} else {
|
||||||
std::cerr<<"Bootloader version not found"<<std::endl;
|
std::cerr << "Bootloader version not found" << std::endl;
|
||||||
}
|
}
|
||||||
readFlash(fd, END_BOOT, false, false, data);
|
readFlash(fd, END_BOOT, false, false, data);
|
||||||
int firmwareVersion = -1;
|
int firmwareVersion = -1;
|
||||||
if (data[0x2*2]==0xae && data[0x2*2+1]==0x34 && data[0x3*2+1]==0x34) {
|
if (data[0x2*2] == 0xae && data[0x2*2+1] == 0x34 && data[0x3*2+1] == 0x34) {
|
||||||
firmwareVersion = data[0x3*2];
|
firmwareVersion = data[0x3*2];
|
||||||
int picSum = calcChecksum(fd, END_BOOT, END_FLASH_BYTES-END_BOOT_BYTES);
|
int picSum = calcChecksum(fd, END_BOOT, END_FLASH_BYTES-END_BOOT_BYTES);
|
||||||
std::cout
|
std::cout
|
||||||
<< "Firmware version: " << static_cast<unsigned>(firmwareVersion)
|
<< "Firmware version: " << static_cast<unsigned>(firmwareVersion)
|
||||||
<< " [" << std::hex << std::setw (4) << std::setfill('0') << static_cast<signed>(picSum) << "]" << std::endl;
|
<< " [" << std::hex << std::setw (4) << std::setfill('0') << static_cast<signed>(picSum) << "]" << std::endl;
|
||||||
} else {
|
} else {
|
||||||
std::cout<<"Firmware version not found"<<std::endl;
|
std::cout << "Firmware version not found" << std::endl;
|
||||||
}
|
}
|
||||||
readIpSettings(fd);
|
readIpSettings(fd);
|
||||||
std::cout<<std::endl;
|
std::cout << std::endl;
|
||||||
bool success = true;
|
bool success = true;
|
||||||
if (flashFile) {
|
if (flashFile) {
|
||||||
printFileChecksum();
|
printFileChecksum();
|
||||||
|
|||||||
Reference in New Issue
Block a user