Exportable version of WizziLab's modem driver.

Dependents:   modem_ref_helper

Revision:
57:5444cfda9889
Parent:
56:67e3d9608403
Child:
58:8d58e5cb4037
--- a/src/modem_ref.cpp	Wed Jan 27 14:45:28 2021 +0000
+++ b/src/modem_ref.cpp	Fri Jan 29 16:36:32 2021 +0000
@@ -7,35 +7,26 @@
 #include "d7a_1x_fs.h"
 
 #if 0
-    #define REF_PRINT(...)  PRINT(__VA_ARGS__)
-    #define URC_PRINT(...)  PRINT(__VA_ARGS__)
+#define REF_PRINT(...)  PRINT(__VA_ARGS__)
+#define URC_PRINT(...)  PRINT(__VA_ARGS__)
 #else
-    #define REF_PRINT(...);
-    #define URC_PRINT(...);
+#define REF_PRINT(...);
+#define URC_PRINT(...);
 #endif
 
 typedef struct {
     action_callback_t*      cb;
-    uint8_t*                     data;
-    uint8_t*                     istatus;
+    alp_payload_t**         alp_rsp;
 } modem_ref_user_t;
 
 typedef struct {
-    uint8_t*                     data;
-    uint8_t                      type;
-    uint8_t                      length;
-} modem_ref_istatus_t;
-
-typedef struct {
-    fx_serial_send_t*   send;
+    fx_serial_send_t*       send;
     modem_ref_callbacks_t*  cb;
     modem_lwan_callbacks_t* lwan_cb;
     modem_ref_user_t        user[MAX_USER_NB];
-    modem_ref_istatus_t     istatus;
-    uint8_t                  state;
-    uint8_t                  tx_sequ;
-    s32                 action;
+    u8                      state;
 } modem_ref_ctx_t;
+
 static modem_ref_ctx_t g_modem;
 
 #define STATE_OPEN      0xab
@@ -61,306 +52,248 @@
 // Misc CMD...
 #define WM_BOOT             0x81
 
-static void serial_send(uint8_t flowid, uint8_t* data, int size)
+#define PKT_MAX_SIZE 255
+static void serial_send(WizziComPacketType type, alp_payload_t* alp)
+{
+    u8 buf[PKT_MAX_SIZE];
+    u32 len = alp_payload_to_buf(alp, buf, 0, PKT_MAX_SIZE);
+        
+    g_modem.send(type, buf, len);
+}
+
+static void _call_fs_user_cb(alp_payload_t* alp, int id, u32 action)
 {
-    uint8_t len = (uint8_t)size;
-    uint8_t wch[WC_HEADER_SIZE] = {
-        WC_SYNC_BYTE_0,
-        WC_SYNC_BYTE_1,
-        len,
-        g_modem.tx_sequ++,
-        flowid
-        };
+    alp_parsed_chunk_t r;
+    u8* p = alp->d;
+    
+    if (NULL == alp)
+    {
+        return;
+    }
+    
+    alp_parse_chunk(&p, &r);
+            
+    switch (r.type)
+    {
+        case ALP_OPCODE_TAG:
+            id  = r.meta.tag.id;
+            REF_PRINT("ACT %d: TAG[%d] ID:%d ERR:%d EOP:%d\n", action, id, r.meta.tag.err, r.meta.tag.eop);
+            break;
+        case ALP_OPCODE_F_RD_DATA:
+            REF_PRINT("ACT %d: F_RD_DATA[%d] @%d %d bytes\n", action, r.meta.f_data.fid, r.meta.f_data.offset, r.meta.f_data.length);
+            if (g_modem.cb->read)
+            {
+                g_modem.cb->read(action, r.meta.f_data.fid, r.meta.f_data.offset, r.meta.f_data.length, id);
+            }
+            break;
+        case ALP_OPCODE_F_WR_DATA:
+            REF_PRINT("ACT %d: F_WR_DATA[%d] @%d %d bytes\n", action, r.meta.f_data.fid, r.meta.f_data.offset, r.meta.f_data.length);
+            if (g_modem.cb->write)
+            {
+                g_modem.cb->write(action, r.meta.f_data.fid, r.data, r.meta.f_data.offset, r.meta.f_data.length, id);
+            }
+            break;
+        case ALP_OPCODE_F_RD_PROP:
+            REF_PRINT("ACT %d: F_RD_PROP[%d]\n", action, r.meta.f_data.fid);
+            if (g_modem.cb->read_fprop)
+            {
+                g_modem.cb->read_fprop(action, r.meta.f_data.fid, id);
+            }
+            break;
+        case ALP_OPCODE_F_DELETE:
+            REF_PRINT("ACT %d: F_DELETE[%d]\n", action, r.meta.f_data.fid);
+            if (g_modem.cb->remove)
+            {
+                g_modem.cb->remove(action, r.meta.f_data.fid, id);
+            }
+            break;
+        case ALP_OPCODE_F_FLUSH:
+            REF_PRINT("ACT %d: F_FLUSH[%d]\n", action, r.meta.f_data.fid);
+            if (g_modem.cb->flush)
+            {
+                g_modem.cb->flush(action, r.meta.f_data.fid, id);
+            }
+            break;
+        default:
+            ASSERT(false, "ASSERT: Unsupported ALP File Operation: %d\n", r.type);
+            break;
+    }
+    
+    ASSERT(id >= 0, "ASSERT: Wrong id %d\n", id);
+    
+    _call_fs_user_cb(alp->next, id, ++action);
+}
 
-    ASSERT(size < 256, "serial_send too big for serial protocol (%d/%dmax)", size, 255);
-
-    g_modem.send(wch, WC_HEADER_SIZE, data, len);
+static void call_fs_user_cb(alp_payload_t* alp)
+{
+    _call_fs_user_cb(alp, -1, 0);
 }
 
-void modem_ref_input(uint8_t flowid, uint8_t* payload, uint8_t size)
+static void _call_urc_user_cb(alp_payload_t* alp, u32 action)
+{
+    alp_parsed_chunk_t r;
+    u8* p = alp->d;
+    
+    if (NULL == alp)
+    {
+        return;
+    }
+    
+    alp_parse_chunk(&p, &r);
+
+    switch (r.type)
+    {
+        case ALP_OPCODE_RSP_URC:
+            if (ALP_URC_TYPE_LQUAL == r.meta.urc.type)
+            {
+                REF_PRINT("ACT %d: RSP_URC: LQUAL[%d] %d\n", action, r.meta.urc.ifid, r.meta.urc.per);
+                if (g_modem.cb->lqual)
+                {
+                    g_modem.cb->lqual(r.meta.urc.ifid, r.meta.urc.per);
+                }
+            }
+            else if (ALP_URC_TYPE_LDOWN == r.meta.urc.type)
+            {
+                REF_PRINT("ACT %d: RSP_URC: LDOWN[%d]\n", action, r.meta.urc.ifid);
+                if (g_modem.cb->ldown)
+                {
+                    g_modem.cb->ldown(r.meta.urc.ifid);
+                }
+            }
+            else if (ALP_URC_TYPE_BUSY == r.meta.urc.type)
+            {
+                REF_PRINT("ACT %d: RSP_URC: BUSY[%d]\n", action, r.meta.urc.ifid);
+                if (g_modem.cb->busy)
+                {
+                    g_modem.cb->busy(r.meta.urc.ifid);
+                }
+            }
+            else if (ALP_URC_TYPE_ITF_BUSY == r.meta.urc.type)
+            {
+                REF_PRINT("ACT %d: RSP_URC: ITF_BUSY[%d] for %d seconds\n", action, r.meta.urc.ifid, r.meta.urc.per);
+
+                if (FID_LWAN_ITF == r.meta.urc.ifid)
+                {
+                    if (g_modem.lwan_cb)
+                    {
+                        if (MAX_U32 == r.meta.urc.per)
+                        {
+                            if (g_modem.lwan_cb->join_failed)
+                            {
+                                g_modem.lwan_cb->join_failed();
+                            }
+                        }
+                        else if (0 == r.meta.urc.per)
+                        {
+                            if (g_modem.lwan_cb->packet_sent)
+                            {
+                                g_modem.lwan_cb->packet_sent();
+                            }
+                        }
+                        else
+                        {
+                            if (g_modem.lwan_cb->itf_busy)
+                            {
+                                g_modem.lwan_cb->itf_busy(r.meta.urc.per);
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    if (g_modem.cb->itf_busy)
+                    {
+                        g_modem.cb->itf_busy(r.meta.urc.ifid, r.meta.urc.per);
+                    }
+                }
+            }
+            else
+            {
+                ASSERT(false, "ASSERT: Unsupported ALP URC: %d\n", r.meta.urc.type);
+            }
+            break;
+        default:
+            // This could be anything
+            // Let user deal with the payload
+            if (g_modem.cb->udata)
+            {
+                g_modem.cb->udata(alp);
+            }
+            break;
+    }
+    
+    _call_urc_user_cb(alp->next, ++action);
+}
+
+static void call_urc_user_cb(alp_payload_t* alp)
+{
+    _call_urc_user_cb(alp, 0);
+}
+
+void modem_ref_input(u8 flowid, u8* payload, u8 size)
 {
     int rem =size;
-    uint8_t* p = payload;
+    u8* p = payload;
     alp_parsed_chunk_t r;
     int id = -1;
-    int8_t err = ALP_ERR_NONE;
-    uint8_t eop;
-    uint32_t parsed;
+    s8 err = ALP_ERR_NONE;
+    u8 eop;
+    u32 parsed;
+    alp_payload_t* alp;    
 
-    g_modem.action = -1;
-
-    //REF_PRINT("input 0x%x/%d Bytes\n", flowid, size);
+    REF_PRINT("input 0x%x/%d Bytes\n", flowid, size);
     switch (flowid)
     {
         case WC_FLOW_ALP_UNS:
         case WC_FLOW_ALP_CMD:
-            parsed = alp_parse_chunk(&p, &r);
-            if (!parsed)
-            {
-                // Discard the payload in case of parsing error.
-                REF_PRINT("Parsing error line %d!\r\n", __LINE__);
-                break;
-            }
-            rem -= parsed;
-            g_modem.action++;
-            //REF_PRINT("Rem %d Bytes\n", rem);
-            // This should always be a TAG'ed request in case of FS access...
-            if (r.type == ALP_OPCODE_TAG)
+        
+            // pre-parse payload
+            alp = alp_payload_parse(p, size);
+            //alp_payload_print(alp);
+            
+            if (ALP_OPCODE_TAG == (alp->d[0] & 0x3F))
             {
-                REF_PRINT("ACT %d: TAG[%d]\n", g_modem.action, r.meta.tag.id);
-
-                id = r.meta.tag.id;
-
-                while(rem>0)
-                {
-                    // Parse File Operation
-                    parsed = alp_parse_chunk(&p, &r);
-                    if (!parsed)
-                    {
-                        // Discard the payload in case of parsing error.
-                        REF_PRINT("Parsing error line %d!\r\n", __LINE__);
-                        break;
-                    }
-                    rem -= parsed;
-                    g_modem.action++;
-                    //REF_PRINT("ALP OP[%d]\n", r.type);
-                    switch (r.type)
-                    {
-                        case ALP_OPCODE_F_RD_DATA:
-                            REF_PRINT("ACT %d: F_RD_DATA[%d] @%d %d bytes\n", g_modem.action, r.meta.f_data.fid, r.meta.f_data.offset, r.meta.f_data.length);
-                            if (g_modem.cb->read)
-                            {
-                                g_modem.cb->read(r.meta.f_data.fid, r.meta.f_data.offset, r.meta.f_data.length, id);
-                            }
-                            break;
-                        case ALP_OPCODE_F_WR_DATA:
-                            REF_PRINT("ACT %d: F_WR_DATA[%d] @%d %d bytes\n", g_modem.action, r.meta.f_data.fid, r.meta.f_data.offset, r.meta.f_data.length);
-                            if (g_modem.cb->write)
-                            {
-                                g_modem.cb->write(r.meta.f_data.fid, r.data, r.meta.f_data.offset, r.meta.f_data.length, id);
-                            }
-                            break;
-                        case ALP_OPCODE_F_RD_PROP:
-                            REF_PRINT("ACT %d: F_RD_PROP[%d]\n", g_modem.action, r.meta.f_data.fid);
-                            if (g_modem.cb->read_fprop)
-                            {
-                                g_modem.cb->read_fprop(r.meta.f_data.fid, id);
-                            }
-                            break;
-                        case ALP_OPCODE_F_DELETE:
-                            REF_PRINT("ACT %d: F_DELETE[%d]\n", g_modem.action, r.meta.f_data.fid);
-                            if (g_modem.cb->remove)
-                            {
-                                g_modem.cb->remove(r.meta.f_data.fid, id);
-                            }
-                            break;
-                        case ALP_OPCODE_F_FLUSH:
-                            REF_PRINT("ACT %d: F_FLUSH[%d]\n", g_modem.action, r.meta.f_data.fid);
-                            if (g_modem.cb->flush)
-                            {
-                                g_modem.cb->flush(r.meta.f_data.fid, id);
-                            }
-                            break;
-                        default:
-                            ASSERT(false, "ASSERT: Unsupported ALP File Operation: %d\n", r.type);
-                            break;
-                    }
-                    //REF_PRINT("ALP Parsing done. rem %d\n", rem);
-                }
-                //REF_PRINT("ALP Packet done.\n");
+                // Payload starts with a tag, this must be a FS command
+                call_fs_user_cb(alp);
             }
             else
             {
-                // ... or a 'real' URC (or ISTATUS if enabled on modem)
-                g_modem.istatus = (modem_ref_istatus_t){0};
-                do
-                {
-                    switch (r.type)
-                    {
-                        case ALP_OPCODE_RSP_URC:
-                            if (ALP_URC_TYPE_LQUAL == r.meta.urc.type)
-                            {
-                                REF_PRINT("ACT %d: RSP_URC: LQUAL[%d] %d\n", g_modem.action, r.meta.urc.ifid, r.meta.urc.per);
-                                if (g_modem.cb->lqual)
-                                {
-                                    g_modem.cb->lqual(r.meta.urc.ifid, r.meta.urc.per);
-                                }
-                            }
-                            else if (ALP_URC_TYPE_LDOWN == r.meta.urc.type)
-                            {
-                                REF_PRINT("ACT %d: RSP_URC: LDOWN[%d]\n", g_modem.action, r.meta.urc.ifid);
-                                if (g_modem.cb->ldown)
-                                {
-                                    g_modem.cb->ldown(r.meta.urc.ifid);
-                                }
-                            }
-                            else if (ALP_URC_TYPE_BUSY == r.meta.urc.type)
-                            {
-                                REF_PRINT("ACT %d: RSP_URC: BUSY[%d]\n", g_modem.action, r.meta.urc.ifid);
-                                if (g_modem.cb->busy)
-                                {
-                                    g_modem.cb->busy(r.meta.urc.ifid);
-                                }
-                            }
-                            else if (ALP_URC_TYPE_ITF_BUSY == r.meta.urc.type)
-                            {
-                                REF_PRINT("ACT %d: RSP_URC: ITF_BUSY[%d] for %d seconds\n", g_modem.action, r.meta.urc.ifid, r.meta.urc.per);
+                // else this is a 'real' URC (or ISTATUS if enabled on modem)
+                call_urc_user_cb(alp);
+            }
+            
+            alp_payload_free(alp);
 
-                                if (FID_LWAN_ITF == r.meta.urc.ifid)
-                                {
-                                    if (g_modem.lwan_cb)
-                                    {
-                                        if (MAX_U32 == r.meta.urc.per)
-                                        {
-                                            if (g_modem.lwan_cb->join_failed)
-                                            {
-                                                g_modem.lwan_cb->join_failed();
-                                            }
-                                        }
-                                        else if (0 == r.meta.urc.per)
-                                        {
-                                            if (g_modem.lwan_cb->packet_sent)
-                                            {
-                                                g_modem.lwan_cb->packet_sent();
-                                            }
-                                        }
-                                        else
-                                        {
-                                            if (g_modem.lwan_cb->itf_busy)
-                                            {
-                                                g_modem.lwan_cb->itf_busy(r.meta.urc.per);
-                                            }
-                                        }
-                                    }
-                                }
-                                else
-                                {
-                                    if (g_modem.cb->itf_busy)
-                                    {
-                                        g_modem.cb->itf_busy(r.meta.urc.ifid, r.meta.urc.per);
-                                    }
-                                }
-                            }
-                            else
-                            {
-                                ASSERT(false, "ASSERT: Unsupported ALP URC: %d\n", r.meta.urc.type);
-                            }
-                            break;
-                        default:
-                            // This could be anything
-                            // Let user deal with the payload
-                            if (g_modem.cb->udata)
-                            {
-                                g_modem.cb->udata(payload, size);
-                            }
-                            rem = 0;
-                            break;
-                    }
-
-                    int tem = alp_parse_chunk(&p, &r);
-                    if (!tem)
-                    {
-                        break;
-                    }
-                    rem -= tem;
-                } while (rem>=0);
-            }
             break;
         case WC_FLOW_ALP_RESP:
+        
+            // pre-parse payload
+            alp = alp_payload_parse(p, size);
+            //alp_payload_print(alp);
+            
+            p = alp->d;
+            alp_parse_chunk(&p, &r);
+
             // This should always be a TAG'ed response as we tag our requests
-            parsed = alp_parse_chunk(&p, &r);
-            if (!parsed)
-            {
-                // Discard the payload in case of parsing error.
-                REF_PRINT("Parsing error line %d!\r\n", __LINE__);
-                break;
-            }
-            rem -= parsed;
-            g_modem.action++;
-            //REF_PRINT("Rem %d Bytes\n", rem);
-
-            ASSERT((r.type == ALP_OPCODE_RSP_TAG), "ASSERT: expecting RESP_TAG got %d\n", r.type);
-            REF_PRINT("ACT %d: TAG[%d]\n", g_modem.action, r.meta.tag.id);
+            ASSERT((r.type == ALP_OPCODE_RSP_TAG), "ASSERT: expecting RESP_TAG got 0x%02X\n", r.type);
+            
             id  = r.meta.tag.id;
             eop = r.meta.tag.eop;
             ASSERT(g_modem.user[id].cb != NULL, "ASSERT: NULL Callback for ID %d\n", id);
-            // Empty response
-            if (rem <= 0)
-            {
-                // TODO: still no info on error...
-                err = r.meta.tag.err ? ALP_ERR_UNKNOWN : ALP_ERR_NONE;
 
-                if (ALP_ERR_NONE != err)
-                {
-                    REF_PRINT("NO INFO ON ERROR.\n");
-                }
-                else if (eop)
-                {
-                    REF_PRINT("EOP.\n");
-                }
-
-                g_modem.user[id].cb(eop, err, id);
-                return;
-            }
-
-            // Actual response(s)
-            while(rem>0)
-            {
-                parsed = alp_parse_chunk(&p, &r);
-                if (!parsed)
-                {
-                    // Discard the payload in case of parsing error.
-                    REF_PRINT("Parsing error line %d!\r\n", __LINE__);
-                    break;
-                }
-                rem -= parsed;
-                g_modem.action++;
-                //REF_PRINT("Rem %d Bytes\n", rem);
-
-                switch (r.type)
-                {
-                    case ALP_OPCODE_RSP_TAG:
-                        REF_PRINT("ACT %d: RSP_TAG[%d]\n", g_modem.action, r.meta.tag.id);
-                        break;
-                    case ALP_OPCODE_RSP_F_DATA:
-                        REF_PRINT("ACT %d: RSP_F_DATA[%d]\n", g_modem.action, r.meta.f_data.length);
-                        ASSERT(g_modem.user[id].data != NULL, "ASSERT: NULL Data Buffer for RD on ID %d\n", id);
-                        memcpy(g_modem.user[id].data, r.data, r.meta.f_data.length);
-                        break;
-                    case ALP_OPCODE_RSP_F_PROP:
-                        REF_PRINT("ACT %d: RSP_F_PROP[%d]\n", g_modem.action, r.meta.f_data.length);
-                        ASSERT(g_modem.user[id].data != NULL, "ASSERT: NULL Data Buffer for RD on ID %d\n", id);
-                        memcpy(g_modem.user[id].data, r.data, r.meta.f_data.length);
-                        break;
-                    case ALP_OPCODE_RSP_STATUS:
-                        REF_PRINT("ACT %d: RSP_STATUS[%d]\n", g_modem.action, r.meta.status.code);
-                        err = r.meta.status.code;
-                        break;
-                    case ALP_OPCODE_RSP_ISTATUS:
-                        REF_PRINT("ACT %d: RSP_ISTATUS[%d]\n", g_modem.action, r.meta.itf.length);
-                        ASSERT(g_modem.user[id].istatus != NULL, "ASSERT: NULL ISTAT Buffer for RD on ID %d\n", id);
-                        memcpy(g_modem.user[id].istatus, r.data, r.meta.itf.length);
-                        break;
-                    case ALP_OPCODE_RSP_EOPISTATUS:
-                        REF_PRINT("ACT %d: RSP_EOPISTATUS[%02X]\n", g_modem.action, r.meta.istatus.itf);
-                        err = r.meta.istatus.err ? ALP_ERR_ITF_START + r.meta.istatus.err : ALP_ERR_NONE;
-                        break;
-                    default:
-                        ASSERT(false, "ASSERT: Unsupported ALP Response: %d\n", r.type);
-                        break;
-                }
-            }
+            // Give the remaining of the payload to the user to deal with
+            *(g_modem.user[id].alp_rsp) = alp_payload_append(*(g_modem.user[id].alp_rsp), alp);
+                        
             if(eop)
             { // This is mainly for debug, catch old pointers
                 //g_modem.user[id].data   = NULL;
                 //g_modem.user[id].istatus= NULL;
                 REF_PRINT("EOP\n");
             }
+            
             // User Callback
-            if (g_modem.user[id].cb)
-            {
-                g_modem.user[id].cb(eop, err, id);
-            }
+            g_modem.user[id].cb(eop, err, id);
+            
             break;
         case WC_FLOW_SYS_RST:
             // 'Software' reset request
@@ -373,7 +306,7 @@
             if (*p == WM_BOOT)
             {
                 uint16_t nb_boot;
-                uint8_t cause;
+                u8 cause;
                 p++;
                 cause = p[0];
                 nb_boot = HAL_TO_U16(p[3], p[2]);
@@ -387,15 +320,15 @@
                 REF_PRINT("Unsupported CMD :0x%x\n", *p);
             }
             break;
-         default:
+        default:
             REF_PRINT("Unsupported WC Flowid:0x%x / %d Bytes\n", flowid, size);
             break;
     }
 }
 
-static uint32_t modem_ref_add_root_permission(uint8_t* p, uint8_t* root_key, uint8_t* action, uint32_t action_size)
+static u32 modem_ref_add_root_permission(u8* p, u8* root_key, u8* action, u32 action_size)
 {
-    uint8_t hash[32];
+    u8 hash[32];
 
     // Calculate hash on action
     kal_sha256_init();
@@ -414,7 +347,7 @@
 {
     int i;
     // Use rolling ids
-    static int rolling;
+    static u8 rolling;
 
     for(i = 0; i < MAX_USER_NB; i++)
     {
@@ -432,13 +365,11 @@
     return -1;
 }
 
-int modem_ref_free_id(int id)
+int modem_ref_free_id(u8 id)
 {
     if (id < MAX_USER_NB)
     {
         g_modem.user[id].cb     = NULL;
-        g_modem.user[id].data   = NULL;
-        g_modem.user[id].istatus= NULL;
         //REF_PRINT("Free ID:%d\n", id);
         return id;
     }
@@ -449,7 +380,7 @@
 {
     if (g_modem.state != STATE_OPEN)
     {
-        g_modem.send= send;
+        g_modem.send = send;
         g_modem.cb  = callbacks;
         memset(g_modem.user, 0, (MAX_USER_NB * sizeof(modem_ref_user_t)));
 
@@ -469,7 +400,7 @@
 
 void modem_ref_reset(void)
 {
-    serial_send(WC_FLOW_SYS_RST, NULL, 0);
+    serial_send(WizziComPacketSysReset, NULL);
 }
 
 void modem_ref_set_lwan_cb(modem_lwan_callbacks_t* callbacks)
@@ -477,11 +408,20 @@
     g_modem.lwan_cb = callbacks;
 }
 
-static void _modem_ref_alp(void* itf, void* istatus, alp_pub_payload_t* alp_user, int id)
+void modem_ref_alp(void* itf, alp_payload_t* alp_user, alp_payload_t** alp_rsp, int id)
 {
-    alp_pub_payload_t* alp = NULL;
+    alp_payload_t* alp = NULL;
+
+    if (alp_rsp)
+    {
+        // Expecting a response
 
-    REF_PRINT("ALP %d Bytes\n", alp_user->len);
+        // Make sure pointer value is NULL
+        *alp_rsp = NULL;
+    }
+
+    // response pointer
+    g_modem.user[id].alp_rsp = alp_rsp;
 
     // Always a tag
     alp = alp_payload_tag(alp, id);
@@ -490,156 +430,55 @@
     if (itf)
     {
         alp = alp_payload_forward(alp, itf);
-    }
-
-    // add nop to get istatus if any
-    if (istatus)
-    {
         // NOP action to get istats on ACKs
         alp = alp_payload_nop(alp);
     }
 
     // Add user payload
-    alp = alp_append(alp, alp_user);
+    alp = alp_payload_append(alp, alp_user);
 
     // Send to modem
-    serial_send(WC_FLOW_ALP_UNS, alp->d, alp->len);
-
-    FREE(alp);
+    serial_send(WizziComPacketAlpUns, alp);
 }
 
-static void _modem_ref_rsp(alp_pub_payload_t* alp_user, u8 err, int id)
+static void _modem_ref_rsp(alp_payload_t* alp_user, u8 err, int id)
 {
-    alp_pub_payload_t* alp = NULL;
+    alp_payload_t* alp = NULL;
 
-    REF_PRINT("RSP %d Bytes\n", alp_user->len);
+    // response pointer
+    g_modem.user[id].alp_rsp = NULL;
 
     // Always a tag
     alp = alp_payload_rsp_tag(alp, id, true, err);
 
     // Add user payload
-    alp = alp_append(alp, alp_user);
+    alp = alp_payload_append(alp, alp_user);
 
     // Send to modem
-    serial_send(WC_FLOW_ALP_UNS, alp->d, alp->len);
-
-    FREE(alp);
-}
-
-static void _modem_ref_read(void* itf, void* istatus , uint8_t fid, void* data, uint32_t offset, uint32_t length, int id)
-{
-    alp_pub_payload_t* alp = NULL;
-
-    // Expecting data and istatus
-    g_modem.user[id].data    = (uint8_t*)data;
-    g_modem.user[id].istatus = (uint8_t*)istatus;
-
-    alp = alp_payload_f_rd_data(alp, fid, offset, length, false);
-
-    _modem_ref_alp(itf, istatus, alp, id);
-}
-
-static void _modem_ref_write(void* itf, void* istatus, uint8_t fid, void* data, uint32_t offset, uint32_t length, int id)
-{
-    alp_pub_payload_t* alp = NULL;
-
-    alp = alp_payload_f_wr_data(alp, fid, data, offset, length, false);
-
-    _modem_ref_alp(itf, istatus, alp, id);
-}
-
-static void _modem_ref_flush(void* itf, void* istatus, uint8_t fid, int id)
-{
-    alp_pub_payload_t* alp = NULL;
-
-    alp = alp_payload_f_flush(alp, fid, false);
-
-    _modem_ref_alp(itf, istatus, alp, id);
-}
-
-void modem_ref_raw_alp(alp_pub_payload_t* alp_user, int id)
-{
-    _modem_ref_alp(NULL, NULL, alp_user, id);
-}
-
-void modem_ref_remote_raw_alp(void* itf, void* istatus, alp_pub_payload_t* alp_user, int id)
-{
-    _modem_ref_alp(itf, istatus, alp_user, id);
+    serial_send(WizziComPacketAlpUns, alp);
 }
 
-void modem_ref_read_file(uint8_t fid, void* data, uint32_t offset, uint32_t length, int id)
-{
-    _modem_ref_read(NULL, NULL, fid, data, offset, length, id);
-}
-
-void modem_ref_remote_read_file(void* itf, void* istatus , uint8_t fid, void* data, uint32_t offset, uint32_t length, int id)
-{
-    _modem_ref_read(itf, istatus, fid, data, offset, length, id);
-}
-
-void modem_ref_write_file(uint8_t fid, void* data, uint32_t offset, uint32_t length, int id)
-{
-    _modem_ref_write(NULL, NULL, fid, data, offset, length, id);
-}
-
-void modem_ref_remote_write_file(void* itf, void* istatus , uint8_t fid, void* data, uint32_t offset, uint32_t length, int id)
-{
-    _modem_ref_write(itf, istatus, fid, data, offset, length, id);
-}
-
-void modem_ref_flush_file(uint8_t fid, int id)
-{
-    _modem_ref_flush(NULL, NULL, fid, id);
-}
-
-void modem_ref_declare_file(u8 fid, alp_file_header_t* hdr, int id)
+void modem_ref_respond(u8 action, s8 status, int id)
 {
-    alp_pub_payload_t* alp = NULL;
-
-    alp = alp_payload_f_flush(alp, fid, false);
-
-    _modem_ref_alp(NULL, NULL, alp, id);
-}
-
-void modem_ref_enable_urc(uint8_t type, uint8_t ifid, uint8_t val, int id)
-{
-    alp_pub_payload_t* alp = NULL;
-
-    alp = alp_payload_urcc_en(alp, type, ifid, val);
-
-    _modem_ref_alp(NULL, NULL, alp, id);
-}
-
-void modem_ref_activate_itf(uint8_t type, uint8_t nb_dev, uint8_t ifid, uint8_t flags, uint8_t enable, int id)
-{
-    alp_pub_payload_t* alp = NULL;
-
-    alp = alp_payload_activate_itf(alp, type, nb_dev, ifid, flags, enable);
-
-    _modem_ref_alp(NULL, NULL, alp, id);
-}
-
-void modem_ref_respond(uint8_t action, int8_t status, int id)
-{
-    alp_pub_payload_t* alp = NULL;
+    alp_payload_t* alp = NULL;
 
     alp = alp_payload_rsp_status(alp, action, status);
 
     _modem_ref_rsp(alp, (status < ALP_ERR_NONE)? true: false, id);
 }
 
-void modem_ref_respond_fprop(uint8_t fid, alp_file_header_t* hdr, int id)
+void modem_ref_respond_fprop(u8 fid, alp_file_header_t* hdr, int id)
 {
-    alp_pub_payload_t* alp = NULL;
+    alp_payload_t* alp = NULL;
 
     alp = alp_payload_rsp_fprop(alp, fid, hdr);
 
     _modem_ref_rsp(alp, false, id);
 }
 
-void modem_ref_respond_read(uint8_t fid, void* data, uint32_t offset, uint32_t length, int id)
+void modem_ref_respond_read(u8 fid, void* data, u32 offset, u32 length, int id)
 {
-    alp_pub_payload_t* alp = NULL;
+    alp_payload_t* alp = NULL;
 
     alp = alp_payload_rsp_f_data(alp, fid, data, offset, length);