mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-23 03:00:56 +00:00
Adding to generated for now, protobuf PR will come when it works ... :-)
This commit is contained in:
201
src/xmodem.cpp
Normal file
201
src/xmodem.cpp
Normal file
@@ -0,0 +1,201 @@
|
||||
/***********************************************************************************************************************
|
||||
* XMODEM implementation with YMODEM support
|
||||
***********************************************************************************************************************
|
||||
* Copyright 2001-2019 Georges Menie (www.menie.org)
|
||||
* Modified by Thuffir in 2019
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University of California, Berkeley nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#include "xmodem.h"
|
||||
|
||||
XModemAdapter xModem;
|
||||
|
||||
XModemAdapter::XModemAdapter()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned short XModemAdapter::crc16_ccitt(const pb_byte_t *buffer, int length)
|
||||
{
|
||||
unsigned short crc16 = 0;
|
||||
while(length != 0) {
|
||||
crc16 = (unsigned char)(crc16 >> 8) | (crc16 << 8);
|
||||
crc16 ^= *buffer;
|
||||
crc16 ^= (unsigned char)(crc16 & 0xff) >> 4;
|
||||
crc16 ^= (crc16 << 8) << 4;
|
||||
crc16 ^= ((crc16 & 0xff) << 4) << 1;
|
||||
buffer++;
|
||||
length--;
|
||||
}
|
||||
|
||||
return crc16;
|
||||
}
|
||||
|
||||
int XModemAdapter::check(const pb_byte_t *buf, int sz, unsigned short tcrc)
|
||||
{
|
||||
unsigned short crc = crc16_ccitt(buf, sz);
|
||||
if (crc == tcrc)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void XModemAdapter::sendControl(XModem_Control c) {
|
||||
memset(xmodemStore, 0, XModem_size);
|
||||
xmodemStore->control = c;
|
||||
}
|
||||
|
||||
XModem *XModemAdapter::getForPhone()
|
||||
{
|
||||
if(xmodemStore) {
|
||||
return xmodemStore;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void XModemAdapter::handlePacket(XModem xmodemPacket)
|
||||
{
|
||||
switch(xmodemPacket.control) {
|
||||
case XModem_Control_SOH:
|
||||
case XModem_Control_STX:
|
||||
if ((xmodemPacket.seq == 0) && !isReceiving && !isTransmitting) {
|
||||
// NULL packet has the destination filename
|
||||
memcpy(filename, &xmodemPacket.buffer.bytes, xmodemPacket.buffer.size);
|
||||
if(xmodemPacket.control == XModem_Control_SOH) { // Receive this file and put to Flash
|
||||
file = FSCom.open(filename, FILE_O_WRITE);
|
||||
if(file) {
|
||||
sendControl(XModem_Control_ACK);
|
||||
isReceiving = true;
|
||||
packetno = 1;
|
||||
break;
|
||||
}
|
||||
sendControl(XModem_Control_NAK);
|
||||
isReceiving = false;
|
||||
break;
|
||||
} else { // Transmit this file from Flash
|
||||
file = FSCom.open(filename, FILE_O_READ);
|
||||
if (file) {
|
||||
packetno = 1;
|
||||
isTransmitting = true;
|
||||
memset(xmodemStore, 0, XModem_size);
|
||||
xmodemStore->control = XModem_Control_SOH;
|
||||
xmodemStore->seq = packetno;
|
||||
xmodemStore->buffer.size = file.read(xmodemStore->buffer.bytes, sizeof(XModem_buffer_t::bytes));
|
||||
xmodemStore->crc16 = crc16_ccitt(xmodemStore->buffer.bytes, xmodemStore->buffer.size);
|
||||
break;
|
||||
}
|
||||
sendControl(XModem_Control_NAK);
|
||||
isTransmitting = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (isReceiving) {
|
||||
// normal file data packet
|
||||
if ((xmodemPacket.seq == packetno) && check(xmodemPacket.buffer.bytes, xmodemPacket.buffer.size, xmodemPacket.crc16)) {
|
||||
// valid packet
|
||||
file.write(xmodemPacket.buffer.bytes, xmodemPacket.buffer.size);
|
||||
sendControl(XModem_Control_ACK);
|
||||
packetno++;
|
||||
break;
|
||||
}
|
||||
// invalid packet
|
||||
sendControl(XModem_Control_NAK);
|
||||
break;
|
||||
} else if (isTransmitting) {
|
||||
// just received something weird.
|
||||
sendControl(XModem_Control_CAN);
|
||||
isTransmitting = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case XModem_Control_EOT:
|
||||
// End of transmission
|
||||
sendControl(XModem_Control_ACK);
|
||||
file.close();
|
||||
isReceiving = false;
|
||||
break;
|
||||
case XModem_Control_CAN:
|
||||
// Cancel transmission and remove file
|
||||
sendControl(XModem_Control_ACK);
|
||||
file.close();
|
||||
FSCom.remove(filename);
|
||||
isReceiving = false;
|
||||
break;
|
||||
case XModem_Control_ACK:
|
||||
// Acknowledge Send the next packet
|
||||
if (isTransmitting) {
|
||||
if (isEOT) {
|
||||
sendControl(XModem_Control_EOT);
|
||||
file.close();
|
||||
isTransmitting = false;
|
||||
isEOT = false;
|
||||
break;
|
||||
}
|
||||
retrans = MAXRETRANS; // reset retransmit counter
|
||||
packetno++;
|
||||
memset(xmodemStore, 0, XModem_size);
|
||||
xmodemStore->control = XModem_Control_SOH;
|
||||
xmodemStore->seq = packetno;
|
||||
xmodemStore->buffer.size = file.read(xmodemStore->buffer.bytes, sizeof(XModem_buffer_t::bytes));
|
||||
xmodemStore->crc16 = crc16_ccitt(xmodemStore->buffer.bytes, xmodemStore->buffer.size);
|
||||
if (xmodemStore->buffer.size < sizeof(XModem_buffer_t::bytes)) {
|
||||
isEOT = true;
|
||||
// send EOT on next Ack
|
||||
}
|
||||
} else {
|
||||
// just received something weird.
|
||||
sendControl(XModem_Control_CAN);
|
||||
}
|
||||
break;
|
||||
case XModem_Control_NAK:
|
||||
// Negative acknowledge. Send the same buffer again
|
||||
if (isTransmitting) {
|
||||
if (--retrans <= 0) {
|
||||
sendControl(XModem_Control_CAN);
|
||||
file.close();
|
||||
isTransmitting = false;
|
||||
break;
|
||||
}
|
||||
memset(xmodemStore, 0, XModem_size);
|
||||
xmodemStore->control = XModem_Control_SOH;
|
||||
xmodemStore->seq = packetno;
|
||||
file.seek((packetno-1) * sizeof(XModem_buffer_t::bytes));
|
||||
xmodemStore->buffer.size = file.read(xmodemStore->buffer.bytes, sizeof(XModem_buffer_t::bytes));
|
||||
xmodemStore->crc16 = crc16_ccitt(xmodemStore->buffer.bytes, xmodemStore->buffer.size);
|
||||
if (xmodemStore->buffer.size < sizeof(XModem_buffer_t::bytes)) {
|
||||
isEOT = true;
|
||||
// send EOT on next Ack
|
||||
}
|
||||
} else {
|
||||
// just received something weird.
|
||||
sendControl(XModem_Control_CAN);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Unknown control character
|
||||
break;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user