forked from Minki/linux
USB: make usbdevices export their device nodes instead of using a separate class
o The "real" usb-devices export now a device node which can populate /dev/bus/usb. o The usb_device class is optional now and can be disabled in the kernel config. Major/minor of the "real" devices and class devices are the same. o The environment of the usb-device event contains DEVNUM and BUSNUM to help udev and get rid of the ugly udev rule we need for the class devices. o The usb-devices and usb-interfaces share the same bus, so I used the new "struct device_type" to let these devices identify themselves. This also removes the current logic of using a magic platform-pointer. The name of the device_type is also added to the environment which makes it easier to distinguish the different kinds of devices on the same subsystem. It looks like this: add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1 ACTION=add DEVPATH=/devices/pci0000:00/0000:00:1d.1/usb2/2-1 SUBSYSTEM=usb SEQNUM=1533 MAJOR=189 MINOR=131 DEVTYPE=usb_device PRODUCT=46d/c03e/2000 TYPE=0/0/0 BUSNUM=002 DEVNUM=004 This udev rule works as a replacement for usb_device class devices: SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", \ NAME="bus/usb/$env{BUSNUM}/$env{DEVNUM}", MODE="0644" Updated patch, which needs the device_type patches in Greg's tree. I also got a bugzilla assigned for this. :) https://bugzilla.novell.com/show_bug.cgi?id=250659 Signed-off-by: Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
8784028963
commit
9f8b17e643
@ -31,7 +31,30 @@ config USB_DEVICEFS
|
||||
For the format of the various /proc/bus/usb/ files, please read
|
||||
<file:Documentation/usb/proc_usb_info.txt>.
|
||||
|
||||
Most users want to say Y here.
|
||||
Usbfs files can't handle Access Control Lists (ACL), which are the
|
||||
default way to grant access to USB devices for untrusted users of a
|
||||
desktop system. The usbfs functionality is replaced by real
|
||||
device-nodes managed by udev. These nodes live in /dev/bus/usb and
|
||||
are used by libusb.
|
||||
|
||||
config USB_DEVICE_CLASS
|
||||
bool "USB device class-devices (DEPRECATED)"
|
||||
depends on USB
|
||||
default n
|
||||
---help---
|
||||
Userspace access to USB devices is granted by device-nodes exported
|
||||
directly from the usbdev in sysfs. Old versions of the driver
|
||||
core and udev needed additional class devices to export device nodes.
|
||||
|
||||
These additional devices are difficult to handle in userspace, if
|
||||
information about USB interfaces must be available. One device contains
|
||||
the device node, the other device contains the interface data. Both
|
||||
devices are at the same level in sysfs (siblings) and one can't access
|
||||
the other. The device node created directly by the usbdev is the parent
|
||||
device of the interface and therefore easily accessible from the interface
|
||||
event.
|
||||
|
||||
This option provides backward compatibility if needed.
|
||||
|
||||
config USB_DYNAMIC_MINORS
|
||||
bool "Dynamic USB minor allocation (EXPERIMENTAL)"
|
||||
|
@ -57,7 +57,6 @@
|
||||
|
||||
#define USB_MAXBUS 64
|
||||
#define USB_DEVICE_MAX USB_MAXBUS * 128
|
||||
static struct class *usb_device_class;
|
||||
|
||||
/* Mutual exclusion for removal, open, and release */
|
||||
DEFINE_MUTEX(usbfs_mutex);
|
||||
@ -514,22 +513,25 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct usb_device *usbdev_lookup_minor(int minor)
|
||||
static int __match_minor(struct device *dev, void *data)
|
||||
{
|
||||
struct device *device;
|
||||
struct usb_device *udev = NULL;
|
||||
int minor = *((int *)data);
|
||||
|
||||
down(&usb_device_class->sem);
|
||||
list_for_each_entry(device, &usb_device_class->devices, node) {
|
||||
if (device->devt == MKDEV(USB_DEVICE_MAJOR, minor)) {
|
||||
udev = device->platform_data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
up(&usb_device_class->sem);
|
||||
if (dev->devt == MKDEV(USB_DEVICE_MAJOR, minor))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return udev;
|
||||
};
|
||||
static struct usb_device *usbdev_lookup_by_minor(int minor)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
dev = bus_find_device(&usb_bus_type, NULL, &minor, __match_minor);
|
||||
if (!dev)
|
||||
return NULL;
|
||||
put_device(dev);
|
||||
return container_of(dev, struct usb_device, dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* file operations
|
||||
@ -548,11 +550,14 @@ static int usbdev_open(struct inode *inode, struct file *file)
|
||||
goto out;
|
||||
|
||||
ret = -ENOENT;
|
||||
/* check if we are called from a real node or usbfs */
|
||||
/* usbdev device-node */
|
||||
if (imajor(inode) == USB_DEVICE_MAJOR)
|
||||
dev = usbdev_lookup_minor(iminor(inode));
|
||||
dev = usbdev_lookup_by_minor(iminor(inode));
|
||||
#ifdef CONFIG_USB_DEVICEFS
|
||||
/* procfs file */
|
||||
if (!dev)
|
||||
dev = inode->i_private;
|
||||
#endif
|
||||
if (!dev)
|
||||
goto out;
|
||||
ret = usb_autoresume_device(dev);
|
||||
@ -1570,7 +1575,7 @@ static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wai
|
||||
return mask;
|
||||
}
|
||||
|
||||
const struct file_operations usbfs_device_file_operations = {
|
||||
const struct file_operations usbdev_file_operations = {
|
||||
.llseek = usbdev_lseek,
|
||||
.read = usbdev_read,
|
||||
.poll = usbdev_poll,
|
||||
@ -1579,50 +1584,53 @@ const struct file_operations usbfs_device_file_operations = {
|
||||
.release = usbdev_release,
|
||||
};
|
||||
|
||||
static int usbdev_add(struct usb_device *dev)
|
||||
#ifdef CONFIG_USB_DEVICE_CLASS
|
||||
static struct class *usb_classdev_class;
|
||||
|
||||
static int usb_classdev_add(struct usb_device *dev)
|
||||
{
|
||||
int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
|
||||
|
||||
dev->usbfs_dev = device_create(usb_device_class, &dev->dev,
|
||||
dev->usb_classdev = device_create(usb_classdev_class, &dev->dev,
|
||||
MKDEV(USB_DEVICE_MAJOR, minor),
|
||||
"usbdev%d.%d", dev->bus->busnum, dev->devnum);
|
||||
if (IS_ERR(dev->usbfs_dev))
|
||||
return PTR_ERR(dev->usbfs_dev);
|
||||
if (IS_ERR(dev->usb_classdev))
|
||||
return PTR_ERR(dev->usb_classdev);
|
||||
|
||||
dev->usbfs_dev->platform_data = dev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usbdev_remove(struct usb_device *dev)
|
||||
static void usb_classdev_remove(struct usb_device *dev)
|
||||
{
|
||||
device_unregister(dev->usbfs_dev);
|
||||
device_unregister(dev->usb_classdev);
|
||||
}
|
||||
|
||||
static int usbdev_notify(struct notifier_block *self, unsigned long action,
|
||||
void *dev)
|
||||
static int usb_classdev_notify(struct notifier_block *self,
|
||||
unsigned long action, void *dev)
|
||||
{
|
||||
switch (action) {
|
||||
case USB_DEVICE_ADD:
|
||||
if (usbdev_add(dev))
|
||||
if (usb_classdev_add(dev))
|
||||
return NOTIFY_BAD;
|
||||
break;
|
||||
case USB_DEVICE_REMOVE:
|
||||
usbdev_remove(dev);
|
||||
usb_classdev_remove(dev);
|
||||
break;
|
||||
}
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block usbdev_nb = {
|
||||
.notifier_call = usbdev_notify,
|
||||
.notifier_call = usb_classdev_notify,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct cdev usb_device_cdev = {
|
||||
.kobj = {.name = "usb_device", },
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
int __init usbdev_init(void)
|
||||
int __init usb_devio_init(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
@ -1632,38 +1640,38 @@ int __init usbdev_init(void)
|
||||
err("unable to register minors for usb_device");
|
||||
goto out;
|
||||
}
|
||||
cdev_init(&usb_device_cdev, &usbfs_device_file_operations);
|
||||
cdev_init(&usb_device_cdev, &usbdev_file_operations);
|
||||
retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX);
|
||||
if (retval) {
|
||||
err("unable to get usb_device major %d", USB_DEVICE_MAJOR);
|
||||
goto error_cdev;
|
||||
}
|
||||
usb_device_class = class_create(THIS_MODULE, "usb_device");
|
||||
if (IS_ERR(usb_device_class)) {
|
||||
#ifdef CONFIG_USB_DEVICE_CLASS
|
||||
usb_classdev_class = class_create(THIS_MODULE, "usb_device");
|
||||
if (IS_ERR(usb_classdev_class)) {
|
||||
err("unable to register usb_device class");
|
||||
retval = PTR_ERR(usb_device_class);
|
||||
goto error_class;
|
||||
retval = PTR_ERR(usb_classdev_class);
|
||||
cdev_del(&usb_device_cdev);
|
||||
usb_classdev_class = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
usb_register_notify(&usbdev_nb);
|
||||
|
||||
#endif
|
||||
out:
|
||||
return retval;
|
||||
|
||||
error_class:
|
||||
usb_device_class = NULL;
|
||||
cdev_del(&usb_device_cdev);
|
||||
|
||||
error_cdev:
|
||||
unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
|
||||
goto out;
|
||||
}
|
||||
|
||||
void usbdev_cleanup(void)
|
||||
void usb_devio_cleanup(void)
|
||||
{
|
||||
#ifdef CONFIG_USB_DEVICE_CLASS
|
||||
usb_unregister_notify(&usbdev_nb);
|
||||
class_destroy(usb_device_class);
|
||||
class_destroy(usb_classdev_class);
|
||||
#endif
|
||||
cdev_del(&usb_device_cdev);
|
||||
unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
|
||||
}
|
||||
|
||||
|
@ -574,23 +574,10 @@ static int usb_device_match(struct device *dev, struct device_driver *drv)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
|
||||
/*
|
||||
* This sends an uevent to userspace, typically helping to load driver
|
||||
* or other modules, configure the device, and more. Drivers can provide
|
||||
* a MODULE_DEVICE_TABLE to help with module loading subtasks.
|
||||
*
|
||||
* We're called either from khubd (the typical case) or from root hub
|
||||
* (init, kapmd, modprobe, rmmod, etc), but the agents need to handle
|
||||
* delays in event delivery. Use sysfs (and DEVPATH) to make sure the
|
||||
* device (and this configuration!) are still present.
|
||||
*/
|
||||
static int usb_uevent(struct device *dev, char **envp, int num_envp,
|
||||
char *buffer, int buffer_size)
|
||||
{
|
||||
struct usb_interface *intf;
|
||||
struct usb_device *usb_dev;
|
||||
struct usb_host_interface *alt;
|
||||
int i = 0;
|
||||
int length = 0;
|
||||
|
||||
@ -600,13 +587,11 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp,
|
||||
/* driver is often null here; dev_dbg() would oops */
|
||||
pr_debug ("usb %s: uevent\n", dev->bus_id);
|
||||
|
||||
if (is_usb_device(dev)) {
|
||||
if (is_usb_device(dev))
|
||||
usb_dev = to_usb_device(dev);
|
||||
alt = NULL;
|
||||
} else {
|
||||
intf = to_usb_interface(dev);
|
||||
else {
|
||||
struct usb_interface *intf = to_usb_interface(dev);
|
||||
usb_dev = interface_to_usbdev(intf);
|
||||
alt = intf->cur_altsetting;
|
||||
}
|
||||
|
||||
if (usb_dev->devnum < 0) {
|
||||
@ -621,9 +606,7 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp,
|
||||
#ifdef CONFIG_USB_DEVICEFS
|
||||
/* If this is available, userspace programs can directly read
|
||||
* all the device descriptors we don't tell them about. Or
|
||||
* even act as usermode drivers.
|
||||
*
|
||||
* FIXME reduce hardwired intelligence here
|
||||
* act as usermode drivers.
|
||||
*/
|
||||
if (add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
@ -650,44 +633,29 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp,
|
||||
usb_dev->descriptor.bDeviceProtocol))
|
||||
return -ENOMEM;
|
||||
|
||||
if (!is_usb_device(dev)) {
|
||||
|
||||
if (add_uevent_var(envp, num_envp, &i,
|
||||
if (add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"INTERFACE=%d/%d/%d",
|
||||
alt->desc.bInterfaceClass,
|
||||
alt->desc.bInterfaceSubClass,
|
||||
alt->desc.bInterfaceProtocol))
|
||||
return -ENOMEM;
|
||||
"BUSNUM=%03d",
|
||||
usb_dev->bus->busnum))
|
||||
return -ENOMEM;
|
||||
|
||||
if (add_uevent_var(envp, num_envp, &i,
|
||||
if (add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
|
||||
le16_to_cpu(usb_dev->descriptor.idVendor),
|
||||
le16_to_cpu(usb_dev->descriptor.idProduct),
|
||||
le16_to_cpu(usb_dev->descriptor.bcdDevice),
|
||||
usb_dev->descriptor.bDeviceClass,
|
||||
usb_dev->descriptor.bDeviceSubClass,
|
||||
usb_dev->descriptor.bDeviceProtocol,
|
||||
alt->desc.bInterfaceClass,
|
||||
alt->desc.bInterfaceSubClass,
|
||||
alt->desc.bInterfaceProtocol))
|
||||
return -ENOMEM;
|
||||
}
|
||||
"DEVNUM=%03d",
|
||||
usb_dev->devnum))
|
||||
return -ENOMEM;
|
||||
|
||||
envp[i] = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int usb_uevent(struct device *dev, char **envp,
|
||||
int num_envp, char *buffer, int buffer_size)
|
||||
int num_envp, char *buffer, int buffer_size)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_HOTPLUG */
|
||||
|
||||
/**
|
||||
|
@ -1367,11 +1367,15 @@ int usb_new_device(struct usb_device *udev)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* export the usbdev device-node for libusb */
|
||||
udev->dev.devt = MKDEV(USB_DEVICE_MAJOR,
|
||||
(((udev->bus->busnum-1) * 128) + (udev->devnum-1)));
|
||||
|
||||
/* Register the device. The device driver is responsible
|
||||
* for adding the device files to usbfs and sysfs and for
|
||||
* configuring the device.
|
||||
* for adding the device files to sysfs and for configuring
|
||||
* the device.
|
||||
*/
|
||||
err = device_add (&udev->dev);
|
||||
err = device_add(&udev->dev);
|
||||
if (err) {
|
||||
dev_err(&udev->dev, "can't device_add, error %d\n", err);
|
||||
goto fail;
|
||||
|
@ -662,7 +662,7 @@ static void usbfs_add_device(struct usb_device *dev)
|
||||
sprintf (name, "%03d", dev->devnum);
|
||||
dev->usbfs_dentry = fs_create_file (name, devmode | S_IFREG,
|
||||
dev->bus->usbfs_dentry, dev,
|
||||
&usbfs_device_file_operations,
|
||||
&usbdev_file_operations,
|
||||
devuid, devgid);
|
||||
if (dev->usbfs_dentry == NULL) {
|
||||
err ("error creating usbfs device entry");
|
||||
|
@ -1305,7 +1305,7 @@ int usb_reset_configuration(struct usb_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void release_interface(struct device *dev)
|
||||
void usb_release_interface(struct device *dev)
|
||||
{
|
||||
struct usb_interface *intf = to_usb_interface(dev);
|
||||
struct usb_interface_cache *intfc =
|
||||
@ -1315,6 +1315,67 @@ static void release_interface(struct device *dev)
|
||||
kfree(intf);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
static int usb_if_uevent(struct device *dev, char **envp, int num_envp,
|
||||
char *buffer, int buffer_size)
|
||||
{
|
||||
struct usb_device *usb_dev;
|
||||
struct usb_interface *intf;
|
||||
struct usb_host_interface *alt;
|
||||
int i = 0;
|
||||
int length = 0;
|
||||
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
/* driver is often null here; dev_dbg() would oops */
|
||||
pr_debug ("usb %s: uevent\n", dev->bus_id);
|
||||
|
||||
intf = to_usb_interface(dev);
|
||||
usb_dev = interface_to_usbdev(intf);
|
||||
alt = intf->cur_altsetting;
|
||||
|
||||
if (add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"INTERFACE=%d/%d/%d",
|
||||
alt->desc.bInterfaceClass,
|
||||
alt->desc.bInterfaceSubClass,
|
||||
alt->desc.bInterfaceProtocol))
|
||||
return -ENOMEM;
|
||||
|
||||
if (add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
|
||||
le16_to_cpu(usb_dev->descriptor.idVendor),
|
||||
le16_to_cpu(usb_dev->descriptor.idProduct),
|
||||
le16_to_cpu(usb_dev->descriptor.bcdDevice),
|
||||
usb_dev->descriptor.bDeviceClass,
|
||||
usb_dev->descriptor.bDeviceSubClass,
|
||||
usb_dev->descriptor.bDeviceProtocol,
|
||||
alt->desc.bInterfaceClass,
|
||||
alt->desc.bInterfaceSubClass,
|
||||
alt->desc.bInterfaceProtocol))
|
||||
return -ENOMEM;
|
||||
|
||||
envp[i] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int usb_if_uevent(struct device *dev, char **envp,
|
||||
int num_envp, char *buffer, int buffer_size)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif /* CONFIG_HOTPLUG */
|
||||
|
||||
struct device_type usb_if_device_type = {
|
||||
.name = "usb_interface",
|
||||
.release = usb_release_interface,
|
||||
.uevent = usb_if_uevent,
|
||||
};
|
||||
|
||||
/*
|
||||
* usb_set_configuration - Makes a particular device setting be current
|
||||
* @dev: the device whose configuration is being updated
|
||||
@ -1478,8 +1539,8 @@ free_interfaces:
|
||||
intf->dev.parent = &dev->dev;
|
||||
intf->dev.driver = NULL;
|
||||
intf->dev.bus = &usb_bus_type;
|
||||
intf->dev.type = &usb_if_device_type;
|
||||
intf->dev.dma_mask = dev->dev.dma_mask;
|
||||
intf->dev.release = release_interface;
|
||||
device_initialize (&intf->dev);
|
||||
mark_quiesced(intf);
|
||||
sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
|
||||
|
@ -197,6 +197,11 @@ static void usb_release_dev(struct device *dev)
|
||||
kfree(udev);
|
||||
}
|
||||
|
||||
struct device_type usb_device_type = {
|
||||
.name = "usb_device",
|
||||
.release = usb_release_dev,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int ksuspend_usb_init(void)
|
||||
@ -247,13 +252,10 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
|
||||
|
||||
device_initialize(&dev->dev);
|
||||
dev->dev.bus = &usb_bus_type;
|
||||
dev->dev.type = &usb_device_type;
|
||||
dev->dev.dma_mask = bus->controller->dma_mask;
|
||||
dev->dev.release = usb_release_dev;
|
||||
dev->state = USB_STATE_ATTACHED;
|
||||
|
||||
/* This magic assignment distinguishes devices from interfaces */
|
||||
dev->dev.platform_data = &usb_generic_driver;
|
||||
|
||||
INIT_LIST_HEAD(&dev->ep0.urb_list);
|
||||
dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
|
||||
dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
|
||||
@ -882,9 +884,9 @@ static int __init usb_init(void)
|
||||
retval = usb_register(&usbfs_driver);
|
||||
if (retval)
|
||||
goto driver_register_failed;
|
||||
retval = usbdev_init();
|
||||
retval = usb_devio_init();
|
||||
if (retval)
|
||||
goto usbdevice_init_failed;
|
||||
goto usb_devio_init_failed;
|
||||
retval = usbfs_init();
|
||||
if (retval)
|
||||
goto fs_init_failed;
|
||||
@ -899,8 +901,8 @@ static int __init usb_init(void)
|
||||
hub_init_failed:
|
||||
usbfs_cleanup();
|
||||
fs_init_failed:
|
||||
usbdev_cleanup();
|
||||
usbdevice_init_failed:
|
||||
usb_devio_cleanup();
|
||||
usb_devio_init_failed:
|
||||
usb_deregister(&usbfs_driver);
|
||||
driver_register_failed:
|
||||
usb_major_cleanup();
|
||||
@ -927,7 +929,7 @@ static void __exit usb_exit(void)
|
||||
usb_major_cleanup();
|
||||
usbfs_cleanup();
|
||||
usb_deregister(&usbfs_driver);
|
||||
usbdev_cleanup();
|
||||
usb_devio_cleanup();
|
||||
usb_hub_cleanup();
|
||||
usb_host_cleanup();
|
||||
bus_unregister(&usb_bus_type);
|
||||
|
@ -78,15 +78,13 @@ static inline int usb_autoresume_device(struct usb_device *udev)
|
||||
|
||||
extern struct workqueue_struct *ksuspend_usb_wq;
|
||||
extern struct bus_type usb_bus_type;
|
||||
extern struct device_type usb_device_type;
|
||||
extern struct device_type usb_if_device_type;
|
||||
extern struct usb_device_driver usb_generic_driver;
|
||||
|
||||
/* Here's how we tell apart devices and interfaces. Luckily there's
|
||||
* no such thing as a platform USB device, so we can steal the use
|
||||
* of the platform_data field. */
|
||||
|
||||
static inline int is_usb_device(const struct device *dev)
|
||||
{
|
||||
return dev->platform_data == &usb_generic_driver;
|
||||
return dev->type == &usb_device_type;
|
||||
}
|
||||
|
||||
/* Do the same for device drivers and interface drivers. */
|
||||
@ -122,11 +120,11 @@ extern const char *usbcore_name;
|
||||
extern struct mutex usbfs_mutex;
|
||||
extern struct usb_driver usbfs_driver;
|
||||
extern const struct file_operations usbfs_devices_fops;
|
||||
extern const struct file_operations usbfs_device_file_operations;
|
||||
extern const struct file_operations usbdev_file_operations;
|
||||
extern void usbfs_conn_disc_event(void);
|
||||
|
||||
extern int usbdev_init(void);
|
||||
extern void usbdev_cleanup(void);
|
||||
extern int usb_devio_init(void);
|
||||
extern void usb_devio_cleanup(void);
|
||||
|
||||
struct dev_state {
|
||||
struct list_head list; /* state list */
|
||||
|
@ -299,8 +299,9 @@ struct usb_bus {
|
||||
int bandwidth_int_reqs; /* number of Interrupt requests */
|
||||
int bandwidth_isoc_reqs; /* number of Isoc. requests */
|
||||
|
||||
#ifdef CONFIG_USB_DEVICEFS
|
||||
struct dentry *usbfs_dentry; /* usbfs dentry entry for the bus */
|
||||
|
||||
#endif
|
||||
struct class_device *class_dev; /* class device for this bus */
|
||||
|
||||
#if defined(CONFIG_USB_MON)
|
||||
@ -373,9 +374,12 @@ struct usb_device {
|
||||
char *serial; /* iSerialNumber string, if present */
|
||||
|
||||
struct list_head filelist;
|
||||
struct device *usbfs_dev;
|
||||
#ifdef CONFIG_USB_DEVICE_CLASS
|
||||
struct device *usb_classdev;
|
||||
#endif
|
||||
#ifdef CONFIG_USB_DEVICEFS
|
||||
struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */
|
||||
|
||||
#endif
|
||||
/*
|
||||
* Child devices - these can be either new devices
|
||||
* (if this is a hub device), or different instances
|
||||
|
Loading…
Reference in New Issue
Block a user