1 /*
2 * Copyright (c) 2018 Intel Corporation
3 * Copyright (c) 2021 Dennis Ruffer <daruffer@gmail.com>
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Use "device list" command for GPIO port names
8 */
9
10 #include <zephyr/sys/printk.h>
11 #include <zephyr/shell/shell.h>
12 #include <zephyr/init.h>
13 #include <string.h>
14 #include <stdio.h>
15 #include <zephyr/drivers/gpio.h>
16 #include <stdlib.h>
17 #include <ctype.h>
18 #include <zephyr/logging/log.h>
19
20 #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
21
22 LOG_MODULE_REGISTER(gpio_shell);
23
24 struct args_index {
25 uint8_t port;
26 uint8_t index;
27 uint8_t mode;
28 uint8_t value;
29 };
30
31 static const struct args_index args_indx = {
32 .port = 1,
33 .index = 2,
34 .mode = 3,
35 .value = 3,
36 };
37
cmd_gpio_conf(const struct shell * sh,size_t argc,char ** argv)38 static int cmd_gpio_conf(const struct shell *sh, size_t argc, char **argv)
39 {
40 uint8_t index = 0U;
41 int type = GPIO_OUTPUT;
42 const struct device *dev;
43
44 if (isdigit((unsigned char)argv[args_indx.index][0]) != 0 &&
45 isalpha((unsigned char)argv[args_indx.mode][0]) != 0) {
46 index = (uint8_t)atoi(argv[args_indx.index]);
47 if (!strcmp(argv[args_indx.mode], "in")) {
48 type = GPIO_INPUT;
49 } else if (!strcmp(argv[args_indx.mode], "inu")) {
50 type = GPIO_INPUT | GPIO_PULL_UP;
51 } else if (!strcmp(argv[args_indx.mode], "ind")) {
52 type = GPIO_INPUT | GPIO_PULL_DOWN;
53 } else if (!strcmp(argv[args_indx.mode], "out")) {
54 type = GPIO_OUTPUT;
55 } else {
56 return 0;
57 }
58 } else {
59 shell_error(sh, "Wrong parameters for conf");
60 return -ENOTSUP;
61 }
62
63 dev = device_get_binding(argv[args_indx.port]);
64
65 if (dev != NULL) {
66 index = (uint8_t)atoi(argv[args_indx.index]);
67 shell_print(sh, "Configuring %s pin %d",
68 argv[args_indx.port], index);
69 gpio_pin_configure(dev, index, type);
70 }
71
72 return 0;
73 }
74
cmd_gpio_get(const struct shell * sh,size_t argc,char ** argv)75 static int cmd_gpio_get(const struct shell *sh,
76 size_t argc, char **argv)
77 {
78 const struct device *dev;
79 uint8_t index = 0U;
80 int rc;
81
82 if (isdigit((unsigned char)argv[args_indx.index][0]) != 0) {
83 index = (uint8_t)atoi(argv[args_indx.index]);
84 } else {
85 shell_error(sh, "Wrong parameters for get");
86 return -EINVAL;
87 }
88
89 dev = device_get_binding(argv[args_indx.port]);
90
91 if (dev != NULL) {
92 index = (uint8_t)atoi(argv[2]);
93 shell_print(sh, "Reading %s pin %d",
94 argv[args_indx.port], index);
95 rc = gpio_pin_get(dev, index);
96 if (rc >= 0) {
97 shell_print(sh, "Value %d", rc);
98 } else {
99 shell_error(sh, "Error %d reading value", rc);
100 return -EIO;
101 }
102 }
103
104 return 0;
105 }
106
cmd_gpio_set(const struct shell * sh,size_t argc,char ** argv)107 static int cmd_gpio_set(const struct shell *sh,
108 size_t argc, char **argv)
109 {
110 const struct device *dev;
111 uint8_t index = 0U;
112 uint8_t value = 0U;
113
114 if (isdigit((unsigned char)argv[args_indx.index][0]) != 0 &&
115 isdigit((unsigned char)argv[args_indx.value][0]) != 0) {
116 index = (uint8_t)atoi(argv[args_indx.index]);
117 value = (uint8_t)atoi(argv[args_indx.value]);
118 } else {
119 shell_print(sh, "Wrong parameters for set");
120 return -EINVAL;
121 }
122 dev = device_get_binding(argv[args_indx.port]);
123
124 if (dev != NULL) {
125 index = (uint8_t)atoi(argv[2]);
126 shell_print(sh, "Writing to %s pin %d",
127 argv[args_indx.port], index);
128 gpio_pin_set(dev, index, value);
129 }
130
131 return 0;
132 }
133
134
135 /* 500 msec = 1/2 sec */
136 #define SLEEP_TIME_MS 500
137
cmd_gpio_blink(const struct shell * sh,size_t argc,char ** argv)138 static int cmd_gpio_blink(const struct shell *sh,
139 size_t argc, char **argv)
140 {
141 const struct device *dev;
142 uint8_t index = 0U;
143 uint8_t value = 0U;
144 size_t count = 0;
145 char data;
146
147 if (isdigit((unsigned char)argv[args_indx.index][0]) != 0) {
148 index = (uint8_t)atoi(argv[args_indx.index]);
149 } else {
150 shell_error(sh, "Wrong parameters for blink");
151 return -EINVAL;
152 }
153 dev = device_get_binding(argv[args_indx.port]);
154
155 if (dev != NULL) {
156 index = (uint8_t)atoi(argv[2]);
157 shell_fprintf(sh, SHELL_NORMAL, "Blinking port %s index %d.", argv[1], index);
158 shell_fprintf(sh, SHELL_NORMAL, " Hit any key to exit");
159
160 /* dummy read to clear any pending input */
161 (void)sh->iface->api->read(sh->iface, &data, sizeof(data), &count);
162
163 while (true) {
164 (void)sh->iface->api->read(sh->iface, &data, sizeof(data), &count);
165 if (count != 0) {
166 break;
167 }
168 gpio_pin_set(dev, index, value);
169 value = !value;
170 k_msleep(SLEEP_TIME_MS);
171 }
172
173 shell_fprintf(sh, SHELL_NORMAL, "\n");
174 }
175
176 return 0;
177 }
178
179 SHELL_STATIC_SUBCMD_SET_CREATE(sub_gpio,
180 SHELL_CMD_ARG(conf, NULL, "Configure GPIO", cmd_gpio_conf, 4, 0),
181 SHELL_CMD_ARG(get, NULL, "Get GPIO value", cmd_gpio_get, 3, 0),
182 SHELL_CMD_ARG(set, NULL, "Set GPIO", cmd_gpio_set, 4, 0),
183 SHELL_CMD_ARG(blink, NULL, "Blink GPIO", cmd_gpio_blink, 3, 0),
184 SHELL_SUBCMD_SET_END /* Array terminated. */
185 );
186
187 SHELL_CMD_REGISTER(gpio, &sub_gpio, "GPIO commands", NULL);
188