Add jack reporting API for ALSA
Subsystems (3)
PATCH 1/2 Add jack reporting API for ALSA
Currently very few systems provide information about jack status to user space, even though many have hardware facilities to do detection. Those systems that do use an input device with the existing SW_HEADPHONE_INSERT switch type to do so, often independently of ALSA.
This patch introduces a standard method for representing jacks to user space into ALSA. It allows drivers to register jacks for a sound card with the input subsystem, binding the input device to the card to help user space associate the input devices with their sound cards. The created input devices are named in the form "card longname jack" where jack is provided by the driver when allocating a jack.
The existing user space API with SW_HEADPHONE_INSERT is preserved.
--- include/sound/core.h | 1 + include/sound/jack.h | 51 +++++++++++++++++++ sound/core/Kconfig | 5 ++ sound/core/Makefile | 2 + sound/core/jack.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 195 insertions(+), 0 deletions(-) create mode 100644 include/sound/jack.h create mode 100644 sound/core/jack.c
include/sound/core.h +1 -0
@@ -53,6 +53,7 @@ typedef int __bitwise snd_device_type_t;#define SNDRV_DEV_INFO ((__force snd_device_type_t) 0x1006)#define SNDRV_DEV_BUS ((__force snd_device_type_t) 0x1007)#define SNDRV_DEV_CODEC ((__force snd_device_type_t) 0x1008) +#define SNDRV_DEV_JACK ((__force snd_device_type_t) 0x1009)#define SNDRV_DEV_LOWLEVEL ((__force snd_device_type_t) 0x2000)typedef int __bitwise snd_device_state_t ;
include/sound/jack.h new file +51 -0
51 lines not on this page · raw message
sound/core/Kconfig +5 -0
@@ -16,6 +16,11 @@ config SND_RAWMIDI tristate depends on SND +config SND_JACK + tristate + depends on SND + depends on INPUT + config SND_SEQUENCER tristate "Sequencer support" depends on SND
sound/core/Makefile +2 -0
@@ -20,9 +20,11 @@ snd-rawmidi-objs := rawmidi.o snd-timer-objs := timer.o snd-rtctimer-objs := rtctimer.o snd-hwdep-objs := hwdep.o +snd-jack-objs := jack.o obj-$(CONFIG_SND) += snd.o obj-$(CONFIG_SND_HWDEP) += snd-hwdep.o +obj-$(CONFIG_SND_JACK) += snd-jack.o obj-$(CONFIG_SND_TIMER) += snd-timer.o obj-$(CONFIG_SND_RTCTIMER) += snd-rtctimer.o obj-$(CONFIG_SND_PCM) += snd-pcm.o snd-page-alloc.o
sound/core/jack.c new file +136 -0
136 lines not on this page · raw message
Signature · 1 line
1.5.5.1
PATCH 2/2 Add microphone and headset reporting
Add a new switch type to the input API for reporting microphone insertion and extend the ALSA jack reporting API to include this. Since a headset is a combination of a microphone and at least a mono headphone a convenience defintion is provided for describing them.
--- include/linux/input.h | 1 + include/sound/jack.h | 4 +++- sound/core/jack.c | 6 ++++++ 3 files changed, 10 insertions(+), 1 deletions(-)
include/linux/input.h +1 -0
@@ -612,6 +612,7 @@ struct input_absinfo {#define SW_TABLET_MODE 0x01/* set = tablet mode */ #define SW_HEADPHONE_INSERT 0x02/* set = inserted */ #define SW_RADIO 0x03/* set = radio enabled */ +#define SW_MICROPHONE_INSERT 0x04/* set = inserted */ #define SW_MAX 0x0f/*
include/sound/jack.h +3 -1
@@ -32,7 +32,9 @@ struct input_dev;* bitmask. */ enum snd_jack_types { -SND_JACK_HEADPHONE =0x0001 , +SND_JACK_HEADPHONE =0x0001 , +SND_JACK_MICROPHONE =0x0002 , +SND_JACK_HEADSET =0x0003 ,/* Both microphone and headphone */ };struct snd_jack {
sound/core/jack.c +6 -0
@@ -99,6 +99,9 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,if (type &SND_JACK_HEADPHONE )input_set_capability (jack->input_dev,EV_SW ,SW_HEADPHONE_INSERT ); +if (type &SND_JACK_MICROPHONE ) +input_set_capability (jack->input_dev,EV_SW , +SW_MICROPHONE_INSERT ); err =snd_device_new (card,SNDRV_DEV_JACK , jack, &ops);if (err <0 )
@@ -126,6 +129,9 @@ void snd_jack_report(struct snd_jack *jack, int status)if (jack->type &SND_JACK_HEADPHONE )input_report_switch (jack->input_dev,SW_HEADPHONE_INSERT , status &SND_JACK_HEADPHONE ); +if (jack->type &SND_JACK_MICROPHONE ) +input_report_switch (jack->input_dev,SW_MICROPHONE_INSERT , + status &SND_JACK_MICROPHONE );input_sync (jack->input_dev); }
Signature · 1 line
1.5.5.1
At Thu, 29 May 2008 22:09:04 +0100,
Quoted 6 lines · Mark Brown
Currently very few systems provide information about jack status to user space, even though many have hardware facilities to do detection. Those systems that do use an input device with the existing
SW_HEADPHONE_INSERTswitch type to do so, often independently of ALSA.
Quoted 8 lines
This patch introduces a standard method for representing jacks to user space into ALSA. It allows drivers to register jacks for a sound card with the input subsystem, binding the input device to the card to help user space associate the input devices with their sound cards. The created input devices are named in the form "card longname jack" where jack is provided by the driver when allocating a jack.
The existing user space API with
SW_HEADPHONE_INSERTis preserved.
The implementation looks good, simple enough.
sound/core/Kconfig config SND_RAWMIDI · line 22
Quoted 12 lines
sound/core/Kconfig +4
-0@@ -16,6 +16,11 @@ config SND_RAWMIDI tristate depends on SND +config SND_JACK + tristate + depends on SND + depends on INPUT
If you suppose to "select" SND_JACK, depends have no meaning.
sound/core/Makefile snd-rawmidi-objs := rawmidi.o · line 27
Quoted 13 lines
sound/core/Makefile +2
-0@@ -20,9 +20,11 @@ snd-rawmidi-objs := rawmidi.o snd-timer-objs := timer.o snd-rtctimer-objs := rtctimer.o snd-hwdep-objs := hwdep.o +snd-jack-objs := jack.o obj-$(CONFIG_SND) += snd.o obj-$(CONFIG_SND_HWDEP) += snd-hwdep.o +obj-$(CONFIG_SND_JACK) += snd-jack.o
The code is small, and I don't see a big merit to make it a module.
sound/core/Makefile snd-rawmidi-objs := rawmidi.o
Quoted 8 lines
sound/core/Makefile +8
-0+static int snd_jack_dev_register(struct snd_device *device) +{ + struct snd_jack *jack = device->device_data; + struct snd_card *card = device->card; + int err; + + snprintf(jack->name, sizeof(jack->name), "%s %s", + card->longname, jack->id);
The longname field could be sometimes really too long and verbose. I guess shortname would match better.
Quoted 2 lines
sound/core/Makefile +2
-0+int snd_jack_new(struct snd_card *card, const char *id, int type, + struct snd_jack **jjack)
(snip)
sound/core/Makefile
Quoted 2 lines
sound/core/Makefile +2
-0+ jack->input_dev->phys = "ALSA"; + jack->input_dev->dev.parent = card->dev;
The card->dev pointer might not be initialized always at this stage. You should check rather at register.
Also, someone may want to pass a different device pointer for this. Passing struct device * to snd_jack_new would be an alternative.
thanks,
Takashi
Quoted 1 line · Takashi Iwai
The implementation looks good, simple enough.
Thanks.
Quoted 8 lines
sound/core/Kconfig config SND_RAWMIDI · line 22
Quoted 4 lines · Mark Brown
sound/core/Kconfig +4
-0+config SND_JACK + tristate + depends on SND + depends on INPUTThe code is small, and I don't see a big merit to make it a module.
I agree - I had meant to flag this up, actually. I hadn't been sure if some of the other objects were being built conditionally for size or not since they seemed relatively small too. When I respin I'll remove this option.
Quoted 5 lines
sound/core/jack.c line 49
Quoted 2 lines
sound/core/jack.c new file +2
-0+snprintf (jack->name,sizeof (jack->name),"%s %s" , + card->longname, jack->id);The longname field could be sometimes really too long and verbose. I guess shortname would match better.
The general style for input device names tends towards the long and verbose. For example, on my work laptop I have devices with names like:
Macintosh mouse button emulation
AT Translated Set 2 Keyboard
Lid Switch
Power Button (CM)
Sleep Button (CM)
AlpsPS/2 ALPS GlidePoint
The ALSA long name seems more idiomatic for this context.
Quoted 8 lines
Quoted 2 lines
sound/core/jack.c new file +2
-0+int snd_jack_new (struct snd_card *card,const char *id,int type, +struct snd_jack **jjack)(snip)
sound/core/jack.c line 95
Quoted 2 lines
sound/core/jack.c new file +2
-0+ jack->input_dev->phys ="ALSA" ; + jack->input_dev->dev.parent = card->dev;The
card->devpointer might not be initialized always at this stage. You should check rather at register.
Will do.
Quoted 2 lines
Also, someone may want to pass a different device pointer for this. Passing struct device * to
snd_jack_newwould be an alternative.
Good idea, that might be useful for ASoC v2 sound cards. I'll add something which allows the caller to optionally specify a parent, defaulting to the sound card if none is given.
The only issue might be for user space figuring out which sound card corresponds to which jack but if jacks might be implemented outside of ALSA anyway (which is possible) that could happen anyway.
Jack reporting v2
In reply to Mark BrownThe following couple of patches update the jack reporting API I posted last week with the feedback I have received so far. The changes since the last submision are:
- Addition of snd_jack_set_parent(), allowing drivers to override the default parent for the input device prior to registration.
- The jack detection support is now included unconditionally in ALSA, requiring a dependency on the input subsystem.
I'm not entirely happy with making ALSA depend on input but given that it is only optional on embedded systems and that the input core is not that large it seemed the best way of ensuring that the input subsystem is available for the jack API without hassle for drivers using it, especially given the lack of dependency propagation from select.
PATCH 1/2 Add jack reporting API for ALSA
Currently very few systems provide information about jack status to user space, even though many have hardware facilities to do detection. Those systems that do use an input device with the existing SW_HEADPHONE_INSERT switch type to do so, often independently of ALSA.
This patch introduces a standard method for representing jacks to user space into ALSA. It allows drivers to register jacks for a sound card with the input subsystem, binding the input device to the card to help user space associate the input devices with their sound cards. The created input devices are named in the form "card longname jack" where jack is provided by the driver when allocating a jack. By default the parent for the input device is the sound card but this can be overridden by the card driver.
The existing user space API with SW_HEADPHONE_INSERT is preserved.
--- include/sound/core.h | 1 + include/sound/jack.h | 52 +++++++++++++++++ sound/Kconfig | 1 + sound/core/Makefile | 3 +- sound/core/jack.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 213 insertions(+), 1 deletions(-) create mode 100644 include/sound/jack.h create mode 100644 sound/core/jack.c
include/sound/core.h +1 -0
@@ -63,6 +63,7 @@ typedef int __bitwise snd_device_type_t;#define SNDRV_DEV_INFO ((__force snd_device_type_t) 0x1006)#define SNDRV_DEV_BUS ((__force snd_device_type_t) 0x1007)#define SNDRV_DEV_CODEC ((__force snd_device_type_t) 0x1008) +#define SNDRV_DEV_JACK ((__force snd_device_type_t) 0x1009)#define SNDRV_DEV_LOWLEVEL ((__force snd_device_type_t) 0x2000)typedef int __bitwise snd_device_state_t ;
include/sound/jack.h new file +52 -0
52 lines not on this page · raw message
sound/Kconfig +1 -0
@@ -38,6 +38,7 @@ menu "Advanced Linux Sound Architecture" config SND tristate "Advanced Linux Sound Architecture" depends on SOUND + depends on INPUT help Say 'Y' or 'M' to enable ALSA (Advanced Linux Sound Architecture), the new base sound system.
sound/core/Makefile +2 -1
@@ -3,7 +3,8 @@ # Copyright (c) 1999,2001 by Jaroslav Kysela <[email protected]> # -snd-y := sound.o init.o memory.o info.o control.o misc.o device.o +snd-y := sound.o init.o memory.o info.o control.o misc.o device.o \ + jack.o snd-$(CONFIG_ISA_DMA_API) += isadma.o snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o info_oss.o snd-$(CONFIG_SND_VMASTER) += vmaster.o
sound/core/jack.c new file +157 -0
157 lines not on this page · raw message
Signature · 1 line
1.5.5.3
PATCH 2/2 Add microphone and headset reporting
Add a new switch type to the input API for reporting microphone insertion and extend the ALSA jack reporting API to include this. Since a headset is a combination of a microphone and at least a mono headphone a convenience defintion is provided for describing them.
--- include/linux/input.h | 1 + include/sound/jack.h | 4 +++- sound/core/jack.c | 6 ++++++ 3 files changed, 10 insertions(+), 1 deletions(-)
include/linux/input.h +1 -0
@@ -640,6 +640,7 @@ struct input_absinfo {#define SW_RFKILL_ALL 0x03/* rfkill master switch, type "any" set = radio enabled */ #define SW_RADIO SW_RFKILL_ALL/* deprecated */ +#define SW_MICROPHONE_INSERT 0x04/* set = inserted */ #define SW_MAX 0x0f#define SW_CNT (SW_MAX+1)
include/sound/jack.h +3 -1
@@ -32,7 +32,9 @@ struct input_dev;* bitmask. */ enum snd_jack_types { -SND_JACK_HEADPHONE =0x0001 , +SND_JACK_HEADPHONE =0x0001 , +SND_JACK_MICROPHONE =0x0002 , +SND_JACK_HEADSET =0x0003 ,/* Both microphone and headphone */ };struct snd_jack {
sound/core/jack.c +6 -0
@@ -102,6 +102,9 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,if (type &SND_JACK_HEADPHONE )input_set_capability (jack->input_dev,EV_SW ,SW_HEADPHONE_INSERT ); +if (type &SND_JACK_MICROPHONE ) +input_set_capability (jack->input_dev,EV_SW , +SW_MICROPHONE_INSERT ); err =snd_device_new (card,SNDRV_DEV_JACK , jack, &ops);if (err <0 )
@@ -147,6 +150,9 @@ void snd_jack_report(struct snd_jack *jack, int status)if (jack->type &SND_JACK_HEADPHONE )input_report_switch (jack->input_dev,SW_HEADPHONE_INSERT , status &SND_JACK_HEADPHONE ); +if (jack->type &SND_JACK_MICROPHONE ) +input_report_switch (jack->input_dev,SW_MICROPHONE_INSERT , + status &SND_JACK_MICROPHONE );input_sync (jack->input_dev); }
Signature · 1 line
1.5.5.3
Re: Jack reporting v2
In reply to Mark BrownAt Tue, 3 Jun 2008 11:40:48 +0100,
Quoted 10 lines · Mark Brown
The following couple of patches update the jack reporting API I posted last week with the feedback I have received so far. The changes since the last submision are:
- Addition of
snd_jack_set_parent(), allowing drivers to override the default parent for the input device prior to registration.
- The jack detection support is now included unconditionally in ALSA, requiring a dependency on the input subsystem.
Quoted 5 lines
I'm not entirely happy with making ALSA depend on input but given that it is only optional on embedded systems and that the input core is not that large it seemed the best way of ensuring that the input subsystem is available for the jack API without hassle for drivers using it, especially given the lack of dependency propagation from select.
I also feel uneasy that it's built in unconditionally and requires an additional dependency on CONFIG_INPUT. The fact that both SND and INPUT can be modules makes things a bit complicated.
As a workaround, how about to select with "if" conditions? For example, in sound/core/Kconfig,
config SND_JACK
bool
while the driver requires SND_JACK has the below:
config SND_FOO
tristate "..." ... select SND_JACK if INPUT=y || INPUT=SND
Yeah, it looks horrible at a first glance, but it's a known workaround for reverse selections...
In sound/core/Makefile, just add the line:
snd-$(CONFIG_SND_JACK) += jack.o
so that the code is built into snd module only when necessary.
Also, sound/jack.h should provide empty inline functions for the case CONFIG_SND_JACK=n. Then you'll be able to reduce ifdefs in the driver codes.
thanks,
Takashi
Re: Jack reporting v2
Quoted 2 lines · Takashi Iwai
Yeah, it looks horrible at a first glance, but it's a known workaround for reverse selections...
Indeed - that was the main other solution I'd looked at. It seemed like too much splatter in the configuration for the drivers but it's about as good as it looks like it'll get if simply depending on input isn't going to be OK.
Looking at all this I'm thinking we may as well leave the jack stuff as a module - it'd at least make the dependency stuff at runtime slightly easier and if we're going to put in the effort to support all these mixes of SND and INPUT it's probably as well to remove the runtime dependency between ALSA and input if jacks aren't actually in use too.
Quoted 3 lines
Also,
sound/jack.hshould provide empty inline functions for the caseCONFIG_SND_JACK=n. Then you'll be able to reduce ifdefs in the driver codes.
Yeah, probably. Though from that point of view it might be as well to cut out the SND_JACK middleman...
Dmitry Torokhov
maintainerRe: Jack reporting v2
In reply to Mark BrownHi Mark,
Quoted 9 lines · Mark Brown
The following couple of patches update the jack reporting API I posted last week with the feedback I have received so far. The changes since the last submision are:
- Addition of
snd_jack_set_parent(), allowing drivers to override the default parent for the input device prior to registration.
- The jack detection support is now included unconditionally in ALSA, requiring a dependency on the input subsystem.
Quoted 5 lines
I'm not entirely happy with making ALSA depend on input but given that it is only optional on embedded systems and that the input core is not that large it seemed the best way of ensuring that the input subsystem is available for the jack API without hassle for drivers using it, especially given the lack of dependency propagation from select.
I think it is a great idea to intoroduce a mechanism treporting state of a generic connector, it was a long overdue. However I don't think that using input as a delivery mechanism is the best solution. What is needed from a connector:
1. A way to query its state
2. A way to notify userspace of state change.
Pros for using input devices:
- we already have them
Cons:
- space consideration. Input_dev structure is quite fat. It has all the capabilities strings exported through sysfs, hist of other attributes, etc. On top of that we have a character device (evdev) plus its own sysfs representation. IOW lots of stuff.
- input device require ioctl to get the switch state, no easy way to do it through sysfs.
- As the number of types of connectors grows new switches will need to be added to input, potentially completely unrelated. My lacmus test for it - does it make sense to add network cable state to inputi core?
Do you think that something small that has only one sysfs device per switch and uses KOBJ_ONLINE/KOBJ_OFFLINE to signal state change would be better suited here?
BTW, the same goes for the SW_DOCK that Matthew wants to add (CC-ed).
Signature · 1 line
Dmitry
Re: Jack reporting v2
Quoted 2 lines · Dmitry Torokhov
Pros for using input devices:
- we already have them
...and it already models switches.
As mentioned in the description of the original patch there's also the fact that the existing implementations I've found are doing things this way. The only in-kernel ones are corgi and spitz which skip the input device overhead by using the keyboard input device.
There is an additional motivation for using an input device for jacks - it is common to support a button implemented by shorting the microphone connection as well as simply detecting the presence of something in the jack.
Quoted 5 lines
Cons:
- space consideration.Input_devstructure is quite fat. It has all the capabilities strings exported through sysfs, hist of other attributes, etc. On top of that we have a character device (evdev) plus its own sysfs representation. IOW lots of stuff.
I'm not sure how many systems this is a concern for these days (the things I found exporting to user space at the minute are embedded) but it could be an issue.
Quoted 2 lines
- input device require ioctl to get the switch state, no easy way to do it through sysfs.
That sounds like something that is worth adding anyway, regardless of what gets done with jacks.
Quoted 4 lines
- As the number of types of connectors grows new switches will need to be added to input, potentially completely unrelated. My lacmus test for it - does it make sense to add network cable state to inputi core?
The number of potential switches could get rather large, yes - to my mind it's the main concern with using the input API.
Quoted 3 lines
Do you think that something small that has only one sysfs device per switch and uses KOBJ_ONLINE/KOBJ_OFFLINE to signal state change would be better suited here?
It's certainly doable and it would avoid any issues with memory overhead and with the number of switch types.
Jacks would in general have more than one thing to report - as well as jacks for headsets with both headphone and optional microphone support on one physical jack many devices will also be able to give an idea of the device connected to a jack, doing things like distinguishing between speakers and headphones. This information could still be exported via the sort of interface you suggest, for example with one sysfs file per thing that can be detected contents indicating the state for that thing. It could also be exported as environment variables along with the uevent. The jack API would be able to standardise the names so that shouldn't be an issue.
Ignoring the buttons it should be fairly straightforward from a kernel point of view. I'm not sure how some of the userspace people would feel about it, mainly those in embedded systems not already dealing with uevents, but if they don't want to use netlink then uevent_helper should do the job for them even though it is a bit more cumbersome than the input API.
Buttons would presumably end up as an input device registered only if supported by the jack - this would be easy enough for the kernel.
If jack reporting is implemented this way we'd want to add a comment indicating that SW_HEADPHONE_INSERT shouldn't be used.
Re: Jack reporting v2
Quoted 4 lines · Mark Brown
There is an additional motivation for using an input device for jacks - it is common to support a button implemented by shorting the microphone connection as well as simply detecting the presence of something in the jack.
Dimitry, do you have any further thoughts on this? Due to jacks being able to function as buttons as well as switches I do prefer the use of input devices for jack reporting but if you still disagree I'll redo the patch since I don't feel *that* strongly.
Re: Jack reporting v2
In reply to Mark BrownQuoted 4 lines · Mark Brown
There is an additional motivation for using an input device for jacks - it is common to support a button implemented by shorting the microphone connection as well as simply detecting the presence of something in the jack.
Hi Dimitry,
Do you have any further thoughts on this? I'd really like to get this in during 2.6.28 if possible but it really needs your feedback.
Thanks,
Mark