WizziLab / modem_ref

Dependents:   modem_ref_helper

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers alp_helpers.cpp Source File

alp_helpers.cpp

00001 /// @copyright
00002 /// ========================================================================={{{
00003 /// Copyright (c) 2012-2017 WizziLab                                           /
00004 /// All rights reserved                                                        /
00005 ///                                                                            /
00006 /// Should you have any questions regarding your right to use this Software,   /
00007 /// contact WizziLab at www.wizzilab.com.                                      /
00008 ///                                                                            /
00009 /// =========================================================================}}}
00010 /// @endcopyright
00011 
00012 //  ====================================================================
00013 //  @file           alp_helpers.c
00014 //  @brief          ALP helpers functions.
00015 //                  This code should be disclosable in source.
00016 //  ====================================================================
00017 
00018 
00019 #include "alp.h"
00020 #include "alp_dbg.h"
00021 #include "kal_math.h"
00022 #include "kal_crypto.h"
00023 #include "d7a_1x_fs.h"
00024 
00025 #include "WizziDebug.h"
00026 
00027 //======================================================================
00028 // alp_size
00029 //----------------------------------------------------------------------
00030 /// @brief Return payload length of most ALP operations
00031 /// @param op       : ALP Action amongst alp_opcodes_t
00032 /// @param offset   : Associated Offset if relevant
00033 /// @param size     : Associated Size if relevant
00034 /// @retval payload size in bytes
00035 //======================================================================
00036 uint alp_size(u8 op, u32 offset, u32 length)
00037 {
00038     uint len=2;// At least OP+FID / OP+TAG
00039     switch (op)
00040     {
00041         case ALP_OPCODE_NOP:
00042         case ALP_OPCODE_F_TOUCH:
00043         case ALP_OPCODE_F_EXIST:
00044         case ALP_OPCODE_F_DELETE:
00045         case ALP_OPCODE_F_FLUSH:
00046         case ALP_OPCODE_RSP_TAG:
00047         case ALP_OPCODE_F_RD_PROP:
00048             break;
00049         case ALP_OPCODE_RSP_STATUS:
00050             len += 1;
00051             break;
00052         case ALP_OPCODE_F_CREATE:
00053         case ALP_OPCODE_F_DECLARE:
00054         case ALP_OPCODE_RSP_F_PROP:
00055             len += ALP_FILE_HEADER_SIZE;
00056             break;
00057         case ALP_OPCODE_F_WR_PROP:
00058         case ALP_OPCODE_F_WR_DATA:
00059         case ALP_OPCODE_RSP_F_DATA:
00060             len = length;
00061             // Fallthrough
00062         case ALP_OPCODE_F_RD_DATA:
00063             len += ALP_LFIELD_SIZE(offset) + ALP_LFIELD_SIZE(length);
00064             break;
00065         default:
00066             //ALP_ASSERT(false, "ASSERT: ALP: alp_size unsupported op %d\n", op);
00067             break;
00068     }
00069     return len;
00070 }
00071 
00072 //======================================================================
00073 // alp_encode_length
00074 //----------------------------------------------------------------------
00075 /// @brief Encodes an ALP length/offset field
00076 /// @param p        : pointer to the payload buffer
00077 /// @param len      : value to be encoded
00078 /// @retval resulting payload size in bytes
00079 //======================================================================
00080 u8 alp_encode_length(u8* p, u32 len)
00081 {
00082     if (len <= 0x3F)
00083     {
00084         *p++ = len;
00085         return 1;
00086     }
00087     else if (len <= 0x3FFF)
00088     {
00089         *p++ = 0x40 + (u8)(len >> 8);
00090         *p++ =        (u8)(len & 0xFF);
00091         return 2;
00092     }
00093     else if (len <= 0x3FFFFF)
00094     {
00095         *p++ = 0x80 + (u8) (len >> 16);
00096         *p++ =        (u8)((len >> 8) & 0xFF);
00097         *p++ =        (u8) (len       & 0xFF);
00098         return 3;
00099     }
00100     else
00101     {
00102         *p++ = 0xC0 + (u8) (len >> 24);
00103         *p++ =        (u8)((len >> 16) & 0xFF);
00104         *p++ =        (u8)((len >>  8) & 0xFF);
00105         *p++ =        (u8) (len        & 0xFF);
00106         return 4;
00107     }
00108 }
00109 
00110 
00111 //======================================================================
00112 // alp_decode_length
00113 //----------------------------------------------------------------------
00114 /// @brief Decodes an ALP length/offset field
00115 /// @param p        : pointer to the pointer to payload buffer
00116 /// @param actp     : pointer to ALP's Action Protocol Substitution flag
00117 ///                   Result amongst alp_actp_substitution_mode_t
00118 /// @retval decoded value
00119 //======================================================================
00120 u32 alp_decode_length(u8** p, u8* actp)
00121 {
00122     u32 tmp = 0;
00123     switch ((**p) & 0xC0)
00124     {
00125         case 0xC0: // 0xCx xx xx xx
00126             tmp  = ((*(*p)++) & 0x3F) << 24;
00127             tmp +=  (*(*p)++)         << 16;
00128             tmp +=  (*(*p)++)         <<  8;
00129             tmp +=  (*(*p)++)         <<  0;
00130             break;
00131         case 0x80: // 0x8x xx xx : 16384 <= Len <4194303
00132             tmp  = ((*(*p)++) & 0x3F) << 16;
00133             tmp +=  (*(*p)++)         <<  8;
00134             if (tmp == 0)
00135             {
00136                 // 0x8000 ActP special ActP code
00137                 // Do not fetch the extra byte
00138                 *actp = 2;
00139             }
00140             else
00141             {
00142                 tmp +=  (*(*p)++)     <<  0;
00143             }
00144             break;
00145         case 0x40: // 0x4x xx : 64 <= Len < 16383
00146             tmp  = ((*(*p)++) & 0x3F) <<  8;
00147             tmp +=  (*(*p)++)         <<  0;
00148             if (tmp == 0)
00149             {
00150                 // 0x4000 ActP special ActP code
00151                 *actp = 1;
00152             }
00153             break;
00154         case 0: // Len <63
00155             tmp  = (*(*p)++ & 0x3F) <<  0;
00156             break;
00157     }
00158     return tmp;
00159 }
00160 
00161 //======================================================================
00162 // alp_itf_size
00163 //----------------------------------------------------------------------
00164 /// @brief  Get size of the interface configuration
00165 /// @param  itf pointer to the configuration
00166 /// @return int configuration size
00167 //======================================================================
00168 int alp_itf_size(void* itf)
00169 {
00170     alp_itf_cfg_t* p = (alp_itf_cfg_t*)itf;
00171 
00172     switch (p->type)
00173     {
00174         case ALP_ITF_TYPE_D7A:
00175             {
00176                 alp_itf_d7a_cfg_t* d7a_itf = (alp_itf_d7a_cfg_t*)itf;
00177                 return (1 + alp_itf_d7a_cfg_size((u8*)&d7a_itf->cfg));
00178             }
00179         case ALP_ITF_TYPE_COM:
00180             return sizeof(alp_itf_com_cfg_t);
00181         case ALP_ITF_TYPE_LWAN:
00182             return sizeof(alp_itf_lwan_cfg_t);
00183         default:
00184             ALP_ASSERT(FALSE, "ASSERT: ALP: Unknown ITF 0x%02X for itf size\n", p->type);
00185             break;
00186     }
00187 
00188     return 0;
00189 }
00190 
00191 //======================================================================
00192 // alp_parse_chunk
00193 //----------------------------------------------------------------------
00194 /// @brief Parses an ALP payload and extract a single chunk (action or
00195 ///        response) to a more generic alp_parsed_chunk_t structure.
00196 /// @param payload  : pointer to the pointer to payload buffer
00197 /// @param resp     : pointer to alp_parsed_chunk_t structure
00198 /// @retval number of parsed bytes
00199 //======================================================================
00200 int alp_parse_chunk(u8** payload, alp_parsed_chunk_t* resp) // {{{
00201 {
00202     u8* p = *payload;
00203     u8 op = *p++;
00204     u8 actp;
00205     u32 bytes;
00206     resp->type = op & 0x3F;
00207     resp->data = (u8*)NULL;
00208     switch(resp->type) // XXX preemption bits squashed
00209     {
00210         case ALP_OPCODE_RSP_TAG:
00211         case ALP_OPCODE_TAG:
00212             resp->meta.tag.id  = *p++; // PID
00213             resp->meta.tag.eop = !!(op & ALP_OPCODE_EOP);
00214             resp->meta.tag.err = !!(op & ALP_OPCODE_ERR);
00215             break;
00216         case ALP_OPCODE_RSP_F_DATA:
00217         case ALP_OPCODE_F_WR_DATA:
00218             resp->meta.f_data.fid = *p++; // FID
00219             resp->meta.f_data.offset = alp_decode_length(&p, &actp); // Offset
00220             resp->meta.f_data.length = alp_decode_length(&p, &actp); // Length
00221             resp->data = p;
00222             p += resp->meta.f_data.length;
00223             break;
00224         case ALP_OPCODE_F_RD_DATA:
00225             resp->meta.f_data.fid = *p++; // FID
00226             resp->meta.f_data.offset = alp_decode_length(&p, &actp); // Offset
00227             resp->meta.f_data.length = alp_decode_length(&p, &actp); // Length
00228             break;
00229         case ALP_OPCODE_F_RD_PROP:
00230             resp->meta.f_prop.fid = *p++; // FID
00231             resp->meta.f_prop.offset = 0;
00232             resp->meta.f_prop.length = ALP_FILE_HEADER_SIZE; // Hardcoded Length
00233             break;
00234         case ALP_OPCODE_RSP_F_PROP:
00235             resp->meta.f_prop.fid = *p++; // FID
00236             resp->meta.f_prop.offset = 0;
00237             resp->meta.f_prop.length = ALP_FILE_HEADER_SIZE; // Hardcoded Length
00238             resp->data = p;
00239             p += resp->meta.f_prop.length;
00240             break;
00241         case ALP_OPCODE_RSP_STATUS:
00242             if (ALP_OPCODE_RSP_ISTATUS == op)
00243             {
00244                 resp->type = ALP_OPCODE_RSP_ISTATUS;
00245                 resp->meta.itf.type = *p++; // ITF Type
00246                 resp->meta.itf.length = alp_decode_length(&p, &actp); // Length
00247                 resp->data = p;
00248                 p += resp->meta.itf.length;
00249             }
00250             else if (ALP_OPCODE_RSP_EOPISTATUS == op)
00251             {
00252                 resp->type = ALP_OPCODE_RSP_EOPISTATUS;
00253                 resp->meta.istatus.itf = *p++; // ITF Type
00254                 p++; // Length (always 1)
00255                 resp->meta.istatus.err = *p++; // Interface error
00256             }
00257             else
00258             {
00259                 resp->meta.status.id = *p++; // Action ID
00260                 resp->meta.status.code = *p++; // status
00261             }
00262             break;
00263         case ALP_OPCODE_RSP_URC:
00264             resp->meta.urc.type = *p++; // Type
00265             resp->meta.urc.ifid = *p++; // Ifid
00266             if (resp->meta.urc.type == ALP_URC_TYPE_LQUAL)
00267             {
00268                 resp->meta.urc.per = *p++; // Per
00269             }
00270             else if (resp->meta.urc.type == ALP_URC_TYPE_ITF_BUSY)
00271             {
00272                 kal_ctf_t to;
00273                 to.byte = *p++; // timeout
00274                 resp->meta.urc.per = (to.byte == 0xff) ? MAX_U32 : kal_ctf_decode(to);
00275             }
00276             break;
00277         case ALP_OPCODE_F_DELETE:
00278         case ALP_OPCODE_F_FLUSH:
00279             resp->meta.f_data.fid = *p++; // FID
00280             break;
00281         case ALP_OPCODE_RSP_SECURED:
00282             resp->type = ALP_OPCODE_RSP_SECURED;
00283             *payload = (u8*)NULL;
00284             return 0; // XXX payload length unknown
00285         default:
00286             resp->type = ALP_OPCODE_UNKNOWN;
00287             *payload = (u8*)NULL;
00288             return 0;
00289     }
00290     bytes = p - *payload;
00291     *payload = p;
00292     return bytes;
00293 } // }}}