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