xref: /nrf52832-nimble/rt-thread/components/net/at/src/at_cli.c (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero /*
2*10465441SEvalZero  * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero  *
4*10465441SEvalZero  * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero  *
6*10465441SEvalZero  * Change Logs:
7*10465441SEvalZero  * Date           Author       Notes
8*10465441SEvalZero  * 2018-04-02     armink       first version
9*10465441SEvalZero  */
10*10465441SEvalZero 
11*10465441SEvalZero #include <at.h>
12*10465441SEvalZero #include <stdio.h>
13*10465441SEvalZero #include <string.h>
14*10465441SEvalZero 
15*10465441SEvalZero #include <rtthread.h>
16*10465441SEvalZero #include <rtdevice.h>
17*10465441SEvalZero #include <rthw.h>
18*10465441SEvalZero 
19*10465441SEvalZero #ifdef AT_USING_CLI
20*10465441SEvalZero 
21*10465441SEvalZero #define AT_CLI_FIFO_SIZE                      256
22*10465441SEvalZero 
23*10465441SEvalZero static struct rt_semaphore console_rx_notice;
24*10465441SEvalZero static struct rt_ringbuffer *console_rx_fifo = RT_NULL;
25*10465441SEvalZero static rt_err_t (*odev_rx_ind)(rt_device_t dev, rt_size_t size) = RT_NULL;
26*10465441SEvalZero 
27*10465441SEvalZero #ifdef AT_USING_CLIENT
28*10465441SEvalZero static struct rt_semaphore client_rx_notice;
29*10465441SEvalZero static struct rt_ringbuffer *client_rx_fifo = RT_NULL;
30*10465441SEvalZero #endif
31*10465441SEvalZero 
console_getchar(void)32*10465441SEvalZero static char console_getchar(void)
33*10465441SEvalZero {
34*10465441SEvalZero     char ch;
35*10465441SEvalZero 
36*10465441SEvalZero     rt_sem_take(&console_rx_notice, RT_WAITING_FOREVER);
37*10465441SEvalZero     rt_ringbuffer_getchar(console_rx_fifo, (rt_uint8_t *)&ch);
38*10465441SEvalZero 
39*10465441SEvalZero     return ch;
40*10465441SEvalZero }
41*10465441SEvalZero 
console_getchar_rx_ind(rt_device_t dev,rt_size_t size)42*10465441SEvalZero static rt_err_t console_getchar_rx_ind(rt_device_t dev, rt_size_t size)
43*10465441SEvalZero {
44*10465441SEvalZero     uint8_t ch;
45*10465441SEvalZero     rt_size_t i;
46*10465441SEvalZero 
47*10465441SEvalZero     for (i = 0; i < size; i++)
48*10465441SEvalZero     {
49*10465441SEvalZero         /* read a char */
50*10465441SEvalZero         if (rt_device_read(dev, 0, &ch, 1))
51*10465441SEvalZero         {
52*10465441SEvalZero             rt_ringbuffer_put_force(console_rx_fifo, &ch, 1);
53*10465441SEvalZero             rt_sem_release(&console_rx_notice);
54*10465441SEvalZero         }
55*10465441SEvalZero     }
56*10465441SEvalZero 
57*10465441SEvalZero     return RT_EOK;
58*10465441SEvalZero }
59*10465441SEvalZero 
at_cli_init(void)60*10465441SEvalZero void at_cli_init(void)
61*10465441SEvalZero {
62*10465441SEvalZero     rt_base_t int_lvl;
63*10465441SEvalZero     rt_device_t console;
64*10465441SEvalZero 
65*10465441SEvalZero     rt_sem_init(&console_rx_notice, "cli_c", 0, RT_IPC_FLAG_FIFO);
66*10465441SEvalZero 
67*10465441SEvalZero     /* create RX FIFO */
68*10465441SEvalZero     console_rx_fifo = rt_ringbuffer_create(AT_CLI_FIFO_SIZE);
69*10465441SEvalZero     /* created must success */
70*10465441SEvalZero     RT_ASSERT(console_rx_fifo);
71*10465441SEvalZero 
72*10465441SEvalZero     int_lvl = rt_hw_interrupt_disable();
73*10465441SEvalZero     console = rt_console_get_device();
74*10465441SEvalZero     if (console)
75*10465441SEvalZero     {
76*10465441SEvalZero         /* backup RX indicate */
77*10465441SEvalZero         odev_rx_ind = console->rx_indicate;
78*10465441SEvalZero         rt_device_set_rx_indicate(console, console_getchar_rx_ind);
79*10465441SEvalZero     }
80*10465441SEvalZero 
81*10465441SEvalZero     rt_hw_interrupt_enable(int_lvl);
82*10465441SEvalZero }
83*10465441SEvalZero 
at_cli_deinit(void)84*10465441SEvalZero void at_cli_deinit(void)
85*10465441SEvalZero {
86*10465441SEvalZero     rt_base_t int_lvl;
87*10465441SEvalZero     rt_device_t console;
88*10465441SEvalZero 
89*10465441SEvalZero     int_lvl = rt_hw_interrupt_disable();
90*10465441SEvalZero     console = rt_console_get_device();
91*10465441SEvalZero     if (console && odev_rx_ind)
92*10465441SEvalZero     {
93*10465441SEvalZero         /* restore RX indicate */
94*10465441SEvalZero         rt_device_set_rx_indicate(console, odev_rx_ind);
95*10465441SEvalZero     }
96*10465441SEvalZero     rt_hw_interrupt_enable(int_lvl);
97*10465441SEvalZero 
98*10465441SEvalZero     rt_sem_detach(&console_rx_notice);
99*10465441SEvalZero     rt_ringbuffer_destroy(console_rx_fifo);
100*10465441SEvalZero }
101*10465441SEvalZero 
102*10465441SEvalZero #ifdef AT_USING_SERVER
server_cli_parser(void)103*10465441SEvalZero static void server_cli_parser(void)
104*10465441SEvalZero {
105*10465441SEvalZero     extern at_server_t at_get_server(void);
106*10465441SEvalZero 
107*10465441SEvalZero     at_server_t server = at_get_server();
108*10465441SEvalZero     rt_base_t int_lvl;
109*10465441SEvalZero     static rt_device_t device_bak;
110*10465441SEvalZero     static char (*getchar_bak)(void);
111*10465441SEvalZero     static char endmark_back[AT_END_MARK_LEN];
112*10465441SEvalZero 
113*10465441SEvalZero     /* backup server device and getchar function */
114*10465441SEvalZero     {
115*10465441SEvalZero         int_lvl = rt_hw_interrupt_disable();
116*10465441SEvalZero 
117*10465441SEvalZero         device_bak = server->device;
118*10465441SEvalZero         getchar_bak = server->get_char;
119*10465441SEvalZero 
120*10465441SEvalZero         memset(endmark_back, 0x00, AT_END_MARK_LEN);
121*10465441SEvalZero         memcpy(endmark_back, server->end_mark, strlen(server->end_mark));
122*10465441SEvalZero 
123*10465441SEvalZero         /* setup server device as console device */
124*10465441SEvalZero         server->device = rt_console_get_device();
125*10465441SEvalZero         server->get_char = console_getchar;
126*10465441SEvalZero 
127*10465441SEvalZero         memset(server->end_mark, 0x00, AT_END_MARK_LEN);
128*10465441SEvalZero         server->end_mark[0] = '\r';
129*10465441SEvalZero 
130*10465441SEvalZero         rt_hw_interrupt_enable(int_lvl);
131*10465441SEvalZero     }
132*10465441SEvalZero 
133*10465441SEvalZero     if (server)
134*10465441SEvalZero     {
135*10465441SEvalZero         rt_kprintf("======== Welcome to using RT-Thread AT command server cli ========\n");
136*10465441SEvalZero         rt_kprintf("Input your at command for test server. Press 'ESC' to exit.\n");
137*10465441SEvalZero         server->parser_entry(server);
138*10465441SEvalZero     }
139*10465441SEvalZero     else
140*10465441SEvalZero     {
141*10465441SEvalZero         rt_kprintf("AT client not initialized\n");
142*10465441SEvalZero     }
143*10465441SEvalZero 
144*10465441SEvalZero     /* restore server device and getchar function */
145*10465441SEvalZero     {
146*10465441SEvalZero         int_lvl = rt_hw_interrupt_disable();
147*10465441SEvalZero 
148*10465441SEvalZero         server->device = device_bak;
149*10465441SEvalZero         server->get_char = getchar_bak;
150*10465441SEvalZero 
151*10465441SEvalZero         memset(server->end_mark, 0x00, AT_END_MARK_LEN);
152*10465441SEvalZero         memcpy(server->end_mark, endmark_back, strlen(endmark_back));
153*10465441SEvalZero 
154*10465441SEvalZero         rt_hw_interrupt_enable(int_lvl);
155*10465441SEvalZero     }
156*10465441SEvalZero }
157*10465441SEvalZero #endif /* AT_USING_SERVER */
158*10465441SEvalZero 
159*10465441SEvalZero #ifdef AT_USING_CLIENT
client_getchar(void)160*10465441SEvalZero static char client_getchar(void)
161*10465441SEvalZero {
162*10465441SEvalZero     char ch;
163*10465441SEvalZero 
164*10465441SEvalZero     rt_sem_take(&client_rx_notice, RT_WAITING_FOREVER);
165*10465441SEvalZero     rt_ringbuffer_getchar(client_rx_fifo, (rt_uint8_t *)&ch);
166*10465441SEvalZero 
167*10465441SEvalZero     return ch;
168*10465441SEvalZero }
169*10465441SEvalZero 
at_client_entry(void * param)170*10465441SEvalZero static void at_client_entry(void *param)
171*10465441SEvalZero {
172*10465441SEvalZero     char ch;
173*10465441SEvalZero 
174*10465441SEvalZero     while(1)
175*10465441SEvalZero     {
176*10465441SEvalZero         ch = client_getchar();
177*10465441SEvalZero         rt_kprintf("%c", ch);
178*10465441SEvalZero     }
179*10465441SEvalZero }
180*10465441SEvalZero 
client_getchar_rx_ind(rt_device_t dev,rt_size_t size)181*10465441SEvalZero static rt_err_t client_getchar_rx_ind(rt_device_t dev, rt_size_t size)
182*10465441SEvalZero {
183*10465441SEvalZero     uint8_t ch;
184*10465441SEvalZero     rt_size_t i;
185*10465441SEvalZero 
186*10465441SEvalZero     for (i = 0; i < size; i++)
187*10465441SEvalZero     {
188*10465441SEvalZero         /* read a char */
189*10465441SEvalZero         if (rt_device_read(dev, 0, &ch, 1))
190*10465441SEvalZero         {
191*10465441SEvalZero             rt_ringbuffer_put_force(client_rx_fifo, &ch, 1);
192*10465441SEvalZero             rt_sem_release(&client_rx_notice);
193*10465441SEvalZero         }
194*10465441SEvalZero     }
195*10465441SEvalZero 
196*10465441SEvalZero     return RT_EOK;
197*10465441SEvalZero }
client_cli_parser(at_client_t client)198*10465441SEvalZero static void client_cli_parser(at_client_t  client)
199*10465441SEvalZero {
200*10465441SEvalZero #define ESC_KEY                 0x1B
201*10465441SEvalZero #define BACKSPACE_KEY           0x08
202*10465441SEvalZero #define DELECT_KEY              0x7F
203*10465441SEvalZero 
204*10465441SEvalZero     char ch;
205*10465441SEvalZero     char cur_line[FINSH_CMD_SIZE] = { 0 };
206*10465441SEvalZero     rt_size_t cur_line_len = 0;
207*10465441SEvalZero     static rt_err_t (*client_odev_rx_ind)(rt_device_t dev, rt_size_t size) = RT_NULL;
208*10465441SEvalZero     rt_base_t int_lvl;
209*10465441SEvalZero     rt_thread_t at_client;
210*10465441SEvalZero 
211*10465441SEvalZero     if (client)
212*10465441SEvalZero     {
213*10465441SEvalZero         /* backup client device RX indicate */
214*10465441SEvalZero         {
215*10465441SEvalZero             int_lvl = rt_hw_interrupt_disable();
216*10465441SEvalZero             client_odev_rx_ind = client->device->rx_indicate;
217*10465441SEvalZero             rt_device_set_rx_indicate(client->device, client_getchar_rx_ind);
218*10465441SEvalZero             rt_hw_interrupt_enable(int_lvl);
219*10465441SEvalZero         }
220*10465441SEvalZero 
221*10465441SEvalZero         rt_sem_init(&client_rx_notice, "cli_r", 0, RT_IPC_FLAG_FIFO);
222*10465441SEvalZero         client_rx_fifo = rt_ringbuffer_create(AT_CLI_FIFO_SIZE);
223*10465441SEvalZero 
224*10465441SEvalZero         at_client = rt_thread_create("at_cli", at_client_entry, RT_NULL, 512, 8, 8);
225*10465441SEvalZero         if (client_rx_fifo && at_client)
226*10465441SEvalZero         {
227*10465441SEvalZero             rt_kprintf("======== Welcome to using RT-Thread AT command client cli ========\n");
228*10465441SEvalZero             rt_kprintf("Cli will forward your command to server port(%s). Press 'ESC' to exit.\n", client->device->parent.name);
229*10465441SEvalZero             rt_thread_startup(at_client);
230*10465441SEvalZero             /* process user input */
231*10465441SEvalZero             while (ESC_KEY != (ch = console_getchar()))
232*10465441SEvalZero             {
233*10465441SEvalZero                 if (ch == BACKSPACE_KEY || ch == DELECT_KEY)
234*10465441SEvalZero                 {
235*10465441SEvalZero                     if (cur_line_len)
236*10465441SEvalZero                     {
237*10465441SEvalZero                         cur_line[--cur_line_len] = 0;
238*10465441SEvalZero                         rt_kprintf("\b \b");
239*10465441SEvalZero                     }
240*10465441SEvalZero                     continue;
241*10465441SEvalZero                 }
242*10465441SEvalZero                 else if (ch == '\r' || ch == '\n')
243*10465441SEvalZero                 {
244*10465441SEvalZero                     /* execute a AT request */
245*10465441SEvalZero                     if (cur_line_len)
246*10465441SEvalZero                     {
247*10465441SEvalZero                         rt_kprintf("\n");
248*10465441SEvalZero                         at_obj_exec_cmd(client, RT_NULL, "%.*s", cur_line_len, cur_line);
249*10465441SEvalZero                     }
250*10465441SEvalZero                     cur_line_len = 0;
251*10465441SEvalZero                 }
252*10465441SEvalZero                 else
253*10465441SEvalZero                 {
254*10465441SEvalZero                     rt_kprintf("%c", ch);
255*10465441SEvalZero                     cur_line[cur_line_len++] = ch;
256*10465441SEvalZero                 }
257*10465441SEvalZero             }
258*10465441SEvalZero 
259*10465441SEvalZero             /* restore client device RX indicate */
260*10465441SEvalZero             {
261*10465441SEvalZero                 int_lvl = rt_hw_interrupt_disable();
262*10465441SEvalZero                 rt_device_set_rx_indicate(client->device, client_odev_rx_ind);
263*10465441SEvalZero                 rt_hw_interrupt_enable(int_lvl);
264*10465441SEvalZero             }
265*10465441SEvalZero 
266*10465441SEvalZero             rt_thread_delete(at_client);
267*10465441SEvalZero             rt_sem_detach(&client_rx_notice);
268*10465441SEvalZero             rt_ringbuffer_destroy(client_rx_fifo);
269*10465441SEvalZero         }
270*10465441SEvalZero         else
271*10465441SEvalZero         {
272*10465441SEvalZero             rt_kprintf("No mem for AT cli client\n");
273*10465441SEvalZero         }
274*10465441SEvalZero     }
275*10465441SEvalZero     else
276*10465441SEvalZero     {
277*10465441SEvalZero         rt_kprintf("AT client not initialized\n");
278*10465441SEvalZero     }
279*10465441SEvalZero }
280*10465441SEvalZero #endif /* AT_USING_CLIENT */
281*10465441SEvalZero 
at(int argc,char ** argv)282*10465441SEvalZero static void at(int argc, char **argv)
283*10465441SEvalZero {
284*10465441SEvalZero 
285*10465441SEvalZero     if (argc != 2 && argc != 3)
286*10465441SEvalZero     {
287*10465441SEvalZero         rt_kprintf("Please input '<server|client [dev_name]>' \n");
288*10465441SEvalZero         return;
289*10465441SEvalZero     }
290*10465441SEvalZero 
291*10465441SEvalZero     at_cli_init();
292*10465441SEvalZero 
293*10465441SEvalZero     if (!strcmp(argv[1], "server"))
294*10465441SEvalZero     {
295*10465441SEvalZero #ifdef AT_USING_SERVER
296*10465441SEvalZero         server_cli_parser();
297*10465441SEvalZero #else
298*10465441SEvalZero         rt_kprintf("Not support AT server, please check your configure!\n");
299*10465441SEvalZero #endif /* AT_USING_SERVER */
300*10465441SEvalZero     }
301*10465441SEvalZero     else if (!strcmp(argv[1], "client"))
302*10465441SEvalZero     {
303*10465441SEvalZero #ifdef AT_USING_CLIENT
304*10465441SEvalZero         at_client_t client = RT_NULL;
305*10465441SEvalZero 
306*10465441SEvalZero         if (argc == 2)
307*10465441SEvalZero         {
308*10465441SEvalZero             client_cli_parser(at_client_get_first());
309*10465441SEvalZero         }
310*10465441SEvalZero         else if (argc == 3)
311*10465441SEvalZero         {
312*10465441SEvalZero             client = at_client_get(argv[2]);
313*10465441SEvalZero             if (client == RT_NULL)
314*10465441SEvalZero             {
315*10465441SEvalZero                 rt_kprintf("input AT client device name(%s) error.\n", argv[2]);
316*10465441SEvalZero             }
317*10465441SEvalZero             else
318*10465441SEvalZero             {
319*10465441SEvalZero                 client_cli_parser(client);
320*10465441SEvalZero             }
321*10465441SEvalZero         }
322*10465441SEvalZero #else
323*10465441SEvalZero         rt_kprintf("Not support AT client, please check your configure!\n");
324*10465441SEvalZero #endif /* AT_USING_CLIENT */
325*10465441SEvalZero     }
326*10465441SEvalZero     else
327*10465441SEvalZero     {
328*10465441SEvalZero         rt_kprintf("Please input '<server|client [dev_name]>' \n");
329*10465441SEvalZero     }
330*10465441SEvalZero 
331*10465441SEvalZero     at_cli_deinit();
332*10465441SEvalZero }
333*10465441SEvalZero MSH_CMD_EXPORT(at, RT-Thread AT component cli: at <server|client [dev_name]>);
334*10465441SEvalZero 
335*10465441SEvalZero #endif /* AT_USING_CLI */
336