Kaynağa Gözat

added wait cycle at the end of a ymodem session to flush out all bytes from the sender and get a fresh shellmatta session

stefan 9 ay önce
ebeveyn
işleme
2c57e28fd3
3 değiştirilmiş dosya ile 50 ekleme ve 22 silme
  1. 2 1
      api/shellmatta.h
  2. 2 2
      src/shellmatta.c
  3. 46 19
      src/shellmatta_ymodem.c

+ 2 - 1
api/shellmatta.h

@@ -229,7 +229,7 @@ typedef enum
     SHELLMATTA_YMODEM_RECEIVE_HEADER,   /**< reading header data            */
     SHELLMATTA_YMODEM_RECEIVE_DATA,     /**< reading payload                */
     SHELLMATTA_YMODEM_RECEIVE_CRC,      /**< reading crc                    */
-    SHELLMATTA_YMODEM_PAUSE             /**< pause after a packet           */
+    SHELLMATTA_YMODEM_WAIT_FOR_END      /**< wait until EOTs stop           */
 } shellmatta_ymodem_state_t;
 
 /** @brief packet structure that holds several information about its content */
@@ -252,6 +252,7 @@ typedef struct
     uint32_t totalBytesReceived;                                /**< counter of the totally received bytes          */
     uint32_t fileSize;                                          /**< size of the file received in packet 0          */
     bool pauseRequested;                                        /**< pause requested from the application           */
+    uint32_t pollCyclesLeft;                                    /**< number of poll cycles left before ending       */
     shellmatta_ymodem_packet_t packet;                          /**< currently processed packet                     */
     shellmatta_ymodem_cancel_t cancelCallback;                  /**< callback to pass cancel events                 */
     shellmatta_ymodem_recvHeader_t recvHeaderCallback;          /**< callback to pass received header data          */

+ 2 - 2
src/shellmatta.c

@@ -79,7 +79,7 @@ static shellmatta_retCode_t shellmatta_processDataInt(shellmatta_handle_t     ha
         }
     }
     /** -# poll shellmatta ymomdem to send out the request to the sender */
-    if(SHELLMATTA_YMODEM_WAIT_FOR_START == inst->ymodem.state)
+    if(SHELLMATTA_YMODEM_INACTIVE != inst->ymodem.state)
     {
         (void)shellmatta_ymodem_poll(handle);
     }
@@ -549,7 +549,7 @@ shellmatta_retCode_t shellmatta_resetShell(shellmatta_handle_t handle, bool prin
         inst->hereStartIdx          = 0u;
         inst->hereDelimiterIdx      = 0u;
         inst->hereLength            = 0u;
-        inst->ymodem.state          = SHELLMATTA_YMODEM_INACTIVE; // todo move to shellmatta_ymodem
+        inst->ymodem.state          = SHELLMATTA_YMODEM_INACTIVE;
         shellmatta_opt_init(inst, 0u);
 
 #ifdef SHELLMATTA_AUTHENTICATION

+ 46 - 19
src/shellmatta_ymodem.c

@@ -34,6 +34,7 @@ typedef enum {
 #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                  */
+#define YMODEM_EOT_NUMBER           2u      /**< Number of EOTs or polls to be received         */
 
 /**
  * @brief               forwards the given character to write-function without formatting
@@ -72,6 +73,7 @@ static void shellmatta_ymodem_reset(shellmatta_handle_t handle, bool doCancel)
     inst->ymodem.totalBytesReceived = 0u;
     inst->ymodem.fileSize = 0u;
     inst->ymodem.pauseRequested = false;
+    inst->ymodem.pollCyclesLeft = 0u;
 
 #ifdef SHELLMATTA_TRANSPORT
     /** .-# reenable transport layer optional mode */
@@ -145,28 +147,13 @@ static shellmatta_retCode_t ymodem_stateMachine(shellmatta_handle_t handle, uint
                     break;
 
                 case YMODEM_EOT:
-                    /** -# check if the received data matches the file size */
-                    if((inst->ymodem.totalBytesReceived < inst->ymodem.fileSize) ||
-                       ((inst->ymodem.totalBytesReceived - inst->ymodem.fileSize) >= YMODEM_PACKET_SIZE_1K))
-                    {
-                        ret = SHELLMATTA_ERROR;
-                    }
-
-                    inst->ymodem.transmissionCompleteCallback(ret);
-
-                    // todo add a wait state to answer some more EOTs after time
-
                     /** -# ACK the successful file reception */
                     shellmatta_ymodem_control(handle, YMODEM_ACK);
                     shellmatta_ymodem_control(handle, YMODEM_CRC);
 
-#ifdef SHELLMATTA_TRANSPORT
-                    /** .-# reenable transport layer optional mode */
-                    inst->transportLayer.suspendOptional = false;
-#endif
-
-                    inst->ymodem.state = SHELLMATTA_YMODEM_INACTIVE;
-                    (void)utils_terminateInput(inst);
+                    /** -# handle additional EOTs in WAIT FOR END state */
+                    inst->ymodem.state = SHELLMATTA_YMODEM_WAIT_FOR_END;
+                    inst->ymodem.pollCyclesLeft = YMODEM_EOT_NUMBER;
                     break;
                 default:
                     /** -# ignore unexpected characters on start */
@@ -251,6 +238,16 @@ static shellmatta_retCode_t ymodem_stateMachine(shellmatta_handle_t handle, uint
                 }
             }
             break;
+        case SHELLMATTA_YMODEM_WAIT_FOR_END:
+
+            inst->ymodem.pollCyclesLeft = YMODEM_EOT_NUMBER;
+            if(YMODEM_EOT ==  byte)
+            {
+                /** -# ACK the successful file reception */
+                shellmatta_ymodem_control(handle, YMODEM_ACK);
+                shellmatta_ymodem_control(handle, YMODEM_CRC);
+            }
+            break;
         default:
             /** -# unexpected state - should never happen */
             break;
@@ -287,11 +284,41 @@ shellmatta_retCode_t shellmatta_ymodem_poll(shellmatta_handle_t handle)
     shellmatta_retCode_t ret = SHELLMATTA_ERROR;
     shellmatta_instance_t *inst = (shellmatta_instance_t*)handle;
 
-    if (inst->ymodem.state == SHELLMATTA_YMODEM_WAIT_FOR_START)
+    switch (inst->ymodem.state)
     {
+    case SHELLMATTA_YMODEM_WAIT_FOR_START:
         /** -# send ymodem symbol to start transmission */
         shellmatta_ymodem_control(handle, YMODEM_CRC);
         ret = SHELLMATTA_OK;
+        break;
+    case SHELLMATTA_YMODEM_WAIT_FOR_END:
+        if(0u != inst->ymodem.pollCyclesLeft)
+        {
+            inst->ymodem.pollCyclesLeft --;
+        }
+        else
+        {
+            ret = SHELLMATTA_OK;
+            /** -# check if the received data matches the file size */
+            if((inst->ymodem.totalBytesReceived < inst->ymodem.fileSize) ||
+                ((inst->ymodem.totalBytesReceived - inst->ymodem.fileSize) >= YMODEM_PACKET_SIZE_1K))
+            {
+                ret = SHELLMATTA_ERROR;
+            }
+
+#ifdef SHELLMATTA_TRANSPORT
+            /** .-# reenable transport layer optional mode */
+            inst->transportLayer.suspendOptional = false;
+#endif
+
+            shellmatta_ymodem_reset(handle, false);
+            inst->ymodem.transmissionCompleteCallback(ret);
+            (void)utils_terminateInput(inst);
+        }
+        break;
+    default:
+        /* nothing to do */
+        break;
     }
 
     return ret;