Browse Source

got the shellmatta up and running again - missing package decoding

stefan 9 months ago
parent
commit
d141d3ea58
5 changed files with 239 additions and 92 deletions
  1. 6 6
      api/shellmatta.h
  2. 1 1
      example/main.c
  3. 13 8
      src/shellmatta_utils.c
  4. 219 51
      src/shellmatta_ymodem.c
  5. 0 26
      src/shellmatta_ymodem.h

+ 6 - 6
api/shellmatta.h

@@ -465,13 +465,13 @@ shellmatta_retCode_t shellmatta_auth_chpasswd(              shellmatta_handle_t
 
 #endif
 
-uint8_t shellmatta_ymodem(      shellmatta_handle_t             handle,
-                                uint8_t*                        buffer,
-                                void (*cancelCallback)(void),
-                                void (*recvPacketCallback)(void),
-                                void (*transmissionCompleteCallback)(void));
+shellmatta_retCode_t shellmatta_ymodem_init(shellmatta_handle_t handle, 
+                                            uint8_t*            recvBuffer, 
+                                            void                (*cancelCallback)(void),
+                                            void                (*recvPacketCallback)(void),
+                                            void                (*transmissionCompleteCallback)(void));
 
-void shellmatta_ymodem_cancel(  shellmatta_handle_t             handle);
+void shellmatta_ymodem_cancel(              shellmatta_handle_t handle);
 
 #endif
 

+ 1 - 1
example/main.c

@@ -198,7 +198,7 @@ static shellmatta_retCode_t ymodem(shellmatta_handle_t handle, const char *argum
     (void)arguments;
     (void)length;
     shellmatta_printf(handle, "Starting ymodem session\r\n");
-    shellmatta_ymodem(handle,
+    shellmatta_ymodem_init(handle,
                       ymodemBuffer,
                       ymodemCallbackCancel,
                       ymodemCallbackReceivePacket,

+ 13 - 8
src/shellmatta_utils.c

@@ -513,16 +513,21 @@ void utils_terminateInput(shellmatta_instance_t *inst)
     inst->stdinLength       = 0u;
     inst->continuousCmd     = NULL;
     inst->busyCmd           = NULL;
-    SHELLMATTA_WRITE("\r\n", 2u);
-#ifdef SHELLMATTA_AUTHENTICATION
-    inst->loginState        = SHELLMATTA_AUTH_IDLE;
-    if (NULL != inst->userPointer)
+
+    /** -# print prompt and username when no ymodem session is running */
+    if(SHELLMATTA_YMODEM_INACTIVE == inst->ymodem.state)
     {
-        SHELLMATTA_WRITE(inst->userPointer->username, strlen(inst->userPointer->username));
-        SHELLMATTA_WRITE("@", 1);
-    }
+        SHELLMATTA_WRITE("\r\n", 2u);
+#ifdef SHELLMATTA_AUTHENTICATION
+        inst->loginState        = SHELLMATTA_AUTH_IDLE;
+        if (NULL != inst->userPointer)
+        {
+            SHELLMATTA_WRITE(inst->userPointer->username, strlen(inst->userPointer->username));
+            SHELLMATTA_WRITE("@", 1);
+        }
 #endif
-    SHELLMATTA_WRITE(inst->prompt, strlen(inst->prompt));
+        SHELLMATTA_WRITE(inst->prompt, strlen(inst->prompt));
+    }
 }
 
 /**

+ 219 - 51
src/shellmatta_ymodem.c

@@ -10,31 +10,91 @@
 #include <stddef.h>
 #include <string.h>
 
+/** @brief symbols needed for ymodem protocol */
+typedef enum {
+    YMODEM_NULL    = 0x00, /**< NULL-terminator                 */
+    YMODEM_SOH     = 0x01, /**< Start of header                 */
+    YMODEM_STX     = 0x02, /**< Start of header for 1k packet   */
+    YMODEM_EOT     = 0x04, /**< End of transmission             */
+    YMODEM_ACK     = 0x06, /**< Acknowledge                     */
+    YMODEM_NAK     = 0x15, /**< Negative acknowledge            */
+    YMODEM_CA      = 0x18, /**< Cancel                          */
+    YMODEM_SPACE   = 0x20, /**< Space                           */
+    YMODEM_CRC     = 0x43  /**< 'C' to indicate CRC type        */
+} YMODEM_SYMBOLS;
+
+#define YMODEM_PACKET_SIZE          128u    /**< default packet size of ymodem transmission     */
+#define YMODEM_PACKET_SIZE_1K       1024u   /**< extended packet size of ymodem transmission    */
+#define YMODEM_CRC_SIZE             2u      /**< CRC size of the ymodem packet                  */
+
+/**
+ * @brief               forwards the given character to write-function without formatting
+ * @param[in]   handle  shellmatta handle of the instance
+ * @param[in]   c       character to be sent
+*/
+static void shellmatta_ymodem_control(shellmatta_handle_t handle, const uint8_t c)
+{
+    shellmatta_instance_t *inst = (shellmatta_instance_t*)handle;
+    SHELLMATTA_WRITE((char*)&c, 1);
+}
+
 /**
  * @brief                                           Initialise the ymodem prior to actually receiving data
- * @param[in, out]  ymodem                          shellmatta ymodem instance
+ * @param[in, out]  handle                          shellmatta instance handle
  * @param[in]       recvBuffer                      pointer to the buffer to save the received payload in
  * @param[in]       recvPacketCallback              pointer to the file size variable
  * @param[in]       recvPacketCallback              pointer to the packet size variable
  * @param[in]       transmissionCompleteCallback    callback functions for the ymodem module
+ * @return          todo
+ * @note            Disables the tranport layer if inactive or sets it to mandatory if active
 */
-void shellmatta_ymodem_init(shellmatta_ymodem_t *ymodem,
-                            uint8_t* recvBuffer,
-                            void (*cancelCallback)(void),
-                            void (*recvPacketCallback)(void),
-                            void (*transmissionCompleteCallback)(void))
+shellmatta_retCode_t shellmatta_ymodem_init(shellmatta_handle_t handle,
+                                            uint8_t* recvBuffer,
+                                            void (*cancelCallback)(void),
+                                            void (*recvPacketCallback)(void),
+                                            void (*transmissionCompleteCallback)(void))
 {
-    memset((void *)&ymodem, 0, sizeof(shellmatta_ymodem_t));
+    shellmatta_retCode_t ret = SHELLMATTA_OK;
+    shellmatta_instance_t *inst = (shellmatta_instance_t *)handle;
+    (void)memset((void *)&inst->ymodem, 0, sizeof(shellmatta_ymodem_t));
+
+    /** -# check parameters for plausibility  */
+    if(     (NULL               != inst)
+        &&  (SHELLMATTA_MAGIC   == inst->magic))
+    {
+        /** -# use instances buffer if no buffer is given */
+        if(NULL == recvBuffer)
+        {
+            if(inst->bufferSize <= YMODEM_PACKET_SIZE_1K)
+            {
+                /** -# return use fault if buffer is too small */
+                ret = SHELLMATTA_USE_FAULT;
+            }
+            else
+            {
+                inst->ymodem.packet.packetData = (uint8_t*)inst->buffer;
+            }
+        }
 
-    /** -# store buffer */
-    ymodem->packet.packetData = recvBuffer;
+        /** -# store buffer */
+        inst->ymodem.packet.packetData = recvBuffer;
 
-    /** -# init callbacks */
-    ymodem->cancelCallback = cancelCallback;
-    ymodem->recvPacketCallback = recvPacketCallback;
-    ymodem->transmissionCompleteCallback = transmissionCompleteCallback;
+        /** -# init callbacks */
+        inst->ymodem.cancelCallback = cancelCallback;
+        inst->ymodem.recvPacketCallback = recvPacketCallback;
+        inst->ymodem.transmissionCompleteCallback = transmissionCompleteCallback;
 
-    ymodem->state = SHELLMATTA_YMODEM_WAIT_FOR_START;
+        inst->ymodem.state = SHELLMATTA_YMODEM_WAIT_FOR_START;
+
+        /* send initial ymodem symbol to start transmission */
+        shellmatta_ymodem_control(handle, YMODEM_CRC);
+    }
+    else
+    {
+        ret = SHELLMATTA_USE_FAULT;
+    }
+
+    return ret;
 }
 
 // /**
@@ -286,15 +346,154 @@ void shellmatta_ymodem_init(shellmatta_ymodem_t *ymodem,
 //         }
 //         break;
 
+
 //     default:
 //         break;
 //     }
 // }
 
+shellmatta_retCode_t processPacket(shellmatta_handle_t *handle)
+{
+    shellmatta_retCode_t ret = SHELLMATTA_OK;
+    shellmatta_instance_t *inst = (shellmatta_instance_t *)handle;
+
+    (void)inst;
+
+    return ret;
+}
+
+static shellmatta_retCode_t ymodem_stateMachine(shellmatta_handle_t *handle, uint8_t byte)
+{
+    shellmatta_retCode_t ret = SHELLMATTA_OK;
+    shellmatta_instance_t *inst = (shellmatta_instance_t *)handle;
+    uint16_t computedCrc;
+
+    switch(inst->ymodem.state)
+    {
+        case SHELLMATTA_YMODEM_INACTIVE:
+            /** -# skip state machine if inactive */
+            break;
+        case SHELLMATTA_YMODEM_WAIT_FOR_START:
+            /** -# Wait for start character */
+            inst->ymodem.byteCounter = 0u;
+            switch(byte)
+            {
+                case YMODEM_SOH:
+                    inst->ymodem.packet.size = YMODEM_PACKET_SIZE;
+                    inst->ymodem.state = SHELLMATTA_YMODEM_RECEIVE_HEADER;
+                    break;
+                case YMODEM_STX:
+                    inst->ymodem.packet.size = YMODEM_PACKET_SIZE_1K;
+                    inst->ymodem.state = SHELLMATTA_YMODEM_RECEIVE_HEADER;
+                    break;
+                case YMODEM_EOT:
+                    if(NULL != inst->ymodem.transmissionCompleteCallback)
+                    {
+                        inst->ymodem.transmissionCompleteCallback();
+                    }
+                    /** -# ACK the successful file reception */
+                    shellmatta_ymodem_control(handle, YMODEM_ACK);
+                    shellmatta_ymodem_control(handle, YMODEM_CRC);
+                    inst->ymodem.state = SHELLMATTA_YMODEM_INACTIVE;
+                    break;
+                default:
+                    /** -# ignore unexpected characters on start */
+                    break;
+            }
+            break;
+        case SHELLMATTA_YMODEM_RECEIVE_HEADER:
+            if(0u == inst->ymodem.byteCounter)
+            {
+                inst->ymodem.packet.packetNumber = byte;
+                inst->ymodem.byteCounter ++;
+            }
+            else
+            {
+                if(((0xffu - byte) != inst->ymodem.packet.packetNumber) ||
+                  (inst->ymodem.packetCounter % 256u != inst->ymodem.packet.packetNumber))
+                {
+                    /** -# return error on packet number mismatch or on unexpected packet numbers */
+                    inst->ymodem.state = SHELLMATTA_YMODEM_WAIT_FOR_START;
+                    ret = SHELLMATTA_ERROR;
+                }
+                else
+                {
+                    /** -# start receiving the payload */
+                    inst->ymodem.state = SHELLMATTA_YMODEM_RECEIVE_DATA;
+                    inst->ymodem.byteCounter = 0u;
+                }
+            }
+            break;
+        case SHELLMATTA_YMODEM_RECEIVE_DATA:
+            inst->ymodem.packet.packetData[inst->ymodem.byteCounter] = byte;
+            inst->ymodem.byteCounter ++;
+            
+            /** -# load payload until the packet is full */
+            if(inst->ymodem.byteCounter >= inst->ymodem.packet.size)
+            {
+                inst->ymodem.state = SHELLMATTA_YMODEM_RECEIVE_CRC;
+                inst->ymodem.byteCounter = 0u;
+                inst->ymodem.packet.crc = 0u;
+            }
+
+            break;
+        case SHELLMATTA_YMODEM_RECEIVE_CRC:
+            inst->ymodem.byteCounter ++;
+            inst->ymodem.packet.crc |= (uint16_t)byte << (8u * (YMODEM_CRC_SIZE - inst->ymodem.byteCounter));
+
+            if(inst->ymodem.byteCounter >= YMODEM_CRC_SIZE)
+            {
+                /** -# check CRC */
+                computedCrc = crc16Calc((const char*)inst->ymodem.packet.packetData,
+                                        inst->ymodem.packet.size);
+                if(computedCrc != inst->ymodem.packet.crc)
+                {
+                    ret = SHELLMATTA_ERROR;
+                }
+                else
+                {
+                    ret = processPacket(handle);
+                    if(SHELLMATTA_OK == ret)
+                    {
+                        /** -# pass data to the application using the callback */
+                        if(NULL != inst->ymodem.recvPacketCallback)
+                        {
+                            inst->ymodem.recvPacketCallback();
+                        }
+
+                        //todo - wait - or is it enough to block the recvPacketCallback?
+
+                        /** -# ACK the successful packet reception */
+                        shellmatta_ymodem_control(handle, YMODEM_ACK);
+                        if(0u == inst->ymodem.packetCounter)
+                        {
+                            /** -# send addional CRC flag after packet 0 */
+                            shellmatta_ymodem_control(handle, YMODEM_CRC);
+                        }
+                        else
+                        {
+                            /** -# Calculate the total bytes received */
+                            inst->ymodem.totalBytesReceived += inst->ymodem.packet.size;
+                        }
+                        inst->ymodem.packetCounter ++;
+                    }
+                }
+                inst->ymodem.state = SHELLMATTA_YMODEM_WAIT_FOR_START;
+            }
+            break;
+        default:
+            /** -# unexpected state - should never happen */
+            break;
+    }
+
+    return ret;
+}
+
 
 shellmatta_retCode_t shellmatta_ymodem_processByte(shellmatta_handle_t handle, char byte)
 {
     shellmatta_instance_t *inst = (shellmatta_instance_t*)handle;
+    shellmatta_retCode_t ret;
 
     /** -# check if session is cancelled -accept only if ymodem is between packets */
     if(('\x03' == byte) && (inst->ymodem.state == SHELLMATTA_YMODEM_WAIT_FOR_START))
@@ -304,12 +503,14 @@ shellmatta_retCode_t shellmatta_ymodem_processByte(shellmatta_handle_t handle, c
 
         utils_terminateInput(inst);
 
-        return SHELLMATTA_ERROR;
+        ret = SHELLMATTA_ERROR;
+    }
+    else
+    {
+        ret = ymodem_stateMachine(handle, (uint8_t)byte);
     }
 
-    //shellmatta_ymodem_receive_packet(handle, byte);
-
-    return SHELLMATTA_OK;
+    return ret;
 }
 
 
@@ -495,15 +696,6 @@ shellmatta_retCode_t shellmatta_ymodem_poll(shellmatta_handle_t handle)
 //     }
 // }
 
-/**
- * @brief               forwards the given character to write-function without formatting
- * @param[in]   handle  shellmatta handle of the instance
- * @param[in]   c       character to be sent
-*/
-void shellmatta_ymodem_control(shellmatta_handle_t handle, const char c)
-{
-    ((shellmatta_instance_t*)handle)->write(&c, 1);
-}
 
 /**
  * @brief                       reset function for the ymodem module
@@ -532,30 +724,6 @@ void shellmatta_ymodem_reset(shellmatta_ymodem_t *ymodem, bool doCancel)
     (void)memset((void *)&ymodem->packet, 0, sizeof(shellmatta_ymodem_packet_t));
 }
 
-/** 
- * @brief       starts the ymodem receive module 
- * @param[in]   handle      shellmatta instance handle
- * @param[in]   buffer      pointer to where the received data is stored
- * @param[in]   callbacks   callback functions for ymodem module
- * @note        disables the transport layer if active
-*/
-uint8_t shellmatta_ymodem(  shellmatta_handle_t             handle,
-                            uint8_t*                        buffer,
-                            void (*cancelCallback)(void),
-                            void (*recvPacketCallback)(void),
-                            void (*transmissionCompleteCallback)(void))
-{
-    shellmatta_instance_t *inst = (shellmatta_instance_t *)handle;
-
-    // todo check magic
-
-    shellmatta_ymodem_init(&inst->ymodem, buffer, cancelCallback, recvPacketCallback, transmissionCompleteCallback);
-
-    /* send initial ymodem symbol to start transmission */
-    shellmatta_ymodem_control(handle, YMODEM_CRC);
-    return 0;
-}
-
 /**
  * @brief       Resets the ymodem module
  * @param[in]   doCancel    Set this flag to execute the cancel-callback function within the ymodem-reset function

+ 0 - 26
src/shellmatta_ymodem.h

@@ -10,24 +10,6 @@
 #include <stdint.h>
 #include "shellmatta.h"
 
-#define YMODEM_PACKET_SIZE          128u    /* default packet size of ymodem transmission */
-#define YMODEM_PACKET_SIZE_1K       1024u   /* extended packet size of ymodem transmission */
-#define YMODEM_HEADER_DATA_OFFSET   2u      /* offset position of data field in header packet */
-#define YMODEM_HEADER_CRC_POSITION  130u    /* position of crc16 in header packet, relative to packet number */
-
-/** @brief symbols needed for ymodem protocol */
-typedef enum {
-    YMODEM_NULL    = 0x00, /* NULL-terminator */
-    YMODEM_SOH     = 0x01, /* Start of header */
-    YMODEM_STX     = 0x02, /* Start of header for 1k packet */
-    YMODEM_EOT     = 0x04, /* End of transmission */
-    YMODEM_ACK     = 0x06, /* Acknowledge */
-    YMODEM_NAK     = 0x15, /* Negative acknowledge */
-    YMODEM_CA      = 0x18, /* Cancel */
-    YMODEM_SPACE   = 0x20, /* Space */
-    YMODEM_CRC     = 0x43  /* 'C' to indicate CRC type */
-} YMODEM_SYMBOLS;
-
 /**
  * @brief return codes for receive byte function of ymodem module
 */
@@ -47,11 +29,6 @@ typedef enum {
     YMODEM_FOOTER  /* end of transmission packet is transmitted */
 } shellmatta_ymodem_datatype_t;
 
-void shellmatta_ymodem_init(            shellmatta_ymodem_t             *ymodem, 
-                                        uint8_t*                        recvBuffer, 
-                                        void                            (*cancelCallback)(void),
-                                        void                            (*recvPacketCallback)(void),
-                                        void                            (*transmissionCompleteCallback)(void));
 
 void shellmatta_ymodem_receive_packet(  shellmatta_handle_t             handle, 
                                         uint8_t                         byteIn);
@@ -69,9 +46,6 @@ shellmatta_ymodem_state_t shellmatta_ymodem_get_state(          shellmatta_handl
 shellmatta_ymodem_rcv_retcode_t shellmatta_ymodem_receive_byte( shellmatta_handle_t handle, 
                                                                 uint8_t             byteIn);
 
-void shellmatta_ymodem_control(         shellmatta_handle_t handle, 
-                                        const char          c);
-
 void shellmatta_ymodem_ack(             shellmatta_handle_t handle);
 
 void shellmatta_ymodem_nak(             shellmatta_handle_t handle);