1 /*
2  * Copyright (c) 2018 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <stdio.h>
9 #include <zephyr/sys/printk.h>
10 #include <zephyr/shell/shell.h>
11 #include <zephyr/shell/shell_uart.h>
12 
13 #include <openthread.h>
14 
15 #include <openthread/cli.h>
16 #include <openthread/instance.h>
17 
18 #include "platform-zephyr.h"
19 
20 #define OT_SHELL_BUFFER_SIZE CONFIG_SHELL_CMD_BUFF_SIZE
21 
22 static char rx_buffer[OT_SHELL_BUFFER_SIZE];
23 
24 static const struct shell *shell_p;
25 static bool is_shell_initialized;
26 
ot_console_cb(void * context,const char * format,va_list arg)27 static int ot_console_cb(void *context, const char *format, va_list arg)
28 {
29 	ARG_UNUSED(context);
30 
31 	if (shell_p == NULL) {
32 		return 0;
33 	}
34 
35 	shell_vfprintf(shell_p, SHELL_NORMAL, format, arg);
36 
37 	return 0;
38 }
39 
40 #define SHELL_HELP_OT	"OpenThread subcommands\n" \
41 			"Use \"ot help\" to get the list of subcommands"
42 
ot_cmd(const struct shell * sh,size_t argc,char * argv[])43 static int ot_cmd(const struct shell *sh, size_t argc, char *argv[])
44 {
45 	char *buf_ptr = rx_buffer;
46 	size_t buf_len = OT_SHELL_BUFFER_SIZE;
47 	size_t arg_len = 0;
48 	int i;
49 
50 	if (!is_shell_initialized) {
51 		return -ENOEXEC;
52 	}
53 
54 	for (i = 1; i < argc; i++) {
55 		if (arg_len) {
56 			buf_len -= arg_len + 1;
57 			if (buf_len) {
58 				buf_ptr[arg_len] = ' ';
59 			}
60 			buf_ptr += arg_len + 1;
61 		}
62 
63 		arg_len = snprintk(buf_ptr, buf_len, "%s", argv[i]);
64 
65 		if (arg_len >= buf_len) {
66 			shell_fprintf(sh, SHELL_WARNING,
67 				      "OT shell buffer full\n");
68 			return -ENOEXEC;
69 		}
70 	}
71 
72 	if (i == argc) {
73 		buf_len -= arg_len;
74 	}
75 
76 	shell_p = sh;
77 
78 	openthread_mutex_lock();
79 	otCliInputLine(rx_buffer);
80 	openthread_mutex_unlock();
81 
82 	return 0;
83 }
84 
85 SHELL_CMD_ARG_REGISTER(ot, NULL, SHELL_HELP_OT, ot_cmd, 2, 255);
86 
platformShellInit(otInstance * aInstance)87 void platformShellInit(otInstance *aInstance)
88 {
89 	if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL)) {
90 		shell_p = shell_backend_uart_get_ptr();
91 	} else {
92 		shell_p = NULL;
93 	}
94 
95 	otCliInit(aInstance, ot_console_cb, NULL);
96 	is_shell_initialized = true;
97 }
98