Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: modem_ref_helper_for_v5_3_217
Diff: modem_ref.cpp
- 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); +} + +