|
@@ -0,0 +1,537 @@
|
|
|
+/**
|
|
|
+ * @file shellmatta_ymodem.c
|
|
|
+ * @brief ymodem functions of shellmatta
|
|
|
+ * @author Simon Fischer <dev@s-fischer.net>
|
|
|
+ */
|
|
|
+
|
|
|
+#include "shellmatta_ymodem.h"
|
|
|
+#include "shellmatta_crc.h"
|
|
|
+#include "shellmatta_utils.h"
|
|
|
+
|
|
|
+/* current ymodem packet size */
|
|
|
+uint16_t yModemPacketSize = YMODEM_PACKET_SIZE;
|
|
|
+/* packet counter - counts all correctly received packets during one transmission */
|
|
|
+uint8_t shellmatta_ymodem_packet_counter = 0u;
|
|
|
+/* counts total amount of data bytes received during one transmission */
|
|
|
+uint16_t shellmatta_ymodem_total_bytes_received = 0u;
|
|
|
+/* counts total amount of data bytes received during one packet */
|
|
|
+uint16_t shellmatta_ymodem_byte_counter = 0u;
|
|
|
+/* structure of a packet consisting of data and metadata */
|
|
|
+shellmatta_ymodem_packet_t shellmatta_ymodem_packet;
|
|
|
+/* holds information about which data type is currently actice: YMODEM_NONE, YMODEM_HEADER, YMODEM_BODY, YMODEM_FOOTER */
|
|
|
+shellmatta_ymodem_datatype_t shellmatta_ymodem_current_data_type = YMODEM_NONE;
|
|
|
+/* structure of ymodem callback functions */
|
|
|
+shellmatta_ymodem_callbacks_t shellmatta_ymodem_callbacks;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Initialise the ymodem prior to actually receiving data
|
|
|
+ * @param[in, out] handle shellmatta handle of the instance
|
|
|
+ * @param[in] recvBuffer pointer to the buffer to save the received payload in
|
|
|
+ * @param[in] fileSize pointer to the file size variable
|
|
|
+ * @param[in] packetSize pointer to the packet size variable
|
|
|
+ * @param[in] callbacks callback functions for the ymodem module
|
|
|
+*/
|
|
|
+void shellmatta_ymodem_init(shellmatta_handle_t handle,
|
|
|
+ uint8_t* recvBuffer,
|
|
|
+ uint16_t* fileSize,
|
|
|
+ uint16_t* packetSize,
|
|
|
+ shellmatta_ymodem_callbacks_t callbacks)
|
|
|
+{
|
|
|
+ if ((void*)0u == recvBuffer) return;
|
|
|
+ /* init packet structure */
|
|
|
+ shellmatta_ymodem_packet.packetNumber = 0u;
|
|
|
+ shellmatta_ymodem_packet.reversePacketNumber = 0u;
|
|
|
+ shellmatta_ymodem_packet.packetCrc = 0u;
|
|
|
+ shellmatta_ymodem_packet.packetSize = packetSize;
|
|
|
+ shellmatta_ymodem_packet.fileSize = fileSize;
|
|
|
+ shellmatta_ymodem_packet.packetData = recvBuffer;
|
|
|
+
|
|
|
+ /* init callbacks */
|
|
|
+ shellmatta_ymodem_callbacks = callbacks;
|
|
|
+
|
|
|
+ /* init ymodem state */
|
|
|
+ shellmatta_ymodem_set_state(handle, WAIT_FOR_START);
|
|
|
+
|
|
|
+ /* init current data type */
|
|
|
+ shellmatta_ymodem_current_data_type = YMODEM_NONE;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief change the current state of the ymodem module
|
|
|
+ * @param[in, out] handle shellmatta handle of the instance
|
|
|
+ * @param[in] newState the state the ymodem module should be changed to
|
|
|
+*/
|
|
|
+void shellmatta_ymodem_set_state(shellmatta_handle_t handle, shellmatta_ymodem_state_t newState)
|
|
|
+{
|
|
|
+ ((shellmatta_instance_t*)handle)->ymodemState = newState;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Returns the current state of the ymodem module
|
|
|
+ * @param[in, out] handle shellmatta handle of the instance
|
|
|
+ * @return the current state of the ymodem module
|
|
|
+*/
|
|
|
+shellmatta_ymodem_state_t shellmatta_ymodem_get_state(shellmatta_handle_t handle)
|
|
|
+{
|
|
|
+ return ((shellmatta_instance_t*)handle)->ymodemState;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief State machine that processes bytewise input during active ymodem transmission
|
|
|
+ * @param[in, out] handle shellmatta handle of the instance
|
|
|
+ * @param[in] byteIn the byte to be processed
|
|
|
+ * @note won't do anything if ymodem module is not initialized
|
|
|
+*/
|
|
|
+void shellmatta_ymodem_receive_packet(shellmatta_handle_t handle, uint8_t byteIn)
|
|
|
+{
|
|
|
+ static uint8_t fileNameDelimiterPosition = 255u;
|
|
|
+ static uint8_t fileSizeDelimiterPosition = 255u;
|
|
|
+ static uint32_t fileSize = 0u;
|
|
|
+ static char fileSizeStr[7u]; /* hopefully no more bytes than a million will ever be transmitted */
|
|
|
+ shellmatta_ymodem_rcv_retcode_t recvRetCode;
|
|
|
+ recvRetCode = shellmatta_ymodem_receive_byte(handle, byteIn);
|
|
|
+ switch (shellmatta_ymodem_get_state(handle))
|
|
|
+ {
|
|
|
+ case INACTIVE:
|
|
|
+ /* cant do anything if ymodem module was not correctly initialized */
|
|
|
+ return;
|
|
|
+ case WAIT_FOR_START:
|
|
|
+ /* wait for start symbol of a packet */
|
|
|
+ switch (shellmatta_ymodem_current_data_type)
|
|
|
+ {
|
|
|
+ case YMODEM_NONE: /* go here if the header packet is to be expected */
|
|
|
+ if (recvRetCode == SOH_RECEIVED || recvRetCode == STX_RECEIVED)
|
|
|
+ {
|
|
|
+ /* reset packet counter */
|
|
|
+ shellmatta_ymodem_packet_counter = 0u;
|
|
|
+ shellmatta_ymodem_byte_counter = 0u;
|
|
|
+ shellmatta_printf(handle, "SOH receive\r\n");
|
|
|
+ shellmatta_ymodem_set_state(handle, RECEIVE_PACKET);
|
|
|
+ shellmatta_ymodem_current_data_type = YMODEM_HEADER;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case YMODEM_HEADER: /* go here if the first body packet is to be expected */
|
|
|
+ if (recvRetCode == SOH_RECEIVED || recvRetCode == STX_RECEIVED)
|
|
|
+ {
|
|
|
+ shellmatta_ymodem_byte_counter = 0u;
|
|
|
+ shellmatta_printf(handle, "SOH receive\r\n");
|
|
|
+ shellmatta_ymodem_set_state(handle, RECEIVE_PACKET);
|
|
|
+ shellmatta_ymodem_current_data_type = YMODEM_BODY;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case YMODEM_BODY: /* go here if the data transmission loop is active */
|
|
|
+ if (recvRetCode == SOH_RECEIVED || recvRetCode == STX_RECEIVED)
|
|
|
+ {
|
|
|
+ shellmatta_ymodem_byte_counter = 0u;
|
|
|
+ /* stay in body when SOH was received */
|
|
|
+ shellmatta_printf(handle, "SOH receive\r\n");
|
|
|
+ shellmatta_ymodem_set_state(handle, RECEIVE_PACKET);
|
|
|
+ shellmatta_ymodem_current_data_type = YMODEM_BODY;
|
|
|
+ }
|
|
|
+ else /* go here if the end of transmission symbol is received */
|
|
|
+ if (recvRetCode == EOT_RECEIVED)
|
|
|
+ {
|
|
|
+ shellmatta_ymodem_byte_counter = 0u;
|
|
|
+ /* go to footer when EOT was received */
|
|
|
+ shellmatta_printf(handle, "EOT receive\r\n");
|
|
|
+ /* answer with ACK */
|
|
|
+ shellmatta_ymodem_ack(handle);
|
|
|
+ /* then send 0x43 symbol */
|
|
|
+ shellmatta_ymodem_control(handle, YMODEM_CRC);
|
|
|
+ /* then wait for SOH */
|
|
|
+ shellmatta_ymodem_current_data_type = YMODEM_FOOTER;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case YMODEM_FOOTER: /* go here if the end of transmission packet is to be expected */
|
|
|
+ /* it _may_ be, that EOT is sent multiple times, repeat previous procedure */
|
|
|
+ if (recvRetCode == EOT_RECEIVED)
|
|
|
+ {
|
|
|
+ /* answer with ACK */
|
|
|
+ shellmatta_ymodem_ack(handle);
|
|
|
+ /* then send 0x43 symbol */
|
|
|
+ shellmatta_ymodem_control(handle, YMODEM_CRC);
|
|
|
+ }
|
|
|
+ if (recvRetCode == SOH_RECEIVED)
|
|
|
+ {
|
|
|
+ /* reset packet counter */
|
|
|
+ shellmatta_ymodem_packet_counter = 0u;
|
|
|
+ /* reset byte counter to avoid error by one caused by previously received EOT symbol */
|
|
|
+ shellmatta_ymodem_byte_counter = 0u;
|
|
|
+ shellmatta_printf(handle, "EOT packet starting\r\n");
|
|
|
+ shellmatta_ymodem_set_state(handle, RECEIVE_PACKET);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case RECEIVE_PACKET:
|
|
|
+ /* receiving data */
|
|
|
+ if (recvRetCode == DATA_RECEIVED)
|
|
|
+ {
|
|
|
+ switch (shellmatta_ymodem_current_data_type)
|
|
|
+ {
|
|
|
+ case YMODEM_HEADER:
|
|
|
+ switch (shellmatta_ymodem_byte_counter)
|
|
|
+ {
|
|
|
+ /* first two bytes are packet number and reverse packet number */
|
|
|
+ case 0:
|
|
|
+ shellmatta_ymodem_packet.packetNumber = byteIn;
|
|
|
+ shellmatta_printf(handle, "packet number = %u\r\n", shellmatta_ymodem_packet.packetNumber);
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ shellmatta_ymodem_packet.reversePacketNumber = byteIn;
|
|
|
+ shellmatta_printf(handle, "reverse packet number = %u\r\n", shellmatta_ymodem_packet.reversePacketNumber);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ /* after packet numbers, data field begins */
|
|
|
+ if (shellmatta_ymodem_byte_counter >= YMODEM_HEADER_DATA_OFFSET && shellmatta_ymodem_byte_counter < YMODEM_HEADER_CRC_POSITION)
|
|
|
+ {
|
|
|
+ shellmatta_ymodem_packet.packetData[shellmatta_ymodem_byte_counter - YMODEM_HEADER_DATA_OFFSET] = byteIn;
|
|
|
+ /* check for filename */
|
|
|
+ if (shellmatta_ymodem_byte_counter < fileNameDelimiterPosition)
|
|
|
+ {
|
|
|
+ /* find NULL-Terminator in filename */
|
|
|
+ if (byteIn == YMODEM_NULL)
|
|
|
+ {
|
|
|
+ fileNameDelimiterPosition = shellmatta_ymodem_byte_counter + 1;
|
|
|
+ shellmatta_printf(handle, "%s\r\n", shellmatta_ymodem_packet.packetData);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /* after filename the filesize begins */
|
|
|
+ else
|
|
|
+ if (shellmatta_ymodem_byte_counter >= fileNameDelimiterPosition && shellmatta_ymodem_byte_counter < fileSizeDelimiterPosition)
|
|
|
+ {
|
|
|
+ /* find space as delimiter after filesize */
|
|
|
+ if (byteIn == YMODEM_SPACE)
|
|
|
+ {
|
|
|
+ fileSizeDelimiterPosition = shellmatta_ymodem_byte_counter;
|
|
|
+ /* convert file size string to actual number */
|
|
|
+ fileSize = utils_shellAsciiToUInt32(fileSizeStr, fileSizeDelimiterPosition - fileNameDelimiterPosition);
|
|
|
+ *shellmatta_ymodem_packet.fileSize = fileSize;
|
|
|
+ shellmatta_printf(handle, "fileSize = %u\r\n", fileSize);
|
|
|
+ }
|
|
|
+ /* save characters in string otherwise */
|
|
|
+ else
|
|
|
+ {
|
|
|
+ fileSizeStr[shellmatta_ymodem_byte_counter - fileNameDelimiterPosition] = byteIn;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ /* some meta data from sender, possibly file date */
|
|
|
+ /* not needed for now */
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /* after data field, crc begins */
|
|
|
+ if (shellmatta_ymodem_byte_counter >= YMODEM_HEADER_CRC_POSITION)
|
|
|
+ {
|
|
|
+ if (shellmatta_ymodem_byte_counter == YMODEM_HEADER_CRC_POSITION)
|
|
|
+ {
|
|
|
+ /* upper byte */
|
|
|
+ shellmatta_ymodem_packet.packetCrc = byteIn << 8u;
|
|
|
+ }
|
|
|
+ if (shellmatta_ymodem_byte_counter == YMODEM_HEADER_CRC_POSITION + 1)
|
|
|
+ {
|
|
|
+ /* lower byte */
|
|
|
+ shellmatta_ymodem_packet.packetCrc |= byteIn;
|
|
|
+ /* change ymodem state to check packet */
|
|
|
+ shellmatta_printf(handle, "packetCrc = 0x%04x\r\n", shellmatta_ymodem_packet.packetCrc);
|
|
|
+ shellmatta_ymodem_check_packet(handle);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ shellmatta_ymodem_byte_counter++;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case YMODEM_BODY:
|
|
|
+ switch (shellmatta_ymodem_byte_counter)
|
|
|
+ {
|
|
|
+ case 0:
|
|
|
+ shellmatta_ymodem_packet.packetNumber = byteIn;
|
|
|
+ shellmatta_printf(handle, "packet number = %u\r\n", shellmatta_ymodem_packet.packetNumber);
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ shellmatta_ymodem_packet.reversePacketNumber = byteIn;
|
|
|
+ shellmatta_printf(handle, "reverse packet number = %u\r\n", shellmatta_ymodem_packet.reversePacketNumber);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // TODO: Something might still be wrong here
|
|
|
+ /* after data field, crc begins */
|
|
|
+ if (shellmatta_ymodem_byte_counter > yModemPacketSize + 2)
|
|
|
+ {
|
|
|
+ if (shellmatta_ymodem_byte_counter == yModemPacketSize + 3)
|
|
|
+ {
|
|
|
+ /* upper byte */
|
|
|
+ shellmatta_ymodem_packet.packetCrc = byteIn << 8u;
|
|
|
+ }
|
|
|
+ if (shellmatta_ymodem_byte_counter == yModemPacketSize + 4)
|
|
|
+ {
|
|
|
+ /* lower byte */
|
|
|
+ shellmatta_ymodem_packet.packetCrc |= byteIn;
|
|
|
+ /* change ymodem state to check packet */
|
|
|
+ shellmatta_printf(handle, "packetCrc = 0x%04x\r\n", shellmatta_ymodem_packet.packetCrc);
|
|
|
+ shellmatta_ymodem_check_packet(handle);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ if (shellmatta_ymodem_byte_counter > 1)
|
|
|
+ {
|
|
|
+ shellmatta_ymodem_packet.packetData[shellmatta_ymodem_byte_counter - YMODEM_HEADER_DATA_OFFSET] = byteIn;
|
|
|
+ }
|
|
|
+ shellmatta_ymodem_byte_counter++;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case YMODEM_FOOTER:
|
|
|
+ /* reset packet counter */
|
|
|
+ shellmatta_ymodem_packet_counter = 0;
|
|
|
+
|
|
|
+ switch (shellmatta_ymodem_byte_counter)
|
|
|
+ {
|
|
|
+ case 0:
|
|
|
+ shellmatta_ymodem_packet.packetNumber = byteIn;
|
|
|
+ shellmatta_printf(handle, "packet number = %u\r\n", shellmatta_ymodem_packet.packetNumber);
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ shellmatta_ymodem_packet.reversePacketNumber = byteIn;
|
|
|
+ shellmatta_printf(handle, "reverse packet number = %u\r\n", shellmatta_ymodem_packet.reversePacketNumber);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (shellmatta_ymodem_byte_counter == YMODEM_PACKET_SIZE)
|
|
|
+ {
|
|
|
+ shellmatta_ymodem_check_packet(handle);
|
|
|
+ }
|
|
|
+ shellmatta_ymodem_byte_counter++;
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Gives a return code depending on symbol received at different states of the ymodem module
|
|
|
+ * @param[in, out] handle shellmatta handle of the instance
|
|
|
+ * @param[in] byteIn currently processed input byte
|
|
|
+*/
|
|
|
+shellmatta_ymodem_rcv_retcode_t shellmatta_ymodem_receive_byte(shellmatta_handle_t handle, uint8_t byteIn)
|
|
|
+{
|
|
|
+ shellmatta_ymodem_rcv_retcode_t ret;
|
|
|
+ if (WAIT_FOR_START == shellmatta_ymodem_get_state(handle))
|
|
|
+ {
|
|
|
+ switch (byteIn)
|
|
|
+ {
|
|
|
+ case YMODEM_SOH:
|
|
|
+ /* start of header -> default packet size */
|
|
|
+ yModemPacketSize = YMODEM_PACKET_SIZE;
|
|
|
+ ret = SOH_RECEIVED;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case YMODEM_STX:
|
|
|
+ /* start of header -> extended packet size */
|
|
|
+ yModemPacketSize = YMODEM_PACKET_SIZE_1K;
|
|
|
+ ret = STX_RECEIVED;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case YMODEM_EOT:
|
|
|
+ /* end of transmission -> data transmission complete */
|
|
|
+ ret = EOT_RECEIVED;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case YMODEM_CA:
|
|
|
+ /* cancel transmssion -> reset state machine */
|
|
|
+ ret = CA_RECEIVED;
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ /* no other data should be received in this state */
|
|
|
+ ret = ERROR;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ /* give packet size back to upper layer */
|
|
|
+ *shellmatta_ymodem_packet.packetSize = yModemPacketSize;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ if (RECEIVE_PACKET == shellmatta_ymodem_get_state(handle))
|
|
|
+ {
|
|
|
+ ret = DATA_RECEIVED;
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Checks packet data for validity and sends ACK or NAK accordingly
|
|
|
+ * @param[in, out] handle shellmatta handle of the instance
|
|
|
+ * @note Only to be called after full packet is received
|
|
|
+ * @note Will call yModemRecvPacketCallback when packet is received correctly
|
|
|
+ * @note Will call ymodemTransmissionCompleteCallback when transmission is completed
|
|
|
+*/
|
|
|
+void shellmatta_ymodem_check_packet(shellmatta_handle_t handle)
|
|
|
+{
|
|
|
+ uint8_t computedCrc = 0u;
|
|
|
+ if (shellmatta_ymodem_packet.packetNumber != (0xFF - shellmatta_ymodem_packet.reversePacketNumber))
|
|
|
+ {
|
|
|
+ shellmatta_printf(handle, "wrong packet number pair\r\n");
|
|
|
+ shellmatta_ymodem_nak(handle);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ /* compare to internal packet counter */
|
|
|
+ if (shellmatta_ymodem_packet.packetNumber != shellmatta_ymodem_packet_counter)
|
|
|
+ {
|
|
|
+ shellmatta_printf(handle, "wrong packet number\r\n");
|
|
|
+ shellmatta_printf(handle, "expected %u, got %u\r\n", shellmatta_ymodem_packet_counter, shellmatta_ymodem_packet.packetNumber);
|
|
|
+ shellmatta_ymodem_nak(handle);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ /* compare packet crc only after other checks succeeded */
|
|
|
+ computedCrc = crc16Calc((const char*)shellmatta_ymodem_packet.packetData, yModemPacketSize);
|
|
|
+ //! uncomment for debug purposes
|
|
|
+ // if (shellmatta_ymodem_packet.packetCrc != computedCrc)
|
|
|
+ // {
|
|
|
+ // shellmatta_printf(handle, "wrong packet crc: expected 0x%04x\r\n", computedCrc);
|
|
|
+ // shellmatta_ymodem_nak(handle);
|
|
|
+ // return;
|
|
|
+ // }
|
|
|
+ /* if previous checks passed, packet is acknowledged */
|
|
|
+ (void) computedCrc;
|
|
|
+ shellmatta_ymodem_total_bytes_received += shellmatta_ymodem_byte_counter;
|
|
|
+ shellmatta_ymodem_byte_counter = 0u;
|
|
|
+ shellmatta_ymodem_ack(handle);
|
|
|
+ if (shellmatta_ymodem_current_data_type == YMODEM_HEADER)
|
|
|
+ {
|
|
|
+ /* send additional CRC symbol if the packet was a header packet */
|
|
|
+ shellmatta_ymodem_control(handle, YMODEM_CRC);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* callback handling */
|
|
|
+ switch (shellmatta_ymodem_current_data_type)
|
|
|
+ {
|
|
|
+ case YMODEM_NONE:
|
|
|
+ /* shouldn't happen */
|
|
|
+ break;
|
|
|
+
|
|
|
+ case YMODEM_HEADER:
|
|
|
+ /* nothing to do after receiving the header packet */
|
|
|
+ break;
|
|
|
+
|
|
|
+ case YMODEM_BODY:
|
|
|
+ /* call the ymodem receive packet callback */
|
|
|
+ if (shellmatta_ymodem_callbacks.yModemRecvPacketCallback != (void*)0u)
|
|
|
+ {
|
|
|
+ shellmatta_ymodem_callbacks.yModemRecvPacketCallback();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case YMODEM_FOOTER:
|
|
|
+ /* call the ymodem transmission complete callback */
|
|
|
+ if (shellmatta_ymodem_callbacks.ymodemTransmissionCompleteCallback != (void*)0u)
|
|
|
+ {
|
|
|
+ shellmatta_ymodem_callbacks.ymodemTransmissionCompleteCallback();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Acknowledge handling. Will send ACK and set ymodem state back to WAIT_FOR_START
|
|
|
+ * @param[in, out] handle shellmatta handle of the instance
|
|
|
+*/
|
|
|
+void shellmatta_ymodem_ack(shellmatta_handle_t handle)
|
|
|
+{
|
|
|
+ shellmatta_ymodem_control(handle, YMODEM_ACK);
|
|
|
+ shellmatta_ymodem_packet_counter++;
|
|
|
+ shellmatta_ymodem_set_state(handle, WAIT_FOR_START);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Not-Acknowledge handling. Will send NAK and set ymodem state back to WAIT_FOR_START
|
|
|
+ * @param[in, out] handle shellmatta handle of the instance
|
|
|
+*/
|
|
|
+void shellmatta_ymodem_nak(shellmatta_handle_t handle)
|
|
|
+{
|
|
|
+ shellmatta_ymodem_control(handle, YMODEM_NAK);
|
|
|
+ shellmatta_ymodem_set_state(handle, WAIT_FOR_START);
|
|
|
+ /* set back current data type to prevent false forward stepping */
|
|
|
+ switch (shellmatta_ymodem_current_data_type)
|
|
|
+ {
|
|
|
+ case YMODEM_NONE:
|
|
|
+ /* no handling needed */
|
|
|
+ break;
|
|
|
+
|
|
|
+ case YMODEM_HEADER:
|
|
|
+ shellmatta_ymodem_current_data_type = YMODEM_NONE;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case YMODEM_BODY:
|
|
|
+ /* YMODEM_BODY stays in YMODEM_BODY */
|
|
|
+ shellmatta_ymodem_current_data_type = YMODEM_BODY;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case YMODEM_FOOTER:
|
|
|
+ /* YMODEM_FOOTER as well */
|
|
|
+ shellmatta_ymodem_current_data_type = YMODEM_FOOTER;
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void shellmatta_ymodem_control(shellmatta_handle_t handle, const char c)
|
|
|
+{
|
|
|
+ shellmatta_printf(handle, "0x%02x\r\n", c);
|
|
|
+ ((shellmatta_instance_t*)handle)->write(&c, 1);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief reset function for the ymodem module
|
|
|
+ * @param[in, out] handle shellmatta handle of the instance
|
|
|
+ * @param[in] doCancel flag to execute the cancel-callback
|
|
|
+*/
|
|
|
+void shellmatta_ymodem_reset(shellmatta_handle_t handle, bool doCancel)
|
|
|
+{
|
|
|
+ /* call cancel callback function */
|
|
|
+ if (doCancel)
|
|
|
+ {
|
|
|
+ if (shellmatta_ymodem_callbacks.yModemCancelCallback != (void*)0u)
|
|
|
+ {
|
|
|
+ shellmatta_ymodem_callbacks.yModemCancelCallback();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* reset all ymodem_packet data */
|
|
|
+ shellmatta_ymodem_packet.packetNumber = 0u;
|
|
|
+ shellmatta_ymodem_packet.reversePacketNumber = 0u;
|
|
|
+ shellmatta_ymodem_packet.packetCrc = 0u;
|
|
|
+ shellmatta_ymodem_packet.packetSize = 0u;
|
|
|
+ shellmatta_ymodem_packet.fileSize = 0u;
|
|
|
+ shellmatta_ymodem_packet.packetData = 0u;
|
|
|
+
|
|
|
+ /* set ymodem to inactive */
|
|
|
+ shellmatta_ymodem_set_state(handle, INACTIVE);
|
|
|
+
|
|
|
+ shellmatta_ymodem_current_data_type = YMODEM_NONE;
|
|
|
+
|
|
|
+#ifdef SHELLMATTA_TRANSPORT_ENABLE
|
|
|
+ /* re-enable transport layer */
|
|
|
+ ((shellmatta_instance_t*)handle)->transportEnabled = true;
|
|
|
+#endif
|
|
|
+}
|