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