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: src/alp_helpers.cpp
- Revision:
- 19:701d5669f2e9
- Parent:
- 16:3cdc2e00f5ed
- Child:
- 26:2c934a269914
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/alp_helpers.cpp Tue Dec 12 16:03:12 2017 +0000
@@ -0,0 +1,239 @@
+/// @copyright
+/// ========================================================================={{{
+/// Copyright (c) 2012-2017 WizziLab /
+/// All rights reserved /
+/// /
+/// Should you have any questions regarding your right to use this Software, /
+/// contact WizziLab at www.wizzilab.com. /
+/// /
+/// =========================================================================}}}
+/// @endcopyright
+
+// ====================================================================
+// @file alp_helpers.c
+// @brief ALP public helpers functions.
+// This code should be disclosable in source.
+// ====================================================================
+
+
+#include "alp.h"
+
+//======================================================================
+// alp_size
+//----------------------------------------------------------------------
+/// @brief Return payload length of most ALP operations
+/// @param op : ALP Action amongst alp_opcodes_t
+/// @param offset : Associated Offset if relevant
+/// @param size : Associated Size if relevant
+/// @retval payload size in bytes
+//======================================================================
+public uint alp_size(u8 op, u32 offset, u32 length)
+{
+ uint len=2;// At least OP+FID / OP+TAG
+ switch (op)
+ {
+ case ALP_OPCODE_NOP:
+ case ALP_OPCODE_F_TOUCH:
+ case ALP_OPCODE_F_EXIST:
+ case ALP_OPCODE_F_DELETE:
+ case ALP_OPCODE_F_FLUSH:
+ case ALP_OPCODE_RSP_TAG:
+ case ALP_OPCODE_F_RD_PROP:
+ break;
+ case ALP_OPCODE_RSP_STATUS:
+ len += 1;
+ break;
+ case ALP_OPCODE_F_CREATE:
+ case ALP_OPCODE_F_DECLARE:
+ case ALP_OPCODE_RSP_F_PROP:
+ len += ALP_FILE_HEADER_SIZE;
+ break;
+ case ALP_OPCODE_F_WR_PROP:
+ case ALP_OPCODE_F_WR_DATA:
+ case ALP_OPCODE_RSP_F_DATA:
+ len = length;
+ case ALP_OPCODE_F_RD_DATA:
+ len += ALP_LFIELD_SIZE(offset) + ALP_LFIELD_SIZE(length);
+ break;
+ default:
+ //ASSERT(false,"ASSERT: ALP: alp_size unsupported op %d\n",op);
+ break;
+ }
+ return len;
+}
+
+//======================================================================
+// alp_encode_length
+//----------------------------------------------------------------------
+/// @brief Encodes an ALP length/offset field
+/// @param p : pointer to the payload buffer
+/// @param len : value to be encoded
+/// @retval resulting payload size in bytes
+//======================================================================
+public u8 alp_encode_length(u8* p, u32 len)
+{
+ if (len <= 0x3F)
+ {
+ *p++ = len;
+ return 1;
+ }
+ else if (len <= 0x3FFF)
+ {
+ *p++ = 0x40 + (u8)(len >> 8);
+ *p++ = (u8)(len & 0xFF);
+ return 2;
+ }
+ else if (len <= 0x3FFFFF)
+ {
+ *p++ = 0x80 + (u8) (len >> 16);
+ *p++ = (u8)((len >> 8) & 0xFF);
+ *p++ = (u8) (len & 0xFF);
+ return 3;
+ }
+ else
+ {
+ *p++ = 0xC0 + (u8) (len >> 24);
+ *p++ = (u8)((len >> 16) & 0xFF);
+ *p++ = (u8)((len >> 8) & 0xFF);
+ *p++ = (u8) (len & 0xFF);
+ return 4;
+ }
+}
+
+
+//======================================================================
+// alp_decode_length
+//----------------------------------------------------------------------
+/// @brief Decodes an ALP length/offset field
+/// @param p : pointer to the pointer to payload buffer
+/// @param actp : pointer to ALP's Action Protocol Substitution flag
+/// Result amongst alp_actp_substitution_mode_t
+/// @retval decoded value
+//======================================================================
+public u32 alp_decode_length(u8** p, u8* actp)
+{
+ u32 tmp = 0;
+ switch ((**p) & 0xC0)
+ {
+ case 0xC0: // 0xCx xx xx xx
+ tmp = ((*(*p)++) & 0x3F) << 24;
+ tmp += (*(*p)++) << 16;
+ tmp += (*(*p)++) << 8;
+ tmp += (*(*p)++) << 0;
+ break;
+ case 0x80: // 0x8x xx xx : 16384 <= Len <4194303
+ tmp = ((*(*p)++) & 0x3F) << 16;
+ tmp += (*(*p)++) << 8;
+ if (tmp == 0)
+ {
+ // 0x8000 ActP special ActP code
+ // Do not fetch the extra byte
+ *actp = 2;
+ }
+ else
+ {
+ tmp += (*(*p)++) << 0;
+ }
+ break;
+ case 0x40: // 0x4x xx : 64 <= Len < 16383
+ tmp = ((*(*p)++) & 0x3F) << 8;
+ tmp += (*(*p)++) << 0;
+ if (tmp == 0)
+ {
+ // 0x4000 ActP special ActP code
+ *actp = 1;
+ }
+ break;
+ case 0: // Len <63
+ tmp = (*(*p)++ & 0x3F) << 0;
+ break;
+ }
+ return tmp;
+}
+
+
+//======================================================================
+// alp_parse_chunk
+//----------------------------------------------------------------------
+/// @brief Parses an ALP payload and extract a single chunk (action or
+/// response) to a more generic alp_parsed_chunk_t structure.
+/// @param payload : pointer to the pointer to payload buffer
+/// @param resp : pointer to alp_parsed_chunk_t structure
+/// @retval number of parsed bytes
+//======================================================================
+public int alp_parse_chunk(u8** payload, alp_parsed_chunk_t* resp) // {{{
+{
+ u8* p = *payload;
+ u8 op = *p++;
+ u8 actp;
+ u32 bytes;
+ resp->type = op & 0x3F;
+ resp->data = (u8*)NULL;
+ switch(resp->type) // XXX preemption bits squashed
+ {
+ case ALP_OPCODE_RSP_TAG:
+ case ALP_OPCODE_TAG:
+ resp->meta.tag.id = *p++; // PID
+ resp->meta.tag.eop = !!(op & ALP_OPCODE_EOP);
+ resp->meta.tag.err = !!(op & ALP_OPCODE_ERR);
+ break;
+ case ALP_OPCODE_RSP_F_DATA:
+ case ALP_OPCODE_F_WR_DATA:
+ resp->meta.f_data.fid = *p++; // FID
+ resp->meta.f_data.offset = alp_decode_length(&p,&actp); // Offset
+ resp->meta.f_data.length = alp_decode_length(&p,&actp); // Length
+ resp->data = p;
+ p += resp->meta.f_data.length;
+ break;
+ case ALP_OPCODE_F_RD_DATA:
+ resp->meta.f_data.fid = *p++; // FID
+ resp->meta.f_data.offset = alp_decode_length(&p,&actp); // Offset
+ resp->meta.f_data.length = alp_decode_length(&p,&actp); // Length
+ break;
+ case ALP_OPCODE_F_RD_PROP:
+ resp->meta.f_prop.fid = *p++; // FID
+ resp->meta.f_prop.offset = 0;
+ resp->meta.f_prop.length = ALP_FILE_HEADER_SIZE; // Hardcoded Length
+ break;
+ case ALP_OPCODE_RSP_F_PROP:
+ resp->meta.f_prop.fid = *p++; // FID
+ resp->meta.f_prop.offset = 0;
+ resp->meta.f_prop.length = ALP_FILE_HEADER_SIZE; // Hardcoded Length
+ resp->data = p;
+ p += resp->meta.f_prop.length;
+ break;
+ case ALP_OPCODE_RSP_STATUS:
+ if (op == ALP_OPCODE_RSP_ISTATUS)
+ {
+ resp->type = ALP_OPCODE_RSP_ISTATUS;
+ resp->meta.itf.type = *p++; // ITF Type
+ resp->meta.itf.length = alp_decode_length(&p,&actp); // Length
+ resp->data = p;
+ p += resp->meta.itf.length;
+ }
+ else
+ {
+ resp->meta.status.id = *p++; // Action ID
+ resp->meta.status.code = *p++; // status
+ }
+ break;
+ case ALP_OPCODE_RSP_URC:
+ resp->meta.urc.type = *p++; // Type
+ resp->meta.urc.ifid = *p++; // Ifid
+ if (resp->meta.urc.type == ALP_URC_TYPE_LQUAL)
+ resp->meta.urc.per = *p++; // Per
+ break;
+ case ALP_OPCODE_F_DELETE:
+ case ALP_OPCODE_F_FLUSH:
+ resp->meta.f_data.fid = *p++; // FID
+ break;
+ default:
+ resp->type = ALP_OPCODE_UNKNOWN;
+ *payload = (u8*)NULL;
+ return 0;
+ }
+ bytes = p - *payload;
+ *payload = p;
+ return bytes;
+} // }}}
+