[RFC][PATCH v6 1/1] alsa: jack: implement software jack injection via debugfs
Takashi Iwai
tiwai at suse.de
Fri Jan 22 16:13:26 CET 2021
On Fri, 22 Jan 2021 15:14:56 +0100,
Hui Wang wrote:
>
> --- /dev/null
> +++ b/Documentation/sound/designs/jack-injection.rst
> @@ -0,0 +1,124 @@
(snip)
> +Explanation for the debugfs nodes:
> +::
> +
> + - kctl_id, read-only, get jack_kctl->kctl's id
> + sound/card1/Headphone_Jack# cat kctl_id
> + Headphone Jack
> +
> + - mask_bits, read-only, get jack_kctl's supported events mask_bits
> + sound/card1/Headphone_Jack# cat mask_bits
> + 0x0001 HEADPHONE(0x0001)
> +
> + - status, read-only, get jack_kctl's current status
> + headphone unplugged:
> + sound/card1/Headphone_Jack# cat status
> + Unplugged
> + headphone plugged:
> + sound/card1/Headphone_Jack# cat status
> + Plugged
> +
> + - type, read-only, get snd_jack's supported events type (all
> + supported events on the physical audio jack)
> + sound/card1/Headphone_Jack# cat type
> + 0x7803 HEADPHONE(0x0001) MICROPHONE(0x0002) BTN_3(0x0800) BTN_2(0x1000) BTN_1(0x2000) BTN_0(0x4000)
> +
> + - sw_inject_enable, read-write, enable or disable injection
> + injection disabled:
> + sound/card1/Headphone_Jack# cat sw_inject_enable
> + Jack: Headphone Jack Inject Enabled: 0
> + injection enabled:
> + sound/card1/Headphone_Jack# cat sw_inject_enable
> + Jack: Headphone Jack Inject Enabled: 1
> + to enable jack injection:
> + sound/card1/Headphone_Jack# echo 1 > sw_inject_enable
> + to disable jack injection:
> + sound/card1/Headphone_Jack# echo 0 > sw_inject_enable
> +
> + - jackin_inject, write-only, inject plugin or plugout
> + to inject plugin:
> + sound/card1/Headphone_Jack# echo 1 > jackin_inject
> + to inject plugout:
> + sound/card1/Headphone_Jack# echo 0 > jackin_inject
The lists could be better in a normal format, while only the examples
with cat and echo should be in verbose format.
> diff --git a/sound/core/Kconfig b/sound/core/Kconfig
> index d4554f376160..a9189f58dc56 100644
> --- a/sound/core/Kconfig
> +++ b/sound/core/Kconfig
> @@ -38,6 +38,15 @@ config SND_JACK_INPUT_DEV
> depends on SND_JACK
> default y if INPUT=y || INPUT=SND
>
> +config SND_JACK_INJECTION_DEBUG
> + bool "Sound jack injection interface via debugfs"
> + depends on SND_JACK && DEBUG_FS
Also, could depend on SND_DEBUG for consistency.
> diff --git a/sound/core/init.c b/sound/core/init.c
> index 75aec71c48a8..e7f7cfe1143b 100644
> --- a/sound/core/init.c
> +++ b/sound/core/init.c
> @@ -13,6 +13,7 @@
> #include <linux/time.h>
> #include <linux/ctype.h>
> #include <linux/pm.h>
> +#include <linux/debugfs.h>
> #include <linux/completion.h>
>
> #include <sound/core.h>
> @@ -161,6 +162,7 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
> {
> struct snd_card *card;
> int err;
> + char name[8];
>
> if (snd_BUG_ON(!card_ret))
> return -EINVAL;
> @@ -244,6 +246,10 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
> dev_err(parent, "unable to create card info\n");
> goto __error_ctl;
> }
> +
> + sprintf(name, "card%d", idx);
> + card->debugfs_root = debugfs_create_dir(name, sound_debugfs_root);
It's still an open question whether we want to create the debugfs
always. But I guess it's OK, we might want to add more stuff to
debugfs later. Or, it makes sense to create only if
CONFIG_SND_DEBUG=y.
> +static ssize_t sw_inject_enable_write(struct file *file,
> + const char __user *from, size_t count, loff_t *ppos)
> +{
> + struct snd_jack_kctl *jack_kctl = file->private_data;
> + int ret, err;
> + unsigned long enable;
> + char buf[8] = { 0 };
> +
> + if (count >= 8)
> + return -EINVAL;
> +
> + ret = simple_write_to_buffer(buf, count, ppos, from, count);
The simple_write_to_buffer() doesn't terminate the string by itself,
hence you need to make sure the string termination before kstrtoul()
call. e.g. buf[sizeof(buf)-1] = 0;
And maybe it's easier to make a helper function to that, since it's
called in multiple places.
> +static int parse_mask_bits(unsigned int mask_bits, char *s)
> +{
> + char buf[256];
> + int len, i;
> +
> + len = scnprintf(buf, sizeof(buf), "0x%04x", mask_bits);
> +
> + for (i = 0; i < 16; i++)
> + if (mask_bits & (1 << i))
> + len += scnprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> + " %s", jack_events_name[i]);
> +
> + len += scnprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "\n");
> +
> + strcpy(s, buf);
You need to intermediate buffer if you do a full copy here...
Just perform the string ops on s with a certain limit.
Also, you can use strncat() or strlcat() for simplicity.
thanks,
Takashi
More information about the Alsa-devel
mailing list