1 /*
2 * Copyright (c) 2024 Yishai Jaffe <yishai1999@gmail.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/drivers/uart.h>
8 #include <zephyr/shell/shell.h>
9 #include <stdlib.h>
10
11 #include <zephyr/logging/log.h>
12 LOG_MODULE_REGISTER(uart_shell, CONFIG_LOG_DEFAULT_LEVEL);
13
device_is_uart(const struct device * dev)14 static bool device_is_uart(const struct device *dev)
15 {
16 return DEVICE_API_IS(uart, dev);
17 }
18
cmd_uart_write(const struct shell * sh,size_t argc,char ** argv)19 static int cmd_uart_write(const struct shell *sh, size_t argc, char **argv)
20 {
21 char *s_dev_name = argv[1];
22 const struct device *dev = shell_device_get_binding(s_dev_name);
23
24 if (!dev || !device_is_uart(dev)) {
25 shell_error(sh, "UART: Device driver %s not found.", s_dev_name);
26 return -ENODEV;
27 }
28
29 char *buf = argv[2];
30 int msg_len = strlen(buf);
31
32 for (int i = 0; i < msg_len; i++) {
33 uart_poll_out(dev, buf[i]);
34 }
35
36 return 0;
37 }
38
39
cmd_uart_read(const struct shell * sh,size_t argc,char ** argv)40 static int cmd_uart_read(const struct shell *sh, size_t argc, char **argv)
41 {
42 char *s_dev_name = argv[1];
43 const struct device *dev = shell_device_get_binding(s_dev_name);
44 int ret = 0;
45 char chr;
46 k_timepoint_t end;
47 uint64_t seconds;
48
49 if (!dev || !device_is_uart(dev)) {
50 shell_error(sh, "UART: Device driver %s not found.", s_dev_name);
51 return -ENODEV;
52 }
53
54 seconds = shell_strtoul(argv[2], 10, &ret);
55 if (ret != 0) {
56 shell_help(sh);
57 return SHELL_CMD_HELP_PRINTED;
58 }
59 if (seconds < 1) {
60 return -EINVAL;
61 }
62 shell_info(sh, "UART: Read for %lli seconds from %s.", seconds, s_dev_name);
63
64 end = sys_timepoint_calc(K_SECONDS(seconds));
65 while (!sys_timepoint_expired(end)) {
66 ret = uart_poll_in(dev, &chr);
67 if (ret == 0) {
68 shell_fprintf_normal(sh, "%c", chr);
69 }
70 if (ret != 0 && ret != -1) {
71 shell_error(sh, "Failed to read from UART (%d)", ret);
72 return ret;
73 }
74 }
75
76 shell_fprintf_normal(sh, "\n");
77
78 return 0;
79 }
80
81
cmd_uart_baudrate(const struct shell * sh,size_t argc,char ** argv)82 static int cmd_uart_baudrate(const struct shell *sh, size_t argc, char **argv)
83 {
84 char *s_dev_name = argv[1];
85 const struct device *dev;
86 struct uart_config cfg;
87 uint32_t baudrate;
88 int ret = 0;
89
90 dev = shell_device_get_binding(s_dev_name);
91 if (!dev || !device_is_uart(dev)) {
92 shell_error(sh, "UART: Device driver %s not found.", s_dev_name);
93 return -ENODEV;
94 }
95
96 baudrate = shell_strtoul(argv[2], 10, &ret);
97 if (ret != 0) {
98 shell_help(sh);
99 return SHELL_CMD_HELP_PRINTED;
100 }
101 ret = uart_config_get(dev, &cfg);
102 if (ret < 0) {
103 shell_error(sh, "UART: Failed to get current configuration: %d", ret);
104 return ret;
105 }
106 cfg.baudrate = baudrate;
107
108 ret = uart_configure(dev, &cfg);
109 if (ret < 0) {
110 shell_error(sh, "UART: Failed to configure device: %d", ret);
111 return ret;
112 }
113 return 0;
114 }
115
cmd_uart_flow_control(const struct shell * sh,size_t argc,char ** argv)116 static int cmd_uart_flow_control(const struct shell *sh, size_t argc, char **argv)
117 {
118 char *s_dev_name = argv[1];
119 const struct device *dev;
120 struct uart_config cfg;
121 uint8_t flow_control;
122 int ret;
123
124 dev = shell_device_get_binding(s_dev_name);
125 if (!dev || !device_is_uart(dev)) {
126 shell_error(sh, "UART: Device driver %s not found.", s_dev_name);
127 return -ENODEV;
128 }
129
130 if (!strcmp(argv[2], "none")) {
131 flow_control = UART_CFG_FLOW_CTRL_NONE;
132 } else if (!strcmp(argv[2], "rtscts")) {
133 flow_control = UART_CFG_FLOW_CTRL_RTS_CTS;
134 } else if (!strcmp(argv[2], "dtrdsr")) {
135 flow_control = UART_CFG_FLOW_CTRL_DTR_DSR;
136 } else if (!strcmp(argv[2], "rs485")) {
137 flow_control = UART_CFG_FLOW_CTRL_RS485;
138 } else {
139 shell_error(sh, "Unknown: '%s'", argv[2]);
140 shell_help(sh);
141 return SHELL_CMD_HELP_PRINTED;
142 }
143
144 ret = uart_config_get(dev, &cfg);
145 if (ret < 0) {
146 shell_error(sh, "UART: Failed to get current configuration: %d", ret);
147 return ret;
148 }
149 cfg.flow_ctrl = flow_control;
150
151 ret = uart_configure(dev, &cfg);
152 if (ret < 0) {
153 shell_error(sh, "UART: Failed to configure device: %d", ret);
154 return ret;
155 }
156 return 0;
157 }
158
device_name_get(size_t idx,struct shell_static_entry * entry)159 static void device_name_get(size_t idx, struct shell_static_entry *entry)
160 {
161 const struct device *dev = shell_device_filter(idx, device_is_uart);
162
163 entry->syntax = (dev != NULL) ? dev->name : NULL;
164 entry->handler = NULL;
165 entry->help = NULL;
166 entry->subcmd = NULL;
167 }
168
169 SHELL_DYNAMIC_CMD_CREATE(dsub_device_name, device_name_get);
170
171 SHELL_STATIC_SUBCMD_SET_CREATE(sub_uart_cmds,
172 SHELL_CMD_ARG(write, &dsub_device_name,
173 SHELL_HELP("Write data to the UART device",
174 "<device> <data>"),
175 cmd_uart_write, 3, 0),
176 SHELL_CMD_ARG(read, &dsub_device_name,
177 SHELL_HELP("Read data from the UART device",
178 "<device> <duration in secs>"),
179 cmd_uart_read, 3, 0),
180 SHELL_CMD_ARG(baudrate, &dsub_device_name,
181 SHELL_HELP("Configure the UART device baudrate",
182 "<device> <baudrate>"),
183 cmd_uart_baudrate, 3, 0),
184 SHELL_CMD_ARG(fc, &dsub_device_name,
185 SHELL_HELP("Configure the UART device flow control",
186 "<device> <none|rtscts|dtrdsr|rs485>"),
187 cmd_uart_flow_control, 3, 0),
188 SHELL_SUBCMD_SET_END /* Array terminated. */
189 );
190
191 SHELL_CMD_REGISTER(uart, &sub_uart_cmds, "UART commands", NULL);
192