Exportable version of WizziLab's modem driver.
src/alp_helpers.cpp
- Committer:
- Jeej
- Date:
- 2021-01-27
- Revision:
- 56:67e3d9608403
- Parent:
- 41:6f83174ffed4
- Child:
- 57:5444cfda9889
File content as of revision 56:67e3d9608403:
/// @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 helpers functions. // This code should be disclosable in source. // ==================================================================== #include "alp.h" #include "alp_dbg.h" #include "kal_math.h" #include "kal_crypto.h" #include "d7a_1x_fs.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 //====================================================================== 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; // Fallthrough case ALP_OPCODE_F_RD_DATA: len += ALP_LFIELD_SIZE(offset) + ALP_LFIELD_SIZE(length); break; default: //ALP_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 //====================================================================== 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 //====================================================================== 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_itf_size //---------------------------------------------------------------------- /// @brief Get size of the interface configuration /// @param itf pointer to the configuration /// @return int configuration size //====================================================================== int alp_itf_size(void* itf) { alp_itf_cfg_t* p = (alp_itf_cfg_t*)itf; switch (p->type) { case ALP_ITF_TYPE_D7A: { alp_itf_d7a_cfg_t* d7a_itf = (alp_itf_d7a_cfg_t*)itf; return (1 + alp_itf_d7a_cfg_size((u8*)&d7a_itf->cfg)); } case ALP_ITF_TYPE_COM: return sizeof(alp_itf_com_cfg_t); case ALP_ITF_TYPE_LWAN: return sizeof(alp_itf_lwan_cfg_t); default: ALP_ASSERT(FALSE, "ASSERT: ALP: Unknown ITF 0x%02X for itf size\n", p->type); break; } return 0; } //====================================================================== // 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 //====================================================================== 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 (ALP_OPCODE_RSP_ISTATUS == op) { 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 if (ALP_OPCODE_RSP_EOPISTATUS == op) { resp->type = ALP_OPCODE_RSP_EOPISTATUS; resp->meta.istatus.itf = *p++; // ITF Type p++; // Length (always 1) resp->meta.istatus.err = *p++; // Interface error } 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 } else if (resp->meta.urc.type == ALP_URC_TYPE_ITF_BUSY) { kal_ctf_t to; to.byte = *p++; // timeout resp->meta.urc.per = (to.byte == 0xff) ? MAX_U32 : kal_ctf_decode(to); } break; case ALP_OPCODE_F_DELETE: case ALP_OPCODE_F_FLUSH: resp->meta.f_data.fid = *p++; // FID break; case ALP_OPCODE_RSP_SECURED: resp->type = ALP_OPCODE_RSP_SECURED; *payload = (u8*)NULL; return 0; // XXX payload length unknown default: resp->type = ALP_OPCODE_UNKNOWN; *payload = (u8*)NULL; return 0; } bytes = p - *payload; *payload = p; return bytes; } // }}} //====================================================================== // alp_append //---------------------------------------------------------------------- /// @brief Appends ALP payload 2 after payload 1 /// @param alp_pub_payload_t* Payload 1 /// @param alp_pub_payload_t* Payload 2 /// @return alp_pub_payload_t* Appended payloads /// @note: XXX payloads MUST be malloced //====================================================================== alp_pub_payload_t* alp_append(alp_pub_payload_t* alp_1, alp_pub_payload_t* alp_2) { alp_pub_payload_t* alp; if (NULL == alp_1) { return alp_2; } if (NULL == alp_2) { return alp_1; } alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + alp_1->len + alp_2->len); alp->len = alp_1->len + alp_2->len; memcpy(alp->d, alp_1->d, alp_1->len); memcpy(&(alp->d[alp_1->len]), alp_2->d, alp_2->len); FREE(alp_1); FREE(alp_2); return alp; } void alp_payload_print(alp_pub_payload_t* alp) { if (NULL == alp) { return; } u32 i; for (i = 0; i < alp->len; i++) { PRINT("%02X ", alp->d[i]); FLUSH(); } PRINT("\n"); } //====================================================================== // alp_payload_root_auth //---------------------------------------------------------------------- /// @brief Add the root access request to the given payload using the authentication protocol /// @param alp alp_pub_payload_t* Payload /// @return alp_pub_payload_t* Root access request + payload /// @note: XXX payloads MUST be malloced //====================================================================== alp_pub_payload_t* alp_payload_root_auth(alp_pub_payload_t* alp, u8* root_key) { u8* p; alp_pub_payload_t* new_alp; u8 hash[32]; // Calculate hash on payload kal_sha256_init(); kal_sha256_update(alp->d, alp->len); kal_sha256_update(root_key, D7A_FS_ROOT_KEY_SIZE); kal_sha256_final(hash); new_alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + ALP_ACTION_PERM_REQ_SIZE(0) ); p = new_alp->d; ALP_ACTION_PERM_REQ(p, FALSE, ALP_PERM_REQ_ROOT, ALP_WIZZILAB_AUTH_PROTOCOL_ID); memcpy(p, hash, ALP_ACTION_PERM_REQ_TOKEN_SIZE); p += ALP_ACTION_PERM_REQ_TOKEN_SIZE; new_alp->len = ALP_ACTION_PERM_REQ_SIZE(0); // XXX Prepend return alp_append(new_alp, alp); } //====================================================================== // alp_payload_root_sign //---------------------------------------------------------------------- /// @brief Sign payload with root key /// @param alp alp_pub_payload_t* Payload /// @param iv u8* Initialization vector /// @return alp_pub_payload_t* Root access request + payload /// @note: XXX payloads MUST be malloced //====================================================================== alp_pub_payload_t* alp_payload_root_sign(alp_pub_payload_t* alp, u8* root_key, u8* iv) { u8* p; alp_pub_payload_t* new_alp; u8 hash[32]; // Calculate hash on payload kal_sha256_init(); kal_sha256_update(alp->d, alp->len); kal_sha256_update(root_key, D7A_FS_ROOT_KEY_SIZE); kal_sha256_update(iv, ALP_ACTION_SECURED_IV_SIZE); kal_sha256_final(hash); new_alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + ALP_ACTION_SECURED_SIZE(0) ); p = new_alp->d; ALP_ACTION_SECURED(p, ALP_SECURED_ROOT, ALP_WIZZILAB_SIGN_PROTOCOL_ID); memcpy(p, iv, ALP_ACTION_SECURED_IV_SIZE); p += ALP_ACTION_SECURED_IV_SIZE; memcpy(p, hash, ALP_ACTION_SECURED_TOKEN_SIZE); p += ALP_ACTION_SECURED_TOKEN_SIZE; new_alp->len = ALP_ACTION_SECURED_SIZE(0); // XXX Prepend return alp_append(new_alp, alp); } //====================================================================== // alp_payload_root_auth_enc //---------------------------------------------------------------------- /// @brief Add the root access request to the given payload and encrypt using the challenge protocol /// @param alp alp_pub_payload_t* Payload /// @param challenge u8* 32-byte challenge /// @return alp_pub_payload_t* Root access request + encrypted payload /// @note: XXX payloads MUST be malloced //====================================================================== alp_pub_payload_t* alp_payload_root_auth_enc(alp_pub_payload_t* alp, u8* root_key, u8* challenge) { u8* p; alp_pub_payload_t* new_alp; u8 hash[32]; // encrypt u8 key[16]; memcpy(key, root_key, D7A_FS_ROOT_KEY_SIZE); kal_xor(key, challenge, D7A_FS_ROOT_KEY_SIZE); kal_aes128_init(key); kal_aes128_ctr(alp->d, alp->len, challenge + D7A_FS_ROOT_KEY_SIZE, TRUE); // Calculate hash on payload kal_sha256_init(); kal_sha256_update(alp->d, alp->len); kal_sha256_update(root_key, D7A_FS_ROOT_KEY_SIZE); kal_sha256_update(challenge, 32); kal_sha256_final(hash); new_alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + ALP_ACTION_PERM_REQ_SIZE(0) ); p = new_alp->d; ALP_ACTION_PERM_REQ(p, FALSE, ALP_PERM_REQ_ROOT, ALP_WIZZILAB_CHAL_PROTOCOL_ID); memcpy(p, hash, ALP_ACTION_PERM_REQ_TOKEN_SIZE); p += ALP_ACTION_PERM_REQ_TOKEN_SIZE; new_alp->len = ALP_ACTION_PERM_REQ_SIZE(0); // XXX Prepend return alp_append(new_alp, alp); } //====================================================================== // alp_payload_rsp_f_data //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_pub_payload_t* Payload to append the ALP message to. A new payload will be malloc'ed if NULL /// @param fid u8 file identifier /// @param data void* file content /// @param offset u32 file offset /// @param length u32 file length /// @return alp_pub_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_pub_payload_t* alp_payload_rsp_f_data(alp_pub_payload_t* alp, u8 fid, void* data, u32 offset, u32 length) { u8* p; alp_pub_payload_t* new_alp; new_alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + ALP_ACTION_RSP_F_DATA_SIZE(offset, length) ); p = new_alp->d; ALP_ACTION_RSP_F_DATA(p, fid, offset, length, data); new_alp->len = (u32)(p - new_alp->d); return alp_append(alp, new_alp); } //====================================================================== // alp_payload_qbreak //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_pub_payload_t* Payload to append the ALP message to. A new payload will be malloc'ed if NULL /// @param fid u8 file identifier /// @param data void* file content /// @param offset u32 file offset /// @param length u32 file length /// @param group u8 group with next OP /// @return alp_pub_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_pub_payload_t* alp_payload_qbreak(alp_pub_payload_t* alp, u8 fid, void* data, u32 offset, u32 length, u8 group) { u8* p; alp_pub_payload_t* new_alp; u8 mask = 0; new_alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + ALP_ACTION_QBREAK_SIZE(offset, length, mask) ); p = new_alp->d; ALP_ACTION_QBREAK_STRTOK(p, mask, data, fid, offset, length, group); new_alp->len = (u32)(p - new_alp->d); return alp_append(alp, new_alp); } static alp_pub_payload_t* _alp_payload_qbreak_comp(alp_pub_payload_t* alp, u8 fid, u32 mask, u32 data, u32 offset, u32 length, u8 group, u8 comp) { u8* p; alp_pub_payload_t* new_alp; new_alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + ALP_ACTION_QBREAK_SIZE(offset, length, (mask)? 1 : 0) ); p = new_alp->d; ALP_ACTION_QBREAK_COMP(p, mask, data, comp, fid, offset, length, group); new_alp->len = (u32)(p - new_alp->d); return alp_append(alp, new_alp); } alp_pub_payload_t* alp_payload_qbreak_eq(alp_pub_payload_t* alp, u8 fid, u32 data, u32 offset, u32 length, u8 group) { return _alp_payload_qbreak_comp(alp, fid, 0, data, offset, length, group, ALP_QCOMP_EQ); } alp_pub_payload_t* alp_payload_qbreak_ne(alp_pub_payload_t* alp, u8 fid, u32 data, u32 offset, u32 length, u8 group) { return _alp_payload_qbreak_comp(alp, fid, 0, data, offset, length, group, ALP_QCOMP_NE); } alp_pub_payload_t* alp_payload_qbreak_gt(alp_pub_payload_t* alp, u8 fid, u32 data, u32 offset, u32 length, u8 group) { return _alp_payload_qbreak_comp(alp, fid, 0, data, offset, length, group, ALP_QCOMP_GT); } alp_pub_payload_t* alp_payload_qbreak_gte(alp_pub_payload_t* alp, u8 fid, u32 data, u32 offset, u32 length, u8 group) { return _alp_payload_qbreak_comp(alp, fid, 0, data, offset, length, group, ALP_QCOMP_GTE); } alp_pub_payload_t* alp_payload_qbreak_lt(alp_pub_payload_t* alp, u8 fid, u32 data, u32 offset, u32 length, u8 group) { return _alp_payload_qbreak_comp(alp, fid, 0, data, offset, length, group, ALP_QCOMP_LT); } alp_pub_payload_t* alp_payload_qbreak_lte(alp_pub_payload_t* alp, u8 fid, u32 data, u32 offset, u32 length, u8 group) { return _alp_payload_qbreak_comp(alp, fid, 0, data, offset, length, group, ALP_QCOMP_LTE); } alp_pub_payload_t* alp_payload_qbreak_eq_msk(alp_pub_payload_t* alp, u8 fid, u32 mask, u32 data, u32 offset, u32 length, u8 group) { return _alp_payload_qbreak_comp(alp, fid, mask, data, offset, length, group, ALP_QCOMP_EQ); } //====================================================================== // alp_payload_query //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_pub_payload_t* Payload to append the ALP message to. A new payload will be malloc'ed if NULL /// @param fid u8 file identifier /// @param data void* file content /// @param offset u32 file offset /// @param length u32 file length /// @param group u8 group with next OP /// @return alp_pub_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_pub_payload_t* alp_payload_query(alp_pub_payload_t* alp, u8 fid, void* data, u32 offset, u32 length, u8 group) { u8* p; alp_pub_payload_t* new_alp; u8 mask = 0; new_alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + ALP_ACTION_QUERY_SIZE(offset, length, mask) ); p = new_alp->d; ALP_ACTION_QUERY_STRTOK(p, mask, data, fid, offset, length, group); new_alp->len = (u32)(p - new_alp->d); return alp_append(alp, new_alp); } //====================================================================== // alp_payload_nop //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_pub_payload_t* Payload to append the ALP message to. A new payload will be malloc'ed if NULL /// @return alp_pub_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_pub_payload_t* alp_payload_nop(alp_pub_payload_t* alp) { u8* p; alp_pub_payload_t* new_alp; new_alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + ALP_ACTION_NOP_SIZE ); p = new_alp->d; ALP_ACTION_NOP(p, true); // XXX RESP always true. If we use NOP, it's to get a response (istatus). new_alp->len = (u32)(p - new_alp->d); return alp_append(alp, new_alp); } //====================================================================== // alp_payload_f_wr_data //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_pub_payload_t* Payload to append the ALP message to. A new payload will be malloc'ed if NULL /// @param fid u8 file identifier /// @param data void* file content /// @param offset u32 file offset /// @param length u32 file length /// @param group u8 group with next OP /// @return alp_pub_payload_t* New ALP payload /// @revent NONE //====================================================================== static alp_pub_payload_t* _alp_payload_f_wr_data_resp(alp_pub_payload_t* alp, u8 fid, void* data, u32 offset, u32 length, u8 group, u8 resp) { u8* p; alp_pub_payload_t* new_alp; new_alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + ALP_ACTION_F_WR_DATA_SIZE(offset, length) ); p = new_alp->d; ALP_ACTION_F_WR_DATA(p, resp, fid, offset, length, data, group); new_alp->len = (u32)(p - new_alp->d); return alp_append(alp, new_alp); } alp_pub_payload_t* alp_payload_f_wr_data(alp_pub_payload_t* alp, u8 fid, void* data, u32 offset, u32 length, u8 group) { return _alp_payload_f_wr_data_resp(alp, fid, data, offset, length, group, true); } alp_pub_payload_t* alp_payload_f_wr_data_nr(alp_pub_payload_t* alp, u8 fid, void* data, u32 offset, u32 length, u8 group) { return _alp_payload_f_wr_data_resp(alp, fid, data, offset, length, group, false); } //====================================================================== // alp_payload_f_rd_data //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_pub_payload_t* Payload to append the ALP message to. A new payload will be malloc'ed if NULL /// @param fid u8 file identifier /// @param offset u32 file offset /// @param length u32 file length /// @param group u8 group with next OP /// @return alp_pub_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_pub_payload_t* alp_payload_f_rd_data(alp_pub_payload_t* alp, u8 fid, u32 offset, u32 length, u8 group) { u8* p; alp_pub_payload_t* new_alp; new_alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + ALP_ACTION_F_RD_DATA_SIZE(offset, length) ); p = new_alp->d; ALP_ACTION_F_RD_DATA(p, true, fid, offset, length, group); new_alp->len = (u32)(p - new_alp->d); return alp_append(alp, new_alp); } //====================================================================== // alp_payload_f_flush //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_pub_payload_t* Payload to append the ALP message to. A new payload will be malloc'ed if NULL /// @param fid u8 file identifier /// @param group u8 group with next OP /// @return alp_pub_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_pub_payload_t* alp_payload_f_flush(alp_pub_payload_t* alp, u8 fid, u8 group) { u8* p; alp_pub_payload_t* new_alp; new_alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + ALP_ACTION_F_FLUSH_SIZE ); p = new_alp->d; ALP_ACTION_F_FLUSH(p, true, fid, group); new_alp->len = (u32)(p - new_alp->d); return alp_append(alp, new_alp); } //====================================================================== // alp_payload_f_flush //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_pub_payload_t* Payload to append the ALP message to. A new payload will be malloc'ed if NULL /// @param fid u8 file identifier /// @param group u8 group with next OP /// @return alp_pub_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_pub_payload_t* alp_payload_f_declare(alp_pub_payload_t* alp, u8 fid, alp_file_header_t* hdr) { u8* p; alp_pub_payload_t* new_alp; new_alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + ALP_ACTION_F_DECLARE_SIZE ); p = new_alp->d; ALP_ACTION_F_DECLARE(p, true, fid, hdr, true); new_alp->len = (u32)(p - new_alp->d); return alp_append(alp, new_alp); } //====================================================================== // alp_payload_forward //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_pub_payload_t* Payload to append the ALP message to. A new payload will be malloc'ed if NULL /// @param itf void* Forward interface /// @return alp_pub_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_pub_payload_t* alp_payload_forward(alp_pub_payload_t* alp, void* itf) { u8* p; alp_pub_payload_t* new_alp; u32 itf_length = alp_itf_size(itf); new_alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + ALP_ACTION_FORWARD_SIZE(itf_length) ); p = new_alp->d; ALP_ACTION_FORWARD(p, itf, itf_length); new_alp->len = (u32)(p - new_alp->d); return alp_append(alp, new_alp); } //====================================================================== // alp_payload_tag //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_pub_payload_t* Payload to append the ALP message to. A new payload will be malloc'ed if NULL /// @param tag u8 Tag value /// @return alp_pub_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_pub_payload_t* alp_payload_tag(alp_pub_payload_t* alp, u8 tag) { u8* p; alp_pub_payload_t* new_alp; new_alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + ALP_ACTION_TAG_SIZE ); p = new_alp->d; ALP_ACTION_TAG(p, tag, true); new_alp->len = (u32)(p - new_alp->d); return alp_append(alp, new_alp); } //====================================================================== // alp_payload_tag //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_pub_payload_t* Payload to append the ALP message to. A new payload will be malloc'ed if NULL /// @param tag u8 Tag value /// @return alp_pub_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_pub_payload_t* alp_payload_rsp_tag(alp_pub_payload_t* alp, u8 tag, u8 eop, u8 err) { u8* p; alp_pub_payload_t* new_alp; new_alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + ALP_ACTION_RSP_TAG_SIZE ); p = new_alp->d; ALP_ACTION_RSP_TAG(p, tag, eop, err); new_alp->len = (u32)(p - new_alp->d); return alp_append(alp, new_alp); } //====================================================================== // alp_payload_tag //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_pub_payload_t* Payload to append the ALP message to. A new payload will be malloc'ed if NULL /// @param tag u8 Action index /// @param tag s8 Status /// @return alp_pub_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_pub_payload_t* alp_payload_rsp_status(alp_pub_payload_t* alp, u8 action, s8 status) { u8* p; alp_pub_payload_t* new_alp; new_alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + ALP_ACTION_RSP_STATUS_SIZE ); p = new_alp->d; ALP_ACTION_RSP_STATUS(p, action, status); new_alp->len = (u32)(p - new_alp->d); return alp_append(alp, new_alp); } //====================================================================== // alp_payload_tag //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_pub_payload_t* Payload to append the ALP message to. A new payload will be malloc'ed if NULL /// @param tag u8 Action index /// @param tag s8 Status /// @return alp_pub_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_pub_payload_t* alp_payload_rsp_fprop(alp_pub_payload_t* alp, u8 fid, alp_file_header_t* hdr) { u8* p; alp_pub_payload_t* new_alp; new_alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + ALP_ACTION_RSP_F_PROP_SIZE ); p = new_alp->d; ALP_ACTION_RSP_F_PROP(p, fid, hdr); new_alp->len = (u32)(p - new_alp->d); return alp_append(alp, new_alp); } alp_pub_payload_t* alp_payload_activate_itf(alp_pub_payload_t* alp, uint8_t type, uint8_t nb_dev, uint8_t ifid, uint8_t flags, uint8_t enable) { u8* p; alp_pub_payload_t* new_alp; new_alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + ALP_ACTION_ACTIVATE_ITF_SIZE ); p = new_alp->d; ALP_ACTION_ACTIVATE_ITF(p, true, enable, type, nb_dev, ifid, flags); new_alp->len = (u32)(p - new_alp->d); return alp_append(alp, new_alp); } alp_pub_payload_t* alp_payload_urcc_en(alp_pub_payload_t* alp, uint8_t type, uint8_t ifid, uint8_t val) { u8* p; alp_pub_payload_t* new_alp; new_alp = (alp_pub_payload_t*)MALLOC(sizeof(alp_pub_payload_t) - 1 + ALP_ACTION_ACTIVATE_ITF_SIZE ); p = new_alp->d; ALP_ACTION_URCC_EN(p, true, type, ifid, val); new_alp->len = (u32)(p - new_alp->d); return alp_append(alp, new_alp); } static int _alp_payload_parse(alp_pub_payload_t* alp, u8 op, void* buffer, u8 extract) { if (NULL == alp) { return 0; } u8* p = alp->d; u8* d; int rem = alp->len; int len; alp_parsed_chunk_t r; while (rem > 0) { // Parse payload d = p; len = alp_parse_chunk(&p, &r); rem -= len; if (r.type == op) { // Extract wanted payload if (buffer) { memcpy(buffer, d, len); } if (extract) { // Remove parsed OP from total length alp->len -= len; // Shift end of payload to delete parsed OP if (rem) { memcpy(d, p, rem); } } return len; } } return 0; } int alp_payload_get(alp_pub_payload_t* alp, u8 op, void* buffer) { return _alp_payload_parse(alp, op, buffer, false); } int alp_payload_extract(alp_pub_payload_t* alp, u8 op, void* buffer) { return _alp_payload_parse(alp, op, buffer, true); }