drivers: audio: add Audio Codec shell commands
Add shell commands to start, stop and set properties of an Audio Codec device. Signed-off-by: Benjamin Lemouzy <blemouzy@centralp.fr>
This commit is contained in:
parent
5690387462
commit
9fd0185c3b
3 changed files with 205 additions and 0 deletions
|
|
@ -7,3 +7,4 @@ zephyr_library_sources_ifdef(CONFIG_AUDIO_MPXXDTYY mpxxdtyy.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_AUDIO_MPXXDTYY mpxxdtyy-i2s.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_AUDIO_DMIC_NRFX_PDM dmic_nrfx_pdm.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_AUDIO_TAS6422DAC tas6422dac.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_AUDIO_CODEC_SHELL codec_shell.c)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,13 @@ config AUDIO_CODEC_INIT_PRIORITY
|
|||
help
|
||||
Audio codec device driver initialization priority.
|
||||
|
||||
config AUDIO_CODEC_SHELL
|
||||
bool "Audio Codec shell"
|
||||
default y
|
||||
depends on SHELL
|
||||
help
|
||||
Enable the Audio Codec shell with Audio Codec related commands.
|
||||
|
||||
module = AUDIO_CODEC
|
||||
module-str = audio codec
|
||||
source "subsys/logging/Kconfig.template.log_config"
|
||||
|
|
|
|||
197
drivers/audio/codec_shell.c
Normal file
197
drivers/audio/codec_shell.c
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Centralp
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/shell/shell.h>
|
||||
#include <zephyr/audio/codec.h>
|
||||
|
||||
#define CODEC_START_HELP \
|
||||
"Start output audio playback. Syntax:\n" \
|
||||
"<device>"
|
||||
|
||||
#define CODEC_STOP_HELP \
|
||||
"Stop output audio playback. Syntax:\n" \
|
||||
"<device>"
|
||||
|
||||
#define CODEC_SET_PROP_HELP \
|
||||
"Set a codec property. Syntax:\n" \
|
||||
"<device> <property> <channel> <value>"
|
||||
|
||||
#define CODEC_APPLY_PROP_HELP \
|
||||
"Apply any cached properties. Syntax:\n" \
|
||||
"<device>"
|
||||
|
||||
static const char *const codec_property_name[] = {
|
||||
[AUDIO_PROPERTY_OUTPUT_VOLUME] = "volume",
|
||||
[AUDIO_PROPERTY_OUTPUT_MUTE] = "mute",
|
||||
};
|
||||
|
||||
static const char *const codec_channel_name[] = {
|
||||
[AUDIO_CHANNEL_FRONT_LEFT] = "front_left",
|
||||
[AUDIO_CHANNEL_FRONT_RIGHT] = "front_right",
|
||||
[AUDIO_CHANNEL_LFE] = "lfe",
|
||||
[AUDIO_CHANNEL_FRONT_CENTER] = "front_center",
|
||||
[AUDIO_CHANNEL_REAR_LEFT] = "rear_left",
|
||||
[AUDIO_CHANNEL_REAR_RIGHT] = "rear_right",
|
||||
[AUDIO_CHANNEL_REAR_CENTER] = "rear_center",
|
||||
[AUDIO_CHANNEL_SIDE_LEFT] = "side_left",
|
||||
[AUDIO_CHANNEL_SIDE_RIGHT] = "side_right",
|
||||
[AUDIO_CHANNEL_ALL] = "all",
|
||||
};
|
||||
|
||||
struct args_index {
|
||||
uint8_t device;
|
||||
uint8_t property;
|
||||
uint8_t channel;
|
||||
uint8_t value;
|
||||
};
|
||||
|
||||
static const struct args_index args_indx = {
|
||||
.device = 1,
|
||||
.property = 2,
|
||||
.channel = 3,
|
||||
.value = 4,
|
||||
};
|
||||
|
||||
static int parse_named_int(const char *name, const char *keystack[], size_t count)
|
||||
{
|
||||
char *endptr;
|
||||
int i;
|
||||
|
||||
/* Attempt to parse name as a number first */
|
||||
i = strtoul(name, &endptr, 0);
|
||||
if (*endptr == '\0') {
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Name is not a number, look it up */
|
||||
for (i = 0; i < count; i++) {
|
||||
if (strcmp(name, keystack[i]) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int cmd_start(const struct shell *sh, size_t argc, char *argv[])
|
||||
{
|
||||
const struct device *dev;
|
||||
|
||||
dev = device_get_binding(argv[args_indx.device]);
|
||||
if (!dev) {
|
||||
shell_error(sh, "Audio Codec device not found");
|
||||
return -ENODEV;
|
||||
}
|
||||
audio_codec_start_output(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_stop(const struct shell *sh, size_t argc, char *argv[])
|
||||
{
|
||||
const struct device *dev;
|
||||
|
||||
dev = device_get_binding(argv[args_indx.device]);
|
||||
if (!dev) {
|
||||
shell_error(sh, "Audio Codec device not found");
|
||||
return -ENODEV;
|
||||
}
|
||||
audio_codec_stop_output(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_set_prop(const struct shell *sh, size_t argc, char *argv[])
|
||||
{
|
||||
const struct device *dev;
|
||||
int property;
|
||||
int channel;
|
||||
long value;
|
||||
char *endptr;
|
||||
audio_property_value_t property_value;
|
||||
|
||||
dev = device_get_binding(argv[args_indx.device]);
|
||||
if (!dev) {
|
||||
shell_error(sh, "Audio Codec device not found");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
property = parse_named_int(argv[args_indx.property], codec_property_name,
|
||||
ARRAY_SIZE(codec_property_name));
|
||||
if (property < 0) {
|
||||
shell_error(sh, "Property '%s' unknown", argv[args_indx.property]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
channel = parse_named_int(argv[args_indx.channel], codec_channel_name,
|
||||
ARRAY_SIZE(codec_channel_name));
|
||||
if (channel < 0) {
|
||||
shell_error(sh, "Channel '%s' unknown", argv[args_indx.channel]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
value = strtol(argv[args_indx.value], &endptr, 0);
|
||||
if (*endptr != '\0') {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (value > INT32_MAX || value < INT32_MIN) {
|
||||
return -EINVAL;
|
||||
}
|
||||
switch (property) {
|
||||
case AUDIO_PROPERTY_OUTPUT_VOLUME:
|
||||
property_value.vol = value;
|
||||
break;
|
||||
case AUDIO_PROPERTY_OUTPUT_MUTE:
|
||||
property_value.mute = value;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return audio_codec_set_property(dev, property, channel, property_value);
|
||||
}
|
||||
|
||||
static int cmd_apply_prop(const struct shell *sh, size_t argc, char *argv[])
|
||||
{
|
||||
const struct device *dev;
|
||||
|
||||
dev = device_get_binding(argv[args_indx.device]);
|
||||
if (!dev) {
|
||||
shell_error(sh, "Audio Codec device not found");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return audio_codec_apply_properties(dev);
|
||||
}
|
||||
|
||||
/* Device name autocompletion support */
|
||||
static void device_name_get(size_t idx, struct shell_static_entry *entry)
|
||||
{
|
||||
const struct device *dev = shell_device_lookup(idx, NULL);
|
||||
|
||||
entry->syntax = (dev != NULL) ? dev->name : NULL;
|
||||
entry->handler = NULL;
|
||||
entry->help = NULL;
|
||||
entry->subcmd = NULL;
|
||||
}
|
||||
|
||||
SHELL_DYNAMIC_CMD_CREATE(dsub_device_name, device_name_get);
|
||||
|
||||
/* clang-format off */
|
||||
SHELL_STATIC_SUBCMD_SET_CREATE(sub_codec,
|
||||
SHELL_CMD_ARG(start, &dsub_device_name, CODEC_START_HELP, cmd_start,
|
||||
2, 0),
|
||||
SHELL_CMD_ARG(stop, &dsub_device_name, CODEC_STOP_HELP, cmd_stop,
|
||||
2, 0),
|
||||
SHELL_CMD_ARG(set_prop, &dsub_device_name, CODEC_SET_PROP_HELP, cmd_set_prop,
|
||||
5, 0),
|
||||
SHELL_CMD_ARG(apply_prop, &dsub_device_name, CODEC_APPLY_PROP_HELP, cmd_apply_prop,
|
||||
2, 0),
|
||||
SHELL_SUBCMD_SET_END
|
||||
);
|
||||
/* clang-format on */
|
||||
|
||||
SHELL_CMD_REGISTER(codec, &sub_codec, "Audio Codec commands", NULL);
|
||||
Loading…
Reference in a new issue