Commit 1cb1a277 authored by Tomasz Bursztyka's avatar Tomasz Bursztyka Committed by Fabio Baltieri
Browse files

shell: Add an init command to device module



Optional, this command can be helpful to debug device initialization
process.

Signed-off-by: default avatarTomasz Bursztyka <tobu@bang-olufsen.dk>
parent c30cbe39
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -9,6 +9,17 @@ config DEVICE_SHELL
	help
	  This shell provides access to basic device data.

config DEVICE_SHELL_INIT_CMD
	bool "Device shell init command"
	depends on DEVICE_SHELL
	default y if !SHELL_MINIMAL
	help
	  Add an 'init' command to the device shell module in order
	  to initialize, at runtime and manually, the devices that
	  own the 'zephyr,deferred-init' attribute. Note that if you
	  enable CONFIG_DEVICE_DEPS, it will take dependencies into
	  account.

config DATE_SHELL
	bool "Date shell"
	default y if !SHELL_MINIMAL
+83 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2018 Nordic Semiconductor ASA
 * Copyright (c) 2016 Intel Corporation
 * Copyright (C) 2025 Bang & Olufsen A/S, Denmark
 *
 * SPDX-License-Identifier: Apache-2.0
 */
@@ -117,6 +118,87 @@ static int cmd_device_list(const struct shell *sh,
	return 0;
}

#ifdef CONFIG_DEVICE_SHELL_INIT_CMD
#ifdef CONFIG_DEVICE_DEPS
static int cmd_device_check_deps(const struct device *dev,
				 void *context)
{
	const struct cmd_device_list_visitor_context *ctx = context;

	if (!device_is_ready(dev)) {
		shell_error(ctx->sh, "Device %s is required, but not ready",
			    get_device_name(dev, ctx->buf, ctx->buf_size));
		return -EINVAL;
	}

	return 0;
}
#endif /* CONFIG_DEVICE_DEPS */

static int cmd_device_init(const struct shell *sh, size_t argc, char **argv)
{
	const struct device *dev;
	int ret;

	dev = shell_device_get_binding_all(argv[1]);
	if (dev == NULL) {
		shell_error(sh, "Device unknown (%s)", argv[1]);
		return -ENODEV;
	}

	if (device_is_ready(dev)) {
		shell_info(sh, "Device %s is already initialized", argv[1]);
		return 0;
	}

#ifdef CONFIG_DEVICE_DEPS
	if (!k_is_user_context()) {
		char buf[Z_DEVICE_MAX_NAME_LEN];

		struct cmd_device_list_visitor_context ctx = {
			.sh = sh,
			.buf = buf,
			.buf_size = sizeof(buf),
		};

		ret = device_required_foreach(dev, cmd_device_check_deps, &ctx);
		if (ret < 0) {
			return ret;
		}
	}
#endif /* CONFIG_DEVICE_DEPS */

	ret = device_init(dev);
	if (ret != 0) {
		shell_error(sh, "Device %s initialization failed with err=%d",
			    argv[1], ret);
	} else {
		shell_info(sh, "Device %s initialized successfully", argv[1]);
	}

	return ret;
}

static void device_name_get_non_ready(size_t idx,
				      struct shell_static_entry *entry)
{
	const struct device *dev = shell_device_lookup_non_ready(idx, NULL);

	entry->syntax = dev != NULL ? dev->name : NULL;
	entry->handler = NULL;
	entry->help = "device";
	entry->subcmd = NULL;
}

SHELL_DYNAMIC_CMD_CREATE(dsub_device_name_non_ready, device_name_get_non_ready);

#define DEVICE_INIT_CMD SHELL_CMD_ARG(init, &dsub_device_name_non_ready, \
				      "Manually initialize a device",	\
				      cmd_device_init, 2, 0),
#else
#define DEVICE_INIT_CMD
#endif /* CONFIG_DEVICE_SHELL_INIT_CMD */

#ifdef CONFIG_PM_DEVICE_RUNTIME
static int cmd_device_pm_toggle(const struct shell *sh,
			 size_t argc, char **argv)
@@ -157,9 +239,9 @@ static int cmd_device_pm_toggle(const struct shell *sh,
#endif /* CONFIG_PM_DEVICE_RUNTIME  */



SHELL_STATIC_SUBCMD_SET_CREATE(sub_device,
	SHELL_CMD(list, NULL, "List configured devices", cmd_device_list),
	DEVICE_INIT_CMD
	PM_SHELL_CMD
	SHELL_SUBCMD_SET_END /* Array terminated. */
);