diff options
Diffstat (limited to 'drivers/usb')
33 files changed, 767 insertions, 310 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index cd329dd7fb8..85dacc92545 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -20,6 +20,7 @@ config USB_ARCH_HAS_OHCI default y if SA1111 default y if ARCH_OMAP default y if ARCH_LH7A404 + default y if ARCH_S3C2410 default y if PXA27x # PPC: default y if STB03xxx diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index adff5a77e31..16ecad30e29 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -980,6 +980,9 @@ static struct usb_device_id acm_ids[] = { { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ }, + { USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */ + .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ + }, /* control interfaces with various AT-command sets */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_ACM_PROTO_AT_V25TER) }, diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 787c27a63c5..f86bf1454e2 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -569,8 +569,11 @@ static int proc_control(struct dev_state *ps, void __user *arg) free_page((unsigned long)tbuf); return -EINVAL; } - snoop(&dev->dev, "control read: bRequest=%02x bRrequestType=%02x wValue=%04x wIndex=%04x\n", - ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex); + snoop(&dev->dev, "control read: bRequest=%02x " + "bRrequestType=%02x wValue=%04x " + "wIndex=%04x wLength=%04x\n", + ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, + ctrl.wIndex, ctrl.wLength); usb_unlock_device(dev); i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType, @@ -579,11 +582,11 @@ static int proc_control(struct dev_state *ps, void __user *arg) if ((i > 0) && ctrl.wLength) { if (usbfs_snoop) { dev_info(&dev->dev, "control read: data "); - for (j = 0; j < ctrl.wLength; ++j) + for (j = 0; j < i; ++j) printk ("%02x ", (unsigned char)(tbuf)[j]); printk("\n"); } - if (copy_to_user(ctrl.data, tbuf, ctrl.wLength)) { + if (copy_to_user(ctrl.data, tbuf, i)) { free_page((unsigned long)tbuf); return -EFAULT; } @@ -595,8 +598,11 @@ static int proc_control(struct dev_state *ps, void __user *arg) return -EFAULT; } } - snoop(&dev->dev, "control write: bRequest=%02x bRrequestType=%02x wValue=%04x wIndex=%04x\n", - ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex); + snoop(&dev->dev, "control write: bRequest=%02x " + "bRrequestType=%02x wValue=%04x " + "wIndex=%04x wLength=%04x\n", + ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, + ctrl.wIndex, ctrl.wLength); if (usbfs_snoop) { dev_info(&dev->dev, "control write: data: "); for (j = 0; j < ctrl.wLength; ++j) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 8616356f55e..79422a3b07b 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -939,9 +939,9 @@ long usb_calc_bus_time (int speed, int is_input, int isoc, int bytecount) case USB_SPEED_HIGH: /* ISOC or INTR */ // FIXME adjust for input vs output if (isoc) - tmp = HS_USECS (bytecount); + tmp = HS_NSECS_ISO (bytecount); else - tmp = HS_USECS_ISO (bytecount); + tmp = HS_NSECS (bytecount); return tmp; default: pr_debug ("%s: bogus device speed!\n", usbcore_name); diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 67db4a999b9..28055f95645 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -334,17 +334,19 @@ extern void usb_release_bandwidth (struct usb_device *dev, struct urb *urb, extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb); /* - * Ceiling microseconds (typical) for that many bytes at high speed + * Ceiling [nano/micro]seconds (typical) for that many bytes at high speed * ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed * to preallocate bandwidth) */ #define USB2_HOST_DELAY 5 /* nsec, guess */ -#define HS_USECS(bytes) NS_TO_US ( ((55 * 8 * 2083)/1000) \ +#define HS_NSECS(bytes) ( ((55 * 8 * 2083)/1000) \ + ((2083UL * (3167 + BitTime (bytes)))/1000) \ + USB2_HOST_DELAY) -#define HS_USECS_ISO(bytes) NS_TO_US ( ((38 * 8 * 2083)/1000) \ +#define HS_NSECS_ISO(bytes) ( ((38 * 8 * 2083)/1000) \ + ((2083UL * (3167 + BitTime (bytes)))/1000) \ + USB2_HOST_DELAY) +#define HS_USECS(bytes) NS_TO_US (HS_NSECS(bytes)) +#define HS_USECS_ISO(bytes) NS_TO_US (HS_NSECS_ISO(bytes)) extern long usb_calc_bus_time (int speed, int is_input, int isoc, int bytecount); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index a428ef479bd..88d1b376f67 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -985,8 +985,10 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { struct usb_interface *interface; - /* remove this interface */ + /* remove this interface if it has been registered */ interface = dev->actconfig->interface[i]; + if (!klist_node_attached(&interface->dev.knode_bus)) + continue; dev_dbg (&dev->dev, "unregistering interface %s\n", interface->dev.bus_id); usb_remove_sysfs_intf_files(interface); @@ -1439,7 +1441,7 @@ free_interfaces: } } - return ret; + return 0; } // synchronous request completion model diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index d74b2d68a50..4f97a4ad1ed 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -657,8 +657,8 @@ qh_make ( * For control/bulk requests, the HC or TT handles these. */ if (type == PIPE_INTERRUPT) { - qh->usecs = usb_calc_bus_time (USB_SPEED_HIGH, is_input, 0, - hb_mult (maxp) * max_packet (maxp)); + qh->usecs = NS_TO_US (usb_calc_bus_time (USB_SPEED_HIGH, is_input, 0, + hb_mult (maxp) * max_packet (maxp))); qh->start = NO_FRAME; if (urb->dev->speed == USB_SPEED_HIGH) { diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 68decab280d..56b43f2a0e5 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -887,6 +887,10 @@ MODULE_LICENSE ("GPL"); #include "ohci-sa1111.c" #endif +#ifdef CONFIG_ARCH_S3C2410 +#include "ohci-s3c2410.c" +#endif + #ifdef CONFIG_ARCH_OMAP #include "ohci-omap.c" #endif @@ -909,6 +913,7 @@ MODULE_LICENSE ("GPL"); #if !(defined(CONFIG_PCI) \ || defined(CONFIG_SA1111) \ + || defined(CONFIG_ARCH_S3C2410) \ || defined(CONFIG_ARCH_OMAP) \ || defined (CONFIG_ARCH_LH7A404) \ || defined (CONFIG_PXA27x) \ diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c new file mode 100644 index 00000000000..e9401662503 --- /dev/null +++ b/drivers/usb/host/ohci-s3c2410.c @@ -0,0 +1,496 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> + * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> + * (C) Copyright 2002 Hewlett-Packard Company + * + * USB Bus Glue for Samsung S3C2410 + * + * Written by Christopher Hoover <ch@hpl.hp.com> + * Based on fragments of previous driver by Rusell King et al. + * + * Modified for S3C2410 from ohci-sa1111.c, ohci-omap.c and ohci-lh7a40.c + * by Ben Dooks, <ben@simtec.co.uk> + * Copyright (C) 2004 Simtec Electronics + * + * Thanks to basprog@mail.ru for updates to newer kernels + * + * This file is licenced under the GPL. +*/ + +#include <asm/hardware.h> +#include <asm/mach-types.h> +#include <asm/hardware/clock.h> +#include <asm/arch/usb-control.h> + +#define valid_port(idx) ((idx) == 1 || (idx) == 2) + +/* clock device associated with the hcd */ + +static struct clk *clk; + +/* forward definitions */ + +static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc); + +/* conversion functions */ + +struct s3c2410_hcd_info *to_s3c2410_info(struct usb_hcd *hcd) +{ + return hcd->self.controller->platform_data; +} + +static void s3c2410_start_hc(struct platform_device *dev, struct usb_hcd *hcd) +{ + struct s3c2410_hcd_info *info = dev->dev.platform_data; + + dev_dbg(&dev->dev, "s3c2410_start_hc:\n"); + clk_enable(clk); + + if (info != NULL) { + info->hcd = hcd; + info->report_oc = s3c2410_hcd_oc; + + if (info->enable_oc != NULL) { + (info->enable_oc)(info, 1); + } + } +} + +static void s3c2410_stop_hc(struct platform_device *dev) +{ + struct s3c2410_hcd_info *info = dev->dev.platform_data; + + dev_dbg(&dev->dev, "s3c2410_stop_hc:\n"); + + if (info != NULL) { + info->report_oc = NULL; + info->hcd = NULL; + + if (info->enable_oc != NULL) { + (info->enable_oc)(info, 0); + } + } + + clk_disable(clk); +} + +/* ohci_s3c2410_hub_status_data + * + * update the status data from the hub with anything that + * has been detected by our system +*/ + +static int +ohci_s3c2410_hub_status_data (struct usb_hcd *hcd, char *buf) +{ + struct s3c2410_hcd_info *info = to_s3c2410_info(hcd); + struct s3c2410_hcd_port *port; + int orig; + int portno; + + orig = ohci_hub_status_data (hcd, buf); + + if (info == NULL) + return orig; + + port = &info->port[0]; + + /* mark any changed port as changed */ + + for (portno = 0; portno < 2; port++, portno++) { + if (port->oc_changed == 1 && + port->flags & S3C_HCDFLG_USED) { + dev_dbg(hcd->self.controller, + "oc change on port %d\n", portno); + + if (orig < 1) + orig = 1; + + buf[0] |= 1<<(portno+1); + } + } + + return orig; +} + +/* s3c2410_usb_set_power + * + * configure the power on a port, by calling the platform device + * routine registered with the platform device +*/ + +static void s3c2410_usb_set_power(struct s3c2410_hcd_info *info, + int port, int to) +{ + if (info == NULL) + return; + + if (info->power_control != NULL) { + info->port[port-1].power = to; + (info->power_control)(port, to); + } +} + +/* ohci_s3c2410_hub_control + * + * look at control requests to the hub, and see if we need + * to take any action or over-ride the results from the + * request. +*/ + +static int ohci_s3c2410_hub_control ( + struct usb_hcd *hcd, + u16 typeReq, + u16 wValue, + u16 wIndex, + char *buf, + u16 wLength) +{ + struct s3c2410_hcd_info *info = to_s3c2410_info(hcd); + struct usb_hub_descriptor *desc; + int ret = -EINVAL; + u32 *data = (u32 *)buf; + + dev_dbg(hcd->self.controller, + "s3c2410_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n", + hcd, typeReq, wValue, wIndex, buf, wLength); + + /* if we are only an humble host without any special capabilites + * process the request straight away and exit */ + + if (info == NULL) { + ret = ohci_hub_control(hcd, typeReq, wValue, + wIndex, buf, wLength); + goto out; + } + + /* check the request to see if it needs handling */ + + switch (typeReq) { + case SetPortFeature: + if (wValue == USB_PORT_FEAT_POWER) { + dev_dbg(hcd->self.controller, "SetPortFeat: POWER\n"); + s3c2410_usb_set_power(info, wIndex, 1); + goto out; + } + break; + + case ClearPortFeature: + switch (wValue) { + case USB_PORT_FEAT_C_OVER_CURRENT: + dev_dbg(hcd->self.controller, + "ClearPortFeature: C_OVER_CURRENT\n"); + + if (valid_port(wIndex)) { + info->port[wIndex-1].oc_changed = 0; + info->port[wIndex-1].oc_status = 0; + } + + goto out; + + case USB_PORT_FEAT_OVER_CURRENT: + dev_dbg(hcd->self.controller, + "ClearPortFeature: OVER_CURRENT\n"); + + if (valid_port(wIndex)) { + info->port[wIndex-1].oc_status = 0; + } + + goto out; + + case USB_PORT_FEAT_POWER: + dev_dbg(hcd->self.controller, + "ClearPortFeature: POWER\n"); + + if (valid_port(wIndex)) { + s3c2410_usb_set_power(info, wIndex, 0); + return 0; + } + } + break; + } + + ret = ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); + if (ret) + goto out; + + switch (typeReq) { + case GetHubDescriptor: + + /* update the hub's descriptor */ + + desc = (struct usb_hub_descriptor *)buf; + + if (info->power_control == NULL) + return ret; + + dev_dbg(hcd->self.controller, "wHubCharacteristics 0x%04x\n", + desc->wHubCharacteristics); + + /* remove the old configurations for power-switching, and + * over-current protection, and insert our new configuration + */ + + desc->wHubCharacteristics &= ~cpu_to_le16(HUB_CHAR_LPSM); + desc->wHubCharacteristics |= cpu_to_le16(0x0001); + + if (info->enable_oc) { + desc->wHubCharacteristics &= ~cpu_to_le16(HUB_CHAR_OCPM); + desc->wHubCharacteristics |= cpu_to_le16(0x0008|0x0001); + } + + dev_dbg(hcd->self.controller, "wHubCharacteristics after 0x%04x\n", + desc->wHubCharacteristics); + + return ret; + + case GetPortStatus: + /* check port status */ + + dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex); + + if (valid_port(wIndex)) { + if (info->port[wIndex-1].oc_changed) { + *data |= cpu_to_le32(RH_PS_OCIC); + } + + if (info->port[wIndex-1].oc_status) { + *data |= cpu_to_le32(RH_PS_POCI); + } + } + } + + out: + return ret; +} + +/* s3c2410_hcd_oc + * + * handle an over-current report +*/ + +static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc) +{ + struct s3c2410_hcd_port *port; + struct usb_hcd *hcd; + unsigned long flags; + int portno; + + if (info == NULL) + return; + + port = &info->port[0]; + hcd = info->hcd; + + local_irq_save(flags); + + for (portno = 0; portno < 2; port++, portno++) { + if (port_oc & (1<<portno) && + port->flags & S3C_HCDFLG_USED) { + port->oc_status = 1; + port->oc_changed = 1; + + /* ok, once over-current is detected, + the port needs to be powered down */ + s3c2410_usb_set_power(info, portno+1, 0); + } + } + + local_irq_restore(flags); +} + +/* may be called without controller electrically present */ +/* may be called with controller, bus, and devices active */ + +/* + * usb_hcd_s3c2410_remove - shutdown processing for HCD + * @dev: USB Host Controller being removed + * Context: !in_interrupt() + * + * Reverses the effect of usb_hcd_3c2410_probe(), first invoking + * the HCD's stop() method. It is always called from a thread + * context, normally "rmmod", "apmd", or something similar. + * +*/ + +void usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev) +{ + usb_remove_hcd(hcd); + s3c2410_stop_hc(dev); + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + usb_put_hcd(hcd); +} + +/** + * usb_hcd_s3c2410_probe - initialize S3C2410-based HCDs + * Context: !in_interrupt() + * + * Allocates basic resources for this USB host controller, and + * then invokes the start() method for the HCD associated with it + * through the hotplug entry's driver_data. + * + */ +int usb_hcd_s3c2410_probe (const struct hc_driver *driver, + struct platform_device *dev) +{ + struct usb_hcd *hcd = NULL; + int retval; + + s3c2410_usb_set_power(dev->dev.platform_data, 0, 1); + s3c2410_usb_set_power(dev->dev.platform_data, 1, 1); + + hcd = usb_create_hcd(driver, &dev->dev, "s3c24xx"); + if (hcd == NULL) + return -ENOMEM; + + hcd->rsrc_start = dev->resource[0].start; + hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; + + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { + dev_err(&dev->dev, "request_mem_region failed"); + retval = -EBUSY; + goto err0; + } + + clk = clk_get(NULL, "usb-host"); + if (IS_ERR(clk)) { + dev_err(&dev->dev, "cannot get usb-host clock\n"); + retval = -ENOENT; + goto err1; + } + + clk_use(clk); + s3c2410_start_hc(dev, hcd); + + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + if (!hcd->regs) { + dev_err(&dev->dev, "ioremap failed\n"); + retval = -ENOMEM; + goto err2; + } + + ohci_hcd_init(hcd_to_ohci(hcd)); + + retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT); + if (retval != 0) + goto err2; + + return 0; + + err2: + s3c2410_stop_hc(dev); + iounmap(hcd->regs); + clk_unuse(clk); + clk_put(clk); + + err1: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + + err0: + usb_put_hcd(hcd); + return retval; +} + +/*-------------------------------------------------------------------------*/ + +static int +ohci_s3c2410_start (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int ret; + + if ((ret = ohci_init(ohci)) < 0) + return ret; + + if ((ret = ohci_run (ohci)) < 0) { + err ("can't start %s", hcd->self.bus_name); + ohci_stop (hcd); + return ret; + } + + return 0; +} + + +static const struct hc_driver ohci_s3c2410_hc_driver = { + .description = hcd_name, + .product_desc = "S3C24XX OHCI", + .hcd_priv_size = sizeof(struct ohci_hcd), + + /* + * generic hardware linkage + */ + .irq = ohci_irq, + .flags = HCD_USB11 | HCD_MEMORY, + + /* + * basic lifecycle operations + */ + .start = ohci_s3c2410_start, + .stop = ohci_stop, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ohci_urb_enqueue, + .urb_dequeue = ohci_urb_dequeue, + .endpoint_disable = ohci_endpoint_disable, + + /* + * scheduling support + */ + .get_frame_number = ohci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ohci_s3c2410_hub_status_data, + .hub_control = ohci_s3c2410_hub_control, + +#if defined(CONFIG_USB_SUSPEND) && 0 + .hub_suspend = ohci_hub_suspend, + .hub_resume = ohci_hub_resume, +#endif +}; + +/* device driver */ + +static int ohci_hcd_s3c2410_drv_probe(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + return usb_hcd_s3c2410_probe(&ohci_s3c2410_hc_driver, pdev); +} + +static int ohci_hcd_s3c2410_drv_remove(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct usb_hcd *hcd = dev_get_drvdata(dev); + + usb_hcd_s3c2410_remove(hcd, pdev); + return 0; +} + +static struct device_driver ohci_hcd_s3c2410_driver = { + .name = "s3c2410-ohci", + .bus = &platform_bus_type, + .probe = ohci_hcd_s3c2410_drv_probe, + .remove = ohci_hcd_s3c2410_drv_remove, + /*.suspend = ohci_hcd_s3c2410_drv_suspend, */ + /*.resume = ohci_hcd_s3c2410_drv_resume, */ +}; + +static int __init ohci_hcd_s3c2410_init (void) +{ + return driver_register(&ohci_hcd_s3c2410_driver); +} + +static void __exit ohci_hcd_s3c2410_cleanup (void) +{ + driver_unregister(&ohci_hcd_s3c2410_driver); +} + +module_init (ohci_hcd_s3c2410_init); +module_exit (ohci_hcd_s3c2410_cleanup); diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index 7d21a4f5c42..c84e1486054 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c @@ -361,8 +361,7 @@ int mts_scsi_queuecommand (Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback ); static void mts_transfer_cleanup( struct urb *transfer ); static void mts_do_sg(struct urb * transfer, struct pt_regs *regs); - -inline static +static inline void mts_int_submit_urb (struct urb* transfer, int pipe, void* data, diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c index ebcf7c95580..13532f3e3ef 100644 --- a/drivers/usb/input/acecad.c +++ b/drivers/usb/input/acecad.c @@ -31,6 +31,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/usb.h> +#include <linux/usb_input.h> /* * Version Information @@ -87,8 +88,8 @@ static void usb_acecad_irq(struct urb *urb, struct pt_regs *regs) if (prox) { int x = data[1] | (data[2] << 8); int y = data[3] | (data[4] << 8); - /*Pressure should compute the same way for flair and 302*/ - int pressure = data[5] | ((int)data[6] << 8); + /* Pressure should compute the same way for flair and 302 */ + int pressure = data[5] | (data[6] << 8); int touch = data[0] & 0x01; int stylus = (data[0] & 0x10) >> 4; int stylus2 = (data[0] & 0x20) >> 5; @@ -104,9 +105,9 @@ static void usb_acecad_irq(struct urb *urb, struct pt_regs *regs) input_sync(dev); resubmit: - status = usb_submit_urb (urb, GFP_ATOMIC); + status = usb_submit_urb(urb, GFP_ATOMIC); if (status) - err ("can't resubmit intr, %s-%s/input0, status %d", + err("can't resubmit intr, %s-%s/input0, status %d", acecad->usbdev->bus->bus_name, acecad->usbdev->devpath, status); } @@ -212,10 +213,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ acecad->dev.name = acecad->name; acecad->dev.phys = acecad->phys; - acecad->dev.id.bustype = BUS_USB; - acecad->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); - acecad->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); - acecad->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice); + usb_to_input_id(dev, &acecad->dev.id); acecad->dev.dev = &intf->dev; usb_fill_int_urb(acecad->irq, dev, pipe, diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c index 6bb0f25e8e9..cd0cbfe2072 100644 --- a/drivers/usb/input/aiptek.c +++ b/drivers/usb/input/aiptek.c @@ -77,6 +77,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/usb.h> +#include <linux/usb_input.h> #include <linux/sched.h> #include <asm/uaccess.h> #include <asm/unaligned.h> @@ -2125,10 +2126,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) aiptek->inputdev.absflat[ABS_WHEEL] = 0; aiptek->inputdev.name = "Aiptek"; aiptek->inputdev.phys = aiptek->features.usbPath; - aiptek->inputdev.id.bustype = BUS_USB; - aiptek->inputdev.id.vendor = le16_to_cpu(usbdev->descriptor.idVendor); - aiptek->inputdev.id.product = le16_to_cpu(usbdev->descriptor.idProduct); - aiptek->inputdev.id.version = le16_to_cpu(usbdev->descriptor.bcdDevice); + usb_to_input_id(usbdev, &aiptek->inputdev.id); aiptek->inputdev.dev = &intf->dev; aiptek->usbdev = usbdev; diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index 654ac454744..fd99681ee48 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c @@ -94,6 +94,7 @@ #include <linux/moduleparam.h> #include <linux/input.h> #include <linux/usb.h> +#include <linux/usb_input.h> #include <linux/wait.h> /* @@ -635,11 +636,8 @@ static void ati_remote_input_init(struct ati_remote *ati_remote) idev->name = ati_remote->name; idev->phys = ati_remote->phys; - idev->id.bustype = BUS_USB; - idev->id.vendor = le16_to_cpu(ati_remote->udev->descriptor.idVendor); - idev->id.product = le16_to_cpu(ati_remote->udev->descriptor.idProduct); - idev->id.version = le16_to_cpu(ati_remote->udev->descriptor.bcdDevice); - idev->dev = &(ati_remote->udev->dev); + usb_to_input_id(ati_remote->udev, &idev->id); + idev->dev = &ati_remote->udev->dev; } static int ati_remote_initialize(struct ati_remote *ati_remote) diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 2350e7a5ad7..b2cb2b35892 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -789,12 +789,12 @@ static __inline__ int search(__s32 *array, __s32 value, unsigned n) return -1; } -static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, struct pt_regs *regs) +static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, int interrupt, struct pt_regs *regs) { hid_dump_input(usage, value); if (hid->claimed & HID_CLAIMED_INPUT) hidinput_hid_event(hid, field, usage, value, regs); - if (hid->claimed & HID_CLAIMED_HIDDEV) + if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt) hiddev_hid_event(hid, field, usage, value, regs); } @@ -804,7 +804,7 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field, s * reporting to the layer). */ -static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, struct pt_regs *regs) +static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt, struct pt_regs *regs) { unsigned n; unsigned count = field->report_count; @@ -831,19 +831,19 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u for (n = 0; n < count; n++) { if (HID_MAIN_ITEM_VARIABLE & field->flags) { - hid_process_event(hid, field, &field->usage[n], value[n], regs); + hid_process_event(hid, field, &field->usage[n], value[n], interrupt, regs); continue; } if (field->value[n] >= min && field->value[n] <= max && field->usage[field->value[n] - min].hid && search(value, field->value[n], count)) - hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, regs); + hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt, regs); if (value[n] >= min && value[n] <= max && field->usage[value[n] - min].hid && search(field->value, value[n], count)) - hid_process_event(hid, field, &field->usage[value[n] - min], 1, regs); + hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt, regs); } memcpy(field->value, value, count * sizeof(__s32)); @@ -851,7 +851,7 @@ exit: kfree(value); } -static int hid_input_report(int type, struct urb *urb, struct pt_regs *regs) +static int hid_input_report(int type, struct urb *urb, int interrupt, struct pt_regs *regs) { struct hid_device *hid = urb->context; struct hid_report_enum *report_enum = hid->report_enum + type; @@ -899,7 +899,7 @@ static int hid_input_report(int type, struct urb *urb, struct pt_regs *regs) hiddev_report_event(hid, report); for (n = 0; n < report->maxfield; n++) - hid_input_field(hid, report->field[n], data, regs); + hid_input_field(hid, report->field[n], data, interrupt, regs); if (hid->claimed & HID_CLAIMED_INPUT) hidinput_report_event(hid, report); @@ -918,7 +918,7 @@ static void hid_irq_in(struct urb *urb, struct pt_regs *regs) switch (urb->status) { case 0: /* success */ - hid_input_report(HID_INPUT_REPORT, urb, regs); + hid_input_report(HID_INPUT_REPORT, urb, 1, regs); break; case -ECONNRESET: /* unlink */ case -ENOENT: @@ -1142,7 +1142,7 @@ static void hid_ctrl(struct urb *urb, struct pt_regs *regs) switch (urb->status) { case 0: /* success */ if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) - hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, regs); + hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0, regs); case -ESHUTDOWN: /* unplug */ case -EILSEQ: /* unplug timectrl on uhci */ unplug = 1; @@ -1372,6 +1372,9 @@ void hid_init_reports(struct hid_device *hid) #define USB_VENDOR_ID_A4TECH 0x09da #define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 +#define USB_VENDOR_ID_AASHIMA 0x06D6 +#define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025 + #define USB_VENDOR_ID_CYPRESS 0x04b4 #define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001 #define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500 @@ -1548,6 +1551,7 @@ static struct hid_blacklist { { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 }, { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 }, + { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 9ac1e909533..63a4db721f7 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c @@ -31,6 +31,7 @@ #include <linux/kernel.h> #include <linux/input.h> #include <linux/usb.h> +#include <linux/usb_input.h> #undef DEBUG @@ -397,11 +398,12 @@ ignore: void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, struct pt_regs *regs) { - struct input_dev *input = &field->hidinput->input; + struct input_dev *input; int *quirks = &hid->quirks; - if (!input) + if (!field->hidinput) return; + input = &field->hidinput->input; input_regs(input, regs); @@ -581,10 +583,7 @@ int hidinput_connect(struct hid_device *hid) hidinput->input.name = hid->name; hidinput->input.phys = hid->phys; hidinput->input.uniq = hid->uniq; - hidinput->input.id.bustype = BUS_USB; - hidinput->input.id.vendor = le16_to_cpu(dev->descriptor.idVendor); - hidinput->input.id.product = le16_to_cpu(dev->descriptor.idProduct); - hidinput->input.id.version = le16_to_cpu(dev->descriptor.bcdDevice); + usb_to_input_id(dev, &hidinput->input.id); hidinput->input.dev = &hid->intf->dev; } diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c index 47dec6a1b34..0dc439f1082 100644 --- a/drivers/usb/input/itmtouch.c +++ b/drivers/usb/input/itmtouch.c @@ -53,6 +53,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/usb.h> +#include <linux/usb_input.h> /* only an 8 byte buffer necessary for a single packet */ #define ITM_BUFSIZE 8 @@ -184,10 +185,7 @@ static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id itmtouch->inputdev.name = itmtouch->name; itmtouch->inputdev.phys = itmtouch->phys; - itmtouch->inputdev.id.bustype = BUS_USB; - itmtouch->inputdev.id.vendor = udev->descriptor.idVendor; - itmtouch->inputdev.id.product = udev->descriptor.idProduct; - itmtouch->inputdev.id.version = udev->descriptor.bcdDevice; + usb_to_input_id(udev, &itmtouch->inputdev.id); itmtouch->inputdev.dev = &intf->dev; if (!strlen(itmtouch->name)) diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c index d2f0f90a9bc..b6f6ac8d9c2 100644 --- a/drivers/usb/input/kbtab.c +++ b/drivers/usb/input/kbtab.c @@ -4,6 +4,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/usb.h> +#include <linux/usb_input.h> #include <asm/unaligned.h> #include <asm/byteorder.h> @@ -167,10 +168,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i kbtab->dev.name = "KB Gear Tablet"; kbtab->dev.phys = kbtab->phys; - kbtab->dev.id.bustype = BUS_USB; - kbtab->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); - kbtab->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); - kbtab->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice); + usb_to_input_id(dev, &kbtab->dev.id); kbtab->dev.dev = &intf->dev; kbtab->usbdev = dev; diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c index 09b5cc7c66d..ff9275057a1 100644 --- a/drivers/usb/input/mtouchusb.c +++ b/drivers/usb/input/mtouchusb.c @@ -53,6 +53,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/usb.h> +#include <linux/usb_input.h> #define MTOUCHUSB_MIN_XC 0x0 #define MTOUCHUSB_MAX_RAW_XC 0x4000 @@ -232,10 +233,7 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i mtouch->input.name = mtouch->name; mtouch->input.phys = mtouch->phys; - mtouch->input.id.bustype = BUS_USB; - mtouch->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor); - mtouch->input.id.product = le16_to_cpu(udev->descriptor.idProduct); - mtouch->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); + usb_to_input_id(udev, &mtouch->input.id); mtouch->input.dev = &intf->dev; mtouch->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c index 3975b309d55..ad4afe7e589 100644 --- a/drivers/usb/input/powermate.c +++ b/drivers/usb/input/powermate.c @@ -35,6 +35,7 @@ #include <linux/init.h> #include <linux/spinlock.h> #include <linux/usb.h> +#include <linux/usb_input.h> #define POWERMATE_VENDOR 0x077d /* Griffin Technology, Inc. */ #define POWERMATE_PRODUCT_NEW 0x0410 /* Griffin PowerMate */ @@ -389,10 +390,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i pm->input.keybit[LONG(BTN_0)] = BIT(BTN_0); pm->input.relbit[LONG(REL_DIAL)] = BIT(REL_DIAL); pm->input.mscbit[LONG(MSC_PULSELED)] = BIT(MSC_PULSELED); - pm->input.id.bustype = BUS_USB; - pm->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor); - pm->input.id.product = le16_to_cpu(udev->descriptor.idProduct); - pm->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); + usb_to_input_id(udev, &pm->input.id); pm->input.event = powermate_input_event; pm->input.dev = &intf->dev; pm->input.phys = pm->phys; diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c index 386595ee21c..4276c24a508 100644 --- a/drivers/usb/input/touchkitusb.c +++ b/drivers/usb/input/touchkitusb.c @@ -35,7 +35,7 @@ #define DEBUG #endif #include <linux/usb.h> - +#include <linux/usb_input.h> #define TOUCHKIT_MIN_XC 0x0 #define TOUCHKIT_MAX_XC 0x07ff @@ -202,10 +202,7 @@ static int touchkit_probe(struct usb_interface *intf, touchkit->input.name = touchkit->name; touchkit->input.phys = touchkit->phys; - touchkit->input.id.bustype = BUS_USB; - touchkit->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor); - touchkit->input.id.product = le16_to_cpu(udev->descriptor.idProduct); - touchkit->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); + usb_to_input_id(udev, &touchkit->input.id); touchkit->input.dev = &intf->dev; touchkit->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c index f35db1974c4..28987f15eee 100644 --- a/drivers/usb/input/usbkbd.c +++ b/drivers/usb/input/usbkbd.c @@ -32,6 +32,7 @@ #include <linux/input.h> #include <linux/init.h> #include <linux/usb.h> +#include <linux/usb_input.h> /* * Version Information @@ -288,10 +289,7 @@ static int usb_kbd_probe(struct usb_interface *iface, kbd->dev.name = kbd->name; kbd->dev.phys = kbd->phys; - kbd->dev.id.bustype = BUS_USB; - kbd->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); - kbd->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); - kbd->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice); + usb_to_input_id(dev, &kbd->dev.id); kbd->dev.dev = &iface->dev; if (dev->manufacturer) diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c index 1ec41b5effe..4104dec847f 100644 --- a/drivers/usb/input/usbmouse.c +++ b/drivers/usb/input/usbmouse.c @@ -32,6 +32,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/usb.h> +#include <linux/usb_input.h> /* * Version Information @@ -171,10 +172,7 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_ mouse->dev.name = mouse->name; mouse->dev.phys = mouse->phys; - mouse->dev.id.bustype = BUS_USB; - mouse->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); - mouse->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); - mouse->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice); + usb_to_input_id(dev, &mouse->dev.id); mouse->dev.dev = &intf->dev; if (dev->manufacturer) diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c index f6b34af66b3..02412e31a46 100644 --- a/drivers/usb/input/wacom.c +++ b/drivers/usb/input/wacom.c @@ -69,6 +69,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/usb.h> +#include <linux/usb_input.h> #include <asm/unaligned.h> #include <asm/byteorder.h> @@ -823,10 +824,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i wacom->dev.name = wacom->features->name; wacom->dev.phys = wacom->phys; - wacom->dev.id.bustype = BUS_USB; - wacom->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); - wacom->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); - wacom->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice); + usb_to_input_id(dev, &wacom->dev.id); wacom->dev.dev = &intf->dev; wacom->usbdev = dev; diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c index a7fa1b17dcf..18125e0bffa 100644 --- a/drivers/usb/input/xpad.c +++ b/drivers/usb/input/xpad.c @@ -62,6 +62,7 @@ #include <linux/module.h> #include <linux/smp_lock.h> #include <linux/usb.h> +#include <linux/usb_input.h> #define DRIVER_VERSION "v0.0.5" #define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>" @@ -256,10 +257,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id xpad->udev = udev; - xpad->dev.id.bustype = BUS_USB; - xpad->dev.id.vendor = le16_to_cpu(udev->descriptor.idVendor); - xpad->dev.id.product = le16_to_cpu(udev->descriptor.idProduct); - xpad->dev.id.version = le16_to_cpu(udev->descriptor.bcdDevice); + usb_to_input_id(udev, &xpad->dev.id); xpad->dev.dev = &intf->dev; xpad->dev.private = xpad; xpad->dev.name = xpad_device[i].name; diff --git a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c index 08521a2b4f3..20ac9e1069d 100644 --- a/drivers/usb/media/konicawc.c +++ b/drivers/usb/media/konicawc.c @@ -16,6 +16,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/input.h> +#include <linux/usb_input.h> #include "usbvideo.h" @@ -845,10 +846,7 @@ static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id cam->input.private = cam; cam->input.evbit[0] = BIT(EV_KEY); cam->input.keybit[LONG(BTN_0)] = BIT(BTN_0); - cam->input.id.bustype = BUS_USB; - cam->input.id.vendor = le16_to_cpu(dev->descriptor.idVendor); - cam->input.id.product = le16_to_cpu(dev->descriptor.idProduct); - cam->input.id.version = le16_to_cpu(dev->descriptor.bcdDevice); + usb_to_input_id(dev, &cam->input.id); input_register_device(&cam->input); usb_make_path(dev, cam->input_physname, 56); diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 66ec88354b9..ad17892aac9 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -23,6 +23,7 @@ * * V0.1 (mh) Initial version * V0.11 (mh) Added raw support for HID 1.0 devices (no interrupt out endpoint) + * V0.12 (mh) Added kmalloc check for string buffer */ #include <linux/config.h> @@ -84,7 +85,7 @@ static struct usb_device_id ld_usb_table [] = { { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, ld_usb_table); -MODULE_VERSION("V0.11"); +MODULE_VERSION("V0.12"); MODULE_AUTHOR("Michael Hund <mhund@ld-didactic.de>"); MODULE_DESCRIPTION("LD USB Driver"); MODULE_LICENSE("GPL"); @@ -635,6 +636,10 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id * (le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_COM3LAB)) && (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x103)) { buffer = kmalloc(256, GFP_KERNEL); + if (buffer == NULL) { + dev_err(&intf->dev, "Couldn't allocate string buffer\n"); + goto error; + } /* usb_string makes SETUP+STALL to leave always ControlReadLoop */ usb_string(udev, 255, buffer, 256); kfree(buffer); diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index 5f4496d8dba..fcd6d3ccef4 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c @@ -59,7 +59,6 @@ static const char driver_name[] = "pegasus"; static int loopback = 0; static int mii_mode = 0; -static int multicast_filter_limit = 32; static struct usb_eth_dev usb_dev_id[] = { #define PEGASUS_DEV(pn, vid, pid, flags) \ diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c index 626b016addf..59ab40ebb39 100644 --- a/drivers/usb/net/rtl8150.c +++ b/drivers/usb/net/rtl8150.c @@ -167,8 +167,6 @@ struct rtl8150 { typedef struct rtl8150 rtl8150_t; -static unsigned long multicast_filter_limit = 32; - static void fill_skb_pool(rtl8150_t *); static void free_skb_pool(rtl8150_t *); static inline struct sk_buff *pull_skb(rtl8150_t *); diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c index 72b06129e20..2a1d489e92c 100644 --- a/drivers/usb/net/zd1201.c +++ b/drivers/usb/net/zd1201.c @@ -29,6 +29,7 @@ static struct usb_device_id zd1201_table[] = { {USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */ {USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb adapter */ {USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb adapter */ + {USB_DEVICE(0x1044, 0x8005)}, /* GIGABYTE GN-WLBZ201 usb adapter */ {} }; diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 0b03ddab53d..d1964a0c416 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -429,6 +429,9 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) }, { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y6_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y8_PID) }, + { USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) }, { } /* Terminating entry */ }; @@ -545,6 +548,7 @@ static struct usb_serial_device_type ftdi_sio_device = { #define WDR_TIMEOUT 5000 /* default urb timeout */ +#define WDR_SHORT_TIMEOUT 1000 /* shorter urb timeout */ /* High and low are for DTR, RTS etc etc */ #define HIGH 1 @@ -593,62 +597,59 @@ static __u32 ftdi_232bm_baud_to_divisor(int baud) return(ftdi_232bm_baud_base_to_divisor(baud, 48000000)); } -static int set_rts(struct usb_serial_port *port, int high_or_low) +#define set_mctrl(port, set) update_mctrl((port), (set), 0) +#define clear_mctrl(port, clear) update_mctrl((port), 0, (clear)) + +static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned int clear) { struct ftdi_private *priv = usb_get_serial_port_data(port); char *buf; - unsigned ftdi_high_or_low; + unsigned urb_value; int rv; - - buf = kmalloc(1, GFP_NOIO); - if (!buf) - return -ENOMEM; - - if (high_or_low) { - ftdi_high_or_low = FTDI_SIO_SET_RTS_HIGH; - priv->last_dtr_rts |= TIOCM_RTS; - } else { - ftdi_high_or_low = FTDI_SIO_SET_RTS_LOW; - priv->last_dtr_rts &= ~TIOCM_RTS; - } - rv = usb_control_msg(port->serial->dev, - usb_sndctrlpipe(port->serial->dev, 0), - FTDI_SIO_SET_MODEM_CTRL_REQUEST, - FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - ftdi_high_or_low, priv->interface, - buf, 0, WDR_TIMEOUT); - - kfree(buf); - return rv; -} + if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) { + dbg("%s - DTR|RTS not being set|cleared", __FUNCTION__); + return 0; /* no change */ + } -static int set_dtr(struct usb_serial_port *port, int high_or_low) -{ - struct ftdi_private *priv = usb_get_serial_port_data(port); - char *buf; - unsigned ftdi_high_or_low; - int rv; - buf = kmalloc(1, GFP_NOIO); - if (!buf) + if (!buf) { return -ENOMEM; - - if (high_or_low) { - ftdi_high_or_low = FTDI_SIO_SET_DTR_HIGH; - priv->last_dtr_rts |= TIOCM_DTR; - } else { - ftdi_high_or_low = FTDI_SIO_SET_DTR_LOW; - priv->last_dtr_rts &= ~TIOCM_DTR; } + + clear &= ~set; /* 'set' takes precedence over 'clear' */ + urb_value = 0; + if (clear & TIOCM_DTR) + urb_value |= FTDI_SIO_SET_DTR_LOW; + if (clear & TIOCM_RTS) + urb_value |= FTDI_SIO_SET_RTS_LOW; + if (set & TIOCM_DTR) + urb_value |= FTDI_SIO_SET_DTR_HIGH; + if (set & TIOCM_RTS) + urb_value |= FTDI_SIO_SET_RTS_HIGH; rv = usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - ftdi_high_or_low, priv->interface, + urb_value, priv->interface, buf, 0, WDR_TIMEOUT); kfree(buf); + if (rv < 0) { + err("%s Error from MODEM_CTRL urb: DTR %s, RTS %s", + __FUNCTION__, + (set & TIOCM_DTR) ? "HIGH" : + (clear & TIOCM_DTR) ? "LOW" : "unchanged", + (set & TIOCM_RTS) ? "HIGH" : + (clear & TIOCM_RTS) ? "LOW" : "unchanged"); + } else { + dbg("%s - DTR %s, RTS %s", __FUNCTION__, + (set & TIOCM_DTR) ? "HIGH" : + (clear & TIOCM_DTR) ? "LOW" : "unchanged", + (set & TIOCM_RTS) ? "HIGH" : + (clear & TIOCM_RTS) ? "LOW" : "unchanged"); + priv->last_dtr_rts = (priv->last_dtr_rts & ~clear) | set; + } return rv; } @@ -681,7 +682,7 @@ static int change_speed(struct usb_serial_port *port) FTDI_SIO_SET_BAUDRATE_REQUEST, FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, urb_value, urb_index, - buf, 0, 100); + buf, 0, WDR_SHORT_TIMEOUT); kfree(buf); return rv; @@ -1219,12 +1220,7 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) /* FIXME: Flow control might be enabled, so it should be checked - we have no control of defaults! */ /* Turn on RTS and DTR since we are not flow controlling by default */ - if (set_dtr(port, HIGH) < 0) { - err("%s Error from DTR HIGH urb", __FUNCTION__); - } - if (set_rts(port, HIGH) < 0){ - err("%s Error from RTS HIGH urb", __FUNCTION__); - } + set_mctrl(port, TIOCM_DTR | TIOCM_RTS); /* Not throttled */ spin_lock_irqsave(&priv->rx_lock, flags); @@ -1274,14 +1270,8 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp) err("error from flowcontrol urb"); } - /* drop DTR */ - if (set_dtr(port, LOW) < 0){ - err("Error from DTR LOW urb"); - } - /* drop RTS */ - if (set_rts(port, LOW) < 0) { - err("Error from RTS LOW urb"); - } + /* drop RTS and DTR */ + clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); } /* Note change no line if hupcl is off */ /* cancel any scheduled reading */ @@ -1797,7 +1787,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_ FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, urb_value , priv->interface, - buf, 0, 100) < 0) { + buf, 0, WDR_SHORT_TIMEOUT) < 0) { err("%s FAILED to set databits/stopbits/parity", __FUNCTION__); } @@ -1812,25 +1802,14 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_ err("%s error from disable flowcontrol urb", __FUNCTION__); } /* Drop RTS and DTR */ - if (set_dtr(port, LOW) < 0){ - err("%s Error from DTR LOW urb", __FUNCTION__); - } - if (set_rts(port, LOW) < 0){ - err("%s Error from RTS LOW urb", __FUNCTION__); - } - + clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); } else { /* set the baudrate determined before */ if (change_speed(port)) { err("%s urb failed to set baurdrate", __FUNCTION__); } /* Ensure RTS and DTR are raised */ - else if (set_dtr(port, HIGH) < 0){ - err("%s Error from DTR HIGH urb", __FUNCTION__); - } - else if (set_rts(port, HIGH) < 0){ - err("%s Error from RTS HIGH urb", __FUNCTION__); - } + set_mctrl(port, TIOCM_DTR | TIOCM_RTS); } /* Set flow control */ @@ -1942,35 +1921,8 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file) static int ftdi_tiocmset(struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear) { - int ret; - dbg("%s TIOCMSET", __FUNCTION__); - if (set & TIOCM_DTR){ - if ((ret = set_dtr(port, HIGH)) < 0) { - err("Urb to set DTR failed"); - return(ret); - } - } - if (set & TIOCM_RTS) { - if ((ret = set_rts(port, HIGH)) < 0){ - err("Urb to set RTS failed"); - return(ret); - } - } - - if (clear & TIOCM_DTR){ - if ((ret = set_dtr(port, LOW)) < 0){ - err("Urb to unset DTR failed"); - return(ret); - } - } - if (clear & TIOCM_RTS) { - if ((ret = set_rts(port, LOW)) < 0){ - err("Urb to unset RTS failed"); - return(ret); - } - } - return(0); + return update_mctrl(port, set, clear); } diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 8866376823a..9f4342093e8 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -265,10 +265,24 @@ #define MOBILITY_USB_SERIAL_PID 0x0202 /* EasiDock USB 200 serial */ /* + * microHAM product IDs (http://www.microham.com). + * Submitted by Justin Burket (KL1RL) <zorton@jtan.com>. + */ +#define FTDI_MHAM_Y6_PID 0xEEEA /* USB-Y6 interface */ +#define FTDI_MHAM_Y8_PID 0xEEEB /* USB-Y8 interface */ + +/* * Active Robots product ids. */ #define FTDI_ACTIVE_ROBOTS_PID 0xE548 /* USB comms board */ +/* + * Evolution Robotics products (http://www.evolution.com/). + * Submitted by Shawn M. Lavelle. + */ +#define EVOLUTION_VID 0xDEEE /* Vendor ID */ +#define EVOLUTION_ER1_PID 0x0300 /* ER1 Control Module */ + /* Commands */ #define FTDI_SIO_RESET 0 /* Reset the port */ #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 b722175f108..e9256408757 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -12,14 +12,25 @@ History: 2005-05-19 v0.1 Initial version, based on incomplete docs - and analysis of misbehavior of the standard driver + and analysis of misbehavior with the standard driver 2005-05-20 v0.2 Extended the input buffer to avoid losing random 64-byte chunks of data 2005-05-21 v0.3 implemented chars_in_buffer() turned on low_latency simplified the code somewhat + 2005-05-24 v0.4 option_write() sometimes deadlocked under heavy load + removed some dead code + added sponsor notice + coding style clean-up + 2005-06-20 v0.4.1 add missing braces :-/ + killed end-of-line whitespace + 2005-07-15 v0.4.2 rename WLAN product to FUSION, add FUSION2 + + Work sponsored by: Sigos GmbH, Germany <info@sigos.de> + */ -#define DRIVER_VERSION "v0.3" + +#define DRIVER_VERSION "v0.4" #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>" #define DRIVER_DESC "Option Card (PC-Card to) USB to Serial Driver" @@ -44,7 +55,6 @@ static int option_write_room (struct usb_serial_port *port); static void option_instat_callback(struct urb *urb, struct pt_regs *regs); - static int option_write (struct usb_serial_port *port, const unsigned char *buf, int count); @@ -60,14 +70,17 @@ static int option_tiocmset (struct usb_serial_port *port, struct file *file, static int option_send_setup (struct usb_serial_port *port); /* Vendor and product IDs */ -#define OPTION_VENDOR_ID 0x0AF0 +#define OPTION_VENDOR_ID 0x0AF0 + +#define OPTION_PRODUCT_OLD 0x5000 +#define OPTION_PRODUCT_FUSION 0x6000 +#define OPTION_PRODUCT_FUSION2 0x6300 -#define OPTION_PRODUCT_OLD 0x5000 -#define OPTION_PRODUCT_WLAN 0x6000 static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, - { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_WLAN) }, + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) }, + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) }, { } /* Terminating entry */ }; @@ -85,58 +98,62 @@ static struct usb_driver option_driver = { * recognizes separately, thus num_port=1. */ static struct usb_serial_device_type option_3port_device = { - .owner = THIS_MODULE, - .name = "Option 3-port card", - .short_name = "option", - .id_table = option_ids, - .num_interrupt_in = NUM_DONT_CARE, - .num_bulk_in = NUM_DONT_CARE, - .num_bulk_out = NUM_DONT_CARE, - .num_ports = 1, /* 3 */ - .open = option_open, - .close = option_close, - .write = option_write, - .write_room = option_write_room, - .chars_in_buffer = option_chars_in_buffer, - .throttle = option_rx_throttle, - .unthrottle = option_rx_unthrottle, - .ioctl = option_ioctl, - .set_termios = option_set_termios, - .break_ctl = option_break_ctl, - .tiocmget = option_tiocmget, - .tiocmset = option_tiocmset, - .attach = option_startup, - .shutdown = option_shutdown, - .read_int_callback = option_instat_callback, + .owner = THIS_MODULE, + .name = "Option 3G data card", + .short_name = "option", + .id_table = option_ids, + .num_interrupt_in = NUM_DONT_CARE, + .num_bulk_in = NUM_DONT_CARE, + .num_bulk_out = NUM_DONT_CARE, + .num_ports = 1, /* 3, but the card reports its ports separately */ + .open = option_open, + .close = option_close, + .write = option_write, + .write_room = option_write_room, + .chars_in_buffer = option_chars_in_buffer, + .throttle = option_rx_throttle, + .unthrottle = option_rx_unthrottle, + .ioctl = option_ioctl, + .set_termios = option_set_termios, + .break_ctl = option_break_ctl, + .tiocmget = option_tiocmget, + .tiocmset = option_tiocmset, + .attach = option_startup, + .shutdown = option_shutdown, + .read_int_callback = option_instat_callback, }; +#ifdef CONFIG_USB_DEBUG static int debug; +#else +#define debug 0 +#endif + /* per port private data */ -#define N_IN_URB 4 -#define N_OUT_URB 1 -#define IN_BUFLEN 1024 -#define OUT_BUFLEN 1024 +#define N_IN_URB 4 +#define N_OUT_URB 1 +#define IN_BUFLEN 1024 +#define OUT_BUFLEN 128 struct option_port_private { /* Input endpoints and buffer for this port */ - struct urb *in_urbs[N_IN_URB]; - char in_buffer[N_IN_URB][IN_BUFLEN]; + struct urb *in_urbs[N_IN_URB]; + char in_buffer[N_IN_URB][IN_BUFLEN]; /* Output endpoints and buffer for this port */ - struct urb *out_urbs[N_OUT_URB]; - char out_buffer[N_OUT_URB][OUT_BUFLEN]; + struct urb *out_urbs[N_OUT_URB]; + char out_buffer[N_OUT_URB][OUT_BUFLEN]; /* Settings for the port */ - int rts_state; /* Handshaking pins (outputs) */ - int dtr_state; - int cts_state; /* Handshaking pins (inputs) */ - int dsr_state; - int dcd_state; - int ri_state; - // int break_on; - - unsigned long tx_start_time[N_OUT_URB]; + int rts_state; /* Handshaking pins (outputs) */ + int dtr_state; + int cts_state; /* Handshaking pins (inputs) */ + int dsr_state; + int dcd_state; + int ri_state; + + unsigned long tx_start_time[N_OUT_URB]; }; @@ -190,13 +207,13 @@ static void option_break_ctl (struct usb_serial_port *port, int break_state) { /* Unfortunately, I don't know how to send a break */ - dbg("%s", __FUNCTION__); + dbg("%s", __FUNCTION__); } static void option_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct termios *old_termios) { dbg("%s", __FUNCTION__); @@ -204,10 +221,10 @@ option_set_termios (struct usb_serial_port *port, } static int -option_tiocmget(struct usb_serial_port *port, struct file *file) +option_tiocmget (struct usb_serial_port *port, struct file *file) { - unsigned int value; - struct option_port_private *portdata; + unsigned int value; + struct option_port_private *portdata; portdata = usb_get_serial_port_data(port); @@ -225,7 +242,7 @@ static int option_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear) { - struct option_port_private *portdata; + struct option_port_private *portdata; portdata = usb_get_serial_port_data(port); @@ -250,71 +267,50 @@ option_ioctl (struct usb_serial_port *port, struct file *file, /* Write */ static int -option_write(struct usb_serial_port *port, - const unsigned char *buf, int count) +option_write (struct usb_serial_port *port, + const unsigned char *buf, int count) { - struct option_port_private *portdata; - int i; - int left, todo; - struct urb *this_urb = NULL; /* spurious */ - int err; + struct option_port_private *portdata; + int i; + int left, todo; + struct urb *this_urb = NULL; /* spurious */ + int err; portdata = usb_get_serial_port_data(port); dbg("%s: write (%d chars)", __FUNCTION__, count); -#if 0 - spin_lock(&port->lock); - if (port->write_urb_busy) { - spin_unlock(&port->lock); - dbg("%s: already writing", __FUNCTION__); - return 0; - } - port->write_urb_busy = 1; - spin_unlock(&port->lock); -#endif - i = 0; left = count; - while (left>0) { + for (i=0; left > 0 && i < N_OUT_URB; i++) { todo = left; if (todo > OUT_BUFLEN) todo = OUT_BUFLEN; - for (;i < N_OUT_URB; i++) { - /* Check we have a valid urb/endpoint before we use it... */ - this_urb = portdata->out_urbs[i]; - if (this_urb->status != -EINPROGRESS) - break; + this_urb = portdata->out_urbs[i]; + if (this_urb->status == -EINPROGRESS) { if (this_urb->transfer_flags & URB_ASYNC_UNLINK) continue; if (time_before(jiffies, portdata->tx_start_time[i] + 10 * HZ)) continue; this_urb->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(this_urb); + continue; } - - if (i == N_OUT_URB) { - /* no bulk out free! */ - dbg("%s: no output urb -- left %d", __FUNCTION__,count-left); -#if 0 - port->write_urb_busy = 0; -#endif - return count-left; - } + if (this_urb->status != 0) + dbg("usb_write %p failed (err=%d)", this_urb, this_urb->status); dbg("%s: endpoint %d buf %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe), i); + /* send the data */ memcpy (this_urb->transfer_buffer, buf, todo); - - /* send the data out the bulk port */ this_urb->transfer_buffer_length = todo; this_urb->transfer_flags &= ~URB_ASYNC_UNLINK; this_urb->dev = port->serial->dev; err = usb_submit_urb(this_urb, GFP_ATOMIC); if (err) { - dbg("usb_submit_urb %p (write bulk) failed (%d,, has %d)", this_urb, err, this_urb->status); + dbg("usb_submit_urb %p (write bulk) failed (%d, has %d)", this_urb, err, this_urb->status); continue; } portdata->tx_start_time[i] = jiffies; @@ -323,9 +319,6 @@ option_write(struct usb_serial_port *port, } count -= left; -#if 0 - port->write_urb_busy = 0; -#endif dbg("%s: wrote (did %d)", __FUNCTION__, count); return count; } @@ -333,7 +326,7 @@ option_write(struct usb_serial_port *port, static void option_indat_callback (struct urb *urb, struct pt_regs *regs) { - int i, err; + int i, err; int endpoint; struct usb_serial_port *port; struct tty_struct *tty; @@ -444,10 +437,11 @@ option_write_room (struct usb_serial_port *port) portdata = usb_get_serial_port_data(port); - for (i=0; i < N_OUT_URB; i++) + for (i=0; i < N_OUT_URB; i++) { this_urb = portdata->out_urbs[i]; if (this_urb && this_urb->status != -EINPROGRESS) data_len += OUT_BUFLEN; + } dbg("%s: %d", __FUNCTION__, data_len); return data_len; @@ -464,11 +458,11 @@ option_chars_in_buffer (struct usb_serial_port *port) portdata = usb_get_serial_port_data(port); - for (i=0; i < N_OUT_URB; i++) + for (i=0; i < N_OUT_URB; i++) { this_urb = portdata->out_urbs[i]; if (this_urb && this_urb->status == -EINPROGRESS) data_len += this_urb->transfer_buffer_length; - + } dbg("%s: %d", __FUNCTION__, data_len); return data_len; } @@ -477,10 +471,10 @@ option_chars_in_buffer (struct usb_serial_port *port) static int option_open (struct usb_serial_port *port, struct file *filp) { - struct option_port_private *portdata; - struct usb_serial *serial = port->serial; - int i, err; - struct urb *urb; + struct option_port_private *portdata; + struct usb_serial *serial = port->serial; + int i, err; + struct urb *urb; portdata = usb_get_serial_port_data(port); @@ -528,7 +522,7 @@ option_open (struct usb_serial_port *port, struct file *filp) } static inline void -stop_urb(struct urb *urb) +stop_urb (struct urb *urb) { if (urb && urb->status == -EINPROGRESS) { urb->transfer_flags &= ~URB_ASYNC_UNLINK; @@ -537,11 +531,11 @@ stop_urb(struct urb *urb) } static void -option_close(struct usb_serial_port *port, struct file *filp) +option_close (struct usb_serial_port *port, struct file *filp) { - int i; - struct usb_serial *serial = port->serial; - struct option_port_private *portdata; + int i; + struct usb_serial *serial = port->serial; + struct option_port_private *portdata; dbg("%s", __FUNCTION__); portdata = usb_get_serial_port_data(port); @@ -589,11 +583,11 @@ option_setup_urb (struct usb_serial *serial, int endpoint, /* Setup urbs */ static void -option_setup_urbs(struct usb_serial *serial) +option_setup_urbs (struct usb_serial *serial) { - int j; - struct usb_serial_port *port; - struct option_port_private *portdata; + int j; + struct usb_serial_port *port; + struct option_port_private *portdata; dbg("%s", __FUNCTION__); @@ -617,7 +611,7 @@ option_setup_urbs(struct usb_serial *serial) static int -option_send_setup(struct usb_serial_port *port) +option_send_setup (struct usb_serial_port *port) { struct usb_serial *serial = port->serial; struct option_port_private *portdata; @@ -644,9 +638,9 @@ option_send_setup(struct usb_serial_port *port) static int option_startup (struct usb_serial *serial) { - int i, err; - struct usb_serial_port *port; - struct option_port_private *portdata; + int i, err; + struct usb_serial_port *port; + struct option_port_private *portdata; dbg("%s", __FUNCTION__); @@ -677,9 +671,9 @@ option_startup (struct usb_serial *serial) static void option_shutdown (struct usb_serial *serial) { - int i, j; - struct usb_serial_port *port; - struct option_port_private *portdata; + int i, j; + struct usb_serial_port *port; + struct option_port_private *portdata; dbg("%s", __FUNCTION__); @@ -724,6 +718,8 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); +#ifdef CONFIG_USB_DEBUG module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug messages"); +#endif diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index 6051a646fe6..353f24d45bc 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -257,7 +257,8 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i endpoint = &iface_desc->endpoint[i].desc; if (!dev->bulk_in_endpointAddr && - (endpoint->bEndpointAddress & USB_DIR_IN) && + ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + == USB_DIR_IN) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) { /* we found a bulk in endpoint */ @@ -272,7 +273,8 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i } if (!dev->bulk_out_endpointAddr && - !(endpoint->bEndpointAddress & USB_DIR_OUT) && + ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + == USB_DIR_OUT) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) { /* we found a bulk out endpoint */ |