WizziLab / modem_ref_v5_3_217

Dependents:   modem_ref_helper_for_v5_3_217

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers modem_ref.cpp Source File

modem_ref.cpp

00001 #include "mbed.h"
00002 #include "WizziDebug.h"
00003 
00004 #include "modem_ref.h"
00005 #include "kal_crypto.h"
00006 #include "kal_codec.h"
00007 
00008 #if 0
00009     #define REF_PRINT(...)  PRINT(__VA_ARGS__)
00010     #define URC_PRINT(...)  PRINT(__VA_ARGS__)
00011 #else
00012     #define REF_PRINT(...);
00013     #define URC_PRINT(...);
00014 #endif
00015 
00016 typedef struct {
00017     action_callback_t*      cb;
00018     u8*                     data;
00019     u8*                     istatus;
00020 } modem_user_t;
00021 
00022 typedef struct {
00023     u8*                     data;
00024     u8                      type;
00025     u8                      length;
00026 } modem_istatus_t;
00027 
00028 typedef struct {
00029     fx_serial_send_t*   send;
00030     modem_callbacks_t*  cb;
00031     modem_user_t        user[MAX_USER_NB];
00032     modem_istatus_t     istatus;
00033     u8                  state;
00034     u8                  tx_sequ;
00035     s32                 action;
00036 } modem_ctx_t;
00037 static modem_ctx_t g_modem;
00038 
00039 #define STATE_OPEN      0xab
00040 #define STATE_CLOSED    0
00041 
00042 #define ROOT_KEY_SIZE   16
00043 
00044 // Flows
00045 #define WC_FLOWID_CMD       0x10
00046 #define WC_FLOWID_ALP       0x20
00047 #define WC_FLOWID_SYS       0x30
00048 
00049 // Sub-Flows
00050 #define WC_FLOW_ALP_CMD     0x20
00051 #define WC_FLOW_ALP_RESP    0x21
00052 #define WC_FLOW_ALP_UNS     0x22
00053 #define WC_FLOW_SYS_RST     0x30
00054 #define WC_FLOW_SYS_PING    0x34
00055 #define WC_FLOW_SYS_PONG    0x35
00056 #define WC_FLOW_SYS_CFG     0x36
00057 #define WC_FLOW_SYS_XON     0x39
00058 #define WC_FLOW_SYS_XOFF    0x3a
00059 #define WC_FLOW_SYS_XACK    0x3b
00060 
00061 // Misc CMD...
00062 #define WM_BOOT             0x81
00063 
00064 static void serial_send(u8 flowid, u8* data, int size)
00065 {
00066     u8 len = (u8)size;
00067     u8 wch[WC_HEADER_SIZE] = {
00068         WC_SYNC_BYTE_0,
00069         WC_SYNC_BYTE_1,
00070         len,
00071         g_modem.tx_sequ++,
00072         flowid
00073         };
00074 
00075     ASSERT(size < 256, "serial_send too big for serial protocol (%d/%dmax)", size, 255);
00076     
00077     g_modem.send(wch, WC_HEADER_SIZE, data, len);
00078 }
00079 
00080 protected void modem_input(u8 flowid,u8* payload,u8 size)
00081 {
00082     int rem =size;
00083     u8* p = payload;
00084     alp_parsed_chunk_t r;
00085     int id = -1;
00086     s8 err = ALP_ERR_NONE;
00087     u8 eop;
00088     uint32_t parsed;
00089 
00090     g_modem.action = -1;
00091 
00092     //REF_PRINT("input 0x%x/%d Bytes\n",flowid,size);
00093     switch (flowid)
00094     {
00095         case WC_FLOW_ALP_UNS:
00096         case WC_FLOW_ALP_CMD:
00097             parsed = alp_parse_chunk(&p, &r);
00098             if (!parsed)
00099             {
00100                 // Discard the payload in case of parsing error.
00101                 REF_PRINT("Parsing error line %d!\r\n", __LINE__);
00102                 break;
00103             }
00104             rem -= parsed;
00105             g_modem.action++;
00106             //REF_PRINT("Rem %d Bytes\n", rem);
00107             // This should always be a TAG'ed request in case of FS access...
00108             if (r.type == ALP_OPCODE_TAG)
00109             {
00110                 REF_PRINT("ACT %d: TAG[%d]\n", g_modem.action, r.meta.tag.id);
00111                 
00112                 id = r.meta.tag.id;
00113                 
00114                 while(rem>0)
00115                 {
00116                     // Parse File Operation
00117                     parsed = alp_parse_chunk(&p, &r);
00118                     if (!parsed)
00119                     {
00120                         // Discard the payload in case of parsing error.
00121                         REF_PRINT("Parsing error line %d!\r\n", __LINE__);
00122                         break;
00123                     }
00124                     rem -= parsed;
00125                     g_modem.action++;
00126                     //REF_PRINT("ALP OP[%d]\n",r.type);
00127                     switch (r.type)
00128                     {
00129                         case ALP_OPCODE_F_RD_DATA:
00130                             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);
00131                             if (g_modem.cb->read)
00132                             {
00133                                 g_modem.cb->read(r.meta.f_data.fid, r.meta.f_data.offset, r.meta.f_data.length, id);
00134                             }
00135                             break;
00136                         case ALP_OPCODE_F_WR_DATA:
00137                             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);
00138                             if (g_modem.cb->write)
00139                             {
00140                                 g_modem.cb->write(r.meta.f_data.fid, r.data, r.meta.f_data.offset, r.meta.f_data.length, id);
00141                             }
00142                             break;
00143                         case ALP_OPCODE_F_RD_PROP:
00144                             REF_PRINT("ACT %d: F_RD_PROP[%d]\n", g_modem.action, r.meta.f_data.fid);
00145                             if (g_modem.cb->read_fprop)
00146                             {
00147                                 g_modem.cb->read_fprop(r.meta.f_data.fid, id);
00148                             }
00149                             break;
00150                         case ALP_OPCODE_F_DELETE:
00151                             REF_PRINT("ACT %d: F_DELETE[%d]\n", g_modem.action, r.meta.f_data.fid);
00152                             if (g_modem.cb->remove)
00153                             {
00154                                 g_modem.cb->remove(r.meta.f_data.fid, id);
00155                             }
00156                             break;
00157                         case ALP_OPCODE_F_FLUSH:
00158                             REF_PRINT("ACT %d: F_FLUSH[%d]\n", g_modem.action, r.meta.f_data.fid);
00159                             if (g_modem.cb->flush)
00160                             {
00161                                 g_modem.cb->flush(r.meta.f_data.fid, id);
00162                             }
00163                             break;
00164                         default:
00165                             ASSERT(false,"ASSERT: Unsupported ALP File Operation: %d\n", r.type);
00166                             break;
00167                     }
00168                     //REF_PRINT("ALP Parsing done. rem %d\n", rem);
00169                 }
00170                 //REF_PRINT("ALP Packet done.\n");
00171             }
00172             else
00173             {
00174                 // ... or a 'real' URC (or ISTATUS if enabled on modem)
00175                 g_modem.istatus = (modem_istatus_t){0};
00176                 do
00177                 {
00178                     switch (r.type)
00179                     {
00180                         case ALP_OPCODE_RSP_URC:
00181                             if (ALP_URC_TYPE_LQUAL == r.meta.urc.type)
00182                             {
00183                                 REF_PRINT("ACT %d: RSP_URC: LQUAL[%d] %d\n", g_modem.action, r.meta.urc.ifid, r.meta.urc.per);
00184                                 if (g_modem.cb->lqual)
00185                                 {
00186                                     g_modem.cb->lqual(r.meta.urc.ifid, r.meta.urc.per);
00187                                 }
00188                             }
00189                             else if (ALP_URC_TYPE_LDOWN == r.meta.urc.type)
00190                             {
00191                                 REF_PRINT("ACT %d: RSP_URC: LDOWN[%d]\n", g_modem.action, r.meta.urc.ifid);
00192                                 if (g_modem.cb->ldown)
00193                                 {
00194                                     g_modem.cb->ldown(r.meta.urc.ifid);
00195                                 }
00196                             }
00197                             else if (ALP_URC_TYPE_BUSY == r.meta.urc.type)
00198                             {
00199                                 REF_PRINT("ACT %d: RSP_URC: BUSY[%d]\n", g_modem.action, r.meta.urc.ifid);
00200                                 if (g_modem.cb->busy)
00201                                 {
00202                                     g_modem.cb->busy(r.meta.urc.ifid);
00203                                 }
00204                             }
00205                             else if (ALP_URC_TYPE_ITF_BUSY == r.meta.urc.type)
00206                             {
00207                                 REF_PRINT("ACT %d: RSP_URC: ITF_BUSY[%d] for %d seconds\n", g_modem.action, r.meta.urc.ifid, r.meta.urc.per);
00208                                 if (g_modem.cb->itf_busy)
00209                                 {
00210                                     g_modem.cb->itf_busy(r.meta.urc.ifid, r.meta.urc.per);
00211                                 }
00212                             }
00213                             else
00214                             {
00215                                 ASSERT(false, "ASSERT: Unsupported ALP URC: %d\n", r.meta.urc.type);
00216                             }
00217                             break;
00218                         default:
00219                             // This could be anything
00220                             // Let user deal with the payload
00221                             if (g_modem.cb->udata)
00222                             {
00223                                 g_modem.cb->udata(payload, size);
00224                             }
00225                             rem = 0;
00226                             break;
00227                     }
00228 
00229                     int tem = alp_parse_chunk(&p, &r);
00230                     if (!tem)
00231                     {
00232                         break;
00233                     }
00234                     rem -= tem;
00235                 } while (rem>=0);
00236             }
00237             break;
00238         case WC_FLOW_ALP_RESP:
00239             // This should always be a TAG'ed response as we tag our requests
00240             parsed = alp_parse_chunk(&p, &r);
00241             if (!parsed)
00242             {
00243                 // Discard the payload in case of parsing error.
00244                 REF_PRINT("Parsing error line %d!\r\n", __LINE__);
00245                 break;
00246             }
00247             rem -= parsed;
00248             g_modem.action++;
00249             //REF_PRINT("Rem %d Bytes\n", rem);
00250             
00251             ASSERT((r.type == ALP_OPCODE_RSP_TAG),"ASSERT: expecting RESP_TAG got %d\n",r.type);
00252             REF_PRINT("ACT %d: TAG[%d]\n", g_modem.action, r.meta.tag.id);
00253             id  = r.meta.tag.id;
00254             eop = r.meta.tag.eop;
00255             ASSERT(g_modem.user[id].cb != NULL,"ASSERT: NULL Callback for ID %d\n",id);
00256             // Empty response
00257             if (rem <= 0)
00258             {
00259                 // TODO: still no info on error...
00260                 err = r.meta.tag.err ? ALP_ERR_UNKNOWN : ALP_ERR_NONE;
00261                 
00262                 if (ALP_ERR_NONE != err)
00263                 {
00264                     REF_PRINT("NO INFO ON ERROR.\n");
00265                 }
00266                 else if (eop)
00267                 {
00268                     REF_PRINT("EOP.\n");
00269                 }
00270                 
00271                 g_modem.user[id].cb(eop,err,id);
00272                 return;
00273             }
00274 
00275             // Actual response(s)
00276             while(rem>0)
00277             {
00278                 parsed = alp_parse_chunk(&p, &r);
00279                 if (!parsed)
00280                 {
00281                     // Discard the payload in case of parsing error.
00282                     REF_PRINT("Parsing error line %d!\r\n", __LINE__);
00283                     break;
00284                 }
00285                 rem -= parsed;
00286                 g_modem.action++;
00287                 //REF_PRINT("Rem %d Bytes\n", rem);
00288                 
00289                 switch (r.type)
00290                 {
00291                     case ALP_OPCODE_RSP_TAG:
00292                         REF_PRINT("ACT %d: RSP_TAG[%d]\n", g_modem.action, r.meta.tag.id);
00293                         break;
00294                     case ALP_OPCODE_RSP_F_DATA:
00295                         REF_PRINT("ACT %d: RSP_F_DATA[%d]\n", g_modem.action, r.meta.f_data.length);
00296                         ASSERT(g_modem.user[id].data != NULL,"ASSERT: NULL Data Buffer for RD on ID %d\n",id);
00297                         memcpy(g_modem.user[id].data, r.data, r.meta.f_data.length);
00298                         break;
00299                     case ALP_OPCODE_RSP_F_PROP:
00300                         REF_PRINT("ACT %d: RSP_F_PROP[%d]\n", g_modem.action, r.meta.f_data.length);
00301                         ASSERT(g_modem.user[id].data != NULL,"ASSERT: NULL Data Buffer for RD on ID %d\n",id);
00302                         memcpy(g_modem.user[id].data, r.data, r.meta.f_data.length);
00303                         break;
00304                     case ALP_OPCODE_RSP_STATUS:
00305                         REF_PRINT("ACT %d: RSP_STATUS[%d]\n", g_modem.action, r.meta.status.code);
00306                         err = r.meta.status.code;
00307                         break;
00308                     case ALP_OPCODE_RSP_ISTATUS:
00309                         REF_PRINT("ACT %d: RSP_ISTATUS[%d]\n", g_modem.action, r.meta.itf.length);
00310                         ASSERT(g_modem.user[id].istatus != NULL,"ASSERT: NULL ISTAT Buffer for RD on ID %d\n",id);
00311                         memcpy(g_modem.user[id].istatus, r.data, r.meta.itf.length);
00312                         break;
00313                     case ALP_OPCODE_RSP_EOPISTATUS:
00314                         REF_PRINT("ACT %d: RSP_EOPISTATUS[%02X]\n", g_modem.action, r.meta.istatus.itf);
00315                         err = r.meta.istatus.err ? ALP_ERR_ITF_START + r.meta.istatus.err : ALP_ERR_NONE;
00316                         break;
00317                     default:
00318                         ASSERT(false,"ASSERT: Unsupported ALP Response: %d\n",r.type);
00319                         break;
00320                 }
00321             }
00322             if(eop)
00323             { // This is mainly for debug, catch old pointers
00324                 //g_modem.user[id].data   = NULL;
00325                 //g_modem.user[id].istatus= NULL;
00326                 REF_PRINT("EOP\n");
00327             }
00328             // User Callback
00329             if (g_modem.user[id].cb)
00330             {
00331                 g_modem.user[id].cb(eop,err,id);
00332             }
00333             break;
00334         case WC_FLOW_SYS_RST:
00335             // 'Software' reset request
00336             if (g_modem.cb->reset)
00337             {
00338                 g_modem.cb->reset();
00339             }
00340             break;
00341         case WC_FLOWID_CMD:
00342             if (*p == WM_BOOT)
00343             {
00344                 u16 nb_boot;
00345                 u8 cause;
00346                 p++;
00347                 cause = p[0];
00348                 nb_boot = HAL_TO_U16(p[3],p[2]);
00349                 if (g_modem.cb->boot)
00350                 {
00351                     g_modem.cb->boot(cause,nb_boot);
00352                 }
00353             }
00354             else
00355             {
00356                 REF_PRINT("Unsupported CMD :0x%x\n",*p);
00357             }
00358             break;
00359          default:
00360             REF_PRINT("Unsupported WC Flowid:0x%x / %d Bytes\n",flowid,size);
00361             break;
00362     }
00363 }
00364 
00365 private u32 modem_add_root_permission(u8* p, u8* root_key, u8* action, u32 action_size)
00366 {
00367     u8 hash[32];
00368 
00369     // Calculate hash on action
00370     kal_sha256_init();
00371     kal_sha256_update(action, action_size);
00372     kal_sha256_update(root_key, ROOT_KEY_SIZE);
00373     kal_sha256_final(hash);
00374     // Prepend Permission-request...
00375     ALP_ACTION_PERM_REQ(p, false, ALP_PERM_REQ_ROOT);
00376     // ... and hash
00377     memcpy(p, hash, ALP_WIZZILAB_AUTH_PROTOCOL_TOKEN_SIZE);
00378 
00379     return ALP_ACTION_PERM_REQ_OFFSET;
00380 }
00381 
00382 public int modem_get_id(action_callback_t* cb)
00383 {
00384     int i;
00385     for(i=0;i<MAX_USER_NB;i++)
00386     {
00387         if (g_modem.user[i].cb == NULL)
00388         {
00389             g_modem.user[i].cb = cb;
00390             //REF_PRINT("Get ID:%d/0x%08x\n",i,cb);
00391             return i;
00392         }
00393     }
00394     ASSERT(i < MAX_USER_NB,"ASSERT: out of users\n");
00395     return -1;
00396 }
00397 
00398 public int modem_free_id(u8 id)
00399 {
00400     if (id < MAX_USER_NB)
00401     {
00402         g_modem.user[id].cb     = NULL;
00403         g_modem.user[id].data   = NULL;
00404         g_modem.user[id].istatus= NULL;
00405         //REF_PRINT("Free ID:%d\n",id);
00406         return id;
00407     }
00408     return -1;
00409 }
00410 
00411 public void modem_open(fx_serial_send_t* send,modem_callbacks_t* callbacks)
00412 {
00413     if (g_modem.state != STATE_OPEN)
00414     {
00415         g_modem.send= send;
00416         g_modem.cb  = callbacks;
00417         memset(g_modem.user,0,(MAX_USER_NB * sizeof(modem_user_t)));
00418 
00419         REF_PRINT("Open Modem - Max users:%d\n",MAX_USER_NB);
00420 
00421         g_modem.state = STATE_OPEN;
00422     }
00423 }
00424 
00425 public void modem_close(void)
00426 {
00427     if (g_modem.state == STATE_OPEN)
00428     {
00429         g_modem.state = STATE_CLOSED;
00430     }
00431 }
00432 
00433 public void modem_reset(void)
00434 {
00435     serial_send(WC_FLOW_SYS_RST,NULL,0);
00436 }
00437 
00438 public void modem_read_file(u8 fid, void *data, u32 offset, u32 length, u8 id)
00439 {
00440     u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_F_RD_DATA_SIZE_MAX];
00441     u8* p = tmp;
00442     REF_PRINT("RD[%d]@%d %d Bytes\n",fid,offset,length);
00443     g_modem.user[id].data = (u8*)data;
00444     ALP_ACTION_TAG(p,id,true);
00445     ALP_ACTION_F_RD_DATA(p,true,fid,offset,length);
00446     serial_send(WC_FLOW_ALP_UNS, tmp, (p-tmp));
00447 }
00448 
00449 public void modem_read_fprop(u8 fid, alp_file_header_t* data, u8 id)
00450 {
00451     u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_F_RD_PROP_SIZE];
00452     u8* p = tmp;
00453     REF_PRINT("RD PROPS[%d]\n",fid);
00454     g_modem.user[id].data = (u8*)data;
00455     ALP_ACTION_TAG(p,id,true);
00456     ALP_ACTION_F_RD_PROP(p,true,fid);
00457     serial_send(WC_FLOW_ALP_UNS, tmp, (p-tmp));
00458 }
00459 
00460 public void modem_read_fprop_root(u8 fid, alp_file_header_t* data, u8* root_key, u8 id)
00461 {
00462     u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_PERM_REQ_SIZE(ALP_ACTION_F_RD_PROP_SIZE)];
00463     u8* p = tmp;
00464     u8* lastp;
00465     REF_PRINT("RD PROPS (ROOT)[%d]\n",fid);
00466     ASSERT(root_key != NULL, "Missing ROOT KEY\n");
00467     g_modem.user[id].data = (u8*)data;
00468     ALP_ACTION_TAG(p, id, true);
00469     // Actual Operation will take place after PERM_REQ
00470     p = &tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_PERM_REQ_OFFSET];
00471     ALP_ACTION_F_RD_PROP(p,true,fid);
00472     lastp = p;
00473     modem_add_root_permission(&tmp[ALP_ACTION_TAG_SIZE], root_key,
00474             &tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_PERM_REQ_OFFSET],
00475             ALP_ACTION_F_RD_PROP_SIZE);
00476     serial_send(WC_FLOW_ALP_UNS, tmp, (lastp-tmp));
00477 }
00478 
00479 public void modem_write_fprop(u8 fid, alp_file_header_t* data, u8 id)
00480 {
00481     u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_F_WR_PROP_SIZE_MAX];
00482     u8* p = tmp;
00483     DPRINT(L_API, "WR PROPS[%d]\n",fid);
00484     ALP_ACTION_TAG(p,id,true);
00485     ALP_ACTION_F_WR_PROP(p,true,fid,0,sizeof(alp_file_header_t),data);
00486     serial_send(WC_FLOW_ALP_UNS, tmp, (p-tmp));
00487 }
00488 
00489 public void modem_write_fprop_root(u8 fid, alp_file_header_t* data, u8* root_key, u8 id)
00490 {
00491     u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_PERM_REQ_SIZE(ALP_ACTION_F_WR_PROP_SIZE_MAX)];
00492     u8* p = tmp;
00493     u8* lastp;
00494     DPRINT(L_API, "WR PROPS (ROOT)[%d]\n",fid);
00495     ASSERT(root_key != NULL, "Missing ROOT KEY\n");
00496     ALP_ACTION_TAG(p, id, true);
00497     // Actual Operation will take place after PERM_REQ
00498     p = &tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_PERM_REQ_OFFSET];
00499     ALP_ACTION_F_WR_PROP(p,true,fid,0,sizeof(alp_file_header_t),data);
00500     lastp = p;
00501     modem_add_root_permission(&tmp[ALP_ACTION_TAG_SIZE], root_key,
00502             &tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_PERM_REQ_OFFSET],
00503             ALP_ACTION_F_WR_PROP_SIZE_MAX);
00504     serial_send(WC_FLOW_ALP_UNS, tmp, (lastp-tmp));
00505 }
00506 
00507 public void modem_write_file(u8 fid, void *data, u32 offset, u32 length, u8 id)
00508 {
00509     ALLOC_BUFFER(u8, tmp,(ALP_ACTION_TAG_SIZE + ALP_ACTION_F_WR_DATA_SIZE_MAX(length)));
00510 
00511     u8* p = tmp;
00512     REF_PRINT("WR[%d]@%d %d Bytes\n",fid,offset,length);
00513     ALP_ACTION_TAG(p,id,true);
00514     ALP_ACTION_F_WR_DATA(p,true,fid,offset,length,data);
00515     serial_send(WC_FLOW_ALP_UNS, tmp, (p-tmp));
00516     DEALLOC_BUFFER(tmp);
00517 }
00518 
00519 public void modem_write_file_root(u8 fid, void *data, u32 offset, u32 length, u8* root_key, u8 id)
00520 {
00521     ALLOC_BUFFER(u8, tmp,(ALP_ACTION_TAG_SIZE + ALP_ACTION_PERM_REQ_SIZE(ALP_ACTION_F_WR_DATA_SIZE_MAX(length))));
00522 
00523     u8* p = tmp;
00524     u8* lastp;
00525     REF_PRINT("WR (ROOT)[%d]@%d %d Bytes\n",fid,offset,length);
00526     ASSERT(root_key != NULL, "Missing ROOT KEY\n");
00527     ALP_ACTION_TAG(p, id, true);
00528     // Actual Operation will take place after PERM_REQ
00529     p = &tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_PERM_REQ_OFFSET];
00530     ALP_ACTION_F_WR_DATA(p,true,fid,offset,length,data);
00531     lastp = p;
00532     modem_add_root_permission(&tmp[ALP_ACTION_TAG_SIZE], root_key,
00533             &tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_PERM_REQ_OFFSET],
00534             ALP_ACTION_F_WR_DATA_SIZE(offset,length));
00535     serial_send(WC_FLOW_ALP_UNS, tmp, (lastp-tmp));
00536     DEALLOC_BUFFER(tmp);
00537 }
00538 
00539 public void modem_flush_file(u8 fid, u8 id)
00540 {
00541     u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_F_FLUSH_SIZE];
00542     u8* p = tmp;
00543     REF_PRINT("FLUSH[%d]\n",fid);
00544     ALP_ACTION_TAG(p,id,true);
00545     ALP_ACTION_F_FLUSH(p,true,fid);
00546     serial_send(WC_FLOW_ALP_UNS, tmp, (p-tmp));
00547 }
00548 
00549 public void modem_flush_file_root(u8 fid, u8* root_key, u8 id)
00550 {
00551     u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_PERM_REQ_SIZE(ALP_ACTION_F_FLUSH_SIZE)];
00552     u8* p = tmp;
00553     u8* lastp;
00554     REF_PRINT("FLUSH (ROOT)[%d]\n",fid);
00555     ASSERT(root_key != NULL, "Missing ROOT KEY\n");
00556     ALP_ACTION_TAG(p, id, true);
00557     // Actual Operation will take place after PERM_REQ
00558     p = &tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_PERM_REQ_OFFSET];
00559     ALP_ACTION_F_FLUSH(p,true,fid);
00560     lastp = p;
00561     modem_add_root_permission(&tmp[ALP_ACTION_TAG_SIZE], root_key,
00562             &tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_PERM_REQ_OFFSET],
00563             ALP_ACTION_F_FLUSH_SIZE);
00564     serial_send(WC_FLOW_ALP_UNS, tmp, (lastp-tmp));
00565 }
00566 
00567 public void modem_declare_file(u8 fid, alp_file_header_t* hdr, u8 local, u8 id)
00568 {
00569     u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_F_DECLARE_SIZE];
00570     u8* p = tmp;
00571 
00572     REF_PRINT("DECLARE[%d]\n",fid);
00573     ALP_ACTION_TAG(p,id,true);
00574     ALP_ACTION_F_DECLARE(p,true,fid,hdr,local);
00575     serial_send(WC_FLOW_ALP_UNS, tmp, (p-tmp));
00576 }
00577 
00578 public void modem_create_file(u8 fid, alp_file_header_t* hdr, u8 id)
00579 {
00580     u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_F_CREATE_SIZE];
00581     u8* p = tmp;
00582 
00583     REF_PRINT("CREATE[%d]\n",fid);
00584     ALP_ACTION_TAG(p,id,true);
00585     ALP_ACTION_F_CREATE(p,true,fid,hdr);
00586     serial_send(WC_FLOW_ALP_UNS, tmp, (p-tmp));
00587 }
00588 
00589 public void modem_notify_file(u8 fid, u32 offset, u32 length, u8 id)
00590 {
00591     u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_F_TOUCH_SIZE_MAX];
00592     u8* p = tmp;
00593 
00594     REF_PRINT("NOTIFY[%d]@%d %d Bytes\n",fid,offset,length);
00595     ALP_ACTION_TAG(p,id,true);
00596     ALP_ACTION_F_TOUCH(p,true,fid,offset,length);
00597     serial_send(WC_FLOW_ALP_UNS, tmp, (p-tmp));
00598 }
00599 
00600 public void modem_delete_file(u8 fid, u8 id)
00601 {
00602     u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_F_DELETE_SIZE];
00603     u8* p = tmp;
00604 
00605     REF_PRINT("DELETE[%d]\n",fid);
00606     ALP_ACTION_TAG(p,id,true);
00607     ALP_ACTION_F_DELETE(p,true,fid);
00608     serial_send(WC_FLOW_ALP_UNS, tmp, (p-tmp));
00609 }
00610 
00611 public void modem_delete_file_root(u8 fid, u8* root_key, u8 id)
00612 {
00613     u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_PERM_REQ_SIZE(ALP_ACTION_F_DELETE_SIZE)];
00614     u8* p = tmp;
00615     u8* lastp;
00616 
00617     REF_PRINT("DELETE ROOT[%d]\n",fid);
00618     ALP_ACTION_TAG(p,id,true);
00619     // Actual Operation will take place after PERM_REQ
00620     p = &tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_PERM_REQ_OFFSET];
00621     ALP_ACTION_F_DELETE(p,true,fid);
00622     lastp = p;
00623     modem_add_root_permission(&tmp[ALP_ACTION_TAG_SIZE], root_key,
00624             &tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_PERM_REQ_OFFSET],
00625             ALP_ACTION_F_DELETE_SIZE);
00626     serial_send(WC_FLOW_ALP_UNS, tmp, (lastp-tmp));
00627 }
00628 
00629 public void modem_send_raw_alp(u8* payload, u32 length, u8 id)
00630 {
00631     ALLOC_BUFFER(u8, tmp,ALP_ACTION_TAG_SIZE + length);
00632     u8* p = tmp;
00633 
00634     REF_PRINT("ALP RAW %d Bytes\n",length);
00635     ALP_ACTION_TAG(p,id,true);
00636     // User Payload
00637     memcpy(p,payload,length);p+=length;
00638     serial_send(WC_FLOW_ALP_UNS, tmp, (p-tmp));
00639     DEALLOC_BUFFER(tmp);
00640 }
00641 
00642 public void modem_send_file_content(u8* itf, u8 itf_length, void *istatus, u8 fid, void *data, u32 offset, u32 length, u8 id)
00643 {
00644     ALLOC_BUFFER(u8, tmp,ALP_ACTION_TAG_SIZE + ALP_ACTION_FORWARD_SIZE(itf_length) + ALP_ACTION_RSP_F_DATA_SIZE_MAX(length));
00645     u8* p = tmp;
00646     g_modem.user[id].istatus= (u8*)istatus;
00647 
00648     REF_PRINT("SEND FILE[%d] CONTENTS @%d %d Bytes (itf %d Bytes)\n",fid,offset,length,itf_length);
00649     ALP_ACTION_TAG(p,id,true);
00650     ALP_ACTION_FORWARD(p,itf,itf_length);
00651     if (istatus)
00652     {
00653         // NOP action to get istats on ACKs
00654         ALP_ACTION_NOP(p,true);
00655     }
00656     ALP_ACTION_RSP_F_DATA(p,fid,offset,length,data);
00657     serial_send(WC_FLOW_ALP_UNS, tmp, (p-tmp));
00658     DEALLOC_BUFFER(tmp);
00659 }
00660 
00661 public void modem_remote_read_file(u8* itf, u8 itf_length, void *istatus , u8 fid, void *data, u32 offset, u32 length, u8 id)
00662 {
00663     ALLOC_BUFFER(u8, tmp,ALP_ACTION_TAG_SIZE + ALP_ACTION_FORWARD_SIZE(itf_length) + ALP_ACTION_F_RD_DATA_SIZE_MAX);
00664     u8* p = tmp;
00665     g_modem.user[id].data    = (u8*)data;
00666     g_modem.user[id].istatus = (u8*)istatus;
00667 
00668     REF_PRINT("RMT RD FILE[%d]@%d %d Bytes (itf %d Bytes)\n",fid,offset,length,itf_length);
00669     ALP_ACTION_TAG(p,id,true);
00670     ALP_ACTION_FORWARD(p,itf,itf_length);
00671     ALP_ACTION_F_RD_DATA(p,true,fid,offset,length);
00672     serial_send(WC_FLOW_ALP_UNS, tmp, (p-tmp));
00673     DEALLOC_BUFFER(tmp);
00674 }
00675 
00676 public void modem_remote_read_file_root(u8* itf, u8 itf_length, void *istatus , u8 fid, void *data, u32 offset, u32 length, u8* root_key, u8 id)
00677 {
00678     ALLOC_BUFFER(u8, tmp, ALP_ACTION_TAG_SIZE + ALP_ACTION_FORWARD_SIZE(itf_length) + ALP_ACTION_PERM_REQ_SIZE(ALP_ACTION_F_RD_DATA_SIZE_MAX));
00679     u8* p = tmp;
00680     u32 perm_offset;
00681     
00682     ASSERT(root_key != NULL, "Missing ROOT KEY\n");
00683     
00684     g_modem.user[id].data    = (u8*)data;
00685     g_modem.user[id].istatus = (u8*)istatus;
00686 
00687     REF_PRINT("RMT RD FILE (ROOT)[%d]@%d %d Bytes (itf %d Bytes)\n", fid, offset, length, itf_length);
00688     ALP_ACTION_TAG(p, id, true);
00689     ALP_ACTION_FORWARD(p, itf, itf_length);
00690     
00691     // Mark start of permission request
00692     perm_offset = (u32)(p-tmp);
00693     
00694     // Actual Operation will take place after PERM_REQ
00695     p = &tmp[perm_offset + ALP_ACTION_PERM_REQ_OFFSET];
00696     ALP_ACTION_F_RD_DATA(p, true, fid, offset, length);
00697     
00698     modem_add_root_permission(&tmp[perm_offset], root_key,
00699             &tmp[perm_offset + ALP_ACTION_PERM_REQ_OFFSET],
00700             ALP_ACTION_F_RD_DATA_SIZE(offset, length));
00701             
00702     serial_send(WC_FLOW_ALP_UNS, tmp, (p-tmp));
00703     DEALLOC_BUFFER(tmp);
00704 }
00705 
00706 public void modem_remote_write_file(u8* itf, u8 itf_length, void *istatus , u8 fid, void *data, u32 offset, u32 length, u8 id)
00707 {
00708     ALLOC_BUFFER(u8, tmp,ALP_ACTION_TAG_SIZE + ALP_ACTION_FORWARD_SIZE(itf_length) + ALP_ACTION_F_WR_DATA_SIZE_MAX(length));
00709     u8* p = tmp;
00710     g_modem.user[id].istatus = (u8*)istatus;
00711 
00712     REF_PRINT("RMT WR FILE[%d]@%d %d Bytes (itf %d Bytes)\n",fid,offset,length,itf_length);
00713     ALP_ACTION_TAG(p,id,true);
00714     ALP_ACTION_FORWARD(p,itf,itf_length);
00715     ALP_ACTION_F_WR_DATA(p,true,fid,offset,length,data);
00716     serial_send(WC_FLOW_ALP_UNS, tmp, (p-tmp));
00717     DEALLOC_BUFFER(tmp);
00718 }
00719 
00720 public void modem_remote_write_file_root(u8* itf, u8 itf_length, void *istatus, u8 fid, void *data, u32 offset, u32 length, u8* root_key, u8 id)
00721 {
00722     ALLOC_BUFFER(u8, tmp, (ALP_ACTION_TAG_SIZE + ALP_ACTION_FORWARD_SIZE(itf_length) + ALP_ACTION_PERM_REQ_SIZE(ALP_ACTION_F_WR_DATA_SIZE_MAX(length))));
00723 
00724     u8* p = tmp;
00725     u8* actp;
00726     u8* reqp;
00727     
00728     g_modem.user[id].istatus = (u8*)istatus;
00729     
00730     REF_PRINT("WR (ROOT)[%d]@%d %d Bytes\n",fid,offset,length);
00731     ASSERT(root_key != NULL, "Missing ROOT KEY\n");
00732     
00733     // TAG and FORWARD
00734     ALP_ACTION_TAG(p, id, true);
00735     ALP_ACTION_FORWARD(p,itf,itf_length);
00736     
00737     // Save offset of permission request
00738     reqp = p;
00739     
00740     // Actual Operation will take place after PERM_REQ, skip it
00741     p += ALP_ACTION_PERM_REQ_OFFSET;
00742     
00743     // Save action offset
00744     actp = p;
00745     
00746     // Actual action
00747     ALP_ACTION_F_WR_DATA(p,true,fid,offset,length,data);
00748     
00749     // Add permission request at request offset
00750     modem_add_root_permission(
00751         reqp,
00752         root_key,
00753         actp,
00754         ALP_ACTION_F_WR_DATA_SIZE(offset,length)
00755     );
00756     
00757     serial_send(WC_FLOW_ALP_UNS, tmp, (p-tmp));
00758     DEALLOC_BUFFER(tmp);
00759 }
00760 
00761 public void modem_enable_urc(u8 type, u8 ifid, u8 val, u8 enable, u8 id)
00762 {
00763     u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_URCC_SIZE(ALP_URC_TYPE_LQUAL)];
00764     u8* p = tmp;
00765     REF_PRINT("URC[%d] Type %d ifid %d\n",enable,type,ifid);
00766 
00767     ALP_ACTION_TAG(p,id,true);
00768     // Actual Operation
00769     if (enable)
00770     {
00771         ALP_ACTION_URCC_EN(p,true,type,ifid,val);
00772     }
00773     else
00774     {
00775         ALP_ACTION_URCC_DIS(p,true,type,ifid,val);
00776     }
00777     serial_send(WC_FLOW_ALP_UNS, tmp, (p-tmp));
00778 }
00779 
00780 public void modem_activate_itf(u8 type, u8 nb_dev, u8 ifid, u8 flags, u8 enable, u8 id)
00781 {
00782     u8 tmp[ALP_ACTION_TAG_SIZE + ALP_ACTION_ACTIVATE_ITF_SIZE];
00783     u8* p = tmp;
00784 
00785     REF_PRINT("ACTIVATE ITFTYPE[%x]:%d\n",type,enable);
00786     ALP_ACTION_TAG(p,id,true);
00787     ALP_ACTION_ACTIVATE_ITF(p,true,enable,type,nb_dev,ifid,flags);
00788     serial_send(WC_FLOW_ALP_UNS, tmp, (p-tmp));
00789 }
00790 
00791 public void modem_respond(s8 status, int id)
00792 {
00793     u8 tmp[ALP_ACTION_RSP_TAG_SIZE + ALP_ACTION_RSP_STATUS_SIZE];
00794     u8* p = tmp;
00795     REF_PRINT("RESP[%d]:%d\n",g_modem.action,status);
00796 
00797     if (id>=0) { ALP_ACTION_RSP_TAG(p,id,true,(status<0)?true:false); }
00798     ALP_ACTION_RSP_STATUS(p, g_modem.action, status);
00799     serial_send(WC_FLOW_ALP_RESP, tmp, (p-tmp));
00800 }
00801 
00802 public void modem_respond_fprop(u8 fid, u8* hdr, int id)
00803 {
00804     u8 tmp[ALP_ACTION_RSP_TAG_SIZE + ALP_ACTION_RSP_F_PROP_SIZE];
00805     u8* p = tmp;
00806     REF_PRINT("RESP FPROP[%d]\n",fid);
00807 
00808     if (id>=0) { ALP_ACTION_RSP_TAG(p,id,true,false); }
00809     ALP_ACTION_RSP_F_PROP(p,fid,hdr);
00810     serial_send(WC_FLOW_ALP_RESP, tmp, (p-tmp));
00811 }
00812 
00813 public void modem_respond_read(u8 fid,void *data, u32 offset, u32 length, int id)
00814 {
00815     ALLOC_BUFFER(u8, tmp,ALP_ACTION_RSP_TAG_SIZE + ALP_ACTION_RSP_F_DATA_SIZE_MAX(length));
00816     u8* p = tmp;
00817     REF_PRINT("F_DATA[%d]@%d %d Bytes\n",fid,offset,length);
00818     if (id>=0) { ALP_ACTION_RSP_TAG(p,id,true,false); }
00819     ALP_ACTION_RSP_F_DATA(p,fid,offset,length,data);
00820     serial_send(WC_FLOW_ALP_RESP, tmp, (p-tmp));
00821     DEALLOC_BUFFER(tmp);
00822 }