2005-04-16 22:20:36 +00:00
|
|
|
/* Functions local to drivers/usb/core/ */
|
|
|
|
|
2006-08-28 18:43:25 +00:00
|
|
|
extern int usb_create_sysfs_dev_files (struct usb_device *dev);
|
2005-04-16 22:20:36 +00:00
|
|
|
extern void usb_remove_sysfs_dev_files (struct usb_device *dev);
|
2006-08-28 18:43:25 +00:00
|
|
|
extern int usb_create_sysfs_intf_files (struct usb_interface *intf);
|
2005-04-16 22:20:36 +00:00
|
|
|
extern void usb_remove_sysfs_intf_files (struct usb_interface *intf);
|
2006-08-28 18:43:25 +00:00
|
|
|
extern int usb_create_ep_files(struct device *parent, struct usb_host_endpoint *endpoint,
|
2006-06-14 19:14:34 +00:00
|
|
|
struct usb_device *udev);
|
|
|
|
extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr);
|
|
|
|
extern void usb_disable_interface (struct usb_device *dev,
|
|
|
|
struct usb_interface *intf);
|
|
|
|
extern void usb_release_interface_cache(struct kref *ref);
|
|
|
|
extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
|
2007-01-26 13:26:21 +00:00
|
|
|
extern void usb_detect_quirks(struct usb_device *udev);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
extern int usb_get_device_descriptor(struct usb_device *dev,
|
|
|
|
unsigned int size);
|
2005-10-24 20:24:14 +00:00
|
|
|
extern char *usb_cache_string(struct usb_device *udev, int index);
|
2005-04-16 22:20:36 +00:00
|
|
|
extern int usb_set_configuration(struct usb_device *dev, int configuration);
|
|
|
|
|
|
|
|
extern void usb_kick_khubd(struct usb_device *dev);
|
2007-01-26 13:26:21 +00:00
|
|
|
extern int usb_match_device(struct usb_device *dev,
|
|
|
|
const struct usb_device_id *id);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2005-04-19 00:39:24 +00:00
|
|
|
extern int usb_hub_init(void);
|
|
|
|
extern void usb_hub_cleanup(void);
|
|
|
|
extern int usb_major_init(void);
|
|
|
|
extern void usb_major_cleanup(void);
|
|
|
|
extern int usb_host_init(void);
|
|
|
|
extern void usb_host_cleanup(void);
|
|
|
|
|
2006-07-02 02:14:24 +00:00
|
|
|
#ifdef CONFIG_PM
|
|
|
|
|
2007-03-09 20:41:13 +00:00
|
|
|
extern void usb_autosuspend_work(struct work_struct *work);
|
2006-07-02 02:07:21 +00:00
|
|
|
extern int usb_port_suspend(struct usb_device *dev);
|
|
|
|
extern int usb_port_resume(struct usb_device *dev);
|
2007-03-13 20:37:30 +00:00
|
|
|
extern int usb_external_suspend_device(struct usb_device *udev,
|
|
|
|
pm_message_t msg);
|
|
|
|
extern int usb_external_resume_device(struct usb_device *udev);
|
2005-09-23 05:45:26 +00:00
|
|
|
|
2006-09-26 18:50:20 +00:00
|
|
|
static inline void usb_pm_lock(struct usb_device *udev)
|
|
|
|
{
|
|
|
|
mutex_lock_nested(&udev->pm_mutex, udev->level);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void usb_pm_unlock(struct usb_device *udev)
|
|
|
|
{
|
|
|
|
mutex_unlock(&udev->pm_mutex);
|
|
|
|
}
|
|
|
|
|
2006-07-02 02:14:24 +00:00
|
|
|
#else
|
|
|
|
|
2007-05-30 20:51:28 +00:00
|
|
|
static inline int usb_port_suspend(struct usb_device *udev)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int usb_port_resume(struct usb_device *udev)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-09-26 18:50:20 +00:00
|
|
|
static inline void usb_pm_lock(struct usb_device *udev) {}
|
|
|
|
static inline void usb_pm_unlock(struct usb_device *udev) {}
|
2006-07-02 02:14:24 +00:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2006-08-30 19:47:02 +00:00
|
|
|
#ifdef CONFIG_USB_SUSPEND
|
|
|
|
|
2006-11-20 16:38:46 +00:00
|
|
|
extern void usb_autosuspend_device(struct usb_device *udev);
|
2007-02-20 20:03:32 +00:00
|
|
|
extern void usb_try_autosuspend_device(struct usb_device *udev);
|
2006-11-20 16:38:46 +00:00
|
|
|
extern int usb_autoresume_device(struct usb_device *udev);
|
2006-08-30 19:47:02 +00:00
|
|
|
|
|
|
|
#else
|
|
|
|
|
2007-02-20 20:03:32 +00:00
|
|
|
#define usb_autosuspend_device(udev) do {} while (0)
|
|
|
|
#define usb_try_autosuspend_device(udev) do {} while (0)
|
2006-11-20 16:38:46 +00:00
|
|
|
static inline int usb_autoresume_device(struct usb_device *udev)
|
2006-09-26 18:50:20 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2006-08-30 19:47:02 +00:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2006-09-19 14:14:07 +00:00
|
|
|
extern struct workqueue_struct *ksuspend_usb_wq;
|
2006-07-02 02:08:06 +00:00
|
|
|
extern struct bus_type usb_bus_type;
|
2007-03-13 14:59:31 +00:00
|
|
|
extern struct device_type usb_device_type;
|
|
|
|
extern struct device_type usb_if_device_type;
|
2006-07-02 02:08:49 +00:00
|
|
|
extern struct usb_device_driver usb_generic_driver;
|
|
|
|
|
2006-08-27 02:48:11 +00:00
|
|
|
static inline int is_usb_device(const struct device *dev)
|
2006-07-02 02:08:49 +00:00
|
|
|
{
|
2007-03-13 14:59:31 +00:00
|
|
|
return dev->type == &usb_device_type;
|
2006-07-02 02:08:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Do the same for device drivers and interface drivers. */
|
|
|
|
|
|
|
|
static inline int is_usb_device_driver(struct device_driver *drv)
|
|
|
|
{
|
|
|
|
return container_of(drv, struct usbdrv_wrap, driver)->
|
|
|
|
for_devices;
|
|
|
|
}
|
2005-09-23 05:45:26 +00:00
|
|
|
|
2005-09-14 02:56:33 +00:00
|
|
|
/* Interfaces and their "power state" are owned by usbcore */
|
|
|
|
|
|
|
|
static inline void mark_active(struct usb_interface *f)
|
|
|
|
{
|
2006-07-02 02:11:44 +00:00
|
|
|
f->is_active = 1;
|
2007-05-04 15:49:57 +00:00
|
|
|
f->dev.power.power_state.event = PM_EVENT_ON;
|
2005-09-14 02:56:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void mark_quiesced(struct usb_interface *f)
|
|
|
|
{
|
2006-07-02 02:11:44 +00:00
|
|
|
f->is_active = 0;
|
2007-05-04 15:49:57 +00:00
|
|
|
f->dev.power.power_state.event = PM_EVENT_SUSPEND;
|
2005-09-14 02:56:33 +00:00
|
|
|
}
|
|
|
|
|
2006-08-27 02:48:11 +00:00
|
|
|
static inline int is_active(const struct usb_interface *f)
|
2005-09-14 02:56:33 +00:00
|
|
|
{
|
2006-07-02 02:11:44 +00:00
|
|
|
return f->is_active;
|
2005-09-14 02:56:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* for labeling diagnostics */
|
|
|
|
extern const char *usbcore_name;
|
|
|
|
|
|
|
|
/* usbfs stuff */
|
usbfs: private mutex for open, release, and remove
The usbfs code doesn't provide sufficient mutual exclusion among open,
release, and remove. Release vs. remove is okay because they both
acquire the device lock, but open is not exclusive with either one. All
three routines modify the udev->filelist linked list, so they must not
run concurrently.
Apparently someone gave this a minimum amount of thought in the past by
explicitly acquiring the BKL at the start of the usbdev_open routine.
Oddly enough, there's a comment pointing out that locking is unnecessary
because chrdev_open already has acquired the BKL.
But this ignores the point that the files in /proc/bus/usb/* are not
char device files; they are regular files and so they don't get any
special locking. Furthermore it's necessary to acquire the same lock in
the release and remove routines, which the code does not do.
Yet another problem arises because the same file_operations structure is
accessible through both the /proc/bus/usb/* and /dev/usb/usbdev* file
nodes. Even when one of them has been removed, it's still possible for
userspace to open the other. So simple locking around the individual
remove routines is insufficient; we need to lock the entire
usb_notify_remove_device notifier chain.
Rather than rely on the BKL, this patch (as723) introduces a new private
mutex for the purpose. Holding the BKL while invoking a notifier chain
doesn't seem like a good idea.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2006-07-02 02:05:01 +00:00
|
|
|
extern struct mutex usbfs_mutex;
|
2005-04-16 22:20:36 +00:00
|
|
|
extern struct usb_driver usbfs_driver;
|
2006-08-05 23:37:11 +00:00
|
|
|
extern const struct file_operations usbfs_devices_fops;
|
2007-03-13 14:59:31 +00:00
|
|
|
extern const struct file_operations usbdev_file_operations;
|
2005-04-16 22:20:36 +00:00
|
|
|
extern void usbfs_conn_disc_event(void);
|
|
|
|
|
2007-03-13 14:59:31 +00:00
|
|
|
extern int usb_devio_init(void);
|
|
|
|
extern void usb_devio_cleanup(void);
|
2005-04-19 00:39:24 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
struct dev_state {
|
|
|
|
struct list_head list; /* state list */
|
|
|
|
struct usb_device *dev;
|
|
|
|
struct file *file;
|
|
|
|
spinlock_t lock; /* protects the async urb lists */
|
|
|
|
struct list_head async_pending;
|
|
|
|
struct list_head async_completed;
|
|
|
|
wait_queue_head_t wait; /* wake up if a request completed */
|
|
|
|
unsigned int discsignr;
|
2006-10-02 09:17:28 +00:00
|
|
|
struct pid *disc_pid;
|
2005-10-10 23:31:30 +00:00
|
|
|
uid_t disc_uid, disc_euid;
|
2005-04-16 22:20:36 +00:00
|
|
|
void __user *disccontext;
|
|
|
|
unsigned long ifclaimed;
|
2006-06-30 08:55:48 +00:00
|
|
|
u32 secid;
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
2005-06-21 04:15:16 +00:00
|
|
|
/* internal notify stuff */
|
|
|
|
extern void usb_notify_add_device(struct usb_device *udev);
|
|
|
|
extern void usb_notify_remove_device(struct usb_device *udev);
|
|
|
|
extern void usb_notify_add_bus(struct usb_bus *ubus);
|
|
|
|
extern void usb_notify_remove_bus(struct usb_bus *ubus);
|
|
|
|
|