diff options
Diffstat (limited to 'drivers/usb/input')
-rw-r--r-- | drivers/usb/input/Kconfig | 13 | ||||
-rw-r--r-- | drivers/usb/input/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/input/acecad.c | 14 | ||||
-rw-r--r-- | drivers/usb/input/aiptek.c | 6 | ||||
-rw-r--r-- | drivers/usb/input/ati_remote.c | 8 | ||||
-rw-r--r-- | drivers/usb/input/hid-core.c | 48 | ||||
-rw-r--r-- | drivers/usb/input/hid-input.c | 11 | ||||
-rw-r--r-- | drivers/usb/input/itmtouch.c | 6 | ||||
-rw-r--r-- | drivers/usb/input/kbtab.c | 6 | ||||
-rw-r--r-- | drivers/usb/input/keyspan_remote.c | 633 | ||||
-rw-r--r-- | drivers/usb/input/mtouchusb.c | 6 | ||||
-rw-r--r-- | drivers/usb/input/powermate.c | 6 | ||||
-rw-r--r-- | drivers/usb/input/touchkitusb.c | 7 | ||||
-rw-r--r-- | drivers/usb/input/usbkbd.c | 6 | ||||
-rw-r--r-- | drivers/usb/input/usbmouse.c | 6 | ||||
-rw-r--r-- | drivers/usb/input/wacom.c | 27 | ||||
-rw-r--r-- | drivers/usb/input/xpad.c | 6 |
17 files changed, 729 insertions, 81 deletions
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index fd59f6bdd67f..298e4a25e3d3 100644 --- a/drivers/usb/input/Kconfig +++ b/drivers/usb/input/Kconfig @@ -259,3 +259,16 @@ config USB_ATI_REMOTE To compile this driver as a module, choose M here: the module will be called ati_remote. +config USB_KEYSPAN_REMOTE + tristate "Keyspan DMR USB remote control (EXPERIMENTAL)" + depends on USB && INPUT && EXPERIMENTAL + ---help--- + Say Y here if you want to use a Keyspan DMR USB remote control. + Currently only the UIA-11 type of receiver has been tested. The tag + on the receiver that connects to the USB port should have a P/N that + will tell you what type of DMR you have. The UIA-10 type is not + supported at this time. This driver maps all buttons to keypress + events. + + To compile this driver as a module, choose M here: the module will + be called keyspan_remote. diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile index 831b2b0f1f05..f1547be632d4 100644 --- a/drivers/usb/input/Makefile +++ b/drivers/usb/input/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_USB_ATI_REMOTE) += ati_remote.o obj-$(CONFIG_USB_HID) += usbhid.o obj-$(CONFIG_USB_KBD) += usbkbd.o obj-$(CONFIG_USB_KBTAB) += kbtab.o +obj-$(CONFIG_USB_KEYSPAN_REMOTE) += keyspan_remote.o obj-$(CONFIG_USB_MOUSE) += usbmouse.o obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o obj-$(CONFIG_USB_ITMTOUCH) += itmtouch.o diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c index ebcf7c955800..13532f3e3efc 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 6bb0f25e8e93..cd0cbfe20723 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 654ac454744d..fd99681ee483 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 100b49bd1d3e..b2cb2b35892e 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 @@ -1428,6 +1431,19 @@ void hid_init_reports(struct hid_device *hid) #define USB_DEVICE_ID_VERNIER_SKIP 0x0003 #define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004 +#define USB_VENDOR_ID_LD 0x0f11 +#define USB_DEVICE_ID_CASSY 0x1000 +#define USB_DEVICE_ID_POCKETCASSY 0x1010 +#define USB_DEVICE_ID_MOBILECASSY 0x1020 +#define USB_DEVICE_ID_JWM 0x1080 +#define USB_DEVICE_ID_DMMP 0x1081 +#define USB_DEVICE_ID_UMIP 0x1090 +#define USB_DEVICE_ID_VIDEOCOM 0x1200 +#define USB_DEVICE_ID_COM3LAB 0x2000 +#define USB_DEVICE_ID_TELEPORT 0x2010 +#define USB_DEVICE_ID_NETWORKANALYSER 0x2020 +#define USB_DEVICE_ID_POWERCONTROL 0x2030 + /* * Alphabetically sorted blacklist by quirk type. @@ -1463,6 +1479,17 @@ static struct hid_blacklist { { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_CASSY, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_POCKETCASSY, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_MOBILECASSY, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_JWM, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_DMMP, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_UMIP, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_VIDEOCOM, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_COM3LAB, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_TELEPORT, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_NETWORKANALYSER, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_POWERCONTROL, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE }, @@ -1524,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 9ac1e9095334..63a4db721f7e 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 47dec6a1b344..0dc439f10823 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 d2f0f90a9bcd..b6f6ac8d9c2f 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/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c new file mode 100644 index 000000000000..67dc93685203 --- /dev/null +++ b/drivers/usb/input/keyspan_remote.c @@ -0,0 +1,633 @@ +/* + * keyspan_remote: USB driver for the Keyspan DMR + * + * Copyright (C) 2005 Zymeta Corporation - Michael Downey (downey@zymeta.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + * This driver has been put together with the support of Innosys, Inc. + * and Keyspan, Inc the manufacturers of the Keyspan USB DMR product. + */ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/input.h> +#include <linux/usb.h> + +#define DRIVER_VERSION "v0.1" +#define DRIVER_AUTHOR "Michael Downey <downey@zymeta.com>" +#define DRIVER_DESC "Driver for the USB Keyspan remote control." +#define DRIVER_LICENSE "GPL" + +/* Parameters that can be passed to the driver. */ +static int debug; +module_param(debug, int, 0444); +MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); + +/* Vendor and product ids */ +#define USB_KEYSPAN_VENDOR_ID 0x06CD +#define USB_KEYSPAN_PRODUCT_UIA11 0x0202 + +/* Defines for converting the data from the remote. */ +#define ZERO 0x18 +#define ZERO_MASK 0x1F /* 5 bits for a 0 */ +#define ONE 0x3C +#define ONE_MASK 0x3F /* 6 bits for a 1 */ +#define SYNC 0x3F80 +#define SYNC_MASK 0x3FFF /* 14 bits for a SYNC sequence */ +#define STOP 0x00 +#define STOP_MASK 0x1F /* 5 bits for the STOP sequence */ +#define GAP 0xFF + +#define RECV_SIZE 8 /* The UIA-11 type have a 8 byte limit. */ + +/* table of devices that work with this driver */ +static struct usb_device_id keyspan_table[] = { + { USB_DEVICE(USB_KEYSPAN_VENDOR_ID, USB_KEYSPAN_PRODUCT_UIA11) }, + { } /* Terminating entry */ +}; + +/* Structure to store all the real stuff that a remote sends to us. */ +struct keyspan_message { + u16 system; + u8 button; + u8 toggle; +}; + +/* Structure used for all the bit testing magic needed to be done. */ +struct bit_tester { + u32 tester; + int len; + int pos; + int bits_left; + u8 buffer[32]; +}; + +/* Structure to hold all of our driver specific stuff */ +struct usb_keyspan { + char name[128]; + char phys[64]; + struct usb_device* udev; + struct input_dev input; + struct usb_interface* interface; + struct usb_endpoint_descriptor* in_endpoint; + struct urb* irq_urb; + int open; + dma_addr_t in_dma; + unsigned char* in_buffer; + + /* variables used to parse messages from remote. */ + struct bit_tester data; + int stage; + int toggle; +}; + +/* + * Table that maps the 31 possible keycodes to input keys. + * Currently there are 15 and 17 button models so RESERVED codes + * are blank areas in the mapping. + */ +static int keyspan_key_table[] = { + KEY_RESERVED, /* 0 is just a place holder. */ + KEY_RESERVED, + KEY_STOP, + KEY_PLAYCD, + KEY_RESERVED, + KEY_PREVIOUSSONG, + KEY_REWIND, + KEY_FORWARD, + KEY_NEXTSONG, + KEY_RESERVED, + KEY_RESERVED, + KEY_RESERVED, + KEY_PAUSE, + KEY_VOLUMEUP, + KEY_RESERVED, + KEY_RESERVED, + KEY_RESERVED, + KEY_VOLUMEDOWN, + KEY_RESERVED, + KEY_UP, + KEY_RESERVED, + KEY_MUTE, + KEY_LEFT, + KEY_ENTER, + KEY_RIGHT, + KEY_RESERVED, + KEY_RESERVED, + KEY_DOWN, + KEY_RESERVED, + KEY_KPASTERISK, + KEY_RESERVED, + KEY_MENU +}; + +static struct usb_driver keyspan_driver; + +/* + * Debug routine that prints out what we've received from the remote. + */ +static void keyspan_print(struct usb_keyspan* dev) /*unsigned char* data)*/ +{ + char codes[4*RECV_SIZE]; + int i; + + for (i = 0; i < RECV_SIZE; i++) { + snprintf(codes+i*3, 4, "%02x ", dev->in_buffer[i]); + } + + dev_info(&dev->udev->dev, "%s\n", codes); +} + +/* + * Routine that manages the bit_tester structure. It makes sure that there are + * at least bits_needed bits loaded into the tester. + */ +static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed) +{ + if (dev->data.bits_left >= bits_needed) + return(0); + + /* + * Somehow we've missed the last message. The message will be repeated + * though so it's not too big a deal + */ + if (dev->data.pos >= dev->data.len) { + dev_dbg(&dev->udev, "%s - Error ran out of data. pos: %d, len: %d\n", + __FUNCTION__, dev->data.pos, dev->data.len); + return(-1); + } + + /* Load as much as we can into the tester. */ + while ((dev->data.bits_left + 7 < (sizeof(dev->data.tester) * 8)) && + (dev->data.pos < dev->data.len)) { + dev->data.tester += (dev->data.buffer[dev->data.pos++] << dev->data.bits_left); + dev->data.bits_left += 8; + } + + return(0); +} + +/* + * Routine that handles all the logic needed to parse out the message from the remote. + */ +static void keyspan_check_data(struct usb_keyspan *remote, struct pt_regs *regs) +{ + int i; + int found = 0; + struct keyspan_message message; + + switch(remote->stage) { + case 0: + /* + * In stage 0 we want to find the start of a message. The remote sends a 0xFF as filler. + * So the first byte that isn't a FF should be the start of a new message. + */ + for (i = 0; i < RECV_SIZE && remote->in_buffer[i] == GAP; ++i); + + if (i < RECV_SIZE) { + memcpy(remote->data.buffer, remote->in_buffer, RECV_SIZE); + remote->data.len = RECV_SIZE; + remote->data.pos = 0; + remote->data.tester = 0; + remote->data.bits_left = 0; + remote->stage = 1; + } + break; + + case 1: + /* + * Stage 1 we should have 16 bytes and should be able to detect a + * SYNC. The SYNC is 14 bits, 7 0's and then 7 1's. + */ + memcpy(remote->data.buffer + remote->data.len, remote->in_buffer, RECV_SIZE); + remote->data.len += RECV_SIZE; + + found = 0; + while ((remote->data.bits_left >= 14 || remote->data.pos < remote->data.len) && !found) { + for (i = 0; i < 8; ++i) { + if (keyspan_load_tester(remote, 14) != 0) { + remote->stage = 0; + return; + } + + if ((remote->data.tester & SYNC_MASK) == SYNC) { + remote->data.tester = remote->data.tester >> 14; + remote->data.bits_left -= 14; + found = 1; + break; + } else { + remote->data.tester = remote->data.tester >> 1; + --remote->data.bits_left; + } + } + } + + if (!found) { + remote->stage = 0; + remote->data.len = 0; + } else { + remote->stage = 2; + } + break; + + case 2: + /* + * Stage 2 we should have 24 bytes which will be enough for a full + * message. We need to parse out the system code, button code, + * toggle code, and stop. + */ + memcpy(remote->data.buffer + remote->data.len, remote->in_buffer, RECV_SIZE); + remote->data.len += RECV_SIZE; + + message.system = 0; + for (i = 0; i < 9; i++) { + keyspan_load_tester(remote, 6); + + if ((remote->data.tester & ZERO_MASK) == ZERO) { + message.system = message.system << 1; + remote->data.tester = remote->data.tester >> 5; + remote->data.bits_left -= 5; + } else if ((remote->data.tester & ONE_MASK) == ONE) { + message.system = (message.system << 1) + 1; + remote->data.tester = remote->data.tester >> 6; + remote->data.bits_left -= 6; + } else { + err("%s - Unknown sequence found in system data.\n", __FUNCTION__); + remote->stage = 0; + return; + } + } + + message.button = 0; + for (i = 0; i < 5; i++) { + keyspan_load_tester(remote, 6); + + if ((remote->data.tester & ZERO_MASK) == ZERO) { + message.button = message.button << 1; + remote->data.tester = remote->data.tester >> 5; + remote->data.bits_left -= 5; + } else if ((remote->data.tester & ONE_MASK) == ONE) { + message.button = (message.button << 1) + 1; + remote->data.tester = remote->data.tester >> 6; + remote->data.bits_left -= 6; + } else { + err("%s - Unknown sequence found in button data.\n", __FUNCTION__); + remote->stage = 0; + return; + } + } + + keyspan_load_tester(remote, 6); + if ((remote->data.tester & ZERO_MASK) == ZERO) { + message.toggle = 0; + remote->data.tester = remote->data.tester >> 5; + remote->data.bits_left -= 5; + } else if ((remote->data.tester & ONE_MASK) == ONE) { + message.toggle = 1; + remote->data.tester = remote->data.tester >> 6; + remote->data.bits_left -= 6; + } else { + err("%s - Error in message, invalid toggle.\n", __FUNCTION__); + } + + keyspan_load_tester(remote, 5); + if ((remote->data.tester & STOP_MASK) == STOP) { + remote->data.tester = remote->data.tester >> 5; + remote->data.bits_left -= 5; + } else { + err("Bad message recieved, no stop bit found.\n"); + } + + dev_dbg(&remote->udev, + "%s found valid message: system: %d, button: %d, toggle: %d\n", + __FUNCTION__, message.system, message.button, message.toggle); + + if (message.toggle != remote->toggle) { + input_regs(&remote->input, regs); + input_report_key(&remote->input, keyspan_key_table[message.button], 1); + input_report_key(&remote->input, keyspan_key_table[message.button], 0); + input_sync(&remote->input); + remote->toggle = message.toggle; + } + + remote->stage = 0; + break; + } +} + +/* + * Routine for sending all the initialization messages to the remote. + */ +static int keyspan_setup(struct usb_device* dev) +{ + int retval = 0; + + retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + 0x11, 0x40, 0x5601, 0x0, NULL, 0, 0); + if (retval) { + dev_dbg(&dev->dev, "%s - failed to set bit rate due to error: %d\n", + __FUNCTION__, retval); + return(retval); + } + + retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + 0x44, 0x40, 0x0, 0x0, NULL, 0, 0); + if (retval) { + dev_dbg(&dev->dev, "%s - failed to set resume sensitivity due to error: %d\n", + __FUNCTION__, retval); + return(retval); + } + + retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + 0x22, 0x40, 0x0, 0x0, NULL, 0, 0); + if (retval) { + dev_dbg(&dev->dev, "%s - failed to turn receive on due to error: %d\n", + __FUNCTION__, retval); + return(retval); + } + + dev_dbg(&dev->dev, "%s - Setup complete.\n", __FUNCTION__); + return(retval); +} + +/* + * Routine used to handle a new message that has come in. + */ +static void keyspan_irq_recv(struct urb *urb, struct pt_regs *regs) +{ + struct usb_keyspan *dev = urb->context; + int retval; + + /* Check our status in case we need to bail out early. */ + switch (urb->status) { + case 0: + break; + + /* Device went away so don't keep trying to read from it. */ + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + return; + + default: + goto resubmit; + break; + } + + if (debug) + keyspan_print(dev); + + keyspan_check_data(dev, regs); + +resubmit: + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + err ("%s - usb_submit_urb failed with result: %d", __FUNCTION__, retval); +} + +static int keyspan_open(struct input_dev *dev) +{ + struct usb_keyspan *remote = dev->private; + + if (remote->open++) + return 0; + + remote->irq_urb->dev = remote->udev; + if (usb_submit_urb(remote->irq_urb, GFP_KERNEL)) { + remote->open--; + return -EIO; + } + + return 0; +} + +static void keyspan_close(struct input_dev *dev) +{ + struct usb_keyspan *remote = dev->private; + + if (!--remote->open) + usb_kill_urb(remote->irq_urb); +} + +/* + * Routine that sets up the driver to handle a specific USB device detected on the bus. + */ +static int keyspan_probe(struct usb_interface *interface, const struct usb_device_id *id) +{ + int i; + int retval = -ENOMEM; + char path[64]; + char *buf; + struct usb_keyspan *remote = NULL; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + struct usb_device *udev = usb_get_dev(interface_to_usbdev(interface)); + + /* See if the offered device matches what we can accept */ + if ((udev->descriptor.idVendor != USB_KEYSPAN_VENDOR_ID) || + (udev->descriptor.idProduct != USB_KEYSPAN_PRODUCT_UIA11) ) + return -ENODEV; + + /* allocate memory for our device state and initialize it */ + remote = kmalloc(sizeof(*remote), GFP_KERNEL); + if (remote == NULL) { + err("Out of memory\n"); + goto error; + } + memset(remote, 0x00, sizeof(*remote)); + + remote->udev = udev; + remote->interface = interface; + remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */ + + /* set up the endpoint information */ + /* use only the first in interrupt endpoint */ + iface_desc = interface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + + if (!remote->in_endpoint && + (endpoint->bEndpointAddress & USB_DIR_IN) && + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) { + /* we found our interrupt in endpoint */ + remote->in_endpoint = endpoint; + + remote->in_buffer = usb_buffer_alloc(remote->udev, RECV_SIZE, SLAB_ATOMIC, &remote->in_dma); + if (!remote->in_buffer) { + retval = -ENOMEM; + goto error; + } + } + } + + if (!remote->in_endpoint) { + err("Could not find interrupt input endpoint.\n"); + retval = -ENODEV; + goto error; + } + + remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!remote->irq_urb) { + err("Failed to allocate urb.\n"); + retval = -ENOMEM; + goto error; + } + + retval = keyspan_setup(remote->udev); + if (retval) { + err("Failed to setup device.\n"); + retval = -ENODEV; + goto error; + } + + /* + * Setup the input system with the bits we are going to be reporting + */ + remote->input.evbit[0] = BIT(EV_KEY); /* We will only report KEY events. */ + for (i = 0; i < 32; ++i) { + if (keyspan_key_table[i] != KEY_RESERVED) { + set_bit(keyspan_key_table[i], remote->input.keybit); + } + } + + remote->input.private = remote; + remote->input.open = keyspan_open; + remote->input.close = keyspan_close; + + usb_make_path(remote->udev, path, 64); + sprintf(remote->phys, "%s/input0", path); + + remote->input.name = remote->name; + remote->input.phys = remote->phys; + remote->input.id.bustype = BUS_USB; + remote->input.id.vendor = le16_to_cpu(remote->udev->descriptor.idVendor); + remote->input.id.product = le16_to_cpu(remote->udev->descriptor.idProduct); + remote->input.id.version = le16_to_cpu(remote->udev->descriptor.bcdDevice); + + if (!(buf = kmalloc(63, GFP_KERNEL))) { + usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma); + kfree(remote); + return -ENOMEM; + } + + if (remote->udev->descriptor.iManufacturer && + usb_string(remote->udev, remote->udev->descriptor.iManufacturer, buf, 63) > 0) + strcat(remote->name, buf); + + if (remote->udev->descriptor.iProduct && + usb_string(remote->udev, remote->udev->descriptor.iProduct, buf, 63) > 0) + sprintf(remote->name, "%s %s", remote->name, buf); + + if (!strlen(remote->name)) + sprintf(remote->name, "USB Keyspan Remote %04x:%04x", + remote->input.id.vendor, remote->input.id.product); + + kfree(buf); + + /* + * Initialize the URB to access the device. The urb gets sent to the device in keyspan_open() + */ + usb_fill_int_urb(remote->irq_urb, + remote->udev, usb_rcvintpipe(remote->udev, remote->in_endpoint->bEndpointAddress), + remote->in_buffer, RECV_SIZE, keyspan_irq_recv, remote, + remote->in_endpoint->bInterval); + remote->irq_urb->transfer_dma = remote->in_dma; + remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + /* we can register the device now, as it is ready */ + input_register_device(&remote->input); + + /* save our data pointer in this interface device */ + usb_set_intfdata(interface, remote); + + /* let the user know what node this device is now attached to */ + info("connected: %s on %s", remote->name, path); + return 0; + +error: + /* + * In case of error we need to clean up any allocated buffers + */ + if (remote->irq_urb) + usb_free_urb(remote->irq_urb); + + if (remote->in_buffer) + usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma); + + if (remote) + kfree(remote); + + return retval; +} + +/* + * Routine called when a device is disconnected from the USB. + */ +static void keyspan_disconnect(struct usb_interface *interface) +{ + struct usb_keyspan *remote; + + /* prevent keyspan_open() from racing keyspan_disconnect() */ + lock_kernel(); + + remote = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + + if (remote) { /* We have a valid driver structure so clean up everything we allocated. */ + input_unregister_device(&remote->input); + usb_kill_urb(remote->irq_urb); + usb_free_urb(remote->irq_urb); + usb_buffer_free(interface_to_usbdev(interface), RECV_SIZE, remote->in_buffer, remote->in_dma); + kfree(remote); + } + + unlock_kernel(); + + info("USB Keyspan now disconnected"); +} + +/* + * Standard driver set up sections + */ +static struct usb_driver keyspan_driver = +{ + .owner = THIS_MODULE, + .name = "keyspan_remote", + .probe = keyspan_probe, + .disconnect = keyspan_disconnect, + .id_table = keyspan_table +}; + +static int __init usb_keyspan_init(void) +{ + int result; + + /* register this driver with the USB subsystem */ + result = usb_register(&keyspan_driver); + if (result) + err("usb_register failed. Error number %d\n", result); + + return result; +} + +static void __exit usb_keyspan_exit(void) +{ + /* deregister this driver with the USB subsystem */ + usb_deregister(&keyspan_driver); +} + +module_init(usb_keyspan_init); +module_exit(usb_keyspan_exit); + +MODULE_DEVICE_TABLE(usb, keyspan_table); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE(DRIVER_LICENSE); diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c index 09b5cc7c66de..ff9275057a18 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 3975b309d55f..ad4afe7e5897 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 386595ee21c0..4276c24a5080 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 f35db1974c42..28987f15eeee 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 1ec41b5effe6..4104dec847fb 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 f6b34af66b3d..3b266af3048a 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> @@ -341,9 +342,6 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) goto exit; } - x = le16_to_cpu(*(__le16 *) &data[2]); - y = le16_to_cpu(*(__le16 *) &data[4]); - input_regs(dev, regs); if (data[1] & 0x10) { /* in prox */ @@ -372,15 +370,17 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) } } - if (data[1] & 0x80) { + if (data[1] & 0x90) { + x = le16_to_cpu(*(__le16 *) &data[2]); + y = le16_to_cpu(*(__le16 *) &data[4]); input_report_abs(dev, ABS_X, x); input_report_abs(dev, ABS_Y, y); - } - if (wacom->tool[0] != BTN_TOOL_MOUSE) { - input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6])); - input_report_key(dev, BTN_TOUCH, data[1] & 0x01); - input_report_key(dev, BTN_STYLUS, data[1] & 0x02); - input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); + if (wacom->tool[0] != BTN_TOOL_MOUSE) { + input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6])); + input_report_key(dev, BTN_TOUCH, data[1] & 0x01); + input_report_key(dev, BTN_STYLUS, data[1] & 0x02); + input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); + } } input_report_key(dev, wacom->tool[0], data[1] & 0x10); @@ -567,7 +567,7 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) /* Cintiq doesn't send data when RDY bit isn't set */ if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40)) - return; + goto exit; if (wacom->features->type >= INTUOS3) { input_report_abs(dev, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1)); @@ -823,10 +823,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 a7fa1b17dcfe..18125e0bffa2 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; |