You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
167 lines
4.0 KiB
167 lines
4.0 KiB
/* |
|
* Copyright (c) 2018 Nordic Semiconductor ASA |
|
* Copyright (c) 2016 Intel Corporation |
|
* |
|
* SPDX-License-Identifier: Apache-2.0 |
|
*/ |
|
|
|
#include <zephyr/shell/shell.h> |
|
#include <zephyr/init.h> |
|
#include <string.h> |
|
#include <stdio.h> |
|
#include <zephyr/device.h> |
|
#include <zephyr/pm/device.h> |
|
#include <zephyr/pm/device_runtime.h> |
|
#include <zephyr/arch/arch_interface.h> |
|
|
|
static const char *get_device_name(const struct device *dev, |
|
char *buf, |
|
size_t len) |
|
{ |
|
const char *name = dev->name; |
|
|
|
if ((name == NULL) || (name[0] == 0)) { |
|
snprintf(buf, len, "[%p]", dev); |
|
name = buf; |
|
} |
|
|
|
return name; |
|
} |
|
|
|
#ifdef CONFIG_DEVICE_DEPS |
|
struct cmd_device_list_visitor_context { |
|
const struct shell *sh; |
|
char *buf; |
|
size_t buf_size; |
|
}; |
|
|
|
static int cmd_device_list_visitor(const struct device *dev, |
|
void *context) |
|
{ |
|
const struct cmd_device_list_visitor_context *ctx = context; |
|
|
|
shell_fprintf(ctx->sh, SHELL_NORMAL, " requires: %s\n", |
|
get_device_name(dev, ctx->buf, ctx->buf_size)); |
|
|
|
return 0; |
|
} |
|
#endif /* CONFIG_DEVICE_DEPS */ |
|
|
|
static int cmd_device_list(const struct shell *sh, |
|
size_t argc, char **argv) |
|
{ |
|
const struct device *devlist; |
|
size_t devcnt = z_device_get_all_static(&devlist); |
|
const struct device *devlist_end = devlist + devcnt; |
|
const struct device *dev; |
|
|
|
ARG_UNUSED(argc); |
|
ARG_UNUSED(argv); |
|
|
|
shell_fprintf(sh, SHELL_NORMAL, "devices:\n"); |
|
|
|
for (dev = devlist; dev < devlist_end; dev++) { |
|
char buf[20]; |
|
const char *name = get_device_name(dev, buf, sizeof(buf)); |
|
const char *state = "READY"; |
|
int usage; |
|
|
|
shell_fprintf(sh, SHELL_NORMAL, "- %s", name); |
|
if (!device_is_ready(dev)) { |
|
state = "DISABLED"; |
|
} else { |
|
#ifdef CONFIG_PM_DEVICE |
|
enum pm_device_state st = PM_DEVICE_STATE_ACTIVE; |
|
int err = pm_device_state_get(dev, &st); |
|
|
|
if (!err) { |
|
state = pm_device_state_str(st); |
|
} |
|
#endif /* CONFIG_PM_DEVICE */ |
|
} |
|
|
|
usage = pm_device_runtime_usage(dev); |
|
if (usage >= 0) { |
|
shell_fprintf(sh, SHELL_NORMAL, " (%s, usage=%d)\n", state, usage); |
|
} else { |
|
shell_fprintf(sh, SHELL_NORMAL, " (%s)\n", state); |
|
} |
|
|
|
#ifdef CONFIG_DEVICE_DEPS |
|
if (!k_is_user_context()) { |
|
struct cmd_device_list_visitor_context ctx = { |
|
.sh = sh, |
|
.buf = buf, |
|
.buf_size = sizeof(buf), |
|
}; |
|
|
|
(void)device_required_foreach(dev, cmd_device_list_visitor, &ctx); |
|
} |
|
#endif /* CONFIG_DEVICE_DEPS */ |
|
|
|
#ifdef CONFIG_DEVICE_DT_METADATA |
|
const struct device_dt_nodelabels *nl = device_get_dt_nodelabels(dev); |
|
|
|
if (nl != NULL && nl->num_nodelabels > 0) { |
|
shell_fprintf(sh, SHELL_NORMAL, " DT node labels:"); |
|
for (size_t j = 0; j < nl->num_nodelabels; j++) { |
|
const char *nodelabel = nl->nodelabels[j]; |
|
|
|
shell_fprintf(sh, SHELL_NORMAL, " %s", nodelabel); |
|
} |
|
shell_fprintf(sh, SHELL_NORMAL, "\n"); |
|
} |
|
#endif /* CONFIG_DEVICE_DT_METADATAa */ |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
#ifdef CONFIG_PM_DEVICE_RUNTIME |
|
static int cmd_device_pm_toggle(const struct shell *sh, |
|
size_t argc, char **argv) |
|
{ |
|
const struct device *dev; |
|
enum pm_device_state pm_state; |
|
|
|
dev = device_get_binding(argv[1]); |
|
if (dev == NULL) { |
|
shell_error(sh, "Device unknown (%s)", argv[1]); |
|
return -ENODEV; |
|
} |
|
|
|
if (!pm_device_runtime_is_enabled(dev)) { |
|
shell_error(sh, "Device (%s) does not have runtime power management", |
|
argv[1]); |
|
return -ENOTSUP; |
|
} |
|
|
|
(void)pm_device_state_get(dev, &pm_state); |
|
|
|
if (pm_state == PM_DEVICE_STATE_ACTIVE) { |
|
shell_fprintf(sh, SHELL_NORMAL, "pm_device_runtime_put(%s)\n", |
|
argv[1]); |
|
pm_device_runtime_put(dev); |
|
} else { |
|
shell_fprintf(sh, SHELL_NORMAL, "pm_device_runtime_get(%s)\n", |
|
argv[1]); |
|
pm_device_runtime_get(dev); |
|
} |
|
|
|
return 0; |
|
} |
|
#define PM_SHELL_CMD SHELL_CMD(pm_toggle, NULL, "Toggle device power (pm get/put)",\ |
|
cmd_device_pm_toggle), |
|
#else |
|
#define PM_SHELL_CMD |
|
#endif /* CONFIG_PM_DEVICE_RUNTIME */ |
|
|
|
|
|
|
|
SHELL_STATIC_SUBCMD_SET_CREATE(sub_device, |
|
SHELL_CMD(list, NULL, "List configured devices", cmd_device_list), |
|
PM_SHELL_CMD |
|
SHELL_SUBCMD_SET_END /* Array terminated. */ |
|
); |
|
|
|
SHELL_CMD_REGISTER(device, &sub_device, "Device commands", NULL);
|
|
|