Skip to content

Commit accdb4d

Browse files
committed
shell: utils: Improve utility by addding non-ready devices functions
This are necessary changes to handle non-initialized devices. I.e. devices which 'zephyr,deferred-init' DTS attribute was set. Later on, such utility will prove to be useful on improving devices shell module. Signed-off-by: Tomasz Bursztyka <[email protected]>
1 parent 016362a commit accdb4d

File tree

3 files changed

+145
-6
lines changed

3 files changed

+145
-6
lines changed

include/zephyr/shell/shell.h

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,44 @@ struct shell_static_args {
129129
* start with this text. Pass null if no prefix match is required.
130130
*/
131131
const struct device *shell_device_lookup(size_t idx,
132-
const char *prefix);
132+
const char *prefix);
133+
134+
/**
135+
* @brief Get by index a device that matches .
136+
*
137+
* This can be used, for example, to identify I2C_1 as the second I2C
138+
* device.
139+
*
140+
* Devices that failed to initialize - or deferred to be - are included
141+
* from the candidates for a match, minus the ones who do not have
142+
* a non-empty name.
143+
*
144+
* @param idx the device number starting from zero.
145+
*
146+
* @param prefix optional name prefix used to restrict candidate
147+
* devices. Indexing is done relative to devices with names that
148+
* start with this text. Pass null if no prefix match is required.
149+
*/
150+
const struct device *shell_device_lookup_all(size_t idx,
151+
const char *prefix);
152+
153+
/**
154+
* @brief Get by index a non-initialized device that matches .
155+
*
156+
* This can be used, for example, to identify I2C_1 as the second I2C
157+
* device.
158+
*
159+
* Devices that initialized successfully or do not have a non-empty name
160+
* are excluded.
161+
*
162+
* @param idx the device number starting from zero.
163+
*
164+
* @param prefix optional name prefix used to restrict candidate
165+
* devices. Indexing is done relative to devices with names that
166+
* start with this text. Pass null if no prefix match is required.
167+
*/
168+
const struct device *shell_device_lookup_non_ready(size_t idx,
169+
const char *prefix);
133170

134171
/**
135172
* @brief Filter callback type, for use with shell_device_lookup_filter
@@ -181,6 +218,23 @@ const struct device *shell_device_filter(size_t idx,
181218
*/
182219
const struct device *shell_device_get_binding(const char *name);
183220

221+
/**
222+
* @brief Get a @ref device reference from its @ref device.name field or label.
223+
*
224+
* This function iterates through the devices on the system. If a device with
225+
* the given @p name field is found, this function returns a pointer to the
226+
* device.
227+
*
228+
* If no device has the given @p name, this function returns `NULL`.
229+
*
230+
* @param name device name to search for. A null pointer, or a pointer to an
231+
* empty string, will cause NULL to be returned.
232+
*
233+
* @return pointer to device structure with the given name; `NULL` if the device
234+
* is not found.
235+
*/
236+
const struct device *shell_device_get_binding_all(const char *name);
237+
184238
/**
185239
* @brief Shell command handler prototype.
186240
*

subsys/shell/modules/device_service.c

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*
22
* Copyright (c) 2018 Nordic Semiconductor ASA
33
* Copyright (c) 2016 Intel Corporation
4+
* Copyright (C) 2025 Bang & Olufsen A/S, Denmark
45
*
56
* SPDX-License-Identifier: Apache-2.0
67
*/
@@ -117,6 +118,33 @@ static int cmd_device_list(const struct shell *sh,
117118
return 0;
118119
}
119120

121+
static int cmd_device_init(const struct shell *sh, size_t argc, char **argv)
122+
{
123+
const struct device *dev;
124+
int ret;
125+
126+
dev = device_get_binding(argv[1]);
127+
if (dev == NULL) {
128+
shell_error(sh, "Device unknown (%s)", argv[1]);
129+
return -ENODEV;
130+
}
131+
132+
if (device_is_ready(dev)) {
133+
shell_info(sh, "Device %s is already initialized", argv[1]);
134+
return 0;
135+
}
136+
137+
ret = device_init(dev);
138+
if (ret != 0) {
139+
shell_error(sh, "Device %s initalization failed with err=%d",
140+
argv[1], ret);
141+
} else {
142+
shell_info(sh, "Device %s inialized successfully", argv[1]);
143+
}
144+
145+
return ret;
146+
}
147+
120148
#ifdef CONFIG_PM_DEVICE_RUNTIME
121149
static int cmd_device_pm_toggle(const struct shell *sh,
122150
size_t argc, char **argv)
@@ -156,10 +184,24 @@ static int cmd_device_pm_toggle(const struct shell *sh,
156184
#define PM_SHELL_CMD
157185
#endif /* CONFIG_PM_DEVICE_RUNTIME */
158186

187+
static void device_name_get_non_ready(size_t idx,
188+
struct shell_static_entry *entry)
189+
{
190+
const struct device *dev = shell_device_lookup_non_ready(idx, NULL);
191+
192+
entry->syntax = dev != NULL ? dev->name : NULL;
193+
entry->handler = NULL;
194+
entry->help = "device";
195+
entry->subcmd = NULL;
196+
}
159197

198+
SHELL_DYNAMIC_CMD_CREATE(dsub_device_name_non_ready, device_name_get_non_ready);
160199

161200
SHELL_STATIC_SUBCMD_SET_CREATE(sub_device,
162-
SHELL_CMD(list, NULL, "List configured devices", cmd_device_list),
201+
SHELL_CMD(list, &dsub_device_name_all,
202+
"List configured devices", cmd_device_list),
203+
SHELL_CMD_ARG(init, &dsub_device_name_non_ready,
204+
"Manually initialize a device", cmd_device_init, 1, 0),
163205
PM_SHELL_CMD
164206
SHELL_SUBCMD_SET_END /* Array terminated. */
165207
);

subsys/shell/shell_utils.c

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -496,17 +496,28 @@ void z_shell_cmd_trim(const struct shell *sh)
496496
sh->ctx->cmd_buff_pos = sh->ctx->cmd_buff_len;
497497
}
498498

499+
enum shell_device_status {
500+
SHELL_DEVICE_STATUS_ANY,
501+
SHELL_DEVICE_STATUS_READY,
502+
SHELL_DEVICE_STATUS_NON_READY
503+
};
504+
499505
static const struct device *shell_device_internal(size_t idx,
500506
const char *prefix,
501-
shell_device_filter_t filter)
507+
shell_device_filter_t filter,
508+
enum shell_device_status status)
502509
{
503510
size_t match_idx = 0;
504511
const struct device *dev;
505512
size_t len = z_device_get_all_static(&dev);
506513
const struct device *dev_end = dev + len;
507514

508515
while (dev < dev_end) {
509-
if (device_is_ready(dev)
516+
if ((status == SHELL_DEVICE_STATUS_ANY
517+
|| (status == SHELL_DEVICE_STATUS_READY &&
518+
device_is_ready(dev))
519+
|| (status == SHELL_DEVICE_STATUS_NON_READY &&
520+
!device_is_ready(dev)))
510521
&& (dev->name != NULL)
511522
&& (strlen(dev->name) != 0)
512523
&& ((prefix == NULL)
@@ -527,13 +538,29 @@ static const struct device *shell_device_internal(size_t idx,
527538
const struct device *shell_device_filter(size_t idx,
528539
shell_device_filter_t filter)
529540
{
530-
return shell_device_internal(idx, NULL, filter);
541+
return shell_device_internal(idx, NULL, filter,
542+
SHELL_DEVICE_STATUS_READY);
531543
}
532544

533545
const struct device *shell_device_lookup(size_t idx,
534546
const char *prefix)
535547
{
536-
return shell_device_internal(idx, prefix, NULL);
548+
return shell_device_internal(idx, prefix, NULL,
549+
SHELL_DEVICE_STATUS_READY);
550+
}
551+
552+
const struct device *shell_device_lookup_all(size_t idx,
553+
const char *prefix)
554+
{
555+
return shell_device_internal(idx, prefix, NULL,
556+
SHELL_DEVICE_STATUS_ANY);
557+
}
558+
559+
const struct device *shell_device_lookup_non_ready(size_t idx,
560+
const char *prefix)
561+
{
562+
return shell_device_internal(idx, prefix, NULL,
563+
SHELL_DEVICE_STATUS_NON_READY);
537564
}
538565

539566
const struct device *shell_device_get_binding(const char *name)
@@ -547,6 +574,22 @@ const struct device *shell_device_get_binding(const char *name)
547574
return dev;
548575
}
549576

577+
const struct device *shell_device_get_binding_all(const char *name)
578+
{
579+
const struct device *dev;
580+
size_t len = z_device_get_all_static(&dev);
581+
const struct device *dev_end = dev + len;
582+
583+
for (; dev < dev_end; dev++) {
584+
if ((dev->name != NULL) &&
585+
(strncmp(name, dev->name, strlen(name)) == 0)) {
586+
return dev;
587+
}
588+
}
589+
590+
return NULL;
591+
}
592+
550593
long shell_strtol(const char *str, int base, int *err)
551594
{
552595
long val;

0 commit comments

Comments
 (0)