Commit 92320cec authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6:
  USB: export autosuspend delay in sysfs
  sysfs: allow attributes to be added to groups
  USB: make autosuspend delay a module parameter
  USB: minor cleanups for sysfs.c
  USB: add a blacklist for devices that can't handle some things we throw at them.
  USB: refactor usb device matching and create usb_device_match
  USB: Wacom driver updates
  gadgetfs: Fixed bug in ep_aio_read_retry.
  USB: Use USB defines in usbmouse.c and usbkbd.c
  USB: add rationale on why usb descriptor structures have to be packed
  USB: ftdi_sio: Adding VID and PID for Tellstick
  UHCI: Eliminate asynchronous skeleton Queue Headers
  UHCI: Add macros for computing DMA values
  USB: Davicom DM9601 usbnet driver
  USB: asix.c - Add JVC-PRX1 ids
  usbmon: Remove erroneous __exit
  USB: add driver for iowarrior devices.
  USB: option: add a bunch of new device ids
  USB: option: remove duplicate device id table
parents 63ae0e5b 19c26239
...@@ -1758,6 +1758,13 @@ and is between 256 and 4096 characters. It is defined in the file ...@@ -1758,6 +1758,13 @@ and is between 256 and 4096 characters. It is defined in the file
Note that genuine overcurrent events won't be Note that genuine overcurrent events won't be
reported either. reported either.
usbcore.autosuspend=
[USB] The autosuspend time delay (in seconds) used
for newly-detected USB devices (default 2). This
is the time required before an idle device will be
autosuspended. Devices for which the delay is set
to 0 won't be autosuspended at all.
usbhid.mousepoll= usbhid.mousepoll=
[USBHID] The interval which mice are to be polled at. [USBHID] The interval which mice are to be polled at.
......
...@@ -3392,6 +3392,13 @@ L: linux-usb-devel@lists.sourceforge.net ...@@ -3392,6 +3392,13 @@ L: linux-usb-devel@lists.sourceforge.net
S: Maintained S: Maintained
W: http://www.kroah.com/linux-usb/ W: http://www.kroah.com/linux-usb/
USB DAVICOM DM9601 DRIVER
P: Peter Korsgaard
M: jacmet@sunsite.dk
L: linux-usb-devel@lists.sourceforge.net
W: http://www.linux-usb.org/usbnet
S: Maintained
USB EHCI DRIVER USB EHCI DRIVER
P: David Brownell P: David Brownell
M: dbrownell@users.sourceforge.net M: dbrownell@users.sourceforge.net
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \ usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \
config.o file.o buffer.o sysfs.o endpoint.o \ config.o file.o buffer.o sysfs.o endpoint.o \
devio.o notify.o generic.o devio.o notify.o generic.o quirks.o
ifeq ($(CONFIG_PCI),y) ifeq ($(CONFIG_PCI),y)
usbcore-objs += hcd-pci.o usbcore-objs += hcd-pci.o
......
...@@ -366,19 +366,8 @@ void usb_driver_release_interface(struct usb_driver *driver, ...@@ -366,19 +366,8 @@ void usb_driver_release_interface(struct usb_driver *driver,
EXPORT_SYMBOL(usb_driver_release_interface); EXPORT_SYMBOL(usb_driver_release_interface);
/* returns 0 if no match, 1 if match */ /* returns 0 if no match, 1 if match */
int usb_match_one_id(struct usb_interface *interface, int usb_match_device(struct usb_device *dev, const struct usb_device_id *id)
const struct usb_device_id *id)
{ {
struct usb_host_interface *intf;
struct usb_device *dev;
/* proc_connectinfo in devio.c may call us with id == NULL. */
if (id == NULL)
return 0;
intf = interface->cur_altsetting;
dev = interface_to_usbdev(interface);
if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
id->idVendor != le16_to_cpu(dev->descriptor.idVendor)) id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
return 0; return 0;
...@@ -409,6 +398,26 @@ int usb_match_one_id(struct usb_interface *interface, ...@@ -409,6 +398,26 @@ int usb_match_one_id(struct usb_interface *interface,
(id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
return 0; return 0;
return 1;
}
/* returns 0 if no match, 1 if match */
int usb_match_one_id(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct usb_host_interface *intf;
struct usb_device *dev;
/* proc_connectinfo in devio.c may call us with id == NULL. */
if (id == NULL)
return 0;
intf = interface->cur_altsetting;
dev = interface_to_usbdev(interface);
if (!usb_match_device(dev, id))
return 0;
/* The interface class, subclass, and protocol should never be /* The interface class, subclass, and protocol should never be
* checked for a match if the device class is Vendor Specific, * checked for a match if the device class is Vendor Specific,
* unless the match record specifies the Vendor ID. */ * unless the match record specifies the Vendor ID. */
...@@ -954,12 +963,16 @@ static int autosuspend_check(struct usb_device *udev) ...@@ -954,12 +963,16 @@ static int autosuspend_check(struct usb_device *udev)
int i; int i;
struct usb_interface *intf; struct usb_interface *intf;
/* For autosuspend, fail fast if anything is in use. /* For autosuspend, fail fast if anything is in use or autosuspend
* Also fail if any interfaces require remote wakeup but it * is disabled. Also fail if any interfaces require remote wakeup
* isn't available. */ * but it isn't available.
*/
udev->do_remote_wakeup = device_may_wakeup(&udev->dev); udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
if (udev->pm_usage_cnt > 0) if (udev->pm_usage_cnt > 0)
return -EBUSY; return -EBUSY;
if (!udev->autosuspend_delay)
return -EPERM;
if (udev->actconfig) { if (udev->actconfig) {
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i]; intf = udev->actconfig->interface[i];
...@@ -982,7 +995,7 @@ static int autosuspend_check(struct usb_device *udev) ...@@ -982,7 +995,7 @@ static int autosuspend_check(struct usb_device *udev)
#define autosuspend_check(udev) 0 #define autosuspend_check(udev) 0
#endif #endif /* CONFIG_USB_SUSPEND */
/** /**
* usb_suspend_both - suspend a USB device and its interfaces * usb_suspend_both - suspend a USB device and its interfaces
...@@ -1177,7 +1190,7 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt) ...@@ -1177,7 +1190,7 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
udev->pm_usage_cnt -= inc_usage_cnt; udev->pm_usage_cnt -= inc_usage_cnt;
} else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0) } else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
USB_AUTOSUSPEND_DELAY); udev->autosuspend_delay);
usb_pm_unlock(udev); usb_pm_unlock(udev);
return status; return status;
} }
...@@ -1211,6 +1224,26 @@ void usb_autosuspend_device(struct usb_device *udev) ...@@ -1211,6 +1224,26 @@ void usb_autosuspend_device(struct usb_device *udev)
// __FUNCTION__, udev->pm_usage_cnt); // __FUNCTION__, udev->pm_usage_cnt);
} }
/**
* usb_try_autosuspend_device - attempt an autosuspend of a USB device and its interfaces
* @udev: the usb_device to autosuspend
*
* This routine should be called when a core subsystem thinks @udev may
* be ready to autosuspend.
*
* @udev's usage counter left unchanged. If it or any of the usage counters
* for an active interface is greater than 0, or autosuspend is not allowed
* for any other reason, no autosuspend request will be queued.
*
* This routine can run only in process context.
*/
void usb_try_autosuspend_device(struct usb_device *udev)
{
usb_autopm_do_device(udev, 0);
// dev_dbg(&udev->dev, "%s: cnt %d\n",
// __FUNCTION__, udev->pm_usage_cnt);
}
/** /**
* usb_autoresume_device - immediately autoresume a USB device and its interfaces * usb_autoresume_device - immediately autoresume a USB device and its interfaces
* @udev: the usb_device to autoresume * @udev: the usb_device to autoresume
...@@ -1261,7 +1294,7 @@ static int usb_autopm_do_interface(struct usb_interface *intf, ...@@ -1261,7 +1294,7 @@ static int usb_autopm_do_interface(struct usb_interface *intf,
intf->pm_usage_cnt -= inc_usage_cnt; intf->pm_usage_cnt -= inc_usage_cnt;
} else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0) } else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
USB_AUTOSUSPEND_DELAY); udev->autosuspend_delay);
} }
usb_pm_unlock(udev); usb_pm_unlock(udev);
return status; return status;
......
...@@ -1287,6 +1287,9 @@ int usb_new_device(struct usb_device *udev) ...@@ -1287,6 +1287,9 @@ int usb_new_device(struct usb_device *udev)
if (!try_module_get(THIS_MODULE)) if (!try_module_get(THIS_MODULE))
return -EINVAL; return -EINVAL;
/* Determine quirks */
usb_detect_quirks(udev);
err = usb_get_configuration(udev); err = usb_get_configuration(udev);
if (err < 0) { if (err < 0) {
dev_err(&udev->dev, "can't read configurations, error %d\n", dev_err(&udev->dev, "can't read configurations, error %d\n",
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/usb/quirks.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/scatterlist.h> #include <asm/scatterlist.h>
...@@ -685,6 +686,9 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid, ...@@ -685,6 +686,9 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid,
/* Try to read the string descriptor by asking for the maximum /* Try to read the string descriptor by asking for the maximum
* possible number of bytes */ * possible number of bytes */
if (dev->quirks & USB_QUIRK_STRING_FETCH_255)
rc = -EIO;
else
rc = usb_get_string(dev, langid, index, buf, 255); rc = usb_get_string(dev, langid, index, buf, 255);
/* If that failed try to read the descriptor length, then /* If that failed try to read the descriptor length, then
......
/*
* USB device quirk handling logic and table
*
* Copyright (c) 2007 Oliver Neukum
* Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
*
*/
#include <linux/usb.h>
#include <linux/usb/quirks.h>
#include "usb.h"
/* List of quirky USB devices. Please keep this list ordered by:
* 1) Vendor ID
* 2) Product ID
* 3) Class ID
*
* as we want specific devices to be overridden first, and only after that, any
* class specific quirks.
*
* Right now the logic aborts if it finds a valid device in the table, we might
* want to change that in the future if it turns out that a whole class of
* devices is broken...
*/
static const struct usb_device_id usb_quirk_list[] = {
/* HP 5300/5370C scanner */
{ USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 },
/* Elsa MicroLink 56k (V.250) */
{ USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
{ } /* terminating entry must be last */
};
static void usb_autosuspend_quirk(struct usb_device *udev)
{
#ifdef CONFIG_USB_SUSPEND
/* disable autosuspend, but allow the user to re-enable it via sysfs */
udev->autosuspend_delay = 0;
#endif
}
static const struct usb_device_id *find_id(struct usb_device *udev)
{
const struct usb_device_id *id = usb_quirk_list;
for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
id->driver_info; id++) {
if (usb_match_device(udev, id))
return id;
}
return NULL;
}
/*
* Detect any quirks the device has, and do any housekeeping for it if needed.
*/
void usb_detect_quirks(struct usb_device *udev)
{
const struct usb_device_id *id = usb_quirk_list;
id = find_id(udev);
if (id)
udev->quirks = (u32)(id->driver_info);
if (udev->quirks)
dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
udev->quirks);
/* do any special quirk handling here if needed */
if (udev->quirks & USB_QUIRK_NO_AUTOSUSPEND)
usb_autosuspend_quirk(udev);
}
...@@ -148,6 +148,75 @@ show_maxchild(struct device *dev, struct device_attribute *attr, char *buf) ...@@ -148,6 +148,75 @@ show_maxchild(struct device *dev, struct device_attribute *attr, char *buf)
} }
static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL); static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL);
static ssize_t
show_quirks(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_device *udev;
udev = to_usb_device(dev);
return sprintf(buf, "0x%x\n", udev->quirks);
}
static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL);
#ifdef CONFIG_USB_SUSPEND
static ssize_t
show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_device *udev = to_usb_device(dev);
return sprintf(buf, "%u\n", udev->autosuspend_delay / HZ);
}
static ssize_t
set_autosuspend(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct usb_device *udev = to_usb_device(dev);
unsigned value, old;
if (sscanf(buf, "%u", &value) != 1 || value >= INT_MAX/HZ)
return -EINVAL;
value *= HZ;
old = udev->autosuspend_delay;
udev->autosuspend_delay = value;
if (value > 0 && old == 0)
usb_try_autosuspend_device(udev);
return count;
}
static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR,
show_autosuspend, set_autosuspend);
static char power_group[] = "power";
static int add_power_attributes(struct device *dev)
{
int rc = 0;
if (is_usb_device(dev))
rc = sysfs_add_file_to_group(&dev->kobj,
&dev_attr_autosuspend.attr,
power_group);
return rc;
}
static void remove_power_attributes(struct device *dev)
{
sysfs_remove_file_from_group(&dev->kobj,
&dev_attr_autosuspend.attr,
power_group);
}
#else
#define add_power_attributes(dev) 0
#define remove_power_attributes(dev) do {} while (0)
#endif /* CONFIG_USB_SUSPEND */
/* Descriptor fields */ /* Descriptor fields */
#define usb_descriptor_attr_le16(field, format_string) \ #define usb_descriptor_attr_le16(field, format_string) \
static ssize_t \ static ssize_t \
...@@ -204,6 +273,7 @@ static struct attribute *dev_attrs[] = { ...@@ -204,6 +273,7 @@ static struct attribute *dev_attrs[] = {
&dev_attr_devnum.attr, &dev_attr_devnum.attr,
&dev_attr_version.attr, &dev_attr_version.attr,
&dev_attr_maxchild.attr, &dev_attr_maxchild.attr,
&dev_attr_quirks.attr,
NULL, NULL,
}; };
static struct attribute_group dev_attr_grp = { static struct attribute_group dev_attr_grp = {
...@@ -219,6 +289,10 @@ int usb_create_sysfs_dev_files(struct usb_device *udev) ...@@ -219,6 +289,10 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
if (retval) if (retval)
return retval; return retval;
retval = add_power_attributes(dev);
if (retval)
goto error;
if (udev->manufacturer) { if (udev->manufacturer) {
retval = device_create_file(dev, &dev_attr_manufacturer); retval = device_create_file(dev, &dev_attr_manufacturer);
if (retval) if (retval)
...@@ -239,10 +313,7 @@ int usb_create_sysfs_dev_files(struct usb_device *udev) ...@@ -239,10 +313,7 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
goto error; goto error;
return 0; return 0;
error: error:
usb_remove_ep_files(&udev->ep0); usb_remove_sysfs_dev_files(udev);
device_remove_file(dev, &dev_attr_manufacturer);
device_remove_file(dev, &dev_attr_product);
device_remove_file(dev, &dev_attr_serial);
return retval; return retval;
} }
...@@ -251,14 +322,11 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev) ...@@ -251,14 +322,11 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
struct device *dev = &udev->dev; struct device *dev = &udev->dev;
usb_remove_ep_files(&udev->ep0); usb_remove_ep_files(&udev->ep0);
sysfs_remove_group(&dev->kobj, &dev_attr_grp);
if (udev->manufacturer)
device_remove_file(dev, &dev_attr_manufacturer); device_remove_file(dev, &dev_attr_manufacturer);
if (udev->product)
device_remove_file(dev, &dev_attr_product); device_remove_file(dev, &dev_attr_product);
if (udev->serial)
device_remove_file(dev, &dev_attr_serial); device_remove_file(dev, &dev_attr_serial);
remove_power_attributes(dev);
sysfs_remove_group(&dev->kobj, &dev_attr_grp);
} }
/* Interface fields */ /* Interface fields */
...@@ -362,33 +430,28 @@ static inline void usb_remove_intf_ep_files(struct usb_interface *intf) ...@@ -362,33 +430,28 @@ static inline void usb_remove_intf_ep_files(struct usb_interface *intf)
int usb_create_sysfs_intf_files(struct usb_interface *intf) int usb_create_sysfs_intf_files(struct usb_interface *intf)
{ {
struct device *dev = &intf->dev;
struct usb_device *udev = interface_to_usbdev(intf); struct usb_device *udev = interface_to_usbdev(intf);
struct usb_host_interface *alt = intf->cur_altsetting; struct usb_host_interface *alt = intf->cur_altsetting;
int retval; int retval;
retval = sysfs_create_group(&intf->dev.kobj, &intf_attr_grp); retval = sysfs_create_group(&dev->kobj, &intf_attr_grp);
if (retval) if (retval)
goto error; return retval;
if (alt->string == NULL) if (alt->string == NULL)
alt->string = usb_cache_string(udev, alt->desc.iInterface); alt->string = usb_cache_string(udev, alt->desc.iInterface);
if (alt->string) if (alt->string)
retval = device_create_file(&intf->dev, &dev_attr_interface); retval = device_create_file(dev, &dev_attr_interface);
usb_create_intf_ep_files(intf, udev); usb_create_intf_ep_files(intf, udev);
return 0; return 0;
error:
if (alt->string)
device_remove_file(&intf->dev, &dev_attr_interface);
sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
usb_remove_intf_ep_files(intf);
return retval;
} }
void usb_remove_sysfs_intf_files(struct usb_interface *intf) void usb_remove_sysfs_intf_files(struct usb_interface *intf)
{ {
usb_remove_intf_ep_files(intf); struct device *dev = &intf->dev;
sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
if (intf->cur_altsetting->string) usb_remove_intf_ep_files(intf);
device_remove_file(&intf->dev, &dev_attr_interface); device_remove_file(dev, &dev_attr_interface);
sysfs_remove_group(&dev->kobj, &intf_attr_grp);
} }
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -50,6 +51,16 @@ static int nousb; /* Disable USB when built into kernel image */ ...@@ -50,6 +51,16 @@ static int nousb; /* Disable USB when built into kernel image */
struct workqueue_struct *ksuspend_usb_wq; /* For autosuspend */ struct workqueue_struct *ksuspend_usb_wq; /* For autosuspend */
#ifdef CONFIG_USB_SUSPEND
static int usb_autosuspend_delay = 2; /* Default delay value,
* in seconds */
module_param_named(autosuspend, usb_autosuspend_delay, uint, 0644);
MODULE_PARM_DESC(autosuspend, "default autosuspend delay");
#else
#define usb_autosuspend_delay 0
#endif
/** /**
* usb_ifnum_to_if - get the interface object with a given interface number * usb_ifnum_to_if - get the interface object with a given interface number
...@@ -306,6 +317,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) ...@@ -306,6 +317,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
#ifdef CONFIG_PM #ifdef CONFIG_PM
mutex_init(&dev->pm_mutex); mutex_init(&dev->pm_mutex);
INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work); INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
dev->autosuspend_delay = usb_autosuspend_delay * HZ;
#endif #endif
return dev; return dev;
} }
......
...@@ -13,6 +13,7 @@ extern void usb_disable_interface (struct usb_device *dev, ...@@ -13,6 +13,7 @@ extern void usb_disable_interface (struct usb_device *dev,
struct usb_interface *intf); struct usb_interface *intf);
extern void usb_release_interface_cache(struct kref *ref); extern void usb_release_interface_cache(struct kref *ref);
extern void usb_disable_device (struct usb_device *dev, int skip_ep0); extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
extern void usb_detect_quirks(struct usb_device *udev);
extern int usb_get_device_descriptor(struct usb_device *dev, extern int usb_get_device_descriptor(struct usb_device *dev,
unsigned int size); unsigned int size);
...@@ -21,6 +22,8 @@ extern int usb_set_configuration(struct usb_device *dev, int configuration); ...@@ -21,6 +22,8 @@ extern int usb_set_configuration(struct usb_device *dev, int configuration);
extern void usb_kick_khubd(struct usb_device *dev); extern void usb_kick_khubd(struct usb_device *dev);
extern void usb_resume_root_hub(struct usb_device *dev); extern void usb_resume_root_hub(struct usb_device *dev);
extern int usb_match_device(struct usb_device *dev,
const struct usb_device_id *id);
extern int usb_hub_init(void); extern int usb_hub_init(void);
extern void usb_hub_cleanup(void); extern void usb_hub_cleanup(void);
...@@ -62,14 +65,14 @@ static inline void usb_pm_unlock(struct usb_device *udev) {} ...@@ -62,14 +65,14 @@ static inline void usb_pm_unlock(struct usb_device *udev) {}
#ifdef CONFIG_USB_SUSPEND #ifdef CONFIG_USB_SUSPEND
#define USB_AUTOSUSPEND_DELAY (HZ*2)
extern void usb_autosuspend_device(struct usb_device *udev); extern void usb_autosuspend_device(struct usb_device *udev);
extern void usb_try_autosuspend_device(struct usb_device *udev);
extern int usb_autoresume_device(struct usb_device *udev); extern int usb_autoresume_device(struct usb_device *udev);
#else #else
#define usb_autosuspend_device(udev) do {} while (0) #define usb_autosuspend_device(udev) do {} while (0)
#define usb_try_autosuspend_device(udev) do {} while (0)
static inline int usb_autoresume_device(struct usb_device *udev) static inline int usb_autoresume_device(struct usb_device *udev)
{ {
return 0; return 0;
......
...@@ -553,6 +553,7 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb) ...@@ -553,6 +553,7 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb)
{ {
struct kiocb_priv *priv = iocb->private; struct kiocb_priv *priv = iocb->private;
ssize_t len, total; ssize_t len, total;
void *to_copy;
int i; int i;
/* we "retry" to get the right mm context for this: */ /* we "retry" to get the right mm context for this: */
...@@ -560,10 +561,11 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb) ...@@ -560,10 +561,11 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb)
/* copy stuff into user buffers */ /* copy stuff into user buffers */
total = priv->actual; total = priv->actual;
len = 0; len = 0;
to_copy = priv->buf;
for (i=0; i < priv->nr_segs; i++) { for (i=0; i < priv->nr_segs; i++) {
ssize_t this = min((ssize_t)(priv->iv[i].iov_len), total); ssize_t this = min((ssize_t)(priv->iv[i].iov_len), total);
if (copy_to_user(priv->iv[i].iov_base, priv->buf, this)) { if (copy_to_user(priv->iv[i].iov_base, to_copy, this)) {
if (len == 0) if (len == 0)
len = -EFAULT; len = -EFAULT;
break; break;
...@@ -571,6 +573,7 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb) ...@@ -571,6 +573,7 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb)
total -= this; total -= this;
len += this; len += this;
to_copy += this;
if (total == 0) if (total == 0)
break; break;
} }
......
...@@ -196,7 +196,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) ...@@ -196,7 +196,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
struct uhci_td *td = list_entry(urbp->td_list.next, struct uhci_td *td = list_entry(urbp->td_list.next,
struct uhci_td, list); struct uhci_td, list);
if (cpu_to_le32(td->dma_handle) != (element & ~UHCI_PTR_BITS)) if (element != LINK_TO_TD(td))
out += sprintf(out, "%*s Element != First TD\n", out += sprintf(out, "%*s Element != First TD\n",
space, ""); space, "");
i = nurbs = 0; i = nurbs = 0;
...@@ -220,16 +220,6 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) ...@@ -220,16 +220,6 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
return out - buf; return out - buf;
} }
static const char * const qh_names[] = {
"skel_unlink_qh", "skel_iso_qh",
"skel_int128_qh", "skel_int64_qh",
"skel_int32_qh", "skel_int16_qh",
"skel_int8_qh", "skel_int4_qh",
"skel_int2_qh", "skel_int1_qh",
"skel_ls_control_qh", "skel_fs_control_qh",
"skel_bulk_qh", "skel_term_qh"
};
static int uhci_show_sc(int port, unsigned short status, char *buf, int len) static int uhci_show_sc(int port, unsigned short status, char *buf, int len)
{ {
char *out = buf; char *out = buf;
...@@ -352,6 +342,12 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) ...@@ -352,6 +342,12 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
struct uhci_td *td; struct uhci_td *td;
struct list_head *tmp, *head; struct list_head *tmp, *head;
int nframes, nerrs; int nframes, nerrs;
__le32 link;
static const char * const qh_names[] = {
"unlink", "iso", "int128", "int64", "int32", "int16",
"int8", "int4", "int2", "async", "term"
};
out += uhci_show_root_hub_state(uhci, out, len - (out - buf)); out += uhci_show_root_hub_state(uhci, out, len - (out - buf));
out += sprintf(out, "HC status\n"); out += sprintf(out, "HC status\n");
...@@ -374,7 +370,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) ...@@ -374,7 +370,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
nframes = 10; nframes = 10;
nerrs = 0; nerrs = 0;
for (i = 0; i < UHCI_NUMFRAMES; ++i) { for (i = 0; i < UHCI_NUMFRAMES; ++i) {
__le32 link, qh_dma; __le32 qh_dma;
j = 0; j = 0;
td = uhci->frame_cpu[i]; td = uhci->frame_cpu[i];
...@@ -393,7 +389,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) ...@@ -393,7 +389,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
do { do {
td = list_entry(tmp, struct uhci_td, fl_list); td = list_entry(tmp, struct uhci_td, fl_list);
tmp = tmp->next; tmp = tmp->next;
if (cpu_to_le32(td->dma_handle) != link) { if (link != LINK_TO_TD(td)) {
if (nframes > 0) if (nframes > 0)
out += sprintf(out, " link does " out += sprintf(out, " link does "
"not match list entry!\n"); "not match list entry!\n");
...@@ -430,23 +426,21 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) ...@@ -430,23 +426,21 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
for (i = 0; i < UHCI_NUM_SKELQH; ++i) { for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
int cnt = 0; int cnt = 0;
__le32 fsbr_link = 0;
qh = uhci->skelqh[i]; qh = uhci->skelqh[i];
out += sprintf(out, "- %s\n", qh_names[i]); \ out += sprintf(out, "- skel_%s_qh\n", qh_names[i]); \
out += uhci_show_qh(qh, out, len - (out - buf), 4); out += uhci_show_qh(qh, out, len - (out - buf), 4);
/* Last QH is the Terminating QH, it's different */ /* Last QH is the Terminating QH, it's different */
if (i == UHCI_NUM_SKELQH - 1) { if (i == SKEL_TERM) {
if (qh->link != UHCI_PTR_TERM) if (qh_element(qh) != LINK_TO_TD(uhci->term_td))
out += sprintf(out, " bandwidth reclamation on!\n");
if (qh_element(qh) != cpu_to_le32(uhci->term_td->dma_handle))
out += sprintf(out, " skel_term_qh element is not set to term_td!\n"); out += sprintf(out, " skel_term_qh element is not set to term_td!\n");
if (link == LINK_TO_QH(uhci->skel_term_qh))
goto check_qh_link;
continue; continue;
} }
j = (i < 9) ? 9 : i+1; /* Next skeleton */
head = &qh->node; head = &qh->node;
tmp = head->next; tmp = head->next;
...@@ -456,16 +450,27 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) ...@@ -456,16 +450,27 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
if (++cnt <= 10) if (++cnt <= 10)
out += uhci_show_qh(qh, out, out += uhci_show_qh(qh, out,
len - (out - buf), 4); len - (out - buf), 4);
if (!fsbr_link && qh->skel >= SKEL_FSBR)
fsbr_link = LINK_TO_QH(qh);
} }
if ((cnt -= 10) > 0) if ((cnt -= 10) > 0)
out += sprintf(out, " Skipped %d QHs\n", cnt); out += sprintf(out, " Skipped %d QHs\n", cnt);
if (i > 1 && i < UHCI_NUM_SKELQH - 1) { link = UHCI_PTR_TERM;
if (qh->link != if (i <= SKEL_ISO)
(cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH)) ;
else if (i < SKEL_ASYNC)
link = LINK_TO_QH(uhci->skel_async_qh);
else if (!uhci->fsbr_is_on)
;
else if (fsbr_link)
link = fsbr_link;
else
link = LINK_TO_QH(uhci->skel_term_qh);
check_qh_link:
if (qh->link != link)
out += sprintf(out, " last QH not linked to next skeleton!\n"); out += sprintf(out, " last QH not linked to next skeleton!\n");
} }
}
return out - buf; return out - buf;
} }
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
* support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
* (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
* (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu
* *
* Intel documents this fairly well, and as far as I know there * Intel documents this fairly well, and as far as I know there
* are no royalties or anything like that, but even so there are * are no royalties or anything like that, but even so there are
...@@ -107,16 +107,16 @@ static __le32 uhci_frame_skel_link(struct uhci_hcd *uhci, int frame) ...@@ -107,16 +107,16 @@ static __le32 uhci_frame_skel_link(struct uhci_hcd *uhci, int frame)
* interrupt QHs, which will help spread out bandwidth utilization. * interrupt QHs, which will help spread out bandwidth utilization.
* *
* ffs (Find First bit Set) does exactly what we need: * ffs (Find First bit Set) does exactly what we need:
* 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[8], * 1,3,5,... => ffs = 0 => use period-2 QH = skelqh[8],
* 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc. * 2,6,10,... => ffs = 1 => use period-4 QH = skelqh[7], etc.
* ffs >= 7 => not on any high-period queue, so use * ffs >= 7 => not on any high-period queue, so use
* skel_int1_qh = skelqh[9]. * period-1 QH = skelqh[9].
* Add in UHCI_NUMFRAMES to insure at least one bit is set. * Add in UHCI_NUMFRAMES to insure at least one bit is set.
*/ */
skelnum = 8 - (int) __ffs(frame | UHCI_NUMFRAMES); skelnum = 8 - (int) __ffs(frame | UHCI_NUMFRAMES);
if (skelnum <= 1) if (skelnum <= 1)
skelnum = 9; skelnum = 9;
return UHCI_PTR_QH | cpu_to_le32(uhci->skelqh[skelnum]->dma_handle); return LINK_TO_QH(uhci->skelqh[skelnum]);
} }
#include "uhci-debug.c" #include "uhci-debug.c"
...@@ -540,16 +540,18 @@ static void uhci_shutdown(struct pci_dev *pdev) ...@@ -540,16 +540,18 @@ static void uhci_shutdown(struct pci_dev *pdev)
* *
* The hardware doesn't really know any difference * The hardware doesn't really know any difference
* in the queues, but the order does matter for the * in the queues, but the order does matter for the
* protocols higher up. The order is: * protocols higher up. The order in which the queues
* are encountered by the hardware is:
* *
* - any isochronous events handled before any * - All isochronous events are handled before any
* of the queues. We don't do that here, because * of the queues. We don't do that here, because
* we'll create the actual TD entries on demand. * we'll create the actual TD entries on demand.
* - The first queue is the interrupt queue. * - The first queue is the high-period interrupt queue.
* - The second queue is the control queue, split into low- and full-speed * - The second queue is the period-1 interrupt and async
* - The third queue is bulk queue. * (low-speed control, full-speed control, then bulk) queue.
* - The fourth queue is the bandwidth reclamation queue, which loops back * - The third queue is the terminating bandwidth reclamation queue,
* to the full-speed control queue. * which contains no members, loops back to itself, and is present
* only when FSBR is on and there are no full-speed control or bulk QHs.
*/ */
static int uhci_start(struct usb_hcd *hcd) static int uhci_start(struct usb_hcd *hcd)
{ {
...@@ -626,34 +628,18 @@ static int uhci_start(struct usb_hcd *hcd) ...@@ -626,34 +628,18 @@ static int uhci_start(struct usb_hcd *hcd)
} }
/* /*
* 8 Interrupt queues; link all higher int queues to int1, * 8 Interrupt queues; link all higher int queues to int1 = async
* then link int1 to control and control to bulk */
*/ for (i = SKEL_ISO + 1; i < SKEL_ASYNC; ++i)
uhci->skel_int128_qh->link = uhci->skelqh[i]->link = LINK_TO_QH(uhci->skel_async_qh);
uhci->skel_int64_qh->link = uhci->skel_async_qh->link = uhci->skel_term_qh->link = UHCI_PTR_TERM;
uhci->skel_int32_qh->link =
uhci->skel_int16_qh->link =
uhci->skel_int8_qh->link =
uhci->skel_int4_qh->link =
uhci->skel_int2_qh->link = UHCI_PTR_QH |
cpu_to_le32(uhci->skel_int1_qh->dma_handle);
uhci->skel_int1_qh->link = UHCI_PTR_QH |
cpu_to_le32(uhci->skel_ls_control_qh->dma_handle);
uhci->skel_ls_control_qh->link = UHCI_PTR_QH |
cpu_to_le32(uhci->skel_fs_control_qh->dma_handle);
uhci->skel_fs_control_qh->link = UHCI_PTR_QH |
cpu_to_le32(uhci->skel_bulk_qh->dma_handle);
uhci->skel_bulk_qh->link = UHCI_PTR_QH |
cpu_to_le32(uhci->skel_term_qh->dma_handle);
/* This dummy TD is to work around a bug in Intel PIIX controllers */ /* This dummy TD is to work around a bug in Intel PIIX controllers */
uhci_fill_td(uhci->term_td, 0, uhci_explen(0) | uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0); (0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
uhci->term_td->link = cpu_to_le32(uhci->term_td->dma_handle); uhci->term_td->link = UHCI_PTR_TERM;
uhci->skel_async_qh->element = uhci->skel_term_qh->element =
uhci->skel_term_qh->link = UHCI_PTR_TERM; LINK_TO_TD(uhci->term_td);
uhci->skel_term_qh->element = cpu_to_le32(uhci->term_td->dma_handle);
/* /*
* Fill the frame list: make all entries point to the proper * Fill the frame list: make all entries point to the proper
......
...@@ -129,11 +129,12 @@ struct uhci_qh { ...@@ -129,11 +129,12 @@ struct uhci_qh {
__le32 element; /* Queue element (TD) pointer */ __le32 element; /* Queue element (TD) pointer */
/* Software fields */ /* Software fields */
dma_addr_t dma_handle;
struct list_head node; /* Node in the list of QHs */ struct list_head node; /* Node in the list of QHs */
struct usb_host_endpoint *hep; /* Endpoint information */ struct usb_host_endpoint *hep; /* Endpoint information */
struct usb_device *udev; struct usb_device *udev;
struct list_head queue; /* Queue of urbps for this QH */ struct list_head queue; /* Queue of urbps for this QH */
struct uhci_qh *skel; /* Skeleton for this QH */
struct uhci_td *dummy_td; /* Dummy TD to end the queue */ struct uhci_td *dummy_td; /* Dummy TD to end the queue */
struct uhci_td *post_td; /* Last TD completed */ struct uhci_td *post_td; /* Last TD completed */
...@@ -149,8 +150,7 @@ struct uhci_qh { ...@@ -149,8 +150,7 @@ struct uhci_qh {
int state; /* QH_STATE_xxx; see above */ int state; /* QH_STATE_xxx; see above */
int type; /* Queue type (control, bulk, etc) */ int type; /* Queue type (control, bulk, etc) */
int skel; /* Skeleton queue number */
dma_addr_t dma_handle;
unsigned int initial_toggle:1; /* Endpoint's current toggle value */ unsigned int initial_toggle:1; /* Endpoint's current toggle value */
unsigned int needs_fixup:1; /* Must fix the TD toggle values */ unsigned int needs_fixup:1; /* Must fix the TD toggle values */
...@@ -171,6 +171,8 @@ static inline __le32 qh_element(struct uhci_qh *qh) { ...@@ -171,6 +171,8 @@ static inline __le32 qh_element(struct uhci_qh *qh) {
return element; return element;
} }
#define LINK_TO_QH(qh) (UHCI_PTR_QH | cpu_to_le32((qh)->dma_handle))
/* /*
* Transfer Descriptors * Transfer Descriptors
...@@ -264,6 +266,8 @@ static inline u32 td_status(struct uhci_td *td) { ...@@ -264,6 +266,8 @@ static inline u32 td_status(struct uhci_td *td) {
return le32_to_cpu(status); return le32_to_cpu(status);
} }
#define LINK_TO_TD(td) (cpu_to_le32((td)->dma_handle))
/* /*
* Skeleton Queue Headers * Skeleton Queue Headers
...@@ -272,12 +276,13 @@ static inline u32 td_status(struct uhci_td *td) { ...@@ -272,12 +276,13 @@ static inline u32 td_status(struct uhci_td *td) {
/* /*
* The UHCI driver uses QHs with Interrupt, Control and Bulk URBs for * The UHCI driver uses QHs with Interrupt, Control and Bulk URBs for
* automatic queuing. To make it easy to insert entries into the schedule, * automatic queuing. To make it easy to insert entries into the schedule,
* we have a skeleton of QHs for each predefined Interrupt latency, * we have a skeleton of QHs for each predefined Interrupt latency.
* low-speed control, full-speed control, bulk, and terminating QH * Asynchronous QHs (low-speed control, full-speed control, and bulk)
* (see explanation for the terminating QH below). * go onto the period-1 interrupt list, since they all get accessed on
* every frame.
* *
* When we want to add a new QH, we add it to the end of the list for the * When we want to add a new QH, we add it to the list starting from the
* skeleton QH. For instance, the schedule list can look like this: * appropriate skeleton QH. For instance, the schedule can look like this:
* *
* skel int128 QH * skel int128 QH
* dev 1 interrupt QH * dev 1 interrupt QH
...@@ -285,50 +290,47 @@ static inline u32 td_status(struct uhci_td *td) { ...@@ -285,50 +290,47 @@ static inline u32 td_status(struct uhci_td *td) {
* skel int64 QH * skel int64 QH
* skel int32 QH * skel int32 QH
* ... * ...
* skel int1 QH * skel int1 + async QH
* skel low-speed control QH * dev 5 low-speed control QH
* dev 5 control QH
* skel full-speed control QH
* skel bulk QH
* dev 1 bulk QH * dev 1 bulk QH
* dev 2 bulk QH * dev 2 bulk QH
* skel terminating QH
* *
* The terminating QH is used for 2 reasons: * There is a special terminating QH used to keep full-speed bandwidth
* - To place a terminating TD which is used to workaround a PIIX bug * reclamation active when no full-speed control or bulk QHs are linked
* (see Intel errata for explanation), and * into the schedule. It has an inactive TD (to work around a PIIX bug,
* - To loop back to the full-speed control queue for full-speed bandwidth * see the Intel errata) and it points back to itself.
* reclamation.
* *
* There's a special skeleton QH for Isochronous QHs. It never appears * There's a special skeleton QH for Isochronous QHs which never appears
* on the schedule, and Isochronous TDs go on the schedule before the * on the schedule. Isochronous TDs go on the schedule before the
* the skeleton QHs. The hardware accesses them directly rather than * the skeleton QHs. The hardware accesses them directly rather than
* through their QH, which is used only for bookkeeping purposes. * through their QH, which is used only for bookkeeping purposes.
* While the UHCI spec doesn't forbid the use of QHs for Isochronous, * While the UHCI spec doesn't forbid the use of QHs for Isochronous,
* it doesn't use them either. And the spec says that queues never * it doesn't use them either. And the spec says that queues never
* advance on an error completion status, which makes them totally * advance on an error completion status, which makes them totally
* unsuitable for Isochronous transfers. * unsuitable for Isochronous transfers.
*
* There's also a special skeleton QH used for QHs which are in the process
* of unlinking and so may still be in use by the hardware. It too never
* appears on the schedule.
*/ */
#define UHCI_NUM_SKELQH 14 #define UHCI_NUM_SKELQH 11
#define skel_unlink_qh skelqh[0] #define SKEL_UNLINK 0
#define skel_iso_qh skelqh[1] #define skel_unlink_qh skelqh[SKEL_UNLINK]
#define skel_int128_qh skelqh[2] #define SKEL_ISO 1
#define skel_int64_qh skelqh[3] #define skel_iso_qh skelqh[SKEL_ISO]
#define skel_int32_qh skelqh[4] /* int128, int64, ..., int1 = 2, 3, ..., 9 */
#define skel_int16_qh skelqh[5] #define SKEL_INDEX(exponent) (9 - exponent)
#define skel_int8_qh skelqh[6] #define SKEL_ASYNC 9
#define skel_int4_qh skelqh[7] #define skel_async_qh skelqh[SKEL_ASYNC]
#define skel_int2_qh skelqh[8] #define SKEL_TERM 10
#define skel_int1_qh skelqh[9] #define skel_term_qh skelqh[SKEL_TERM]
#define skel_ls_control_qh skelqh[10]
#define skel_fs_control_qh skelqh[11] /* The following entries refer to sublists of skel_async_qh */
#define skel_bulk_qh skelqh[12] #define SKEL_LS_CONTROL 20
#define skel_term_qh skelqh[13] #define SKEL_FS_CONTROL 21
#define SKEL_FSBR SKEL_FS_CONTROL
/* Find the skelqh entry corresponding to an interval exponent */ #define SKEL_BULK 22
#define UHCI_SKEL_INDEX(exponent) (9 - exponent)
/* /*
* The UHCI controller and root hub * The UHCI controller and root hub
......
This diff is collapsed.
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/usb/input.h> #include <linux/usb/input.h>
#include <linux/hid.h>
/* /*
* Version Information * Version Information
...@@ -330,7 +331,8 @@ static void usb_kbd_disconnect(struct usb_interface *intf) ...@@ -330,7 +331,8 @@ static void usb_kbd_disconnect(struct usb_interface *intf)
} }
static struct usb_device_id usb_kbd_id_table [] = { static struct usb_device_id usb_kbd_id_table [] = {
{ USB_INTERFACE_INFO(3, 1, 1) }, { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
USB_INTERFACE_PROTOCOL_KEYBOARD) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/usb/input.h> #include <linux/usb/input.h>
#include <linux/hid.h>
/* /*
* Version Information * Version Information
...@@ -213,7 +214,8 @@ static void usb_mouse_disconnect(struct usb_interface *intf) ...@@ -213,7 +214,8 @@ static void usb_mouse_disconnect(struct usb_interface *intf)
} }
static struct usb_device_id usb_mouse_id_table [] = { static struct usb_device_id usb_mouse_id_table [] = {
{ USB_INTERFACE_INFO(3, 1, 2) }, { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
USB_INTERFACE_PROTOCOL_MOUSE) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
......
...@@ -163,7 +163,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) ...@@ -163,7 +163,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
} }
id = STYLUS_DEVICE_ID; id = STYLUS_DEVICE_ID;
if (data[1] & 0x10) { /* in prox */ if (data[1] & 0x80) { /* in prox */
switch ((data[1] >> 5) & 3) { switch ((data[1] >> 5) & 3) {
...@@ -196,9 +196,6 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) ...@@ -196,9 +196,6 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f);
break; break;
} }
}
if (data[1] & 0x90) {
x = wacom_le16_to_cpu(&data[2]); x = wacom_le16_to_cpu(&data[2]);
y = wacom_le16_to_cpu(&data[4]); y = wacom_le16_to_cpu(&data[4]);
wacom_report_abs(wcombo, ABS_X, x); wacom_report_abs(wcombo, ABS_X, x);
...@@ -210,19 +207,28 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) ...@@ -210,19 +207,28 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04); wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04);
} }
wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */ wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
wacom_report_key(wcombo, wacom->tool[0], 1);
} else if (!(data[1] & 0x90)) {
wacom_report_abs(wcombo, ABS_X, 0);
wacom_report_abs(wcombo, ABS_Y, 0);
if (wacom->tool[0] == BTN_TOOL_MOUSE) {
wacom_report_key(wcombo, BTN_LEFT, 0);
wacom_report_key(wcombo, BTN_RIGHT, 0);
wacom_report_abs(wcombo, ABS_DISTANCE, 0);
} else {
wacom_report_abs(wcombo, ABS_PRESSURE, 0);
wacom_report_key(wcombo, BTN_TOUCH, 0);
wacom_report_key(wcombo, BTN_STYLUS, 0);
wacom_report_key(wcombo, BTN_STYLUS2, 0);
} }
else
wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
if (data[1] & 0x10) /* only report prox-in when in area */
wacom_report_key(wcombo, wacom->tool[0], 1);
if (!(data[1] & 0x90)) /* report prox-out when physically out */
wacom_report_key(wcombo, wacom->tool[0], 0); wacom_report_key(wcombo, wacom->tool[0], 0);
wacom_input_sync(wcombo); }
/* send pad data */ /* send pad data */
if (wacom->features->type == WACOM_G4) { if (wacom->features->type == WACOM_G4) {
if ( (wacom->serial[1] & 0xc0) != (data[7] & 0xf8) ) { if (data[7] & 0xf8) {
wacom_input_sync(wcombo); /* sync last event */
wacom->id[1] = 1; wacom->id[1] = 1;
wacom->serial[1] = (data[7] & 0xf8); wacom->serial[1] = (data[7] & 0xf8);
wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
...@@ -230,10 +236,15 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) ...@@ -230,10 +236,15 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
wacom_report_rel(wcombo, REL_WHEEL, rw); wacom_report_rel(wcombo, REL_WHEEL, rw);
wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
} else if (wacom->id[1]) { } else if (wacom->id[1]) {
wacom_input_sync(wcombo); /* sync last event */
wacom->id[1] = 0; wacom->id[1] = 0;
wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
wacom_report_key(wcombo, BTN_4, (data[7] & 0x80));
wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); wacom_report_key(wcombo, BTN_TOOL_FINGER, 0);
wacom_report_abs(wcombo, ABS_MISC, 0);
wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
} }
} }
...@@ -304,29 +315,36 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) ...@@ -304,29 +315,36 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
default: /* Unknown tool */ default: /* Unknown tool */
wacom->tool[idx] = BTN_TOOL_PEN; wacom->tool[idx] = BTN_TOOL_PEN;
} }
/* only large I3 support Lens Cursor */
if(!((wacom->tool[idx] == BTN_TOOL_LENS)
&& ((wacom->features->type == INTUOS3)
|| (wacom->features->type == INTUOS3S)))) {
wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */
wacom_report_key(wcombo, wacom->tool[idx], 1);
wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
return 2;
}
return 1; return 1;
} }
/* Exit report */ /* Exit report */
if ((data[1] & 0xfe) == 0x80) { if ((data[1] & 0xfe) == 0x80) {
if(!((wacom->tool[idx] == BTN_TOOL_LENS) wacom_report_abs(wcombo, ABS_X, 0);
&& ((wacom->features->type == INTUOS3) wacom_report_abs(wcombo, ABS_Y, 0);
|| (wacom->features->type == INTUOS3S)))) { wacom_report_abs(wcombo, ABS_DISTANCE, 0);
if (wacom->tool[idx] >= BTN_TOOL_MOUSE) {
wacom_report_key(wcombo, BTN_LEFT, 0);
wacom_report_key(wcombo, BTN_MIDDLE, 0);
wacom_report_key(wcombo, BTN_RIGHT, 0);
wacom_report_key(wcombo, BTN_SIDE, 0);
wacom_report_key(wcombo, BTN_EXTRA, 0);
wacom_report_abs(wcombo, ABS_THROTTLE, 0);
wacom_report_abs(wcombo, ABS_RZ, 0);
} else {
wacom_report_abs(wcombo, ABS_PRESSURE, 0);
wacom_report_abs(wcombo, ABS_TILT_X, 0);
wacom_report_abs(wcombo, ABS_TILT_Y, 0);
wacom_report_key(wcombo, BTN_STYLUS, 0);
wacom_report_key(wcombo, BTN_STYLUS2, 0);
wacom_report_key(wcombo, BTN_TOUCH, 0);
wacom_report_abs(wcombo, ABS_WHEEL, 0);
}
wacom_report_key(wcombo, wacom->tool[idx], 0); wacom_report_key(wcombo, wacom->tool[idx], 0);
wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
return 2; return 2;
} }
}
return 0; return 0;
} }
...@@ -394,6 +412,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) ...@@ -394,6 +412,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
wacom_report_key(wcombo, wacom->tool[1], 1); wacom_report_key(wcombo, wacom->tool[1], 1);
else else
wacom_report_key(wcombo, wacom->tool[1], 0); wacom_report_key(wcombo, wacom->tool[1], 0);
wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff); wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff);
return 1; return 1;
} }
...@@ -403,6 +422,12 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) ...@@ -403,6 +422,12 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
if (result) if (result)
return result-1; return result-1;
/* Only large I3 and I1 & I2 support Lense Cursor */
if((wacom->tool[idx] == BTN_TOOL_LENS)
&& ((wacom->features->type == INTUOS3)
|| (wacom->features->type == INTUOS3S)))
return 0;
/* Cintiq doesn't send data when RDY bit isn't set */ /* Cintiq doesn't send data when RDY bit isn't set */
if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40)) if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40))
return 0; return 0;
...@@ -554,11 +579,11 @@ static struct wacom_features wacom_features[] = { ...@@ -554,11 +579,11 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE }, { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE },
{ "Wacom Volito2 2x3", 8, 3248, 2320, 511, 63, GRAPHIRE }, { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 63, GRAPHIRE },
{ "Wacom PenPartner2", 8, 3250, 2320, 255, 63, GRAPHIRE }, { "Wacom PenPartner2", 8, 3250, 2320, 255, 63, GRAPHIRE },
{ "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 63, INTUOS }, { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 31, INTUOS },
{ "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 63, INTUOS }, { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 31, INTUOS },
{ "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 63, INTUOS }, { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 31, INTUOS },
{ "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 63, INTUOS }, { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 31, INTUOS },
{ "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 63, INTUOS }, { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 31, INTUOS },
{ "Wacom PL400", 8, 5408, 4056, 255, 0, PL }, { "Wacom PL400", 8, 5408, 4056, 255, 0, PL },
{ "Wacom PL500", 8, 6144, 4608, 255, 0, PL }, { "Wacom PL500", 8, 6144, 4608, 255, 0, PL },
{ "Wacom PL600", 8, 6126, 4604, 255, 0, PL }, { "Wacom PL600", 8, 6126, 4604, 255, 0, PL },
...@@ -571,11 +596,11 @@ static struct wacom_features wacom_features[] = { ...@@ -571,11 +596,11 @@ static struct wacom_features wacom_features[] = {
{ "Wacom DTF521", 8, 6282, 4762, 511, 0, PL }, { "Wacom DTF521", 8, 6282, 4762, 511, 0, PL },
{ "Wacom DTF720", 8, 6858, 5506, 511, 0, PL }, { "Wacom DTF720", 8, 6858, 5506, 511, 0, PL },
{ "Wacom Cintiq Partner",8, 20480, 15360, 511, 0, PTU }, { "Wacom Cintiq Partner",8, 20480, 15360, 511, 0, PTU },
{ "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 63, INTUOS }, { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 31, INTUOS },
{ "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 63, INTUOS }, { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS },
{ "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 63, INTUOS }, { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 31, INTUOS },
{ "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 63, INTUOS }, { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 31, INTUOS },
{ "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 63, INTUOS }, { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 31, INTUOS },
{ "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 63, INTUOS3S }, { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 63, INTUOS3S },
{ "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 63, INTUOS3 }, { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 63, INTUOS3 },
{ "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 63, INTUOS3 }, { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 63, INTUOS3 },
...@@ -584,7 +609,7 @@ static struct wacom_features wacom_features[] = { ...@@ -584,7 +609,7 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 63, INTUOS3 }, { "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 63, INTUOS3 },
{ "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 63, INTUOS3S }, { "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 63, INTUOS3S },
{ "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ }, { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ },
{ "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 63, INTUOS }, { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS },
{ } { }
}; };
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#define STYLUS_DEVICE_ID 0x02 #define STYLUS_DEVICE_ID 0x02
#define CURSOR_DEVICE_ID 0x06 #define CURSOR_DEVICE_ID 0x06
#define ERASER_DEVICE_ID 0x0A #define ERASER_DEVICE_ID 0x0A
#define PAD_DEVICE_ID 0x0F
enum { enum {
PENPARTNER = 0, PENPARTNER = 0,
......
...@@ -244,6 +244,20 @@ config USB_TRANCEVIBRATOR ...@@ -244,6 +244,20 @@ config USB_TRANCEVIBRATOR
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called trancevibrator. module will be called trancevibrator.
config USB_IOWARRIOR
tristate "IO Warrior driver support"
depends on USB
help
Say Y here if you want to support the IO Warrior devices from Code
Mercenaries. This includes support for the following devices:
IO Warrior 40
IO Warrior 24
IO Warrior 56
IO Warrior 24 Power Vampire
To compile this driver as a module, choose M here: the
module will be called iowarrior.
config USB_TEST config USB_TEST
tristate "USB testing driver (DEVELOPMENT)" tristate "USB testing driver (DEVELOPMENT)"
depends on USB && USB_DEVICEFS && EXPERIMENTAL depends on USB && USB_DEVICEFS && EXPERIMENTAL
......
...@@ -13,6 +13,7 @@ obj-$(CONFIG_USB_EMI26) += emi26.o ...@@ -13,6 +13,7 @@ obj-$(CONFIG_USB_EMI26) += emi26.o
obj-$(CONFIG_USB_EMI62) += emi62.o obj-$(CONFIG_USB_EMI62) += emi62.o
obj-$(CONFIG_USB_FTDI_ELAN) += ftdi-elan.o obj-$(CONFIG_USB_FTDI_ELAN) += ftdi-elan.o
obj-$(CONFIG_USB_IDMOUSE) += idmouse.o obj-$(CONFIG_USB_IDMOUSE) += idmouse.o
obj-$(CONFIG_USB_IOWARRIOR) += iowarrior.o
obj-$(CONFIG_USB_LCD) += usblcd.o obj-$(CONFIG_USB_LCD) += usblcd.o
obj-$(CONFIG_USB_LD) += ldusb.o obj-$(CONFIG_USB_LD) += ldusb.o
obj-$(CONFIG_USB_LED) += usbled.o obj-$(CONFIG_USB_LED) += usbled.o
......
This diff is collapsed.
...@@ -1165,7 +1165,7 @@ int __init mon_bin_init(void) ...@@ -1165,7 +1165,7 @@ int __init mon_bin_init(void)
return rc; return rc;
} }
void __exit mon_bin_exit(void) void mon_bin_exit(void)
{ {
cdev_del(&mon_bin_cdev); cdev_del(&mon_bin_cdev);
unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR); unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
......
...@@ -520,7 +520,7 @@ int __init mon_text_init(void) ...@@ -520,7 +520,7 @@ int __init mon_text_init(void)
return 0; return 0;
} }
void __exit mon_text_exit(void) void mon_text_exit(void)
{ {
debugfs_remove(mon_dir); debugfs_remove(mon_dir);
} }
...@@ -57,9 +57,9 @@ void mon_text_del(struct mon_bus *mbus); ...@@ -57,9 +57,9 @@ void mon_text_del(struct mon_bus *mbus);
// void mon_bin_add(struct mon_bus *); // void mon_bin_add(struct mon_bus *);
int __init mon_text_init(void); int __init mon_text_init(void);
void __exit mon_text_exit(void); void mon_text_exit(void);
int __init mon_bin_init(void); int __init mon_bin_init(void);
void __exit mon_bin_exit(void); void mon_bin_exit(void);
/* /*
* DMA interface. * DMA interface.
......
...@@ -186,6 +186,15 @@ config USB_NET_CDCETHER ...@@ -186,6 +186,15 @@ config USB_NET_CDCETHER
IEEE 802 "local assignment" bit is set in the address, a "usbX" IEEE 802 "local assignment" bit is set in the address, a "usbX"
name is used instead. name is used instead.
config USB_NET_DM9601
tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
depends on USB_USBNET
select CRC32
select USB_USBNET_MII
help
This option adds support for Davicom DM9601 based USB 1.1
10/100 Ethernet adapters.
config USB_NET_GL620A config USB_NET_GL620A
tristate "GeneSys GL620USB-A based cables" tristate "GeneSys GL620USB-A based cables"
depends on USB_USBNET depends on USB_USBNET
......
...@@ -8,6 +8,7 @@ obj-$(CONFIG_USB_PEGASUS) += pegasus.o ...@@ -8,6 +8,7 @@ obj-$(CONFIG_USB_PEGASUS) += pegasus.o
obj-$(CONFIG_USB_RTL8150) += rtl8150.o obj-$(CONFIG_USB_RTL8150) += rtl8150.o
obj-$(CONFIG_USB_NET_AX8817X) += asix.o obj-$(CONFIG_USB_NET_AX8817X) += asix.o
obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o
obj-$(CONFIG_USB_NET_DM9601) += dm9601.o
obj-$(CONFIG_USB_NET_GL620A) += gl620a.o obj-$(CONFIG_USB_NET_GL620A) += gl620a.o
obj-$(CONFIG_USB_NET_NET1080) += net1080.o obj-$(CONFIG_USB_NET_NET1080) += net1080.o
obj-$(CONFIG_USB_NET_PLUSB) += plusb.o obj-$(CONFIG_USB_NET_PLUSB) += plusb.o
......
...@@ -1422,6 +1422,10 @@ static const struct usb_device_id products [] = { ...@@ -1422,6 +1422,10 @@ static const struct usb_device_id products [] = {
// goodway corp usb gwusb2e // goodway corp usb gwusb2e
USB_DEVICE (0x1631, 0x6200), USB_DEVICE (0x1631, 0x6200),
.driver_info = (unsigned long) &ax8817x_info, .driver_info = (unsigned long) &ax8817x_info,
}, {
// JVC MP-PRX1 Port Replicator
USB_DEVICE (0x04f1, 0x3008),
.driver_info = (unsigned long) &ax8817x_info,
}, { }, {
// ASIX AX88772 10/100 // ASIX AX88772 10/100
USB_DEVICE (0x0b95, 0x7720), USB_DEVICE (0x0b95, 0x7720),
......
This diff is collapsed.
...@@ -513,6 +513,7 @@ static struct usb_device_id id_table_combined [] = { ...@@ -513,6 +513,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) }, { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) }, { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) },
{ USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) }, { USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) },
{ USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
{ }, /* Optional parameter entry */ { }, /* Optional parameter entry */
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
......
...@@ -491,6 +491,12 @@ ...@@ -491,6 +491,12 @@
#define FTDI_TACTRIX_OPENPORT_13S_PID 0xCC49 /* OpenPort 1.3 Subaru */ #define FTDI_TACTRIX_OPENPORT_13S_PID 0xCC49 /* OpenPort 1.3 Subaru */
#define FTDI_TACTRIX_OPENPORT_13U_PID 0xCC4A /* OpenPort 1.3 Universal */ #define FTDI_TACTRIX_OPENPORT_13U_PID 0xCC4A /* OpenPort 1.3 Universal */
/*
* Telldus Technologies
*/
#define TELLDUS_VID 0x1781 /* Vendor ID */
#define TELLDUS_TELLSTICK_PID 0x0C30 /* RF control dongle 433 MHz using FT232RL */
/* Commands */ /* Commands */
#define FTDI_SIO_RESET 0 /* Reset the port */ #define FTDI_SIO_RESET 0 /* Reset the port */
#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */
......
...@@ -68,49 +68,94 @@ static int option_send_setup(struct usb_serial_port *port); ...@@ -68,49 +68,94 @@ static int option_send_setup(struct usb_serial_port *port);
/* Vendor and product IDs */ /* Vendor and product IDs */
#define OPTION_VENDOR_ID 0x0AF0 #define OPTION_VENDOR_ID 0x0AF0
#define HUAWEI_VENDOR_ID 0x12D1 #define OPTION_PRODUCT_COLT 0x5000
#define NOVATELWIRELESS_VENDOR_ID 0x1410 #define OPTION_PRODUCT_RICOLA 0x6000
#define ANYDATA_VENDOR_ID 0x16d5 #define OPTION_PRODUCT_RICOLA_LIGHT 0x6100
#define OPTION_PRODUCT_RICOLA_QUAD 0x6200
#define OPTION_PRODUCT_OLD 0x5000 #define OPTION_PRODUCT_RICOLA_QUAD_LIGHT 0x6300
#define OPTION_PRODUCT_FUSION 0x6000 #define OPTION_PRODUCT_RICOLA_NDIS 0x6050
#define OPTION_PRODUCT_FUSION2 0x6300 #define OPTION_PRODUCT_RICOLA_NDIS_LIGHT 0x6150
#define OPTION_PRODUCT_RICOLA_NDIS_QUAD 0x6250
#define OPTION_PRODUCT_RICOLA_NDIS_QUAD_LIGHT 0x6350
#define OPTION_PRODUCT_COBRA 0x6500 #define OPTION_PRODUCT_COBRA 0x6500
#define OPTION_PRODUCT_COBRA2 0x6600 #define OPTION_PRODUCT_COBRA_BUS 0x6501
#define OPTION_PRODUCT_GTMAX36 0x6701 #define OPTION_PRODUCT_VIPER 0x6600
#define OPTION_PRODUCT_VIPER_BUS 0x6601
#define OPTION_PRODUCT_GT_MAX_READY 0x6701
#define OPTION_PRODUCT_GT_MAX 0x6711
#define OPTION_PRODUCT_FUJI_MODEM_LIGHT 0x6721
#define OPTION_PRODUCT_FUJI_MODEM_GT 0x6741
#define OPTION_PRODUCT_FUJI_MODEM_EX 0x6761
#define OPTION_PRODUCT_FUJI_NETWORK_LIGHT 0x6731
#define OPTION_PRODUCT_FUJI_NETWORK_GT 0x6751
#define OPTION_PRODUCT_FUJI_NETWORK_EX 0x6771
#define OPTION_PRODUCT_KOI_MODEM 0x6800
#define OPTION_PRODUCT_KOI_NETWORK 0x6811
#define OPTION_PRODUCT_SCORPION_MODEM 0x6901
#define OPTION_PRODUCT_SCORPION_NETWORK 0x6911
#define OPTION_PRODUCT_ETNA_MODEM 0x7001
#define OPTION_PRODUCT_ETNA_NETWORK 0x7011
#define OPTION_PRODUCT_ETNA_MODEM_LITE 0x7021
#define OPTION_PRODUCT_ETNA_MODEM_GT 0x7041
#define OPTION_PRODUCT_ETNA_MODEM_EX 0x7061
#define OPTION_PRODUCT_ETNA_NETWORK_LITE 0x7031
#define OPTION_PRODUCT_ETNA_NETWORK_GT 0x7051
#define OPTION_PRODUCT_ETNA_NETWORK_EX 0x7071
#define OPTION_PRODUCT_ETNA_KOI_MODEM 0x7100
#define OPTION_PRODUCT_ETNA_KOI_NETWORK 0x7111
#define HUAWEI_VENDOR_ID 0x12D1
#define HUAWEI_PRODUCT_E600 0x1001 #define HUAWEI_PRODUCT_E600 0x1001
#define HUAWEI_PRODUCT_E220 0x1003 #define HUAWEI_PRODUCT_E220 0x1003
#define NOVATELWIRELESS_VENDOR_ID 0x1410
#define NOVATELWIRELESS_PRODUCT_U740 0x1400 #define NOVATELWIRELESS_PRODUCT_U740 0x1400
#define ANYDATA_VENDOR_ID 0x16d5
#define ANYDATA_PRODUCT_ID 0x6501 #define ANYDATA_PRODUCT_ID 0x6501
static struct usb_device_id option_ids[] = { static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD_LIGHT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_LIGHT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_QUAD) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_QUAD_LIGHT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA_BUS) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_VIPER) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_VIPER_BUS) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GT_MAX_READY) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GT_MAX) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_LIGHT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_GT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_EX) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_LIGHT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_GT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_EX) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_KOI_MODEM) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_KOI_NETWORK) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_SCORPION_MODEM) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_SCORPION_NETWORK) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_LITE) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_GT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_EX) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_LITE) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_GT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_EX) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_NETWORK) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
static struct usb_device_id option_ids1[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids); MODULE_DEVICE_TABLE(usb, option_ids);
static struct usb_driver option_driver = { static struct usb_driver option_driver = {
...@@ -132,7 +177,7 @@ static struct usb_serial_driver option_1port_device = { ...@@ -132,7 +177,7 @@ static struct usb_serial_driver option_1port_device = {
}, },
.description = "GSM modem (1-port)", .description = "GSM modem (1-port)",
.usb_driver = &option_driver, .usb_driver = &option_driver,
.id_table = option_ids1, .id_table = option_ids,
.num_interrupt_in = NUM_DONT_CARE, .num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE,
.num_bulk_out = NUM_DONT_CARE, .num_bulk_out = NUM_DONT_CARE,
......
...@@ -501,6 +501,30 @@ int sysfs_create_file(struct kobject * kobj, const struct attribute * attr) ...@@ -501,6 +501,30 @@ int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
} }
/**
* sysfs_add_file_to_group - add an attribute file to a pre-existing group.
* @kobj: object we're acting for.
* @attr: attribute descriptor.
* @group: group name.
*/
int sysfs_add_file_to_group(struct kobject *kobj,
const struct attribute *attr, const char *group)
{
struct dentry *dir;
int error;
dir = lookup_one_len(group, kobj->dentry, strlen(group));
if (IS_ERR(dir))
error = PTR_ERR(dir);
else {
error = sysfs_add_file(dir, attr, SYSFS_KOBJ_ATTR);
dput(dir);
}
return error;
}
EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
/** /**
* sysfs_update_file - update the modified timestamp on an object attribute. * sysfs_update_file - update the modified timestamp on an object attribute.
* @kobj: object we're acting for. * @kobj: object we're acting for.
...@@ -586,6 +610,26 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) ...@@ -586,6 +610,26 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
} }
/**
* sysfs_remove_file_from_group - remove an attribute file from a group.
* @kobj: object we're acting for.
* @attr: attribute descriptor.
* @group: group name.
*/
void sysfs_remove_file_from_group(struct kobject *kobj,
const struct attribute *attr, const char *group)
{
struct dentry *dir;
dir = lookup_one_len(group, kobj->dentry, strlen(group));
if (!IS_ERR(dir)) {
sysfs_hash_and_remove(dir, attr->name);
dput(dir);
}
}
EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
EXPORT_SYMBOL_GPL(sysfs_create_file); EXPORT_SYMBOL_GPL(sysfs_create_file);
EXPORT_SYMBOL_GPL(sysfs_remove_file); EXPORT_SYMBOL_GPL(sysfs_remove_file);
EXPORT_SYMBOL_GPL(sysfs_update_file); EXPORT_SYMBOL_GPL(sysfs_update_file);
...@@ -126,6 +126,11 @@ void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr); ...@@ -126,6 +126,11 @@ void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr);
int __must_check sysfs_create_group(struct kobject *, int __must_check sysfs_create_group(struct kobject *,
const struct attribute_group *); const struct attribute_group *);
void sysfs_remove_group(struct kobject *, const struct attribute_group *); void sysfs_remove_group(struct kobject *, const struct attribute_group *);
int sysfs_add_file_to_group(struct kobject *kobj,
const struct attribute *attr, const char *group);
void sysfs_remove_file_from_group(struct kobject *kobj,
const struct attribute *attr, const char *group);
void sysfs_notify(struct kobject * k, char *dir, char *attr); void sysfs_notify(struct kobject * k, char *dir, char *attr);
...@@ -210,6 +215,18 @@ static inline void sysfs_remove_group(struct kobject * k, const struct attribute ...@@ -210,6 +215,18 @@ static inline void sysfs_remove_group(struct kobject * k, const struct attribute
; ;
} }
static inline int sysfs_add_file_to_group(struct kobject *kobj,
const struct attribute *attr, const char *group)
{
return 0;
}
static inline void sysfs_remove_file_from_group(struct kobject *kobj,
const struct attribute *attr, const char *group);
{
;
}
static inline void sysfs_notify(struct kobject * k, char *dir, char *attr) static inline void sysfs_notify(struct kobject * k, char *dir, char *attr)
{ {
} }
......
...@@ -388,10 +388,14 @@ struct usb_device { ...@@ -388,10 +388,14 @@ struct usb_device {
struct usb_device *children[USB_MAXCHILDREN]; struct usb_device *children[USB_MAXCHILDREN];
int pm_usage_cnt; /* usage counter for autosuspend */ int pm_usage_cnt; /* usage counter for autosuspend */
u32 quirks; /* quirks of the whole device */
#ifdef CONFIG_PM #ifdef CONFIG_PM
struct delayed_work autosuspend; /* for delayed autosuspends */ struct delayed_work autosuspend; /* for delayed autosuspends */
struct mutex pm_mutex; /* protects PM operations */ struct mutex pm_mutex; /* protects PM operations */
unsigned autosuspend_delay; /* in jiffies */
unsigned auto_pm:1; /* autosuspend/resume in progress */ unsigned auto_pm:1; /* autosuspend/resume in progress */
unsigned do_remote_wakeup:1; /* remote wakeup should be enabled */ unsigned do_remote_wakeup:1; /* remote wakeup should be enabled */
#endif #endif
......
/* /*
* This file holds USB constants and structures that are needed for USB * This file holds USB constants and structures that are needed for
* device APIs. These are used by the USB device model, which is defined * USB device APIs. These are used by the USB device model, which is
* in chapter 9 of the USB 2.0 specification. Linux has several APIs in C * defined in chapter 9 of the USB 2.0 specification and in the
* that need these: * Wireless USB 1.0 (spread around). Linux has several APIs in C that
* need these:
* *
* - the master/host side Linux-USB kernel driver API; * - the master/host side Linux-USB kernel driver API;
* - the "usbfs" user space API; and * - the "usbfs" user space API; and
...@@ -14,6 +15,19 @@ ...@@ -14,6 +15,19 @@
* *
* There's also "Wireless USB", using low power short range radios for * There's also "Wireless USB", using low power short range radios for
* peripheral interconnection but otherwise building on the USB framework. * peripheral interconnection but otherwise building on the USB framework.
*
* Note all descriptors are declared '__attribute__((packed))' so that:
*
* [a] they never get padded, either internally (USB spec writers
* probably handled that) or externally;
*
* [b] so that accessing bigger-than-a-bytes fields will never
* generate bus errors on any platform, even when the location of
* its descriptor inside a bundle isn't "naturally aligned", and
*
* [c] for consistency, removing all doubt even when it appears to
* someone that the two other points are non-issues for that
* particular descriptor type.
*/ */
#ifndef __LINUX_USB_CH9_H #ifndef __LINUX_USB_CH9_H
......
#ifndef _IOWARRIOR_H_
#define _IOWARRIOR_H_
#define CODEMERCS_MAGIC_NUMBER 0xC0 /* like COde Mercenaries */
/* Define the ioctl commands for reading and writing data */
#define IOW_WRITE _IOW(CODEMERCS_MAGIC_NUMBER, 1, __u8 *)
#define IOW_READ _IOW(CODEMERCS_MAGIC_NUMBER, 2, __u8 *)
/*
A struct for available device info which is read
with the ioctl IOW_GETINFO.
To be compatible with 2.4 userspace which didn't have an easy way to get
this information.
*/
struct iowarrior_info {
__u32 vendor; /* vendor id : supposed to be USB_VENDOR_ID_CODEMERCS in all cases */
__u32 product; /* product id : depends on type of chip (USB_DEVICE_ID_CODEMERCS_XXXXX) */
__u8 serial[9]; /* the serial number of our chip (if a serial-number is not available this is empty string) */
__u32 revision; /* revision number of the chip */
__u32 speed; /* USB-speed of the device (0=UNKNOWN, 1=LOW, 2=FULL 3=HIGH) */
__u32 power; /* power consumption of the device in mA */
__u32 if_num; /* the number of the endpoint */
__u32 report_size; /* size of the data-packets on this interface */
};
/*
Get some device-information (product-id , serial-number etc.)
in order to identify a chip.
*/
#define IOW_GETINFO _IOR(CODEMERCS_MAGIC_NUMBER, 3, struct iowarrior_info)
#endif /* _IOWARRIOR_H_ */
/*
* This file holds the definitions of quirks found in USB devices.
* Only quirks that affect the whole device, not an interface,
* belong here.
*/
/* device must not be autosuspended */
#define USB_QUIRK_NO_AUTOSUSPEND 0x00000001
/* string descriptors must not be fetched using a 255-byte read */
#define USB_QUIRK_STRING_FETCH_255 0x00000002
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