/**************************************************************************** Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED. This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT be copied by any method or incorporated into another program without the express written consent of Aerospace C.Power. This Information or any portion thereof remains the property of Aerospace C.Power. The Information contained herein is believed to be accurate and Aerospace C.Power assumes no responsibility or liability for its use in any way and conveys no license or title under any patent or copyright and makes no representation or warranty that this Information is free from patent or copyright infringement. ****************************************************************************/ #include "iot_io_api.h" #include "iot_cli_module_config.h" #include "iot_cli_tx_rx.h" #include "iot_cli_host_interface.h" #include "iot_cli_ul_buf.h" #ifdef HOST_APP_FEATURE_ENABLE iot_cli_ul_buf *cli_ul_buf = NULL; extern iot_cli_t cli; /* add ul buf entry */ uint16_t cli_ul_buf_add_entry(uint32_t msgid, uint8_t *data, uint32_t len) { if (cli_ul_buf) { iot_pkt_t *pkt = NULL; if (!cli_ul_buf->active) { iot_printf("ul ack handler %lu\n", cli_ul_buf->active); } else { pkt = iot_pkt_alloc(len, IOT_CLI_MID); if (pkt) { os_mem_cpy(iot_pkt_data(pkt), data, len); iot_pkt_put(pkt, len); iot_printf("ul buf add data\n"); return cli_ul_buf_add_pkt_entry(msgid, pkt); } } } return CLI_UL_BUF_IVALID_SN; } /* add new pkt entry */ uint16_t cli_ul_buf_add_pkt_entry(uint32_t msgid, iot_pkt_t *data) { if (cli_ul_buf && data) { uint16_t idx = 0; os_acquire_mutex(cli_ul_buf->ul_buf_mutex); for (; idx < CLI_UL_BUF_SIZE; idx++) { if (cli_ul_buf->ul_buf[idx].acked || cli_ul_buf->ul_buf[idx].timeout) { cli_ul_buf->ul_buf[idx].acked = 0; cli_ul_buf->ul_buf[idx].msgid = msgid; if (cli_ul_buf->ul_buf[idx].data) { iot_pkt_free(cli_ul_buf->ul_buf[idx].data); cli_ul_buf->ul_buf[idx].data = NULL; } cli_ul_buf->ul_buf[idx].data = data; cli_ul_buf->ul_buf[idx].age = 0; cli_ul_buf->ul_buf[idx].timeout = 0; cli_ul_buf->ul_buf[idx].send_cnt = 0; cli_ul_buf->ul_buf[idx].sn = cli_ul_buf->sn; cli_ul_buf->sn++; iot_printf("ul buf add pkt entry, idx %lu sn %lu\n", idx, cli_ul_buf->ul_buf[idx].sn); break; } } os_release_mutex(cli_ul_buf->ul_buf_mutex); if (idx == CLI_UL_BUF_SIZE) { iot_pkt_free(data); iot_printf("add to ul buf failed since of buf full\n"); } else { return cli_ul_buf->ul_buf[idx].sn; } } return CLI_UL_BUF_IVALID_SN; } /* ul buf timer msg */ void iot_cli_handle_ul_buf_timer_msg() { if (cli_ul_buf) { os_acquire_mutex(cli_ul_buf->ul_buf_mutex); for (uint16_t idx = 0; idx < CLI_UL_BUF_SIZE; idx++) { if (cli_ul_buf->ul_buf[idx].acked) { if (cli_ul_buf->ul_buf[idx].data) { iot_printf("ul buf timer free acked data, sn %lu\n", cli_ul_buf->ul_buf[idx].sn); iot_pkt_free(cli_ul_buf->ul_buf[idx].data); cli_ul_buf->ul_buf[idx].data = NULL; } } else if (!cli_ul_buf->ul_buf[idx].timeout) { cli_ul_buf->ul_buf[idx].age++; // time out if (cli_ul_buf->ul_buf[idx].age == CLI_UL_BUF_MAX_AGE) { cli_ul_buf->ul_buf[idx].timeout = 1; if (cli_ul_buf->ul_buf[idx].data) { iot_printf("ul buf timer free timeout data, sn %lu\n", cli_ul_buf->ul_buf[idx].sn); iot_pkt_free(cli_ul_buf->ul_buf[idx].data); cli_ul_buf->ul_buf[idx].data = NULL; } } else if (!(cli_ul_buf->ul_buf[idx].age % CLI_UL_BUF_ACK_TIMEOUT)) { // send one more time iot_printf("ul buf timer retry sending msg, sn %lu\n", cli_ul_buf->ul_buf[idx].sn); iot_cli_send_to_host_with_sn( cli_ul_buf->ul_buf[idx].msgid, iot_pkt_data(cli_ul_buf->ul_buf[idx].data), iot_pkt_data_len(cli_ul_buf->ul_buf[idx].data), cli_ul_buf->ul_buf[idx].sn, NULL); } } } os_release_mutex(cli_ul_buf->ul_buf_mutex); } } static void cli_ul_buf_clean_all_entry() { uint16_t idx = 0; if (!cli_ul_buf) { return; } os_acquire_mutex(cli_ul_buf->ul_buf_mutex); for (; idx < CLI_UL_BUF_SIZE; idx++) { if (cli_ul_buf->ul_buf[idx].data) { iot_pkt_free(cli_ul_buf->ul_buf[idx].data); cli_ul_buf->ul_buf[idx].data = NULL; } cli_ul_buf->ul_buf[idx].acked = 0; cli_ul_buf->ul_buf[idx].msgid = 0; cli_ul_buf->ul_buf[idx].data = NULL; cli_ul_buf->ul_buf[idx].age = 0; cli_ul_buf->ul_buf[idx].timeout = 1; cli_ul_buf->ul_buf[idx].send_cnt = 0; } os_release_mutex(cli_ul_buf->ul_buf_mutex); } /* timer alive */ static void iot_cli_ul_buf_timer(timer_id_t timer_id, void *arg) { (void)timer_id; (void)arg; iot_task_msg_t *msg; msg = iot_cli_create_cli_msg(IOT_CLI_UL_BUF_TIMER, NULL); if (msg) { iot_task_queue_msg(cli.cli_task_h, msg, IOT_CLI_QUEUE_TIMER); } } /* ul ack handler */ void cli_ul_ack_handler(uint8_t *buffer, uint32_t bufferlen, uint8_t *src_mac) { (void)src_mac; cli_ul_ack *ack = (cli_ul_ack*)buffer; if ((!ack) || (bufferlen < sizeof(*ack))) { return; } iot_printf("ul ack handler %lu sn %lu\n", cli_ul_buf->active, ack->sn); if (!cli_ul_buf->active) { return; } if (cli_ul_buf) { os_acquire_mutex(cli_ul_buf->ul_buf_mutex); for (uint16_t idx = 0; idx < CLI_UL_BUF_SIZE; idx++) { if ((!cli_ul_buf->ul_buf[idx].acked) && (!cli_ul_buf->ul_buf[idx].timeout) && (cli_ul_buf->ul_buf[idx].sn == ack->sn)) { iot_printf("ul entry acked idx %lu sn %lu\n", idx, ack->sn); cli_ul_buf->ul_buf[idx].acked = 1; break; } } os_release_mutex(cli_ul_buf->ul_buf_mutex); } } /* set ul buf timer active */ void cli_set_ul_buf_active(uint8_t active) { if (cli_ul_buf) { cli_ul_buf->active = active; if (cli_ul_buf->active && (!os_is_timer_active(cli_ul_buf->timer))) { os_start_timer(cli_ul_buf->timer, CLI_UL_BUF_TIMER); } else if ((!cli_ul_buf->active) && os_is_timer_active(cli_ul_buf->timer)) { cli_ul_buf_clean_all_entry(); os_stop_timer(cli_ul_buf->timer); } } } /* init ul buf */ void iot_cli_ul_buf_init() { cli_ul_buf = (iot_cli_ul_buf *) os_mem_malloc(IOT_CLI_MID, sizeof(iot_cli_ul_buf)); if (cli_ul_buf) { os_mem_set(cli_ul_buf, 0, sizeof(cli_ul_buf)); cli_ul_buf->sn = 1; cli_ul_buf->ul_buf_mutex = os_create_mutex(IOT_CLI_MID); for (uint16_t idx = 0; idx < CLI_UL_BUF_SIZE; idx++) { cli_ul_buf->ul_buf[idx].timeout = 1; } cli_ul_buf->timer = os_create_timer(IOT_CLI_MID, 1, iot_cli_ul_buf_timer, NULL); } } #endif