Exportable version of WizziLab's modem driver.
src/alp_payload.cpp
- Committer:
- marin_wizzi
- Date:
- 2021-10-29
- Revision:
- 67:e458db8402dc
- Parent:
- 65:c7749f9b6009
File content as of revision 67:e458db8402dc:
/// @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" #include "WizziDebug.h" static int32_t g_payload_nb = 0; alp_payload_t* alp_payload_new(u32 size) { alp_payload_t* alp = (alp_payload_t*)MALLOC(sizeof(alp_payload_t) - 1 + size); alp->len = 0; alp->next = NULL; g_payload_nb++; return alp; } void alp_payload_free(alp_payload_t* alp) { while (NULL != alp) { alp_payload_t* alp_next = alp->next; FREE(alp); g_payload_nb--; alp = alp_next; } } void alp_payload_print_nb(void) { PRINT("ALP: %d payloads assigned\n", g_payload_nb); } //====================================================================== // alp_payload_append //---------------------------------------------------------------------- /// @brief Appends ALP payload 2 after payload 1 /// @param alp_payload_t* Payload 1 /// @param alp_payload_t* Payload 2 /// @return alp_payload_t* Appended payloads /// @note: XXX payloads MUST be malloced //====================================================================== alp_payload_t* alp_payload_append(alp_payload_t* alp_1, alp_payload_t* alp_2) { alp_payload_t* alp = alp_1; if (NULL == alp_1) { return alp_2; } if (NULL == alp_2) { return alp_1; } while (NULL != alp) { if (NULL == alp->next) { alp->next = alp_2; return alp_1; } alp = alp->next; } return alp_1; } void alp_payload_print(alp_payload_t* alp) { u32 action = 0; u32 i; while (NULL != alp) { PRINT("ALP[%d]: (0x%x)", action, alp); PRINT_DATA("", " %02X", alp->d, alp->len, "\n"); FLUSH(); action++; alp = alp->next; } PRINT("---\n"); } u32 alp_payload_to_buf(alp_payload_t* alp, u8* buf, u32 max) { u32 offset = 0; while (NULL != alp) { // End of payload ALP_ASSERT((offset + alp->len) <= max, "ALP payload too big for buffer (%d\%d)\n", offset + alp->len, max); // Copy into buffer memcpy(&(buf[offset]), alp->d, alp->len); offset += alp->len; alp = alp->next; } return offset; } //====================================================================== // alp_payload_root_auth //---------------------------------------------------------------------- /// @brief Add the root access request to the given payload using the authentication protocol /// @param alp alp_payload_t* Payload /// @return alp_payload_t* Root access request + payload /// @note: XXX payloads MUST be malloced //====================================================================== alp_payload_t* alp_payload_root_auth(alp_payload_t* alp, u8* root_key) { u8* p; alp_payload_t* new_alp; alp_payload_t* alp_hash = alp; u8 hash[32]; // Calculate hash on payload kal_sha256_init(); while (NULL != alp_hash) { kal_sha256_update(alp_hash->d, alp_hash->len); alp_hash = alp_hash->next; } kal_sha256_update(root_key, D7A_FS_ROOT_KEY_SIZE); kal_sha256_final(hash); new_alp = alp_payload_new(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_payload_append(new_alp, alp); } //====================================================================== // alp_payload_root_sign //---------------------------------------------------------------------- /// @brief Sign payload with root key /// @param alp alp_payload_t* Payload /// @param iv u8* Initialization vector /// @return alp_payload_t* Root access request + payload /// @note: XXX payloads MUST be malloced //====================================================================== alp_payload_t* alp_payload_root_sign(alp_payload_t* alp, u8* root_key, u8* iv) { u8* p; alp_payload_t* new_alp; alp_payload_t* alp_hash = alp; u8 hash[32]; // Calculate hash on payload kal_sha256_init(); while (NULL != alp_hash) { kal_sha256_update(alp_hash->d, alp_hash->len); alp_hash = alp_hash->next; } 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_payload_new(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_payload_append(new_alp, alp); } #if 0 //====================================================================== // alp_payload_root_auth_enc //---------------------------------------------------------------------- /// @brief Add the root access request to the given payload and encrypt using the challenge protocol /// @param alp alp_payload_t* Payload /// @param challenge u8* 32-byte challenge /// @return alp_payload_t* Root access request + encrypted payload /// @note: XXX payloads MUST be malloced //====================================================================== alp_payload_t* alp_payload_root_auth_enc(alp_payload_t* alp, u8* root_key, u8* challenge) { u8* p; alp_payload_t* new_alp; alp_payload_t* alp_hash = alp; u8 hash[32]; // encrypt u8 key[D7A_FS_ROOT_KEY_SIZE]; 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(); while (NULL != alp_hash) { kal_sha256_update(alp_hash->d, alp_hash->len); alp_hash = alp_hash->next; } kal_sha256_update(root_key, D7A_FS_ROOT_KEY_SIZE); kal_sha256_update(challenge, 32); kal_sha256_final(hash); new_alp = alp_payload_new(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_payload_append(new_alp, alp); } #endif //====================================================================== // alp_payload_rsp_f_data //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_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_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_payload_t* alp_payload_rsp_f_data(alp_payload_t* alp, u8 fid, void* data, u32 offset, u32 length) { u8* p; alp_payload_t* new_alp; new_alp = alp_payload_new(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_payload_append(alp, new_alp); } //====================================================================== // alp_payload_qbreak //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_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_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_payload_t* alp_payload_qbreak(alp_payload_t* alp, u8 fid, void* data, u32 offset, u32 length, u8 group) { u8* p; alp_payload_t* new_alp; u8 mask = 0; new_alp = alp_payload_new(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_payload_append(alp, new_alp); } static alp_payload_t* _alp_payload_qbreak_comp(alp_payload_t* alp, u8 fid, u32 mask, u32 data, u32 offset, u32 length, u8 group, u8 comp) { u8* p; alp_payload_t* new_alp; new_alp = alp_payload_new(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_payload_append(alp, new_alp); } alp_payload_t* alp_payload_qbreak_eq(alp_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_payload_t* alp_payload_qbreak_ne(alp_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_payload_t* alp_payload_qbreak_gt(alp_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_payload_t* alp_payload_qbreak_gte(alp_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_payload_t* alp_payload_qbreak_lt(alp_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_payload_t* alp_payload_qbreak_lte(alp_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_payload_t* alp_payload_qbreak_eq_msk(alp_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_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_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_payload_t* alp_payload_query(alp_payload_t* alp, u8 fid, void* data, u32 offset, u32 length, u8 group) { u8* p; alp_payload_t* new_alp; u8 mask = 0; new_alp = alp_payload_new(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_payload_append(alp, new_alp); } //====================================================================== // alp_payload_nop //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_payload_t* Payload to append the ALP message to. A new payload will be malloc'ed if NULL /// @return alp_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_payload_t* alp_payload_nop(alp_payload_t* alp, u8 group) { u8* p; alp_payload_t* new_alp; new_alp = alp_payload_new(ALP_ACTION_NOP_SIZE); p = new_alp->d; ALP_ACTION_NOP(p, true, group); // 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_payload_append(alp, new_alp); } //====================================================================== // alp_payload_f_touch //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_payload_t* Payload to append the ALP message to. A new payload will be malloc'ed if NULL /// @return alp_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_payload_t* alp_payload_f_touch(alp_payload_t* alp, u8 fid, u32 offset, u32 length, u8 group) { u8* p; alp_payload_t* new_alp; new_alp = alp_payload_new(ALP_ACTION_F_TOUCH_SIZE(offset, length)); p = new_alp->d; ALP_ACTION_F_TOUCH(p, true, fid, offset, length, group); new_alp->len = (u32)(p - new_alp->d); return alp_payload_append(alp, new_alp); } //====================================================================== // alp_payload_f_wr_data //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_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_payload_t* New ALP payload /// @revent NONE //====================================================================== static alp_payload_t* _alp_payload_f_wr_data_resp(alp_payload_t* alp, u8 fid, void* data, u32 offset, u32 length, u8 group, u8 resp) { u8* p; alp_payload_t* new_alp; new_alp = alp_payload_new(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_payload_append(alp, new_alp); } alp_payload_t* alp_payload_f_wr_data(alp_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_payload_t* alp_payload_f_wr_data_nr(alp_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_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_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_payload_t* alp_payload_f_rd_data(alp_payload_t* alp, u8 fid, u32 offset, u32 length, u8 group) { u8* p; alp_payload_t* new_alp; new_alp = alp_payload_new(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_payload_append(alp, new_alp); } //====================================================================== // alp_payload_f_flush //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_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_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_payload_t* alp_payload_f_flush(alp_payload_t* alp, u8 fid, u8 group) { u8* p; alp_payload_t* new_alp; new_alp = alp_payload_new(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_payload_append(alp, new_alp); } //====================================================================== // alp_payload_f_flush //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_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_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_payload_t* alp_payload_f_declare(alp_payload_t* alp, u8 fid, alp_file_header_t* hdr) { u8* p; alp_payload_t* new_alp; new_alp = alp_payload_new(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_payload_append(alp, new_alp); } //====================================================================== // alp_payload_forward //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_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_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_payload_t* alp_payload_forward(alp_payload_t* alp, void* itf) { u8* p; alp_payload_t* new_alp; u32 itf_length = alp_itf_size(itf); new_alp = alp_payload_new(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_payload_append(alp, new_alp); } //====================================================================== // alp_payload_tag //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_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_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_payload_t* alp_payload_tag(alp_payload_t* alp, u8 tag) { u8* p; alp_payload_t* new_alp; new_alp = alp_payload_new(ALP_ACTION_TAG_SIZE); p = new_alp->d; ALP_ACTION_TAG(p, tag, true); new_alp->len = (u32)(p - new_alp->d); return alp_payload_append(alp, new_alp); } //====================================================================== // alp_payload_tag //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_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_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_payload_t* alp_payload_rsp_tag(alp_payload_t* alp, u8 tag, u8 eop, u8 err) { u8* p; alp_payload_t* new_alp; new_alp = alp_payload_new(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_payload_append(alp, new_alp); } //====================================================================== // alp_payload_tag //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_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_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_payload_t* alp_payload_rsp_status(alp_payload_t* alp, u8 action, s8 status) { u8* p; alp_payload_t* new_alp; new_alp = alp_payload_new(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_payload_append(alp, new_alp); } //====================================================================== // alp_payload_tag //---------------------------------------------------------------------- /// @brief Creates malloc'ed ALP payload /// @param alp alp_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_payload_t* New ALP payload /// @revent NONE //====================================================================== alp_payload_t* alp_payload_rsp_fprop(alp_payload_t* alp, u8 fid, alp_file_header_t* hdr) { u8* p; alp_payload_t* new_alp; new_alp = alp_payload_new(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_payload_append(alp, new_alp); } alp_payload_t* alp_payload_activate_itf(alp_payload_t* alp, u8 type, u8 nb_dev, u8 ifid, u8 flags, u8 enable) { u8* p; alp_payload_t* new_alp; new_alp = alp_payload_new(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_payload_append(alp, new_alp); } alp_payload_t* alp_payload_urcc_en(alp_payload_t* alp, u8 type, u8 ifid, u8 val) { u8* p; alp_payload_t* new_alp; new_alp = alp_payload_new(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_payload_append(alp, new_alp); } alp_payload_t* alp_payload_extract(alp_payload_t** alp, u8 op) { if (NULL == *alp) { return NULL; } if ((*alp)->d[0] == op) { // Save alp alp_payload_t* alp_old = *alp; // Remove it from chain *alp = alp_old->next; alp_old->next = NULL; // Return it return alp_old; } return alp_payload_extract((alp_payload_t**)&((*alp)->next), op); } alp_payload_t* alp_payload_get(alp_payload_t* alp, u8 op) { while (NULL != alp) { if (alp->d[0] == op) { // Return it return alp; } alp = alp->next; } return NULL; } bool alp_payload_extract_data(alp_payload_t** alp, u8 op, void* data) { alp_payload_t* alp_data = alp_payload_extract(alp, op); if (alp_data) { alp_parsed_chunk_t r; alp_payload_parse_chunk(alp_data, &r); switch (op) { case ALP_OPCODE_RSP_ISTATUS: memcpy(data, r.data, r.meta.itf.length); break;; case ALP_OPCODE_RSP_F_DATA: memcpy(data, r.data, r.meta.f_data.length); break; default: alp_payload_free(alp_data); return false; break; } alp_payload_free(alp_data); return true; } return false; } enum { ERR_PRIO_EOPISTATUS, ERR_PRIO_STATUS, ERR_PRIO_TAG, ERR_PRIO_NONE, }; int alp_payload_get_err(alp_payload_t* alp) { int err = ALP_ERR_NONE; uint8_t err_prio = ERR_PRIO_NONE; alp_parsed_chunk_t r; while (NULL != alp) { switch (alp->d[0]) { case ALP_OPCODE_RSP_TAG: // Fallthrough case ALP_OPCODE_RSP_EOPTAG: // Fallthrough case ALP_OPCODE_RSP_ERRTAG: { alp_payload_parse_chunk(alp, &r); if (ERR_PRIO_TAG < err_prio && r.meta.tag.err) { err = ALP_ERR_UNKNOWN; err_prio = ERR_PRIO_TAG; } break; } case ALP_OPCODE_RSP_STATUS: { alp_payload_parse_chunk(alp, &r); if (ERR_PRIO_STATUS < err_prio && r.meta.status.code < ALP_ERR_NONE) { err = r.meta.status.code; err_prio = ERR_PRIO_STATUS; } break; } case ALP_OPCODE_RSP_EOPISTATUS: { alp_payload_parse_chunk(alp, &r); if (ERR_PRIO_EOPISTATUS < err_prio && r.meta.istatus.err < ALP_ERR_NONE) { err = r.meta.istatus.err + ALP_ERR_ITF_START; err_prio = ERR_PRIO_EOPISTATUS; } break; } default: break; } alp = alp->next; } return err; } int alp_payload_parse_chunk(alp_payload_t* alp, alp_parsed_chunk_t* r) { if (NULL == alp) { return 0; } uint8_t* p = alp->d; return alp_parse_chunk(&p, r); } alp_payload_t* alp_payload_parse(u8* d, int length) { u8* data_start; int len; alp_parsed_chunk_t r; alp_payload_t* alp = NULL; alp_payload_t* alp_new = NULL; while (length > 0) { data_start = d; len = (int)alp_parse_chunk(&d, &r); // Malloc payload alp_new = alp_payload_new(len); // Fill payload alp_new->len = len; memcpy(alp_new->d, data_start, len); alp = alp_payload_append(alp, alp_new); length -= len; } return alp; }