diff options
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/card.c | 57 | ||||
-rw-r--r-- | sound/usb/stream.c | 98 |
2 files changed, 153 insertions, 2 deletions
diff --git a/sound/usb/card.c b/sound/usb/card.c index 64952e2d3ed1..e0c0e25b7293 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -32,7 +32,6 @@ * indeed an AC3 stream packed in SPDIF frames (i.e. no real AC3 stream). */ - #include <linux/bitops.h> #include <linux/init.h> #include <linux/list.h> @@ -45,6 +44,9 @@ #include <linux/usb/audio.h> #include <linux/usb/audio-v2.h> #include <linux/module.h> +#ifdef CONFIG_SWITCH +#include <linux/switch.h> +#endif #include <sound/control.h> #include <sound/core.h> @@ -113,6 +115,18 @@ static DEFINE_MUTEX(register_mutex); static struct snd_usb_audio *usb_chip[SNDRV_CARDS]; static struct usb_driver usb_audio_driver; +#ifdef CONFIG_SWITCH +enum switch_state { + STATE_CONNECTED_UNKNOWN = -1, + STATE_DISCONNECTED = 0, + STATE_CONNECTED = 1 +}; + +static struct switch_dev usb_switch_dev = { + .name = "usb_audio", +}; +#endif + /* * disconnect streams * called from snd_usb_audio_disconnect() @@ -558,10 +572,15 @@ snd_usb_audio_probe(struct usb_device *dev, goto __error; } +#ifdef CONFIG_SWITCH + switch_set_state(&usb_switch_dev, STATE_CONNECTED); +#endif + usb_chip[chip->index] = chip; chip->num_interfaces++; chip->probing = 0; mutex_unlock(®ister_mutex); + return chip; __error: @@ -572,6 +591,7 @@ snd_usb_audio_probe(struct usb_device *dev, } mutex_unlock(®ister_mutex); __err_val: + return NULL; } @@ -584,6 +604,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, { struct snd_card *card; struct list_head *p, *n; + int i; if (chip == (void *)-1L) return; @@ -595,6 +616,16 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, mutex_lock(®ister_mutex); chip->num_interfaces--; + +#ifdef CONFIG_SWITCH + for (i = 0; i < chip->index; i++) { + if (usb_chip[i]) + break; + } + if (i == chip->index) + switch_set_state(&usb_switch_dev, STATE_DISCONNECTED); +#endif + if (chip->num_interfaces <= 0) { snd_card_disconnect(card); /* release the pcm resources */ @@ -756,15 +787,37 @@ static struct usb_driver usb_audio_driver = { static int __init snd_usb_audio_init(void) { + int err = 0; + if (nrpacks < 1 || nrpacks > MAX_PACKS) { printk(KERN_WARNING "invalid nrpacks value.\n"); return -EINVAL; } - return usb_register(&usb_audio_driver); + +#ifdef CONFIG_SWITCH + /* Add usb_audio swith class support */ + err = switch_dev_register(&usb_switch_dev); + if (err < 0){ + printk(KERN_ERR "failed to register switch device"); + return -EINVAL; + } +#endif + + err = usb_register(&usb_audio_driver); + if (err) { +#ifdef CONFIG_SWITCH + switch_dev_unregister(&usb_switch_dev); +#endif + } + + return err; } static void __exit snd_usb_audio_cleanup(void) { +#ifdef CONFIG_SWITCH + switch_dev_unregister(&usb_switch_dev); +#endif usb_deregister(&usb_audio_driver); } diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 7db2f8958e79..70a07761f270 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -461,6 +461,89 @@ static struct uac2_output_terminal_descriptor * return NULL; } +static int usb_device_sample_rate_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 192000; + return 0; +} + +static int usb_device_sample_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct audioformat *fp = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = fp->rate_min; + ucontrol->value.integer.value[1] = fp->rate_max; + + return 0; +} + +static int usb_device_pb_channels_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 1; + uinfo->value.integer.max = 2; + return 0; +} + +static int usb_device_pb_channels_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct audioformat *fp = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = fp->channels; + return 0; +} + +static int usb_device_cap_channels_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 1; + uinfo->value.integer.max = 2; + return 0; +} + +static int usb_device_cap_channels_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct audioformat *fp = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = fp->channels; + return 0; +} + +struct snd_kcontrol_new usb_device_sample_rate_control = { + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "USB Device Sample Rate", + .info = usb_device_sample_rate_info, + .get = usb_device_sample_rate_get, +}; + +struct snd_kcontrol_new usb_device_pb_channels_control = { + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "USB Device Playback Channels", + .info = usb_device_pb_channels_info, + .get = usb_device_pb_channels_get, +}; + +struct snd_kcontrol_new usb_device_cap_channels_control = { + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "USB Device Capture Channels", + .info = usb_device_cap_channels_info, + .get = usb_device_cap_channels_get, +}; + int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) { struct usb_device *dev; @@ -697,6 +780,21 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) snd_usb_init_pitch(chip, iface_no, alts, fp); snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max); } + + /* Add usb device sample rate control */ + snd_ctl_add(chip->card, + snd_ctl_new1(&usb_device_sample_rate_control, fp)); + + /* Add usb device playback channels control */ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + snd_ctl_add(chip->card, + snd_ctl_new1(&usb_device_pb_channels_control, fp)); + + /* Add usb device capture channels control */ + if (stream == SNDRV_PCM_STREAM_CAPTURE) + snd_ctl_add(chip->card, + snd_ctl_new1(&usb_device_cap_channels_control, fp)); + return 0; } |