• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 channel source \n
16  */
17 
18 #include <stdbool.h>
19 #include "at_base.h"
20 #include "at_msg.h"
21 #include "at_channel.h"
22 
23 #define AT_FLAG_LENGTH 2
24 
25 typedef struct {
26     at_channel_state_t state;
27     at_write_func_t write_func;
28     uint32_t len;
29     uint8_t* data;
30 } at_channel_t;
31 
32 static at_channel_t g_channel_entry[AT_MAX_PORT_NUMBER] = {0};
33 
uapi_at_channel_write_register(at_channel_id_t id,at_write_func_t func)34 errcode_t uapi_at_channel_write_register(at_channel_id_t id, at_write_func_t func)
35 {
36     if (id >= AT_MAX_PORT_NUMBER || func == NULL) {
37         return ERRCODE_INVALID_PARAM;
38     }
39     g_channel_entry[id].write_func = func;
40     return ERRCODE_SUCC;
41 }
42 
at_channel_check_and_enable(void)43 void at_channel_check_and_enable(void)
44 {
45     for (uint16_t id = 0; id < AT_MAX_PORT_NUMBER; id++) {
46         if (g_channel_entry[id].state != AT_CHANNEL_UNINITIALIZED) {
47             continue;
48         }
49 
50         if (g_channel_entry[id].write_func == NULL) {
51             continue;
52         }
53 
54         g_channel_entry[id].state = AT_CHANNEL_FREE;
55     }
56 }
57 
at_channel_get_write_func(at_channel_id_t id)58 at_write_func_t at_channel_get_write_func(at_channel_id_t id)
59 {
60     if (g_channel_entry[id].state == AT_CHANNEL_UNINITIALIZED) {
61         return NULL;
62     }
63     return g_channel_entry[id].write_func;
64 }
65 
at_channel_get_data(at_channel_id_t id)66 uint8_t* at_channel_get_data(at_channel_id_t id)
67 {
68     return g_channel_entry[id].data;
69 }
70 
at_channel_set_state(at_channel_id_t id,at_channel_state_t state)71 void at_channel_set_state(at_channel_id_t id, at_channel_state_t state)
72 {
73     g_channel_entry[id].state = state;
74 }
75 
at_channel_data_reset(at_channel_id_t id)76 void at_channel_data_reset(at_channel_id_t id)
77 {
78     if (g_channel_entry[id].data != NULL) {
79         at_free(g_channel_entry[id].data);
80         g_channel_entry[id].data = NULL;
81     }
82     g_channel_entry[id].len = 0;
83     g_channel_entry[id].state = AT_CHANNEL_FREE;
84 }
85 
at_channel_data_wait_interactivity(at_channel_id_t id)86 void at_channel_data_wait_interactivity(at_channel_id_t id)
87 {
88     g_channel_entry[id].state = AT_CHANNEL_INTERACTIVITY;
89 }
90 
at_is_channel_block(at_channel_id_t id)91 static bool at_is_channel_block(at_channel_id_t id)
92 {
93     if (g_channel_entry[id].state == AT_CHANNEL_BLOCK ||
94         g_channel_entry[id].state == AT_CHANNEL_UNINITIALIZED) {
95         return true;
96     }
97     return false;
98 }
99 
at_channel_is_data_integrated(at_channel_id_t id)100 static bool at_channel_is_data_integrated(at_channel_id_t id)
101 {
102     for (uint32_t index = 1; index < g_channel_entry[id].len; index++) {
103         if (g_channel_entry[id].data[index] == '\r' ||
104             g_channel_entry[id].data[index] == '\n') {
105             g_channel_entry[id].data[index] = '\0';
106             return true;
107         }
108     }
109     return false;
110 }
111 
at_channel_del_invalid_data(at_channel_id_t id,uint32_t index)112 static void at_channel_del_invalid_data(at_channel_id_t id, uint32_t index)
113 {
114     if (memmove_s(g_channel_entry[id].data, AT_CMD_MAX_LENGTH,
115                   g_channel_entry[id].data + index, AT_CMD_MAX_LENGTH - index) != EOK) {
116         return;
117     }
118     g_channel_entry[id].len -= index;
119 }
120 
at_channel_cmd_head_check(at_channel_id_t id)121 static bool at_channel_cmd_head_check(at_channel_id_t id)
122 {
123     uint32_t index;
124     for (index = 0; index < g_channel_entry[id].len - 1; index++) {
125         if (((g_channel_entry[id].data[index] == 'a') || (g_channel_entry[id].data[index] == 'A')) &&
126             ((g_channel_entry[id].data[index + 1] == 't') || (g_channel_entry[id].data[index + 1] == 'T'))) {
127             at_channel_del_invalid_data(id, index);
128             return true;
129         }
130     }
131 
132     if (g_channel_entry[id].data[index] == 'a' || g_channel_entry[id].data[index] == 'A') {
133         at_channel_del_invalid_data(id, index);
134     } else {
135         at_channel_data_reset(id);
136     }
137 
138     return false;
139 }
140 
at_channel_send_msg(at_msg_type_t type,at_channel_id_t id)141 static errcode_t at_channel_send_msg(at_msg_type_t type, at_channel_id_t id)
142 {
143     at_msg_block_t msg;
144     msg.type = type;
145     msg.sub_msg.cmd.channel_id = id;
146     msg.sub_msg.cmd.len = (uint16_t)g_channel_entry[id].len;
147 
148     return at_msg_send(&msg);
149 }
150 
at_channel_cmd_handle(at_channel_id_t id)151 static errcode_t at_channel_cmd_handle(at_channel_id_t id)
152 {
153     errcode_t ret;
154 
155     if (at_channel_cmd_head_check(id) != true) {
156         return ERRCODE_SUCC;
157     }
158 
159     if (at_channel_is_data_integrated(id) != true) {
160         return ERRCODE_SUCC;
161     }
162 
163     at_channel_del_invalid_data(id, AT_FLAG_LENGTH);
164     if (g_channel_entry[id].data[0] == '\0') {
165         g_channel_entry[id].write_func(AT_RESPONSE_OK);
166         return ERRCODE_SUCC;
167     }
168 
169     g_channel_entry[id].state = AT_CHANNEL_BLOCK;
170     ret = at_channel_send_msg(AT_CMD_MSG, id);
171     if (ret != ERRCODE_SUCC) {
172         at_channel_data_reset(id);
173         g_channel_entry[id].state = AT_CHANNEL_FREE;
174     }
175     return ret;
176 }
177 
at_channel_interactivity_handle(at_channel_id_t id)178 static errcode_t at_channel_interactivity_handle(at_channel_id_t id)
179 {
180     if (at_channel_is_data_integrated(id) != true) {
181         return ERRCODE_SUCC;
182     }
183 
184     g_channel_entry[id].state = AT_CHANNEL_BLOCK;
185     return at_channel_send_msg(AT_CMD_INTERACTIVITY_MSG, id);
186 }
187 
at_channel_data_handle(at_channel_id_t id)188 static errcode_t at_channel_data_handle(at_channel_id_t id)
189 {
190     if (g_channel_entry[id].state == AT_CHANNEL_FREE) {
191         return at_channel_cmd_handle(id);
192     } else {
193         return at_channel_interactivity_handle(id);
194     }
195 }
196 
at_channel_prepare(at_channel_id_t id)197 static errcode_t at_channel_prepare(at_channel_id_t id)
198 {
199     if (at_is_channel_block(id) == true) {
200         return ERRCODE_AT_CHANNEL_BUSY;
201     }
202 
203     if (g_channel_entry[id].data == NULL) {
204         g_channel_entry[id].data = at_malloc(AT_CMD_MAX_LENGTH);
205         if (g_channel_entry[id].data == NULL) {
206             return ERRCODE_MALLOC;
207         }
208         memset_s(g_channel_entry[id].data, AT_CMD_MAX_LENGTH, 0, AT_CMD_MAX_LENGTH);
209     }
210 
211     return ERRCODE_SUCC;
212 }
213 
at_channel_data_add(at_channel_id_t id,uint8_t * data,uint32_t len)214 static errcode_t at_channel_data_add(at_channel_id_t id, uint8_t* data, uint32_t len)
215 {
216     if (g_channel_entry[id].len + len > AT_CMD_MAX_LENGTH) {
217         at_channel_data_reset(id);
218         return ERRCODE_AT_CMD_TOO_LONG;
219     }
220 
221     if (memcpy_s(g_channel_entry[id].data + g_channel_entry[id].len,
222                  len, data, len) != AT_RET_OK) {
223         at_channel_data_reset(id);
224         return ERRCODE_MEMCPY;
225     }
226     g_channel_entry[id].len += len;
227 
228     return ERRCODE_SUCC;
229 }
230 
uapi_at_channel_data_recv(at_channel_id_t id,uint8_t * data,uint32_t len)231 errcode_t uapi_at_channel_data_recv(at_channel_id_t id, uint8_t* data, uint32_t len)
232 {
233     if (id >= AT_MAX_PORT_NUMBER || data == NULL || len == 0) {
234         return ERRCODE_INVALID_PARAM;
235     }
236 
237     errcode_t err_ret = at_channel_prepare(id);
238     if (err_ret != ERRCODE_SUCC) {
239         return err_ret;
240     }
241 
242     err_ret = at_channel_data_add(id, data, len);
243     if (err_ret != ERRCODE_SUCC) {
244         return err_ret;
245     }
246 
247     return at_channel_data_handle(id);
248 }
249