Kaynağa Gözat

moved transport layer functions out of the shellmatta module

stefan 3 yıl önce
ebeveyn
işleme
0de0350940

+ 29 - 43
api/shellmatta.h

@@ -119,63 +119,47 @@ typedef struct shellmatta_cmd
  */
 typedef enum
 {
-    STATE_GET_SOH                =0u,   /**< start of header state of transport layer                       */
-    STATE_MANUAL_INPUT              ,   /**< state for manual input => transport layer disabled             */
-    STATE_GET_PROTOCOL_VERSION      ,   /**< protocol version state of transport layer                      */
-    STATE_GET_PACKET_TYPE           ,   /**< packet type state of transport layer                           */
-    STATE_GET_PAYLOAD_LENGTH        ,   /**< payload length state of transport layer                        */
-    STATE_GET_SOURCE                ,   /**< source state of transport layer                                */
-    STATE_GET_DESTINATION           ,   /**< destination state of transport layer                           */
-    STATE_GET_H2S_SEQUENCE_CNT      ,   /**< host to shellmatta sequence counter state of transport layer   */
-    STATE_GET_S2H_SEQUENCE_CNT      ,   /**< shellmatta to host sequence counter state of transport layer   */
-    STATE_GET_PAYLOAD               ,   /**< payload state of transport layer                               */
-    STATE_GET_CRC                   ,   /**< crc state of transport layer                                   */
-    STATE_PROCESS_PAYLOAD
+    SHELLMATTA_TRANSPORT_STATE_WAIT         =0u ,   /**< wait for start of header   */
+    SHELLMATTA_TRANSPORT_STATE_GET_HEADER       ,   /**< read in header             */
+    SHELLMATTA_TRANSPORT_STATE_GET_PAYLOAD      ,   /**< read in payload            */
+    SHELLMATTA_TRANSPORT_STATE_GET_CRC          ,   /**< read crc and process data  */
 } shellmatta_transport_state_t;
 
-/**
- * @brief definition of shellmatta transport layer packet types
- */
-typedef enum
-{
-    PACKET_DATA                     = 0x00u,    /**< packet type to send plain data                                  */
-    PACKET_SEQ_CNT_REQUEST          = 0x01u,    /**< packet type to request sequence counters                        */
-    PACKET_SEQ_CNT_RESPOND          = 0x81u,    /**< packet type to respond with sequence counters                   */
-    PACKET_MAX_BUFFERSIZE_REQUEST   = 0x02u,    /**< packet type to set and request max buffersize                   */
-    PACKET_MAX_BUFFERSIZE_RESPOND   = 0x82u,    /**< packet type to respond with max buffersize                      */
-    PACKET_SEARCH_DEVICE_REQUEST    = 0x03u,    /**< UNUSED: packet type to request search for a device by unique id */
-    PACKET_SEARCH_DEVICE_RESPOND    = 0x83u,    /**< UNUSED: packet type to respond with search results              */
-    PACKET_SET_ADDRESS_REQUEST      = 0x04u,    /**< UNUSED: packet type to set and request an address               */
-    PACKET_SET_ADDRESS_RESPOND      = 0x84u     /**< UNUSED: packet type to respond with a set address               */
-} shellmatta_transport_packet_t;
-
 /* payload length defines */
 /** @brief max length of a plain data payload */
-#define SHELLMATTA_PAYLOAD_MAXLENGTH        ((uint8_t)(255))
+#define SHELLMATTA_TRANPORT_PAYLOAD_MAXLENGTH           ((uint8_t)(255))
+
+typedef struct __attribute__((__packed__))
+{
+    uint8_t startOfHeader;
+    uint8_t protocolVersion;
+    uint8_t packetType;
+    uint8_t payloadLength;
+    uint8_t source;
+    uint8_t destination;
+    uint8_t sequenceH2S;
+    uint8_t sequenceS2H;
+    char payload[SHELLMATTA_TRANPORT_PAYLOAD_MAXLENGTH];
+    uint32_t checksum;
+} shellmatta_transport_packet_t;
 
 /**
  * @brief structure of one shellmatta transport layer instance
  */
 typedef struct
 {
-    uint8_t h2s_sequenceCnt;                            /**< TODO */
-    uint8_t s2h_sequenceCnt;                            /**<  */
     shellmatta_transport_state_t state;                 /**<  */
-    bool mandatory;                                     /**<  */
     bool active;                                        /**<  */
+    bool mandatory;                                     /**<  */
     bool continueStep;                                  /**<  */
+    uint8_t sequenceH2S;                                /**< TODO */
+    uint8_t sequenceS2H;                                /**<  */
     shellmatta_write_t originalWrite;                   /**<  */
-    uint8_t protocolVersion;                            /**<  */
-    shellmatta_transport_packet_t packetType;           /**<  */
-    uint32_t payloadLength;                             /**<  */
-    uint8_t source;                                     /**<  */
-    uint8_t destination;                                /**<  */
-    uint32_t crc32;                                     /**<  */
-    uint8_t payloadCounter;                             /**<  */
-    uint8_t crcCounter;                                 /**<  */
-    uint8_t packetSequenceCounter_h2s;                  /**<  */
-    uint8_t packetSequenceCounter_s2h;                  /**<  */
-    char payloadBuffer[SHELLMATTA_PAYLOAD_MAXLENGTH];   /**<  */
+    uint32_t headerIndex;                               /**<  */
+    uint32_t payloadIndex;                              /**<  */
+    uint32_t crcIndex;                                  /**<  */
+    shellmatta_transport_packet_t packetBuffer;         /**<  */
+    shellmatta_transport_packet_t outputPacketBuffer;   /**<  */
 } shellmatta_transport_layer_t;
 
 /**
@@ -217,6 +201,8 @@ typedef struct
     bool                            cmdListIsConst;     /**< true if the #cmdList was passed during
                                                              initialization                         */
     shellmatta_opt_t                optionParser;       /**< option parser sructure                 */
+    uint32_t                        transportBusyMark;  /**< transport processing position during 
+                                                             busy cmd execution                     */
     shellmatta_transport_layer_t    transportLayer;     /**< transport layer instance               */
 } shellmatta_instance_t;
 

+ 368 - 411
src/shellmatta.c

@@ -25,10 +25,357 @@
 #include "shellmatta_opt.h"
 #include "shellmatta_transport.h"
 #include <stddef.h>
+#include <stdint.h>
 #include <string.h>
 #include <stdarg.h>
 #include <stdio.h>
 
+/**
+ * @brief       processes the passed amount of data - called from the transport layer
+ * @param[in]   handle  shellmatta instance handle
+ * @param[in]   data    pointer to input data to process
+ * @param[in]   size    length of input data to process
+ * @return      errorcode   #SHELLMATTA_OK
+ *                          #SHELLMATTA_USE_FAULT
+ */
+static shellmatta_retCode_t shellmatta_processDataInt(shellmatta_handle_t     handle,
+                                                      char                    *data,
+                                                      uint32_t                 size)
+{
+    shellmatta_cmd_t        *cmd;
+    uint8_t                 cmdExecuted = 0u;
+    uint32_t                cmdLen;
+    char                    *tempString;
+
+    shellmatta_retCode_t    ret = SHELLMATTA_OK;
+    shellmatta_retCode_t    cmdRet;
+    shellmatta_instance_t   *inst = (shellmatta_instance_t*)handle;
+
+    /** -# in busy mode - keep calling this command */
+    if(NULL != inst->busyCmd)
+    {
+        /** -# just call the function until it is not busy anymore */
+        (void)shellmatta_opt_reInit(inst);
+        ret = inst->busyCmd->cmdFct(handle, inst->buffer, inst->inputCount);
+
+        if(SHELLMATTA_BUSY == ret)
+        {
+            /** -# do nothing - still busy */
+        }
+        else if(SHELLMATTA_CONTINUE == ret)
+        {
+            inst->continuousCmd = inst->busyCmd;
+            inst->busyCmd       = NULL;
+        }
+        else
+        {
+            utils_terminateInput(inst);
+        }
+    }
+    /** -# call continuous function even if there is no data */
+    else if((0u == size) && (NULL != inst->continuousCmd))
+    {
+        /** -# just call the function without any new data */
+        inst->stdinLength               = 0u;
+        inst->buffer[inst->stdinIdx]    = '\0';
+        (void)shellmatta_opt_reInit(inst);
+        ret = inst->continuousCmd->cmdFct(handle, inst->buffer, inst->inputCount);
+
+        if(SHELLMATTA_CONTINUE == ret)
+        {
+            /** -# do nothing just continue */
+        }
+        else if(SHELLMATTA_BUSY == ret)
+        {
+            inst->busyCmd       = inst->continuousCmd;
+            inst->continuousCmd = NULL;
+        }
+        else
+        {
+            utils_terminateInput(inst);
+        }
+    }
+    else
+    {
+        /* nothing to do here - continue parsing the command */
+    }
+
+    /** -# process byte wise */
+    for (; (inst->byteCounter < size) && (NULL == inst->busyCmd); inst->byteCounter++)
+    {
+        /** -# in continuous mode - pass data directly to the command */
+        if(NULL != inst->continuousCmd)
+        {
+            /** -# copy data and call command function */
+            inst->buffer[inst->stdinIdx]        = data[inst->byteCounter];
+            inst->buffer[inst->stdinIdx + 1u]   = '\0';
+            inst->stdinLength                   = 1u;
+            (void)shellmatta_opt_reInit(inst);
+            ret = inst->continuousCmd->cmdFct(handle, inst->buffer, inst->inputCount);
+            
+            /** -# check if continuous mode is canceled or interrupted by busy mode */
+            if(SHELLMATTA_BUSY == ret)
+            {
+                inst->busyCmd 	= inst->continuousCmd;
+                inst->continuousCmd = NULL;
+            }
+            else if(('\x03' == data[inst->byteCounter]))
+            {
+                /** -# cancel continue session */
+                utils_terminateInput(inst);
+                ret = SHELLMATTA_OK;
+            }
+            else if(SHELLMATTA_CONTINUE == ret)
+            {
+                /** -# do nothing - continue */
+            }
+            else
+            {
+                utils_terminateInput(inst);
+            }
+        }
+        /** -# handle escape sequences */
+        else if(inst->escapeCounter != 0u)
+        {
+            escape_handleSequence(inst, data[inst->byteCounter]);
+        }
+        /** -# handle delimiter as start of processing the command */
+        else if (inst->delimiter == data[inst->byteCounter])
+        {
+            if(0u == inst->hereLength)
+            {
+                /**
+                    *  @dot
+                    *  digraph heredocParser {
+                    *      start -> wait [ label="<< in first line - store delimiter" ];
+                    *      wait -> wait [ label="delimiter not detected" ];
+                    *      wait -> end [ label="delimiter found - remove all heredoc stuff and send the input to the command" ];
+                    *  }
+                    *  @enddot */
+
+                /** -# check for heredoc - add string delimiter to stop strstr from searching too far */
+                inst->buffer[inst->inputCount] = '\0';
+                tempString = strstr(inst->buffer, "<<");
+                if(NULL != tempString)
+                {
+                    /*' -# check if length of heredoc delimiter is valid */
+                    if(inst->inputCount > ((uint32_t)(tempString - inst->buffer) + 2u))
+                    {
+                        inst->hereStartIdx      = (uint32_t)(tempString - inst->buffer);
+                        inst->hereDelimiterIdx  = inst->hereStartIdx + 2u;
+                        while((inst->hereDelimiterIdx < inst->inputCount)
+                                && (    ('\0' == inst->buffer[inst->hereDelimiterIdx])
+                                    ||  (' '  == inst->buffer[inst->hereDelimiterIdx])))
+                        {
+                            inst->hereDelimiterIdx ++;
+                        }
+
+                        inst->hereLength = inst->inputCount - inst->hereDelimiterIdx;
+
+                        inst->dirty = true;
+                        utils_insertChars(inst, &data[inst->byteCounter], 1u);
+                        inst->lastNewlineIdx = inst->inputCount;
+                    }
+                    else
+                    {
+                        inst->hereLength    = 0u;
+
+                        /** -# store the current command and reset the history buffer */
+                        inst->dirty = true;
+                        history_storeCmd(inst);
+                        history_reset(inst);
+                    }
+                }
+                else
+                {
+                    /** -# store the current command and reset the history buffer */
+                    inst->dirty = true;
+                    history_storeCmd(inst);
+                    history_reset(inst);
+                }
+            }
+            else
+            {
+                tempString  = &inst->buffer[inst->lastNewlineIdx];
+                cmdLen      = inst->inputCount - inst->lastNewlineIdx;
+
+                /** -# skip newline characters before comparison */
+                while(('\n' == *tempString) || ('\r' == *tempString))
+                {
+                    tempString ++;
+                    cmdLen --;
+                }
+
+                if(     (inst->hereLength == cmdLen)
+                    &&  (0  == strncmp( &inst->buffer[inst->hereDelimiterIdx],
+                                        tempString,
+                                        inst->hereLength)))
+                {
+                    /** -# store the current command and reset the history buffer */
+                    inst->dirty = true;
+                    history_storeCmd(inst);
+                    history_reset(inst);
+
+                    /** -# process heredoc as stdin like input  */
+                    /** -# find start of heredoc data           */
+                    inst->stdinIdx = inst->hereDelimiterIdx + inst->hereLength;
+                    while(      ('\n' == inst->buffer[inst->stdinIdx])
+                            ||  ('\r' == inst->buffer[inst->stdinIdx]))
+                    {
+                        inst->stdinIdx ++;
+                    }
+                    /** -# calculate length and terminate stdin string */
+                    if(inst->stdinIdx < inst->lastNewlineIdx)
+                    {
+                        inst->stdinLength = inst->lastNewlineIdx - inst->stdinIdx;
+                        inst->buffer[inst->lastNewlineIdx] = '\0';
+                    }
+                    else
+                    {
+                        inst->stdinLength = 0u;
+                    }
+
+                    /** -# calculate length and terminate argument string */
+                    inst->inputCount = inst->hereStartIdx;
+                    inst->buffer[inst->hereStartIdx] = '\0';
+
+                    /** -# terminate heredoc session */
+                    inst->hereLength = 0u;
+                }
+                else
+                {
+                    /** -# the party goes on - just print the delimiter and store the position */
+                    inst->lastNewlineIdx = inst->inputCount;
+                    utils_insertChars(inst, &data[inst->byteCounter], 1u);
+                }
+            }
+
+            if(0u == inst->hereLength)
+            {
+                cmd = inst->cmdList;
+
+                /** -# determine the cmd len (chars until first space or \0 is found */
+                cmdLen = 0u;
+                while(      (cmdLen <   inst->inputCount)
+                        &&  (' '    !=  inst->buffer[cmdLen])
+                        &&  ('\r'   !=  inst->buffer[cmdLen])
+                        &&  ('\n'   !=  inst->buffer[cmdLen])
+                        &&  ('\0'   !=  inst->buffer[cmdLen]))
+                {
+                    cmdLen ++;
+                }
+
+                /** -# search for a matching command */
+                while (NULL != cmd)
+                {
+                    /** -# compare command and alias string and length */
+                    if (    ((cmdLen    == strlen(cmd->cmd))
+                            && (0       == strncmp(inst->buffer, cmd->cmd, cmdLen)))
+                        || ((NULL != cmd->cmdAlias)
+                            && (cmdLen  == strlen(cmd->cmdAlias))
+                            && (0       == strncmp(inst->buffer, cmd->cmdAlias, cmdLen))))
+                    {
+                        utils_writeEcho(inst, "\r\n", 2u);
+                        shellmatta_opt_init(inst, cmdLen + 1u);
+                        cmdExecuted = 1u;
+                        cmdRet = cmd->cmdFct(handle, inst->buffer, inst->inputCount);
+
+                        switch(cmdRet)
+                        {
+                            case SHELLMATTA_CONTINUE:
+                                /** -# initialize stdin buffer and continuous cmd */
+                                inst->stdinIdx      = inst->inputCount + 1u;
+                                inst->stdinLength   = 0u;
+                                inst->continuousCmd = cmd;
+                                ret                 = cmdRet;
+                                break;
+                            
+                            case SHELLMATTA_BUSY:
+                                inst->busyCmd   = cmd;
+                                ret             = cmdRet;
+                                break;
+
+                            default:
+                                /* nothing to do - everything ok */
+                                break;
+                        }
+                        cmd = NULL;
+                    }
+                    else
+                    {
+                        cmd = cmd->next;
+                    }
+                }
+
+                if ((0u == cmdExecuted) && (inst->inputCount > 0))
+                {
+                    SHELLMATTA_WRITE("\r\nCommand: ", 11u);
+                    SHELLMATTA_WRITE(inst->buffer, inst->inputCount);
+                    SHELLMATTA_WRITE(" not found", 10u);
+                }
+
+                /** -# terminate this session if no continuous mode is requested */
+                if(     (NULL == inst->continuousCmd)
+                    &&  (NULL == inst->busyCmd))
+                {
+                    utils_terminateInput(inst);
+                }
+            }
+        }
+        /** -# ignore newline as first character (to be compatible to
+            * terminals sending newline after return) */
+        else if((0u == inst->inputCount) && ('\n' == data[inst->byteCounter]))
+        {
+            /* do nothing */
+        }
+        /** -# check for tabulator key - auto complete */
+        else if('\t' == data[inst->byteCounter])
+        {
+            inst->dirty = true;
+            autocomplete_run(inst);
+        }
+        /** -# check for cancel -
+            *      terminate current input and print prompt again */
+        else if('\x03' == data[inst->byteCounter])
+        {
+            inst->dirty = false;
+            history_reset(inst);
+            utils_terminateInput(inst);
+        }
+        /** -# check for backspace */
+        else if(    ('\b'   == data[inst->byteCounter])
+                ||  ('\x7f' == data[inst->byteCounter]))
+        {
+            inst->dirty = true;
+            utils_removeChars(inst, 1u, true);
+        }
+        /** -# check for start of escape sequence */
+        else if('\x1b' == data[inst->byteCounter])
+        {
+            inst->escapeCounter = 1u;
+        }
+        else
+        {
+            inst->dirty = true;
+            utils_insertChars(inst, &data[inst->byteCounter], 1u);
+        }
+
+        /** -# reset tab counter on not a tab */
+        if ('\t' != data[inst->byteCounter])
+        {
+            inst->tabCounter = 0u;
+        }
+    }
+
+    /** -# initialize the byte buffer if processing of the input is finished */
+    if(ret != SHELLMATTA_BUSY)
+    {
+        inst->byteCounter = 0u;
+    }
+
+    return ret;
+}
+
 /**
  * @}
  * @addtogroup shellmatta_api
@@ -117,6 +464,7 @@ shellmatta_retCode_t shellmatta_doInit(
         *handle     = (shellmatta_handle_t)inst;
 
         /* init transport layer */
+        inst->transportBusyMark = 0u;
         shellmatta_transport_init(&inst->transportLayer, inst->write);
 
         /** -# print the first prompt */
@@ -373,435 +721,50 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
                                             char                    *data,
                                             uint32_t                 size)
 {
-    shellmatta_cmd_t        *cmd;
-    uint8_t                 cmdExecuted = 0u;
-    uint32_t                cmdLen;
-    char                    *tempString;
-
-    shellmatta_retCode_t    ret = SHELLMATTA_OK;
-    shellmatta_retCode_t    cmdRet;
+    shellmatta_retCode_t    ret   = SHELLMATTA_OK;
     shellmatta_instance_t   *inst = (shellmatta_instance_t*)handle;
+    char                    *tmpData;
+    uint32_t                tmpSize = 0;
+    uint32_t                i;
+    bool                    processingDone = false;
 
     /** -# check parameters for plausibility  */
     if(     (NULL               != inst)
         &&  (SHELLMATTA_MAGIC   == inst->magic))
     {
-        if (    (inst->transportLayer.state != STATE_PROCESS_PAYLOAD)
-            &&  (inst->transportLayer.state != STATE_MANUAL_INPUT))
-        {
-            // TODO: Move this into shellmatta_transport.c
-            /* use headerCounter to watch how many header fields have been worked on */
-            uint8_t headerCounter = 0u;
-            while ( (size > headerCounter) 
-                ||  (   (true == inst->transportLayer.mandatory)
-                    &&  (size > headerCounter))
-                ||  (true == inst->transportLayer.continueStep))
-            {
-                switch (inst->transportLayer.state)
-                {
-                case STATE_GET_SOH:
-                    /* wait for SOH or go to payload */
-                    break;
-
-                case STATE_GET_PROTOCOL_VERSION:
-                    inst->transportLayer.protocolVersion = data[headerCounter];
-                    break;
-
-                case STATE_GET_PACKET_TYPE:
-                    inst->transportLayer.packetType = (shellmatta_transport_packet_t)data[headerCounter];
-                    break;
-
-                case STATE_GET_PAYLOAD_LENGTH:
-                    inst->transportLayer.payloadLength = (uint8_t)data[headerCounter];
-                    break;
-
-                case STATE_GET_SOURCE:
-                    inst->transportLayer.source = data[headerCounter];
-                    break;
-
-                case STATE_GET_DESTINATION:
-                    inst->transportLayer.destination = data[headerCounter];
-                    break;
-                
-                case STATE_GET_H2S_SEQUENCE_CNT:
-                    inst->transportLayer.packetSequenceCounter_h2s = data[headerCounter];
-                    break;
-                
-                case STATE_GET_S2H_SEQUENCE_CNT:
-                    inst->transportLayer.packetSequenceCounter_s2h = data[headerCounter];
-                    break;
-
-                case STATE_GET_PAYLOAD:
-                    if (0u == inst->transportLayer.payloadLength)
-                    {
-                        inst->transportLayer.continueStep = true;
-                    }
-                    inst->transportLayer.payloadBuffer[inst->transportLayer.payloadCounter++] = data[headerCounter];
-                    break;
-
-                case STATE_GET_CRC:
-                    inst->transportLayer.continueStep = false;
-                    inst->transportLayer.crc32 |= (uint8_t)data[headerCounter] << (SHELLMATTA_LENGTH_CRC - 1u - inst->transportLayer.crcCounter++) * 8u;
-                    break;
-                
-                default:
-                    break;
-                }
-                /* handling of transport layer fsm */
-                ret = shellmatta_transport_process(&inst->transportLayer, data, 0);
-                
-                /* crc error handling */
-                if (SHELLMATTA_ERROR == ret)
-                {
-                    shellmatta_transport_reset(&inst->transportLayer);
-                    utils_writeEcho(inst, "crc error\r\n", 11);
-                    utils_terminateInput(inst);
-                    return SHELLMATTA_OK;
-                }
-
-                headerCounter++;
-
-                /* processes payload by forwarding it recursively without transport layer to processData() */
-                if (inst->transportLayer.state == STATE_PROCESS_PAYLOAD)
-                {
-                    /* recursive call with complete payload */
-                    shellmatta_processData(handle,
-                                           inst->transportLayer.payloadBuffer,
-                                           inst->transportLayer.payloadLength);
-
-                    shellmatta_transport_process(&inst->transportLayer, data, 0);
-                    return SHELLMATTA_OK;
-                }
-            }
-        }
-
-        if (    (inst->transportLayer.active)
-            &&  (inst->transportLayer.state != STATE_PROCESS_PAYLOAD)
-            &&  (inst->transportLayer.state != STATE_MANUAL_INPUT))
-        {
-            return SHELLMATTA_OK;
-        }
-
-        /** -# in busy mode - keep calling this command */
-        if(NULL != inst->busyCmd)
+        for (i = inst->transportBusyMark; i < size; i ++)
         {
-            /** -# just call the function until it is not busy anymore */
-            (void)shellmatta_opt_reInit(inst);
-            ret = inst->busyCmd->cmdFct(handle, inst->buffer, inst->inputCount);
-
-            if(SHELLMATTA_BUSY == ret)
+            ret = shellmatta_transport_process(&inst->transportLayer, data[i], &tmpData, &tmpSize);
+            if (SHELLMATTA_OK == ret)
             {
-                /** -# do nothing - still busy */
-            }
-            else if(SHELLMATTA_CONTINUE == ret)
-            {
-                inst->continuousCmd = inst->busyCmd;
-                inst->busyCmd       = NULL;
-            }
-            else
-            {
-                utils_terminateInput(inst);
-            }
-        }
-        /** -# call continuous function even if there is no data */
-        else if((0u == size) && (NULL != inst->continuousCmd))
-        {
-            /** -# just call the function without any new data */
-            inst->stdinLength               = 0u;
-            inst->buffer[inst->stdinIdx]    = '\0';
-            (void)shellmatta_opt_reInit(inst);
-            ret = inst->continuousCmd->cmdFct(handle, inst->buffer, inst->inputCount);
+                ret = shellmatta_processDataInt(handle, tmpData, tmpSize);
+                processingDone = true;
 
-            if(SHELLMATTA_CONTINUE == ret)
-            {
-                /** -# do nothing just continue */
-            }
-            else if(SHELLMATTA_BUSY == ret)
-            {
-                inst->busyCmd       = inst->continuousCmd;
-                inst->continuousCmd = NULL;
-            }
-            else
-            {
-                utils_terminateInput(inst);
-            }
-        }
-        else
-        {
-            /* nothing to do here - continue parsing the command */
-        }
-
-        /** -# process byte wise */
-        for (; (inst->byteCounter < size) && (NULL == inst->busyCmd); inst->byteCounter++)
-        {
-            /** -# in continuous mode - pass data directly to the command */
-            if(NULL != inst->continuousCmd)
-            {
-                /** -# copy data and call command function */
-                inst->buffer[inst->stdinIdx]        = data[inst->byteCounter];
-                inst->buffer[inst->stdinIdx + 1u]   = '\0';
-                inst->stdinLength                   = 1u;
-                (void)shellmatta_opt_reInit(inst);
-                ret = inst->continuousCmd->cmdFct(handle, inst->buffer, inst->inputCount);
-                
-                /** -# check if continuous mode is canceled or interrupted by busy mode */
-                if(SHELLMATTA_BUSY == ret)
-                {
-                    inst->busyCmd 	= inst->continuousCmd;
-                    inst->continuousCmd = NULL;
-                }
-                else if(('\x03' == data[inst->byteCounter]))
-                {
-                    /** -# cancel continue session */
-                    utils_terminateInput(inst);
-                    ret = SHELLMATTA_OK;
-                }
-                else if(SHELLMATTA_CONTINUE == ret)
+                if (SHELLMATTA_BUSY == ret)
                 {
-                    /** -# do nothing - continue */
+                    inst->transportBusyMark = i;
+                    break;
                 }
                 else
                 {
-                    utils_terminateInput(inst);
+                    inst->transportBusyMark = 0u;
                 }
             }
-            /** -# handle escape sequences */
-            else if(inst->escapeCounter != 0u)
-            {
-                escape_handleSequence(inst, data[inst->byteCounter]);
-            }
-            /** -# handle delimiter as start of processing the command */
-            else if (inst->delimiter == data[inst->byteCounter])
+            else if (SHELLMATTA_ERROR == ret)
             {
-                if(0u == inst->hereLength)
-                {
-                    /**
-                      *  @dot
-                      *  digraph heredocParser {
-                      *      start -> wait [ label="<< in first line - store delimiter" ];
-                      *      wait -> wait [ label="delimiter not detected" ];
-                      *      wait -> end [ label="delimiter found - remove all heredoc stuff and send the input to the command" ];
-                      *  }
-                      *  @enddot */
-
-                    /** -# check for heredoc - add string delimiter to stop strstr from searching too far */
-                    inst->buffer[inst->inputCount] = '\0';
-                    tempString = strstr(inst->buffer, "<<");
-                    if(NULL != tempString)
-                    {
-                        /*' -# check if length of heredoc delimiter is valid */
-                        if(inst->inputCount > ((uint32_t)(tempString - inst->buffer) + 2u))
-                        {
-                            inst->hereStartIdx      = (uint32_t)(tempString - inst->buffer);
-                            inst->hereDelimiterIdx  = inst->hereStartIdx + 2u;
-                            while((inst->hereDelimiterIdx < inst->inputCount)
-                                    && (    ('\0' == inst->buffer[inst->hereDelimiterIdx])
-                                        ||  (' '  == inst->buffer[inst->hereDelimiterIdx])))
-                            {
-                                inst->hereDelimiterIdx ++;
-                            }
-
-                            inst->hereLength = inst->inputCount - inst->hereDelimiterIdx;
-
-                            inst->dirty = true;
-                            utils_insertChars(inst, &data[inst->byteCounter], 1u);
-                            inst->lastNewlineIdx = inst->inputCount;
-                        }
-                        else
-                        {
-                            inst->hereLength    = 0u;
-
-                            /** -# store the current command and reset the history buffer */
-                            inst->dirty = true;
-                            history_storeCmd(inst);
-                            history_reset(inst);
-                        }
-                    }
-                    else
-                    {
-                        /** -# store the current command and reset the history buffer */
-                        inst->dirty = true;
-                        history_storeCmd(inst);
-                        history_reset(inst);
-                    }
-                }
-                else
-                {
-                    tempString  = &inst->buffer[inst->lastNewlineIdx];
-                    cmdLen      = inst->inputCount - inst->lastNewlineIdx;
-
-                    /** -# skip newline characters before comparison */
-                    while(('\n' == *tempString) || ('\r' == *tempString))
-                    {
-                        tempString ++;
-                        cmdLen --;
-                    }
-
-                    if(     (inst->hereLength == cmdLen)
-                        &&  (0  == strncmp( &inst->buffer[inst->hereDelimiterIdx],
-                                            tempString,
-                                            inst->hereLength)))
-                    {
-                        /** -# store the current command and reset the history buffer */
-                        inst->dirty = true;
-                        history_storeCmd(inst);
-                        history_reset(inst);
-
-                        /** -# process heredoc as stdin like input  */
-                        /** -# find start of heredoc data           */
-                        inst->stdinIdx = inst->hereDelimiterIdx + inst->hereLength;
-                        while(      ('\n' == inst->buffer[inst->stdinIdx])
-                                ||  ('\r' == inst->buffer[inst->stdinIdx]))
-                        {
-                            inst->stdinIdx ++;
-                        }
-                        /** -# calculate length and terminate stdin string */
-                        if(inst->stdinIdx < inst->lastNewlineIdx)
-                        {
-                            inst->stdinLength = inst->lastNewlineIdx - inst->stdinIdx;
-                            inst->buffer[inst->lastNewlineIdx] = '\0';
-                        }
-                        else
-                        {
-                            inst->stdinLength = 0u;
-                        }
-
-                        /** -# calculate length and terminate argument string */
-                        inst->inputCount = inst->hereStartIdx;
-                        inst->buffer[inst->hereStartIdx] = '\0';
-
-                        /** -# terminate heredoc session */
-                        inst->hereLength = 0u;
-                    }
-                    else
-                    {
-                        /** -# the party goes on - just print the delimiter and store the position */
-                        inst->lastNewlineIdx = inst->inputCount;
-                        utils_insertChars(inst, &data[inst->byteCounter], 1u);
-                    }
-                }
-
-                if(0u == inst->hereLength)
-                {
-                    cmd = inst->cmdList;
-
-                    /** -# determine the cmd len (chars until first space or \0 is found */
-                    cmdLen = 0u;
-                    while(      (cmdLen <   inst->inputCount)
-                            &&  (' '    !=  inst->buffer[cmdLen])
-                            &&  ('\r'   !=  inst->buffer[cmdLen])
-                            &&  ('\n'   !=  inst->buffer[cmdLen])
-                            &&  ('\0'   !=  inst->buffer[cmdLen]))
-                    {
-                        cmdLen ++;
-                    }
-
-                    /** -# search for a matching command */
-                    while (NULL != cmd)
-                    {
-                        /** -# compare command and alias string and length */
-                        if (    ((cmdLen    == strlen(cmd->cmd))
-                                && (0       == strncmp(inst->buffer, cmd->cmd, cmdLen)))
-                            || ((NULL != cmd->cmdAlias)
-                                && (cmdLen  == strlen(cmd->cmdAlias))
-                                && (0       == strncmp(inst->buffer, cmd->cmdAlias, cmdLen))))
-                        {
-                            utils_writeEcho(inst, "\r\n", 2u);
-                            shellmatta_opt_init(inst, cmdLen + 1u);
-                            cmdExecuted = 1u;
-                            cmdRet = cmd->cmdFct(handle, inst->buffer, inst->inputCount);
-
-                            switch(cmdRet)
-                            {
-                                case SHELLMATTA_CONTINUE:
-                                    /** -# initialize stdin buffer and continuous cmd */
-                                    inst->stdinIdx      = inst->inputCount + 1u;
-                                    inst->stdinLength   = 0u;
-                                    inst->continuousCmd = cmd;
-                                    ret                 = cmdRet;
-                                    break;
-                                
-                                case SHELLMATTA_BUSY:
-                                    inst->busyCmd   = cmd;
-                                    ret             = cmdRet;
-                                    break;
-
-                                default:
-                                    /* nothing to do - everything ok */
-                                    break;
-                            }
-                            cmd = NULL;
-                        }
-                        else
-                        {
-                            cmd = cmd->next;
-                        }
-                    }
-
-                    if ((0u == cmdExecuted) && (inst->inputCount > 0))
-                    {
-                        SHELLMATTA_WRITE("\r\nCommand: ", 11u);
-                        SHELLMATTA_WRITE(inst->buffer, inst->inputCount);
-                        SHELLMATTA_WRITE(" not found", 10u);
-                    }
-
-                    /** -# terminate this session if no continuous mode is requested */
-                    if(     (NULL == inst->continuousCmd)
-                        &&  (NULL == inst->busyCmd))
-                    {
-                        utils_terminateInput(inst);
-                    }
-                }
-            }
-            /** -# ignore newline as first character (to be compatible to
-             * terminals sending newline after return) */
-            else if((0u == inst->inputCount) && ('\n' == data[inst->byteCounter]))
-            {
-                /* do nothing */
-            }
-            /** -# check for tabulator key - auto complete */
-            else if('\t' == data[inst->byteCounter])
-            {
-                inst->dirty = true;
-                autocomplete_run(inst);
-            }
-            /** -# check for cancel -
-             *      terminate current input and print prompt again */
-            else if('\x03' == data[inst->byteCounter])
-            {
-                inst->dirty = false;
-                history_reset(inst);
+                utils_writeEcho(inst, "crc error\r\n", 11);
                 utils_terminateInput(inst);
             }
-            /** -# check for backspace */
-            else if(    ('\b'   == data[inst->byteCounter])
-                    ||  ('\x7f' == data[inst->byteCounter]))
-            {
-                inst->dirty = true;
-                utils_removeChars(inst, 1u, true);
-            }
-            /** -# check for start of escape sequence */
-            else if('\x1b' == data[inst->byteCounter])
-            {
-                inst->escapeCounter = 1u;
-            }
             else
             {
-                inst->dirty = true;
-                utils_insertChars(inst, &data[inst->byteCounter], 1u);
-            }
-
-            /** -# reset tab counter on not a tab */
-            if ('\t' != data[inst->byteCounter])
-            {
-                inst->tabCounter = 0u;
+                /* nothing to do - transport layer busy */
             }
         }
 
-        /** -# initialize the byte buffer if processing of the input is finished */
-        if(ret != SHELLMATTA_BUSY)
+        /*! -# call the internal processing at least once - for continued and busy commands */
+        if (true != processingDone)
         {
-            inst->byteCounter = 0u;
+            ret = shellmatta_processDataInt(handle, tmpData, 0);
         }
     }
     else
@@ -809,12 +772,6 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
         ret = SHELLMATTA_USE_FAULT;
     }
 
-    /* if manual input happened, reset transport layer fsm back to initial state */
-    if (inst->transportLayer.state == STATE_MANUAL_INPUT)
-    {
-        inst->transportLayer.state = STATE_GET_SOH;
-    }
-
     return ret;
 }
 

+ 126 - 163
src/shellmatta_transport.c

@@ -10,6 +10,44 @@
 #include <string.h>
 
 
+
+/**
+ * @brief   create a secured packet and pass it to the shellmatta write function
+ *
+ * @note    The packetType, payloadLength and payload have to be preset!
+ *
+ * @param[in, out]  transportLayer  transport layer instance to work on
+ * @param[in]       packetType      type of packet to send
+ * @param[in]       packet          packet to send
+ * @return          errorcode
+ */
+static shellmatta_retCode_t shellmatta_transport_send(shellmatta_transport_layer_t *transportLayer,
+                                                      shellmatta_transport_packet_t *packet)
+{
+    uint32_t checksum;
+    char *rawPacketBuffer = (char*)packet;
+
+    /** -# fill header */
+    packet->startOfHeader   = SHELLMATTA_START_OF_HEADER;
+    packet->protocolVersion = PROTOCOL_VERSION;
+    packet->source          = 0;
+    packet->destination     = 0;
+    packet->sequenceH2S     = transportLayer->sequenceH2S;
+    packet->sequenceS2H     = ++transportLayer->sequenceS2H;
+
+    checksum = crc32Calc((char*) packet, SHELLMATTA_HEADER_LENGTH + packet->payloadLength);
+
+    /* append crc to end of payload */
+    rawPacketBuffer[SHELLMATTA_HEADER_LENGTH + packet->payloadLength] = (uint8_t)(checksum >> SHELLMATTA_SHIFT_BY_24);
+    rawPacketBuffer[SHELLMATTA_HEADER_LENGTH + packet->payloadLength + SHELLMATTA_SHIFT_BY_1] = (uint8_t)(checksum >> SHELLMATTA_SHIFT_BY_16);
+    rawPacketBuffer[SHELLMATTA_HEADER_LENGTH + packet->payloadLength + SHELLMATTA_SHIFT_BY_2] = (uint8_t)(checksum >> SHELLMATTA_SHIFT_BY_8);
+    rawPacketBuffer[SHELLMATTA_HEADER_LENGTH + packet->payloadLength + SHELLMATTA_SHIFT_BY_3] = (uint8_t)(checksum);
+
+    /* use original write function to send full buffer */
+    return transportLayer->originalWrite((char*) rawPacketBuffer, SHELLMATTA_HEADER_LENGTH + packet->payloadLength + SHELLMATTA_LENGTH_CRC);
+}
+
+
 /**
  * @brief           Initializes the transportLayerInst
  * @param[in, out]  transportLayer  transport layer instance to work on
@@ -32,12 +70,12 @@ shellmatta_retCode_t shellmatta_transport_init( shellmatta_transport_layer_t
  */
 shellmatta_retCode_t shellmatta_transport_reset(shellmatta_transport_layer_t *transportLayer)
 {
-    uint8_t h2s_sequenceCnt = transportLayer->h2s_sequenceCnt;
-    uint8_t s2h_sequenceCnt = transportLayer->s2h_sequenceCnt;
+    uint8_t sequenceH2S = transportLayer->sequenceH2S;
+    uint8_t sequenceS2H = transportLayer->sequenceS2H;
     memset(transportLayer, 0u, sizeof(shellmatta_transport_layer_t));
 
-    transportLayer->h2s_sequenceCnt = h2s_sequenceCnt;
-    transportLayer->s2h_sequenceCnt = s2h_sequenceCnt;
+    transportLayer->sequenceH2S = sequenceH2S;
+    transportLayer->sequenceS2H = sequenceS2H;
 
     return SHELLMATTA_OK;
 }
@@ -45,201 +83,153 @@ shellmatta_retCode_t shellmatta_transport_reset(shellmatta_transport_layer_t *tr
 /**
  * @brief           processes the passed amount of data
  * @param[in, out]  transportLayer  transport layer instance to work on
- * @param[in]       data            pointer to input data to process
- * @return          errorcode       #SHELLMATTA_OK\n
+ * @param[in]       byte            byte to process
+ * @param[out]      data            payload of processed packet - or manual mode
+ * @param[out]      length          length of processed packet
+ * @return          errorcode       #SHELLMATTA_OK      data is returned\n
+ *                                  #SHELLMATTA_BUSY    packet reception ongoing\n
  *                                  #SHELLMATTA_ERROR   in case of crc error
  */
 shellmatta_retCode_t shellmatta_transport_process(shellmatta_transport_layer_t   *transportLayer,
-                                                  char                           *data,
+                                                  char                           byte,
+                                                  char                           **data,
                                                   uint32_t                       *length)
 {
-    shellmatta_retCode_t ret = SHELLMATTA_OK;
-
-
-    //TODO
-    (void)length;
+    shellmatta_retCode_t ret = SHELLMATTA_BUSY;
+    char *rawPacketBuffer = (char*)&transportLayer->packetBuffer;
+    shellmatta_transport_packet_int_t intPacket;
+    uint32_t refCrc;
 
     switch (transportLayer->state)
     {
-        /* look for start of header */
-    case STATE_GET_SOH:
+    /* look for start of header */
+    case SHELLMATTA_TRANSPORT_STATE_WAIT:
         /* if start of header is found, continue transport layer fsm */
-        if (SHELLMATTA_START_OF_HEADER == *data)
+        if (SHELLMATTA_START_OF_HEADER == byte)
         {
-            transportLayer->state = STATE_GET_PROTOCOL_VERSION;
-            transportLayer->active = true;
-        }
-        else if (0x00 != *data)
-        {
-            /* if SOH is not found, handle data as manual input */
-            transportLayer->state = STATE_MANUAL_INPUT;
-            transportLayer->active = false;
-        }
-        break;
-
-    case STATE_MANUAL_INPUT:
-        break;
-
-    /* look for protocol version */
-    case STATE_GET_PROTOCOL_VERSION:
-        /* check protocol version */
-        if (PROTOCOL_VERSION == *data)
-        {
-            transportLayer->state = STATE_GET_PACKET_TYPE;
+            memset(&transportLayer->packetBuffer, 0, sizeof(transportLayer->packetBuffer));
+            transportLayer->headerIndex = 1u;
+            transportLayer->payloadIndex = 0u;
+            transportLayer->crcIndex = 0u;
+            transportLayer->packetBuffer.startOfHeader = byte;
+            transportLayer->state = SHELLMATTA_TRANSPORT_STATE_GET_HEADER;
         }
         else
         {
-            /* reset fsm in case of wrong protocol version */
-            transportLayer->state = STATE_GET_SOH;
+            /* just pass the payload as is */
+            transportLayer->packetBuffer.payload[0] = byte;
+            *data = transportLayer->packetBuffer.payload;
+            *length = 1;
             transportLayer->active = false;
+            ret = SHELLMATTA_OK;
         }
         break;
 
-    /* read packet type */
-    case STATE_GET_PACKET_TYPE:
-        transportLayer->state = STATE_GET_PAYLOAD_LENGTH;
-        break;
-
-    /* look for length of payload */
-    case STATE_GET_PAYLOAD_LENGTH:
-        transportLayer->state = STATE_GET_SOURCE;
-        break;
-
-    /* look for source */
-    case STATE_GET_SOURCE:
-        transportLayer->state = STATE_GET_DESTINATION;
-        break;
-
-    /* look for destination */
-    case STATE_GET_DESTINATION:
-        transportLayer->state = STATE_GET_H2S_SEQUENCE_CNT;
-        break;
+    case SHELLMATTA_TRANSPORT_STATE_GET_HEADER:
 
-    /* look for h2s sequence counter*/
-    case STATE_GET_H2S_SEQUENCE_CNT:
-        transportLayer->state = STATE_GET_S2H_SEQUENCE_CNT;
-        break;
+        rawPacketBuffer[transportLayer->headerIndex] = byte;
+        transportLayer->headerIndex ++;
 
-    /* look for s2h sequence counter */
-    case STATE_GET_S2H_SEQUENCE_CNT:
-        if (transportLayer->packetType == PACKET_SEQ_CNT_REQUEST)
-        {
-            transportLayer->state = STATE_GET_CRC;
-        }
-        else
+        if (transportLayer->headerIndex == SHELLMATTA_HEADER_LENGTH)
         {
-            transportLayer->state = STATE_GET_PAYLOAD;
+            //TODO check for errors in header data
+            if (0u != transportLayer->packetBuffer.payloadLength)
+            {
+                transportLayer->state = SHELLMATTA_TRANSPORT_STATE_GET_PAYLOAD;
+            }
+            else
+            {
+                transportLayer->state = SHELLMATTA_TRANSPORT_STATE_GET_CRC;
+            }
         }
+
         break;
 
     /* read payload for previously read length of payload */
-    case STATE_GET_PAYLOAD:
-        if (    (transportLayer->payloadLength <= transportLayer->payloadCounter)
-            &&  (true == transportLayer->active))
+    case SHELLMATTA_TRANSPORT_STATE_GET_PAYLOAD:
+
+        transportLayer->packetBuffer.payload[transportLayer->payloadIndex] = byte;
+        transportLayer->payloadIndex ++;
+
+        if (transportLayer->payloadIndex >= transportLayer->packetBuffer.payloadLength)
         {
-            transportLayer->state = STATE_GET_CRC;
+            transportLayer->state = SHELLMATTA_TRANSPORT_STATE_GET_CRC;
         }
         break;
 
     /* read crc32 for four bytes */
-    case STATE_GET_CRC:
-        /* if crc32 is read, start computing */
-        if (SHELLMATTA_LENGTH_CRC <= transportLayer->crcCounter)
+    case SHELLMATTA_TRANSPORT_STATE_GET_CRC:
+
+        transportLayer->crcIndex ++;
+        transportLayer->packetBuffer.checksum |= ((uint8_t)byte << ((SHELLMATTA_LENGTH_CRC - transportLayer->crcIndex) * 8u));
+
+        if (transportLayer->crcIndex >= SHELLMATTA_LENGTH_CRC)
         {
-            /* for crc computation only */
-            char crcdata[SHELLMATTA_PAYLOAD_MAXLENGTH + SHELLMATTA_HEADER_LENGTH];
-            memset(crcdata, 0u, SHELLMATTA_PAYLOAD_MAXLENGTH + SHELLMATTA_HEADER_LENGTH);
-            crcdata[SHELLMATTA_POS_SOH]         = SHELLMATTA_START_OF_HEADER;
-            crcdata[SHELLMATTA_POS_PROT_VER]    = transportLayer->protocolVersion;
-            crcdata[SHELLMATTA_POS_PACKET_TYPE] = transportLayer->packetType;
-            crcdata[SHELLMATTA_POS_PAYLOAD_LEN] = transportLayer->payloadLength;
-            crcdata[SHELLMATTA_POS_SRC]         = transportLayer->source;
-            crcdata[SHELLMATTA_POS_DST]         = transportLayer->destination;
-            crcdata[SHELLMATTA_POS_CNT_H2S]     = transportLayer->packetSequenceCounter_h2s;
-            crcdata[SHELLMATTA_POS_CNT_S2H]     = transportLayer->packetSequenceCounter_s2h;
-            strncat(&crcdata[SHELLMATTA_POS_PAYLOAD], transportLayer->payloadBuffer, transportLayer->payloadLength);
-
-            uint32_t refCrc;
-
-            refCrc = crc32Calc(crcdata, SHELLMATTA_HEADER_LENGTH + transportLayer->payloadLength);
+            refCrc = crc32Calc(rawPacketBuffer, SHELLMATTA_HEADER_LENGTH + transportLayer->packetBuffer.payloadLength);
 
             /* if crc is correct, further handling of data depends on type of packet */
-            if (transportLayer->crc32 == refCrc)
+            if (transportLayer->packetBuffer.checksum == refCrc)
             {
-                /* reset fsm by default */
-                transportLayer->state = STATE_GET_SOH;
+
+                transportLayer->active = true;
 
                 /* crc is correct */
-                transportLayer->h2s_sequenceCnt++;
+                transportLayer->sequenceH2S++;
 
-                switch (transportLayer->packetType)
+                switch (transportLayer->packetBuffer.packetType)
                 {
-                case PACKET_DATA:
-                    transportLayer->state = STATE_PROCESS_PAYLOAD;
+                case SHELLMATTA_TRANSPORT_PACKET_DATA:
+                    /** return pointer to payload and length */
+                    *data = (char*)&transportLayer->packetBuffer.payload;
+                    *length = transportLayer->packetBuffer.payloadLength;
+                    ret = SHELLMATTA_OK;
                     break;
                 
-                case PACKET_SEQ_CNT_REQUEST:
-                    /* change packet type to response */
-                    transportLayer->packetType = PACKET_SEQ_CNT_RESPOND;
+                case SHELLMATTA_TRANSPORT_PACKET_SEQ_CNT_REQUEST:
                     /* send out packet with no payload */
-                    shellmatta_transport_write(transportLayer, "", 0u);
+                    intPacket.packetType = SHELLMATTA_TRANSPORT_PACKET_SEQ_CNT_RESPOND;
+                    intPacket.payloadLength = 0u;
+                    (void)shellmatta_transport_send(transportLayer, (shellmatta_transport_packet_t *)&intPacket);
                     break;
 
-                case PACKET_SEQ_CNT_RESPOND:
+                case SHELLMATTA_TRANSPORT_PACKET_SEQ_CNT_RESPOND:
                     break;
                 
-                case PACKET_MAX_BUFFERSIZE_REQUEST:
+                case SHELLMATTA_TRANSPORT_PACKET_MAX_BUFFERSIZE_REQUEST:
                     break;
 
-                case PACKET_MAX_BUFFERSIZE_RESPOND:
+                case SHELLMATTA_TRANSPORT_PACKET_MAX_BUFFERSIZE_RESPOND:
                     break;
                 
-                case PACKET_SEARCH_DEVICE_REQUEST:
+                case SHELLMATTA_TRANSPORT_PACKET_SEARCH_DEVICE_REQUEST:
                     break;
                 
-                case PACKET_SEARCH_DEVICE_RESPOND:
+                case SHELLMATTA_TRANSPORT_PACKET_SEARCH_DEVICE_RESPOND:
                     break;
 
-                case PACKET_SET_ADDRESS_REQUEST:
+                case SHELLMATTA_TRANSPORT_PACKET_SET_ADDRESS_REQUEST:
                     break;
 
-                case PACKET_SET_ADDRESS_RESPOND:
+                case SHELLMATTA_TRANSPORT_PACKET_SET_ADDRESS_RESPOND:
                     break;
 
                 /* wrong packet type */
                 default:
                     /* undo sequence counter increment */
-                    transportLayer->h2s_sequenceCnt--;
+                    transportLayer->sequenceH2S--;
                     break;
                 }
             }
             else
             {
-                transportLayer->state = STATE_GET_SOH;
                 /* crc is incorrect */
                 ret = SHELLMATTA_ERROR;
             }
 
-            /* reset crc variables */
-            transportLayer->crcCounter = 0u;
-            transportLayer->crc32 = 0u;
+            /* reset state machine */
+            transportLayer->state = SHELLMATTA_TRANSPORT_STATE_WAIT;
         }
         break;
-
-    /* start to process payload as if it was entered manually */
-    case STATE_PROCESS_PAYLOAD:
-        transportLayer->state = STATE_GET_SOH;
-        transportLayer->protocolVersion = 0u;
-        transportLayer->packetType      = PACKET_DATA;
-        transportLayer->payloadLength   = 0u;
-        transportLayer->source          = 0u;
-        transportLayer->destination     = 0u;
-        transportLayer->crc32           = 0u;
-        transportLayer->payloadCounter  = 0u;
-        transportLayer->crcCounter      = 0u;
-        transportLayer->active = false;
-        memset(transportLayer->payloadBuffer, 0u, SHELLMATTA_PAYLOAD_MAXLENGTH);
-        break;
     
     default:
         break;
@@ -266,13 +256,6 @@ shellmatta_retCode_t shellmatta_transport_write(shellmatta_transport_layer_t *tr
                                                 uint32_t length)
 {
     shellmatta_retCode_t ret = SHELLMATTA_OK;
-    
-    /* create buffer for data + header + crc with maximum size */
-    uint8_t outputBuffer[   SHELLMATTA_HEADER_LENGTH +      /* length of header */
-                            SHELLMATTA_PAYLOAD_MAXLENGTH +  /* max length of payload */
-                            SHELLMATTA_LENGTH_CRC];         /* length of crc */
-    
-    uint16_t outputBufferSize = sizeof(outputBuffer);
     uint32_t outPayloadLength = length;
 
     /* handle data with length bigger than max length */
@@ -286,42 +269,22 @@ shellmatta_retCode_t shellmatta_transport_write(shellmatta_transport_layer_t *tr
     {
         /* compute length of next payload split */
         restOfPayload = (outPayloadLength - processedLength);
-        if (restOfPayload > SHELLMATTA_PAYLOAD_MAXLENGTH)
+        if (restOfPayload > SHELLMATTA_TRANPORT_PAYLOAD_MAXLENGTH)
         {
-            splitLength = outputBufferSize;
+            splitLength = SHELLMATTA_TRANPORT_PAYLOAD_MAXLENGTH;
         }
         else
         {
-            splitLength = (restOfPayload + SHELLMATTA_HEADER_LENGTH + SHELLMATTA_LENGTH_CRC) % outputBufferSize;
+            splitLength = (restOfPayload + SHELLMATTA_HEADER_LENGTH + SHELLMATTA_LENGTH_CRC) % SHELLMATTA_TRANPORT_PAYLOAD_MAXLENGTH;
         }
         splitPayloadLength = splitLength - SHELLMATTA_HEADER_LENGTH - SHELLMATTA_LENGTH_CRC;
 
-        /* fill buffer with header data */
-        outputBuffer[SHELLMATTA_POS_SOH] = SHELLMATTA_START_OF_HEADER;                  /* start of header                      */
-        outputBuffer[SHELLMATTA_POS_PROT_VER] = PROTOCOL_VERSION;                       /* protocol version                     */
-        outputBuffer[SHELLMATTA_POS_PACKET_TYPE] = transportLayer->packetType;       /* packet type                          */
-        outputBuffer[SHELLMATTA_POS_PAYLOAD_LEN] = splitPayloadLength;                  /* payload length                       */
-        outputBuffer[SHELLMATTA_POS_SRC] = 0x00u;                                       /* source                               */
-        outputBuffer[SHELLMATTA_POS_DST] = 0x00u;                                       /* destination                          */
-        outputBuffer[SHELLMATTA_POS_CNT_H2S] = transportLayer->h2s_sequenceCnt;      /* sequence counter host to shellmatta  */
-        outputBuffer[SHELLMATTA_POS_CNT_S2H] = ++transportLayer->s2h_sequenceCnt;    /* sequence counter shellmatta to host  */
-
-        /* skip copying of payload in case of sequence counter response */
-        if (transportLayer->packetType != PACKET_SEQ_CNT_RESPOND)
-        {
-            memcpy(&outputBuffer[SHELLMATTA_POS_PAYLOAD], data + processedLength, splitPayloadLength);
-        }
-
-        uint32_t outCrc = crc32Calc((char*) outputBuffer, SHELLMATTA_HEADER_LENGTH + splitPayloadLength);
+        transportLayer->outputPacketBuffer.packetType = SHELLMATTA_TRANSPORT_PACKET_DATA;
+        transportLayer->outputPacketBuffer.payloadLength = splitPayloadLength;
+        (void)memcpy(transportLayer->outputPacketBuffer.payload, &data[processedLength], splitPayloadLength);
 
-        /* append crc to end of payload */
-        outputBuffer[splitPayloadLength + SHELLMATTA_HEADER_LENGTH] = (uint8_t)(outCrc >> SHELLMATTA_SHIFT_BY_24);
-        outputBuffer[splitPayloadLength + SHELLMATTA_HEADER_LENGTH + SHELLMATTA_SHIFT_BY_1] = (uint8_t)(outCrc >> SHELLMATTA_SHIFT_BY_16);
-        outputBuffer[splitPayloadLength + SHELLMATTA_HEADER_LENGTH + SHELLMATTA_SHIFT_BY_2] = (uint8_t)(outCrc >> SHELLMATTA_SHIFT_BY_8);
-        outputBuffer[splitPayloadLength + SHELLMATTA_HEADER_LENGTH + SHELLMATTA_SHIFT_BY_3] = (uint8_t)(outCrc);
+        ret = shellmatta_transport_send(transportLayer, &transportLayer->outputPacketBuffer);
 
-        /* use original write function to send full buffer */
-        ret = transportLayer->originalWrite((char*) outputBuffer, splitLength);
         processedLength += splitPayloadLength;
     }
     while (processedLength < outPayloadLength);

+ 31 - 1
src/shellmatta_transport.h

@@ -9,6 +9,21 @@
 
 #include "shellmatta.h"
 
+/** @brief packet definition with reduced payload (for internal packets) */
+typedef struct __attribute__((__packed__))
+{
+    uint8_t startOfHeader;
+    uint8_t protocolVersion;
+    uint8_t packetType;
+    uint8_t payloadLength;
+    uint8_t source;
+    uint8_t destination;
+    uint8_t sequenceH2S;
+    uint8_t sequenceS2H;
+    //char payload[SHELLMATTA_TRANPORT_PAYLOAD_MAXLENGTH];
+    uint32_t checksum;
+} shellmatta_transport_packet_int_t;
+
 #define PROTOCOL_VERSION                    0x01u
 
 /** @brief value of start-of-header character */
@@ -63,6 +78,20 @@
 #define SHELLMATTA_SHIFT_BY_16              ((uint8_t)(16))
 #define SHELLMATTA_SHIFT_BY_24              ((uint8_t)(24))
 
+/**
+ * @brief definitions of shellmatta transport layer packet types
+ */
+
+#define SHELLMATTA_TRANSPORT_PACKET_DATA                    0x00u   /**< packet type to send plain data                                  */
+#define SHELLMATTA_TRANSPORT_PACKET_SEQ_CNT_REQUEST         0x01u   /**< packet type to request sequence counters                        */
+#define SHELLMATTA_TRANSPORT_PACKET_SEQ_CNT_RESPOND         0x81u   /**< packet type to respond with sequence counters                   */
+#define SHELLMATTA_TRANSPORT_PACKET_MAX_BUFFERSIZE_REQUEST  0x02u   /**< packet type to set and request max buffersize                   */
+#define SHELLMATTA_TRANSPORT_PACKET_MAX_BUFFERSIZE_RESPOND  0x82u   /**< packet type to respond with max buffersize                      */
+#define SHELLMATTA_TRANSPORT_PACKET_SEARCH_DEVICE_REQUEST   0x03u   /**< UNUSED: packet type to request search for a device by unique id */
+#define SHELLMATTA_TRANSPORT_PACKET_SEARCH_DEVICE_RESPOND   0x83u   /**< UNUSED: packet type to respond with search results              */
+#define SHELLMATTA_TRANSPORT_PACKET_SET_ADDRESS_REQUEST     0x04u   /**< UNUSED: packet type to set and request an address               */
+#define SHELLMATTA_TRANSPORT_PACKET_SET_ADDRESS_RESPOND     0x84u   /**< UNUSED: packet type to respond with a set address               */
+
 
 shellmatta_retCode_t shellmatta_transport_reset(shellmatta_transport_layer_t *transportLayer);
 
@@ -70,7 +99,8 @@ shellmatta_retCode_t shellmatta_transport_init( shellmatta_transport_layer_t
                                                 shellmatta_write_t              writeFct);
 
 shellmatta_retCode_t shellmatta_transport_process(shellmatta_transport_layer_t   *transportLayer,
-                                                  char                           *data,
+                                                  char                           byte,
+                                                  char                           **data,
                                                   uint32_t                       *length);
 
 shellmatta_retCode_t shellmatta_transport_write(shellmatta_transport_layer_t *transportLayer,

+ 5 - 5
test/integrationtest/test_integration_transport.cpp

@@ -164,10 +164,10 @@ SCENARIO("Integration test of Transport layer", "[integration, transport]")
                 char *dummyData =   (char*)"\x01\x01\x81\x00\x00\x00\x01\x01"
                                            "\xb4\x0f\x12\xe9";
 
-                CHECK( write_length == 12);
-                REQUIRE( memcmp(write_data, dummyData, 12) == 0);
+                CHECK(write_length == 12);
+                REQUIRE(memcmp(write_data, dummyData, 12) == 0);
             }
-            AND_WHEN("Sequence counter is again")
+            AND_WHEN("Sequence counter is requested again")
             {
                 /* request sequence counter again */
                 write_callCnt = 0u;
@@ -180,8 +180,8 @@ SCENARIO("Integration test of Transport layer", "[integration, transport]")
                     char *dummyData =   (char*)"\x01\x01\x81\x00\x00\x00\x02\x02"
                                                "\x06\x2b\x10\x90";
 
-                    CHECK( write_length == 12);
-                    REQUIRE( memcmp(write_data, dummyData, 12) == 0);
+                    CHECK(write_length == 12);
+                    REQUIRE(memcmp(write_data, dummyData, 12) == 0);
                 }
             }
         }