Exportable version of WizziLab's modem driver.

Dependents:   modem_ref_helper

Committer:
Jeej
Date:
Tue Dec 12 16:03:12 2017 +0000
Revision:
19:701d5669f2e9
Parent:
alp_helpers.cpp@16:3cdc2e00f5ed
Child:
26:2c934a269914
Updated for modem v4.13.x

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jeej 0:027760f45e2c 1 /// @copyright
Jeej 0:027760f45e2c 2 /// ========================================================================={{{
Jeej 0:027760f45e2c 3 /// Copyright (c) 2012-2017 WizziLab /
Jeej 0:027760f45e2c 4 /// All rights reserved /
Jeej 0:027760f45e2c 5 /// /
Jeej 0:027760f45e2c 6 /// Should you have any questions regarding your right to use this Software, /
Jeej 0:027760f45e2c 7 /// contact WizziLab at www.wizzilab.com. /
Jeej 0:027760f45e2c 8 /// /
Jeej 0:027760f45e2c 9 /// =========================================================================}}}
Jeej 0:027760f45e2c 10 /// @endcopyright
Jeej 0:027760f45e2c 11
Jeej 0:027760f45e2c 12 // ====================================================================
Jeej 0:027760f45e2c 13 // @file alp_helpers.c
Jeej 0:027760f45e2c 14 // @brief ALP public helpers functions.
Jeej 0:027760f45e2c 15 // This code should be disclosable in source.
Jeej 0:027760f45e2c 16 // ====================================================================
Jeej 0:027760f45e2c 17
Jeej 0:027760f45e2c 18
Jeej 0:027760f45e2c 19 #include "alp.h"
Jeej 0:027760f45e2c 20
Jeej 0:027760f45e2c 21 //======================================================================
Jeej 0:027760f45e2c 22 // alp_size
Jeej 0:027760f45e2c 23 //----------------------------------------------------------------------
Jeej 0:027760f45e2c 24 /// @brief Return payload length of most ALP operations
Jeej 0:027760f45e2c 25 /// @param op : ALP Action amongst alp_opcodes_t
Jeej 0:027760f45e2c 26 /// @param offset : Associated Offset if relevant
Jeej 0:027760f45e2c 27 /// @param size : Associated Size if relevant
Jeej 0:027760f45e2c 28 /// @retval payload size in bytes
Jeej 0:027760f45e2c 29 //======================================================================
Jeej 0:027760f45e2c 30 public uint alp_size(u8 op, u32 offset, u32 length)
Jeej 0:027760f45e2c 31 {
Jeej 0:027760f45e2c 32 uint len=2;// At least OP+FID / OP+TAG
Jeej 0:027760f45e2c 33 switch (op)
Jeej 0:027760f45e2c 34 {
Jeej 0:027760f45e2c 35 case ALP_OPCODE_NOP:
Jeej 0:027760f45e2c 36 case ALP_OPCODE_F_TOUCH:
Jeej 0:027760f45e2c 37 case ALP_OPCODE_F_EXIST:
Jeej 0:027760f45e2c 38 case ALP_OPCODE_F_DELETE:
Jeej 0:027760f45e2c 39 case ALP_OPCODE_F_FLUSH:
Jeej 0:027760f45e2c 40 case ALP_OPCODE_RSP_TAG:
Jeej 0:027760f45e2c 41 case ALP_OPCODE_F_RD_PROP:
Jeej 0:027760f45e2c 42 break;
Jeej 0:027760f45e2c 43 case ALP_OPCODE_RSP_STATUS:
Jeej 0:027760f45e2c 44 len += 1;
Jeej 0:027760f45e2c 45 break;
Jeej 0:027760f45e2c 46 case ALP_OPCODE_F_CREATE:
Jeej 0:027760f45e2c 47 case ALP_OPCODE_F_DECLARE:
Jeej 0:027760f45e2c 48 case ALP_OPCODE_RSP_F_PROP:
Jeej 0:027760f45e2c 49 len += ALP_FILE_HEADER_SIZE;
Jeej 0:027760f45e2c 50 break;
Jeej 0:027760f45e2c 51 case ALP_OPCODE_F_WR_PROP:
Jeej 0:027760f45e2c 52 case ALP_OPCODE_F_WR_DATA:
Jeej 0:027760f45e2c 53 case ALP_OPCODE_RSP_F_DATA:
Jeej 0:027760f45e2c 54 len = length;
Jeej 0:027760f45e2c 55 case ALP_OPCODE_F_RD_DATA:
Jeej 0:027760f45e2c 56 len += ALP_LFIELD_SIZE(offset) + ALP_LFIELD_SIZE(length);
Jeej 0:027760f45e2c 57 break;
Jeej 0:027760f45e2c 58 default:
Jeej 0:027760f45e2c 59 //ASSERT(false,"ASSERT: ALP: alp_size unsupported op %d\n",op);
Jeej 0:027760f45e2c 60 break;
Jeej 0:027760f45e2c 61 }
Jeej 0:027760f45e2c 62 return len;
Jeej 0:027760f45e2c 63 }
Jeej 0:027760f45e2c 64
Jeej 0:027760f45e2c 65 //======================================================================
Jeej 0:027760f45e2c 66 // alp_encode_length
Jeej 0:027760f45e2c 67 //----------------------------------------------------------------------
Jeej 0:027760f45e2c 68 /// @brief Encodes an ALP length/offset field
Jeej 0:027760f45e2c 69 /// @param p : pointer to the payload buffer
Jeej 0:027760f45e2c 70 /// @param len : value to be encoded
Jeej 0:027760f45e2c 71 /// @retval resulting payload size in bytes
Jeej 0:027760f45e2c 72 //======================================================================
Jeej 0:027760f45e2c 73 public u8 alp_encode_length(u8* p, u32 len)
Jeej 0:027760f45e2c 74 {
Jeej 0:027760f45e2c 75 if (len <= 0x3F)
Jeej 0:027760f45e2c 76 {
Jeej 0:027760f45e2c 77 *p++ = len;
Jeej 0:027760f45e2c 78 return 1;
Jeej 0:027760f45e2c 79 }
Jeej 0:027760f45e2c 80 else if (len <= 0x3FFF)
Jeej 0:027760f45e2c 81 {
Jeej 0:027760f45e2c 82 *p++ = 0x40 + (u8)(len >> 8);
Jeej 0:027760f45e2c 83 *p++ = (u8)(len & 0xFF);
Jeej 0:027760f45e2c 84 return 2;
Jeej 0:027760f45e2c 85 }
Jeej 0:027760f45e2c 86 else if (len <= 0x3FFFFF)
Jeej 0:027760f45e2c 87 {
Jeej 0:027760f45e2c 88 *p++ = 0x80 + (u8) (len >> 16);
Jeej 0:027760f45e2c 89 *p++ = (u8)((len >> 8) & 0xFF);
Jeej 0:027760f45e2c 90 *p++ = (u8) (len & 0xFF);
Jeej 0:027760f45e2c 91 return 3;
Jeej 0:027760f45e2c 92 }
Jeej 0:027760f45e2c 93 else
Jeej 0:027760f45e2c 94 {
Jeej 0:027760f45e2c 95 *p++ = 0xC0 + (u8) (len >> 24);
Jeej 0:027760f45e2c 96 *p++ = (u8)((len >> 16) & 0xFF);
Jeej 0:027760f45e2c 97 *p++ = (u8)((len >> 8) & 0xFF);
Jeej 0:027760f45e2c 98 *p++ = (u8) (len & 0xFF);
Jeej 0:027760f45e2c 99 return 4;
Jeej 0:027760f45e2c 100 }
Jeej 0:027760f45e2c 101 }
Jeej 0:027760f45e2c 102
Jeej 0:027760f45e2c 103
Jeej 0:027760f45e2c 104 //======================================================================
Jeej 0:027760f45e2c 105 // alp_decode_length
Jeej 0:027760f45e2c 106 //----------------------------------------------------------------------
Jeej 0:027760f45e2c 107 /// @brief Decodes an ALP length/offset field
Jeej 0:027760f45e2c 108 /// @param p : pointer to the pointer to payload buffer
Jeej 0:027760f45e2c 109 /// @param actp : pointer to ALP's Action Protocol Substitution flag
Jeej 0:027760f45e2c 110 /// Result amongst alp_actp_substitution_mode_t
Jeej 0:027760f45e2c 111 /// @retval decoded value
Jeej 0:027760f45e2c 112 //======================================================================
Jeej 0:027760f45e2c 113 public u32 alp_decode_length(u8** p, u8* actp)
Jeej 0:027760f45e2c 114 {
Jeej 0:027760f45e2c 115 u32 tmp = 0;
Jeej 0:027760f45e2c 116 switch ((**p) & 0xC0)
Jeej 0:027760f45e2c 117 {
Jeej 0:027760f45e2c 118 case 0xC0: // 0xCx xx xx xx
Jeej 0:027760f45e2c 119 tmp = ((*(*p)++) & 0x3F) << 24;
Jeej 0:027760f45e2c 120 tmp += (*(*p)++) << 16;
Jeej 0:027760f45e2c 121 tmp += (*(*p)++) << 8;
Jeej 0:027760f45e2c 122 tmp += (*(*p)++) << 0;
Jeej 0:027760f45e2c 123 break;
Jeej 0:027760f45e2c 124 case 0x80: // 0x8x xx xx : 16384 <= Len <4194303
Jeej 0:027760f45e2c 125 tmp = ((*(*p)++) & 0x3F) << 16;
Jeej 0:027760f45e2c 126 tmp += (*(*p)++) << 8;
Jeej 0:027760f45e2c 127 if (tmp == 0)
Jeej 0:027760f45e2c 128 {
Jeej 0:027760f45e2c 129 // 0x8000 ActP special ActP code
Jeej 0:027760f45e2c 130 // Do not fetch the extra byte
Jeej 0:027760f45e2c 131 *actp = 2;
Jeej 0:027760f45e2c 132 }
Jeej 0:027760f45e2c 133 else
Jeej 0:027760f45e2c 134 {
Jeej 0:027760f45e2c 135 tmp += (*(*p)++) << 0;
Jeej 0:027760f45e2c 136 }
Jeej 0:027760f45e2c 137 break;
Jeej 0:027760f45e2c 138 case 0x40: // 0x4x xx : 64 <= Len < 16383
Jeej 0:027760f45e2c 139 tmp = ((*(*p)++) & 0x3F) << 8;
Jeej 0:027760f45e2c 140 tmp += (*(*p)++) << 0;
Jeej 0:027760f45e2c 141 if (tmp == 0)
Jeej 0:027760f45e2c 142 {
Jeej 0:027760f45e2c 143 // 0x4000 ActP special ActP code
Jeej 0:027760f45e2c 144 *actp = 1;
Jeej 0:027760f45e2c 145 }
Jeej 0:027760f45e2c 146 break;
Jeej 0:027760f45e2c 147 case 0: // Len <63
Jeej 0:027760f45e2c 148 tmp = (*(*p)++ & 0x3F) << 0;
Jeej 0:027760f45e2c 149 break;
Jeej 0:027760f45e2c 150 }
Jeej 0:027760f45e2c 151 return tmp;
Jeej 0:027760f45e2c 152 }
Jeej 0:027760f45e2c 153
Jeej 0:027760f45e2c 154
Jeej 0:027760f45e2c 155 //======================================================================
Jeej 0:027760f45e2c 156 // alp_parse_chunk
Jeej 0:027760f45e2c 157 //----------------------------------------------------------------------
Jeej 0:027760f45e2c 158 /// @brief Parses an ALP payload and extract a single chunk (action or
Jeej 0:027760f45e2c 159 /// response) to a more generic alp_parsed_chunk_t structure.
Jeej 0:027760f45e2c 160 /// @param payload : pointer to the pointer to payload buffer
Jeej 0:027760f45e2c 161 /// @param resp : pointer to alp_parsed_chunk_t structure
Jeej 0:027760f45e2c 162 /// @retval number of parsed bytes
Jeej 0:027760f45e2c 163 //======================================================================
Jeej 0:027760f45e2c 164 public int alp_parse_chunk(u8** payload, alp_parsed_chunk_t* resp) // {{{
Jeej 0:027760f45e2c 165 {
Jeej 0:027760f45e2c 166 u8* p = *payload;
Jeej 0:027760f45e2c 167 u8 op = *p++;
Jeej 0:027760f45e2c 168 u8 actp;
Jeej 0:027760f45e2c 169 u32 bytes;
Jeej 0:027760f45e2c 170 resp->type = op & 0x3F;
Jeej 0:027760f45e2c 171 resp->data = (u8*)NULL;
Jeej 0:027760f45e2c 172 switch(resp->type) // XXX preemption bits squashed
Jeej 0:027760f45e2c 173 {
Jeej 0:027760f45e2c 174 case ALP_OPCODE_RSP_TAG:
Jeej 0:027760f45e2c 175 case ALP_OPCODE_TAG:
Jeej 0:027760f45e2c 176 resp->meta.tag.id = *p++; // PID
Jeej 0:027760f45e2c 177 resp->meta.tag.eop = !!(op & ALP_OPCODE_EOP);
Jeej 0:027760f45e2c 178 resp->meta.tag.err = !!(op & ALP_OPCODE_ERR);
Jeej 0:027760f45e2c 179 break;
Jeej 0:027760f45e2c 180 case ALP_OPCODE_RSP_F_DATA:
Jeej 0:027760f45e2c 181 case ALP_OPCODE_F_WR_DATA:
Jeej 0:027760f45e2c 182 resp->meta.f_data.fid = *p++; // FID
Jeej 0:027760f45e2c 183 resp->meta.f_data.offset = alp_decode_length(&p,&actp); // Offset
Jeej 0:027760f45e2c 184 resp->meta.f_data.length = alp_decode_length(&p,&actp); // Length
Jeej 0:027760f45e2c 185 resp->data = p;
Jeej 0:027760f45e2c 186 p += resp->meta.f_data.length;
Jeej 0:027760f45e2c 187 break;
Jeej 0:027760f45e2c 188 case ALP_OPCODE_F_RD_DATA:
Jeej 0:027760f45e2c 189 resp->meta.f_data.fid = *p++; // FID
Jeej 0:027760f45e2c 190 resp->meta.f_data.offset = alp_decode_length(&p,&actp); // Offset
Jeej 0:027760f45e2c 191 resp->meta.f_data.length = alp_decode_length(&p,&actp); // Length
Jeej 0:027760f45e2c 192 break;
Jeej 0:027760f45e2c 193 case ALP_OPCODE_F_RD_PROP:
Jeej 0:027760f45e2c 194 resp->meta.f_prop.fid = *p++; // FID
Jeej 0:027760f45e2c 195 resp->meta.f_prop.offset = 0;
Jeej 0:027760f45e2c 196 resp->meta.f_prop.length = ALP_FILE_HEADER_SIZE; // Hardcoded Length
Jeej 0:027760f45e2c 197 break;
Jeej 0:027760f45e2c 198 case ALP_OPCODE_RSP_F_PROP:
Jeej 0:027760f45e2c 199 resp->meta.f_prop.fid = *p++; // FID
Jeej 0:027760f45e2c 200 resp->meta.f_prop.offset = 0;
Jeej 0:027760f45e2c 201 resp->meta.f_prop.length = ALP_FILE_HEADER_SIZE; // Hardcoded Length
Jeej 0:027760f45e2c 202 resp->data = p;
Jeej 0:027760f45e2c 203 p += resp->meta.f_prop.length;
Jeej 0:027760f45e2c 204 break;
Jeej 0:027760f45e2c 205 case ALP_OPCODE_RSP_STATUS:
Jeej 0:027760f45e2c 206 if (op == ALP_OPCODE_RSP_ISTATUS)
Jeej 0:027760f45e2c 207 {
Jeej 0:027760f45e2c 208 resp->type = ALP_OPCODE_RSP_ISTATUS;
Jeej 0:027760f45e2c 209 resp->meta.itf.type = *p++; // ITF Type
Jeej 0:027760f45e2c 210 resp->meta.itf.length = alp_decode_length(&p,&actp); // Length
Jeej 0:027760f45e2c 211 resp->data = p;
Jeej 0:027760f45e2c 212 p += resp->meta.itf.length;
Jeej 0:027760f45e2c 213 }
Jeej 0:027760f45e2c 214 else
Jeej 0:027760f45e2c 215 {
Jeej 0:027760f45e2c 216 resp->meta.status.id = *p++; // Action ID
Jeej 0:027760f45e2c 217 resp->meta.status.code = *p++; // status
Jeej 0:027760f45e2c 218 }
Jeej 0:027760f45e2c 219 break;
Jeej 0:027760f45e2c 220 case ALP_OPCODE_RSP_URC:
Jeej 0:027760f45e2c 221 resp->meta.urc.type = *p++; // Type
Jeej 0:027760f45e2c 222 resp->meta.urc.ifid = *p++; // Ifid
Jeej 0:027760f45e2c 223 if (resp->meta.urc.type == ALP_URC_TYPE_LQUAL)
Jeej 0:027760f45e2c 224 resp->meta.urc.per = *p++; // Per
Jeej 0:027760f45e2c 225 break;
Jeej 0:027760f45e2c 226 case ALP_OPCODE_F_DELETE:
Jeej 0:027760f45e2c 227 case ALP_OPCODE_F_FLUSH:
Jeej 0:027760f45e2c 228 resp->meta.f_data.fid = *p++; // FID
Jeej 0:027760f45e2c 229 break;
Jeej 0:027760f45e2c 230 default:
Jeej 0:027760f45e2c 231 resp->type = ALP_OPCODE_UNKNOWN;
Jeej 0:027760f45e2c 232 *payload = (u8*)NULL;
Jeej 0:027760f45e2c 233 return 0;
Jeej 0:027760f45e2c 234 }
Jeej 0:027760f45e2c 235 bytes = p - *payload;
Jeej 0:027760f45e2c 236 *payload = p;
Jeej 0:027760f45e2c 237 return bytes;
Jeej 0:027760f45e2c 238 } // }}}
Jeej 0:027760f45e2c 239