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
alp_helpers.cpp
- Committer:
- Jeej
- Date:
- 2017-07-18
- Revision:
- 11:a077da5fe68f
- Parent:
- 0:027760f45e2c
- Child:
- 16:3cdc2e00f5ed
File content as of revision 11:a077da5fe68f:
/// @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;
break;
}
bytes = p - *payload;
*payload = p;
return bytes;
} // }}}