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