238 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			238 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /****************************************************************************
 | |
| 
 | |
| 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 |