diff options
38 files changed, 2393 insertions, 276 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index c479d30eeaa3..03eb5ed503f7 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1758,6 +1758,13 @@ and is between 256 and 4096 characters. It is defined in the file | |||
1758 | Note that genuine overcurrent events won't be | 1758 | Note that genuine overcurrent events won't be |
1759 | reported either. | 1759 | reported either. |
1760 | 1760 | ||
1761 | usbcore.autosuspend= | ||
1762 | [USB] The autosuspend time delay (in seconds) used | ||
1763 | for newly-detected USB devices (default 2). This | ||
1764 | is the time required before an idle device will be | ||
1765 | autosuspended. Devices for which the delay is set | ||
1766 | to 0 won't be autosuspended at all. | ||
1767 | |||
1761 | usbhid.mousepoll= | 1768 | usbhid.mousepoll= |
1762 | [USBHID] The interval which mice are to be polled at. | 1769 | [USBHID] The interval which mice are to be polled at. |
1763 | 1770 | ||
diff --git a/MAINTAINERS b/MAINTAINERS index c268b51e4518..a9c13196f6bd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -3392,6 +3392,13 @@ L: linux-usb-devel@lists.sourceforge.net | |||
3392 | S: Maintained | 3392 | S: Maintained |
3393 | W: http://www.kroah.com/linux-usb/ | 3393 | W: http://www.kroah.com/linux-usb/ |
3394 | 3394 | ||
3395 | USB DAVICOM DM9601 DRIVER | ||
3396 | P: Peter Korsgaard | ||
3397 | M: jacmet@sunsite.dk | ||
3398 | L: linux-usb-devel@lists.sourceforge.net | ||
3399 | W: http://www.linux-usb.org/usbnet | ||
3400 | S: Maintained | ||
3401 | |||
3395 | USB EHCI DRIVER | 3402 | USB EHCI DRIVER |
3396 | P: David Brownell | 3403 | P: David Brownell |
3397 | M: dbrownell@users.sourceforge.net | 3404 | M: dbrownell@users.sourceforge.net |
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index 34e9bac319b4..b6078706fb93 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \ | 5 | usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \ |
6 | config.o file.o buffer.o sysfs.o endpoint.o \ | 6 | config.o file.o buffer.o sysfs.o endpoint.o \ |
7 | devio.o notify.o generic.o | 7 | devio.o notify.o generic.o quirks.o |
8 | 8 | ||
9 | ifeq ($(CONFIG_PCI),y) | 9 | ifeq ($(CONFIG_PCI),y) |
10 | usbcore-objs += hcd-pci.o | 10 | usbcore-objs += hcd-pci.o |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 2aded261f42c..9e3e943f313c 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -366,19 +366,8 @@ void usb_driver_release_interface(struct usb_driver *driver, | |||
366 | EXPORT_SYMBOL(usb_driver_release_interface); | 366 | EXPORT_SYMBOL(usb_driver_release_interface); |
367 | 367 | ||
368 | /* returns 0 if no match, 1 if match */ | 368 | /* returns 0 if no match, 1 if match */ |
369 | int usb_match_one_id(struct usb_interface *interface, | 369 | int usb_match_device(struct usb_device *dev, const struct usb_device_id *id) |
370 | const struct usb_device_id *id) | ||
371 | { | 370 | { |
372 | struct usb_host_interface *intf; | ||
373 | struct usb_device *dev; | ||
374 | |||
375 | /* proc_connectinfo in devio.c may call us with id == NULL. */ | ||
376 | if (id == NULL) | ||
377 | return 0; | ||
378 | |||
379 | intf = interface->cur_altsetting; | ||
380 | dev = interface_to_usbdev(interface); | ||
381 | |||
382 | if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && | 371 | if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && |
383 | id->idVendor != le16_to_cpu(dev->descriptor.idVendor)) | 372 | id->idVendor != le16_to_cpu(dev->descriptor.idVendor)) |
384 | return 0; | 373 | return 0; |
@@ -409,6 +398,26 @@ int usb_match_one_id(struct usb_interface *interface, | |||
409 | (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) | 398 | (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) |
410 | return 0; | 399 | return 0; |
411 | 400 | ||
401 | return 1; | ||
402 | } | ||
403 | |||
404 | /* returns 0 if no match, 1 if match */ | ||
405 | int usb_match_one_id(struct usb_interface *interface, | ||
406 | const struct usb_device_id *id) | ||
407 | { | ||
408 | struct usb_host_interface *intf; | ||
409 | struct usb_device *dev; | ||
410 | |||
411 | /* proc_connectinfo in devio.c may call us with id == NULL. */ | ||
412 | if (id == NULL) | ||
413 | return 0; | ||
414 | |||
415 | intf = interface->cur_altsetting; | ||
416 | dev = interface_to_usbdev(interface); | ||
417 | |||
418 | if (!usb_match_device(dev, id)) | ||
419 | return 0; | ||
420 | |||
412 | /* The interface class, subclass, and protocol should never be | 421 | /* The interface class, subclass, and protocol should never be |
413 | * checked for a match if the device class is Vendor Specific, | 422 | * checked for a match if the device class is Vendor Specific, |
414 | * unless the match record specifies the Vendor ID. */ | 423 | * unless the match record specifies the Vendor ID. */ |
@@ -954,12 +963,16 @@ static int autosuspend_check(struct usb_device *udev) | |||
954 | int i; | 963 | int i; |
955 | struct usb_interface *intf; | 964 | struct usb_interface *intf; |
956 | 965 | ||
957 | /* For autosuspend, fail fast if anything is in use. | 966 | /* For autosuspend, fail fast if anything is in use or autosuspend |
958 | * Also fail if any interfaces require remote wakeup but it | 967 | * is disabled. Also fail if any interfaces require remote wakeup |
959 | * isn't available. */ | 968 | * but it isn't available. |
969 | */ | ||
960 | udev->do_remote_wakeup = device_may_wakeup(&udev->dev); | 970 | udev->do_remote_wakeup = device_may_wakeup(&udev->dev); |
961 | if (udev->pm_usage_cnt > 0) | 971 | if (udev->pm_usage_cnt > 0) |
962 | return -EBUSY; | 972 | return -EBUSY; |
973 | if (!udev->autosuspend_delay) | ||
974 | return -EPERM; | ||
975 | |||
963 | if (udev->actconfig) { | 976 | if (udev->actconfig) { |
964 | for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { | 977 | for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { |
965 | intf = udev->actconfig->interface[i]; | 978 | intf = udev->actconfig->interface[i]; |
@@ -982,7 +995,7 @@ static int autosuspend_check(struct usb_device *udev) | |||
982 | 995 | ||
983 | #define autosuspend_check(udev) 0 | 996 | #define autosuspend_check(udev) 0 |
984 | 997 | ||
985 | #endif | 998 | #endif /* CONFIG_USB_SUSPEND */ |
986 | 999 | ||
987 | /** | 1000 | /** |
988 | * usb_suspend_both - suspend a USB device and its interfaces | 1001 | * 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 | udev->pm_usage_cnt -= inc_usage_cnt; | 1190 | udev->pm_usage_cnt -= inc_usage_cnt; |
1178 | } else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0) | 1191 | } else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0) |
1179 | queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, | 1192 | queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, |
1180 | USB_AUTOSUSPEND_DELAY); | 1193 | udev->autosuspend_delay); |
1181 | usb_pm_unlock(udev); | 1194 | usb_pm_unlock(udev); |
1182 | return status; | 1195 | return status; |
1183 | } | 1196 | } |
@@ -1212,6 +1225,26 @@ void usb_autosuspend_device(struct usb_device *udev) | |||
1212 | } | 1225 | } |
1213 | 1226 | ||
1214 | /** | 1227 | /** |
1228 | * usb_try_autosuspend_device - attempt an autosuspend of a USB device and its interfaces | ||
1229 | * @udev: the usb_device to autosuspend | ||
1230 | * | ||
1231 | * This routine should be called when a core subsystem thinks @udev may | ||
1232 | * be ready to autosuspend. | ||
1233 | * | ||
1234 | * @udev's usage counter left unchanged. If it or any of the usage counters | ||
1235 | * for an active interface is greater than 0, or autosuspend is not allowed | ||
1236 | * for any other reason, no autosuspend request will be queued. | ||
1237 | * | ||
1238 | * This routine can run only in process context. | ||
1239 | */ | ||
1240 | void usb_try_autosuspend_device(struct usb_device *udev) | ||
1241 | { | ||
1242 | usb_autopm_do_device(udev, 0); | ||
1243 | // dev_dbg(&udev->dev, "%s: cnt %d\n", | ||
1244 | // __FUNCTION__, udev->pm_usage_cnt); | ||
1245 | } | ||
1246 | |||
1247 | /** | ||
1215 | * usb_autoresume_device - immediately autoresume a USB device and its interfaces | 1248 | * usb_autoresume_device - immediately autoresume a USB device and its interfaces |
1216 | * @udev: the usb_device to autoresume | 1249 | * @udev: the usb_device to autoresume |
1217 | * | 1250 | * |
@@ -1261,7 +1294,7 @@ static int usb_autopm_do_interface(struct usb_interface *intf, | |||
1261 | intf->pm_usage_cnt -= inc_usage_cnt; | 1294 | intf->pm_usage_cnt -= inc_usage_cnt; |
1262 | } else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0) | 1295 | } else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0) |
1263 | queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, | 1296 | queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, |
1264 | USB_AUTOSUSPEND_DELAY); | 1297 | udev->autosuspend_delay); |
1265 | } | 1298 | } |
1266 | usb_pm_unlock(udev); | 1299 | usb_pm_unlock(udev); |
1267 | return status; | 1300 | return status; |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 50c0db15304a..41400743ce2c 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -1287,6 +1287,9 @@ int usb_new_device(struct usb_device *udev) | |||
1287 | if (!try_module_get(THIS_MODULE)) | 1287 | if (!try_module_get(THIS_MODULE)) |
1288 | return -EINVAL; | 1288 | return -EINVAL; |
1289 | 1289 | ||
1290 | /* Determine quirks */ | ||
1291 | usb_detect_quirks(udev); | ||
1292 | |||
1290 | err = usb_get_configuration(udev); | 1293 | err = usb_get_configuration(udev); |
1291 | if (err < 0) { | 1294 | if (err < 0) { |
1292 | dev_err(&udev->dev, "can't read configurations, error %d\n", | 1295 | dev_err(&udev->dev, "can't read configurations, error %d\n", |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 74edaea5665d..2f17468b5c1e 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/timer.h> | 11 | #include <linux/timer.h> |
12 | #include <linux/ctype.h> | 12 | #include <linux/ctype.h> |
13 | #include <linux/device.h> | 13 | #include <linux/device.h> |
14 | #include <linux/usb/quirks.h> | ||
14 | #include <asm/byteorder.h> | 15 | #include <asm/byteorder.h> |
15 | #include <asm/scatterlist.h> | 16 | #include <asm/scatterlist.h> |
16 | 17 | ||
@@ -685,7 +686,10 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid, | |||
685 | 686 | ||
686 | /* Try to read the string descriptor by asking for the maximum | 687 | /* Try to read the string descriptor by asking for the maximum |
687 | * possible number of bytes */ | 688 | * possible number of bytes */ |
688 | rc = usb_get_string(dev, langid, index, buf, 255); | 689 | if (dev->quirks & USB_QUIRK_STRING_FETCH_255) |
690 | rc = -EIO; | ||
691 | else | ||
692 | rc = usb_get_string(dev, langid, index, buf, 255); | ||
689 | 693 | ||
690 | /* If that failed try to read the descriptor length, then | 694 | /* If that failed try to read the descriptor length, then |
691 | * ask for just that many bytes */ | 695 | * ask for just that many bytes */ |
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c new file mode 100644 index 000000000000..0e5c646cb4f6 --- /dev/null +++ b/drivers/usb/core/quirks.c | |||
@@ -0,0 +1,77 @@ | |||
1 | /* | ||
2 | * USB device quirk handling logic and table | ||
3 | * | ||
4 | * Copyright (c) 2007 Oliver Neukum | ||
5 | * Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.de> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the Free | ||
9 | * Software Foundation, version 2. | ||
10 | * | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/usb.h> | ||
15 | #include <linux/usb/quirks.h> | ||
16 | #include "usb.h" | ||
17 | |||
18 | /* List of quirky USB devices. Please keep this list ordered by: | ||
19 | * 1) Vendor ID | ||
20 | * 2) Product ID | ||
21 | * 3) Class ID | ||
22 | * | ||
23 | * as we want specific devices to be overridden first, and only after that, any | ||
24 | * class specific quirks. | ||
25 | * | ||
26 | * Right now the logic aborts if it finds a valid device in the table, we might | ||
27 | * want to change that in the future if it turns out that a whole class of | ||
28 | * devices is broken... | ||
29 | */ | ||
30 | static const struct usb_device_id usb_quirk_list[] = { | ||
31 | /* HP 5300/5370C scanner */ | ||
32 | { USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 }, | ||
33 | |||
34 | /* Elsa MicroLink 56k (V.250) */ | ||
35 | { USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
36 | |||
37 | { } /* terminating entry must be last */ | ||
38 | }; | ||
39 | |||
40 | static void usb_autosuspend_quirk(struct usb_device *udev) | ||
41 | { | ||
42 | #ifdef CONFIG_USB_SUSPEND | ||
43 | /* disable autosuspend, but allow the user to re-enable it via sysfs */ | ||
44 | udev->autosuspend_delay = 0; | ||
45 | #endif | ||
46 | } | ||
47 | |||
48 | static const struct usb_device_id *find_id(struct usb_device *udev) | ||
49 | { | ||
50 | const struct usb_device_id *id = usb_quirk_list; | ||
51 | |||
52 | for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass || | ||
53 | id->driver_info; id++) { | ||
54 | if (usb_match_device(udev, id)) | ||
55 | return id; | ||
56 | } | ||
57 | return NULL; | ||
58 | } | ||
59 | |||
60 | /* | ||
61 | * Detect any quirks the device has, and do any housekeeping for it if needed. | ||
62 | */ | ||
63 | void usb_detect_quirks(struct usb_device *udev) | ||
64 | { | ||
65 | const struct usb_device_id *id = usb_quirk_list; | ||
66 | |||
67 | id = find_id(udev); | ||
68 | if (id) | ||
69 | udev->quirks = (u32)(id->driver_info); | ||
70 | if (udev->quirks) | ||
71 | dev_dbg(&udev->dev, "USB quirks for this device: %x\n", | ||
72 | udev->quirks); | ||
73 | |||
74 | /* do any special quirk handling here if needed */ | ||
75 | if (udev->quirks & USB_QUIRK_NO_AUTOSUSPEND) | ||
76 | usb_autosuspend_quirk(udev); | ||
77 | } | ||
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 0edfbafd702c..311d5df80386 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c | |||
@@ -148,6 +148,75 @@ show_maxchild(struct device *dev, struct device_attribute *attr, char *buf) | |||
148 | } | 148 | } |
149 | static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL); | 149 | static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL); |
150 | 150 | ||
151 | static ssize_t | ||
152 | show_quirks(struct device *dev, struct device_attribute *attr, char *buf) | ||
153 | { | ||
154 | struct usb_device *udev; | ||
155 | |||
156 | udev = to_usb_device(dev); | ||
157 | return sprintf(buf, "0x%x\n", udev->quirks); | ||
158 | } | ||
159 | static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL); | ||
160 | |||
161 | #ifdef CONFIG_USB_SUSPEND | ||
162 | |||
163 | static ssize_t | ||
164 | show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf) | ||
165 | { | ||
166 | struct usb_device *udev = to_usb_device(dev); | ||
167 | |||
168 | return sprintf(buf, "%u\n", udev->autosuspend_delay / HZ); | ||
169 | } | ||
170 | |||
171 | static ssize_t | ||
172 | set_autosuspend(struct device *dev, struct device_attribute *attr, | ||
173 | const char *buf, size_t count) | ||
174 | { | ||
175 | struct usb_device *udev = to_usb_device(dev); | ||
176 | unsigned value, old; | ||
177 | |||
178 | if (sscanf(buf, "%u", &value) != 1 || value >= INT_MAX/HZ) | ||
179 | return -EINVAL; | ||
180 | value *= HZ; | ||
181 | |||
182 | old = udev->autosuspend_delay; | ||
183 | udev->autosuspend_delay = value; | ||
184 | if (value > 0 && old == 0) | ||
185 | usb_try_autosuspend_device(udev); | ||
186 | |||
187 | return count; | ||
188 | } | ||
189 | |||
190 | static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR, | ||
191 | show_autosuspend, set_autosuspend); | ||
192 | |||
193 | static char power_group[] = "power"; | ||
194 | |||
195 | static int add_power_attributes(struct device *dev) | ||
196 | { | ||
197 | int rc = 0; | ||
198 | |||
199 | if (is_usb_device(dev)) | ||
200 | rc = sysfs_add_file_to_group(&dev->kobj, | ||
201 | &dev_attr_autosuspend.attr, | ||
202 | power_group); | ||
203 | return rc; | ||
204 | } | ||
205 | |||
206 | static void remove_power_attributes(struct device *dev) | ||
207 | { | ||
208 | sysfs_remove_file_from_group(&dev->kobj, | ||
209 | &dev_attr_autosuspend.attr, | ||
210 | power_group); | ||
211 | } | ||
212 | |||
213 | #else | ||
214 | |||
215 | #define add_power_attributes(dev) 0 | ||
216 | #define remove_power_attributes(dev) do {} while (0) | ||
217 | |||
218 | #endif /* CONFIG_USB_SUSPEND */ | ||
219 | |||
151 | /* Descriptor fields */ | 220 | /* Descriptor fields */ |
152 | #define usb_descriptor_attr_le16(field, format_string) \ | 221 | #define usb_descriptor_attr_le16(field, format_string) \ |
153 | static ssize_t \ | 222 | static ssize_t \ |
@@ -204,6 +273,7 @@ static struct attribute *dev_attrs[] = { | |||
204 | &dev_attr_devnum.attr, | 273 | &dev_attr_devnum.attr, |
205 | &dev_attr_version.attr, | 274 | &dev_attr_version.attr, |
206 | &dev_attr_maxchild.attr, | 275 | &dev_attr_maxchild.attr, |
276 | &dev_attr_quirks.attr, | ||
207 | NULL, | 277 | NULL, |
208 | }; | 278 | }; |
209 | static struct attribute_group dev_attr_grp = { | 279 | static struct attribute_group dev_attr_grp = { |
@@ -219,6 +289,10 @@ int usb_create_sysfs_dev_files(struct usb_device *udev) | |||
219 | if (retval) | 289 | if (retval) |
220 | return retval; | 290 | return retval; |
221 | 291 | ||
292 | retval = add_power_attributes(dev); | ||
293 | if (retval) | ||
294 | goto error; | ||
295 | |||
222 | if (udev->manufacturer) { | 296 | if (udev->manufacturer) { |
223 | retval = device_create_file(dev, &dev_attr_manufacturer); | 297 | retval = device_create_file(dev, &dev_attr_manufacturer); |
224 | if (retval) | 298 | if (retval) |
@@ -239,10 +313,7 @@ int usb_create_sysfs_dev_files(struct usb_device *udev) | |||
239 | goto error; | 313 | goto error; |
240 | return 0; | 314 | return 0; |
241 | error: | 315 | error: |
242 | usb_remove_ep_files(&udev->ep0); | 316 | usb_remove_sysfs_dev_files(udev); |
243 | device_remove_file(dev, &dev_attr_manufacturer); | ||
244 | device_remove_file(dev, &dev_attr_product); | ||
245 | device_remove_file(dev, &dev_attr_serial); | ||
246 | return retval; | 317 | return retval; |
247 | } | 318 | } |
248 | 319 | ||
@@ -251,14 +322,11 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev) | |||
251 | struct device *dev = &udev->dev; | 322 | struct device *dev = &udev->dev; |
252 | 323 | ||
253 | usb_remove_ep_files(&udev->ep0); | 324 | usb_remove_ep_files(&udev->ep0); |
325 | device_remove_file(dev, &dev_attr_manufacturer); | ||
326 | device_remove_file(dev, &dev_attr_product); | ||
327 | device_remove_file(dev, &dev_attr_serial); | ||
328 | remove_power_attributes(dev); | ||
254 | sysfs_remove_group(&dev->kobj, &dev_attr_grp); | 329 | sysfs_remove_group(&dev->kobj, &dev_attr_grp); |
255 | |||
256 | if (udev->manufacturer) | ||
257 | device_remove_file(dev, &dev_attr_manufacturer); | ||
258 | if (udev->product) | ||
259 | device_remove_file(dev, &dev_attr_product); | ||
260 | if (udev->serial) | ||
261 | device_remove_file(dev, &dev_attr_serial); | ||
262 | } | 330 | } |
263 | 331 | ||
264 | /* Interface fields */ | 332 | /* Interface fields */ |
@@ -362,33 +430,28 @@ static inline void usb_remove_intf_ep_files(struct usb_interface *intf) | |||
362 | 430 | ||
363 | int usb_create_sysfs_intf_files(struct usb_interface *intf) | 431 | int usb_create_sysfs_intf_files(struct usb_interface *intf) |
364 | { | 432 | { |
433 | struct device *dev = &intf->dev; | ||
365 | struct usb_device *udev = interface_to_usbdev(intf); | 434 | struct usb_device *udev = interface_to_usbdev(intf); |
366 | struct usb_host_interface *alt = intf->cur_altsetting; | 435 | struct usb_host_interface *alt = intf->cur_altsetting; |
367 | int retval; | 436 | int retval; |
368 | 437 | ||
369 | retval = sysfs_create_group(&intf->dev.kobj, &intf_attr_grp); | 438 | retval = sysfs_create_group(&dev->kobj, &intf_attr_grp); |
370 | if (retval) | 439 | if (retval) |
371 | goto error; | 440 | return retval; |
372 | 441 | ||
373 | if (alt->string == NULL) | 442 | if (alt->string == NULL) |
374 | alt->string = usb_cache_string(udev, alt->desc.iInterface); | 443 | alt->string = usb_cache_string(udev, alt->desc.iInterface); |
375 | if (alt->string) | 444 | if (alt->string) |
376 | retval = device_create_file(&intf->dev, &dev_attr_interface); | 445 | retval = device_create_file(dev, &dev_attr_interface); |
377 | usb_create_intf_ep_files(intf, udev); | 446 | usb_create_intf_ep_files(intf, udev); |
378 | return 0; | 447 | return 0; |
379 | error: | ||
380 | if (alt->string) | ||
381 | device_remove_file(&intf->dev, &dev_attr_interface); | ||
382 | sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp); | ||
383 | usb_remove_intf_ep_files(intf); | ||
384 | return retval; | ||
385 | } | 448 | } |
386 | 449 | ||
387 | void usb_remove_sysfs_intf_files(struct usb_interface *intf) | 450 | void usb_remove_sysfs_intf_files(struct usb_interface *intf) |
388 | { | 451 | { |
389 | usb_remove_intf_ep_files(intf); | 452 | struct device *dev = &intf->dev; |
390 | sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp); | ||
391 | 453 | ||
392 | if (intf->cur_altsetting->string) | 454 | usb_remove_intf_ep_files(intf); |
393 | device_remove_file(&intf->dev, &dev_attr_interface); | 455 | device_remove_file(dev, &dev_attr_interface); |
456 | sysfs_remove_group(&dev->kobj, &intf_attr_grp); | ||
394 | } | 457 | } |
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 3db721cd557a..54b42ce311c1 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -22,6 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/moduleparam.h> | ||
25 | #include <linux/string.h> | 26 | #include <linux/string.h> |
26 | #include <linux/bitops.h> | 27 | #include <linux/bitops.h> |
27 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
@@ -50,6 +51,16 @@ static int nousb; /* Disable USB when built into kernel image */ | |||
50 | 51 | ||
51 | struct workqueue_struct *ksuspend_usb_wq; /* For autosuspend */ | 52 | struct workqueue_struct *ksuspend_usb_wq; /* For autosuspend */ |
52 | 53 | ||
54 | #ifdef CONFIG_USB_SUSPEND | ||
55 | static int usb_autosuspend_delay = 2; /* Default delay value, | ||
56 | * in seconds */ | ||
57 | module_param_named(autosuspend, usb_autosuspend_delay, uint, 0644); | ||
58 | MODULE_PARM_DESC(autosuspend, "default autosuspend delay"); | ||
59 | |||
60 | #else | ||
61 | #define usb_autosuspend_delay 0 | ||
62 | #endif | ||
63 | |||
53 | 64 | ||
54 | /** | 65 | /** |
55 | * usb_ifnum_to_if - get the interface object with a given interface number | 66 | * 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 | #ifdef CONFIG_PM | 317 | #ifdef CONFIG_PM |
307 | mutex_init(&dev->pm_mutex); | 318 | mutex_init(&dev->pm_mutex); |
308 | INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work); | 319 | INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work); |
320 | dev->autosuspend_delay = usb_autosuspend_delay * HZ; | ||
309 | #endif | 321 | #endif |
310 | return dev; | 322 | return dev; |
311 | } | 323 | } |
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 17830a81be14..08b5a04e3755 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
@@ -13,6 +13,7 @@ extern void usb_disable_interface (struct usb_device *dev, | |||
13 | struct usb_interface *intf); | 13 | struct usb_interface *intf); |
14 | extern void usb_release_interface_cache(struct kref *ref); | 14 | extern void usb_release_interface_cache(struct kref *ref); |
15 | extern void usb_disable_device (struct usb_device *dev, int skip_ep0); | 15 | extern void usb_disable_device (struct usb_device *dev, int skip_ep0); |
16 | extern void usb_detect_quirks(struct usb_device *udev); | ||
16 | 17 | ||
17 | extern int usb_get_device_descriptor(struct usb_device *dev, | 18 | extern int usb_get_device_descriptor(struct usb_device *dev, |
18 | unsigned int size); | 19 | unsigned int size); |
@@ -21,6 +22,8 @@ extern int usb_set_configuration(struct usb_device *dev, int configuration); | |||
21 | 22 | ||
22 | extern void usb_kick_khubd(struct usb_device *dev); | 23 | extern void usb_kick_khubd(struct usb_device *dev); |
23 | extern void usb_resume_root_hub(struct usb_device *dev); | 24 | extern void usb_resume_root_hub(struct usb_device *dev); |
25 | extern int usb_match_device(struct usb_device *dev, | ||
26 | const struct usb_device_id *id); | ||
24 | 27 | ||
25 | extern int usb_hub_init(void); | 28 | extern int usb_hub_init(void); |
26 | extern void usb_hub_cleanup(void); | 29 | extern void usb_hub_cleanup(void); |
@@ -62,14 +65,14 @@ static inline void usb_pm_unlock(struct usb_device *udev) {} | |||
62 | 65 | ||
63 | #ifdef CONFIG_USB_SUSPEND | 66 | #ifdef CONFIG_USB_SUSPEND |
64 | 67 | ||
65 | #define USB_AUTOSUSPEND_DELAY (HZ*2) | ||
66 | |||
67 | extern void usb_autosuspend_device(struct usb_device *udev); | 68 | extern void usb_autosuspend_device(struct usb_device *udev); |
69 | extern void usb_try_autosuspend_device(struct usb_device *udev); | ||
68 | extern int usb_autoresume_device(struct usb_device *udev); | 70 | extern int usb_autoresume_device(struct usb_device *udev); |
69 | 71 | ||
70 | #else | 72 | #else |
71 | 73 | ||
72 | #define usb_autosuspend_device(udev) do {} while (0) | 74 | #define usb_autosuspend_device(udev) do {} while (0) |
75 | #define usb_try_autosuspend_device(udev) do {} while (0) | ||
73 | static inline int usb_autoresume_device(struct usb_device *udev) | 76 | static inline int usb_autoresume_device(struct usb_device *udev) |
74 | { | 77 | { |
75 | return 0; | 78 | return 0; |
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 34296e79edcf..188c74a95216 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c | |||
@@ -553,6 +553,7 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb) | |||
553 | { | 553 | { |
554 | struct kiocb_priv *priv = iocb->private; | 554 | struct kiocb_priv *priv = iocb->private; |
555 | ssize_t len, total; | 555 | ssize_t len, total; |
556 | void *to_copy; | ||
556 | int i; | 557 | int i; |
557 | 558 | ||
558 | /* we "retry" to get the right mm context for this: */ | 559 | /* 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 | /* copy stuff into user buffers */ | 561 | /* copy stuff into user buffers */ |
561 | total = priv->actual; | 562 | total = priv->actual; |
562 | len = 0; | 563 | len = 0; |
564 | to_copy = priv->buf; | ||
563 | for (i=0; i < priv->nr_segs; i++) { | 565 | for (i=0; i < priv->nr_segs; i++) { |
564 | ssize_t this = min((ssize_t)(priv->iv[i].iov_len), total); | 566 | ssize_t this = min((ssize_t)(priv->iv[i].iov_len), total); |
565 | 567 | ||
566 | if (copy_to_user(priv->iv[i].iov_base, priv->buf, this)) { | 568 | if (copy_to_user(priv->iv[i].iov_base, to_copy, this)) { |
567 | if (len == 0) | 569 | if (len == 0) |
568 | len = -EFAULT; | 570 | len = -EFAULT; |
569 | break; | 571 | break; |
@@ -571,6 +573,7 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb) | |||
571 | 573 | ||
572 | total -= this; | 574 | total -= this; |
573 | len += this; | 575 | len += this; |
576 | to_copy += this; | ||
574 | if (total == 0) | 577 | if (total == 0) |
575 | break; | 578 | break; |
576 | } | 579 | } |
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 5d6c06bc4524..8d24d3dc0a61 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c | |||
@@ -196,7 +196,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) | |||
196 | struct uhci_td *td = list_entry(urbp->td_list.next, | 196 | struct uhci_td *td = list_entry(urbp->td_list.next, |
197 | struct uhci_td, list); | 197 | struct uhci_td, list); |
198 | 198 | ||
199 | if (cpu_to_le32(td->dma_handle) != (element & ~UHCI_PTR_BITS)) | 199 | if (element != LINK_TO_TD(td)) |
200 | out += sprintf(out, "%*s Element != First TD\n", | 200 | out += sprintf(out, "%*s Element != First TD\n", |
201 | space, ""); | 201 | space, ""); |
202 | i = nurbs = 0; | 202 | i = nurbs = 0; |
@@ -220,16 +220,6 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) | |||
220 | return out - buf; | 220 | return out - buf; |
221 | } | 221 | } |
222 | 222 | ||
223 | static const char * const qh_names[] = { | ||
224 | "skel_unlink_qh", "skel_iso_qh", | ||
225 | "skel_int128_qh", "skel_int64_qh", | ||
226 | "skel_int32_qh", "skel_int16_qh", | ||
227 | "skel_int8_qh", "skel_int4_qh", | ||
228 | "skel_int2_qh", "skel_int1_qh", | ||
229 | "skel_ls_control_qh", "skel_fs_control_qh", | ||
230 | "skel_bulk_qh", "skel_term_qh" | ||
231 | }; | ||
232 | |||
233 | static int uhci_show_sc(int port, unsigned short status, char *buf, int len) | 223 | static int uhci_show_sc(int port, unsigned short status, char *buf, int len) |
234 | { | 224 | { |
235 | char *out = buf; | 225 | char *out = buf; |
@@ -352,6 +342,12 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) | |||
352 | struct uhci_td *td; | 342 | struct uhci_td *td; |
353 | struct list_head *tmp, *head; | 343 | struct list_head *tmp, *head; |
354 | int nframes, nerrs; | 344 | int nframes, nerrs; |
345 | __le32 link; | ||
346 | |||
347 | static const char * const qh_names[] = { | ||
348 | "unlink", "iso", "int128", "int64", "int32", "int16", | ||
349 | "int8", "int4", "int2", "async", "term" | ||
350 | }; | ||
355 | 351 | ||
356 | out += uhci_show_root_hub_state(uhci, out, len - (out - buf)); | 352 | out += uhci_show_root_hub_state(uhci, out, len - (out - buf)); |
357 | out += sprintf(out, "HC status\n"); | 353 | out += sprintf(out, "HC status\n"); |
@@ -374,7 +370,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) | |||
374 | nframes = 10; | 370 | nframes = 10; |
375 | nerrs = 0; | 371 | nerrs = 0; |
376 | for (i = 0; i < UHCI_NUMFRAMES; ++i) { | 372 | for (i = 0; i < UHCI_NUMFRAMES; ++i) { |
377 | __le32 link, qh_dma; | 373 | __le32 qh_dma; |
378 | 374 | ||
379 | j = 0; | 375 | j = 0; |
380 | td = uhci->frame_cpu[i]; | 376 | td = uhci->frame_cpu[i]; |
@@ -393,7 +389,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) | |||
393 | do { | 389 | do { |
394 | td = list_entry(tmp, struct uhci_td, fl_list); | 390 | td = list_entry(tmp, struct uhci_td, fl_list); |
395 | tmp = tmp->next; | 391 | tmp = tmp->next; |
396 | if (cpu_to_le32(td->dma_handle) != link) { | 392 | if (link != LINK_TO_TD(td)) { |
397 | if (nframes > 0) | 393 | if (nframes > 0) |
398 | out += sprintf(out, " link does " | 394 | out += sprintf(out, " link does " |
399 | "not match list entry!\n"); | 395 | "not match list entry!\n"); |
@@ -430,23 +426,21 @@ check_link: | |||
430 | 426 | ||
431 | for (i = 0; i < UHCI_NUM_SKELQH; ++i) { | 427 | for (i = 0; i < UHCI_NUM_SKELQH; ++i) { |
432 | int cnt = 0; | 428 | int cnt = 0; |
429 | __le32 fsbr_link = 0; | ||
433 | 430 | ||
434 | qh = uhci->skelqh[i]; | 431 | qh = uhci->skelqh[i]; |
435 | out += sprintf(out, "- %s\n", qh_names[i]); \ | 432 | out += sprintf(out, "- skel_%s_qh\n", qh_names[i]); \ |
436 | out += uhci_show_qh(qh, out, len - (out - buf), 4); | 433 | out += uhci_show_qh(qh, out, len - (out - buf), 4); |
437 | 434 | ||
438 | /* Last QH is the Terminating QH, it's different */ | 435 | /* Last QH is the Terminating QH, it's different */ |
439 | if (i == UHCI_NUM_SKELQH - 1) { | 436 | if (i == SKEL_TERM) { |
440 | if (qh->link != UHCI_PTR_TERM) | 437 | if (qh_element(qh) != LINK_TO_TD(uhci->term_td)) |
441 | out += sprintf(out, " bandwidth reclamation on!\n"); | ||
442 | |||
443 | if (qh_element(qh) != cpu_to_le32(uhci->term_td->dma_handle)) | ||
444 | out += sprintf(out, " skel_term_qh element is not set to term_td!\n"); | 438 | out += sprintf(out, " skel_term_qh element is not set to term_td!\n"); |
445 | 439 | if (link == LINK_TO_QH(uhci->skel_term_qh)) | |
440 | goto check_qh_link; | ||
446 | continue; | 441 | continue; |
447 | } | 442 | } |
448 | 443 | ||
449 | j = (i < 9) ? 9 : i+1; /* Next skeleton */ | ||
450 | head = &qh->node; | 444 | head = &qh->node; |
451 | tmp = head->next; | 445 | tmp = head->next; |
452 | 446 | ||
@@ -456,15 +450,26 @@ check_link: | |||
456 | if (++cnt <= 10) | 450 | if (++cnt <= 10) |
457 | out += uhci_show_qh(qh, out, | 451 | out += uhci_show_qh(qh, out, |
458 | len - (out - buf), 4); | 452 | len - (out - buf), 4); |
453 | if (!fsbr_link && qh->skel >= SKEL_FSBR) | ||
454 | fsbr_link = LINK_TO_QH(qh); | ||
459 | } | 455 | } |
460 | if ((cnt -= 10) > 0) | 456 | if ((cnt -= 10) > 0) |
461 | out += sprintf(out, " Skipped %d QHs\n", cnt); | 457 | out += sprintf(out, " Skipped %d QHs\n", cnt); |
462 | 458 | ||
463 | if (i > 1 && i < UHCI_NUM_SKELQH - 1) { | 459 | link = UHCI_PTR_TERM; |
464 | if (qh->link != | 460 | if (i <= SKEL_ISO) |
465 | (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH)) | 461 | ; |
466 | out += sprintf(out, " last QH not linked to next skeleton!\n"); | 462 | else if (i < SKEL_ASYNC) |
467 | } | 463 | link = LINK_TO_QH(uhci->skel_async_qh); |
464 | else if (!uhci->fsbr_is_on) | ||
465 | ; | ||
466 | else if (fsbr_link) | ||
467 | link = fsbr_link; | ||
468 | else | ||
469 | link = LINK_TO_QH(uhci->skel_term_qh); | ||
470 | check_qh_link: | ||
471 | if (qh->link != link) | ||
472 | out += sprintf(out, " last QH not linked to next skeleton!\n"); | ||
468 | } | 473 | } |
469 | 474 | ||
470 | return out - buf; | 475 | return out - buf; |
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index ded4df30a631..44da4334f1d6 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -13,7 +13,7 @@ | |||
13 | * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface | 13 | * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface |
14 | * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). | 14 | * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). |
15 | * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) | 15 | * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) |
16 | * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu | 16 | * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu |
17 | * | 17 | * |
18 | * Intel documents this fairly well, and as far as I know there | 18 | * Intel documents this fairly well, and as far as I know there |
19 | * are no royalties or anything like that, but even so there are | 19 | * 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 | * interrupt QHs, which will help spread out bandwidth utilization. | 107 | * interrupt QHs, which will help spread out bandwidth utilization. |
108 | * | 108 | * |
109 | * ffs (Find First bit Set) does exactly what we need: | 109 | * ffs (Find First bit Set) does exactly what we need: |
110 | * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[8], | 110 | * 1,3,5,... => ffs = 0 => use period-2 QH = skelqh[8], |
111 | * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc. | 111 | * 2,6,10,... => ffs = 1 => use period-4 QH = skelqh[7], etc. |
112 | * ffs >= 7 => not on any high-period queue, so use | 112 | * ffs >= 7 => not on any high-period queue, so use |
113 | * skel_int1_qh = skelqh[9]. | 113 | * period-1 QH = skelqh[9]. |
114 | * Add in UHCI_NUMFRAMES to insure at least one bit is set. | 114 | * Add in UHCI_NUMFRAMES to insure at least one bit is set. |
115 | */ | 115 | */ |
116 | skelnum = 8 - (int) __ffs(frame | UHCI_NUMFRAMES); | 116 | skelnum = 8 - (int) __ffs(frame | UHCI_NUMFRAMES); |
117 | if (skelnum <= 1) | 117 | if (skelnum <= 1) |
118 | skelnum = 9; | 118 | skelnum = 9; |
119 | return UHCI_PTR_QH | cpu_to_le32(uhci->skelqh[skelnum]->dma_handle); | 119 | return LINK_TO_QH(uhci->skelqh[skelnum]); |
120 | } | 120 | } |
121 | 121 | ||
122 | #include "uhci-debug.c" | 122 | #include "uhci-debug.c" |
@@ -540,16 +540,18 @@ static void uhci_shutdown(struct pci_dev *pdev) | |||
540 | * | 540 | * |
541 | * The hardware doesn't really know any difference | 541 | * The hardware doesn't really know any difference |
542 | * in the queues, but the order does matter for the | 542 | * in the queues, but the order does matter for the |
543 | * protocols higher up. The order is: | 543 | * protocols higher up. The order in which the queues |
544 | * are encountered by the hardware is: | ||
544 | * | 545 | * |
545 | * - any isochronous events handled before any | 546 | * - All isochronous events are handled before any |
546 | * of the queues. We don't do that here, because | 547 | * of the queues. We don't do that here, because |
547 | * we'll create the actual TD entries on demand. | 548 | * we'll create the actual TD entries on demand. |
548 | * - The first queue is the interrupt queue. | 549 | * - The first queue is the high-period interrupt queue. |
549 | * - The second queue is the control queue, split into low- and full-speed | 550 | * - The second queue is the period-1 interrupt and async |
550 | * - The third queue is bulk queue. | 551 | * (low-speed control, full-speed control, then bulk) queue. |
551 | * - The fourth queue is the bandwidth reclamation queue, which loops back | 552 | * - The third queue is the terminating bandwidth reclamation queue, |
552 | * to the full-speed control queue. | 553 | * which contains no members, loops back to itself, and is present |
554 | * only when FSBR is on and there are no full-speed control or bulk QHs. | ||
553 | */ | 555 | */ |
554 | static int uhci_start(struct usb_hcd *hcd) | 556 | static int uhci_start(struct usb_hcd *hcd) |
555 | { | 557 | { |
@@ -626,34 +628,18 @@ static int uhci_start(struct usb_hcd *hcd) | |||
626 | } | 628 | } |
627 | 629 | ||
628 | /* | 630 | /* |
629 | * 8 Interrupt queues; link all higher int queues to int1, | 631 | * 8 Interrupt queues; link all higher int queues to int1 = async |
630 | * then link int1 to control and control to bulk | ||
631 | */ | 632 | */ |
632 | uhci->skel_int128_qh->link = | 633 | for (i = SKEL_ISO + 1; i < SKEL_ASYNC; ++i) |
633 | uhci->skel_int64_qh->link = | 634 | uhci->skelqh[i]->link = LINK_TO_QH(uhci->skel_async_qh); |
634 | uhci->skel_int32_qh->link = | 635 | uhci->skel_async_qh->link = uhci->skel_term_qh->link = UHCI_PTR_TERM; |
635 | uhci->skel_int16_qh->link = | ||
636 | uhci->skel_int8_qh->link = | ||
637 | uhci->skel_int4_qh->link = | ||
638 | uhci->skel_int2_qh->link = UHCI_PTR_QH | | ||
639 | cpu_to_le32(uhci->skel_int1_qh->dma_handle); | ||
640 | |||
641 | uhci->skel_int1_qh->link = UHCI_PTR_QH | | ||
642 | cpu_to_le32(uhci->skel_ls_control_qh->dma_handle); | ||
643 | uhci->skel_ls_control_qh->link = UHCI_PTR_QH | | ||
644 | cpu_to_le32(uhci->skel_fs_control_qh->dma_handle); | ||
645 | uhci->skel_fs_control_qh->link = UHCI_PTR_QH | | ||
646 | cpu_to_le32(uhci->skel_bulk_qh->dma_handle); | ||
647 | uhci->skel_bulk_qh->link = UHCI_PTR_QH | | ||
648 | cpu_to_le32(uhci->skel_term_qh->dma_handle); | ||
649 | 636 | ||
650 | /* This dummy TD is to work around a bug in Intel PIIX controllers */ | 637 | /* This dummy TD is to work around a bug in Intel PIIX controllers */ |
651 | uhci_fill_td(uhci->term_td, 0, uhci_explen(0) | | 638 | uhci_fill_td(uhci->term_td, 0, uhci_explen(0) | |
652 | (0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0); | 639 | (0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0); |
653 | uhci->term_td->link = cpu_to_le32(uhci->term_td->dma_handle); | 640 | uhci->term_td->link = UHCI_PTR_TERM; |
654 | 641 | uhci->skel_async_qh->element = uhci->skel_term_qh->element = | |
655 | uhci->skel_term_qh->link = UHCI_PTR_TERM; | 642 | LINK_TO_TD(uhci->term_td); |
656 | uhci->skel_term_qh->element = cpu_to_le32(uhci->term_td->dma_handle); | ||
657 | 643 | ||
658 | /* | 644 | /* |
659 | * Fill the frame list: make all entries point to the proper | 645 | * Fill the frame list: make all entries point to the proper |
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 74469b5bcb61..1b3d23406ac4 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h | |||
@@ -129,11 +129,12 @@ struct uhci_qh { | |||
129 | __le32 element; /* Queue element (TD) pointer */ | 129 | __le32 element; /* Queue element (TD) pointer */ |
130 | 130 | ||
131 | /* Software fields */ | 131 | /* Software fields */ |
132 | dma_addr_t dma_handle; | ||
133 | |||
132 | struct list_head node; /* Node in the list of QHs */ | 134 | struct list_head node; /* Node in the list of QHs */ |
133 | struct usb_host_endpoint *hep; /* Endpoint information */ | 135 | struct usb_host_endpoint *hep; /* Endpoint information */ |
134 | struct usb_device *udev; | 136 | struct usb_device *udev; |
135 | struct list_head queue; /* Queue of urbps for this QH */ | 137 | struct list_head queue; /* Queue of urbps for this QH */ |
136 | struct uhci_qh *skel; /* Skeleton for this QH */ | ||
137 | struct uhci_td *dummy_td; /* Dummy TD to end the queue */ | 138 | struct uhci_td *dummy_td; /* Dummy TD to end the queue */ |
138 | struct uhci_td *post_td; /* Last TD completed */ | 139 | struct uhci_td *post_td; /* Last TD completed */ |
139 | 140 | ||
@@ -149,8 +150,7 @@ struct uhci_qh { | |||
149 | 150 | ||
150 | int state; /* QH_STATE_xxx; see above */ | 151 | int state; /* QH_STATE_xxx; see above */ |
151 | int type; /* Queue type (control, bulk, etc) */ | 152 | int type; /* Queue type (control, bulk, etc) */ |
152 | 153 | int skel; /* Skeleton queue number */ | |
153 | dma_addr_t dma_handle; | ||
154 | 154 | ||
155 | unsigned int initial_toggle:1; /* Endpoint's current toggle value */ | 155 | unsigned int initial_toggle:1; /* Endpoint's current toggle value */ |
156 | unsigned int needs_fixup:1; /* Must fix the TD toggle values */ | 156 | 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 | return element; | 171 | return element; |
172 | } | 172 | } |
173 | 173 | ||
174 | #define LINK_TO_QH(qh) (UHCI_PTR_QH | cpu_to_le32((qh)->dma_handle)) | ||
175 | |||
174 | 176 | ||
175 | /* | 177 | /* |
176 | * Transfer Descriptors | 178 | * Transfer Descriptors |
@@ -264,6 +266,8 @@ static inline u32 td_status(struct uhci_td *td) { | |||
264 | return le32_to_cpu(status); | 266 | return le32_to_cpu(status); |
265 | } | 267 | } |
266 | 268 | ||
269 | #define LINK_TO_TD(td) (cpu_to_le32((td)->dma_handle)) | ||
270 | |||
267 | 271 | ||
268 | /* | 272 | /* |
269 | * Skeleton Queue Headers | 273 | * Skeleton Queue Headers |
@@ -272,12 +276,13 @@ static inline u32 td_status(struct uhci_td *td) { | |||
272 | /* | 276 | /* |
273 | * The UHCI driver uses QHs with Interrupt, Control and Bulk URBs for | 277 | * The UHCI driver uses QHs with Interrupt, Control and Bulk URBs for |
274 | * automatic queuing. To make it easy to insert entries into the schedule, | 278 | * automatic queuing. To make it easy to insert entries into the schedule, |
275 | * we have a skeleton of QHs for each predefined Interrupt latency, | 279 | * we have a skeleton of QHs for each predefined Interrupt latency. |
276 | * low-speed control, full-speed control, bulk, and terminating QH | 280 | * Asynchronous QHs (low-speed control, full-speed control, and bulk) |
277 | * (see explanation for the terminating QH below). | 281 | * go onto the period-1 interrupt list, since they all get accessed on |
282 | * every frame. | ||
278 | * | 283 | * |
279 | * When we want to add a new QH, we add it to the end of the list for the | 284 | * When we want to add a new QH, we add it to the list starting from the |
280 | * skeleton QH. For instance, the schedule list can look like this: | 285 | * appropriate skeleton QH. For instance, the schedule can look like this: |
281 | * | 286 | * |
282 | * skel int128 QH | 287 | * skel int128 QH |
283 | * dev 1 interrupt QH | 288 | * dev 1 interrupt QH |
@@ -285,50 +290,47 @@ static inline u32 td_status(struct uhci_td *td) { | |||
285 | * skel int64 QH | 290 | * skel int64 QH |
286 | * skel int32 QH | 291 | * skel int32 QH |
287 | * ... | 292 | * ... |
288 | * skel int1 QH | 293 | * skel int1 + async QH |
289 | * skel low-speed control QH | 294 | * dev 5 low-speed control QH |
290 | * dev 5 control QH | ||
291 | * skel full-speed control QH | ||
292 | * skel bulk QH | ||
293 | * dev 1 bulk QH | 295 | * dev 1 bulk QH |
294 | * dev 2 bulk QH | 296 | * dev 2 bulk QH |
295 | * skel terminating QH | ||
296 | * | 297 | * |
297 | * The terminating QH is used for 2 reasons: | 298 | * There is a special terminating QH used to keep full-speed bandwidth |
298 | * - To place a terminating TD which is used to workaround a PIIX bug | 299 | * reclamation active when no full-speed control or bulk QHs are linked |
299 | * (see Intel errata for explanation), and | 300 | * into the schedule. It has an inactive TD (to work around a PIIX bug, |
300 | * - To loop back to the full-speed control queue for full-speed bandwidth | 301 | * see the Intel errata) and it points back to itself. |
301 | * reclamation. | ||
302 | * | 302 | * |
303 | * There's a special skeleton QH for Isochronous QHs. It never appears | 303 | * There's a special skeleton QH for Isochronous QHs which never appears |
304 | * on the schedule, and Isochronous TDs go on the schedule before the | 304 | * on the schedule. Isochronous TDs go on the schedule before the |
305 | * the skeleton QHs. The hardware accesses them directly rather than | 305 | * the skeleton QHs. The hardware accesses them directly rather than |
306 | * through their QH, which is used only for bookkeeping purposes. | 306 | * through their QH, which is used only for bookkeeping purposes. |
307 | * While the UHCI spec doesn't forbid the use of QHs for Isochronous, | 307 | * While the UHCI spec doesn't forbid the use of QHs for Isochronous, |
308 | * it doesn't use them either. And the spec says that queues never | 308 | * it doesn't use them either. And the spec says that queues never |
309 | * advance on an error completion status, which makes them totally | 309 | * advance on an error completion status, which makes them totally |
310 | * unsuitable for Isochronous transfers. | 310 | * unsuitable for Isochronous transfers. |
311 | * | ||
312 | * There's also a special skeleton QH used for QHs which are in the process | ||
313 | * of unlinking and so may still be in use by the hardware. It too never | ||
314 | * appears on the schedule. | ||
311 | */ | 315 | */ |
312 | 316 | ||
313 | #define UHCI_NUM_SKELQH 14 | 317 | #define UHCI_NUM_SKELQH 11 |
314 | #define skel_unlink_qh skelqh[0] | 318 | #define SKEL_UNLINK 0 |
315 | #define skel_iso_qh skelqh[1] | 319 | #define skel_unlink_qh skelqh[SKEL_UNLINK] |
316 | #define skel_int128_qh skelqh[2] | 320 | #define SKEL_ISO 1 |
317 | #define skel_int64_qh skelqh[3] | 321 | #define skel_iso_qh skelqh[SKEL_ISO] |
318 | #define skel_int32_qh skelqh[4] | 322 | /* int128, int64, ..., int1 = 2, 3, ..., 9 */ |
319 | #define skel_int16_qh skelqh[5] | 323 | #define SKEL_INDEX(exponent) (9 - exponent) |
320 | #define skel_int8_qh skelqh[6] | 324 | #define SKEL_ASYNC 9 |
321 | #define skel_int4_qh skelqh[7] | 325 | #define skel_async_qh skelqh[SKEL_ASYNC] |
322 | #define skel_int2_qh skelqh[8] | 326 | #define SKEL_TERM 10 |
323 | #define skel_int1_qh skelqh[9] | 327 | #define skel_term_qh skelqh[SKEL_TERM] |
324 | #define skel_ls_control_qh skelqh[10] | 328 | |
325 | #define skel_fs_control_qh skelqh[11] | 329 | /* The following entries refer to sublists of skel_async_qh */ |
326 | #define skel_bulk_qh skelqh[12] | 330 | #define SKEL_LS_CONTROL 20 |
327 | #define skel_term_qh skelqh[13] | 331 | #define SKEL_FS_CONTROL 21 |
328 | 332 | #define SKEL_FSBR SKEL_FS_CONTROL | |
329 | /* Find the skelqh entry corresponding to an interval exponent */ | 333 | #define SKEL_BULK 22 |
330 | #define UHCI_SKEL_INDEX(exponent) (9 - exponent) | ||
331 | |||
332 | 334 | ||
333 | /* | 335 | /* |
334 | * The UHCI controller and root hub | 336 | * The UHCI controller and root hub |
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 68e66b33e726..f4ebdb3e488f 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
@@ -13,7 +13,7 @@ | |||
13 | * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface | 13 | * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface |
14 | * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). | 14 | * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). |
15 | * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) | 15 | * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) |
16 | * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu | 16 | * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu |
17 | */ | 17 | */ |
18 | 18 | ||
19 | 19 | ||
@@ -45,15 +45,43 @@ static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci) | |||
45 | */ | 45 | */ |
46 | static void uhci_fsbr_on(struct uhci_hcd *uhci) | 46 | static void uhci_fsbr_on(struct uhci_hcd *uhci) |
47 | { | 47 | { |
48 | struct uhci_qh *fsbr_qh, *lqh, *tqh; | ||
49 | |||
48 | uhci->fsbr_is_on = 1; | 50 | uhci->fsbr_is_on = 1; |
49 | uhci->skel_term_qh->link = cpu_to_le32( | 51 | lqh = list_entry(uhci->skel_async_qh->node.prev, |
50 | uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH; | 52 | struct uhci_qh, node); |
53 | |||
54 | /* Find the first FSBR QH. Linear search through the list is | ||
55 | * acceptable because normally FSBR gets turned on as soon as | ||
56 | * one QH needs it. */ | ||
57 | fsbr_qh = NULL; | ||
58 | list_for_each_entry_reverse(tqh, &uhci->skel_async_qh->node, node) { | ||
59 | if (tqh->skel < SKEL_FSBR) | ||
60 | break; | ||
61 | fsbr_qh = tqh; | ||
62 | } | ||
63 | |||
64 | /* No FSBR QH means we must insert the terminating skeleton QH */ | ||
65 | if (!fsbr_qh) { | ||
66 | uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_term_qh); | ||
67 | wmb(); | ||
68 | lqh->link = uhci->skel_term_qh->link; | ||
69 | |||
70 | /* Otherwise loop the last QH to the first FSBR QH */ | ||
71 | } else | ||
72 | lqh->link = LINK_TO_QH(fsbr_qh); | ||
51 | } | 73 | } |
52 | 74 | ||
53 | static void uhci_fsbr_off(struct uhci_hcd *uhci) | 75 | static void uhci_fsbr_off(struct uhci_hcd *uhci) |
54 | { | 76 | { |
77 | struct uhci_qh *lqh; | ||
78 | |||
55 | uhci->fsbr_is_on = 0; | 79 | uhci->fsbr_is_on = 0; |
56 | uhci->skel_term_qh->link = UHCI_PTR_TERM; | 80 | lqh = list_entry(uhci->skel_async_qh->node.prev, |
81 | struct uhci_qh, node); | ||
82 | |||
83 | /* End the async list normally and unlink the terminating QH */ | ||
84 | lqh->link = uhci->skel_term_qh->link = UHCI_PTR_TERM; | ||
57 | } | 85 | } |
58 | 86 | ||
59 | static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb) | 87 | static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb) |
@@ -158,11 +186,11 @@ static inline void uhci_insert_td_in_frame_list(struct uhci_hcd *uhci, | |||
158 | 186 | ||
159 | td->link = ltd->link; | 187 | td->link = ltd->link; |
160 | wmb(); | 188 | wmb(); |
161 | ltd->link = cpu_to_le32(td->dma_handle); | 189 | ltd->link = LINK_TO_TD(td); |
162 | } else { | 190 | } else { |
163 | td->link = uhci->frame[framenum]; | 191 | td->link = uhci->frame[framenum]; |
164 | wmb(); | 192 | wmb(); |
165 | uhci->frame[framenum] = cpu_to_le32(td->dma_handle); | 193 | uhci->frame[framenum] = LINK_TO_TD(td); |
166 | uhci->frame_cpu[framenum] = td; | 194 | uhci->frame_cpu[framenum] = td; |
167 | } | 195 | } |
168 | } | 196 | } |
@@ -184,7 +212,7 @@ static inline void uhci_remove_td_from_frame_list(struct uhci_hcd *uhci, | |||
184 | struct uhci_td *ntd; | 212 | struct uhci_td *ntd; |
185 | 213 | ||
186 | ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list); | 214 | ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list); |
187 | uhci->frame[td->frame] = cpu_to_le32(ntd->dma_handle); | 215 | uhci->frame[td->frame] = LINK_TO_TD(ntd); |
188 | uhci->frame_cpu[td->frame] = ntd; | 216 | uhci->frame_cpu[td->frame] = ntd; |
189 | } | 217 | } |
190 | } else { | 218 | } else { |
@@ -405,12 +433,81 @@ static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first) | |||
405 | } | 433 | } |
406 | 434 | ||
407 | /* | 435 | /* |
408 | * Put a QH on the schedule in both hardware and software | 436 | * Link an Isochronous QH into its skeleton's list |
409 | */ | 437 | */ |
410 | static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) | 438 | static inline void link_iso(struct uhci_hcd *uhci, struct uhci_qh *qh) |
439 | { | ||
440 | list_add_tail(&qh->node, &uhci->skel_iso_qh->node); | ||
441 | |||
442 | /* Isochronous QHs aren't linked by the hardware */ | ||
443 | } | ||
444 | |||
445 | /* | ||
446 | * Link a high-period interrupt QH into the schedule at the end of its | ||
447 | * skeleton's list | ||
448 | */ | ||
449 | static void link_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh) | ||
411 | { | 450 | { |
412 | struct uhci_qh *pqh; | 451 | struct uhci_qh *pqh; |
413 | 452 | ||
453 | list_add_tail(&qh->node, &uhci->skelqh[qh->skel]->node); | ||
454 | |||
455 | pqh = list_entry(qh->node.prev, struct uhci_qh, node); | ||
456 | qh->link = pqh->link; | ||
457 | wmb(); | ||
458 | pqh->link = LINK_TO_QH(qh); | ||
459 | } | ||
460 | |||
461 | /* | ||
462 | * Link a period-1 interrupt or async QH into the schedule at the | ||
463 | * correct spot in the async skeleton's list, and update the FSBR link | ||
464 | */ | ||
465 | static void link_async(struct uhci_hcd *uhci, struct uhci_qh *qh) | ||
466 | { | ||
467 | struct uhci_qh *pqh, *lqh; | ||
468 | __le32 link_to_new_qh; | ||
469 | __le32 *extra_link = &link_to_new_qh; | ||
470 | |||
471 | /* Find the predecessor QH for our new one and insert it in the list. | ||
472 | * The list of QHs is expected to be short, so linear search won't | ||
473 | * take too long. */ | ||
474 | list_for_each_entry_reverse(pqh, &uhci->skel_async_qh->node, node) { | ||
475 | if (pqh->skel <= qh->skel) | ||
476 | break; | ||
477 | } | ||
478 | list_add(&qh->node, &pqh->node); | ||
479 | qh->link = pqh->link; | ||
480 | |||
481 | link_to_new_qh = LINK_TO_QH(qh); | ||
482 | |||
483 | /* If this is now the first FSBR QH, take special action */ | ||
484 | if (uhci->fsbr_is_on && pqh->skel < SKEL_FSBR && | ||
485 | qh->skel >= SKEL_FSBR) { | ||
486 | lqh = list_entry(uhci->skel_async_qh->node.prev, | ||
487 | struct uhci_qh, node); | ||
488 | |||
489 | /* If the new QH is also the last one, we must unlink | ||
490 | * the terminating skeleton QH and make the new QH point | ||
491 | * back to itself. */ | ||
492 | if (qh == lqh) { | ||
493 | qh->link = link_to_new_qh; | ||
494 | extra_link = &uhci->skel_term_qh->link; | ||
495 | |||
496 | /* Otherwise the last QH must point to the new QH */ | ||
497 | } else | ||
498 | extra_link = &lqh->link; | ||
499 | } | ||
500 | |||
501 | /* Link it into the schedule */ | ||
502 | wmb(); | ||
503 | *extra_link = pqh->link = link_to_new_qh; | ||
504 | } | ||
505 | |||
506 | /* | ||
507 | * Put a QH on the schedule in both hardware and software | ||
508 | */ | ||
509 | static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) | ||
510 | { | ||
414 | WARN_ON(list_empty(&qh->queue)); | 511 | WARN_ON(list_empty(&qh->queue)); |
415 | 512 | ||
416 | /* Set the element pointer if it isn't set already. | 513 | /* Set the element pointer if it isn't set already. |
@@ -421,7 +518,7 @@ static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
421 | struct uhci_td *td = list_entry(urbp->td_list.next, | 518 | struct uhci_td *td = list_entry(urbp->td_list.next, |
422 | struct uhci_td, list); | 519 | struct uhci_td, list); |
423 | 520 | ||
424 | qh->element = cpu_to_le32(td->dma_handle); | 521 | qh->element = LINK_TO_TD(td); |
425 | } | 522 | } |
426 | 523 | ||
427 | /* Treat the queue as if it has just advanced */ | 524 | /* Treat the queue as if it has just advanced */ |
@@ -432,18 +529,64 @@ static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
432 | return; | 529 | return; |
433 | qh->state = QH_STATE_ACTIVE; | 530 | qh->state = QH_STATE_ACTIVE; |
434 | 531 | ||
435 | /* Move the QH from its old list to the end of the appropriate | 532 | /* Move the QH from its old list to the correct spot in the appropriate |
436 | * skeleton's list */ | 533 | * skeleton's list */ |
437 | if (qh == uhci->next_qh) | 534 | if (qh == uhci->next_qh) |
438 | uhci->next_qh = list_entry(qh->node.next, struct uhci_qh, | 535 | uhci->next_qh = list_entry(qh->node.next, struct uhci_qh, |
439 | node); | 536 | node); |
440 | list_move_tail(&qh->node, &qh->skel->node); | 537 | list_del(&qh->node); |
538 | |||
539 | if (qh->skel == SKEL_ISO) | ||
540 | link_iso(uhci, qh); | ||
541 | else if (qh->skel < SKEL_ASYNC) | ||
542 | link_interrupt(uhci, qh); | ||
543 | else | ||
544 | link_async(uhci, qh); | ||
545 | } | ||
546 | |||
547 | /* | ||
548 | * Unlink a high-period interrupt QH from the schedule | ||
549 | */ | ||
550 | static void unlink_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh) | ||
551 | { | ||
552 | struct uhci_qh *pqh; | ||
441 | 553 | ||
442 | /* Link it into the schedule */ | ||
443 | pqh = list_entry(qh->node.prev, struct uhci_qh, node); | 554 | pqh = list_entry(qh->node.prev, struct uhci_qh, node); |
444 | qh->link = pqh->link; | 555 | pqh->link = qh->link; |
445 | wmb(); | 556 | mb(); |
446 | pqh->link = UHCI_PTR_QH | cpu_to_le32(qh->dma_handle); | 557 | } |
558 | |||
559 | /* | ||
560 | * Unlink a period-1 interrupt or async QH from the schedule | ||
561 | */ | ||
562 | static void unlink_async(struct uhci_hcd *uhci, struct uhci_qh *qh) | ||
563 | { | ||
564 | struct uhci_qh *pqh, *lqh; | ||
565 | __le32 link_to_next_qh = qh->link; | ||
566 | |||
567 | pqh = list_entry(qh->node.prev, struct uhci_qh, node); | ||
568 | |||
569 | /* If this is the first FSBQ QH, take special action */ | ||
570 | if (uhci->fsbr_is_on && pqh->skel < SKEL_FSBR && | ||
571 | qh->skel >= SKEL_FSBR) { | ||
572 | lqh = list_entry(uhci->skel_async_qh->node.prev, | ||
573 | struct uhci_qh, node); | ||
574 | |||
575 | /* If this QH is also the last one, we must link in | ||
576 | * the terminating skeleton QH. */ | ||
577 | if (qh == lqh) { | ||
578 | link_to_next_qh = LINK_TO_QH(uhci->skel_term_qh); | ||
579 | uhci->skel_term_qh->link = link_to_next_qh; | ||
580 | wmb(); | ||
581 | qh->link = link_to_next_qh; | ||
582 | |||
583 | /* Otherwise the last QH must point to the new first FSBR QH */ | ||
584 | } else | ||
585 | lqh->link = link_to_next_qh; | ||
586 | } | ||
587 | |||
588 | pqh->link = link_to_next_qh; | ||
589 | mb(); | ||
447 | } | 590 | } |
448 | 591 | ||
449 | /* | 592 | /* |
@@ -451,17 +594,18 @@ static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
451 | */ | 594 | */ |
452 | static void uhci_unlink_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) | 595 | static void uhci_unlink_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) |
453 | { | 596 | { |
454 | struct uhci_qh *pqh; | ||
455 | |||
456 | if (qh->state == QH_STATE_UNLINKING) | 597 | if (qh->state == QH_STATE_UNLINKING) |
457 | return; | 598 | return; |
458 | WARN_ON(qh->state != QH_STATE_ACTIVE || !qh->udev); | 599 | WARN_ON(qh->state != QH_STATE_ACTIVE || !qh->udev); |
459 | qh->state = QH_STATE_UNLINKING; | 600 | qh->state = QH_STATE_UNLINKING; |
460 | 601 | ||
461 | /* Unlink the QH from the schedule and record when we did it */ | 602 | /* Unlink the QH from the schedule and record when we did it */ |
462 | pqh = list_entry(qh->node.prev, struct uhci_qh, node); | 603 | if (qh->skel == SKEL_ISO) |
463 | pqh->link = qh->link; | 604 | ; |
464 | mb(); | 605 | else if (qh->skel < SKEL_ASYNC) |
606 | unlink_interrupt(uhci, qh); | ||
607 | else | ||
608 | unlink_async(uhci, qh); | ||
465 | 609 | ||
466 | uhci_get_current_frame_number(uhci); | 610 | uhci_get_current_frame_number(uhci); |
467 | qh->unlink_frame = uhci->frame_number; | 611 | qh->unlink_frame = uhci->frame_number; |
@@ -697,6 +841,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, | |||
697 | dma_addr_t data = urb->transfer_dma; | 841 | dma_addr_t data = urb->transfer_dma; |
698 | __le32 *plink; | 842 | __le32 *plink; |
699 | struct urb_priv *urbp = urb->hcpriv; | 843 | struct urb_priv *urbp = urb->hcpriv; |
844 | int skel; | ||
700 | 845 | ||
701 | /* The "pipe" thing contains the destination in bits 8--18 */ | 846 | /* The "pipe" thing contains the destination in bits 8--18 */ |
702 | destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; | 847 | destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; |
@@ -737,7 +882,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, | |||
737 | td = uhci_alloc_td(uhci); | 882 | td = uhci_alloc_td(uhci); |
738 | if (!td) | 883 | if (!td) |
739 | goto nomem; | 884 | goto nomem; |
740 | *plink = cpu_to_le32(td->dma_handle); | 885 | *plink = LINK_TO_TD(td); |
741 | 886 | ||
742 | /* Alternate Data0/1 (start with Data1) */ | 887 | /* Alternate Data0/1 (start with Data1) */ |
743 | destination ^= TD_TOKEN_TOGGLE; | 888 | destination ^= TD_TOKEN_TOGGLE; |
@@ -757,7 +902,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, | |||
757 | td = uhci_alloc_td(uhci); | 902 | td = uhci_alloc_td(uhci); |
758 | if (!td) | 903 | if (!td) |
759 | goto nomem; | 904 | goto nomem; |
760 | *plink = cpu_to_le32(td->dma_handle); | 905 | *plink = LINK_TO_TD(td); |
761 | 906 | ||
762 | /* | 907 | /* |
763 | * It's IN if the pipe is an output pipe or we're not expecting | 908 | * It's IN if the pipe is an output pipe or we're not expecting |
@@ -784,7 +929,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, | |||
784 | td = uhci_alloc_td(uhci); | 929 | td = uhci_alloc_td(uhci); |
785 | if (!td) | 930 | if (!td) |
786 | goto nomem; | 931 | goto nomem; |
787 | *plink = cpu_to_le32(td->dma_handle); | 932 | *plink = LINK_TO_TD(td); |
788 | 933 | ||
789 | uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); | 934 | uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); |
790 | wmb(); | 935 | wmb(); |
@@ -797,11 +942,13 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, | |||
797 | * isn't in the CONFIGURED state. */ | 942 | * isn't in the CONFIGURED state. */ |
798 | if (urb->dev->speed == USB_SPEED_LOW || | 943 | if (urb->dev->speed == USB_SPEED_LOW || |
799 | urb->dev->state != USB_STATE_CONFIGURED) | 944 | urb->dev->state != USB_STATE_CONFIGURED) |
800 | qh->skel = uhci->skel_ls_control_qh; | 945 | skel = SKEL_LS_CONTROL; |
801 | else { | 946 | else { |
802 | qh->skel = uhci->skel_fs_control_qh; | 947 | skel = SKEL_FS_CONTROL; |
803 | uhci_add_fsbr(uhci, urb); | 948 | uhci_add_fsbr(uhci, urb); |
804 | } | 949 | } |
950 | if (qh->state != QH_STATE_ACTIVE) | ||
951 | qh->skel = skel; | ||
805 | 952 | ||
806 | urb->actual_length = -8; /* Account for the SETUP packet */ | 953 | urb->actual_length = -8; /* Account for the SETUP packet */ |
807 | return 0; | 954 | return 0; |
@@ -860,7 +1007,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, | |||
860 | td = uhci_alloc_td(uhci); | 1007 | td = uhci_alloc_td(uhci); |
861 | if (!td) | 1008 | if (!td) |
862 | goto nomem; | 1009 | goto nomem; |
863 | *plink = cpu_to_le32(td->dma_handle); | 1010 | *plink = LINK_TO_TD(td); |
864 | } | 1011 | } |
865 | uhci_add_td_to_urbp(td, urbp); | 1012 | uhci_add_td_to_urbp(td, urbp); |
866 | uhci_fill_td(td, status, | 1013 | uhci_fill_td(td, status, |
@@ -888,7 +1035,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, | |||
888 | td = uhci_alloc_td(uhci); | 1035 | td = uhci_alloc_td(uhci); |
889 | if (!td) | 1036 | if (!td) |
890 | goto nomem; | 1037 | goto nomem; |
891 | *plink = cpu_to_le32(td->dma_handle); | 1038 | *plink = LINK_TO_TD(td); |
892 | 1039 | ||
893 | uhci_add_td_to_urbp(td, urbp); | 1040 | uhci_add_td_to_urbp(td, urbp); |
894 | uhci_fill_td(td, status, | 1041 | uhci_fill_td(td, status, |
@@ -914,7 +1061,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, | |||
914 | td = uhci_alloc_td(uhci); | 1061 | td = uhci_alloc_td(uhci); |
915 | if (!td) | 1062 | if (!td) |
916 | goto nomem; | 1063 | goto nomem; |
917 | *plink = cpu_to_le32(td->dma_handle); | 1064 | *plink = LINK_TO_TD(td); |
918 | 1065 | ||
919 | uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); | 1066 | uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); |
920 | wmb(); | 1067 | wmb(); |
@@ -931,7 +1078,7 @@ nomem: | |||
931 | return -ENOMEM; | 1078 | return -ENOMEM; |
932 | } | 1079 | } |
933 | 1080 | ||
934 | static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, | 1081 | static int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, |
935 | struct uhci_qh *qh) | 1082 | struct uhci_qh *qh) |
936 | { | 1083 | { |
937 | int ret; | 1084 | int ret; |
@@ -940,7 +1087,8 @@ static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, | |||
940 | if (urb->dev->speed == USB_SPEED_LOW) | 1087 | if (urb->dev->speed == USB_SPEED_LOW) |
941 | return -EINVAL; | 1088 | return -EINVAL; |
942 | 1089 | ||
943 | qh->skel = uhci->skel_bulk_qh; | 1090 | if (qh->state != QH_STATE_ACTIVE) |
1091 | qh->skel = SKEL_BULK; | ||
944 | ret = uhci_submit_common(uhci, urb, qh); | 1092 | ret = uhci_submit_common(uhci, urb, qh); |
945 | if (ret == 0) | 1093 | if (ret == 0) |
946 | uhci_add_fsbr(uhci, urb); | 1094 | uhci_add_fsbr(uhci, urb); |
@@ -968,7 +1116,7 @@ static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, | |||
968 | if (exponent < 0) | 1116 | if (exponent < 0) |
969 | return -EINVAL; | 1117 | return -EINVAL; |
970 | qh->period = 1 << exponent; | 1118 | qh->period = 1 << exponent; |
971 | qh->skel = uhci->skelqh[UHCI_SKEL_INDEX(exponent)]; | 1119 | qh->skel = SKEL_INDEX(exponent); |
972 | 1120 | ||
973 | /* For now, interrupt phase is fixed by the layout | 1121 | /* For now, interrupt phase is fixed by the layout |
974 | * of the QH lists. */ | 1122 | * of the QH lists. */ |
@@ -1005,7 +1153,7 @@ static int uhci_fixup_short_transfer(struct uhci_hcd *uhci, | |||
1005 | * the queue at the status stage transaction, which is | 1153 | * the queue at the status stage transaction, which is |
1006 | * the last TD. */ | 1154 | * the last TD. */ |
1007 | WARN_ON(list_empty(&urbp->td_list)); | 1155 | WARN_ON(list_empty(&urbp->td_list)); |
1008 | qh->element = cpu_to_le32(td->dma_handle); | 1156 | qh->element = LINK_TO_TD(td); |
1009 | tmp = td->list.prev; | 1157 | tmp = td->list.prev; |
1010 | ret = -EINPROGRESS; | 1158 | ret = -EINPROGRESS; |
1011 | 1159 | ||
@@ -1216,7 +1364,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, | |||
1216 | qh->iso_status = 0; | 1364 | qh->iso_status = 0; |
1217 | } | 1365 | } |
1218 | 1366 | ||
1219 | qh->skel = uhci->skel_iso_qh; | 1367 | qh->skel = SKEL_ISO; |
1220 | if (!qh->bandwidth_reserved) | 1368 | if (!qh->bandwidth_reserved) |
1221 | uhci_reserve_bandwidth(uhci, qh); | 1369 | uhci_reserve_bandwidth(uhci, qh); |
1222 | return 0; | 1370 | return 0; |
@@ -1566,8 +1714,7 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
1566 | if (time_after(jiffies, qh->advance_jiffies + QH_WAIT_TIMEOUT)) { | 1714 | if (time_after(jiffies, qh->advance_jiffies + QH_WAIT_TIMEOUT)) { |
1567 | 1715 | ||
1568 | /* Detect the Intel bug and work around it */ | 1716 | /* Detect the Intel bug and work around it */ |
1569 | if (qh->post_td && qh_element(qh) == | 1717 | if (qh->post_td && qh_element(qh) == LINK_TO_TD(qh->post_td)) { |
1570 | cpu_to_le32(qh->post_td->dma_handle)) { | ||
1571 | qh->element = qh->post_td->link; | 1718 | qh->element = qh->post_td->link; |
1572 | qh->advance_jiffies = jiffies; | 1719 | qh->advance_jiffies = jiffies; |
1573 | ret = 1; | 1720 | ret = 1; |
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c index 8505824848f6..3749f4a235f9 100644 --- a/drivers/usb/input/usbkbd.c +++ b/drivers/usb/input/usbkbd.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/usb/input.h> | 33 | #include <linux/usb/input.h> |
34 | #include <linux/hid.h> | ||
34 | 35 | ||
35 | /* | 36 | /* |
36 | * Version Information | 37 | * Version Information |
@@ -330,7 +331,8 @@ static void usb_kbd_disconnect(struct usb_interface *intf) | |||
330 | } | 331 | } |
331 | 332 | ||
332 | static struct usb_device_id usb_kbd_id_table [] = { | 333 | static struct usb_device_id usb_kbd_id_table [] = { |
333 | { USB_INTERFACE_INFO(3, 1, 1) }, | 334 | { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, |
335 | USB_INTERFACE_PROTOCOL_KEYBOARD) }, | ||
334 | { } /* Terminating entry */ | 336 | { } /* Terminating entry */ |
335 | }; | 337 | }; |
336 | 338 | ||
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c index 64a33e420cfb..692fd6087779 100644 --- a/drivers/usb/input/usbmouse.c +++ b/drivers/usb/input/usbmouse.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/usb/input.h> | 33 | #include <linux/usb/input.h> |
34 | #include <linux/hid.h> | ||
34 | 35 | ||
35 | /* | 36 | /* |
36 | * Version Information | 37 | * Version Information |
@@ -213,7 +214,8 @@ static void usb_mouse_disconnect(struct usb_interface *intf) | |||
213 | } | 214 | } |
214 | 215 | ||
215 | static struct usb_device_id usb_mouse_id_table [] = { | 216 | static struct usb_device_id usb_mouse_id_table [] = { |
216 | { USB_INTERFACE_INFO(3, 1, 2) }, | 217 | { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, |
218 | USB_INTERFACE_PROTOCOL_MOUSE) }, | ||
217 | { } /* Terminating entry */ | 219 | { } /* Terminating entry */ |
218 | }; | 220 | }; |
219 | 221 | ||
diff --git a/drivers/usb/input/wacom_wac.c b/drivers/usb/input/wacom_wac.c index 4142e36730fc..4f3e9bc7177d 100644 --- a/drivers/usb/input/wacom_wac.c +++ b/drivers/usb/input/wacom_wac.c | |||
@@ -163,7 +163,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
163 | } | 163 | } |
164 | 164 | ||
165 | id = STYLUS_DEVICE_ID; | 165 | id = STYLUS_DEVICE_ID; |
166 | if (data[1] & 0x10) { /* in prox */ | 166 | if (data[1] & 0x80) { /* in prox */ |
167 | 167 | ||
168 | switch ((data[1] >> 5) & 3) { | 168 | switch ((data[1] >> 5) & 3) { |
169 | 169 | ||
@@ -196,9 +196,6 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
196 | wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); | 196 | wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); |
197 | break; | 197 | break; |
198 | } | 198 | } |
199 | } | ||
200 | |||
201 | if (data[1] & 0x90) { | ||
202 | x = wacom_le16_to_cpu(&data[2]); | 199 | x = wacom_le16_to_cpu(&data[2]); |
203 | y = wacom_le16_to_cpu(&data[4]); | 200 | y = wacom_le16_to_cpu(&data[4]); |
204 | wacom_report_abs(wcombo, ABS_X, x); | 201 | wacom_report_abs(wcombo, ABS_X, x); |
@@ -210,19 +207,28 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
210 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04); | 207 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04); |
211 | } | 208 | } |
212 | wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */ | 209 | wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */ |
213 | } | ||
214 | else | ||
215 | wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ | ||
216 | |||
217 | if (data[1] & 0x10) /* only report prox-in when in area */ | ||
218 | wacom_report_key(wcombo, wacom->tool[0], 1); | 210 | wacom_report_key(wcombo, wacom->tool[0], 1); |
219 | if (!(data[1] & 0x90)) /* report prox-out when physically out */ | 211 | } else if (!(data[1] & 0x90)) { |
212 | wacom_report_abs(wcombo, ABS_X, 0); | ||
213 | wacom_report_abs(wcombo, ABS_Y, 0); | ||
214 | if (wacom->tool[0] == BTN_TOOL_MOUSE) { | ||
215 | wacom_report_key(wcombo, BTN_LEFT, 0); | ||
216 | wacom_report_key(wcombo, BTN_RIGHT, 0); | ||
217 | wacom_report_abs(wcombo, ABS_DISTANCE, 0); | ||
218 | } else { | ||
219 | wacom_report_abs(wcombo, ABS_PRESSURE, 0); | ||
220 | wacom_report_key(wcombo, BTN_TOUCH, 0); | ||
221 | wacom_report_key(wcombo, BTN_STYLUS, 0); | ||
222 | wacom_report_key(wcombo, BTN_STYLUS2, 0); | ||
223 | } | ||
224 | wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ | ||
220 | wacom_report_key(wcombo, wacom->tool[0], 0); | 225 | wacom_report_key(wcombo, wacom->tool[0], 0); |
221 | wacom_input_sync(wcombo); | 226 | } |
222 | 227 | ||
223 | /* send pad data */ | 228 | /* send pad data */ |
224 | if (wacom->features->type == WACOM_G4) { | 229 | if (wacom->features->type == WACOM_G4) { |
225 | if ( (wacom->serial[1] & 0xc0) != (data[7] & 0xf8) ) { | 230 | if (data[7] & 0xf8) { |
231 | wacom_input_sync(wcombo); /* sync last event */ | ||
226 | wacom->id[1] = 1; | 232 | wacom->id[1] = 1; |
227 | wacom->serial[1] = (data[7] & 0xf8); | 233 | wacom->serial[1] = (data[7] & 0xf8); |
228 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); | 234 | 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 | rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); | 236 | rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); |
231 | wacom_report_rel(wcombo, REL_WHEEL, rw); | 237 | wacom_report_rel(wcombo, REL_WHEEL, rw); |
232 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); | 238 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); |
239 | wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID); | ||
233 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | 240 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); |
234 | } else if (wacom->id[1]) { | 241 | } else if (wacom->id[1]) { |
242 | wacom_input_sync(wcombo); /* sync last event */ | ||
235 | wacom->id[1] = 0; | 243 | wacom->id[1] = 0; |
244 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); | ||
245 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); | ||
236 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); | 246 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); |
247 | wacom_report_abs(wcombo, ABS_MISC, 0); | ||
237 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | 248 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); |
238 | } | 249 | } |
239 | } | 250 | } |
@@ -304,28 +315,35 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | |||
304 | default: /* Unknown tool */ | 315 | default: /* Unknown tool */ |
305 | wacom->tool[idx] = BTN_TOOL_PEN; | 316 | wacom->tool[idx] = BTN_TOOL_PEN; |
306 | } | 317 | } |
307 | /* only large I3 support Lens Cursor */ | ||
308 | if(!((wacom->tool[idx] == BTN_TOOL_LENS) | ||
309 | && ((wacom->features->type == INTUOS3) | ||
310 | || (wacom->features->type == INTUOS3S)))) { | ||
311 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */ | ||
312 | wacom_report_key(wcombo, wacom->tool[idx], 1); | ||
313 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | ||
314 | return 2; | ||
315 | } | ||
316 | return 1; | 318 | return 1; |
317 | } | 319 | } |
318 | 320 | ||
319 | /* Exit report */ | 321 | /* Exit report */ |
320 | if ((data[1] & 0xfe) == 0x80) { | 322 | if ((data[1] & 0xfe) == 0x80) { |
321 | if(!((wacom->tool[idx] == BTN_TOOL_LENS) | 323 | wacom_report_abs(wcombo, ABS_X, 0); |
322 | && ((wacom->features->type == INTUOS3) | 324 | wacom_report_abs(wcombo, ABS_Y, 0); |
323 | || (wacom->features->type == INTUOS3S)))) { | 325 | wacom_report_abs(wcombo, ABS_DISTANCE, 0); |
324 | wacom_report_key(wcombo, wacom->tool[idx], 0); | 326 | if (wacom->tool[idx] >= BTN_TOOL_MOUSE) { |
325 | wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ | 327 | wacom_report_key(wcombo, BTN_LEFT, 0); |
326 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | 328 | wacom_report_key(wcombo, BTN_MIDDLE, 0); |
327 | return 2; | 329 | wacom_report_key(wcombo, BTN_RIGHT, 0); |
330 | wacom_report_key(wcombo, BTN_SIDE, 0); | ||
331 | wacom_report_key(wcombo, BTN_EXTRA, 0); | ||
332 | wacom_report_abs(wcombo, ABS_THROTTLE, 0); | ||
333 | wacom_report_abs(wcombo, ABS_RZ, 0); | ||
334 | } else { | ||
335 | wacom_report_abs(wcombo, ABS_PRESSURE, 0); | ||
336 | wacom_report_abs(wcombo, ABS_TILT_X, 0); | ||
337 | wacom_report_abs(wcombo, ABS_TILT_Y, 0); | ||
338 | wacom_report_key(wcombo, BTN_STYLUS, 0); | ||
339 | wacom_report_key(wcombo, BTN_STYLUS2, 0); | ||
340 | wacom_report_key(wcombo, BTN_TOUCH, 0); | ||
341 | wacom_report_abs(wcombo, ABS_WHEEL, 0); | ||
328 | } | 342 | } |
343 | wacom_report_key(wcombo, wacom->tool[idx], 0); | ||
344 | wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ | ||
345 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | ||
346 | return 2; | ||
329 | } | 347 | } |
330 | return 0; | 348 | return 0; |
331 | } | 349 | } |
@@ -394,6 +412,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
394 | wacom_report_key(wcombo, wacom->tool[1], 1); | 412 | wacom_report_key(wcombo, wacom->tool[1], 1); |
395 | else | 413 | else |
396 | wacom_report_key(wcombo, wacom->tool[1], 0); | 414 | wacom_report_key(wcombo, wacom->tool[1], 0); |
415 | wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID); | ||
397 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff); | 416 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff); |
398 | return 1; | 417 | return 1; |
399 | } | 418 | } |
@@ -403,6 +422,12 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
403 | if (result) | 422 | if (result) |
404 | return result-1; | 423 | return result-1; |
405 | 424 | ||
425 | /* Only large I3 and I1 & I2 support Lense Cursor */ | ||
426 | if((wacom->tool[idx] == BTN_TOOL_LENS) | ||
427 | && ((wacom->features->type == INTUOS3) | ||
428 | || (wacom->features->type == INTUOS3S))) | ||
429 | return 0; | ||
430 | |||
406 | /* Cintiq doesn't send data when RDY bit isn't set */ | 431 | /* Cintiq doesn't send data when RDY bit isn't set */ |
407 | if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40)) | 432 | if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40)) |
408 | return 0; | 433 | return 0; |
@@ -554,11 +579,11 @@ static struct wacom_features wacom_features[] = { | |||
554 | { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE }, | 579 | { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE }, |
555 | { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 63, GRAPHIRE }, | 580 | { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 63, GRAPHIRE }, |
556 | { "Wacom PenPartner2", 8, 3250, 2320, 255, 63, GRAPHIRE }, | 581 | { "Wacom PenPartner2", 8, 3250, 2320, 255, 63, GRAPHIRE }, |
557 | { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 63, INTUOS }, | 582 | { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, |
558 | { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 63, INTUOS }, | 583 | { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, |
559 | { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 63, INTUOS }, | 584 | { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 31, INTUOS }, |
560 | { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 63, INTUOS }, | 585 | { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 31, INTUOS }, |
561 | { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 63, INTUOS }, | 586 | { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 31, INTUOS }, |
562 | { "Wacom PL400", 8, 5408, 4056, 255, 0, PL }, | 587 | { "Wacom PL400", 8, 5408, 4056, 255, 0, PL }, |
563 | { "Wacom PL500", 8, 6144, 4608, 255, 0, PL }, | 588 | { "Wacom PL500", 8, 6144, 4608, 255, 0, PL }, |
564 | { "Wacom PL600", 8, 6126, 4604, 255, 0, PL }, | 589 | { "Wacom PL600", 8, 6126, 4604, 255, 0, PL }, |
@@ -571,11 +596,11 @@ static struct wacom_features wacom_features[] = { | |||
571 | { "Wacom DTF521", 8, 6282, 4762, 511, 0, PL }, | 596 | { "Wacom DTF521", 8, 6282, 4762, 511, 0, PL }, |
572 | { "Wacom DTF720", 8, 6858, 5506, 511, 0, PL }, | 597 | { "Wacom DTF720", 8, 6858, 5506, 511, 0, PL }, |
573 | { "Wacom Cintiq Partner",8, 20480, 15360, 511, 0, PTU }, | 598 | { "Wacom Cintiq Partner",8, 20480, 15360, 511, 0, PTU }, |
574 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 63, INTUOS }, | 599 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, |
575 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 63, INTUOS }, | 600 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, |
576 | { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 63, INTUOS }, | 601 | { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 31, INTUOS }, |
577 | { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 63, INTUOS }, | 602 | { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 31, INTUOS }, |
578 | { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 63, INTUOS }, | 603 | { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 31, INTUOS }, |
579 | { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 63, INTUOS3S }, | 604 | { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 63, INTUOS3S }, |
580 | { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 63, INTUOS3 }, | 605 | { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 63, INTUOS3 }, |
581 | { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 63, INTUOS3 }, | 606 | { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 63, INTUOS3 }, |
@@ -584,7 +609,7 @@ static struct wacom_features wacom_features[] = { | |||
584 | { "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 63, INTUOS3 }, | 609 | { "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 63, INTUOS3 }, |
585 | { "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 63, INTUOS3S }, | 610 | { "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 63, INTUOS3S }, |
586 | { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ }, | 611 | { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ }, |
587 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 63, INTUOS }, | 612 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, |
588 | { } | 613 | { } |
589 | }; | 614 | }; |
590 | 615 | ||
diff --git a/drivers/usb/input/wacom_wac.h b/drivers/usb/input/wacom_wac.h index a1d9ce007970..a23022287248 100644 --- a/drivers/usb/input/wacom_wac.h +++ b/drivers/usb/input/wacom_wac.h | |||
@@ -12,6 +12,7 @@ | |||
12 | #define STYLUS_DEVICE_ID 0x02 | 12 | #define STYLUS_DEVICE_ID 0x02 |
13 | #define CURSOR_DEVICE_ID 0x06 | 13 | #define CURSOR_DEVICE_ID 0x06 |
14 | #define ERASER_DEVICE_ID 0x0A | 14 | #define ERASER_DEVICE_ID 0x0A |
15 | #define PAD_DEVICE_ID 0x0F | ||
15 | 16 | ||
16 | enum { | 17 | enum { |
17 | PENPARTNER = 0, | 18 | PENPARTNER = 0, |
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 4907e8b80070..9c7eb6144d02 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig | |||
@@ -244,6 +244,20 @@ config USB_TRANCEVIBRATOR | |||
244 | To compile this driver as a module, choose M here: the | 244 | To compile this driver as a module, choose M here: the |
245 | module will be called trancevibrator. | 245 | module will be called trancevibrator. |
246 | 246 | ||
247 | config USB_IOWARRIOR | ||
248 | tristate "IO Warrior driver support" | ||
249 | depends on USB | ||
250 | help | ||
251 | Say Y here if you want to support the IO Warrior devices from Code | ||
252 | Mercenaries. This includes support for the following devices: | ||
253 | IO Warrior 40 | ||
254 | IO Warrior 24 | ||
255 | IO Warrior 56 | ||
256 | IO Warrior 24 Power Vampire | ||
257 | |||
258 | To compile this driver as a module, choose M here: the | ||
259 | module will be called iowarrior. | ||
260 | |||
247 | config USB_TEST | 261 | config USB_TEST |
248 | tristate "USB testing driver (DEVELOPMENT)" | 262 | tristate "USB testing driver (DEVELOPMENT)" |
249 | depends on USB && USB_DEVICEFS && EXPERIMENTAL | 263 | depends on USB && USB_DEVICEFS && EXPERIMENTAL |
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index dac2d5b71566..b68e6b774f1a 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile | |||
@@ -13,6 +13,7 @@ obj-$(CONFIG_USB_EMI26) += emi26.o | |||
13 | obj-$(CONFIG_USB_EMI62) += emi62.o | 13 | obj-$(CONFIG_USB_EMI62) += emi62.o |
14 | obj-$(CONFIG_USB_FTDI_ELAN) += ftdi-elan.o | 14 | obj-$(CONFIG_USB_FTDI_ELAN) += ftdi-elan.o |
15 | obj-$(CONFIG_USB_IDMOUSE) += idmouse.o | 15 | obj-$(CONFIG_USB_IDMOUSE) += idmouse.o |
16 | obj-$(CONFIG_USB_IOWARRIOR) += iowarrior.o | ||
16 | obj-$(CONFIG_USB_LCD) += usblcd.o | 17 | obj-$(CONFIG_USB_LCD) += usblcd.o |
17 | obj-$(CONFIG_USB_LD) += ldusb.o | 18 | obj-$(CONFIG_USB_LD) += ldusb.o |
18 | obj-$(CONFIG_USB_LED) += usbled.o | 19 | obj-$(CONFIG_USB_LED) += usbled.o |
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c new file mode 100644 index 000000000000..d69665c8de02 --- /dev/null +++ b/drivers/usb/misc/iowarrior.c | |||
@@ -0,0 +1,925 @@ | |||
1 | /* | ||
2 | * Native support for the I/O-Warrior USB devices | ||
3 | * | ||
4 | * Copyright (c) 2003-2005 Code Mercenaries GmbH | ||
5 | * written by Christian Lucht <lucht@codemercs.com> | ||
6 | * | ||
7 | * based on | ||
8 | |||
9 | * usb-skeleton.c by Greg Kroah-Hartman <greg@kroah.com> | ||
10 | * brlvger.c by Stephane Dalton <sdalton@videotron.ca> | ||
11 | * and St�hane Doyon <s.doyon@videotron.ca> | ||
12 | * | ||
13 | * Released under the GPLv2. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/usb.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/poll.h> | ||
22 | #include <linux/version.h> | ||
23 | #include <linux/usb/iowarrior.h> | ||
24 | |||
25 | /* Version Information */ | ||
26 | #define DRIVER_VERSION "v0.4.0" | ||
27 | #define DRIVER_AUTHOR "Christian Lucht <lucht@codemercs.com>" | ||
28 | #define DRIVER_DESC "USB IO-Warrior driver (Linux 2.6.x)" | ||
29 | |||
30 | #define USB_VENDOR_ID_CODEMERCS 1984 | ||
31 | /* low speed iowarrior */ | ||
32 | #define USB_DEVICE_ID_CODEMERCS_IOW40 0x1500 | ||
33 | #define USB_DEVICE_ID_CODEMERCS_IOW24 0x1501 | ||
34 | #define USB_DEVICE_ID_CODEMERCS_IOWPV1 0x1511 | ||
35 | #define USB_DEVICE_ID_CODEMERCS_IOWPV2 0x1512 | ||
36 | /* full speed iowarrior */ | ||
37 | #define USB_DEVICE_ID_CODEMERCS_IOW56 0x1503 | ||
38 | |||
39 | /* Get a minor range for your devices from the usb maintainer */ | ||
40 | #ifdef CONFIG_USB_DYNAMIC_MINORS | ||
41 | #define IOWARRIOR_MINOR_BASE 0 | ||
42 | #else | ||
43 | #define IOWARRIOR_MINOR_BASE 208 // SKELETON_MINOR_BASE 192 + 16, not offical yet | ||
44 | #endif | ||
45 | |||
46 | /* interrupt input queue size */ | ||
47 | #define MAX_INTERRUPT_BUFFER 16 | ||
48 | /* | ||
49 | maximum number of urbs that are submitted for writes at the same time, | ||
50 | this applies to the IOWarrior56 only! | ||
51 | IOWarrior24 and IOWarrior40 use synchronous usb_control_msg calls. | ||
52 | */ | ||
53 | #define MAX_WRITES_IN_FLIGHT 4 | ||
54 | |||
55 | /* Use our own dbg macro */ | ||
56 | #undef dbg | ||
57 | #define dbg( format, arg... ) do { if( debug ) printk( KERN_DEBUG __FILE__ ": " format "\n" , ## arg ); } while ( 0 ) | ||
58 | |||
59 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
60 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
61 | MODULE_LICENSE("GPL"); | ||
62 | |||
63 | /* Module parameters */ | ||
64 | static int debug = 0; | ||
65 | module_param(debug, bool, 0644); | ||
66 | MODULE_PARM_DESC(debug, "debug=1 enables debugging messages"); | ||
67 | |||
68 | static struct usb_driver iowarrior_driver; | ||
69 | |||
70 | /*--------------*/ | ||
71 | /* data */ | ||
72 | /*--------------*/ | ||
73 | |||
74 | /* Structure to hold all of our device specific stuff */ | ||
75 | struct iowarrior { | ||
76 | struct mutex mutex; /* locks this structure */ | ||
77 | struct usb_device *udev; /* save off the usb device pointer */ | ||
78 | struct usb_interface *interface; /* the interface for this device */ | ||
79 | unsigned char minor; /* the starting minor number for this device */ | ||
80 | struct usb_endpoint_descriptor *int_out_endpoint; /* endpoint for reading (needed for IOW56 only) */ | ||
81 | struct usb_endpoint_descriptor *int_in_endpoint; /* endpoint for reading */ | ||
82 | struct urb *int_in_urb; /* the urb for reading data */ | ||
83 | unsigned char *int_in_buffer; /* buffer for data to be read */ | ||
84 | unsigned char serial_number; /* to detect lost packages */ | ||
85 | unsigned char *read_queue; /* size is MAX_INTERRUPT_BUFFER * packet size */ | ||
86 | wait_queue_head_t read_wait; | ||
87 | wait_queue_head_t write_wait; /* wait-queue for writing to the device */ | ||
88 | atomic_t write_busy; /* number of write-urbs submitted */ | ||
89 | atomic_t read_idx; | ||
90 | atomic_t intr_idx; | ||
91 | spinlock_t intr_idx_lock; /* protects intr_idx */ | ||
92 | atomic_t overflow_flag; /* signals an index 'rollover' */ | ||
93 | int present; /* this is 1 as long as the device is connected */ | ||
94 | int opened; /* this is 1 if the device is currently open */ | ||
95 | char chip_serial[9]; /* the serial number string of the chip connected */ | ||
96 | int report_size; /* number of bytes in a report */ | ||
97 | u16 product_id; | ||
98 | }; | ||
99 | |||
100 | /*--------------*/ | ||
101 | /* globals */ | ||
102 | /*--------------*/ | ||
103 | /* prevent races between open() and disconnect() */ | ||
104 | static DECLARE_MUTEX(disconnect_sem); | ||
105 | |||
106 | /* | ||
107 | * USB spec identifies 5 second timeouts. | ||
108 | */ | ||
109 | #define GET_TIMEOUT 5 | ||
110 | #define USB_REQ_GET_REPORT 0x01 | ||
111 | //#if 0 | ||
112 | static int usb_get_report(struct usb_device *dev, | ||
113 | struct usb_host_interface *inter, unsigned char type, | ||
114 | unsigned char id, void *buf, int size) | ||
115 | { | ||
116 | return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
117 | USB_REQ_GET_REPORT, | ||
118 | USB_DIR_IN | USB_TYPE_CLASS | | ||
119 | USB_RECIP_INTERFACE, (type << 8) + id, | ||
120 | inter->desc.bInterfaceNumber, buf, size, | ||
121 | GET_TIMEOUT); | ||
122 | } | ||
123 | //#endif | ||
124 | |||
125 | #define USB_REQ_SET_REPORT 0x09 | ||
126 | |||
127 | static int usb_set_report(struct usb_interface *intf, unsigned char type, | ||
128 | unsigned char id, void *buf, int size) | ||
129 | { | ||
130 | return usb_control_msg(interface_to_usbdev(intf), | ||
131 | usb_sndctrlpipe(interface_to_usbdev(intf), 0), | ||
132 | USB_REQ_SET_REPORT, | ||
133 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
134 | (type << 8) + id, | ||
135 | intf->cur_altsetting->desc.bInterfaceNumber, buf, | ||
136 | size, 1); | ||
137 | } | ||
138 | |||
139 | /*---------------------*/ | ||
140 | /* driver registration */ | ||
141 | /*---------------------*/ | ||
142 | /* table of devices that work with this driver */ | ||
143 | static struct usb_device_id iowarrior_ids[] = { | ||
144 | {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40)}, | ||
145 | {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24)}, | ||
146 | {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOWPV1)}, | ||
147 | {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOWPV2)}, | ||
148 | {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW56)}, | ||
149 | {} /* Terminating entry */ | ||
150 | }; | ||
151 | MODULE_DEVICE_TABLE(usb, iowarrior_ids); | ||
152 | |||
153 | /* | ||
154 | * USB callback handler for reading data | ||
155 | */ | ||
156 | static void iowarrior_callback(struct urb *urb) | ||
157 | { | ||
158 | struct iowarrior *dev = (struct iowarrior *)urb->context; | ||
159 | int intr_idx; | ||
160 | int read_idx; | ||
161 | int aux_idx; | ||
162 | int offset; | ||
163 | int status; | ||
164 | |||
165 | switch (urb->status) { | ||
166 | case 0: | ||
167 | /* success */ | ||
168 | break; | ||
169 | case -ECONNRESET: | ||
170 | case -ENOENT: | ||
171 | case -ESHUTDOWN: | ||
172 | return; | ||
173 | default: | ||
174 | goto exit; | ||
175 | } | ||
176 | |||
177 | spin_lock(&dev->intr_idx_lock); | ||
178 | intr_idx = atomic_read(&dev->intr_idx); | ||
179 | /* aux_idx become previous intr_idx */ | ||
180 | aux_idx = (intr_idx == 0) ? (MAX_INTERRUPT_BUFFER - 1) : (intr_idx - 1); | ||
181 | read_idx = atomic_read(&dev->read_idx); | ||
182 | |||
183 | /* queue is not empty and it's interface 0 */ | ||
184 | if ((intr_idx != read_idx) | ||
185 | && (dev->interface->cur_altsetting->desc.bInterfaceNumber == 0)) { | ||
186 | /* + 1 for serial number */ | ||
187 | offset = aux_idx * (dev->report_size + 1); | ||
188 | if (!memcmp | ||
189 | (dev->read_queue + offset, urb->transfer_buffer, | ||
190 | dev->report_size)) { | ||
191 | /* equal values on interface 0 will be ignored */ | ||
192 | spin_unlock(&dev->intr_idx_lock); | ||
193 | goto exit; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | /* aux_idx become next intr_idx */ | ||
198 | aux_idx = (intr_idx == (MAX_INTERRUPT_BUFFER - 1)) ? 0 : (intr_idx + 1); | ||
199 | if (read_idx == aux_idx) { | ||
200 | /* queue full, dropping oldest input */ | ||
201 | read_idx = (++read_idx == MAX_INTERRUPT_BUFFER) ? 0 : read_idx; | ||
202 | atomic_set(&dev->read_idx, read_idx); | ||
203 | atomic_set(&dev->overflow_flag, 1); | ||
204 | } | ||
205 | |||
206 | /* +1 for serial number */ | ||
207 | offset = intr_idx * (dev->report_size + 1); | ||
208 | memcpy(dev->read_queue + offset, urb->transfer_buffer, | ||
209 | dev->report_size); | ||
210 | *(dev->read_queue + offset + (dev->report_size)) = dev->serial_number++; | ||
211 | |||
212 | atomic_set(&dev->intr_idx, aux_idx); | ||
213 | spin_unlock(&dev->intr_idx_lock); | ||
214 | /* tell the blocking read about the new data */ | ||
215 | wake_up_interruptible(&dev->read_wait); | ||
216 | |||
217 | exit: | ||
218 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
219 | if (status) | ||
220 | dev_err(&dev->interface->dev, "%s - usb_submit_urb failed with result %d", | ||
221 | __FUNCTION__, status); | ||
222 | |||
223 | } | ||
224 | |||
225 | /* | ||
226 | * USB Callback handler for write-ops | ||
227 | */ | ||
228 | static void iowarrior_write_callback(struct urb *urb) | ||
229 | { | ||
230 | struct iowarrior *dev; | ||
231 | dev = (struct iowarrior *)urb->context; | ||
232 | /* sync/async unlink faults aren't errors */ | ||
233 | if (urb->status && | ||
234 | !(urb->status == -ENOENT || | ||
235 | urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) { | ||
236 | dbg("%s - nonzero write bulk status received: %d", | ||
237 | __func__, urb->status); | ||
238 | } | ||
239 | /* free up our allocated buffer */ | ||
240 | usb_buffer_free(urb->dev, urb->transfer_buffer_length, | ||
241 | urb->transfer_buffer, urb->transfer_dma); | ||
242 | /* tell a waiting writer the interrupt-out-pipe is available again */ | ||
243 | atomic_dec(&dev->write_busy); | ||
244 | wake_up_interruptible(&dev->write_wait); | ||
245 | } | ||
246 | |||
247 | /** | ||
248 | * iowarrior_delete | ||
249 | */ | ||
250 | static inline void iowarrior_delete(struct iowarrior *dev) | ||
251 | { | ||
252 | dbg("%s - minor %d", __func__, dev->minor); | ||
253 | kfree(dev->int_in_buffer); | ||
254 | usb_free_urb(dev->int_in_urb); | ||
255 | kfree(dev->read_queue); | ||
256 | kfree(dev); | ||
257 | } | ||
258 | |||
259 | /*---------------------*/ | ||
260 | /* fops implementation */ | ||
261 | /*---------------------*/ | ||
262 | |||
263 | static int read_index(struct iowarrior *dev) | ||
264 | { | ||
265 | int intr_idx, read_idx; | ||
266 | |||
267 | read_idx = atomic_read(&dev->read_idx); | ||
268 | intr_idx = atomic_read(&dev->intr_idx); | ||
269 | |||
270 | return (read_idx == intr_idx ? -1 : read_idx); | ||
271 | } | ||
272 | |||
273 | /** | ||
274 | * iowarrior_read | ||
275 | */ | ||
276 | static ssize_t iowarrior_read(struct file *file, char __user *buffer, | ||
277 | size_t count, loff_t *ppos) | ||
278 | { | ||
279 | struct iowarrior *dev; | ||
280 | int read_idx; | ||
281 | int offset; | ||
282 | |||
283 | dev = (struct iowarrior *)file->private_data; | ||
284 | |||
285 | /* verify that the device wasn't unplugged */ | ||
286 | if (dev == NULL || !dev->present) | ||
287 | return -ENODEV; | ||
288 | |||
289 | dbg("%s - minor %d, count = %zd", __func__, dev->minor, count); | ||
290 | |||
291 | /* read count must be packet size (+ time stamp) */ | ||
292 | if ((count != dev->report_size) | ||
293 | && (count != (dev->report_size + 1))) | ||
294 | return -EINVAL; | ||
295 | |||
296 | /* repeat until no buffer overrun in callback handler occur */ | ||
297 | do { | ||
298 | atomic_set(&dev->overflow_flag, 0); | ||
299 | if ((read_idx = read_index(dev)) == -1) { | ||
300 | /* queue emty */ | ||
301 | if (file->f_flags & O_NONBLOCK) | ||
302 | return -EAGAIN; | ||
303 | else { | ||
304 | //next line will return when there is either new data, or the device is unplugged | ||
305 | int r = wait_event_interruptible(dev->read_wait, | ||
306 | (!dev->present | ||
307 | || (read_idx = | ||
308 | read_index | ||
309 | (dev)) != | ||
310 | -1)); | ||
311 | if (r) { | ||
312 | //we were interrupted by a signal | ||
313 | return -ERESTART; | ||
314 | } | ||
315 | if (!dev->present) { | ||
316 | //The device was unplugged | ||
317 | return -ENODEV; | ||
318 | } | ||
319 | if (read_idx == -1) { | ||
320 | // Can this happen ??? | ||
321 | return 0; | ||
322 | } | ||
323 | } | ||
324 | } | ||
325 | |||
326 | offset = read_idx * (dev->report_size + 1); | ||
327 | if (copy_to_user(buffer, dev->read_queue + offset, count)) { | ||
328 | return -EFAULT; | ||
329 | } | ||
330 | } while (atomic_read(&dev->overflow_flag)); | ||
331 | |||
332 | read_idx = ++read_idx == MAX_INTERRUPT_BUFFER ? 0 : read_idx; | ||
333 | atomic_set(&dev->read_idx, read_idx); | ||
334 | return count; | ||
335 | } | ||
336 | |||
337 | /* | ||
338 | * iowarrior_write | ||
339 | */ | ||
340 | static ssize_t iowarrior_write(struct file *file, | ||
341 | const char __user *user_buffer, | ||
342 | size_t count, loff_t *ppos) | ||
343 | { | ||
344 | struct iowarrior *dev; | ||
345 | int retval = 0; | ||
346 | char *buf = NULL; /* for IOW24 and IOW56 we need a buffer */ | ||
347 | struct urb *int_out_urb = NULL; | ||
348 | |||
349 | dev = (struct iowarrior *)file->private_data; | ||
350 | |||
351 | mutex_lock(&dev->mutex); | ||
352 | /* verify that the device wasn't unplugged */ | ||
353 | if (dev == NULL || !dev->present) { | ||
354 | retval = -ENODEV; | ||
355 | goto exit; | ||
356 | } | ||
357 | dbg("%s - minor %d, count = %zd", __func__, dev->minor, count); | ||
358 | /* if count is 0 we're already done */ | ||
359 | if (count == 0) { | ||
360 | retval = 0; | ||
361 | goto exit; | ||
362 | } | ||
363 | /* We only accept full reports */ | ||
364 | if (count != dev->report_size) { | ||
365 | retval = -EINVAL; | ||
366 | goto exit; | ||
367 | } | ||
368 | switch (dev->product_id) { | ||
369 | case USB_DEVICE_ID_CODEMERCS_IOW24: | ||
370 | case USB_DEVICE_ID_CODEMERCS_IOWPV1: | ||
371 | case USB_DEVICE_ID_CODEMERCS_IOWPV2: | ||
372 | case USB_DEVICE_ID_CODEMERCS_IOW40: | ||
373 | /* IOW24 and IOW40 use a synchronous call */ | ||
374 | buf = kmalloc(8, GFP_KERNEL); /* 8 bytes are enough for both products */ | ||
375 | if (!buf) { | ||
376 | retval = -ENOMEM; | ||
377 | goto exit; | ||
378 | } | ||
379 | if (copy_from_user(buf, user_buffer, count)) { | ||
380 | retval = -EFAULT; | ||
381 | kfree(buf); | ||
382 | goto exit; | ||
383 | } | ||
384 | retval = usb_set_report(dev->interface, 2, 0, buf, count); | ||
385 | kfree(buf); | ||
386 | goto exit; | ||
387 | break; | ||
388 | case USB_DEVICE_ID_CODEMERCS_IOW56: | ||
389 | /* The IOW56 uses asynchronous IO and more urbs */ | ||
390 | if (atomic_read(&dev->write_busy) == MAX_WRITES_IN_FLIGHT) { | ||
391 | /* Wait until we are below the limit for submitted urbs */ | ||
392 | if (file->f_flags & O_NONBLOCK) { | ||
393 | retval = -EAGAIN; | ||
394 | goto exit; | ||
395 | } else { | ||
396 | retval = wait_event_interruptible(dev->write_wait, | ||
397 | (!dev->present || (atomic_read (&dev-> write_busy) < MAX_WRITES_IN_FLIGHT))); | ||
398 | if (retval) { | ||
399 | /* we were interrupted by a signal */ | ||
400 | retval = -ERESTART; | ||
401 | goto exit; | ||
402 | } | ||
403 | if (!dev->present) { | ||
404 | /* The device was unplugged */ | ||
405 | retval = -ENODEV; | ||
406 | goto exit; | ||
407 | } | ||
408 | if (!dev->opened) { | ||
409 | /* We were closed while waiting for an URB */ | ||
410 | retval = -ENODEV; | ||
411 | goto exit; | ||
412 | } | ||
413 | } | ||
414 | } | ||
415 | atomic_inc(&dev->write_busy); | ||
416 | int_out_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
417 | if (!int_out_urb) { | ||
418 | retval = -ENOMEM; | ||
419 | dbg("%s Unable to allocate urb ", __func__); | ||
420 | goto error; | ||
421 | } | ||
422 | buf = usb_buffer_alloc(dev->udev, dev->report_size, | ||
423 | GFP_KERNEL, &int_out_urb->transfer_dma); | ||
424 | if (!buf) { | ||
425 | retval = -ENOMEM; | ||
426 | dbg("%s Unable to allocate buffer ", __func__); | ||
427 | goto error; | ||
428 | } | ||
429 | usb_fill_int_urb(int_out_urb, dev->udev, | ||
430 | usb_sndintpipe(dev->udev, | ||
431 | dev->int_out_endpoint->bEndpointAddress), | ||
432 | buf, dev->report_size, | ||
433 | iowarrior_write_callback, dev, | ||
434 | dev->int_out_endpoint->bInterval); | ||
435 | int_out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
436 | if (copy_from_user(buf, user_buffer, count)) { | ||
437 | retval = -EFAULT; | ||
438 | goto error; | ||
439 | } | ||
440 | retval = usb_submit_urb(int_out_urb, GFP_KERNEL); | ||
441 | if (retval) { | ||
442 | dbg("%s submit error %d for urb nr.%d", __func__, | ||
443 | retval, atomic_read(&dev->write_busy)); | ||
444 | goto error; | ||
445 | } | ||
446 | /* submit was ok */ | ||
447 | retval = count; | ||
448 | usb_free_urb(int_out_urb); | ||
449 | goto exit; | ||
450 | break; | ||
451 | default: | ||
452 | /* what do we have here ? An unsupported Product-ID ? */ | ||
453 | dev_err(&dev->interface->dev, "%s - not supported for product=0x%x", | ||
454 | __FUNCTION__, dev->product_id); | ||
455 | retval = -EFAULT; | ||
456 | goto exit; | ||
457 | break; | ||
458 | } | ||
459 | error: | ||
460 | usb_buffer_free(dev->udev, dev->report_size, buf, | ||
461 | int_out_urb->transfer_dma); | ||
462 | usb_free_urb(int_out_urb); | ||
463 | atomic_dec(&dev->write_busy); | ||
464 | wake_up_interruptible(&dev->write_wait); | ||
465 | exit: | ||
466 | mutex_unlock(&dev->mutex); | ||
467 | return retval; | ||
468 | } | ||
469 | |||
470 | /** | ||
471 | * iowarrior_ioctl | ||
472 | */ | ||
473 | static int iowarrior_ioctl(struct inode *inode, struct file *file, | ||
474 | unsigned int cmd, unsigned long arg) | ||
475 | { | ||
476 | struct iowarrior *dev = NULL; | ||
477 | __u8 *buffer; | ||
478 | __u8 __user *user_buffer; | ||
479 | int retval; | ||
480 | int io_res; /* checks for bytes read/written and copy_to/from_user results */ | ||
481 | |||
482 | dev = (struct iowarrior *)file->private_data; | ||
483 | if (dev == NULL) { | ||
484 | return -ENODEV; | ||
485 | } | ||
486 | |||
487 | buffer = kzalloc(dev->report_size, GFP_KERNEL); | ||
488 | if (!buffer) | ||
489 | return -ENOMEM; | ||
490 | |||
491 | /* lock this object */ | ||
492 | mutex_lock(&dev->mutex); | ||
493 | |||
494 | /* verify that the device wasn't unplugged */ | ||
495 | if (!dev->present) { | ||
496 | mutex_unlock(&dev->mutex); | ||
497 | return -ENODEV; | ||
498 | } | ||
499 | |||
500 | dbg("%s - minor %d, cmd 0x%.4x, arg %ld", __func__, dev->minor, cmd, | ||
501 | arg); | ||
502 | |||
503 | retval = 0; | ||
504 | io_res = 0; | ||
505 | switch (cmd) { | ||
506 | case IOW_WRITE: | ||
507 | if (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW24 || | ||
508 | dev->product_id == USB_DEVICE_ID_CODEMERCS_IOWPV1 || | ||
509 | dev->product_id == USB_DEVICE_ID_CODEMERCS_IOWPV2 || | ||
510 | dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW40) { | ||
511 | user_buffer = (__u8 __user *)arg; | ||
512 | io_res = copy_from_user(buffer, user_buffer, | ||
513 | dev->report_size); | ||
514 | if (io_res) { | ||
515 | retval = -EFAULT; | ||
516 | } else { | ||
517 | io_res = usb_set_report(dev->interface, 2, 0, | ||
518 | buffer, | ||
519 | dev->report_size); | ||
520 | if (io_res < 0) | ||
521 | retval = io_res; | ||
522 | } | ||
523 | } else { | ||
524 | retval = -EINVAL; | ||
525 | dev_err(&dev->interface->dev, | ||
526 | "ioctl 'IOW_WRITE' is not supported for product=0x%x.", | ||
527 | dev->product_id); | ||
528 | } | ||
529 | break; | ||
530 | case IOW_READ: | ||
531 | user_buffer = (__u8 __user *)arg; | ||
532 | io_res = usb_get_report(dev->udev, | ||
533 | dev->interface->cur_altsetting, 1, 0, | ||
534 | buffer, dev->report_size); | ||
535 | if (io_res < 0) | ||
536 | retval = io_res; | ||
537 | else { | ||
538 | io_res = copy_to_user(user_buffer, buffer, dev->report_size); | ||
539 | if (io_res < 0) | ||
540 | retval = -EFAULT; | ||
541 | } | ||
542 | break; | ||
543 | case IOW_GETINFO: | ||
544 | { | ||
545 | /* Report available information for the device */ | ||
546 | struct iowarrior_info info; | ||
547 | /* needed for power consumption */ | ||
548 | struct usb_config_descriptor *cfg_descriptor = &dev->udev->actconfig->desc; | ||
549 | |||
550 | /* directly from the descriptor */ | ||
551 | info.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); | ||
552 | info.product = dev->product_id; | ||
553 | info.revision = le16_to_cpu(dev->udev->descriptor.bcdDevice); | ||
554 | |||
555 | /* 0==UNKNOWN, 1==LOW(usb1.1) ,2=FULL(usb1.1), 3=HIGH(usb2.0) */ | ||
556 | info.speed = le16_to_cpu(dev->udev->speed); | ||
557 | info.if_num = dev->interface->cur_altsetting->desc.bInterfaceNumber; | ||
558 | info.report_size = dev->report_size; | ||
559 | |||
560 | /* serial number string has been read earlier 8 chars or empty string */ | ||
561 | memcpy(info.serial, dev->chip_serial, | ||
562 | sizeof(dev->chip_serial)); | ||
563 | if (cfg_descriptor == NULL) { | ||
564 | info.power = -1; /* no information available */ | ||
565 | } else { | ||
566 | /* the MaxPower is stored in units of 2mA to make it fit into a byte-value */ | ||
567 | info.power = cfg_descriptor->bMaxPower * 2; | ||
568 | } | ||
569 | io_res = copy_to_user((struct iowarrior_info __user *)arg, &info, | ||
570 | sizeof(struct iowarrior_info)); | ||
571 | if (io_res < 0) | ||
572 | retval = -EFAULT; | ||
573 | break; | ||
574 | } | ||
575 | default: | ||
576 | /* return that we did not understand this ioctl call */ | ||
577 | retval = -ENOTTY; | ||
578 | break; | ||
579 | } | ||
580 | |||
581 | /* unlock the device */ | ||
582 | mutex_unlock(&dev->mutex); | ||
583 | return retval; | ||
584 | } | ||
585 | |||
586 | /** | ||
587 | * iowarrior_open | ||
588 | */ | ||
589 | static int iowarrior_open(struct inode *inode, struct file *file) | ||
590 | { | ||
591 | struct iowarrior *dev = NULL; | ||
592 | struct usb_interface *interface; | ||
593 | int subminor; | ||
594 | int retval = 0; | ||
595 | |||
596 | dbg("%s", __func__); | ||
597 | |||
598 | subminor = iminor(inode); | ||
599 | |||
600 | /* prevent disconnects */ | ||
601 | down(&disconnect_sem); | ||
602 | |||
603 | interface = usb_find_interface(&iowarrior_driver, subminor); | ||
604 | if (!interface) { | ||
605 | err("%s - error, can't find device for minor %d", __FUNCTION__, | ||
606 | subminor); | ||
607 | retval = -ENODEV; | ||
608 | goto out; | ||
609 | } | ||
610 | |||
611 | dev = usb_get_intfdata(interface); | ||
612 | if (!dev) { | ||
613 | retval = -ENODEV; | ||
614 | goto out; | ||
615 | } | ||
616 | |||
617 | /* Only one process can open each device, no sharing. */ | ||
618 | if (dev->opened) { | ||
619 | retval = -EBUSY; | ||
620 | goto out; | ||
621 | } | ||
622 | |||
623 | /* setup interrupt handler for receiving values */ | ||
624 | if ((retval = usb_submit_urb(dev->int_in_urb, GFP_KERNEL)) < 0) { | ||
625 | dev_err(&interface->dev, "Error %d while submitting URB\n", retval); | ||
626 | retval = -EFAULT; | ||
627 | goto out; | ||
628 | } | ||
629 | /* increment our usage count for the driver */ | ||
630 | ++dev->opened; | ||
631 | /* save our object in the file's private structure */ | ||
632 | file->private_data = dev; | ||
633 | retval = 0; | ||
634 | |||
635 | out: | ||
636 | up(&disconnect_sem); | ||
637 | return retval; | ||
638 | } | ||
639 | |||
640 | /** | ||
641 | * iowarrior_release | ||
642 | */ | ||
643 | static int iowarrior_release(struct inode *inode, struct file *file) | ||
644 | { | ||
645 | struct iowarrior *dev; | ||
646 | int retval = 0; | ||
647 | |||
648 | dev = (struct iowarrior *)file->private_data; | ||
649 | if (dev == NULL) { | ||
650 | return -ENODEV; | ||
651 | } | ||
652 | |||
653 | dbg("%s - minor %d", __func__, dev->minor); | ||
654 | |||
655 | /* lock our device */ | ||
656 | mutex_lock(&dev->mutex); | ||
657 | |||
658 | if (dev->opened <= 0) { | ||
659 | retval = -ENODEV; /* close called more than once */ | ||
660 | mutex_unlock(&dev->mutex); | ||
661 | } else { | ||
662 | dev->opened = 0; /* we're closeing now */ | ||
663 | retval = 0; | ||
664 | if (dev->present) { | ||
665 | /* | ||
666 | The device is still connected so we only shutdown | ||
667 | pending read-/write-ops. | ||
668 | */ | ||
669 | usb_kill_urb(dev->int_in_urb); | ||
670 | wake_up_interruptible(&dev->read_wait); | ||
671 | wake_up_interruptible(&dev->write_wait); | ||
672 | mutex_unlock(&dev->mutex); | ||
673 | } else { | ||
674 | /* The device was unplugged, cleanup resources */ | ||
675 | mutex_unlock(&dev->mutex); | ||
676 | iowarrior_delete(dev); | ||
677 | } | ||
678 | } | ||
679 | return retval; | ||
680 | } | ||
681 | |||
682 | static unsigned iowarrior_poll(struct file *file, poll_table * wait) | ||
683 | { | ||
684 | struct iowarrior *dev = file->private_data; | ||
685 | unsigned int mask = 0; | ||
686 | |||
687 | if (!dev->present) | ||
688 | return POLLERR | POLLHUP; | ||
689 | |||
690 | poll_wait(file, &dev->read_wait, wait); | ||
691 | poll_wait(file, &dev->write_wait, wait); | ||
692 | |||
693 | if (!dev->present) | ||
694 | return POLLERR | POLLHUP; | ||
695 | |||
696 | if (read_index(dev) != -1) | ||
697 | mask |= POLLIN | POLLRDNORM; | ||
698 | |||
699 | if (atomic_read(&dev->write_busy) < MAX_WRITES_IN_FLIGHT) | ||
700 | mask |= POLLOUT | POLLWRNORM; | ||
701 | return mask; | ||
702 | } | ||
703 | |||
704 | /* | ||
705 | * File operations needed when we register this driver. | ||
706 | * This assumes that this driver NEEDS file operations, | ||
707 | * of course, which means that the driver is expected | ||
708 | * to have a node in the /dev directory. If the USB | ||
709 | * device were for a network interface then the driver | ||
710 | * would use "struct net_driver" instead, and a serial | ||
711 | * device would use "struct tty_driver". | ||
712 | */ | ||
713 | static struct file_operations iowarrior_fops = { | ||
714 | .owner = THIS_MODULE, | ||
715 | .write = iowarrior_write, | ||
716 | .read = iowarrior_read, | ||
717 | .ioctl = iowarrior_ioctl, | ||
718 | .open = iowarrior_open, | ||
719 | .release = iowarrior_release, | ||
720 | .poll = iowarrior_poll, | ||
721 | }; | ||
722 | |||
723 | /* | ||
724 | * usb class driver info in order to get a minor number from the usb core, | ||
725 | * and to have the device registered with devfs and the driver core | ||
726 | */ | ||
727 | static struct usb_class_driver iowarrior_class = { | ||
728 | .name = "iowarrior%d", | ||
729 | .fops = &iowarrior_fops, | ||
730 | .minor_base = IOWARRIOR_MINOR_BASE, | ||
731 | }; | ||
732 | |||
733 | /*---------------------------------*/ | ||
734 | /* probe and disconnect functions */ | ||
735 | /*---------------------------------*/ | ||
736 | /** | ||
737 | * iowarrior_probe | ||
738 | * | ||
739 | * Called by the usb core when a new device is connected that it thinks | ||
740 | * this driver might be interested in. | ||
741 | */ | ||
742 | static int iowarrior_probe(struct usb_interface *interface, | ||
743 | const struct usb_device_id *id) | ||
744 | { | ||
745 | struct usb_device *udev = interface_to_usbdev(interface); | ||
746 | struct iowarrior *dev = NULL; | ||
747 | struct usb_host_interface *iface_desc; | ||
748 | struct usb_endpoint_descriptor *endpoint; | ||
749 | int i; | ||
750 | int retval = -ENOMEM; | ||
751 | int idele = 0; | ||
752 | |||
753 | /* allocate memory for our device state and intialize it */ | ||
754 | dev = kzalloc(sizeof(struct iowarrior), GFP_KERNEL); | ||
755 | if (dev == NULL) { | ||
756 | dev_err(&interface->dev, "Out of memory"); | ||
757 | return retval; | ||
758 | } | ||
759 | |||
760 | mutex_init(&dev->mutex); | ||
761 | |||
762 | atomic_set(&dev->intr_idx, 0); | ||
763 | atomic_set(&dev->read_idx, 0); | ||
764 | spin_lock_init(&dev->intr_idx_lock); | ||
765 | atomic_set(&dev->overflow_flag, 0); | ||
766 | init_waitqueue_head(&dev->read_wait); | ||
767 | atomic_set(&dev->write_busy, 0); | ||
768 | init_waitqueue_head(&dev->write_wait); | ||
769 | |||
770 | dev->udev = udev; | ||
771 | dev->interface = interface; | ||
772 | |||
773 | iface_desc = interface->cur_altsetting; | ||
774 | dev->product_id = le16_to_cpu(udev->descriptor.idProduct); | ||
775 | |||
776 | /* set up the endpoint information */ | ||
777 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | ||
778 | endpoint = &iface_desc->endpoint[i].desc; | ||
779 | |||
780 | if (usb_endpoint_is_int_in(endpoint)) | ||
781 | dev->int_in_endpoint = endpoint; | ||
782 | if (usb_endpoint_is_int_out(endpoint)) | ||
783 | /* this one will match for the IOWarrior56 only */ | ||
784 | dev->int_out_endpoint = endpoint; | ||
785 | } | ||
786 | /* we have to check the report_size often, so remember it in the endianess suitable for our machine */ | ||
787 | dev->report_size = le16_to_cpu(dev->int_in_endpoint->wMaxPacketSize); | ||
788 | if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) && | ||
789 | (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56)) | ||
790 | /* IOWarrior56 has wMaxPacketSize different from report size */ | ||
791 | dev->report_size = 7; | ||
792 | |||
793 | /* create the urb and buffer for reading */ | ||
794 | dev->int_in_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
795 | if (!dev->int_in_urb) { | ||
796 | dev_err(&interface->dev, "Couldn't allocate interrupt_in_urb\n"); | ||
797 | goto error; | ||
798 | } | ||
799 | dev->int_in_buffer = kmalloc(dev->report_size, GFP_KERNEL); | ||
800 | if (!dev->int_in_buffer) { | ||
801 | dev_err(&interface->dev, "Couldn't allocate int_in_buffer\n"); | ||
802 | goto error; | ||
803 | } | ||
804 | usb_fill_int_urb(dev->int_in_urb, dev->udev, | ||
805 | usb_rcvintpipe(dev->udev, | ||
806 | dev->int_in_endpoint->bEndpointAddress), | ||
807 | dev->int_in_buffer, dev->report_size, | ||
808 | iowarrior_callback, dev, | ||
809 | dev->int_in_endpoint->bInterval); | ||
810 | /* create an internal buffer for interrupt data from the device */ | ||
811 | dev->read_queue = | ||
812 | kmalloc(((dev->report_size + 1) * MAX_INTERRUPT_BUFFER), | ||
813 | GFP_KERNEL); | ||
814 | if (!dev->read_queue) { | ||
815 | dev_err(&interface->dev, "Couldn't allocate read_queue\n"); | ||
816 | goto error; | ||
817 | } | ||
818 | /* Get the serial-number of the chip */ | ||
819 | memset(dev->chip_serial, 0x00, sizeof(dev->chip_serial)); | ||
820 | usb_string(udev, udev->descriptor.iSerialNumber, dev->chip_serial, | ||
821 | sizeof(dev->chip_serial)); | ||
822 | if (strlen(dev->chip_serial) != 8) | ||
823 | memset(dev->chip_serial, 0x00, sizeof(dev->chip_serial)); | ||
824 | |||
825 | /* Set the idle timeout to 0, if this is interface 0 */ | ||
826 | if (dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) { | ||
827 | idele = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
828 | 0x0A, | ||
829 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, | ||
830 | 0, NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
831 | dbg("idele = %d", idele); | ||
832 | } | ||
833 | /* allow device read and ioctl */ | ||
834 | dev->present = 1; | ||
835 | |||
836 | /* we can register the device now, as it is ready */ | ||
837 | usb_set_intfdata(interface, dev); | ||
838 | |||
839 | retval = usb_register_dev(interface, &iowarrior_class); | ||
840 | if (retval) { | ||
841 | /* something prevented us from registering this driver */ | ||
842 | dev_err(&interface->dev, "Not able to get a minor for this device.\n"); | ||
843 | usb_set_intfdata(interface, NULL); | ||
844 | goto error; | ||
845 | } | ||
846 | |||
847 | dev->minor = interface->minor; | ||
848 | |||
849 | /* let the user know what node this device is now attached to */ | ||
850 | dev_info(&interface->dev, "IOWarrior product=0x%x, serial=%s interface=%d " | ||
851 | "now attached to iowarrior%d\n", dev->product_id, dev->chip_serial, | ||
852 | iface_desc->desc.bInterfaceNumber, dev->minor - IOWARRIOR_MINOR_BASE); | ||
853 | return retval; | ||
854 | |||
855 | error: | ||
856 | iowarrior_delete(dev); | ||
857 | return retval; | ||
858 | } | ||
859 | |||
860 | /** | ||
861 | * iowarrior_disconnect | ||
862 | * | ||
863 | * Called by the usb core when the device is removed from the system. | ||
864 | */ | ||
865 | static void iowarrior_disconnect(struct usb_interface *interface) | ||
866 | { | ||
867 | struct iowarrior *dev; | ||
868 | int minor; | ||
869 | |||
870 | /* prevent races with open() */ | ||
871 | down(&disconnect_sem); | ||
872 | |||
873 | dev = usb_get_intfdata(interface); | ||
874 | usb_set_intfdata(interface, NULL); | ||
875 | |||
876 | mutex_lock(&dev->mutex); | ||
877 | |||
878 | minor = dev->minor; | ||
879 | |||
880 | /* give back our minor */ | ||
881 | usb_deregister_dev(interface, &iowarrior_class); | ||
882 | |||
883 | /* prevent device read, write and ioctl */ | ||
884 | dev->present = 0; | ||
885 | |||
886 | mutex_unlock(&dev->mutex); | ||
887 | |||
888 | if (dev->opened) { | ||
889 | /* There is a process that holds a filedescriptor to the device , | ||
890 | so we only shutdown read-/write-ops going on. | ||
891 | Deleting the device is postponed until close() was called. | ||
892 | */ | ||
893 | usb_kill_urb(dev->int_in_urb); | ||
894 | wake_up_interruptible(&dev->read_wait); | ||
895 | wake_up_interruptible(&dev->write_wait); | ||
896 | } else { | ||
897 | /* no process is using the device, cleanup now */ | ||
898 | iowarrior_delete(dev); | ||
899 | } | ||
900 | up(&disconnect_sem); | ||
901 | |||
902 | dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n", | ||
903 | minor - IOWARRIOR_MINOR_BASE); | ||
904 | } | ||
905 | |||
906 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
907 | static struct usb_driver iowarrior_driver = { | ||
908 | .name = "iowarrior", | ||
909 | .probe = iowarrior_probe, | ||
910 | .disconnect = iowarrior_disconnect, | ||
911 | .id_table = iowarrior_ids, | ||
912 | }; | ||
913 | |||
914 | static int __init iowarrior_init(void) | ||
915 | { | ||
916 | return usb_register(&iowarrior_driver); | ||
917 | } | ||
918 | |||
919 | static void __exit iowarrior_exit(void) | ||
920 | { | ||
921 | usb_deregister(&iowarrior_driver); | ||
922 | } | ||
923 | |||
924 | module_init(iowarrior_init); | ||
925 | module_exit(iowarrior_exit); | ||
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index c01dfe603672..b2bedd974ac3 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c | |||
@@ -1165,7 +1165,7 @@ err_dev: | |||
1165 | return rc; | 1165 | return rc; |
1166 | } | 1166 | } |
1167 | 1167 | ||
1168 | void __exit mon_bin_exit(void) | 1168 | void mon_bin_exit(void) |
1169 | { | 1169 | { |
1170 | cdev_del(&mon_bin_cdev); | 1170 | cdev_del(&mon_bin_cdev); |
1171 | unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR); | 1171 | unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR); |
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index d38a1279d9d9..494ee3b9a226 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c | |||
@@ -520,7 +520,7 @@ int __init mon_text_init(void) | |||
520 | return 0; | 520 | return 0; |
521 | } | 521 | } |
522 | 522 | ||
523 | void __exit mon_text_exit(void) | 523 | void mon_text_exit(void) |
524 | { | 524 | { |
525 | debugfs_remove(mon_dir); | 525 | debugfs_remove(mon_dir); |
526 | } | 526 | } |
diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h index 4f949ce8a7f3..efdfd8993d9e 100644 --- a/drivers/usb/mon/usb_mon.h +++ b/drivers/usb/mon/usb_mon.h | |||
@@ -57,9 +57,9 @@ void mon_text_del(struct mon_bus *mbus); | |||
57 | // void mon_bin_add(struct mon_bus *); | 57 | // void mon_bin_add(struct mon_bus *); |
58 | 58 | ||
59 | int __init mon_text_init(void); | 59 | int __init mon_text_init(void); |
60 | void __exit mon_text_exit(void); | 60 | void mon_text_exit(void); |
61 | int __init mon_bin_init(void); | 61 | int __init mon_bin_init(void); |
62 | void __exit mon_bin_exit(void); | 62 | void mon_bin_exit(void); |
63 | 63 | ||
64 | /* | 64 | /* |
65 | * DMA interface. | 65 | * DMA interface. |
diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig index 0f3d7dbb537f..3de564b23147 100644 --- a/drivers/usb/net/Kconfig +++ b/drivers/usb/net/Kconfig | |||
@@ -186,6 +186,15 @@ config USB_NET_CDCETHER | |||
186 | IEEE 802 "local assignment" bit is set in the address, a "usbX" | 186 | IEEE 802 "local assignment" bit is set in the address, a "usbX" |
187 | name is used instead. | 187 | name is used instead. |
188 | 188 | ||
189 | config USB_NET_DM9601 | ||
190 | tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices" | ||
191 | depends on USB_USBNET | ||
192 | select CRC32 | ||
193 | select USB_USBNET_MII | ||
194 | help | ||
195 | This option adds support for Davicom DM9601 based USB 1.1 | ||
196 | 10/100 Ethernet adapters. | ||
197 | |||
189 | config USB_NET_GL620A | 198 | config USB_NET_GL620A |
190 | tristate "GeneSys GL620USB-A based cables" | 199 | tristate "GeneSys GL620USB-A based cables" |
191 | depends on USB_USBNET | 200 | depends on USB_USBNET |
diff --git a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile index 7b51964de171..595a539f8384 100644 --- a/drivers/usb/net/Makefile +++ b/drivers/usb/net/Makefile | |||
@@ -8,6 +8,7 @@ obj-$(CONFIG_USB_PEGASUS) += pegasus.o | |||
8 | obj-$(CONFIG_USB_RTL8150) += rtl8150.o | 8 | obj-$(CONFIG_USB_RTL8150) += rtl8150.o |
9 | obj-$(CONFIG_USB_NET_AX8817X) += asix.o | 9 | obj-$(CONFIG_USB_NET_AX8817X) += asix.o |
10 | obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o | 10 | obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o |
11 | obj-$(CONFIG_USB_NET_DM9601) += dm9601.o | ||
11 | obj-$(CONFIG_USB_NET_GL620A) += gl620a.o | 12 | obj-$(CONFIG_USB_NET_GL620A) += gl620a.o |
12 | obj-$(CONFIG_USB_NET_NET1080) += net1080.o | 13 | obj-$(CONFIG_USB_NET_NET1080) += net1080.o |
13 | obj-$(CONFIG_USB_NET_PLUSB) += plusb.o | 14 | obj-$(CONFIG_USB_NET_PLUSB) += plusb.o |
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c index 7ef2e4b5e39b..5808ea082459 100644 --- a/drivers/usb/net/asix.c +++ b/drivers/usb/net/asix.c | |||
@@ -1395,9 +1395,9 @@ static const struct usb_device_id products [] = { | |||
1395 | USB_DEVICE (0x07b8, 0x420a), | 1395 | USB_DEVICE (0x07b8, 0x420a), |
1396 | .driver_info = (unsigned long) &hawking_uf200_info, | 1396 | .driver_info = (unsigned long) &hawking_uf200_info, |
1397 | }, { | 1397 | }, { |
1398 | // Billionton Systems, USB2AR | 1398 | // Billionton Systems, USB2AR |
1399 | USB_DEVICE (0x08dd, 0x90ff), | 1399 | USB_DEVICE (0x08dd, 0x90ff), |
1400 | .driver_info = (unsigned long) &ax8817x_info, | 1400 | .driver_info = (unsigned long) &ax8817x_info, |
1401 | }, { | 1401 | }, { |
1402 | // ATEN UC210T | 1402 | // ATEN UC210T |
1403 | USB_DEVICE (0x0557, 0x2009), | 1403 | USB_DEVICE (0x0557, 0x2009), |
@@ -1423,9 +1423,13 @@ static const struct usb_device_id products [] = { | |||
1423 | USB_DEVICE (0x1631, 0x6200), | 1423 | USB_DEVICE (0x1631, 0x6200), |
1424 | .driver_info = (unsigned long) &ax8817x_info, | 1424 | .driver_info = (unsigned long) &ax8817x_info, |
1425 | }, { | 1425 | }, { |
1426 | // JVC MP-PRX1 Port Replicator | ||
1427 | USB_DEVICE (0x04f1, 0x3008), | ||
1428 | .driver_info = (unsigned long) &ax8817x_info, | ||
1429 | }, { | ||
1426 | // ASIX AX88772 10/100 | 1430 | // ASIX AX88772 10/100 |
1427 | USB_DEVICE (0x0b95, 0x7720), | 1431 | USB_DEVICE (0x0b95, 0x7720), |
1428 | .driver_info = (unsigned long) &ax88772_info, | 1432 | .driver_info = (unsigned long) &ax88772_info, |
1429 | }, { | 1433 | }, { |
1430 | // ASIX AX88178 10/100/1000 | 1434 | // ASIX AX88178 10/100/1000 |
1431 | USB_DEVICE (0x0b95, 0x1780), | 1435 | USB_DEVICE (0x0b95, 0x1780), |
diff --git a/drivers/usb/net/dm9601.c b/drivers/usb/net/dm9601.c new file mode 100644 index 000000000000..4a932e1cd93b --- /dev/null +++ b/drivers/usb/net/dm9601.c | |||
@@ -0,0 +1,606 @@ | |||
1 | /* | ||
2 | * Davicom DM9601 USB 1.1 10/100Mbps ethernet devices | ||
3 | * | ||
4 | * Peter Korsgaard <jacmet@sunsite.dk> | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public License | ||
7 | * version 2. This program is licensed "as is" without any warranty of any | ||
8 | * kind, whether express or implied. | ||
9 | */ | ||
10 | |||
11 | //#define DEBUG | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/netdevice.h> | ||
17 | #include <linux/etherdevice.h> | ||
18 | #include <linux/ethtool.h> | ||
19 | #include <linux/mii.h> | ||
20 | #include <linux/usb.h> | ||
21 | #include <linux/crc32.h> | ||
22 | |||
23 | #include "usbnet.h" | ||
24 | |||
25 | /* datasheet: | ||
26 | http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9601-DS-P01-930914.pdf | ||
27 | */ | ||
28 | |||
29 | /* control requests */ | ||
30 | #define DM_READ_REGS 0x00 | ||
31 | #define DM_WRITE_REGS 0x01 | ||
32 | #define DM_READ_MEMS 0x02 | ||
33 | #define DM_WRITE_REG 0x03 | ||
34 | #define DM_WRITE_MEMS 0x05 | ||
35 | #define DM_WRITE_MEM 0x07 | ||
36 | |||
37 | /* registers */ | ||
38 | #define DM_NET_CTRL 0x00 | ||
39 | #define DM_RX_CTRL 0x05 | ||
40 | #define DM_SHARED_CTRL 0x0b | ||
41 | #define DM_SHARED_ADDR 0x0c | ||
42 | #define DM_SHARED_DATA 0x0d /* low + high */ | ||
43 | #define DM_PHY_ADDR 0x10 /* 6 bytes */ | ||
44 | #define DM_MCAST_ADDR 0x16 /* 8 bytes */ | ||
45 | #define DM_GPR_CTRL 0x1e | ||
46 | #define DM_GPR_DATA 0x1f | ||
47 | |||
48 | #define DM_MAX_MCAST 64 | ||
49 | #define DM_MCAST_SIZE 8 | ||
50 | #define DM_EEPROM_LEN 256 | ||
51 | #define DM_TX_OVERHEAD 2 /* 2 byte header */ | ||
52 | #define DM_RX_OVERHEAD 7 /* 3 byte header + 4 byte crc tail */ | ||
53 | #define DM_TIMEOUT 1000 | ||
54 | |||
55 | |||
56 | static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data) | ||
57 | { | ||
58 | devdbg(dev, "dm_read() reg=0x%02x length=%d", reg, length); | ||
59 | return usb_control_msg(dev->udev, | ||
60 | usb_rcvctrlpipe(dev->udev, 0), | ||
61 | DM_READ_REGS, | ||
62 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
63 | 0, reg, data, length, USB_CTRL_SET_TIMEOUT); | ||
64 | } | ||
65 | |||
66 | static int dm_read_reg(struct usbnet *dev, u8 reg, u8 *value) | ||
67 | { | ||
68 | return dm_read(dev, reg, 1, value); | ||
69 | } | ||
70 | |||
71 | static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data) | ||
72 | { | ||
73 | devdbg(dev, "dm_write() reg=0x%02x, length=%d", reg, length); | ||
74 | return usb_control_msg(dev->udev, | ||
75 | usb_sndctrlpipe(dev->udev, 0), | ||
76 | DM_WRITE_REGS, | ||
77 | USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_DEVICE, | ||
78 | 0, reg, data, length, USB_CTRL_SET_TIMEOUT); | ||
79 | } | ||
80 | |||
81 | static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value) | ||
82 | { | ||
83 | devdbg(dev, "dm_write_reg() reg=0x%02x, value=0x%02x", reg, value); | ||
84 | return usb_control_msg(dev->udev, | ||
85 | usb_sndctrlpipe(dev->udev, 0), | ||
86 | DM_WRITE_REG, | ||
87 | USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_DEVICE, | ||
88 | value, reg, 0, 0, USB_CTRL_SET_TIMEOUT); | ||
89 | } | ||
90 | |||
91 | static void dm_write_async_callback(struct urb *urb) | ||
92 | { | ||
93 | struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context; | ||
94 | |||
95 | if (urb->status < 0) | ||
96 | printk(KERN_DEBUG "dm_write_async_callback() failed with %d", | ||
97 | urb->status); | ||
98 | |||
99 | kfree(req); | ||
100 | usb_free_urb(urb); | ||
101 | } | ||
102 | |||
103 | static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data) | ||
104 | { | ||
105 | struct usb_ctrlrequest *req; | ||
106 | struct urb *urb; | ||
107 | int status; | ||
108 | |||
109 | devdbg(dev, "dm_write_async() reg=0x%02x length=%d", reg, length); | ||
110 | |||
111 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
112 | if (!urb) { | ||
113 | deverr(dev, "Error allocating URB in dm_write_async!"); | ||
114 | return; | ||
115 | } | ||
116 | |||
117 | req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC); | ||
118 | if (!req) { | ||
119 | deverr(dev, "Failed to allocate memory for control request"); | ||
120 | usb_free_urb(urb); | ||
121 | return; | ||
122 | } | ||
123 | |||
124 | req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; | ||
125 | req->bRequest = DM_WRITE_REGS; | ||
126 | req->wValue = 0; | ||
127 | req->wIndex = cpu_to_le16(reg); | ||
128 | req->wLength = cpu_to_le16(length); | ||
129 | |||
130 | usb_fill_control_urb(urb, dev->udev, | ||
131 | usb_sndctrlpipe(dev->udev, 0), | ||
132 | (void *)req, data, length, | ||
133 | dm_write_async_callback, req); | ||
134 | |||
135 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
136 | if (status < 0) { | ||
137 | deverr(dev, "Error submitting the control message: status=%d", | ||
138 | status); | ||
139 | kfree(req); | ||
140 | usb_free_urb(urb); | ||
141 | } | ||
142 | } | ||
143 | |||
144 | static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value) | ||
145 | { | ||
146 | struct usb_ctrlrequest *req; | ||
147 | struct urb *urb; | ||
148 | int status; | ||
149 | |||
150 | devdbg(dev, "dm_write_reg_async() reg=0x%02x value=0x%02x", | ||
151 | reg, value); | ||
152 | |||
153 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
154 | if (!urb) { | ||
155 | deverr(dev, "Error allocating URB in dm_write_async!"); | ||
156 | return; | ||
157 | } | ||
158 | |||
159 | req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC); | ||
160 | if (!req) { | ||
161 | deverr(dev, "Failed to allocate memory for control request"); | ||
162 | usb_free_urb(urb); | ||
163 | return; | ||
164 | } | ||
165 | |||
166 | req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; | ||
167 | req->bRequest = DM_WRITE_REG; | ||
168 | req->wValue = cpu_to_le16(value); | ||
169 | req->wIndex = cpu_to_le16(reg); | ||
170 | req->wLength = 0; | ||
171 | |||
172 | usb_fill_control_urb(urb, dev->udev, | ||
173 | usb_sndctrlpipe(dev->udev, 0), | ||
174 | (void *)req, 0, 0, dm_write_async_callback, req); | ||
175 | |||
176 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
177 | if (status < 0) { | ||
178 | deverr(dev, "Error submitting the control message: status=%d", | ||
179 | status); | ||
180 | kfree(req); | ||
181 | usb_free_urb(urb); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, u16 *value) | ||
186 | { | ||
187 | int ret, i; | ||
188 | |||
189 | mutex_lock(&dev->phy_mutex); | ||
190 | |||
191 | dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg); | ||
192 | dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0xc : 0x4); | ||
193 | |||
194 | for (i = 0; i < DM_TIMEOUT; i++) { | ||
195 | u8 tmp; | ||
196 | |||
197 | udelay(1); | ||
198 | ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp); | ||
199 | if (ret < 0) | ||
200 | goto out; | ||
201 | |||
202 | /* ready */ | ||
203 | if ((tmp & 1) == 0) | ||
204 | break; | ||
205 | } | ||
206 | |||
207 | if (i == DM_TIMEOUT) { | ||
208 | deverr(dev, "%s read timed out!", phy ? "phy" : "eeprom"); | ||
209 | ret = -EIO; | ||
210 | goto out; | ||
211 | } | ||
212 | |||
213 | dm_write_reg(dev, DM_SHARED_CTRL, 0x0); | ||
214 | ret = dm_read(dev, DM_SHARED_DATA, 2, value); | ||
215 | |||
216 | devdbg(dev, "read shared %d 0x%02x returned 0x%04x, %d", | ||
217 | phy, reg, *value, ret); | ||
218 | |||
219 | out: | ||
220 | mutex_unlock(&dev->phy_mutex); | ||
221 | return ret; | ||
222 | } | ||
223 | |||
224 | static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, u16 value) | ||
225 | { | ||
226 | int ret, i; | ||
227 | |||
228 | mutex_lock(&dev->phy_mutex); | ||
229 | |||
230 | ret = dm_write(dev, DM_SHARED_DATA, 2, &value); | ||
231 | if (ret < 0) | ||
232 | goto out; | ||
233 | |||
234 | dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg); | ||
235 | dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1c : 0x14); | ||
236 | |||
237 | for (i = 0; i < DM_TIMEOUT; i++) { | ||
238 | u8 tmp; | ||
239 | |||
240 | udelay(1); | ||
241 | ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp); | ||
242 | if (ret < 0) | ||
243 | goto out; | ||
244 | |||
245 | /* ready */ | ||
246 | if ((tmp & 1) == 0) | ||
247 | break; | ||
248 | } | ||
249 | |||
250 | if (i == DM_TIMEOUT) { | ||
251 | deverr(dev, "%s write timed out!", phy ? "phy" : "eeprom"); | ||
252 | ret = -EIO; | ||
253 | goto out; | ||
254 | } | ||
255 | |||
256 | dm_write_reg(dev, DM_SHARED_CTRL, 0x0); | ||
257 | |||
258 | out: | ||
259 | mutex_unlock(&dev->phy_mutex); | ||
260 | return ret; | ||
261 | } | ||
262 | |||
263 | static int dm_read_eeprom_word(struct usbnet *dev, u8 offset, void *value) | ||
264 | { | ||
265 | return dm_read_shared_word(dev, 0, offset, value); | ||
266 | } | ||
267 | |||
268 | |||
269 | |||
270 | static int dm9601_get_eeprom_len(struct net_device *dev) | ||
271 | { | ||
272 | return DM_EEPROM_LEN; | ||
273 | } | ||
274 | |||
275 | static int dm9601_get_eeprom(struct net_device *net, | ||
276 | struct ethtool_eeprom *eeprom, u8 * data) | ||
277 | { | ||
278 | struct usbnet *dev = netdev_priv(net); | ||
279 | u16 *ebuf = (u16 *) data; | ||
280 | int i; | ||
281 | |||
282 | /* access is 16bit */ | ||
283 | if ((eeprom->offset % 2) || (eeprom->len % 2)) | ||
284 | return -EINVAL; | ||
285 | |||
286 | for (i = 0; i < eeprom->len / 2; i++) { | ||
287 | if (dm_read_eeprom_word(dev, eeprom->offset / 2 + i, | ||
288 | &ebuf[i]) < 0) | ||
289 | return -EINVAL; | ||
290 | } | ||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | static int dm9601_mdio_read(struct net_device *netdev, int phy_id, int loc) | ||
295 | { | ||
296 | struct usbnet *dev = netdev_priv(netdev); | ||
297 | |||
298 | u16 res; | ||
299 | |||
300 | if (phy_id) { | ||
301 | devdbg(dev, "Only internal phy supported"); | ||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | dm_read_shared_word(dev, 1, loc, &res); | ||
306 | |||
307 | devdbg(dev, | ||
308 | "dm9601_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x", | ||
309 | phy_id, loc, le16_to_cpu(res)); | ||
310 | |||
311 | return le16_to_cpu(res); | ||
312 | } | ||
313 | |||
314 | static void dm9601_mdio_write(struct net_device *netdev, int phy_id, int loc, | ||
315 | int val) | ||
316 | { | ||
317 | struct usbnet *dev = netdev_priv(netdev); | ||
318 | u16 res = cpu_to_le16(val); | ||
319 | |||
320 | if (phy_id) { | ||
321 | devdbg(dev, "Only internal phy supported"); | ||
322 | return; | ||
323 | } | ||
324 | |||
325 | devdbg(dev,"dm9601_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x", | ||
326 | phy_id, loc, val); | ||
327 | |||
328 | dm_write_shared_word(dev, 1, loc, res); | ||
329 | } | ||
330 | |||
331 | static void dm9601_get_drvinfo(struct net_device *net, | ||
332 | struct ethtool_drvinfo *info) | ||
333 | { | ||
334 | /* Inherit standard device info */ | ||
335 | usbnet_get_drvinfo(net, info); | ||
336 | info->eedump_len = DM_EEPROM_LEN; | ||
337 | } | ||
338 | |||
339 | static u32 dm9601_get_link(struct net_device *net) | ||
340 | { | ||
341 | struct usbnet *dev = netdev_priv(net); | ||
342 | |||
343 | return mii_link_ok(&dev->mii); | ||
344 | } | ||
345 | |||
346 | static int dm9601_ioctl(struct net_device *net, struct ifreq *rq, int cmd) | ||
347 | { | ||
348 | struct usbnet *dev = netdev_priv(net); | ||
349 | |||
350 | return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); | ||
351 | } | ||
352 | |||
353 | static struct ethtool_ops dm9601_ethtool_ops = { | ||
354 | .get_drvinfo = dm9601_get_drvinfo, | ||
355 | .get_link = dm9601_get_link, | ||
356 | .get_msglevel = usbnet_get_msglevel, | ||
357 | .set_msglevel = usbnet_set_msglevel, | ||
358 | .get_eeprom_len = dm9601_get_eeprom_len, | ||
359 | .get_eeprom = dm9601_get_eeprom, | ||
360 | .get_settings = usbnet_get_settings, | ||
361 | .set_settings = usbnet_set_settings, | ||
362 | .nway_reset = usbnet_nway_reset, | ||
363 | }; | ||
364 | |||
365 | static void dm9601_set_multicast(struct net_device *net) | ||
366 | { | ||
367 | struct usbnet *dev = netdev_priv(net); | ||
368 | /* We use the 20 byte dev->data for our 8 byte filter buffer | ||
369 | * to avoid allocating memory that is tricky to free later */ | ||
370 | u8 *hashes = (u8 *) & dev->data; | ||
371 | u8 rx_ctl = 0x01; | ||
372 | |||
373 | memset(hashes, 0x00, DM_MCAST_SIZE); | ||
374 | hashes[DM_MCAST_SIZE - 1] |= 0x80; /* broadcast address */ | ||
375 | |||
376 | if (net->flags & IFF_PROMISC) { | ||
377 | rx_ctl |= 0x02; | ||
378 | } else if (net->flags & IFF_ALLMULTI || net->mc_count > DM_MAX_MCAST) { | ||
379 | rx_ctl |= 0x04; | ||
380 | } else if (net->mc_count) { | ||
381 | struct dev_mc_list *mc_list = net->mc_list; | ||
382 | int i; | ||
383 | |||
384 | for (i = 0; i < net->mc_count; i++) { | ||
385 | u32 crc = ether_crc(ETH_ALEN, mc_list->dmi_addr) >> 26; | ||
386 | hashes[crc >> 3] |= 1 << (crc & 0x7); | ||
387 | } | ||
388 | } | ||
389 | |||
390 | dm_write_async(dev, DM_MCAST_ADDR, DM_MCAST_SIZE, hashes); | ||
391 | dm_write_reg_async(dev, DM_RX_CTRL, rx_ctl); | ||
392 | } | ||
393 | |||
394 | static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) | ||
395 | { | ||
396 | int ret; | ||
397 | |||
398 | ret = usbnet_get_endpoints(dev, intf); | ||
399 | if (ret) | ||
400 | goto out; | ||
401 | |||
402 | dev->net->do_ioctl = dm9601_ioctl; | ||
403 | dev->net->set_multicast_list = dm9601_set_multicast; | ||
404 | dev->net->ethtool_ops = &dm9601_ethtool_ops; | ||
405 | dev->net->hard_header_len += DM_TX_OVERHEAD; | ||
406 | dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; | ||
407 | dev->rx_urb_size = dev->net->mtu + DM_RX_OVERHEAD; | ||
408 | |||
409 | dev->mii.dev = dev->net; | ||
410 | dev->mii.mdio_read = dm9601_mdio_read; | ||
411 | dev->mii.mdio_write = dm9601_mdio_write; | ||
412 | dev->mii.phy_id_mask = 0x1f; | ||
413 | dev->mii.reg_num_mask = 0x1f; | ||
414 | |||
415 | /* reset */ | ||
416 | ret = dm_write_reg(dev, DM_NET_CTRL, 1); | ||
417 | udelay(20); | ||
418 | |||
419 | /* read MAC */ | ||
420 | ret = dm_read(dev, DM_PHY_ADDR, ETH_ALEN, dev->net->dev_addr); | ||
421 | if (ret < 0) { | ||
422 | printk(KERN_ERR "Error reading MAC address\n"); | ||
423 | ret = -ENODEV; | ||
424 | goto out; | ||
425 | } | ||
426 | |||
427 | |||
428 | /* power up phy */ | ||
429 | dm_write_reg(dev, DM_GPR_CTRL, 1); | ||
430 | dm_write_reg(dev, DM_GPR_DATA, 0); | ||
431 | |||
432 | /* receive broadcast packets */ | ||
433 | dm9601_set_multicast(dev->net); | ||
434 | |||
435 | dm9601_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); | ||
436 | dm9601_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, | ||
437 | ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); | ||
438 | mii_nway_restart(&dev->mii); | ||
439 | |||
440 | out: | ||
441 | return ret; | ||
442 | } | ||
443 | |||
444 | static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | ||
445 | { | ||
446 | u8 status; | ||
447 | int len; | ||
448 | |||
449 | /* format: | ||
450 | b0: rx status | ||
451 | b1: packet length (incl crc) low | ||
452 | b2: packet length (incl crc) high | ||
453 | b3..n-4: packet data | ||
454 | bn-3..bn: ethernet crc | ||
455 | */ | ||
456 | |||
457 | if (unlikely(skb->len < DM_RX_OVERHEAD)) { | ||
458 | dev_err(&dev->udev->dev, "unexpected tiny rx frame\n"); | ||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | status = skb->data[0]; | ||
463 | len = (skb->data[1] | (skb->data[2] << 8)) - 4; | ||
464 | |||
465 | if (unlikely(status & 0xbf)) { | ||
466 | if (status & 0x01) dev->stats.rx_fifo_errors++; | ||
467 | if (status & 0x02) dev->stats.rx_crc_errors++; | ||
468 | if (status & 0x04) dev->stats.rx_frame_errors++; | ||
469 | if (status & 0x20) dev->stats.rx_missed_errors++; | ||
470 | if (status & 0x90) dev->stats.rx_length_errors++; | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | skb_pull(skb, 3); | ||
475 | skb_trim(skb, len); | ||
476 | |||
477 | return 1; | ||
478 | } | ||
479 | |||
480 | static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb, | ||
481 | gfp_t flags) | ||
482 | { | ||
483 | int len; | ||
484 | |||
485 | /* format: | ||
486 | b0: packet length low | ||
487 | b1: packet length high | ||
488 | b3..n: packet data | ||
489 | */ | ||
490 | |||
491 | if (skb_headroom(skb) < DM_TX_OVERHEAD) { | ||
492 | struct sk_buff *skb2; | ||
493 | |||
494 | skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, 0, flags); | ||
495 | dev_kfree_skb_any(skb); | ||
496 | skb = skb2; | ||
497 | if (!skb) | ||
498 | return NULL; | ||
499 | } | ||
500 | |||
501 | __skb_push(skb, DM_TX_OVERHEAD); | ||
502 | |||
503 | len = skb->len; | ||
504 | /* usbnet adds padding if length is a multiple of packet size | ||
505 | if so, adjust length value in header */ | ||
506 | if ((len % dev->maxpacket) == 0) | ||
507 | len++; | ||
508 | |||
509 | skb->data[0] = len; | ||
510 | skb->data[1] = len >> 8; | ||
511 | |||
512 | return skb; | ||
513 | } | ||
514 | |||
515 | static void dm9601_status(struct usbnet *dev, struct urb *urb) | ||
516 | { | ||
517 | int link; | ||
518 | u8 *buf; | ||
519 | |||
520 | /* format: | ||
521 | b0: net status | ||
522 | b1: tx status 1 | ||
523 | b2: tx status 2 | ||
524 | b3: rx status | ||
525 | b4: rx overflow | ||
526 | b5: rx count | ||
527 | b6: tx count | ||
528 | b7: gpr | ||
529 | */ | ||
530 | |||
531 | if (urb->actual_length < 8) | ||
532 | return; | ||
533 | |||
534 | buf = urb->transfer_buffer; | ||
535 | |||
536 | link = !!(buf[0] & 0x40); | ||
537 | if (netif_carrier_ok(dev->net) != link) { | ||
538 | if (link) { | ||
539 | netif_carrier_on(dev->net); | ||
540 | usbnet_defer_kevent (dev, EVENT_LINK_RESET); | ||
541 | } | ||
542 | else | ||
543 | netif_carrier_off(dev->net); | ||
544 | devdbg(dev, "Link Status is: %d", link); | ||
545 | } | ||
546 | } | ||
547 | |||
548 | static int dm9601_link_reset(struct usbnet *dev) | ||
549 | { | ||
550 | struct ethtool_cmd ecmd; | ||
551 | |||
552 | mii_check_media(&dev->mii, 1, 1); | ||
553 | mii_ethtool_gset(&dev->mii, &ecmd); | ||
554 | |||
555 | devdbg(dev, "link_reset() speed: %d duplex: %d", | ||
556 | ecmd.speed, ecmd.duplex); | ||
557 | |||
558 | return 0; | ||
559 | } | ||
560 | |||
561 | static const struct driver_info dm9601_info = { | ||
562 | .description = "Davicom DM9601 USB Ethernet", | ||
563 | .flags = FLAG_ETHER, | ||
564 | .bind = dm9601_bind, | ||
565 | .rx_fixup = dm9601_rx_fixup, | ||
566 | .tx_fixup = dm9601_tx_fixup, | ||
567 | .status = dm9601_status, | ||
568 | .link_reset = dm9601_link_reset, | ||
569 | .reset = dm9601_link_reset, | ||
570 | }; | ||
571 | |||
572 | static const struct usb_device_id products[] = { | ||
573 | { | ||
574 | USB_DEVICE(0x0a46, 0x9601), /* Davicom USB-100 */ | ||
575 | .driver_info = (unsigned long)&dm9601_info, | ||
576 | }, | ||
577 | {}, // END | ||
578 | }; | ||
579 | |||
580 | MODULE_DEVICE_TABLE(usb, products); | ||
581 | |||
582 | static struct usb_driver dm9601_driver = { | ||
583 | .name = "dm9601", | ||
584 | .id_table = products, | ||
585 | .probe = usbnet_probe, | ||
586 | .disconnect = usbnet_disconnect, | ||
587 | .suspend = usbnet_suspend, | ||
588 | .resume = usbnet_resume, | ||
589 | }; | ||
590 | |||
591 | static int __init dm9601_init(void) | ||
592 | { | ||
593 | return usb_register(&dm9601_driver); | ||
594 | } | ||
595 | |||
596 | static void __exit dm9601_exit(void) | ||
597 | { | ||
598 | usb_deregister(&dm9601_driver); | ||
599 | } | ||
600 | |||
601 | module_init(dm9601_init); | ||
602 | module_exit(dm9601_exit); | ||
603 | |||
604 | MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>"); | ||
605 | MODULE_DESCRIPTION("Davicom DM9601 USB 1.1 ethernet devices"); | ||
606 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 4695952b6470..c525b42dadde 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -513,6 +513,7 @@ static struct usb_device_id id_table_combined [] = { | |||
513 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) }, | 513 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) }, |
514 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) }, | 514 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) }, |
515 | { USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) }, | 515 | { USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) }, |
516 | { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, | ||
516 | { }, /* Optional parameter entry */ | 517 | { }, /* Optional parameter entry */ |
517 | { } /* Terminating entry */ | 518 | { } /* Terminating entry */ |
518 | }; | 519 | }; |
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 7eff1c03ba80..1bdda935f7d9 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h | |||
@@ -491,6 +491,12 @@ | |||
491 | #define FTDI_TACTRIX_OPENPORT_13S_PID 0xCC49 /* OpenPort 1.3 Subaru */ | 491 | #define FTDI_TACTRIX_OPENPORT_13S_PID 0xCC49 /* OpenPort 1.3 Subaru */ |
492 | #define FTDI_TACTRIX_OPENPORT_13U_PID 0xCC4A /* OpenPort 1.3 Universal */ | 492 | #define FTDI_TACTRIX_OPENPORT_13U_PID 0xCC4A /* OpenPort 1.3 Universal */ |
493 | 493 | ||
494 | /* | ||
495 | * Telldus Technologies | ||
496 | */ | ||
497 | #define TELLDUS_VID 0x1781 /* Vendor ID */ | ||
498 | #define TELLDUS_TELLSTICK_PID 0x0C30 /* RF control dongle 433 MHz using FT232RL */ | ||
499 | |||
494 | /* Commands */ | 500 | /* Commands */ |
495 | #define FTDI_SIO_RESET 0 /* Reset the port */ | 501 | #define FTDI_SIO_RESET 0 /* Reset the port */ |
496 | #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ | 502 | #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ |
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 9963a8b75840..db92a7fb1f7c 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -67,50 +67,95 @@ static int option_tiocmset(struct usb_serial_port *port, struct file *file, | |||
67 | static int option_send_setup(struct usb_serial_port *port); | 67 | static int option_send_setup(struct usb_serial_port *port); |
68 | 68 | ||
69 | /* Vendor and product IDs */ | 69 | /* Vendor and product IDs */ |
70 | #define OPTION_VENDOR_ID 0x0AF0 | 70 | #define OPTION_VENDOR_ID 0x0AF0 |
71 | #define HUAWEI_VENDOR_ID 0x12D1 | 71 | #define OPTION_PRODUCT_COLT 0x5000 |
72 | #define NOVATELWIRELESS_VENDOR_ID 0x1410 | 72 | #define OPTION_PRODUCT_RICOLA 0x6000 |
73 | #define ANYDATA_VENDOR_ID 0x16d5 | 73 | #define OPTION_PRODUCT_RICOLA_LIGHT 0x6100 |
74 | 74 | #define OPTION_PRODUCT_RICOLA_QUAD 0x6200 | |
75 | #define OPTION_PRODUCT_OLD 0x5000 | 75 | #define OPTION_PRODUCT_RICOLA_QUAD_LIGHT 0x6300 |
76 | #define OPTION_PRODUCT_FUSION 0x6000 | 76 | #define OPTION_PRODUCT_RICOLA_NDIS 0x6050 |
77 | #define OPTION_PRODUCT_FUSION2 0x6300 | 77 | #define OPTION_PRODUCT_RICOLA_NDIS_LIGHT 0x6150 |
78 | #define OPTION_PRODUCT_COBRA 0x6500 | 78 | #define OPTION_PRODUCT_RICOLA_NDIS_QUAD 0x6250 |
79 | #define OPTION_PRODUCT_COBRA2 0x6600 | 79 | #define OPTION_PRODUCT_RICOLA_NDIS_QUAD_LIGHT 0x6350 |
80 | #define OPTION_PRODUCT_GTMAX36 0x6701 | 80 | #define OPTION_PRODUCT_COBRA 0x6500 |
81 | #define HUAWEI_PRODUCT_E600 0x1001 | 81 | #define OPTION_PRODUCT_COBRA_BUS 0x6501 |
82 | #define HUAWEI_PRODUCT_E220 0x1003 | 82 | #define OPTION_PRODUCT_VIPER 0x6600 |
83 | #define NOVATELWIRELESS_PRODUCT_U740 0x1400 | 83 | #define OPTION_PRODUCT_VIPER_BUS 0x6601 |
84 | #define ANYDATA_PRODUCT_ID 0x6501 | 84 | #define OPTION_PRODUCT_GT_MAX_READY 0x6701 |
85 | #define OPTION_PRODUCT_GT_MAX 0x6711 | ||
86 | #define OPTION_PRODUCT_FUJI_MODEM_LIGHT 0x6721 | ||
87 | #define OPTION_PRODUCT_FUJI_MODEM_GT 0x6741 | ||
88 | #define OPTION_PRODUCT_FUJI_MODEM_EX 0x6761 | ||
89 | #define OPTION_PRODUCT_FUJI_NETWORK_LIGHT 0x6731 | ||
90 | #define OPTION_PRODUCT_FUJI_NETWORK_GT 0x6751 | ||
91 | #define OPTION_PRODUCT_FUJI_NETWORK_EX 0x6771 | ||
92 | #define OPTION_PRODUCT_KOI_MODEM 0x6800 | ||
93 | #define OPTION_PRODUCT_KOI_NETWORK 0x6811 | ||
94 | #define OPTION_PRODUCT_SCORPION_MODEM 0x6901 | ||
95 | #define OPTION_PRODUCT_SCORPION_NETWORK 0x6911 | ||
96 | #define OPTION_PRODUCT_ETNA_MODEM 0x7001 | ||
97 | #define OPTION_PRODUCT_ETNA_NETWORK 0x7011 | ||
98 | #define OPTION_PRODUCT_ETNA_MODEM_LITE 0x7021 | ||
99 | #define OPTION_PRODUCT_ETNA_MODEM_GT 0x7041 | ||
100 | #define OPTION_PRODUCT_ETNA_MODEM_EX 0x7061 | ||
101 | #define OPTION_PRODUCT_ETNA_NETWORK_LITE 0x7031 | ||
102 | #define OPTION_PRODUCT_ETNA_NETWORK_GT 0x7051 | ||
103 | #define OPTION_PRODUCT_ETNA_NETWORK_EX 0x7071 | ||
104 | #define OPTION_PRODUCT_ETNA_KOI_MODEM 0x7100 | ||
105 | #define OPTION_PRODUCT_ETNA_KOI_NETWORK 0x7111 | ||
106 | |||
107 | #define HUAWEI_VENDOR_ID 0x12D1 | ||
108 | #define HUAWEI_PRODUCT_E600 0x1001 | ||
109 | #define HUAWEI_PRODUCT_E220 0x1003 | ||
110 | |||
111 | #define NOVATELWIRELESS_VENDOR_ID 0x1410 | ||
112 | #define NOVATELWIRELESS_PRODUCT_U740 0x1400 | ||
113 | |||
114 | #define ANYDATA_VENDOR_ID 0x16d5 | ||
115 | #define ANYDATA_PRODUCT_ID 0x6501 | ||
85 | 116 | ||
86 | static struct usb_device_id option_ids[] = { | 117 | static struct usb_device_id option_ids[] = { |
87 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, | 118 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, |
88 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) }, | 119 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, |
89 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) }, | 120 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) }, |
121 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD) }, | ||
122 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD_LIGHT) }, | ||
123 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS) }, | ||
124 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_LIGHT) }, | ||
125 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_QUAD) }, | ||
126 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_QUAD_LIGHT) }, | ||
90 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) }, | 127 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) }, |
91 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) }, | 128 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA_BUS) }, |
92 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) }, | 129 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_VIPER) }, |
130 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_VIPER_BUS) }, | ||
131 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GT_MAX_READY) }, | ||
132 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GT_MAX) }, | ||
133 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_LIGHT) }, | ||
134 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_GT) }, | ||
135 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_EX) }, | ||
136 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_LIGHT) }, | ||
137 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_GT) }, | ||
138 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_NETWORK_EX) }, | ||
139 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_KOI_MODEM) }, | ||
140 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_KOI_NETWORK) }, | ||
141 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_SCORPION_MODEM) }, | ||
142 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_SCORPION_NETWORK) }, | ||
143 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM) }, | ||
144 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK) }, | ||
145 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_LITE) }, | ||
146 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_GT) }, | ||
147 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_EX) }, | ||
148 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_LITE) }, | ||
149 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_GT) }, | ||
150 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_EX) }, | ||
151 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) }, | ||
152 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_NETWORK) }, | ||
93 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, | 153 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, |
94 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) }, | 154 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) }, |
95 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, | 155 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, |
96 | { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, | 156 | { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, |
97 | { } /* Terminating entry */ | 157 | { } /* Terminating entry */ |
98 | }; | 158 | }; |
99 | |||
100 | static struct usb_device_id option_ids1[] = { | ||
101 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, | ||
102 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) }, | ||
103 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) }, | ||
104 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) }, | ||
105 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) }, | ||
106 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) }, | ||
107 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, | ||
108 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) }, | ||
109 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, | ||
110 | { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, | ||
111 | { } /* Terminating entry */ | ||
112 | }; | ||
113 | |||
114 | MODULE_DEVICE_TABLE(usb, option_ids); | 159 | MODULE_DEVICE_TABLE(usb, option_ids); |
115 | 160 | ||
116 | static struct usb_driver option_driver = { | 161 | static struct usb_driver option_driver = { |
@@ -132,7 +177,7 @@ static struct usb_serial_driver option_1port_device = { | |||
132 | }, | 177 | }, |
133 | .description = "GSM modem (1-port)", | 178 | .description = "GSM modem (1-port)", |
134 | .usb_driver = &option_driver, | 179 | .usb_driver = &option_driver, |
135 | .id_table = option_ids1, | 180 | .id_table = option_ids, |
136 | .num_interrupt_in = NUM_DONT_CARE, | 181 | .num_interrupt_in = NUM_DONT_CARE, |
137 | .num_bulk_in = NUM_DONT_CARE, | 182 | .num_bulk_in = NUM_DONT_CARE, |
138 | .num_bulk_out = NUM_DONT_CARE, | 183 | .num_bulk_out = NUM_DONT_CARE, |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 98b0910ad80c..8d4d839a9d88 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -502,6 +502,30 @@ int sysfs_create_file(struct kobject * kobj, const struct attribute * attr) | |||
502 | 502 | ||
503 | 503 | ||
504 | /** | 504 | /** |
505 | * sysfs_add_file_to_group - add an attribute file to a pre-existing group. | ||
506 | * @kobj: object we're acting for. | ||
507 | * @attr: attribute descriptor. | ||
508 | * @group: group name. | ||
509 | */ | ||
510 | int sysfs_add_file_to_group(struct kobject *kobj, | ||
511 | const struct attribute *attr, const char *group) | ||
512 | { | ||
513 | struct dentry *dir; | ||
514 | int error; | ||
515 | |||
516 | dir = lookup_one_len(group, kobj->dentry, strlen(group)); | ||
517 | if (IS_ERR(dir)) | ||
518 | error = PTR_ERR(dir); | ||
519 | else { | ||
520 | error = sysfs_add_file(dir, attr, SYSFS_KOBJ_ATTR); | ||
521 | dput(dir); | ||
522 | } | ||
523 | return error; | ||
524 | } | ||
525 | EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); | ||
526 | |||
527 | |||
528 | /** | ||
505 | * sysfs_update_file - update the modified timestamp on an object attribute. | 529 | * sysfs_update_file - update the modified timestamp on an object attribute. |
506 | * @kobj: object we're acting for. | 530 | * @kobj: object we're acting for. |
507 | * @attr: attribute descriptor. | 531 | * @attr: attribute descriptor. |
@@ -586,6 +610,26 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) | |||
586 | } | 610 | } |
587 | 611 | ||
588 | 612 | ||
613 | /** | ||
614 | * sysfs_remove_file_from_group - remove an attribute file from a group. | ||
615 | * @kobj: object we're acting for. | ||
616 | * @attr: attribute descriptor. | ||
617 | * @group: group name. | ||
618 | */ | ||
619 | void sysfs_remove_file_from_group(struct kobject *kobj, | ||
620 | const struct attribute *attr, const char *group) | ||
621 | { | ||
622 | struct dentry *dir; | ||
623 | |||
624 | dir = lookup_one_len(group, kobj->dentry, strlen(group)); | ||
625 | if (!IS_ERR(dir)) { | ||
626 | sysfs_hash_and_remove(dir, attr->name); | ||
627 | dput(dir); | ||
628 | } | ||
629 | } | ||
630 | EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group); | ||
631 | |||
632 | |||
589 | EXPORT_SYMBOL_GPL(sysfs_create_file); | 633 | EXPORT_SYMBOL_GPL(sysfs_create_file); |
590 | EXPORT_SYMBOL_GPL(sysfs_remove_file); | 634 | EXPORT_SYMBOL_GPL(sysfs_remove_file); |
591 | EXPORT_SYMBOL_GPL(sysfs_update_file); | 635 | EXPORT_SYMBOL_GPL(sysfs_update_file); |
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 192de3afa96b..f45450b295c0 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h | |||
@@ -126,6 +126,11 @@ void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr); | |||
126 | int __must_check sysfs_create_group(struct kobject *, | 126 | int __must_check sysfs_create_group(struct kobject *, |
127 | const struct attribute_group *); | 127 | const struct attribute_group *); |
128 | void sysfs_remove_group(struct kobject *, const struct attribute_group *); | 128 | void sysfs_remove_group(struct kobject *, const struct attribute_group *); |
129 | int sysfs_add_file_to_group(struct kobject *kobj, | ||
130 | const struct attribute *attr, const char *group); | ||
131 | void sysfs_remove_file_from_group(struct kobject *kobj, | ||
132 | const struct attribute *attr, const char *group); | ||
133 | |||
129 | void sysfs_notify(struct kobject * k, char *dir, char *attr); | 134 | void sysfs_notify(struct kobject * k, char *dir, char *attr); |
130 | 135 | ||
131 | 136 | ||
@@ -210,6 +215,18 @@ static inline void sysfs_remove_group(struct kobject * k, const struct attribute | |||
210 | ; | 215 | ; |
211 | } | 216 | } |
212 | 217 | ||
218 | static inline int sysfs_add_file_to_group(struct kobject *kobj, | ||
219 | const struct attribute *attr, const char *group) | ||
220 | { | ||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static inline void sysfs_remove_file_from_group(struct kobject *kobj, | ||
225 | const struct attribute *attr, const char *group); | ||
226 | { | ||
227 | ; | ||
228 | } | ||
229 | |||
213 | static inline void sysfs_notify(struct kobject * k, char *dir, char *attr) | 230 | static inline void sysfs_notify(struct kobject * k, char *dir, char *attr) |
214 | { | 231 | { |
215 | } | 232 | } |
diff --git a/include/linux/usb.h b/include/linux/usb.h index a8e8d1ecebb1..87dc75a6cee1 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
@@ -388,10 +388,14 @@ struct usb_device { | |||
388 | struct usb_device *children[USB_MAXCHILDREN]; | 388 | struct usb_device *children[USB_MAXCHILDREN]; |
389 | 389 | ||
390 | int pm_usage_cnt; /* usage counter for autosuspend */ | 390 | int pm_usage_cnt; /* usage counter for autosuspend */ |
391 | u32 quirks; /* quirks of the whole device */ | ||
392 | |||
391 | #ifdef CONFIG_PM | 393 | #ifdef CONFIG_PM |
392 | struct delayed_work autosuspend; /* for delayed autosuspends */ | 394 | struct delayed_work autosuspend; /* for delayed autosuspends */ |
393 | struct mutex pm_mutex; /* protects PM operations */ | 395 | struct mutex pm_mutex; /* protects PM operations */ |
394 | 396 | ||
397 | unsigned autosuspend_delay; /* in jiffies */ | ||
398 | |||
395 | unsigned auto_pm:1; /* autosuspend/resume in progress */ | 399 | unsigned auto_pm:1; /* autosuspend/resume in progress */ |
396 | unsigned do_remote_wakeup:1; /* remote wakeup should be enabled */ | 400 | unsigned do_remote_wakeup:1; /* remote wakeup should be enabled */ |
397 | #endif | 401 | #endif |
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index 245c72531228..1122a6c2c1a3 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h | |||
@@ -1,8 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * This file holds USB constants and structures that are needed for USB | 2 | * This file holds USB constants and structures that are needed for |
3 | * device APIs. These are used by the USB device model, which is defined | 3 | * USB device APIs. These are used by the USB device model, which is |
4 | * in chapter 9 of the USB 2.0 specification. Linux has several APIs in C | 4 | * defined in chapter 9 of the USB 2.0 specification and in the |
5 | * that need these: | 5 | * Wireless USB 1.0 (spread around). Linux has several APIs in C that |
6 | * need these: | ||
6 | * | 7 | * |
7 | * - the master/host side Linux-USB kernel driver API; | 8 | * - the master/host side Linux-USB kernel driver API; |
8 | * - the "usbfs" user space API; and | 9 | * - the "usbfs" user space API; and |
@@ -14,6 +15,19 @@ | |||
14 | * | 15 | * |
15 | * There's also "Wireless USB", using low power short range radios for | 16 | * There's also "Wireless USB", using low power short range radios for |
16 | * peripheral interconnection but otherwise building on the USB framework. | 17 | * peripheral interconnection but otherwise building on the USB framework. |
18 | * | ||
19 | * Note all descriptors are declared '__attribute__((packed))' so that: | ||
20 | * | ||
21 | * [a] they never get padded, either internally (USB spec writers | ||
22 | * probably handled that) or externally; | ||
23 | * | ||
24 | * [b] so that accessing bigger-than-a-bytes fields will never | ||
25 | * generate bus errors on any platform, even when the location of | ||
26 | * its descriptor inside a bundle isn't "naturally aligned", and | ||
27 | * | ||
28 | * [c] for consistency, removing all doubt even when it appears to | ||
29 | * someone that the two other points are non-issues for that | ||
30 | * particular descriptor type. | ||
17 | */ | 31 | */ |
18 | 32 | ||
19 | #ifndef __LINUX_USB_CH9_H | 33 | #ifndef __LINUX_USB_CH9_H |
diff --git a/include/linux/usb/iowarrior.h b/include/linux/usb/iowarrior.h new file mode 100644 index 000000000000..cbbe020a4f5c --- /dev/null +++ b/include/linux/usb/iowarrior.h | |||
@@ -0,0 +1,33 @@ | |||
1 | #ifndef _IOWARRIOR_H_ | ||
2 | #define _IOWARRIOR_H_ | ||
3 | |||
4 | #define CODEMERCS_MAGIC_NUMBER 0xC0 /* like COde Mercenaries */ | ||
5 | |||
6 | /* Define the ioctl commands for reading and writing data */ | ||
7 | #define IOW_WRITE _IOW(CODEMERCS_MAGIC_NUMBER, 1, __u8 *) | ||
8 | #define IOW_READ _IOW(CODEMERCS_MAGIC_NUMBER, 2, __u8 *) | ||
9 | |||
10 | /* | ||
11 | A struct for available device info which is read | ||
12 | with the ioctl IOW_GETINFO. | ||
13 | To be compatible with 2.4 userspace which didn't have an easy way to get | ||
14 | this information. | ||
15 | */ | ||
16 | struct iowarrior_info { | ||
17 | __u32 vendor; /* vendor id : supposed to be USB_VENDOR_ID_CODEMERCS in all cases */ | ||
18 | __u32 product; /* product id : depends on type of chip (USB_DEVICE_ID_CODEMERCS_XXXXX) */ | ||
19 | __u8 serial[9]; /* the serial number of our chip (if a serial-number is not available this is empty string) */ | ||
20 | __u32 revision; /* revision number of the chip */ | ||
21 | __u32 speed; /* USB-speed of the device (0=UNKNOWN, 1=LOW, 2=FULL 3=HIGH) */ | ||
22 | __u32 power; /* power consumption of the device in mA */ | ||
23 | __u32 if_num; /* the number of the endpoint */ | ||
24 | __u32 report_size; /* size of the data-packets on this interface */ | ||
25 | }; | ||
26 | |||
27 | /* | ||
28 | Get some device-information (product-id , serial-number etc.) | ||
29 | in order to identify a chip. | ||
30 | */ | ||
31 | #define IOW_GETINFO _IOR(CODEMERCS_MAGIC_NUMBER, 3, struct iowarrior_info) | ||
32 | |||
33 | #endif /* _IOWARRIOR_H_ */ | ||
diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h new file mode 100644 index 000000000000..6bac8faacbc6 --- /dev/null +++ b/include/linux/usb/quirks.h | |||
@@ -0,0 +1,11 @@ | |||
1 | /* | ||
2 | * This file holds the definitions of quirks found in USB devices. | ||
3 | * Only quirks that affect the whole device, not an interface, | ||
4 | * belong here. | ||
5 | */ | ||
6 | |||
7 | /* device must not be autosuspended */ | ||
8 | #define USB_QUIRK_NO_AUTOSUSPEND 0x00000001 | ||
9 | |||
10 | /* string descriptors must not be fetched using a 255-byte read */ | ||
11 | #define USB_QUIRK_STRING_FETCH_255 0x00000002 | ||