Logo Search packages:      
Sourcecode: alsa-driver version File versions

usbmidi.c

#include <linux/config.h>
#include <linux/version.h>

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5)
#define SND_NEED_USB_SET_INTERFACE
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
#define SND_NEED_USB_WRAPPER
#endif
#include <sound/driver.h>
#include <linux/usb.h>
#endif

#ifdef OLD_USB
#define snd_usb_complete_callback(x) __old_ ## x
static void __old_snd_usbmidi_in_urb_complete(struct urb* urb);
static void __old_snd_usbmidi_in_midiman_complete(struct urb* urb);
static void __old_snd_usbmidi_out_urb_complete(struct urb* urb);
#endif

#include "../alsa-kernel/usb/usbmidi.c"

#ifdef OLD_USB
static void __old_snd_usbmidi_in_urb_complete(struct urb* urb)
{
      snd_usbmidi_in_urb_complete(urb, NULL);
}

static void __old_snd_usbmidi_in_midiman_complete(struct urb* urb)
{
      snd_usbmidi_in_midiman_complete(urb, NULL);
}

static void __old_snd_usbmidi_out_urb_complete(struct urb* urb)
{
      snd_usbmidi_out_urb_complete(urb, NULL);
}
#endif

/*
 * workarounds / hacks for the older kernels follow below
 */

#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 24)
/* M-Audio Quattro has weird alternate settings.  the altsetting jumps
 * from 0 to 4 or 3 insuccessively, and this screws up
 * usb_set_interface() (at least on 2.4.18/19 and 2.4.21).
 */

/*
 * the following is a stripped version of usb_set_interface() with the fix
 * for insuccessive altsetting numbers.
 */

/* stripped version for isochronos only */
static void hack_usb_set_maxpacket(struct usb_device *dev)
{
      int i, b;

      for (i=0; i<dev->actconfig->bNumInterfaces; i++) {
            struct usb_interface *ifp = dev->actconfig->interface + i;
            struct usb_interface_descriptor *as = ifp->altsetting + ifp->act_altsetting;
            struct usb_endpoint_descriptor *ep = as->endpoint;
            int e;

            for (e=0; e<as->bNumEndpoints; e++) {
                  b = ep[e].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
                  if (usb_endpoint_out(ep[e].bEndpointAddress)) {
                        if (ep[e].wMaxPacketSize > dev->epmaxpacketout[b])
                              dev->epmaxpacketout[b] = ep[e].wMaxPacketSize;
                  }
                  else {
                        if (ep[e].wMaxPacketSize > dev->epmaxpacketin [b])
                              dev->epmaxpacketin [b] = ep[e].wMaxPacketSize;
                  }
            }
      }
}

/* stripped version */
int snd_hack_usb_set_interface(struct usb_device *dev, int interface, int alternate)
{
      struct usb_interface *iface;
      struct usb_interface_descriptor *iface_as;
      int i, ret;

      iface = usb_ifnum_to_if(dev, interface);
      if (!iface)
            return -EINVAL;
      if (iface->num_altsetting == 1)
            return 0;

      for (i = 0; i < iface->num_altsetting; ++i)
            if (get_iface_desc(&iface->altsetting[i])->bAlternateSetting == alternate)
                  break;
      if (i >= iface->num_altsetting)
            return -EINVAL;
      iface_as = &iface->altsetting[i];

      if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                           USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
                           alternate,
                           interface, NULL, 0, HZ * 5)) < 0)
            return ret;

      iface->act_altsetting = i;
      for (i = 0; i < iface_as->bNumEndpoints; i++) {
            u8 ep = iface_as->endpoint[i].bEndpointAddress;
            usb_settoggle(dev, ep&USB_ENDPOINT_NUMBER_MASK, usb_endpoint_out(ep), 0);
      }
      hack_usb_set_maxpacket(dev);
      return 0;
}

EXPORT_SYMBOL(snd_hack_usb_set_interface);

#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 5)

/* map altsetting number to index */
int snd_hack_usb_set_interface(struct usb_device *dev, int interface, int alternate)
{
      struct usb_interface *iface;
      unsigned int i;

      iface = usb_ifnum_to_if(dev, interface);
      if (!iface)
            return -EINVAL;
      for (i = 0; i < iface->num_altsetting; ++i) {
            if (get_iface_desc(&iface->altsetting[i])->bAlternateSetting == alternate)
                  return real_usb_set_interface(dev, interface, i);
      }
      return -EINVAL;
}

EXPORT_SYMBOL(snd_hack_usb_set_interface);
#endif /* LINUX_VERSION < 2.6.5 */

Generated by  Doxygen 1.6.0   Back to index