inwudriver-weibo/app/mrs/sta/mrs_sta_usr_tx.c

326 lines
9.1 KiB
C
Raw Permalink Normal View History

/*
* Copyright (c) CompanyNameMagicTag 2019-2020. All rights reserved.
* Description: MRS sta uart sending list.
*/
#include "mrs_sta_usr_tx.h"
#include "mrs_common_tools.h"
#include "mrs_common_uart.h"
#include "mrs_common_queue.h"
#include "mrs_common_plc.h"
#if (defined(PRODUCT_CFG_PRODUCT_TYPE_STA) && defined(MRS_USR_DEMO))
#define mrs_sta_usr_tx_notify() mrs_msg_queue_send(MRS_MSG_ID_TIMER, 0, MRS_TIMER_ID_USR_TX, 0)
typedef struct {
EXT_LIST mr_list;
td_u16 item_num;
td_u8 lock;
td_u8 rsv;
} mrs_usr_tx_queue;
td_void mrs_usr_tx_clean(td_void);
mrs_usr_tx_queue *g_usr_tx_queue;
td_u32 mrs_sta_usr_tx_queue_init(td_void)
{
if (g_usr_tx_queue == TD_NULL) {
g_usr_tx_queue = (mrs_usr_tx_queue *)mrs_malloc(sizeof(mrs_usr_tx_queue));
if (g_usr_tx_queue == TD_NULL) {
return EXT_ERR_MALLOC_FAILUE;
}
}
g_usr_tx_queue->item_num = 0;
uapi_list_init(&g_usr_tx_queue->mr_list);
mrs_lock_init(g_usr_tx_queue->lock);
mrs_timer_stop(MRS_TIMER_ID_STA_QUEUE_LOCK);
return EXT_ERR_SUCCESS;
}
td_bool mrs_sta_usr_tx(mrs_usr_tx_item *item)
{
EXT_LIST *link = TD_NULL;
mrs_usr_tx_queue *head = g_usr_tx_queue;
if ((head == TD_NULL) || (item == TD_NULL)) {
return TD_FALSE;
}
/* Remain the first one as the working one, leave it be */
for (link = head->mr_list.prev; link != head->mr_list.next; link = link->prev) {
mrs_usr_tx_item *temp = (mrs_usr_tx_item *)link;
if (item->priority <= temp->priority) {
break;
}
}
item->link.prev = link;
item->link.next = link->next;
item->link.next->prev = &item->link;
item->link.prev->next = &item->link;
head->item_num++;
mrs_sta_usr_tx_notify();
mrs_printf("[xxx Items in Queue] %d\n", head->item_num);
return TD_TRUE;
}
td_void mrs_sta_usr_tx_handle(td_void)
{
td_u32 ret;
mrs_usr_tx_item *item = TD_NULL;
mrs_usr_tx_queue *head = g_usr_tx_queue;
EXT_LIST *link = TD_NULL;
td_u16 timeout = (td_u16)item->frame_head.timeout;
if ((head == TD_NULL) || (head->item_num == 0)) {
return;
}
if (mrs_try_lock(head->lock) == 0) {
return;
}
mrs_timer_start(MRS_TIMER_ID_STA_QUEUE_LOCK, MRS_STA_MR_QUEUE_LOCK_TIME, EXT_TIMER_TYPE_ONCE);
link = ext_list_first(&head->mr_list);
item = (mrs_usr_tx_item *)link;
if (item->retry > MRS_USR_TX_MAX_RETRY) {
mrs_usr_tx_dequeue();
return;
}
item->retry++;
ret = mrs_uart_tx(item->data, item->data_len);
if (ret != EXT_ERR_SUCCESS) {
mrs_usr_tx_dequeue();
return;
}
/* timeout == 0 means not need response. by default ,timer equal to 10 ms */
mrs_timer_start(MRS_TIMER_ID_USR_QUEUE, timeout * 1000, EXT_TIMER_TYPE_ONCE); /* time * 1000 */
}
td_void mrs_sta_usr_tx_unlock(td_void)
{
if (g_usr_tx_queue == TD_NULL) {
return;
}
/* Delete invalid ones */
mrs_usr_tx_dequeue();
}
mrs_usr_tx_item *mrs_sta_usr_get_tx_item(td_void)
{
EXT_LIST *link = TD_NULL;
mrs_usr_tx_queue *head = g_usr_tx_queue;
if (head == TD_NULL) {
return TD_NULL;
}
if (head->item_num > 0) {
link = ext_list_first(&head->mr_list);
return (mrs_usr_tx_item *)link;
}
return TD_NULL;
}
td_void mrs_usr_tx_dequeue(td_void)
{
mrs_usr_tx_queue *head = g_usr_tx_queue;
if (head == TD_NULL) {
return;
}
if (head->item_num > 0) {
mrs_usr_tx_item *temp = (mrs_usr_tx_item *)ext_list_first(&head->mr_list);
uapi_list_delete(&temp->link);
mrs_free(temp);
head->item_num--;
}
mrs_unlock(head->lock);
mrs_timer_stop(MRS_TIMER_ID_STA_QUEUE_LOCK);
mrs_sta_usr_tx_notify();
}
td_void mrs_usr_tx_clean(td_void)
{
mrs_usr_tx_queue *head = g_usr_tx_queue;
if (head == TD_NULL) {
return;
}
while (head->item_num > 0) {
mrs_usr_tx_item *temp = (mrs_usr_tx_item *)ext_list_first(&head->mr_list);
uapi_list_delete(&temp->link);
mrs_free(temp);
head->item_num--;
}
}
td_bool mrs_sta_usr_plc_filter(mrs_sta_usr_frame_head *head)
{
mrs_usr_tx_queue *queue = g_usr_tx_queue;
EXT_LIST *link = TD_NULL;
if ((queue == TD_NULL) || (queue->item_num == 0)) {
return TD_FALSE;
}
if (head == TD_NULL) {
return TD_FALSE;
}
for (link = queue->mr_list.prev; link != &queue->mr_list; link = link->prev) {
mrs_usr_tx_item *temp = (mrs_usr_tx_item *)link;
if ((temp->frame_head.seq == head->seq) && (temp->frame_head.id == head->id) &&
(memcmp(temp->frame_head.addr, head->addr, sizeof(head->addr)) == 0)) {
return TD_TRUE;
}
}
return TD_FALSE;
}
td_u32 mrs_sta_usr_xr_plc_tx(mrs_usr_tx_item *item, td_pbyte data, td_u16 data_len)
{
td_u16 payload_len = sizeof(mrs_plc_frame_data) + sizeof(mrs_data_transmit_xr) + data_len;
td_pbyte payload;
mrs_plc_frame_data *plc = TD_NULL;
mrs_data_transmit_xr *xr = TD_NULL;
mrs_sta_usr_frame_head *head = TD_NULL;
if ((item == TD_NULL) || (data == TD_NULL) || (data_len == 0)) {
return EXT_ERR_INVALID_PARAMETER;
}
payload = mrs_malloc(payload_len);
if (payload == TD_NULL) {
return EXT_ERR_MALLOC_FAILUE;
}
(td_void) memset_s(payload, payload_len, 0, payload_len);
plc = (mrs_plc_frame_data *)payload;
head = &item->frame_head;
(td_void) memcpy_s(plc->addr, sizeof(plc->addr), head->addr, sizeof(head->addr));
plc->id = head->id;
plc->payload_len = sizeof(mrs_data_transmit_xr) + data_len;
plc->payload = payload + sizeof(mrs_plc_frame_data);
xr = (mrs_data_transmit_xr *)plc->payload;
xr->stru_ver = MRS_PLC_PROTO_VERSION;
xr->stru_size = sizeof(mrs_data_transmit_xr);
xr->dir = MRS_PLC_UP_FLG;
xr->protocol = head->protocol;
xr->seq = head->seq;
xr->data_len = data_len;
(td_void) memcpy_s(xr->data, xr->data_len, data, data_len);
mrs_plc_frame_send(plc);
mrs_free(payload);
return EXT_ERR_SUCCESS;
}
td_u32 mrs_sta_usr_pr_plc_tx(mrs_usr_tx_item *item, td_pbyte data, td_u16 data_len)
{
td_u16 payload_len = sizeof(mrs_plc_frame_data) + sizeof(mrs_data_transmit_pr_up) + data_len;
td_pbyte payload;
mrs_plc_frame_data *plc = TD_NULL;
mrs_data_transmit_pr_up *pr = TD_NULL;
mrs_sta_usr_frame_head *head = TD_NULL;
if ((item == TD_NULL) || (data == TD_NULL) || (data_len == 0)) {
return EXT_ERR_INVALID_PARAMETER;
}
payload = mrs_malloc(payload_len);
if (payload == TD_NULL) {
return EXT_ERR_MALLOC_FAILUE;
}
(td_void) memset_s(payload, payload_len, 0, payload_len);
plc = (mrs_plc_frame_data *)payload;
head = &item->frame_head;
(td_void) memcpy_s(plc->addr, sizeof(plc->addr), head->addr, sizeof(head->addr));
plc->id = head->id;
plc->payload_len = sizeof(mrs_data_transmit_xr) + data_len;
plc->payload = payload + sizeof(mrs_plc_frame_data);
pr = (mrs_data_transmit_pr_up *)plc->payload;
pr->stru_ver = MRS_PLC_PROTO_VERSION;
pr->stru_size = sizeof(mrs_data_transmit_xr);
pr->protocol = head->protocol;
pr->seq = head->seq;
pr->data_len = data_len;
(td_void) memcpy_s(pr->data, pr->data_len, data, data_len);
mrs_plc_frame_send(plc);
mrs_free(payload);
return EXT_ERR_SUCCESS;
}
td_u32 mrs_sta_usr_ciu_plc_tx(mrs_usr_tx_item *item, td_pbyte data, td_u16 data_len)
{
mrs_ciu_transmit_inf *inf = TD_NULL;
ext_p2p_mac_frame_ctrl ctrl;
errno_t err;
td_u16 payload_len = sizeof(mrs_ciu_transmit_inf) + data_len;
mrs_sta_usr_frame_head *head = &item->frame_head;
err = memset_s(&ctrl, sizeof(ctrl), 0, sizeof(ctrl));
if (err != EOK) {
return EXT_ERR_FAILURE;
}
err = memcpy_s(ctrl.dest_mac, sizeof(ctrl.dest_mac), head->addr, sizeof(head->addr));
err |= memcpy_s(ctrl.src_mac, sizeof(ctrl.src_mac), head->addr, sizeof(head->addr));
if (err != EOK) {
return EXT_ERR_FAILURE;
}
ctrl.lid = 3; /* priority 3 */
ctrl.port_num = EXT_DMS_CHL_MAC_PORT_APP;
ctrl.ctrl = EXT_DMS_CHL_TX_CTRL_FORCE;
ctrl.id = PLC_CMD_ID_CIU_TRANSMIT;
ctrl.data_size = payload_len;
ctrl.data = (td_pbyte)mrs_malloc(payload_len);
if (ctrl.data == TD_NULL) {
return EXT_ERR_MALLOC_FAILURE;
}
inf = (mrs_ciu_transmit_inf *)ctrl.data;
inf->stru_ver = MRS_PLC_PROTO_VERSION;
inf->stru_size = sizeof(mrs_ciu_transmit_inf);
inf->dir = MRS_DIR_STA_TO_CIU;
inf->prm = MRS_PLC_PRM_SLAVE;
inf->seq = head->seq;
inf->data_len = data_len;
err = memcpy_s(inf->data, inf->data_len, data, data_len);
if (err != EOK) {
mrs_free(ctrl.data);
return EXT_ERR_FAILURE;
}
uapi_p2p_chl_tx(&ctrl, sizeof(ctrl));
mrs_free(ctrl.data);
return EXT_ERR_SUCCESS;
}
#endif /* (defined(PRODUCT_CFG_PRODUCT_TYPE_STA) && defined(MRS_USR_DEMO)) */