[RFC][PATCH v2 1/1] alsa: jack: implement software jack injection via debugfs
Kai Vehmanen
kai.vehmanen at linux.intel.com
Thu Dec 17 17:45:05 CET 2020
Hey,
I gave a quick test spin and features seems to work as advertized. A few
minor comments on the code. If Jaroslav you think this would be ok as an
approach, I can give a more extensive test run on this.
On Wed, 16 Dec 2020, Hui Wang wrote:
> We want to perform remote audio auto test, need the audio jack to
> change from plugout to plugin or vice versa by software ways.
>
> Here the design is creating a sound-core root folder in the debugfs
> dir, and each sound card will create a folder cardN under sound-core,
> then the sound jack will create folders by jack_ctrl->ctrl->id.name,
> and will create 2 file nodes jackin_inject and sw_inject_enable in
> the folder, this is the layout of folder on a machine with 2 sound
> cards:
> $tree $debugfs_mount_dir/sound-core
> sound-core/
> ├── card0
> │ ├── HDMI!DP,pcm=10 Jack
this combination of "!,= " characters in filenames is a bit non-unixy,
but maybe in 2020 we are ready for this.
> +static void _snd_jack_report(struct snd_jack *jack, int status, bool from_inject)
> +{
> + struct snd_jack_kctl *jack_kctl;
> + unsigned int mask_bits = 0;
> +#ifdef CONFIG_SND_JACK_INPUT_DEV
> + int i;
> +#endif
> + list_for_each_entry(jack_kctl, &jack->kctl_list, list) {
> + if (jack_kctl->sw_inject_enable == from_inject)
> + snd_kctl_jack_report(jack->card, jack_kctl->kctl,
> + status & jack_kctl->mask_bits);
> + else if (jack_kctl->sw_inject_enable)
> + mask_bits |= jack_kctl->mask_bits;
> + }
I'm wondering if it would be worth the code duplication to have the
inject-variant of this code in a separate function. I find the above code
to set up "mask_bits" a bit hard to read and this adds a layer of
complexity to anyone just wanting to look at the regular jack report code
path.
> +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;
> + char *buf;
> + int ret, err;
> + unsigned long enable;
> +
> + buf = kzalloc(count, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
> +
> + ret = simple_write_to_buffer(buf, count, ppos, from, count);
> + err = kstrtoul(buf, 0, &enable);
> + if (err) {
> + ret = err;
> + goto exit;
> + }
> +
> + jack_kctl->sw_inject_enable = !!enable;
Here it's a bit annoying that after you disable sw_inject, the kcontrol
values are not restored to reflrect actual hw state (until there are
new jack events from hw). User-space cannot completely handle the
save'n'restore as it cannot detect if real hw jack status changed
during the sw-inject test. OTOH, this would require caching the most
recent value and maybe not worth the effort.
> +static int snd_jack_debugfs_add_inject_node(struct snd_jack *jack,
> + struct snd_jack_kctl *jack_kctl)
> +{
> + char *tname;
> +
> + /* the folder's name can't contains '/', need to replace it with '!' as lib/kobject.c does */
> + tname = kstrdup(jack_kctl->kctl->id.name, GFP_KERNEL);
This goes over 100-column limit and triggers a checkpatch complaint.
Br, Kai
More information about the Alsa-devel
mailing list