1 /**
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License. \n
14 *
15 * Description: Provides AT async notify \n
16 */
17
18 #ifdef CONFIG_AT_SUPPORT_NOTIFY_REPORT
19 #include "at_product.h"
20 #include "at_base.h"
21 #include "at_msg.h"
22 #include "at_process.h"
23 #include "at_notify.h"
24
25 #define STRING_END_FLAG_LEN 1
26
27 typedef struct at_async_notify_t {
28 char *rsp_string;
29 uint16_t string_len;
30 at_channel_id_t channel_id;
31 struct at_async_notify_t *next;
32 } at_async_notify_t;
33
34 static at_async_notify_t *g_notify_list = NULL;
35 static void *g_notify_mutex_handle = NULL;
36
at_notify_append_node(at_async_notify_t * node)37 static void at_notify_append_node(at_async_notify_t *node)
38 {
39 if (g_notify_list == NULL) {
40 g_notify_list = node;
41 } else {
42 at_async_notify_t *next_node = g_notify_list;
43 while (next_node->next != NULL) {
44 next_node = next_node->next;
45 }
46 next_node->next = node;
47 }
48 }
49
50 /* Ensured that the input is not null */
at_notify_free_node(at_async_notify_t * node)51 static void at_notify_free_node(at_async_notify_t *node)
52 {
53 if (node->rsp_string != NULL) {
54 at_free(node->rsp_string);
55 node->rsp_string = NULL;
56 }
57
58 at_free(node);
59 }
60
at_notify_find_next_node(void)61 static at_async_notify_t* at_notify_find_next_node(void)
62 {
63 if (g_notify_list == NULL) {
64 return NULL;
65 }
66
67 at_async_notify_t *node = g_notify_list;
68 g_notify_list = g_notify_list->next;
69 return node;
70 }
71
at_notify_send_msg(void)72 static errcode_t at_notify_send_msg(void)
73 {
74 at_msg_block_t msg;
75 msg.type = AT_CMD_URC_REPORT_MSG;
76
77 return at_msg_send(&msg);
78 }
79
uapi_at_urc_to_channel(at_channel_id_t channel_id,const char * msg,uint32_t msg_len)80 errcode_t uapi_at_urc_to_channel(at_channel_id_t channel_id, const char *msg, uint32_t msg_len)
81 {
82 if (msg == NULL || msg_len == 0) {
83 return ERRCODE_INVALID_PARAM;
84 }
85
86 at_async_notify_t *node = at_malloc(sizeof(at_async_notify_t));
87 if (node == NULL) {
88 return ERRCODE_MALLOC;
89 }
90
91 node->rsp_string = at_malloc(msg_len + STRING_END_FLAG_LEN);
92 if (node->rsp_string == NULL) {
93 return ERRCODE_MALLOC;
94 }
95 node->string_len = msg_len;
96 node->channel_id = channel_id;
97 memset_s(node->rsp_string, msg_len + STRING_END_FLAG_LEN, 0, msg_len + STRING_END_FLAG_LEN);
98 if (memcpy_s(node->rsp_string, msg_len, msg, msg_len) != EOK) {
99 at_free(node->rsp_string);
100 at_free(node);
101 return ERRCODE_MEMCPY;
102 }
103 node->next = NULL;
104
105 at_mutex_acquire(g_notify_mutex_handle);
106 at_notify_append_node(node);
107 at_mutex_release(g_notify_mutex_handle);
108 return at_notify_send_msg();
109 }
110
at_notify_process_list(void)111 void at_notify_process_list(void)
112 {
113 at_mutex_acquire(g_notify_mutex_handle);
114 at_async_notify_t *node = at_notify_find_next_node();
115 while (node != NULL) {
116 uapi_at_report_to_single_channel(node->channel_id, node->rsp_string);
117 at_notify_free_node(node);
118 node = at_notify_find_next_node();
119 }
120 at_mutex_release(g_notify_mutex_handle);
121 }
122
at_notify_init(void)123 void at_notify_init(void)
124 {
125 g_notify_mutex_handle = at_mutex_create();
126 }
127 #endif
128