WizziLab / modem_ref_v5_3_217

Dependents:   modem_ref_helper_for_v5_3_217

Revision:
0:027760f45e2c
Child:
1:40ead20ecb14
diff -r 000000000000 -r 027760f45e2c modem_ref.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modem_ref.cpp	Wed May 03 11:29:16 2017 +0000
@@ -0,0 +1,371 @@
+#include "modem_ref.h"
+
+typedef struct {
+    action_callback_t*      cb;
+    u8*                     data;
+} modem_user_t;
+
+typedef struct {
+    fx_serial_send_t*   send;
+    modem_callbacks_t*  cb;
+    modem_user_t        user[MAX_USER_NB];
+    u8                  state;
+    u8                  tx_sequ;
+} modem_ctx_t;
+static modem_ctx_t g_modem;
+
+#define STATE_OPEN      0xab
+#define STATE_CLOSED    0
+
+#define SERIAL_SEND(_flow,_data,_size)  do { \
+    u8 wch[WC_HEADER_SIZE] = {WC_SYNC_BYTE_0,WC_SYNC_BYTE_1,_size,g_modem.tx_sequ++,_flow};\
+    g_modem.send(wch,WC_HEADER_SIZE,_data,_size);\
+}while(0)
+
+// Flows
+#define WC_FLOWID_CMD       0x10
+#define WC_FLOWID_ALP       0x20
+#define WC_FLOWID_SYS       0x30
+
+// Sub-Flows
+#define WC_FLOW_ALP_CMD     0x20
+#define WC_FLOW_ALP_RESP    0x21
+#define WC_FLOW_ALP_UNS     0x22
+#define WC_FLOW_SYS_RST     0x30
+#define WC_FLOW_SYS_PING    0x34
+#define WC_FLOW_SYS_PONG    0x35
+#define WC_FLOW_SYS_CFG     0x36
+#define WC_FLOW_SYS_XON     0x39
+#define WC_FLOW_SYS_XOFF    0x3a
+#define WC_FLOW_SYS_XACK    0x3b
+
+// Misc CMD...
+#define WM_BOOT             0x81
+
+
+protected void modem_input(u8 flowid,u8* payload,u8 size)
+{
+    int rem =size;
+    u8* p = payload;
+    alp_parsed_chunk_t r;
+    int id = -1;
+    s8 err = ALP_ERR_NONE;
+    //DPRINT("input 0x%x/%d Bytes\n",flowid,size);
+    switch (flowid)
+    {
+        case WC_FLOW_ALP_UNS:
+        case WC_FLOW_ALP_CMD:
+            rem -= alp_parse_chunk(&p, &r);
+            // This should always be a TAG'ed request in case of FS access...
+            if (r.type == ALP_OPCODE_TAG)
+            {
+                id = r.meta.tag.id;
+                // Parse File Operation
+                rem -= alp_parse_chunk(&p, &r);
+                //DPRINT("ALP OP[%d]\n",r.type);
+                switch (r.type)
+                {
+                    case ALP_OPCODE_F_RD_DATA:
+                        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:
+                        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:
+                        g_modem.cb->read_fprop(r.meta.f_data.fid,id);
+                        break;
+                    case ALP_OPCODE_F_DELETE:
+                        g_modem.cb->remove(r.meta.f_data.fid,id);
+                        break;
+                    case ALP_OPCODE_F_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;
+                }
+            }
+            else
+            {
+                // ... or a 'real' URC (or ISTATUS if enabled on modem)
+                switch (r.type)
+                {
+                    case ALP_OPCODE_RSP_ISTATUS:
+                        // TODO
+                        DPRINT("Got ISTATUS[%x] %d Bytes\n",r.meta.itf.type,r.meta.itf.length);
+                        //g_modem.cb->istatus(r.meta.itf.type,r.meta.itf.length,r.data);
+                        break;
+                    case ALP_OPCODE_RSP_URC:
+                        if (r.meta.urc.type == ALP_URC_TYPE_LQUAL)
+                            g_modem.cb->lqual(r.meta.urc.ifid,r.meta.urc.per);
+                        else if (r.meta.urc.type == ALP_URC_TYPE_LQUAL)
+                            g_modem.cb->ldown(r.meta.urc.ifid);
+                        else
+                            ASSERT(false,"ASSERT: Unsupported ALP URC: %d\n",r.meta.urc.type);
+                        break;
+                    default:
+                        ASSERT(false,"ASSERT: Unsupported ALP URC: %d\n",r.type);
+                        break;
+                }
+            }
+            break;
+        case WC_FLOW_ALP_RESP:
+            // This should always be a TAG'ed response as we tag our requests
+            rem -= alp_parse_chunk(&p, &r);
+            ASSERT((r.type == ALP_OPCODE_RSP_TAG),"ASSERT: expecting RESP_TAG got %d\n",r.type);
+            id = r.meta.tag.id;
+            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;
+                g_modem.user[id].cb(err,id);
+                return;
+            }
+
+            // Actual response
+            rem -= alp_parse_chunk(&p, &r);
+            switch (r.type)
+            {
+                case ALP_OPCODE_RSP_F_DATA:
+                case ALP_OPCODE_RSP_F_PROP: // Not supported but comes for free ...
+                    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);
+                    g_modem.user[id].data = NULL; // keep 'data' relevant
+                    break;
+                case ALP_OPCODE_RSP_STATUS:
+                    err = r.meta.status.code;
+                    break;
+                default:
+                    ASSERT(false,"ASSERT: Unsupported ALP Response: %d\n",r.type);
+                break;
+            }
+            g_modem.user[id].cb(err,id);
+            break;
+        case WC_FLOW_SYS_RST:
+            // 'Software' reset request
+            g_modem.cb->reset();
+            break;
+        case WC_FLOWID_CMD:
+            if (*p == WM_BOOT)
+            {
+                u16 nb_boot;
+                u8 cause;
+                p++;
+                cause = p[0];
+                nb_boot = HAL_TO_U16(p[3],p[2]);
+                g_modem.cb->boot(cause,nb_boot);
+            }
+            else
+            {
+                DPRINT("Unsupported CMD :0x%x\n",*p);
+            }
+            break;
+         default:
+            DPRINT("Unsupported WC Flowid:0x%x / %d Bytes\n",flowid,size);
+            break;
+    }
+}
+
+public int modem_get_id(action_callback_t* cb)
+{
+    int i;
+    for(i=0;i<MAX_USER_NB;i++)
+    {
+        if (g_modem.user[i].cb == NULL)
+        {
+            g_modem.user[i].cb = cb;
+            //DPRINT("Get ID:%d/0x%08x\n",i,cb);
+            return i;
+        }
+    }
+    ASSERT(i < MAX_USER_NB,"ASSERT: out of users\n");
+    return -1;
+}
+
+public int modem_free_id(u8 id)
+{
+    if (id < MAX_USER_NB)
+    {
+        g_modem.user[id].cb     = NULL;
+        g_modem.user[id].data   = NULL;
+        //DPRINT("Free ID:%d\n",id);
+        return id;
+    }
+    return -1;
+}
+
+public void modem_open(fx_serial_send_t* send,modem_callbacks_t* callbacks)
+{
+    if (g_modem.state != STATE_OPEN)
+    {
+        g_modem.send= send;
+        g_modem.cb  = callbacks;
+        memset(g_modem.user,0,(MAX_USER_NB * sizeof(modem_user_t)));
+
+        DPRINT("Open Modem - Max users:%d\n",MAX_USER_NB);
+
+        g_modem.state = STATE_OPEN;
+    }
+}
+
+public void modem_close(void)
+{
+    if (g_modem.state == STATE_OPEN)
+    {
+        g_modem.state = STATE_CLOSED;
+    }
+}
+
+public void modem_reset(void)
+{
+    SERIAL_SEND(WC_FLOW_SYS_RST,NULL,0);
+}
+
+public void modem_read_file(u8 fid,void *data,u32 offset,u32 length, u8 id)
+{
+    u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_F_RD_DATA_SIZE_MAX];
+    u8* p = tmp;
+    DPRINT("RD[%d]@%d %d Bytes\n",fid,offset,length);
+    g_modem.user[id].data = (u8*)data;
+    ALP_ACTION_TAG(p,id,true);
+    ALP_ACTION_F_RD_DATA(p,true,fid,offset,length);
+    SERIAL_SEND(WC_FLOW_ALP_UNS,tmp, (u8)(p-tmp));
+}
+
+public void modem_write_file(u8 fid,void *data,u32 offset,u32 length, u8 id)
+{
+    ALLOC_BUFFER(u8,tmp,(ALP_ACTION_TAG_SIZE + ALP_ACTION_F_WR_DATA_SIZE_MAX(length)));
+
+    u8* p = tmp;
+    DPRINT("WR[%d]@%d %d Bytes\n",fid,offset,length);
+    ALP_ACTION_TAG(p,id,true);
+    ALP_ACTION_F_WR_DATA(p,true,fid,offset,length,data);
+    SERIAL_SEND(WC_FLOW_ALP_UNS,tmp, (u8)(p-tmp));
+    DEALLOC_BUFFER(tmp);
+}
+
+public void modem_declare_file(u8 fid, alp_file_header_t* hdr, u8 id)
+{
+    u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_F_DECLARE_SIZE];
+    u8* p = tmp;
+
+    DPRINT("DECLARE[%d]\n",fid);
+    ALP_ACTION_TAG(p,id,true);
+    ALP_ACTION_F_DECLARE(p,true,fid,hdr);
+    SERIAL_SEND(WC_FLOW_ALP_UNS,tmp, (u8)(p-tmp));
+}
+
+public void modem_create_file(u8 fid, alp_file_header_t* hdr, u8 id)
+{
+    u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_F_CREATE_SIZE];
+    u8* p = tmp;
+
+    DPRINT("CREATE[%d]\n",fid);
+    ALP_ACTION_TAG(p,id,true);
+    ALP_ACTION_F_CREATE(p,true,fid,hdr);
+    SERIAL_SEND(WC_FLOW_ALP_UNS,tmp, (u8)(p-tmp));
+}
+
+public void modem_notify_file(u8 fid,u32 offset,u32 length,u8 id)
+{
+    u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_F_TOUCH_SIZE_MAX];
+    u8* p = tmp;
+
+    DPRINT("NOTIFY[%d]@%d %d Bytes\n",fid,offset,length);
+    ALP_ACTION_TAG(p,id,true);
+    ALP_ACTION_F_TOUCH(p,true,fid,offset,length);
+    SERIAL_SEND(WC_FLOW_ALP_UNS,tmp, (u8)(p-tmp));
+}
+
+public void modem_delete_file(u8 fid,u8 id)
+{
+    u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_F_DELETE_SIZE];
+    u8* p = tmp;
+
+    DPRINT("DELETE[%d]\n",fid);
+    ALP_ACTION_TAG(p,id,true);
+    ALP_ACTION_F_DELETE(p,true,fid);
+    SERIAL_SEND(WC_FLOW_ALP_UNS,tmp, (u8)(p-tmp));
+}
+
+public void modem_send_raw_alp(u8* payload, u32 length, u8 id)
+{
+    ALLOC_BUFFER(u8,tmp,ALP_ACTION_TAG_SIZE + length);
+    u8* p = tmp;
+
+    DPRINT("ALP RAW %d Bytes\n",length);
+    ALP_ACTION_TAG(p,id,true);
+    // User Payload
+    memcpy(p,payload,length);p+=length;
+    SERIAL_SEND(WC_FLOW_ALP_UNS,tmp, (u8)(p-tmp));
+    DEALLOC_BUFFER(tmp);
+}
+
+public void modem_send_file_content(u8* itf, u8 itf_length,u8 fid,void *data,u32 offset,u32 length, u8 id)
+{
+    ALLOC_BUFFER(u8,tmp,ALP_ACTION_TAG_SIZE + ALP_ACTION_FORWARD_SIZE(itf_length) + ALP_ACTION_RSP_F_DATA_SIZE_MAX(length));
+    u8* p = tmp;
+
+    DPRINT("SEND FILE[%d] CONTENTS @%d %d Bytes (itf %d Bytes)\n",fid,offset,length,itf_length);
+    ALP_ACTION_TAG(p,id,true);
+    ALP_ACTION_FORWARD(p,itf,itf_length);
+    ALP_ACTION_RSP_F_DATA(p,fid,offset,length,data);
+    SERIAL_SEND(WC_FLOW_ALP_UNS,tmp, (u8)(p-tmp));
+    DEALLOC_BUFFER(tmp);
+}
+
+public void modem_enable_urc(u8 type, u8 ifid, u8 val, u8 enable, u8 id)
+{
+    u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_URCC_SIZE(ALP_URC_TYPE_LQUAL)];
+    u8* p = tmp;
+    DPRINT("URC[%d] Type %d ifid %d\n",enable,type,ifid);
+
+    ALP_ACTION_TAG(p,id,true);
+    // Actual Operation
+    if (enable)
+    {
+        ALP_ACTION_URCC_EN(p,true,type,ifid,val);
+    }
+    else
+    {
+        ALP_ACTION_URCC_DIS(p,true,type,ifid,val);
+    }
+    SERIAL_SEND(WC_FLOW_ALP_UNS,tmp, (u8)(p-tmp));
+}
+
+public void modem_respond(u8 action, s8 status, int id)
+{
+    u8 tmp[ALP_ACTION_RSP_TAG_SIZE + ALP_ACTION_RSP_STATUS_SIZE];
+    u8* p = tmp;
+    DPRINT("RESP[%d]:%d\n",action,status);
+
+    if (id>=0) { ALP_ACTION_RSP_TAG(p,id,true,(status<0)?true:false); }
+    ALP_ACTION_RSP_STATUS(p,action,status);
+    SERIAL_SEND(WC_FLOW_ALP_RESP,tmp, (u8)(p-tmp));
+}
+
+public void modem_respond_fprop(u8 fid, u8* hdr, int id)
+{
+    u8 tmp[ALP_ACTION_RSP_TAG_SIZE + ALP_ACTION_RSP_F_PROP_SIZE];
+    u8* p = tmp;
+    DPRINT("RESP FPROP[%d]\n",fid);
+
+    if (id>=0) { ALP_ACTION_RSP_TAG(p,id,true,false); }
+    ALP_ACTION_RSP_F_PROP(p,fid,hdr);
+    SERIAL_SEND(WC_FLOW_ALP_RESP,tmp, (u8)(p-tmp));
+}
+
+public void modem_respond_read(u8 fid,void *data,u32 offset,u32 length, int id)
+{
+    ALLOC_BUFFER(u8,tmp,ALP_ACTION_RSP_TAG_SIZE + ALP_ACTION_RSP_F_DATA_SIZE_MAX(length));
+    u8* p = tmp;
+    DPRINT("F_DATA[%d]@%d %d Bytes\n",fid,offset,length);
+    if (id>=0) { ALP_ACTION_RSP_TAG(p,id,true,false); }
+    ALP_ACTION_RSP_F_DATA(p,fid,offset,length,data);
+    SERIAL_SEND(WC_FLOW_ALP_RESP,tmp, (u8)(p-tmp));
+    DEALLOC_BUFFER(tmp);
+}
+
+