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
 |