• 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.
14  */
15 
16 #ifdef SUPPORT_AUDIO_LIEYIN_TOOL
17 #include <stdint.h>
18 #include "common_def.h"
19 #include <string.h>
20 #include <strings.h>
21 #include "securec.h"
22 #include "debug_print.h"
23 #include "audio_crc16.h"
24 #include "audio_lieyin.h"
25 
26 #define LIEYIN_ADAPT_AT_CMD_R               "CRXXAT^AUDIO"
27 #define LIEYIN_ADAPT_AT_CMD_L               "CLXXAT^AUDIO"
28 #define LIEYIN_MODULE_NAME                  "cc0402"
29 #define LIEYIN_CHAR_MAX_LENGTH              16
30 #define BYTE_MASK                           0xff
31 #define BIT_SHIFT_8                         8
32 #define BIT_SHIFT_16                        16
33 #define BIT_SHIFT_24                        24
34 
35 typedef uint32_t (*lieyin_func_callback)(uint8_t *para, uint32_t len);
36 typedef struct {
37     char *func_name;
38     lieyin_func_callback callback;
39     bool is_bin;
40 } lieyin_cmd_process_t;
41 
42 typedef struct {
43     uint8_t tag;
44     uint8_t resp; // for ux handle flag
45     uint8_t src;
46     uint8_t dst;
47     uint16_t len;
48 } pkt_header_t;
49 
50 typedef enum {
51     CMD_WRITE_DATA_OK = 0,
52     CMD_WRITE_DATA_CRC_ERROR,
53     CMD_WRITE_DATA_WRITE_FAIL,
54     CMD_MALLOC_MEM_FAIL,
55 } audio_cmd_ret_code_t;
56 
57 static uint32_t cc0402_write_bin(uint8_t *para, uint32_t len);
58 static uint32_t cc0402_read_bin(uint8_t *para, uint32_t len);
59 
60 static const lieyin_cmd_process_t g_cc0402_cmds[] = {
61     {"write_bin", cc0402_write_bin, true},
62     {"read_bin", cc0402_read_bin, true},
63 };
64 
audio_cmd_feedback(uint8_t * para,uint16_t len)65 static void audio_cmd_feedback(uint8_t *para, uint16_t len)
66 {
67     if (para == NULL) {
68         PRINT("[AudioCmdBinFeedback] para is NULL");
69         return;
70     }
71 
72     uint16_t data_crc = checksum_crc16(0, para, len);
73     char feedback_lead[] = "ASK";
74     uint16_t send_len = len + sizeof(pkt_header_t) + strlen(feedback_lead) + sizeof(data_crc);
75     uint8_t *send_buf;
76 
77     send_buf = (uint8_t *)malloc(send_len);
78     if (send_buf == NULL) {
79         PRINT("[AudioCmdBinFeedback] malloc is failed");
80         return;
81     }
82 
83     pkt_header_t *header = (pkt_header_t *)send_buf;
84     uint8_t *ptr_send = send_buf;
85 
86     header->resp = 1;
87     header->tag = 0;
88     header->dst = 'R';     // right earphone
89     header->src = 'C';     // PC End
90     header->len = len + strlen(feedback_lead);
91 
92     ptr_send += sizeof(pkt_header_t);
93     if (memcpy_s(ptr_send, strlen(feedback_lead), feedback_lead, strlen(feedback_lead)) != EOK) {
94         PRINT("[AudioCmdBinFeedback] memcpy_s is failed");
95         free(send_buf);
96         return;
97     }
98 
99     ptr_send += strlen(feedback_lead);
100     if (memcpy_s(ptr_send, len, para, len) != EOK) {
101         PRINT("[AudioCmdBinFeedback] memcpy_s is failed");
102         free(send_buf);
103         return;
104     }
105 
106     ptr_send += len;
107     if (memcpy_s(ptr_send, sizeof(data_crc), (uint8_t *)&data_crc, sizeof(data_crc)) != EOK) {
108         PRINT("[AudioCmdBinFeedback] memcpy_s is failed");
109         free(send_buf);
110         return;
111     }
112 
113     uapi_uart_write(TEST_SUITE_UART_BUS, send_buf, send_len, 0);
114     uapi_uart_write(TEST_SUITE_UART_BUS, '\r', 1, 0);
115     uapi_uart_write(TEST_SUITE_UART_BUS, '\n', 1, 0);
116 }
117 
cc0402_write_bin(uint8_t * para,uint32_t len)118 static uint32_t cc0402_write_bin(uint8_t *para, uint32_t len)
119 {
120     if (para == NULL || len < (sizeof(uint32_t) + sizeof(uint8_t))) {
121         PRINT("err param len=%d\r\nFAILED", len);
122         return 0;
123     }
124 
125     uint8_t *ptr = para;
126     uint32_t address;
127     uint8_t *data = ptr + sizeof(address);
128     uint16_t data_len = 0;
129     uint8_t feedback_ret = CMD_WRITE_DATA_OK;
130 
131     data_len = len - sizeof(address);
132 
133     if (data_len == 0 || data_len > 450) { /* 450: short cmd max data len */
134         PRINT("err param len=%d, data_len=%u\r\nFAILED", len, data_len);
135         return 0;
136     }
137 
138     address = ((*(ptr + 0x3)) << BIT_SHIFT_24) + ((*(ptr + 0x2)) << BIT_SHIFT_16) +
139         ((*(ptr + 1)) << BIT_SHIFT_8) + (*ptr);
140 
141     /* to write bin */
142     /* send feedback */
143     audio_cmd_feedback(&feedback_ret, sizeof(feedback_ret));
144     return 1;
145 }
146 
cc0402_read_bin(uint8_t * para,uint32_t len)147 static uint32_t cc0402_read_bin(uint8_t *para, uint32_t len)
148 {
149     if (para == NULL || len < (sizeof(uint32_t) + sizeof(uint16_t))) {
150         PRINT("err param len=%d\r\nFAILED", len);
151         return 0;
152     }
153 
154     uint8_t *ptr = para;
155     uint32_t address;
156     uint16_t data_len;
157     uint8_t feedback_ret = CMD_WRITE_DATA_OK;
158     uint8_t *send_buf = NULL;
159 
160     address = ((*(ptr + 0x3)) << BIT_SHIFT_24) + ((*(ptr + 0x2)) << BIT_SHIFT_16) +
161         ((*(ptr + 1)) << BIT_SHIFT_8) + (*ptr);
162     ptr += sizeof(address);
163     data_len = ((*(ptr + 1)) << BIT_SHIFT_8) + (*ptr);
164 
165     send_buf = malloc(data_len + sizeof(feedback_ret));
166     if (send_buf == NULL) {
167         PRINT("[Cc0401ReadBin]malloc fail!\r\n");
168         return 0;
169     }
170 
171     /* read to send_buf + sizeof(feedback_ret), mocked */
172     for (uint32_t i = 0; i < data_len; i++) {
173         send_buf[sizeof(feedback_ret) + i] = (uint8_t)i;
174     }
175 
176     send_buf[0] = feedback_ret;
177     audio_cmd_feedback(send_buf, data_len + sizeof(feedback_ret));
178 
179     return 1;
180 }
181 
lieyin_cmd_argument_get(char * argument,const char * string,char split_char)182 static uint8_t lieyin_cmd_argument_get(char *argument, const char *string, char split_char)
183 {
184     uint8_t i = 0;
185     uint16_t index = 0;
186     while (string[index] != 0) {
187         if (string[index] == split_char || (i == LIEYIN_CHAR_MAX_LENGTH - 1)) {
188             break;  /* we have found the first element */
189         }
190         argument[index] = string[index];
191         i++;
192         index++;
193     }
194     argument[index] = '\0';
195     return i;
196 }
197 
lieyin_command_proc_bin(uint8_t * para,uint32_t length,lieyin_func_callback callback)198 static int32_t lieyin_command_proc_bin(uint8_t *para, uint32_t length, lieyin_func_callback callback)
199 {
200     uint8_t *ptr = para;
201     uint8_t *cmd_data;
202     errno_t ret;
203     uint16_t data_len, data_crc, crc_check;
204 
205     data_len = ((*(ptr + 1)) << BIT_SHIFT_8) + (*ptr);
206     ptr += sizeof(data_len);
207 
208     cmd_data = (uint8_t *)malloc(data_len);
209     if (cmd_data == NULL) {
210         PRINT("[AudioCmdProcBin] malloc fail! cmdDatalen:%d", data_len);
211         return -1;
212     }
213 
214     ret = memcpy_s(cmd_data, data_len, ptr, data_len);
215     if (ret != EOK) {
216         free(cmd_data);
217         return -1;
218     }
219 
220     ptr += data_len;
221     data_crc = ((*(ptr + 1)) << BIT_SHIFT_8) + (*ptr) ;
222 
223     crc_check = checksum_crc16(0, (uint8_t *)cmd_data, data_len);
224 #ifdef AUDIO_LIEYIN_DEBUG
225     PRINT("[AudioCmdProcBin] cmdDatalen:%d data_crc:0x%x crc_check:0x%x\r\n", data_len, data_crc, crc_check);
226 #endif
227     if (crc_check != data_crc) {
228         PRINT("[AudioCmdProcBin] crc check is failed, rec_len=0x%x, len_val=0x%x, cal_crc=0x%x, rec_crc=0x%x",
229             length - sizeof(data_len) - sizeof(data_crc), data_len, crc_check, data_crc);
230         free(cmd_data);
231         return -1;
232     }
233 
234     if (callback != NULL) {
235         callback(cmd_data, data_len);
236     }
237 
238     free(cmd_data);
239     return 0;
240 }
241 
audio_lieyin_command_execute(char * module,char * func,char * para,uint32_t length)242 void audio_lieyin_command_execute(char *module, char *func, char *para, uint32_t length)
243 {
244     if (strcasecmp(module, LIEYIN_MODULE_NAME) != 0) {
245         return;
246     }
247 
248     for (uint32_t i = 0; i < (sizeof(g_cc0402_cmds) / sizeof(lieyin_cmd_process_t)); i++) {
249         if (strcasecmp(func, g_cc0402_cmds[i].func_name) == 0) {
250             if (g_cc0402_cmds[i].is_bin) {
251                 (void)lieyin_command_proc_bin((uint8_t *)para, length, g_cc0402_cmds[i].callback);
252             } else {
253                 g_cc0402_cmds[i].callback((uint8_t *)para, length);
254             }
255         }
256     }
257 }
258 
audio_lieyin_command_receive(char * buf,uint32_t length)259 void audio_lieyin_command_receive(char *buf, uint32_t length)
260 {
261     char first_argument[LIEYIN_CHAR_MAX_LENGTH] = { 0 };
262     char module[LIEYIN_CHAR_MAX_LENGTH] = { 0 };
263     char func_name[LIEYIN_CHAR_MAX_LENGTH] = { 0 };
264     uint8_t argument_length;
265     char *current_cmd = buf;
266     uint32_t remain_len = length;
267 
268     argument_length = lieyin_cmd_argument_get(first_argument, current_cmd, '=');
269 #ifdef AUDIO_LIEYIN_DEBUG
270     PRINT("= argument:%d\r\n", argument_length);
271 #endif
272     /* if it is empty just return */
273     if (argument_length == 0 || (argument_length + 1 >= remain_len)) {
274         return;  /* EARLY RETURN */
275     }
276     current_cmd += argument_length + 1;
277     remain_len -= argument_length + 1;
278 
279     argument_length = lieyin_cmd_argument_get(module, current_cmd, ',');
280 #ifdef AUDIO_LIEYIN_DEBUG
281     PRINT(",1 argument:%d\r\n", argument_length);
282 #endif
283     if (argument_length == 0 || (argument_length + 1 >= remain_len)) {
284         return;  /* EARLY RETURN */
285     }
286     current_cmd += argument_length + 1;
287     remain_len -= argument_length + 1;
288 
289     argument_length = lieyin_cmd_argument_get(func_name, current_cmd, ',');
290 #ifdef AUDIO_LIEYIN_DEBUG
291     PRINT(",2 argument:%d\r\n", argument_length);
292 #endif
293     if (argument_length == 0 || (argument_length + 1 > remain_len)) {
294         return;  /* EARLY RETURN */
295     }
296     current_cmd += argument_length + 1;
297     remain_len -= argument_length + 1;
298 #ifdef AUDIO_LIEYIN_DEBUG
299     PRINT("param len:%d\r\n", remain_len);
300 #endif
301 
302     if ((strcasecmp(first_argument, LIEYIN_ADAPT_AT_CMD_R) == 0) ||
303         (strcasecmp(first_argument, LIEYIN_ADAPT_AT_CMD_L) == 0)) {
304         audio_lieyin_command_execute(module, func_name, current_cmd, remain_len);
305     }
306 }
307 #endif