1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include "k_api.h"
5 #include "cli_console.h"
6 #include "aos/cli.h"
7 #include "aos/kernel.h"
8 #include "cli_api.h"
9 #include "cli_adapt.h"
10 
11 #if AOS_COMP_DEBUG
12 #include "aos/debug.h"
13 #endif
14 
15 #define CONSOLE_USER_INFO_ID (RHINO_CLI_CONSOLE_USER_INFO_POS)
16 
17 extern cli_console cli_uart_console;
18 
19 static dlist_t gCliConsolelist = AOS_DLIST_INIT(gCliConsolelist);
20 
21 static cli_console *default_console = &cli_uart_console;
22 static cli_console *global_console = NULL;
23 
24 static aos_sem_t console_sem;
25 static int mul_console_init_flag = 0;
26 
27 static inline void cli_console_shared_sem_take(aos_sem_t *sem);
28 static inline void cli_console_shared_sem_post(aos_sem_t *sem);
29 
register_cli_console_to_list(cli_console * console)30 static int register_cli_console_to_list(cli_console *console)
31 {
32     if (console == NULL) {
33         return -1;
34     }
35 
36     dlist_init(&console->i_list);
37 
38     cli_console_shared_sem_take(&console_sem);
39     dlist_add(&console->i_list, &gCliConsolelist);
40     cli_console_shared_sem_post(&console_sem);
41     return 0;
42 }
43 
remove_cli_console_from_list(cli_console * console)44 static int remove_cli_console_from_list(cli_console *console)
45 {
46     dlist_t     *pos;
47     dlist_t     *q;
48     cli_console *tmp;
49 
50     if (console == NULL) {
51         return -1;
52     }
53 
54     cli_console_shared_sem_take(&console_sem);
55     dlist_for_each_safe(pos, q, &gCliConsolelist) {
56         tmp = aos_list_entry(pos, cli_console, i_list);
57         if (tmp == console) {
58             dlist_del(pos);
59             break;
60         }
61     }
62     cli_console_shared_sem_post(&console_sem);
63     return 0;
64 }
65 
cli_console_check_is_in_list(cli_console * console)66 static int cli_console_check_is_in_list(cli_console *console)
67 {
68     dlist_t     *pos;
69     dlist_t     *q;
70     cli_console *tmp;
71 
72     int ret = 0;
73 
74     if (console == NULL) {
75         return ret;
76     }
77 
78     cli_console_shared_sem_take(&console_sem);
79     dlist_for_each_safe(pos, q, &gCliConsolelist) {
80         tmp = aos_list_entry(pos, cli_console, i_list);
81         if (console == tmp) {
82             ret = 1;
83         }
84     }
85     cli_console_shared_sem_post(&console_sem);
86     return ret;
87 }
88 
get_alive_console_num(void)89 int get_alive_console_num(void)
90 {
91     dlist_t     *pos;
92     dlist_t     *q;
93     cli_console *tmp;
94 
95     int alive_console_n = 0;
96 
97     cli_console_shared_sem_take(&console_sem);
98     dlist_for_each_safe(pos, q, &gCliConsolelist) {
99         tmp = aos_list_entry(pos, cli_console, i_list);
100         if (tmp->alive == 1) {
101             alive_console_n++;
102         }
103     }
104     cli_console_shared_sem_post(&console_sem);
105     return alive_console_n;
106 }
107 
get_default_console(void)108 cli_console *get_default_console(void)
109 {
110     if (default_console->exit_flag == 1 || default_console->init_flag == 0) {
111         return NULL;
112     }
113     return default_console;
114 }
115 
set_default_console(void * console)116 cli_console *set_default_console(void *console)
117 {
118     cli_console *last_console = default_console;
119     default_console = console;
120     return last_console;
121 }
122 
get_global_console(void)123 cli_console *get_global_console(void)
124 {
125     return global_console;
126 }
127 
set_global_console(void * console)128 cli_console *set_global_console(void *console)
129 {
130     cli_console *last_console = global_console;
131     global_console = console;
132     return last_console;
133 }
134 
get_current_console(void)135 cli_console *get_current_console(void)
136 {
137     cli_console *console = NULL;
138 
139     console = get_global_console();
140     if (console) {
141         return console;
142     }
143 
144     console = get_clitask_console();
145     return console != NULL && console->exit_flag != 1 && console->init_flag == 1 ? console : get_default_console();
146 }
147 
148 /*
149  * get real console from cli task
150  * @return cli task console
151  * */
get_clitask_console(void)152 cli_console *get_clitask_console(void)
153 {
154     return (cli_console *)(cli_task_get_console(krhino_cur_task_get()));
155 }
156 
cli_console_set_tag_len(uint8_t cli_tag_len,int * error)157 void cli_console_set_tag_len(uint8_t cli_tag_len, int *error)
158 {
159     int ret = -1;
160     cli_console *console = get_clitask_console();
161     if (console) {
162         console->cli_tag_len = cli_tag_len;
163         ret = 0;
164     }
165 
166     if (error) {
167         *error = ret;
168     }
169 }
170 
cli_console_get_tag_len(int * error)171 uint8_t cli_console_get_tag_len(int *error)
172 {
173     int ret = -1;
174     uint8_t cli_tag_len = 0;
175     cli_console *console = get_clitask_console();
176     if (console) {
177         cli_tag_len = console->cli_tag_len;
178         ret = 0;
179     }
180 
181     if (error) {
182         *error = ret;
183     }
184 
185     return cli_tag_len;
186 }
187 
cli_console_set_tag(char cli_tag,uint32_t idx,int * error)188 void cli_console_set_tag(char cli_tag, uint32_t idx, int *error)
189 {
190     int ret = -1;
191     cli_console *console = get_clitask_console();
192     if (console && idx < CLI_CONSOLE_TAG_LEN) {
193         console->cli_tag[idx] = cli_tag;
194         console->cli_tag_len++;
195         ret = 0;
196     }
197 
198     if (error) {
199         *error = ret;
200     }
201 }
202 
cli_console_get_tag(uint32_t idx,int * error)203 char cli_console_get_tag(uint32_t idx, int *error)
204 {
205     int ret = -1;
206     char cli_tag_idx = 0;
207     cli_console *console = get_clitask_console();
208     if (console && idx < CLI_CONSOLE_TAG_LEN) {
209         cli_tag_idx = console->cli_tag[idx];
210         ret = 0;
211     }
212 
213     if (error) {
214         *error = ret;
215     }
216 
217     return cli_tag_idx;
218 }
219 
cli_console_get_all_tag(int * error)220 char *cli_console_get_all_tag(int *error)
221 {
222     char *cli_tag = NULL;
223     int ret = -1;
224     cli_console *console = get_clitask_console();
225     if (console) {
226         cli_tag = console->cli_tag;
227         ret = 0;
228     }
229 
230     if (error) {
231         *error = ret;
232     }
233 
234     return cli_tag;
235 }
236 
cli_console_shared_sem_take(aos_sem_t * sem)237 static inline void cli_console_shared_sem_take(aos_sem_t *sem)
238 {
239     aos_sem_wait(sem, AOS_WAIT_FOREVER);
240 }
241 
cli_console_shared_sem_post(aos_sem_t * sem)242 static inline void cli_console_shared_sem_post(aos_sem_t *sem)
243 {
244     aos_sem_signal(sem);
245 }
246 
cli_task_get_console(void * task_handle)247 char *cli_task_get_console(void *task_handle)
248 {
249     ktask_t *task = (ktask_t *)task_handle;
250     void *cli_console = NULL;
251     if (task) {
252         if (krhino_task_info_get(task, CONSOLE_USER_INFO_ID, &cli_console) == RHINO_SUCCESS) {
253             return cli_console;
254         }
255     }
256     return NULL;
257 }
258 
_cli_task_clear_console(void * task_handle)259 int _cli_task_clear_console(void *task_handle)
260 {
261     ktask_t *task = (ktask_t *)task_handle;
262     if (task) {
263         if (krhino_task_info_set(task, CONSOLE_USER_INFO_ID, NULL) != RHINO_SUCCESS) {
264             printf("%s fail\r\n", __func__);
265             return -1;
266         }
267     }
268     return 0;
269 }
270 
_cli_task_set_console(void * task_handle,void * console)271 int _cli_task_set_console(void *task_handle, void *console)
272 {
273     ktask_t *task = (ktask_t *)task_handle;
274 
275     if (task) {
276         if (krhino_task_info_set(task, CONSOLE_USER_INFO_ID, console) != RHINO_SUCCESS) {
277             printf("%s fail\r\n", __func__);
278             return -1;
279         }
280     }
281     return 0;
282 }
283 
cli_console_add_task_list_node(void * current_console,void * task)284 void cli_console_add_task_list_node(void *current_console, void *task)
285 {
286     cli_console *console = (cli_console *)(current_console);
287 
288     if (console == NULL || task == NULL) {
289         return;
290     }
291 
292     wraper_task *wraper_task_node = malloc(sizeof(wraper_task));
293     if (wraper_task_node == NULL) {
294         return;
295     }
296     memset(wraper_task_node, 0, sizeof(wraper_task));
297 
298     aos_sem_wait(&console->sem, AOS_WAIT_FOREVER);
299 
300     wraper_task_node->task = task;
301     dlist_init(&wraper_task_node->task_list_node);
302     dlist_add(&wraper_task_node->task_list_node, &console->task_list);
303 
304     aos_sem_signal(&console->sem);
305 }
306 
cli_task_clear_console(void * task_handle)307 int cli_task_clear_console(void *task_handle)
308 {
309     return _cli_task_clear_console(task_handle);
310 }
311 
312 
cli_task_set_console(void * task_handle,void * console)313 int cli_task_set_console(void *task_handle, void *console)
314 {
315     int ret;
316 
317     if (mul_console_init_flag == 1) {
318         cli_console_shared_sem_take(&console_sem);
319         ret = _cli_task_set_console(task_handle, console);
320         cli_console_shared_sem_post(&console_sem);
321     } else {
322         ret = _cli_task_set_console(task_handle, console);
323     }
324 
325     return ret;
326 }
327 
cli_console_remove_task_list_node(cli_console * console,void * task)328 void cli_console_remove_task_list_node(cli_console *console, void *task)
329 {
330     dlist_t     *pos;
331     dlist_t     *q;
332     wraper_task *tmp;
333 
334     if (console == NULL) {
335         return;
336     }
337 
338     aos_sem_wait(&console->sem, AOS_WAIT_FOREVER);
339     dlist_for_each_safe(pos, q, &console->task_list) {
340         tmp = aos_list_entry(pos, wraper_task, task_list_node);
341         if (tmp && tmp->task == task) {
342             dlist_del(pos);
343             free(tmp);
344             break;
345         }
346     }
347     aos_sem_signal(&console->sem);
348 }
349 
350 /* find task in console task_list
351  * return 0 : not exist
352  *        1 : exist
353  */
cli_console_check_task_list_node(cli_console * console,void * task)354 int cli_console_check_task_list_node(cli_console *console, void *task)
355 {
356     dlist_t     *pos;
357     dlist_t     *q;
358     wraper_task *tmp;
359 
360     int ret = 0;
361 
362     if ((console == NULL) || (task == NULL)) {
363         return 0;
364     }
365 
366     aos_sem_wait(&console->sem, AOS_WAIT_FOREVER);
367     dlist_for_each_safe(pos, q, &console->task_list) {
368         tmp = aos_list_entry(pos, wraper_task, task_list_node);
369         if (tmp && tmp->task == task) {
370             ret = 1;
371             break;
372         }
373     }
374     aos_sem_signal(&console->sem);
375 
376     return ret;
377 }
378 
379 /* clear console for all binded task; clean task_list for console*/
cli_console_clear_task_list(cli_console * console)380 static void cli_console_clear_task_list(cli_console *console)
381 {
382     dlist_t     *pos;
383     dlist_t     *q;
384     wraper_task *tmp;
385     if (console == NULL) {
386         return;
387     }
388 
389     aos_sem_wait(&console->sem, AOS_WAIT_FOREVER);
390 
391     dlist_for_each_safe(pos, q, &console->task_list) {
392         tmp = aos_list_entry(pos, wraper_task, task_list_node);
393         if (tmp && tmp->task) {
394             cli_task_clear_console(tmp->task);
395             dlist_del(pos);
396             free(tmp);
397         }
398     }
399 
400     aos_sem_signal(&console->sem);
401 }
402 
cli_console_read(cli_console * console,void * buf,size_t nbytes)403 int cli_console_read(cli_console *console, void *buf, size_t nbytes)
404 {
405     int rbytes = -1;
406 
407     if (!cli_console_check_is_in_list(console)) {
408         console = get_current_console();
409     }
410 
411     if (console == NULL) {
412         console = get_current_console();
413     }
414 
415     device_console *dev_console;
416     if (console) {
417         dev_console = console->dev_console;
418         if (dev_console && dev_console->read) {
419             rbytes = dev_console->read(buf, nbytes, console->private_data);
420         }
421     }
422 
423     return rbytes;
424 }
425 
cli_console_write(cli_console * console,const void * buf,size_t nbytes)426 int cli_console_write(cli_console *console, const void *buf, size_t nbytes)
427 {
428     int wbytes = -1, ret;
429 
430     if (!cli_console_check_is_in_list(console)) {
431         console = get_current_console();
432     }
433 
434     if (console == NULL) {
435         console = get_current_console();
436     }
437 
438     device_console *dev_console = NULL;
439     if (console) {
440         ret = aos_sem_wait(&console->sem, AOS_WAIT_FOREVER);
441         dev_console = console->dev_console;
442         if (dev_console && dev_console->write) {
443             wbytes = dev_console->write(buf, nbytes, console->private_data);
444         }
445         if (ret == 0) {
446             /* sem take success*/
447             aos_sem_signal(&console->sem);
448         }
449     }
450     return wbytes;
451 }
452 
cli_console_init(cli_console * console)453 int cli_console_init(cli_console *console)
454 {
455     int ret;
456 
457     device_console *dev_console = NULL;
458 
459     if (console && console->init_flag == 0) {
460         dlist_init(&console->task_list);
461         register_cli_console_to_list(console);
462 
463         ret = aos_sem_new(&console->sem, 1);
464         if (ret) {
465             printf("%s %d %d\r\n", __func__, __LINE__, ret);
466             return ret;
467         }
468 
469         ret = aos_sem_new(&console->console_exit_sem, 0);
470         if (ret) {
471             printf("%s %d %d\r\n", __func__, __LINE__, ret);
472             return ret;
473         }
474 
475         console->att_pid = 0;
476 
477         dev_console = console->dev_console;
478         if (dev_console && dev_console->init) {
479             ret = dev_console->init(console->private_data);
480             if (ret) {
481                 printf("%s %d %d\r\n", __func__, __LINE__, ret);
482                 return ret;
483             }
484             console->exit_flag = 0;
485             console->init_flag = 1;
486         }
487         memset(console->cli_console_inbuf, 0, CLI_INBUF_SIZE);
488     }
489 
490     return 0;
491 }
492 
cli_console_deinit(cli_console * console)493 int cli_console_deinit(cli_console *console)
494 {
495     int ret = -1;
496     device_console *dev_console = NULL;
497 
498     if (global_console != NULL && global_console == console) {
499         set_global_console(NULL);
500     }
501 
502     if (console && console->init_flag == 1) {
503         aos_sem_wait(&console->sem, AOS_WAIT_FOREVER);
504         console->exit_flag = 1;
505         aos_sem_signal(&console->sem);
506 
507         cli_console_clear_task_list(console);
508         remove_cli_console_from_list(console);
509         aos_sem_free(&console->sem);
510         aos_sem_free(&console->console_exit_sem);
511         console->att_pid = 0;
512         dev_console = console->dev_console;
513         if (dev_console && dev_console->deinit) {
514             ret = dev_console->deinit(console->private_data);
515             if (ret == 0) {
516                 console->init_flag = 0;
517             }
518         }
519     }
520     return ret;
521 }
522 
523 /*
524  * create new cli_console
525  * @param dev_console: the device console is attached to the new cli console
526  * @param name: the name of new cli console
527  * @param private_data: the private data of the new cli console
528  */
cli_console_create(device_console * dev_console,const char * name,void * private_data)529 cli_console *cli_console_create(
530             device_console *dev_console,
531             const char *name,
532             void *private_data)
533 {
534     cli_console *console;
535     if (dev_console == NULL) {
536         return NULL;
537     }
538 
539     console = malloc(sizeof(cli_console));
540     if (console == NULL) {
541         return NULL;
542     }
543     memset(console, 0, sizeof(cli_console));
544 
545     console->dev_console = dev_console;
546     memcpy(console->name, name, CLI_CONSOLE_MAX_NAME_LEN - 1 > strlen(name) ? strlen(name) : CLI_CONSOLE_MAX_NAME_LEN - 1);
547     console->private_data = private_data;
548     return console;
549 }
550 
cli_console_destory(cli_console * console)551 int cli_console_destory(cli_console *console)
552 {
553     int ret = -1;
554     if (console) {
555         free(console);
556         ret = 0;
557     }
558     return ret;
559 }
560 
561 /* get current console name
562  * @return the name of current console name
563  */
cli_task_get_console_name(void)564 char *cli_task_get_console_name(void)
565 {
566     cli_console *console;
567     char *name = NULL;
568 
569     console = get_clitask_console();
570     if (console) {
571         name = console->name;
572     }
573 
574     if (name == NULL) {
575         name = default_console->name;
576     }
577 
578     return name;
579 }
580 
581 /* get target console name
582  * @param console: the target console
583  * @return the name of target console
584  * */
cli_console_get_name(cli_console * console)585 char *cli_console_get_name(cli_console *console)
586 {
587     char *name = NULL;
588     if (console) {
589         name = console->name;
590     }
591 
592     if (name == NULL) {
593         name = default_console->name;
594     }
595 
596     return name;
597 }
598 
cli_console_check_invalid(cli_console * console)599 int cli_console_check_invalid(cli_console *console)
600 {
601     if (console == NULL) {
602         return 0;
603     }
604     return 1;
605 }
606 
create_default_console_task(uint32_t stack_size,uint32_t priority)607 int32_t create_default_console_task(uint32_t stack_size, uint32_t priority)
608 {
609     int32_t ret = -1;
610     extern cli_console cli_uart_console;
611 
612     if (mul_console_init_flag == 0) {
613         ret = aos_sem_new(&console_sem, 1);
614         if (ret) {
615             printf("%s %d %d\r\n", __func__, __LINE__, ret);
616             return ret;
617         }
618         mul_console_init_flag = 1;
619     }
620     return cli_console_task_create(&cli_uart_console, stack_size, priority);
621 }
622 
623 /* create a cli console task
624  * @param console: the console which is attached t the new task
625  * @param stack_size: the stack size of the new cli task
626  * @param priority: the priority of the new cli task
627  * */
cli_console_task_create(cli_console * console,uint32_t stack_size,uint32_t priority)628 int cli_console_task_create(cli_console *console, uint32_t stack_size, uint32_t priority)
629 {
630     int32_t ret;
631 
632     if (!cli_console_check_invalid(console)) {
633         return -1;
634     }
635     ret = cli_console_init(console);
636     if (ret) {
637         printf("Error: Failed to init cli console\r\n");
638         return -1;
639     }
640     console->alive = 1;
641 
642     ret = cli_task_create(console->name, cli_main, console, stack_size, priority);
643     if (ret != CLI_OK) {
644         printf("Error: Failed to create cli thread: %d\r\n", ret);
645         return -1;
646     }
647 
648     return 0;
649 }
650 
651 
652 /*
653  * destory cli console task
654  * @param console: cli_console need to be destoryed
655  * @return 0
656  * */
cli_console_task_destory(cli_console * console)657 int cli_console_task_destory(cli_console *console)
658 {
659     if (console == NULL) {
660         return -1;
661     }
662 
663 #if 0
664     if (console == get_default_console()) {
665         printf("Can not delete default console\n");
666         return -1;
667     }
668 #endif
669 
670     cli_console_deinit(console);
671     console->alive = 0;
672 
673     return 0;
674 }
675 
cli_console_current_task_destory(void)676 void cli_console_current_task_destory(void)
677 {
678     cli_console_task_destory(get_clitask_console());
679 }
680 
681 /*
682  * check cli_console exit_flag
683  * @return 0/1, 0:the task should be alive; 1:the task should be deleted
684  * */
cli_console_task_check_exit_flag(void)685 int cli_console_task_check_exit_flag(void)
686 {
687     int exit_flag = 0;
688     cli_console *console;
689 
690     console = get_clitask_console();
691 
692     if (console) {
693         exit_flag = console->exit_flag;
694     } else {
695         exit_flag = 1;
696     }
697 
698     return exit_flag;
699 }
700 
cli_console_set_exit_flag(cli_console * console)701 void cli_console_set_exit_flag(cli_console *console)
702 {
703     if (console) {
704         console->exit_flag = 1;
705     }
706 }
707 
check_console_task_exit(void)708 void check_console_task_exit(void)
709 {
710     krhino_task_dyn_del(NULL);
711 }
712 
cli_console_show_cmd(int argc,char ** argv)713 void cli_console_show_cmd(int argc, char **argv)
714 {
715     dlist_t     *pos;
716     dlist_t     *q;
717     cli_console *tmp;
718 
719     int alive_console_n = 0;
720 
721     aos_cli_printf("-------- console show -----------\r\n");
722     aos_cli_printf("id    name     att\r\n");
723 
724     dlist_for_each_safe(pos, q, &gCliConsolelist) {
725         tmp = aos_list_entry(pos, cli_console, i_list);
726         if (tmp == NULL)
727             break;
728         if (tmp->alive == 1) {
729             alive_console_n++;
730             aos_cli_printf("%d    %s  %d  ", alive_console_n, tmp->name, tmp->att_pid);
731             if (tmp == get_clitask_console()) {
732                 aos_cli_printf("c\r\n");
733             }
734             aos_cli_printf("\r\n");
735         }
736     }
737 }
738 
cli_console_show(void)739 void cli_console_show(void)
740 {
741     cli_console_show_cmd(0, NULL);
742 }
743 
744 ALIOS_CLI_CMD_REGISTER(cli_console_show_cmd, ccs, Console Cli Console Show)
745