bool Volkslogger::SendCommand(Port &port, OperationEnvironment &env, Command cmd, uint8_t param1, uint8_t param2) { static constexpr unsigned delay = 2; /* flush buffers */ if (!port.FullFlush(env, 20, 100)) return false; /* reset command interpreter */ if (!Reset(port, env, 6)) return false; /* send command packet */ const uint8_t cmdarray[8] = { (uint8_t)cmd, param1, param2, 0, 0, 0, 0, 0, }; if (!port.Write(ENQ)) return false; env.Sleep(delay); if (!SendWithCRC(port, cmdarray, sizeof(cmdarray), env)) return false; /* wait for confirmation */ return port.WaitRead(env, 4000) == Port::WaitResult::READY && port.GetChar() == 0; }
int main(int argc, char **argv) { Args args(argc, argv, "PORT BAUD"); const DeviceConfig config = ParsePortArgs(args); args.ExpectEnd(); InitialiseIOThread(); Port *port = OpenPort(config, nullptr, *(DataHandler *)nullptr); if (port == NULL) { delete port; fprintf(stderr, "Failed to open COM port\n"); return EXIT_FAILURE; } ConsoleOperationEnvironment env; if (!port->WaitConnected(env)) { delete port; DeinitialiseIOThread(); fprintf(stderr, "Failed to connect the port\n"); return EXIT_FAILURE; } char buffer[4096]; while (true) { switch (port->WaitRead(env, 60000)) { case Port::WaitResult::READY: break; case Port::WaitResult::TIMEOUT: continue; case Port::WaitResult::FAILED: delete port; return EXIT_FAILURE; case Port::WaitResult::CANCELLED: delete port; return EXIT_SUCCESS; } int nbytes = port->Read(buffer, sizeof(buffer)); if (nbytes < 0) break; fwrite((const void *)buffer, 1, nbytes, stdout); } delete port; DeinitialiseIOThread(); return EXIT_SUCCESS; }
static bool TryConnect(Port &port, char *user_data, size_t max_user_data, OperationEnvironment &env) { port.Flush(); port.Write('\x02'); // send IO Mode command unsigned user_size = 0; TimeoutClock timeout(8000); while (true) { int remaining = timeout.GetRemainingSigned(); if (remaining < 0) return false; if (port.WaitRead(env, remaining) != Port::WaitResult::READY) return false; int nbytes = port.Read(user_data + user_size, max_user_data - user_size); if (nbytes < 0) return false; if (user_size == 0) { const char *minus = (const char *)memchr(user_data, '-', nbytes); if (minus == NULL) continue; user_size = user_data + nbytes - minus; memmove(user_data, minus, user_size); } else user_size += nbytes; char *end = (char *)memchr(user_data, '\x13', user_size); if (end != NULL) { *end = 0; port.Write('\x16'); return true; } if (user_size >= max_user_data) /* response too large */ return false; } return false; }
int Volkslogger::ReadBulk(Port &port, OperationEnvironment &env, void *buffer, size_t max_length, unsigned timeout_firstchar_ms) { unsigned nbytes = 0; bool dle_r = false; uint16_t crc16 = 0; bool start = false, ende = false; memset(buffer, 0xff, max_length); uint8_t *p = (uint8_t *)buffer; constexpr unsigned TIMEOUT_NORMAL_MS = 2000; /** * We need to wait longer for the first char to * give the logger time to calculate security * when downloading a log-file. * Therefore timeout_firstchar is configurable. * If the timeout parameter is not specified or 0, * set standard timeout */ if (timeout_firstchar_ms == 0) timeout_firstchar_ms = TIMEOUT_NORMAL_MS; while (!ende) { // Zeichen anfordern und darauf warten if (!port.Write(ACK)) return -1; // Set longer timeout on first char unsigned timeout = start ? TIMEOUT_NORMAL_MS : timeout_firstchar_ms; if (port.WaitRead(env, timeout) != Port::WaitResult::READY) return -1; int ch = port.GetChar(); if (ch < 0) return -1; // dabei ist Benutzerabbruch jederzeit möglich if (env.IsCancelled()) { env.Sleep(10); port.Write(CAN); port.Write(CAN); port.Write(CAN); return -1; } // oder aber das empfangene Zeichen wird ausgewertet switch (ch) { case DLE: if (!dle_r) { //!DLE, DLE -> Achtung! dle_r = true; } else { // DLE, DLE -> DLE-Zeichen dle_r = false; if (start) { if(nbytes < max_length) *p++ = ch; nbytes++; crc16 = UpdateCRC16CCITT(ch, crc16); } } break; case ETX: if (!dle_r) { //!DLE, ETX -> Zeichen if (start) { if(nbytes < max_length) { *p++ = ch; } nbytes++; crc16 = UpdateCRC16CCITT(ch, crc16); }; } else { if (start) { ende = true; // DLE, ETX -> Blockende dle_r = false; } } break; case STX: if (!dle_r) { //!DLE, STX -> Zeichen if (start) { if(nbytes < max_length) *p++ = ch; nbytes++; crc16 = UpdateCRC16CCITT(ch, crc16); } } else { start = true; // DLE, STX -> Blockstart dle_r = false; crc16 = 0; } break; default: if (start) { if(nbytes < max_length) *p++ = ch; nbytes++; crc16 = UpdateCRC16CCITT(ch, crc16); } break; } } env.Sleep(100); if (crc16 != 0) return -1; if (nbytes < 2) return 0; // CRC am Ende abschneiden return nbytes - 2; }