Commit bfa414e2 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

USB: Convert the core code to use struct device_driver.

parent 7c3ccad2
...@@ -111,7 +111,6 @@ static char *format_endpt = ...@@ -111,7 +111,6 @@ static char *format_endpt =
/* /*
* Need access to the driver and USB bus lists. * Need access to the driver and USB bus lists.
* extern struct list_head usb_driver_list;
* extern struct list_head usb_bus_list; * extern struct list_head usb_bus_list;
* However, these will come from functions that return ptrs to each of them. * However, these will come from functions that return ptrs to each of them.
*/ */
......
...@@ -298,15 +298,15 @@ static void destroy_all_async(struct dev_state *ps) ...@@ -298,15 +298,15 @@ static void destroy_all_async(struct dev_state *ps)
* they're also undone when devices disconnect. * they're also undone when devices disconnect.
*/ */
static void *driver_probe(struct usb_device *dev, unsigned int intf, static int driver_probe (struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
return NULL; return -ENODEV;
} }
static void driver_disconnect(struct usb_device *dev, void *context) static void driver_disconnect(struct usb_interface *intf)
{ {
struct dev_state *ps = (struct dev_state *)context; struct dev_state *ps = dev_get_drvdata (&intf->dev);
if (!ps) if (!ps)
return; return;
...@@ -317,6 +317,7 @@ static void driver_disconnect(struct usb_device *dev, void *context) ...@@ -317,6 +317,7 @@ static void driver_disconnect(struct usb_device *dev, void *context)
/* prevent new I/O requests */ /* prevent new I/O requests */
ps->dev = 0; ps->dev = 0;
ps->ifclaimed = 0; ps->ifclaimed = 0;
dev_set_drvdata (&intf->dev, NULL);
/* force async requests to complete */ /* force async requests to complete */
destroy_all_async (ps); destroy_all_async (ps);
...@@ -427,30 +428,6 @@ static int findintfif(struct usb_device *dev, unsigned int ifn) ...@@ -427,30 +428,6 @@ static int findintfif(struct usb_device *dev, unsigned int ifn)
return -ENOENT; return -ENOENT;
} }
extern struct list_head usb_driver_list;
#if 0
static int finddriver(struct usb_driver **driver, char *name)
{
struct list_head *tmp;
tmp = usb_driver_list.next;
while (tmp != &usb_driver_list) {
struct usb_driver *d = list_entry(tmp, struct usb_driver,
driver_list);
if (!strcmp(d->name, name)) {
*driver = d;
return 0;
}
tmp = tmp->next;
}
return -EINVAL;
}
#endif
static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsigned int index) static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsigned int index)
{ {
int ret; int ret;
...@@ -723,11 +700,10 @@ static int proc_resetdevice(struct dev_state *ps) ...@@ -723,11 +700,10 @@ static int proc_resetdevice(struct dev_state *ps)
if (test_bit(i, &ps->ifclaimed)) if (test_bit(i, &ps->ifclaimed))
continue; continue;
lock_kernel(); err ("%s - this function is broken", __FUNCTION__);
if (intf->driver && ps->dev) { if (intf->driver && ps->dev) {
usb_bind_driver (intf->driver, intf); usb_device_probe (&intf->dev);
} }
unlock_kernel();
} }
return 0; return 0;
...@@ -1090,22 +1066,19 @@ static int proc_ioctl (struct dev_state *ps, void *arg) ...@@ -1090,22 +1066,19 @@ static int proc_ioctl (struct dev_state *ps, void *arg)
/* disconnect kernel driver from interface, leaving it unbound. */ /* disconnect kernel driver from interface, leaving it unbound. */
case USBDEVFS_DISCONNECT: case USBDEVFS_DISCONNECT:
/* this function is voodoo. without locking it is a maybe thing */ /* this function is voodoo. */
lock_kernel();
driver = ifp->driver; driver = ifp->driver;
if (driver) { if (driver) {
dbg ("disconnect '%s' from dev %d interface %d", dbg ("disconnect '%s' from dev %d interface %d",
driver->name, ps->dev->devnum, ctrl.ifno); driver->name, ps->dev->devnum, ctrl.ifno);
usb_unbind_driver(ps->dev, ifp); usb_device_remove(&ifp->dev);
usb_driver_release_interface (driver, ifp);
} else } else
retval = -EINVAL; retval = -EINVAL;
unlock_kernel();
break; break;
/* let kernel drivers try to (re)bind to the interface */ /* let kernel drivers try to (re)bind to the interface */
case USBDEVFS_CONNECT: case USBDEVFS_CONNECT:
usb_find_interface_driver (ps->dev, ifp); retval = usb_device_probe (&ifp->dev);
break; break;
/* talk directly to the interface's driver */ /* talk directly to the interface's driver */
......
...@@ -722,12 +722,10 @@ int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev ...@@ -722,12 +722,10 @@ int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev
{ {
int retval; int retval;
usb_dev->dev.parent = parent_dev; sprintf (&usb_dev->dev.bus_id[0], "usb%d", usb_dev->bus->busnum);
strcpy (&usb_dev->dev.name[0], "usb_name"); retval = usb_new_device (usb_dev, parent_dev);
strcpy (&usb_dev->dev.bus_id[0], "usb_bus");
retval = usb_new_device (usb_dev);
if (retval) if (retval)
put_device (&usb_dev->dev); err("%s - usb_new_device failed with value %d", __FUNCTION__, retval);
return retval; return retval;
} }
EXPORT_SYMBOL (usb_register_root_hub); EXPORT_SYMBOL (usb_register_root_hub);
......
...@@ -270,7 +270,7 @@ extern void usb_hc_died (struct usb_hcd *hcd); ...@@ -270,7 +270,7 @@ extern void usb_hc_died (struct usb_hcd *hcd);
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* Enumeration is only for the hub driver, or HCD virtual root hubs */ /* Enumeration is only for the hub driver, or HCD virtual root hubs */
extern int usb_new_device(struct usb_device *dev); extern int usb_new_device(struct usb_device *dev, struct device *parent);
extern void usb_connect(struct usb_device *dev); extern void usb_connect(struct usb_device *dev);
extern void usb_disconnect(struct usb_device **); extern void usb_disconnect(struct usb_device **);
...@@ -396,12 +396,6 @@ extern int usb_find_interface_driver (struct usb_device *dev, ...@@ -396,12 +396,6 @@ extern int usb_find_interface_driver (struct usb_device *dev,
#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN)) #define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN))
/* for probe/disconnect with correct module usage counting */
void *usb_bind_driver(struct usb_driver *driver, struct usb_interface *intf);
void usb_unbind_driver(struct usb_device *device, struct usb_interface *intf);
extern struct list_head usb_driver_list;
/* /*
* USB device fs stuff * USB device fs stuff
*/ */
......
...@@ -175,6 +175,7 @@ static void hub_tt_kevent (void *arg) ...@@ -175,6 +175,7 @@ static void hub_tt_kevent (void *arg)
while (!list_empty (&hub->tt.clear_list)) { while (!list_empty (&hub->tt.clear_list)) {
struct list_head *temp; struct list_head *temp;
struct usb_tt_clear *clear; struct usb_tt_clear *clear;
struct usb_device *dev;
int status; int status;
temp = hub->tt.clear_list.next; temp = hub->tt.clear_list.next;
...@@ -183,13 +184,13 @@ static void hub_tt_kevent (void *arg) ...@@ -183,13 +184,13 @@ static void hub_tt_kevent (void *arg)
/* drop lock so HCD can concurrently report other TT errors */ /* drop lock so HCD can concurrently report other TT errors */
spin_unlock_irqrestore (&hub->tt.lock, flags); spin_unlock_irqrestore (&hub->tt.lock, flags);
status = hub_clear_tt_buffer (hub->dev, dev = interface_to_usbdev (hub->intf);
clear->devinfo, clear->tt); status = hub_clear_tt_buffer (dev, clear->devinfo, clear->tt);
spin_lock_irqsave (&hub->tt.lock, flags); spin_lock_irqsave (&hub->tt.lock, flags);
if (status) if (status)
err ("usb-%s-%s clear tt %d (%04x) error %d", err ("usb-%s-%s clear tt %d (%04x) error %d",
hub->dev->bus->bus_name, hub->dev->devpath, dev->bus->bus_name, dev->devpath,
clear->tt, clear->devinfo, status); clear->tt, clear->devinfo, status);
kfree (clear); kfree (clear);
} }
...@@ -245,12 +246,14 @@ void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe) ...@@ -245,12 +246,14 @@ void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe)
static void usb_hub_power_on(struct usb_hub *hub) static void usb_hub_power_on(struct usb_hub *hub)
{ {
struct usb_device *dev;
int i; int i;
/* Enable power to the ports */ /* Enable power to the ports */
dbg("enabling power on all ports"); dbg("enabling power on all ports");
dev = interface_to_usbdev(hub->intf);
for (i = 0; i < hub->descriptor->bNbrPorts; i++) for (i = 0; i < hub->descriptor->bNbrPorts; i++)
usb_set_port_feature(hub->dev, i + 1, USB_PORT_FEAT_POWER); usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
/* Wait for power to be enabled */ /* Wait for power to be enabled */
wait_ms(hub->descriptor->bPwrOn2PwrGood * 2); wait_ms(hub->descriptor->bPwrOn2PwrGood * 2);
...@@ -259,7 +262,7 @@ static void usb_hub_power_on(struct usb_hub *hub) ...@@ -259,7 +262,7 @@ static void usb_hub_power_on(struct usb_hub *hub)
static int usb_hub_configure(struct usb_hub *hub, static int usb_hub_configure(struct usb_hub *hub,
struct usb_endpoint_descriptor *endpoint) struct usb_endpoint_descriptor *endpoint)
{ {
struct usb_device *dev = hub->dev; struct usb_device *dev = interface_to_usbdev (hub->intf);
struct usb_hub_status hubstatus; struct usb_hub_status hubstatus;
unsigned int pipe; unsigned int pipe;
int maxp, ret; int maxp, ret;
...@@ -425,39 +428,81 @@ static int usb_hub_configure(struct usb_hub *hub, ...@@ -425,39 +428,81 @@ static int usb_hub_configure(struct usb_hub *hub,
return 0; return 0;
} }
static void *hub_probe(struct usb_device *dev, unsigned int i, static void hub_disconnect(struct usb_interface *intf)
const struct usb_device_id *id) {
struct usb_hub *hub = dev_get_drvdata (&intf->dev);
unsigned long flags;
if (!hub)
return;
dev_set_drvdata (&intf->dev, NULL);
spin_lock_irqsave(&hub_event_lock, flags);
/* Delete it and then reset it */
list_del(&hub->event_list);
INIT_LIST_HEAD(&hub->event_list);
list_del(&hub->hub_list);
INIT_LIST_HEAD(&hub->hub_list);
spin_unlock_irqrestore(&hub_event_lock, flags);
down(&hub->khubd_sem); /* Wait for khubd to leave this hub alone. */
up(&hub->khubd_sem);
/* assuming we used keventd, it must quiesce too */
if (hub->tt.hub)
flush_scheduled_tasks ();
if (hub->urb) {
usb_unlink_urb(hub->urb);
usb_free_urb(hub->urb);
hub->urb = NULL;
}
if (hub->descriptor) {
kfree(hub->descriptor);
hub->descriptor = NULL;
}
/* Free the memory */
kfree(hub);
}
static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
{ {
struct usb_interface_descriptor *interface; struct usb_interface_descriptor *desc;
struct usb_endpoint_descriptor *endpoint; struct usb_endpoint_descriptor *endpoint;
struct usb_device *dev;
struct usb_hub *hub; struct usb_hub *hub;
unsigned long flags; unsigned long flags;
interface = &dev->actconfig->interface[i].altsetting[0]; desc = intf->altsetting + intf->act_altsetting;
dev = interface_to_usbdev(intf);
/* Some hubs have a subclass of 1, which AFAICT according to the */ /* Some hubs have a subclass of 1, which AFAICT according to the */
/* specs is not defined, but it works */ /* specs is not defined, but it works */
if ((interface->bInterfaceSubClass != 0) && if ((desc->bInterfaceSubClass != 0) &&
(interface->bInterfaceSubClass != 1)) { (desc->bInterfaceSubClass != 1)) {
err("invalid subclass (%d) for USB hub device #%d", err("invalid subclass (%d) for USB hub device #%d",
interface->bInterfaceSubClass, dev->devnum); desc->bInterfaceSubClass, dev->devnum);
return NULL; return -EIO;
} }
/* Multiple endpoints? What kind of mutant ninja-hub is this? */ /* Multiple endpoints? What kind of mutant ninja-hub is this? */
if (interface->bNumEndpoints != 1) { if (desc->bNumEndpoints != 1) {
err("invalid bNumEndpoints (%d) for USB hub device #%d", err("invalid bNumEndpoints (%d) for USB hub device #%d",
interface->bNumEndpoints, dev->devnum); desc->bNumEndpoints, dev->devnum);
return NULL; return -EIO;
} }
endpoint = &interface->endpoint[0]; endpoint = &desc->endpoint[0];
/* Output endpoint? Curiousier and curiousier.. */ /* Output endpoint? Curiousier and curiousier.. */
if (!(endpoint->bEndpointAddress & USB_DIR_IN)) { if (!(endpoint->bEndpointAddress & USB_DIR_IN)) {
err("Device #%d is hub class, but has output endpoint?", err("Device #%d is hub class, but has output endpoint?",
dev->devnum); dev->devnum);
return NULL; return -EIO;
} }
/* If it's not an interrupt endpoint, we'd better punt! */ /* If it's not an interrupt endpoint, we'd better punt! */
...@@ -465,7 +510,7 @@ static void *hub_probe(struct usb_device *dev, unsigned int i, ...@@ -465,7 +510,7 @@ static void *hub_probe(struct usb_device *dev, unsigned int i,
!= USB_ENDPOINT_XFER_INT) { != USB_ENDPOINT_XFER_INT) {
err("Device #%d is hub class, but endpoint is not interrupt?", err("Device #%d is hub class, but endpoint is not interrupt?",
dev->devnum); dev->devnum);
return NULL; return -EIO;
} }
/* We found a hub */ /* We found a hub */
...@@ -474,13 +519,13 @@ static void *hub_probe(struct usb_device *dev, unsigned int i, ...@@ -474,13 +519,13 @@ static void *hub_probe(struct usb_device *dev, unsigned int i,
hub = kmalloc(sizeof(*hub), GFP_KERNEL); hub = kmalloc(sizeof(*hub), GFP_KERNEL);
if (!hub) { if (!hub) {
err("couldn't kmalloc hub struct"); err("couldn't kmalloc hub struct");
return NULL; return -ENOMEM;
} }
memset(hub, 0, sizeof(*hub)); memset(hub, 0, sizeof(*hub));
INIT_LIST_HEAD(&hub->event_list); INIT_LIST_HEAD(&hub->event_list);
hub->dev = dev; hub->intf = intf;
init_MUTEX(&hub->khubd_sem); init_MUTEX(&hub->khubd_sem);
/* Record the new hub's existence */ /* Record the new hub's existence */
...@@ -489,65 +534,17 @@ static void *hub_probe(struct usb_device *dev, unsigned int i, ...@@ -489,65 +534,17 @@ static void *hub_probe(struct usb_device *dev, unsigned int i,
list_add(&hub->hub_list, &hub_list); list_add(&hub->hub_list, &hub_list);
spin_unlock_irqrestore(&hub_event_lock, flags); spin_unlock_irqrestore(&hub_event_lock, flags);
dev_set_drvdata (&intf->dev, hub);
if (usb_hub_configure(hub, endpoint) >= 0) { if (usb_hub_configure(hub, endpoint) >= 0) {
strcpy (dev->actconfig->interface[i].dev.name, strcpy (intf->dev.name, "Hub/Port Status Changes");
"Hub/Port Status Changes"); return 0;
return hub;
} }
err("hub configuration failed for device at %s", dev->devpath); err("hub configuration failed for device at %s", dev->devpath);
/* free hub, but first clean up its list. */ hub_disconnect (intf);
spin_lock_irqsave(&hub_event_lock, flags); return -ENODEV;
/* Delete it and then reset it */
list_del(&hub->event_list);
INIT_LIST_HEAD(&hub->event_list);
list_del(&hub->hub_list);
INIT_LIST_HEAD(&hub->hub_list);
spin_unlock_irqrestore(&hub_event_lock, flags);
kfree(hub);
return NULL;
}
static void hub_disconnect(struct usb_device *dev, void *ptr)
{
struct usb_hub *hub = (struct usb_hub *)ptr;
unsigned long flags;
spin_lock_irqsave(&hub_event_lock, flags);
/* Delete it and then reset it */
list_del(&hub->event_list);
INIT_LIST_HEAD(&hub->event_list);
list_del(&hub->hub_list);
INIT_LIST_HEAD(&hub->hub_list);
spin_unlock_irqrestore(&hub_event_lock, flags);
down(&hub->khubd_sem); /* Wait for khubd to leave this hub alone. */
up(&hub->khubd_sem);
/* assuming we used keventd, it must quiesce too */
if (hub->tt.hub)
flush_scheduled_tasks ();
if (hub->urb) {
usb_unlink_urb(hub->urb);
usb_free_urb(hub->urb);
hub->urb = NULL;
}
if (hub->descriptor) {
kfree(hub->descriptor);
hub->descriptor = NULL;
}
/* Free the memory */
kfree(hub);
} }
static int hub_ioctl(struct usb_device *hub, unsigned int code, void *user_data) static int hub_ioctl(struct usb_device *hub, unsigned int code, void *user_data)
...@@ -584,7 +581,7 @@ static int hub_ioctl(struct usb_device *hub, unsigned int code, void *user_data) ...@@ -584,7 +581,7 @@ static int hub_ioctl(struct usb_device *hub, unsigned int code, void *user_data)
static int usb_hub_reset(struct usb_hub *hub) static int usb_hub_reset(struct usb_hub *hub)
{ {
struct usb_device *dev = hub->dev; struct usb_device *dev = interface_to_usbdev(hub->intf);
int i; int i;
/* Disconnect any attached devices */ /* Disconnect any attached devices */
...@@ -796,7 +793,7 @@ static int usb_hub_port_debounce(struct usb_device *hub, int port) ...@@ -796,7 +793,7 @@ static int usb_hub_port_debounce(struct usb_device *hub, int port)
static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port, static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
u16 portstatus, u16 portchange) u16 portstatus, u16 portchange)
{ {
struct usb_device *hub = hubstate->dev; struct usb_device *hub = interface_to_usbdev(hubstate->intf);
struct usb_device *dev; struct usb_device *dev;
unsigned int delay = HUB_SHORT_RESET_TIME; unsigned int delay = HUB_SHORT_RESET_TIME;
int i; int i;
...@@ -891,11 +888,10 @@ static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port, ...@@ -891,11 +888,10 @@ static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
/* put the device in the global device tree. the hub port /* put the device in the global device tree. the hub port
* is the "bus_id"; hubs show in hierarchy like bridges * is the "bus_id"; hubs show in hierarchy like bridges
*/ */
dev->dev.parent = &dev->parent->dev; dev->dev.parent = dev->parent->dev.parent->parent;
sprintf (&dev->dev.bus_id[0], "%d", port + 1);
/* Run it through the hoops (find a driver, etc) */ /* Run it through the hoops (find a driver, etc) */
if (!usb_new_device(dev)) if (!usb_new_device(dev, &hub->dev))
goto done; goto done;
/* Free the configuration if there was an error */ /* Free the configuration if there was an error */
...@@ -940,7 +936,7 @@ static void usb_hub_events(void) ...@@ -940,7 +936,7 @@ static void usb_hub_events(void)
tmp = hub_event_list.next; tmp = hub_event_list.next;
hub = list_entry(tmp, struct usb_hub, event_list); hub = list_entry(tmp, struct usb_hub, event_list);
dev = hub->dev; dev = interface_to_usbdev(hub->intf);
list_del(tmp); list_del(tmp);
INIT_LIST_HEAD(tmp); INIT_LIST_HEAD(tmp);
...@@ -1081,8 +1077,8 @@ MODULE_DEVICE_TABLE (usb, hub_id_table); ...@@ -1081,8 +1077,8 @@ MODULE_DEVICE_TABLE (usb, hub_id_table);
static struct usb_driver hub_driver = { static struct usb_driver hub_driver = {
.name = "hub", .name = "hub",
.probe = hub_probe, .probe = hub_probe,
.ioctl = hub_ioctl,
.disconnect = hub_disconnect, .disconnect = hub_disconnect,
.ioctl = hub_ioctl,
.id_table = hub_id_table, .id_table = hub_id_table,
}; };
......
...@@ -170,7 +170,7 @@ struct usb_tt_clear { ...@@ -170,7 +170,7 @@ struct usb_tt_clear {
extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe); extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe);
struct usb_hub { struct usb_hub {
struct usb_device *dev; /* the "real" device */ struct usb_interface *intf; /* the "real" device */
struct urb *urb; /* for interrupt polling pipe */ struct urb *urb; /* for interrupt polling pipe */
/* buffer for urb ... 1 bit each for hub and children, rounded up */ /* buffer for urb ... 1 bit each for hub and children, rounded up */
......
This diff is collapsed.
...@@ -399,9 +399,6 @@ extern struct usb_device *usb_get_dev(struct usb_device *dev); ...@@ -399,9 +399,6 @@ extern struct usb_device *usb_get_dev(struct usb_device *dev);
extern void usb_free_dev(struct usb_device *); extern void usb_free_dev(struct usb_device *);
#define usb_put_dev usb_free_dev #define usb_put_dev usb_free_dev
/* for when layers above USB add new non-USB drivers */
extern void usb_scan_devices(void);
/* mostly for devices emulating SCSI over USB */ /* mostly for devices emulating SCSI over USB */
extern int usb_reset_device(struct usb_device *dev); extern int usb_reset_device(struct usb_device *dev);
...@@ -623,10 +620,10 @@ struct usb_device_id { ...@@ -623,10 +620,10 @@ struct usb_device_id {
* expose information to user space regardless of where they * expose information to user space regardless of where they
* do (or don't) show up otherwise in the filesystem. * do (or don't) show up otherwise in the filesystem.
* @id_table: USB drivers use ID table to support hotplugging. * @id_table: USB drivers use ID table to support hotplugging.
* Export this with MODULE_DEVICE_TABLE(usb,...), or use NULL to * Export this with MODULE_DEVICE_TABLE(usb,...). This must be set
* say that probe() should be called for any unclaimed interfce. * or your driver's probe function will never get called.
* *
* USB drivers should provide a name, probe() and disconnect() methods, * USB drivers must provide a name, probe() and disconnect() methods,
* and an id_table. Other driver fields are optional. * and an id_table. Other driver fields are optional.
* *
* The id_table is used in hotplugging. It holds a set of descriptors, * The id_table is used in hotplugging. It holds a set of descriptors,
...@@ -643,32 +640,23 @@ struct usb_device_id { ...@@ -643,32 +640,23 @@ struct usb_device_id {
*/ */
struct usb_driver { struct usb_driver {
struct module *owner; struct module *owner;
const char *name; const char *name;
void *(*probe)( int (*probe) (struct usb_interface *intf,
struct usb_device *dev, /* the device */ const struct usb_device_id *id);
unsigned intf, /* what interface */
const struct usb_device_id *id /* from id_table */
);
void (*disconnect)(
struct usb_device *dev, /* the device */
void *handle /* as returned by probe() */
);
struct list_head driver_list;
struct semaphore serialize;
/* ioctl -- userspace apps can talk to drivers through usbfs */ void (*disconnect) (struct usb_interface *intf);
int (*ioctl)(struct usb_device *dev, unsigned int code, void *buf);
int (*ioctl) (struct usb_device *dev, unsigned int code, void *buf);
/* support for "new-style" USB hotplugging */
const struct usb_device_id *id_table; const struct usb_device_id *id_table;
/* suspend before the bus suspends; struct device_driver driver;
* disconnect or resume when the bus resumes */
/* void (*suspend)(struct usb_device *dev); */ struct semaphore serialize;
/* void (*resume)(struct usb_device *dev); */
}; };
#define to_usb_driver(d) container_of(d, struct usb_driver, driver)
extern struct bus_type usb_bus_type; extern struct bus_type usb_bus_type;
...@@ -682,6 +670,9 @@ extern void usb_deregister(struct usb_driver *); ...@@ -682,6 +670,9 @@ extern void usb_deregister(struct usb_driver *);
extern int usb_register_dev(struct file_operations *fops, int minor, int num_minors, int *start_minor); extern int usb_register_dev(struct file_operations *fops, int minor, int num_minors, int *start_minor);
extern void usb_deregister_dev(int num_minors, int start_minor); extern void usb_deregister_dev(int num_minors, int start_minor);
extern int usb_device_probe(struct device *dev);
extern int usb_device_remove(struct device *dev);
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment