ChangeSet 1.1608.84.17, 2004/03/10 12:20:55-08:00, stern@rowland.harvard.edu [PATCH] USB: Remove interface/altsetting assumptions from usb-midi This patch makes the usb-midi driver use usb_ifnum_to_if(), thereby removing assumptions about which interface is stored in which array entry. Similarly, it stores the bAlternateSetting value rather than the array index for an altsetting entry. Like the earlier patch for the audio driver, this also changes the driver to use the in-memory rawdescriptor buffer rather than reading a configuration descriptor from the device. Unlike that earlier patch, this time there's no question that the deallocation of the buffer is done correctly. (I suspect the audio driver just left out a call to kfree.) drivers/usb/class/usb-midi.c | 93 ++++++++++++------------------------------- 1 files changed, 28 insertions(+), 65 deletions(-) diff -Nru a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c --- a/drivers/usb/class/usb-midi.c Tue Mar 16 15:02:49 2004 +++ b/drivers/usb/class/usb-midi.c Tue Mar 16 15:02:49 2004 @@ -39,9 +39,6 @@ #include #include -/** This declaration is missing from linux/usb.h **/ -extern int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size); - #include "usb-midi.h" /* ------------------------------------------------------------------------- */ @@ -1519,15 +1516,17 @@ static int get_alt_setting( struct usb_device *d, int ifnum ) { int alts, alt=0; + struct usb_interface *iface; struct usb_host_interface *interface; struct usb_endpoint_descriptor *ep; int epin, epout; int i; - alts = d->actconfig->interface[ifnum]->num_altsetting; + iface = usb_ifnum_to_if( d, ifnum ); + alts = iface->num_altsetting; for ( alt=0 ; altactconfig->interface[ifnum]->altsetting[alt]; + interface = &iface->altsetting[alt]; epin = -1; epout = -1; @@ -1542,7 +1541,7 @@ epout = i; } if ( epin >= 0 && epout >= 0 ) { - return alt; + return interface->desc.bAlternateSetting; } } } @@ -1780,12 +1779,13 @@ * Called by usb_midi_probe(); **/ -static int detect_yamaha_device( struct usb_device *d, unsigned int ifnum, struct usb_midi_state *s) +static int detect_yamaha_device( struct usb_device *d, + struct usb_interface *iface, unsigned int ifnum, + struct usb_midi_state *s) { - struct usb_host_config *c = d->actconfig; struct usb_host_interface *interface; struct usb_midi_device *u; - unsigned char buf[USB_DT_CONFIG_SIZE], *buffer; + unsigned char *buffer; int bufSize; int i; int alts=-1; @@ -1795,13 +1795,13 @@ return -EINVAL; } - for ( i=0 ; i < c->interface[ifnum]->num_altsetting; i++ ) { - interface = c->interface[ifnum]->altsetting + i; + for ( i=0 ; i < iface->num_altsetting; i++ ) { + interface = iface->altsetting + i; if ( interface->desc.bInterfaceClass != 255 || interface->desc.bInterfaceSubClass != 0 ) continue; - alts = i; + alts = interface->desc.bAlternateSetting; } if ( alts == -1 ) { return -EINVAL; @@ -1810,30 +1810,11 @@ printk(KERN_INFO "usb-midi: Found YAMAHA USB-MIDI device on dev %04x:%04x, iface %d\n", d->descriptor.idVendor, d->descriptor.idProduct, ifnum); - ret = usb_get_descriptor( d, USB_DT_CONFIG, i, buf, USB_DT_CONFIG_SIZE ); - if ( ret < 0 ) { - printk(KERN_INFO "usb-midi: Could not get config (error=%d).\n", ret); - return -EINVAL; - } - if ( buf[1] != USB_DT_CONFIG || buf[0] < USB_DT_CONFIG_SIZE ) { - printk(KERN_INFO "usb-midi: config not as expected.\n"); - return -EINVAL; - } - bufSize = buf[2] | buf[3]<<8; - buffer = (unsigned char *)kmalloc(sizeof(unsigned char)*bufSize, GFP_KERNEL); - if ( !buffer ) { - printk(KERN_INFO "usb-midi: Could not allocate memory.\n"); - return -EINVAL; - } - ret = usb_get_descriptor( d, USB_DT_CONFIG, i, buffer, bufSize ); - if ( ret < 0 ) { - printk(KERN_INFO "usb-midi: Could not get full config (error=%d).\n", ret); - kfree(buffer); - return -EINVAL; - } + i = d->actconfig - d->config; + buffer = d->rawdescriptors[i]; + bufSize = d->actconfig->desc.wTotalLength; u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 1); - kfree(buffer); if ( u == NULL ) { return -EINVAL; } @@ -1878,24 +1859,25 @@ * Returns 0 on success, negative on failure. * Called by usb_midi_probe(); **/ -static int detect_midi_subclass(struct usb_device *d, unsigned int ifnum, struct usb_midi_state *s) +static int detect_midi_subclass(struct usb_device *d, + struct usb_interface *iface, unsigned int ifnum, + struct usb_midi_state *s) { - struct usb_host_config *c = d->actconfig; struct usb_host_interface *interface; struct usb_midi_device *u; - unsigned char buf[USB_DT_CONFIG_SIZE], *buffer; + unsigned char *buffer; int bufSize; int i; int alts=-1; int ret; - for ( i=0 ; i < c->interface[ifnum]->num_altsetting; i++ ) { - interface = c->interface[ifnum]->altsetting + i; + for ( i=0 ; i < iface->num_altsetting; i++ ) { + interface = iface->altsetting + i; if ( interface->desc.bInterfaceClass != USB_CLASS_AUDIO || interface->desc.bInterfaceSubClass != USB_SUBCLASS_MIDISTREAMING ) continue; - alts = i; + alts = interface->desc.bAlternateSetting; } if ( alts == -1 ) { return -EINVAL; @@ -1915,30 +1897,11 @@ descriptor they modify or extend. */ - ret = usb_get_descriptor( d, USB_DT_CONFIG, i, buf, USB_DT_CONFIG_SIZE ); - if ( ret < 0 ) { - printk(KERN_INFO "usb-midi: Could not get config (error=%d).\n", ret); - return -EINVAL; - } - if ( buf[1] != USB_DT_CONFIG || buf[0] < USB_DT_CONFIG_SIZE ) { - printk(KERN_INFO "usb-midi: config not as expected.\n"); - return -EINVAL; - } - bufSize = buf[2] | buf[3]<<8; - buffer = (unsigned char *)kmalloc(sizeof(unsigned char)*bufSize, GFP_KERNEL); - if ( !buffer ) { - printk(KERN_INFO "usb-midi: Could not allocate memory.\n"); - return -EINVAL; - } - ret = usb_get_descriptor( d, USB_DT_CONFIG, i, buffer, bufSize ); - if ( ret < 0 ) { - printk(KERN_INFO "usb-midi: Could not get full config (error=%d).\n", ret); - kfree(buffer); - return -EINVAL; - } + i = d->actconfig - d->config; + buffer = d->rawdescriptors[i]; + bufSize = d->actconfig->desc.wTotalLength; u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 0); - kfree(buffer); if ( u == NULL ) { return -EINVAL; } @@ -2002,7 +1965,7 @@ { struct usb_midi_state *s; struct usb_device *dev = interface_to_usbdev(intf); - int ifnum = intf->altsetting->desc.bInterfaceNumber; + int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; s = (struct usb_midi_state *)kmalloc(sizeof(struct usb_midi_state), GFP_KERNEL); if ( !s ) @@ -2018,9 +1981,9 @@ if ( detect_by_hand( dev, ifnum, s ) && - detect_midi_subclass( dev, ifnum, s ) && + detect_midi_subclass( dev, intf, ifnum, s ) && detect_vendor_specific_device( dev, ifnum, s ) && - detect_yamaha_device( dev, ifnum, s) ) { + detect_yamaha_device( dev, intf, ifnum, s) ) { kfree(s); return -EIO; }