Index: alsa/alsa-kernel/include/asound.h =================================================================== --- alsa.orig/alsa-kernel/include/asound.h 2005-05-17 10:04:16.000000000 +0200 +++ alsa/alsa-kernel/include/asound.h 2005-06-08 22:30:47.000000000 +0200 @@ -114,9 +114,10 @@ enum sndrv_hwdep_iface { SNDRV_HWDEP_IFACE_USX2Y_PCM, /* Tascam US122, US224 & US428 rawusb pcm */ SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */ SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */ + SNDRV_HWDEP_IFACE_USB_CTRL, /* USB control transfers */ /* Don't forget to change the following: */ - SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_SB_RC + SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_CTRL, }; struct sndrv_hwdep_info { Index: alsa/alsa-lib/include/sound/asound.h =================================================================== --- alsa.orig/alsa-lib/include/sound/asound.h 2005-05-20 17:15:54.000000000 +0200 +++ alsa/alsa-lib/include/sound/asound.h 2005-06-08 22:34:12.000000000 +0200 @@ -112,9 +112,10 @@ enum sndrv_hwdep_iface { SNDRV_HWDEP_IFACE_USX2Y_PCM, /* Tascam US122, US224 & US428 rawusb pcm */ SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */ SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */ + SNDRV_HWDEP_IFACE_USB_CTRL, /* USB control transfers */ /* Don't forget to change the following: */ - SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_SB_RC + SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_CTRL }; struct sndrv_hwdep_info { Index: alsa/alsa-lib/include/hwdep.h =================================================================== --- alsa.orig/alsa-lib/include/hwdep.h 2005-04-29 17:26:40.000000000 +0200 +++ alsa/alsa-lib/include/hwdep.h 2005-06-08 22:37:08.000000000 +0200 @@ -68,8 +68,9 @@ typedef enum _snd_hwdep_iface { SND_HWDEP_IFACE_USX2Y_PCM, /**< Tascam US122, US224 & US428 raw USB PCM */ SND_HWDEP_IFACE_PCXHR, /**< Digigram PCXHR */ SND_HWDEP_IFACE_SB_RC, /**< SB Extigy/Audigy2NX remote control */ + SND_HWDEP_IFACE_USB_CTRL, /**< USB control transfers */ - SND_HWDEP_IFACE_LAST = SND_HWDEP_IFACE_SB_RC /**< last known hwdep interface */ + SND_HWDEP_IFACE_LAST = SND_HWDEP_IFACE_USB_CTRL /**< last known hwdep interface */ } snd_hwdep_iface_t; /** open for reading */ Index: alsa/alsa-kernel/usb/usbaudio.c =================================================================== --- alsa.orig/alsa-kernel/usb/usbaudio.c 2005-05-31 18:13:22.000000000 +0200 +++ alsa/alsa-kernel/usb/usbaudio.c 2005-06-08 23:31:31.000000000 +0200 @@ -45,11 +45,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include "usbaudio.h" @@ -3012,6 +3014,69 @@ static void snd_usb_audio_create_proc(sn snd_info_set_text_ops(entry, chip, 1024, proc_audio_usbid_read); } +/* hwdep interface */ +static int snd_usb_audio_hwdep_open(snd_hwdep_t *hwdep, struct file *file) +{ + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + return 0; +} + +static int snd_usb_audio_hwdep_ioctl(snd_hwdep_t *hwdep, struct file *file, + unsigned int cmd, unsigned long arg) +{ + snd_usb_audio_t *chip = hwdep->private_data; + struct usbdevfs_ctrltransfer ctrl; + void *buffer; + int ret; + + if (cmd != USBDEVFS_CONTROL) + return -ENOTTY; + if (copy_from_user(&ctrl, (void __user *)arg, sizeof(ctrl))) + return -EFAULT; + if (ctrl.wLength > PAGE_SIZE) + return -EINVAL; + if (!(buffer = (void *)__get_free_page(GFP_KERNEL))) + return -ENOMEM; + if (ctrl.bRequestType & USB_DIR_IN) { + ret = usb_control_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), + ctrl.bRequest, ctrl.bRequestType, + ctrl.wValue, ctrl.wIndex, + buffer, ctrl.wLength, ctrl.timeout); + if (ret > 0 && ctrl.wLength && + copy_to_user(ctrl.data, buffer, ctrl.wLength)) { + ret = -EFAULT; + goto _error; + } + } else { + if (ctrl.wLength && + copy_from_user(buffer, ctrl.data, ctrl.wLength)) { + ret = -EFAULT; + goto _error; + } + ret = usb_control_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), + ctrl.bRequest, ctrl.bRequestType, + ctrl.wValue, ctrl.wIndex, + buffer, ctrl.wLength, ctrl.timeout); + } +_error: + free_page((unsigned long)buffer); + return ret; +} + +static void snd_usb_audio_create_hwdep(snd_usb_audio_t *chip) +{ + snd_hwdep_t *hwdep; + + if (snd_hwdep_new(chip->card, "USB Control", 1, &hwdep) >= 0) { + strcpy(hwdep->name, "USB Control"); + hwdep->iface = SNDRV_HWDEP_IFACE_USB_CTRL; + hwdep->private_data = chip; + hwdep->ops.open = snd_usb_audio_hwdep_open; + hwdep->ops.ioctl = snd_usb_audio_hwdep_ioctl; + } +} + /* * free the chip instance * @@ -3127,6 +3192,7 @@ static int snd_usb_audio_create(struct u sizeof(card->longname)); snd_usb_audio_create_proc(chip); + snd_usb_audio_create_hwdep(chip); *rchip = chip; return 0; Index: alsa/alsa-driver/usb/usbaudio.patch =================================================================== --- alsa.orig/alsa-driver/usb/usbaudio.patch 2005-05-02 09:43:49.000000000 +0200 +++ alsa/alsa-driver/usb/usbaudio.patch 2005-06-08 23:31:50.000000000 +0200 @@ -1,11 +1,11 @@ ---- ../alsa-kernel/usb/usbaudio.c 2005-04-29 23:54:04.000000000 +0200 -+++ usbaudio.c 2005-04-29 23:56:20.000000000 +0200 +--- ../alsa-kernel/usb/usbaudio.c 2005-06-08 23:31:31.000000000 +0200 ++++ usbaudio.c 2005-06-08 23:31:38.000000000 +0200 @@ -1,3 +1,4 @@ +#include "usbaudio.inc" /* * (Tentative) USB Audio Driver for ALSA * -@@ -67,7 +68,12 @@ +@@ -69,7 +70,12 @@ static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Vendor ID for this card */ static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Product ID for this card */ static int nrpacks = 4; /* max. number of packets per urb */ @@ -19,7 +19,7 @@ module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for the USB audio adapter."); -@@ -1902,8 +1908,13 @@ +@@ -1874,8 +1880,13 @@ return -ENOMEM; memcpy(buf, data, size); } @@ -33,7 +33,7 @@ if (size > 0) { memcpy(data, buf, size); kfree(buf); -@@ -1916,9 +1927,11 @@ +@@ -1888,9 +1899,11 @@ * entry point for linux usb interface */ @@ -45,7 +45,7 @@ static struct usb_device_id usb_audio_ids [] = { #include "usbquirks.h" -@@ -1931,10 +1944,15 @@ +@@ -1903,10 +1916,15 @@ MODULE_DEVICE_TABLE (usb, usb_audio_ids); static struct usb_driver usb_audio_driver = { @@ -61,7 +61,7 @@ .id_table = usb_audio_ids, }; -@@ -2460,7 +2478,11 @@ +@@ -2432,7 +2450,11 @@ (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIO_STREAMING && altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) || altsd->bNumEndpoints < 1 || @@ -73,7 +73,7 @@ continue; /* must be isochronous */ if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != -@@ -2523,7 +2545,11 @@ +@@ -2495,7 +2517,11 @@ fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; /* FIXME: decode wMaxPacketSize of high bandwith endpoints */ @@ -85,7 +85,7 @@ fp->attributes = csep[3]; /* some quirks for attributes here */ -@@ -2811,7 +2837,11 @@ +@@ -2782,7 +2808,11 @@ fp->iface = altsd->bInterfaceNumber; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; @@ -97,7 +97,7 @@ switch (fp->maxpacksize) { case 0x120: -@@ -2877,7 +2907,11 @@ +@@ -2848,7 +2878,11 @@ fp->iface = altsd->bInterfaceNumber; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; @@ -109,7 +109,7 @@ fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]); stream = (fp->endpoint & USB_DIR_IN) -@@ -2935,8 +2969,13 @@ +@@ -2906,8 +2940,13 @@ struct usb_host_config *config = dev->actconfig; int err; @@ -123,7 +123,7 @@ snd_printdd("sending Extigy boot sequence...\n"); /* Send message to force it to reconnect with full interface. */ err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev,0), -@@ -2948,8 +2987,13 @@ +@@ -2919,8 +2958,13 @@ if (err < 0) snd_printdd("error usb_get_descriptor: %d\n", err); err = usb_reset_configuration(dev); if (err < 0) snd_printdd("error usb_reset_configuration: %d\n", err); @@ -137,7 +137,17 @@ return -ENODEV; /* quit this anyway */ } return 0; -@@ -3082,8 +3126,13 @@ +@@ -3038,6 +3082,9 @@ + return -EINVAL; + if (!(buffer = (void *)__get_free_page(GFP_KERNEL))) + return -ENOMEM; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12) ++ ctrl.timeout = (ctrl.timeout * HZ + 999) / 1000; ++#endif + if (ctrl.bRequestType & USB_DIR_IN) { + ret = usb_control_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), + ctrl.bRequest, ctrl.bRequestType, +@@ -3135,8 +3182,13 @@ chip->index = idx; chip->dev = dev; chip->card = card; @@ -151,7 +161,7 @@ INIT_LIST_HEAD(&chip->pcm_list); INIT_LIST_HEAD(&chip->midi_list); INIT_LIST_HEAD(&chip->mixer_list); -@@ -3171,8 +3220,12 @@ +@@ -3223,8 +3275,12 @@ alts = &intf->altsetting[0]; ifnum = get_iface_desc(alts)->bInterfaceNumber; @@ -164,7 +174,7 @@ if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum) goto __err_val; -@@ -3293,12 +3346,17 @@ +@@ -3351,12 +3407,17 @@ } usb_chip[chip->index] = NULL; up(®ister_mutex); @@ -182,7 +192,7 @@ /* * new 2.5 USB kernel API */ -@@ -3319,6 +3377,8 @@ +@@ -3377,6 +3438,8 @@ snd_usb_audio_disconnect(interface_to_usbdev(intf), dev_get_drvdata(&intf->dev)); } @@ -191,7 +201,7 @@ static int __init snd_usb_audio_init(void) -@@ -3339,3 +3399,5 @@ +@@ -3397,3 +3460,5 @@ module_init(snd_usb_audio_init); module_exit(snd_usb_audio_cleanup);