On Wed, May 04, 2005 at 10:30:57AM +0400, Roman Kagan wrote:
> On Fri, Apr 29, 2005 at 02:34:59PM -0400, Alan Stern wrote:
> > Does the patch look good?  If you like it, I'll submit it to Greg.
> 
> Yes it looks reasonable.  At the moment I can't test the problematic
> multi-interface USB device case where that bug revealed itself, which
> was observed by Duncan Sands; I'm attaching a simple test case we've
> been using to trigger the problem, so you may want to try it out before
> submitting.  To do that, you need to load the test driver giving vendor and
> product IDs of your multi-interface device as module parameters, and
> then rmmod the driver while the device is still plugged in: it used to
> spin forever

Sorry, forgot to attach the test case (it's very simple but can save you
a bit of typing).

Roman.

===============================================================
#define DEBUG

#include <linux/module.h>
#include <linux/usb.h>

unsigned short vendor;
module_param(vendor, ushort, 0444);
unsigned short product;
module_param(product, ushort, 0444);

static int test_usb_probe(struct usb_interface *intf, const struct 
usb_device_id *id);
void test_usb_disconnect(struct usb_interface *intf);

static struct usb_device_id test_usb_ids[2];
static struct usb_driver test_usb_driver = {
        .owner          = THIS_MODULE,
        .name           = "test",
        .probe          = test_usb_probe,
        .disconnect     = test_usb_disconnect,
        .id_table       = test_usb_ids
};

static void release_interfaces(struct usb_device *usb_dev, int num_interfaces) {
        struct usb_interface *cur_intf;
        int i;

        dbg("%s entered", __func__);

        for(i = 0; i < num_interfaces; i++)
                if ((cur_intf = usb_ifnum_to_if(usb_dev, i))) {
                        usb_set_intfdata(cur_intf, NULL);
                        usb_driver_release_interface(&test_usb_driver, 
cur_intf);
                }
}

static int test_usb_probe(struct usb_interface *intf, const struct 
usb_device_id *id)
{
        struct usb_device *usb_dev = interface_to_usbdev(intf);
        struct usb_interface *cur_intf;
        int ifnum = intf->altsetting->desc.bInterfaceNumber;
        int num_interfaces = usb_dev->actconfig->desc.bNumInterfaces;
        int i, ret;

        dbg("%s entered: intf 0x%p driver 0x%p", __func__, intf, 
intf->dev.driver);

        for (i=0; i < num_interfaces; i++) {
                cur_intf = usb_ifnum_to_if(usb_dev, i);

                if ((i != ifnum) && cur_intf) {
                        dbg("%s: claiming intf 0x%p", __func__, cur_intf);
                        ret = usb_driver_claim_interface(&test_usb_driver, 
cur_intf, usb_dev);

                        if (ret < 0) {
                                dbg("%s: failed to claim interface %d (%d)\n", 
__func__, i, ret);
                                release_interfaces(usb_dev, i);
                                return ret;
                        }

                        dbg("%s: claimed intf 0x%p driver 0x%p", __func__, 
cur_intf, cur_intf->dev.driver);
                }
        }

        return 0;
}

void test_usb_disconnect(struct usb_interface *intf)
{
        struct usb_device *usb_dev = interface_to_usbdev(intf);
        int num_interfaces = usb_dev->actconfig->desc.bNumInterfaces;
        int i = 0;
        struct list_head *l, *n;

        dbg("%s entered: intf 0x%p driver 0x%p", __func__, intf, 
intf->dev.driver);
        if (intf->dev.driver)
                list_for_each_safe(l, n, &intf->dev.driver->devices)
                        i++;
        dbg("%s: driver 0x%p has %d devices", __func__, intf->dev.driver, i);

        if (usb_get_intfdata(intf))
                release_interfaces(usb_dev, num_interfaces);
        else
                dbg("NULL instance");
}

static int __init test_init(void)
{
        dbg("%s entered", __func__);

        printk("vendor: %04x, product: %04x\n", vendor, product);

        test_usb_ids[0].match_flags     = USB_DEVICE_ID_MATCH_DEVICE;
        test_usb_ids[0].idVendor        = vendor;
        test_usb_ids[0].idProduct       = product;

        return usb_register(&test_usb_driver);
}
module_init(test_init);

static void __exit test_exit(void)
{
        dbg("%s entered", __func__);

        usb_deregister(&test_usb_driver);
}
module_exit(test_exit);

MODULE_LICENSE("GPL");


-------------------------------------------------------
This SF.Net email is sponsored by: NEC IT Guy Games.
Get your fingers limbered up and give it your best shot. 4 great events, 4
opportunities to win big! Highest score wins.NEC IT Guy Games. Play to
win an NEC 61 plasma display. Visit http://www.necitguy.com/?r=20
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to