Merge branch 'upstream-fixes' of master.kernel.org:/pub/scm/linux/kernel/git/jikos/hid
* 'upstream-fixes' of master.kernel.org:/pub/scm/linux/kernel/git/jikos/hid: USB HID: hiddev - fix race between hiddev_send_event() and hiddev_release() HID: add hooks for getkeycode() and setkeycode() methods HID: switch to using input_dev->dev.parent USB HID: Logitech wheel 0x046d/0xc294 needs HID_QUIRK_NOGET quirk USB HID: usb_buffer_free() cleanup USB HID: report descriptor of Cypress USB barcode readers needs fixup Bluetooth HID: HIDP - don't initialize force feedback USB HID: update CONFIG_USB_HIDINPUT_POWERBOOK description HID: add input mappings for non-working keys on Logitech S510 remote
This commit is contained in:
commit
5884c40668
13 changed files with 171 additions and 39 deletions
|
@ -240,11 +240,94 @@ static inline void hidinput_pb_setup(struct input_dev *input)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline int match_scancode(int code, int scancode)
|
||||||
|
{
|
||||||
|
if (scancode == 0)
|
||||||
|
return 1;
|
||||||
|
return ((code & (HID_USAGE_PAGE | HID_USAGE)) == scancode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int match_keycode(int code, int keycode)
|
||||||
|
{
|
||||||
|
if (keycode == 0)
|
||||||
|
return 1;
|
||||||
|
return (code == keycode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct hid_usage *hidinput_find_key(struct hid_device *hid,
|
||||||
|
int scancode, int keycode)
|
||||||
|
{
|
||||||
|
int i, j, k;
|
||||||
|
struct hid_report *report;
|
||||||
|
struct hid_usage *usage;
|
||||||
|
|
||||||
|
for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
|
||||||
|
list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
|
||||||
|
for (i = 0; i < report->maxfield; i++) {
|
||||||
|
for ( j = 0; j < report->field[i]->maxusage; j++) {
|
||||||
|
usage = report->field[i]->usage + j;
|
||||||
|
if (usage->type == EV_KEY &&
|
||||||
|
match_scancode(usage->hid, scancode) &&
|
||||||
|
match_keycode(usage->code, keycode))
|
||||||
|
return usage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hidinput_getkeycode(struct input_dev *dev, int scancode,
|
||||||
|
int *keycode)
|
||||||
|
{
|
||||||
|
struct hid_device *hid = dev->private;
|
||||||
|
struct hid_usage *usage;
|
||||||
|
|
||||||
|
usage = hidinput_find_key(hid, scancode, 0);
|
||||||
|
if (usage) {
|
||||||
|
*keycode = usage->code;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hidinput_setkeycode(struct input_dev *dev, int scancode,
|
||||||
|
int keycode)
|
||||||
|
{
|
||||||
|
struct hid_device *hid = dev->private;
|
||||||
|
struct hid_usage *usage;
|
||||||
|
int old_keycode;
|
||||||
|
|
||||||
|
if (keycode < 0 || keycode > KEY_MAX)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
usage = hidinput_find_key(hid, scancode, 0);
|
||||||
|
if (usage) {
|
||||||
|
old_keycode = usage->code;
|
||||||
|
usage->code = keycode;
|
||||||
|
|
||||||
|
clear_bit(old_keycode, dev->keybit);
|
||||||
|
set_bit(usage->code, dev->keybit);
|
||||||
|
#ifdef CONFIG_HID_DEBUG
|
||||||
|
printk (KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
|
||||||
|
#endif
|
||||||
|
/* Set the keybit for the old keycode if the old keycode is used
|
||||||
|
* by another key */
|
||||||
|
if (hidinput_find_key (hid, 0, old_keycode))
|
||||||
|
set_bit(old_keycode, dev->keybit);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
|
static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
|
||||||
struct hid_usage *usage)
|
struct hid_usage *usage)
|
||||||
{
|
{
|
||||||
struct input_dev *input = hidinput->input;
|
struct input_dev *input = hidinput->input;
|
||||||
struct hid_device *device = input->private;
|
struct hid_device *device = input_get_drvdata(input);
|
||||||
int max = 0, code;
|
int max = 0, code;
|
||||||
unsigned long *bit = NULL;
|
unsigned long *bit = NULL;
|
||||||
|
|
||||||
|
@ -553,6 +636,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||||
case 0x1015: map_key_clear(KEY_RECORD); break;
|
case 0x1015: map_key_clear(KEY_RECORD); break;
|
||||||
case 0x1016: map_key_clear(KEY_PLAYER); break;
|
case 0x1016: map_key_clear(KEY_PLAYER); break;
|
||||||
case 0x1017: map_key_clear(KEY_EJECTCD); break;
|
case 0x1017: map_key_clear(KEY_EJECTCD); break;
|
||||||
|
case 0x1018: map_key_clear(KEY_MEDIA); break;
|
||||||
case 0x1019: map_key_clear(KEY_PROG1); break;
|
case 0x1019: map_key_clear(KEY_PROG1); break;
|
||||||
case 0x101a: map_key_clear(KEY_PROG2); break;
|
case 0x101a: map_key_clear(KEY_PROG2); break;
|
||||||
case 0x101b: map_key_clear(KEY_PROG3); break;
|
case 0x101b: map_key_clear(KEY_PROG3); break;
|
||||||
|
@ -560,9 +644,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||||
case 0x1020: map_key_clear(KEY_ZOOMOUT); break;
|
case 0x1020: map_key_clear(KEY_ZOOMOUT); break;
|
||||||
case 0x1021: map_key_clear(KEY_ZOOMRESET); break;
|
case 0x1021: map_key_clear(KEY_ZOOMRESET); break;
|
||||||
case 0x1023: map_key_clear(KEY_CLOSE); break;
|
case 0x1023: map_key_clear(KEY_CLOSE); break;
|
||||||
|
case 0x1027: map_key_clear(KEY_MENU); break;
|
||||||
/* this one is marked as 'Rotate' */
|
/* this one is marked as 'Rotate' */
|
||||||
case 0x1028: map_key_clear(KEY_ANGLE); break;
|
case 0x1028: map_key_clear(KEY_ANGLE); break;
|
||||||
case 0x1029: map_key_clear(KEY_SHUFFLE); break;
|
case 0x1029: map_key_clear(KEY_SHUFFLE); break;
|
||||||
|
case 0x102a: map_key_clear(KEY_BACK); break;
|
||||||
|
case 0x102b: map_key_clear(KEY_CYCLEWINDOWS); break;
|
||||||
case 0x1041: map_key_clear(KEY_BATTERY); break;
|
case 0x1041: map_key_clear(KEY_BATTERY); break;
|
||||||
case 0x1042: map_key_clear(KEY_WORDPROCESSOR); break;
|
case 0x1042: map_key_clear(KEY_WORDPROCESSOR); break;
|
||||||
case 0x1043: map_key_clear(KEY_SPREADSHEET); break;
|
case 0x1043: map_key_clear(KEY_SPREADSHEET); break;
|
||||||
|
@ -855,13 +942,15 @@ EXPORT_SYMBOL_GPL(hidinput_find_field);
|
||||||
|
|
||||||
static int hidinput_open(struct input_dev *dev)
|
static int hidinput_open(struct input_dev *dev)
|
||||||
{
|
{
|
||||||
struct hid_device *hid = dev->private;
|
struct hid_device *hid = input_get_drvdata(dev);
|
||||||
|
|
||||||
return hid->hid_open(hid);
|
return hid->hid_open(hid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hidinput_close(struct input_dev *dev)
|
static void hidinput_close(struct input_dev *dev)
|
||||||
{
|
{
|
||||||
struct hid_device *hid = dev->private;
|
struct hid_device *hid = input_get_drvdata(dev);
|
||||||
|
|
||||||
hid->hid_close(hid);
|
hid->hid_close(hid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -909,10 +998,12 @@ int hidinput_connect(struct hid_device *hid)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
input_dev->private = hid;
|
input_set_drvdata(input_dev, hid);
|
||||||
input_dev->event = hid->hidinput_input_event;
|
input_dev->event = hid->hidinput_input_event;
|
||||||
input_dev->open = hidinput_open;
|
input_dev->open = hidinput_open;
|
||||||
input_dev->close = hidinput_close;
|
input_dev->close = hidinput_close;
|
||||||
|
input_dev->setkeycode = hidinput_setkeycode;
|
||||||
|
input_dev->getkeycode = hidinput_getkeycode;
|
||||||
|
|
||||||
input_dev->name = hid->name;
|
input_dev->name = hid->name;
|
||||||
input_dev->phys = hid->phys;
|
input_dev->phys = hid->phys;
|
||||||
|
@ -921,7 +1012,7 @@ int hidinput_connect(struct hid_device *hid)
|
||||||
input_dev->id.vendor = hid->vendor;
|
input_dev->id.vendor = hid->vendor;
|
||||||
input_dev->id.product = hid->product;
|
input_dev->id.product = hid->product;
|
||||||
input_dev->id.version = hid->version;
|
input_dev->id.version = hid->version;
|
||||||
input_dev->cdev.dev = hid->dev;
|
input_dev->dev.parent = hid->dev;
|
||||||
hidinput->input = input_dev;
|
hidinput->input = input_dev;
|
||||||
list_add_tail(&hidinput->list, &hid->inputs);
|
list_add_tail(&hidinput->list, &hid->inputs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,12 +25,12 @@ comment "Input core support is needed for USB HID input layer or HIDBP support"
|
||||||
depends on USB_HID && INPUT=n
|
depends on USB_HID && INPUT=n
|
||||||
|
|
||||||
config USB_HIDINPUT_POWERBOOK
|
config USB_HIDINPUT_POWERBOOK
|
||||||
bool "Enable support for iBook/PowerBook special keys"
|
bool "Enable support for iBook/PowerBook/MacBook/MacBookPro special keys"
|
||||||
default n
|
default n
|
||||||
depends on USB_HID
|
depends on USB_HID
|
||||||
help
|
help
|
||||||
Say Y here if you want support for the special keys (Fn, Numlock) on
|
Say Y here if you want support for the special keys (Fn, Numlock) on
|
||||||
Apple iBooks and PowerBooks.
|
Apple iBooks, PowerBooks, MacBooks and MacBook Pros.
|
||||||
|
|
||||||
If unsure, say N.
|
If unsure, say N.
|
||||||
|
|
||||||
|
|
|
@ -446,7 +446,7 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns
|
||||||
|
|
||||||
static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
|
static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
|
||||||
{
|
{
|
||||||
struct hid_device *hid = dev->private;
|
struct hid_device *hid = input_get_drvdata(dev);
|
||||||
struct hid_field *field;
|
struct hid_field *field;
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
|
@ -626,14 +626,10 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
|
||||||
{
|
{
|
||||||
struct usbhid_device *usbhid = hid->driver_data;
|
struct usbhid_device *usbhid = hid->driver_data;
|
||||||
|
|
||||||
if (usbhid->inbuf)
|
usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
|
||||||
usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
|
usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
|
||||||
if (usbhid->outbuf)
|
usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma);
|
||||||
usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
|
usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
|
||||||
if (usbhid->cr)
|
|
||||||
usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma);
|
|
||||||
if (usbhid->ctrlbuf)
|
|
||||||
usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -692,6 +688,30 @@ static void hid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some USB barcode readers from cypress have usage min and usage max in
|
||||||
|
* the wrong order
|
||||||
|
*/
|
||||||
|
static void hid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
|
||||||
|
{
|
||||||
|
short fixed = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < rsize - 4; i++) {
|
||||||
|
if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
|
||||||
|
unsigned char tmp;
|
||||||
|
|
||||||
|
rdesc[i] = 0x19; rdesc[i+2] = 0x29;
|
||||||
|
tmp = rdesc[i+3];
|
||||||
|
rdesc[i+3] = rdesc[i+1];
|
||||||
|
rdesc[i+1] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fixed)
|
||||||
|
info("Fixing up Cypress report descriptor");
|
||||||
|
}
|
||||||
|
|
||||||
static struct hid_device *usb_hid_configure(struct usb_interface *intf)
|
static struct hid_device *usb_hid_configure(struct usb_interface *intf)
|
||||||
{
|
{
|
||||||
struct usb_host_interface *interface = intf->cur_altsetting;
|
struct usb_host_interface *interface = intf->cur_altsetting;
|
||||||
|
@ -758,6 +778,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
|
||||||
if (quirks & HID_QUIRK_LOGITECH_DESCRIPTOR)
|
if (quirks & HID_QUIRK_LOGITECH_DESCRIPTOR)
|
||||||
hid_fixup_logitech_descriptor(rdesc, rsize);
|
hid_fixup_logitech_descriptor(rdesc, rsize);
|
||||||
|
|
||||||
|
if (quirks & HID_QUIRK_SWAPPED_MIN_MAX)
|
||||||
|
hid_fixup_cypress_descriptor(rdesc, rsize);
|
||||||
|
|
||||||
#ifdef CONFIG_HID_DEBUG
|
#ifdef CONFIG_HID_DEBUG
|
||||||
printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
|
printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
|
||||||
for (n = 0; n < rsize; n++)
|
for (n = 0; n < rsize; n++)
|
||||||
|
|
|
@ -60,7 +60,7 @@ static const struct dev_type devices[] = {
|
||||||
|
|
||||||
static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
|
static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
|
||||||
{
|
{
|
||||||
struct hid_device *hid = dev->private;
|
struct hid_device *hid = input_get_drvdata(dev);
|
||||||
struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
|
struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
|
||||||
struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
|
struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
|
@ -37,7 +37,7 @@ struct plff_device {
|
||||||
static int hid_plff_play(struct input_dev *dev, void *data,
|
static int hid_plff_play(struct input_dev *dev, void *data,
|
||||||
struct ff_effect *effect)
|
struct ff_effect *effect)
|
||||||
{
|
{
|
||||||
struct hid_device *hid = dev->private;
|
struct hid_device *hid = input_get_drvdata(dev);
|
||||||
struct plff_device *plff = data;
|
struct plff_device *plff = data;
|
||||||
int left, right;
|
int left, right;
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,8 @@
|
||||||
#define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001
|
#define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001
|
||||||
#define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500
|
#define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500
|
||||||
#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE 0x7417
|
#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE 0x7417
|
||||||
|
#define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61
|
||||||
|
#define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64
|
||||||
|
|
||||||
#define USB_VENDOR_ID_DELL 0x413c
|
#define USB_VENDOR_ID_DELL 0x413c
|
||||||
#define USB_DEVICE_ID_DELL_W7658 0x2005
|
#define USB_DEVICE_ID_DELL_W7658 0x2005
|
||||||
|
@ -193,6 +195,7 @@
|
||||||
|
|
||||||
#define USB_VENDOR_ID_LOGITECH 0x046d
|
#define USB_VENDOR_ID_LOGITECH 0x046d
|
||||||
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
|
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
|
||||||
|
#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
|
||||||
#define USB_DEVICE_ID_S510_RECEIVER 0xc50c
|
#define USB_DEVICE_ID_S510_RECEIVER 0xc50c
|
||||||
#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
|
#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
|
||||||
#define USB_DEVICE_ID_MX3000_RECEIVER 0xc513
|
#define USB_DEVICE_ID_MX3000_RECEIVER 0xc513
|
||||||
|
@ -422,6 +425,7 @@ static const struct hid_blacklist {
|
||||||
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
|
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
|
||||||
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
|
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
|
||||||
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
|
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
|
||||||
|
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET },
|
||||||
{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
|
{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
|
||||||
{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
|
{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
|
||||||
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
|
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
|
||||||
|
@ -445,6 +449,9 @@ static const struct hid_blacklist {
|
||||||
|
|
||||||
{ USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
|
{ USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
|
||||||
|
|
||||||
|
{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_SWAPPED_MIN_MAX },
|
||||||
|
{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_SWAPPED_MIN_MAX },
|
||||||
|
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ static inline int hid_tmff_scale(unsigned int in, int minimum, int maximum)
|
||||||
|
|
||||||
static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
|
static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
|
||||||
{
|
{
|
||||||
struct hid_device *hid = dev->private;
|
struct hid_device *hid = input_get_drvdata(dev);
|
||||||
struct tmff_device *tmff = data;
|
struct tmff_device *tmff = data;
|
||||||
int left, right; /* Rumbling */
|
int left, right; /* Rumbling */
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ struct zpff_device {
|
||||||
static int hid_zpff_play(struct input_dev *dev, void *data,
|
static int hid_zpff_play(struct input_dev *dev, void *data,
|
||||||
struct ff_effect *effect)
|
struct ff_effect *effect)
|
||||||
{
|
{
|
||||||
struct hid_device *hid = dev->private;
|
struct hid_device *hid = input_get_drvdata(dev);
|
||||||
struct zpff_device *zpff = data;
|
struct zpff_device *zpff = data;
|
||||||
int left, right;
|
int left, right;
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ struct hiddev {
|
||||||
wait_queue_head_t wait;
|
wait_queue_head_t wait;
|
||||||
struct hid_device *hid;
|
struct hid_device *hid;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
|
spinlock_t list_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hiddev_list {
|
struct hiddev_list {
|
||||||
|
@ -161,7 +162,9 @@ static void hiddev_send_event(struct hid_device *hid,
|
||||||
{
|
{
|
||||||
struct hiddev *hiddev = hid->hiddev;
|
struct hiddev *hiddev = hid->hiddev;
|
||||||
struct hiddev_list *list;
|
struct hiddev_list *list;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&hiddev->list_lock, flags);
|
||||||
list_for_each_entry(list, &hiddev->list, node) {
|
list_for_each_entry(list, &hiddev->list, node) {
|
||||||
if (uref->field_index != HID_FIELD_INDEX_NONE ||
|
if (uref->field_index != HID_FIELD_INDEX_NONE ||
|
||||||
(list->flags & HIDDEV_FLAG_REPORT) != 0) {
|
(list->flags & HIDDEV_FLAG_REPORT) != 0) {
|
||||||
|
@ -171,6 +174,7 @@ static void hiddev_send_event(struct hid_device *hid,
|
||||||
kill_fasync(&list->fasync, SIGIO, POLL_IN);
|
kill_fasync(&list->fasync, SIGIO, POLL_IN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
spin_unlock_irqrestore(&hiddev->list_lock, flags);
|
||||||
|
|
||||||
wake_up_interruptible(&hiddev->wait);
|
wake_up_interruptible(&hiddev->wait);
|
||||||
}
|
}
|
||||||
|
@ -235,9 +239,13 @@ static int hiddev_fasync(int fd, struct file *file, int on)
|
||||||
static int hiddev_release(struct inode * inode, struct file * file)
|
static int hiddev_release(struct inode * inode, struct file * file)
|
||||||
{
|
{
|
||||||
struct hiddev_list *list = file->private_data;
|
struct hiddev_list *list = file->private_data;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
hiddev_fasync(-1, file, 0);
|
hiddev_fasync(-1, file, 0);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&list->hiddev->list_lock, flags);
|
||||||
list_del(&list->node);
|
list_del(&list->node);
|
||||||
|
spin_unlock_irqrestore(&list->hiddev->list_lock, flags);
|
||||||
|
|
||||||
if (!--list->hiddev->open) {
|
if (!--list->hiddev->open) {
|
||||||
if (list->hiddev->exist)
|
if (list->hiddev->exist)
|
||||||
|
@ -257,6 +265,7 @@ static int hiddev_release(struct inode * inode, struct file * file)
|
||||||
static int hiddev_open(struct inode *inode, struct file *file)
|
static int hiddev_open(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
struct hiddev_list *list;
|
struct hiddev_list *list;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
int i = iminor(inode) - HIDDEV_MINOR_BASE;
|
int i = iminor(inode) - HIDDEV_MINOR_BASE;
|
||||||
|
|
||||||
|
@ -267,7 +276,11 @@ static int hiddev_open(struct inode *inode, struct file *file)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
list->hiddev = hiddev_table[i];
|
list->hiddev = hiddev_table[i];
|
||||||
|
|
||||||
|
spin_lock_irqsave(&list->hiddev->list_lock, flags);
|
||||||
list_add_tail(&list->node, &hiddev_table[i]->list);
|
list_add_tail(&list->node, &hiddev_table[i]->list);
|
||||||
|
spin_unlock_irqrestore(&list->hiddev->list_lock, flags);
|
||||||
|
|
||||||
file->private_data = list;
|
file->private_data = list;
|
||||||
|
|
||||||
if (!list->hiddev->open++)
|
if (!list->hiddev->open++)
|
||||||
|
@ -773,6 +786,7 @@ int hiddev_connect(struct hid_device *hid)
|
||||||
|
|
||||||
init_waitqueue_head(&hiddev->wait);
|
init_waitqueue_head(&hiddev->wait);
|
||||||
INIT_LIST_HEAD(&hiddev->list);
|
INIT_LIST_HEAD(&hiddev->list);
|
||||||
|
spin_lock_init(&hiddev->list_lock);
|
||||||
hiddev->hid = hid;
|
hiddev->hid = hid;
|
||||||
hiddev->exist = 1;
|
hiddev->exist = 1;
|
||||||
|
|
||||||
|
|
|
@ -133,12 +133,11 @@ static void usb_kbd_irq(struct urb *urb)
|
||||||
static int usb_kbd_event(struct input_dev *dev, unsigned int type,
|
static int usb_kbd_event(struct input_dev *dev, unsigned int type,
|
||||||
unsigned int code, int value)
|
unsigned int code, int value)
|
||||||
{
|
{
|
||||||
struct usb_kbd *kbd = dev->private;
|
struct usb_kbd *kbd = input_get_drvdata(dev);
|
||||||
|
|
||||||
if (type != EV_LED)
|
if (type != EV_LED)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|
||||||
kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) |
|
kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) |
|
||||||
(!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) |
|
(!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) |
|
||||||
(!!test_bit(LED_NUML, dev->led));
|
(!!test_bit(LED_NUML, dev->led));
|
||||||
|
@ -175,7 +174,7 @@ static void usb_kbd_led(struct urb *urb)
|
||||||
|
|
||||||
static int usb_kbd_open(struct input_dev *dev)
|
static int usb_kbd_open(struct input_dev *dev)
|
||||||
{
|
{
|
||||||
struct usb_kbd *kbd = dev->private;
|
struct usb_kbd *kbd = input_get_drvdata(dev);
|
||||||
|
|
||||||
kbd->irq->dev = kbd->usbdev;
|
kbd->irq->dev = kbd->usbdev;
|
||||||
if (usb_submit_urb(kbd->irq, GFP_KERNEL))
|
if (usb_submit_urb(kbd->irq, GFP_KERNEL))
|
||||||
|
@ -186,7 +185,7 @@ static int usb_kbd_open(struct input_dev *dev)
|
||||||
|
|
||||||
static void usb_kbd_close(struct input_dev *dev)
|
static void usb_kbd_close(struct input_dev *dev)
|
||||||
{
|
{
|
||||||
struct usb_kbd *kbd = dev->private;
|
struct usb_kbd *kbd = input_get_drvdata(dev);
|
||||||
|
|
||||||
usb_kill_urb(kbd->irq);
|
usb_kill_urb(kbd->irq);
|
||||||
}
|
}
|
||||||
|
@ -211,12 +210,9 @@ static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd)
|
||||||
{
|
{
|
||||||
usb_free_urb(kbd->irq);
|
usb_free_urb(kbd->irq);
|
||||||
usb_free_urb(kbd->led);
|
usb_free_urb(kbd->led);
|
||||||
if (kbd->new)
|
usb_buffer_free(dev, 8, kbd->new, kbd->new_dma);
|
||||||
usb_buffer_free(dev, 8, kbd->new, kbd->new_dma);
|
usb_buffer_free(dev, sizeof(struct usb_ctrlrequest), kbd->cr, kbd->cr_dma);
|
||||||
if (kbd->cr)
|
usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma);
|
||||||
usb_buffer_free(dev, sizeof(struct usb_ctrlrequest), kbd->cr, kbd->cr_dma);
|
|
||||||
if (kbd->leds)
|
|
||||||
usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usb_kbd_probe(struct usb_interface *iface,
|
static int usb_kbd_probe(struct usb_interface *iface,
|
||||||
|
@ -274,8 +270,9 @@ static int usb_kbd_probe(struct usb_interface *iface,
|
||||||
input_dev->name = kbd->name;
|
input_dev->name = kbd->name;
|
||||||
input_dev->phys = kbd->phys;
|
input_dev->phys = kbd->phys;
|
||||||
usb_to_input_id(dev, &input_dev->id);
|
usb_to_input_id(dev, &input_dev->id);
|
||||||
input_dev->cdev.dev = &iface->dev;
|
input_dev->dev.parent = &iface->dev;
|
||||||
input_dev->private = kbd;
|
|
||||||
|
input_set_drvdata(input_dev, kbd);
|
||||||
|
|
||||||
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
|
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
|
||||||
input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA);
|
input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA);
|
||||||
|
|
|
@ -96,7 +96,7 @@ static void usb_mouse_irq(struct urb *urb)
|
||||||
|
|
||||||
static int usb_mouse_open(struct input_dev *dev)
|
static int usb_mouse_open(struct input_dev *dev)
|
||||||
{
|
{
|
||||||
struct usb_mouse *mouse = dev->private;
|
struct usb_mouse *mouse = input_get_drvdata(dev);
|
||||||
|
|
||||||
mouse->irq->dev = mouse->usbdev;
|
mouse->irq->dev = mouse->usbdev;
|
||||||
if (usb_submit_urb(mouse->irq, GFP_KERNEL))
|
if (usb_submit_urb(mouse->irq, GFP_KERNEL))
|
||||||
|
@ -107,7 +107,7 @@ static int usb_mouse_open(struct input_dev *dev)
|
||||||
|
|
||||||
static void usb_mouse_close(struct input_dev *dev)
|
static void usb_mouse_close(struct input_dev *dev)
|
||||||
{
|
{
|
||||||
struct usb_mouse *mouse = dev->private;
|
struct usb_mouse *mouse = input_get_drvdata(dev);
|
||||||
|
|
||||||
usb_kill_urb(mouse->irq);
|
usb_kill_urb(mouse->irq);
|
||||||
}
|
}
|
||||||
|
@ -171,7 +171,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
|
||||||
input_dev->name = mouse->name;
|
input_dev->name = mouse->name;
|
||||||
input_dev->phys = mouse->phys;
|
input_dev->phys = mouse->phys;
|
||||||
usb_to_input_id(dev, &input_dev->id);
|
usb_to_input_id(dev, &input_dev->id);
|
||||||
input_dev->cdev.dev = &intf->dev;
|
input_dev->dev.parent = &intf->dev;
|
||||||
|
|
||||||
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
|
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
|
||||||
input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
|
input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
|
||||||
|
@ -179,7 +179,8 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
|
||||||
input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
|
input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
|
||||||
input_dev->relbit[0] |= BIT(REL_WHEEL);
|
input_dev->relbit[0] |= BIT(REL_WHEEL);
|
||||||
|
|
||||||
input_dev->private = mouse;
|
input_set_drvdata(input_dev, mouse);
|
||||||
|
|
||||||
input_dev->open = usb_mouse_open;
|
input_dev->open = usb_mouse_open;
|
||||||
input_dev->close = usb_mouse_close;
|
input_dev->close = usb_mouse_close;
|
||||||
|
|
||||||
|
|
|
@ -275,6 +275,7 @@ struct hid_item {
|
||||||
#define HID_QUIRK_LOGITECH_DESCRIPTOR 0x00100000
|
#define HID_QUIRK_LOGITECH_DESCRIPTOR 0x00100000
|
||||||
#define HID_QUIRK_DUPLICATE_USAGES 0x00200000
|
#define HID_QUIRK_DUPLICATE_USAGES 0x00200000
|
||||||
#define HID_QUIRK_RESET_LEDS 0x00400000
|
#define HID_QUIRK_RESET_LEDS 0x00400000
|
||||||
|
#define HID_QUIRK_SWAPPED_MIN_MAX 0x00800000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the global environment of the parser. This information is
|
* This is the global environment of the parser. This information is
|
||||||
|
|
|
@ -737,10 +737,8 @@ static inline void hidp_setup_hid(struct hidp_session *session, struct hidp_conn
|
||||||
list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
|
list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
|
||||||
hidp_send_report(session, report);
|
hidp_send_report(session, report);
|
||||||
|
|
||||||
if (hidinput_connect(hid) == 0) {
|
if (hidinput_connect(hid) == 0)
|
||||||
hid->claimed |= HID_CLAIMED_INPUT;
|
hid->claimed |= HID_CLAIMED_INPUT;
|
||||||
hid_ff_init(hid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
|
int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
|
||||||
|
|
Loading…
Reference in a new issue