[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