Merge branch 'upstream' into for-linus
Conflicts: drivers/hid/hid-wacom.c
This commit is contained in:
commit
7426ef52b4
16 changed files with 679 additions and 79 deletions
10
Documentation/ABI/testing/sysfs-wacom
Normal file
10
Documentation/ABI/testing/sysfs-wacom
Normal file
|
@ -0,0 +1,10 @@
|
|||
What: /sys/class/hidraw/hidraw*/device/speed
|
||||
Date: April 2010
|
||||
Kernel Version: 2.6.35
|
||||
Contact: linux-bluetooth@vger.kernel.org
|
||||
Description:
|
||||
The /sys/class/hidraw/hidraw*/device/speed file controls
|
||||
reporting speed of wacom bluetooth tablet. Reading from
|
||||
this file returns 1 if tablet reports in high speed mode
|
||||
or 0 otherwise. Writing to this file one of these values
|
||||
switches reporting speed.
|
|
@ -273,7 +273,7 @@ config HID_SAMSUNG
|
|||
depends on USB_HID
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Samsung InfraRed remote control.
|
||||
Support for Samsung InfraRed remote control or keyboards.
|
||||
|
||||
config HID_SONY
|
||||
tristate "Sony" if EMBEDDED
|
||||
|
@ -332,7 +332,7 @@ config HID_TOPSEED
|
|||
depends on USB_HID
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Say Y if you have a TopSeed Cyberlink remote control.
|
||||
Say Y if you have a TopSeed Cyberlink or BTC Emprex remote control.
|
||||
|
||||
config HID_THRUSTMASTER
|
||||
tristate "ThrustMaster devices support" if EMBEDDED
|
||||
|
@ -357,6 +357,14 @@ config HID_WACOM
|
|||
---help---
|
||||
Support for Wacom Graphire Bluetooth tablet.
|
||||
|
||||
config HID_WACOM_POWER_SUPPLY
|
||||
bool "Wacom Bluetooth devices power supply status support"
|
||||
depends on HID_WACOM
|
||||
select POWER_SUPPLY
|
||||
---help---
|
||||
Say Y here if you want to enable power supply status monitoring for
|
||||
Wacom Bluetooth devices.
|
||||
|
||||
config HID_ZEROPLUS
|
||||
tristate "Zeroplus based game controller support" if EMBEDDED
|
||||
depends on USB_HID
|
||||
|
@ -372,6 +380,13 @@ config ZEROPLUS_FF
|
|||
Say Y here if you have a Zeroplus based game controller and want
|
||||
to have force feedback support for it.
|
||||
|
||||
config HID_ZYDACRON
|
||||
tristate "Zydacron remote control support" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Zydacron remote control.
|
||||
|
||||
endmenu
|
||||
|
||||
endif # HID_SUPPORT
|
||||
|
|
|
@ -54,6 +54,7 @@ obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o
|
|||
obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o
|
||||
obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o
|
||||
obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o
|
||||
obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o
|
||||
obj-$(CONFIG_HID_WACOM) += hid-wacom.o
|
||||
|
||||
obj-$(CONFIG_USB_HID) += usbhid/
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* HID driver for 3M PCT multitouch panels
|
||||
*
|
||||
* Copyright (c) 2009 Stephane Chatty <chatty@enac.fr>
|
||||
* Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -25,7 +25,7 @@ MODULE_LICENSE("GPL");
|
|||
#include "hid-ids.h"
|
||||
|
||||
struct mmm_finger {
|
||||
__s32 x, y;
|
||||
__s32 x, y, w, h;
|
||||
__u8 rank;
|
||||
bool touch, valid;
|
||||
};
|
||||
|
@ -82,7 +82,18 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|||
/* touchscreen emulation */
|
||||
hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
|
||||
return 1;
|
||||
case HID_DG_WIDTH:
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_TOUCH_MAJOR);
|
||||
return 1;
|
||||
case HID_DG_HEIGHT:
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_TOUCH_MINOR);
|
||||
input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
|
||||
1, 1, 0, 0);
|
||||
return 1;
|
||||
case HID_DG_CONTACTID:
|
||||
field->logical_maximum = 59;
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_TRACKING_ID);
|
||||
return 1;
|
||||
|
@ -128,9 +139,15 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
|
|||
/* this finger is just placeholder data, ignore */
|
||||
} else if (f->touch) {
|
||||
/* this finger is on the screen */
|
||||
int wide = (f->w > f->h);
|
||||
input_event(input, EV_ABS, ABS_MT_TRACKING_ID, i);
|
||||
input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x);
|
||||
input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y);
|
||||
input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
|
||||
input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR,
|
||||
wide ? f->w : f->h);
|
||||
input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR,
|
||||
wide ? f->h : f->w);
|
||||
input_mt_sync(input);
|
||||
/*
|
||||
* touchscreen emulation: maintain the age rank
|
||||
|
@ -197,6 +214,14 @@ static int mmm_event(struct hid_device *hid, struct hid_field *field,
|
|||
case HID_DG_CONFIDENCE:
|
||||
md->valid = value;
|
||||
break;
|
||||
case HID_DG_WIDTH:
|
||||
if (md->valid)
|
||||
md->f[md->curid].w = value;
|
||||
break;
|
||||
case HID_DG_HEIGHT:
|
||||
if (md->valid)
|
||||
md->f[md->curid].h = value;
|
||||
break;
|
||||
case HID_DG_CONTACTID:
|
||||
if (md->valid) {
|
||||
md->curid = value;
|
||||
|
@ -255,6 +280,7 @@ static void mmm_remove(struct hid_device *hdev)
|
|||
|
||||
static const struct hid_device_id mmm_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, mmm_devices);
|
||||
|
@ -287,5 +313,4 @@ static void __exit mmm_exit(void)
|
|||
|
||||
module_init(mmm_init);
|
||||
module_exit(mmm_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
|
|
@ -653,10 +653,9 @@ int hid_parse_report(struct hid_device *device, __u8 *start,
|
|||
if (device->driver->report_fixup)
|
||||
device->driver->report_fixup(device, start, size);
|
||||
|
||||
device->rdesc = kmalloc(size, GFP_KERNEL);
|
||||
device->rdesc = kmemdup(start, size, GFP_KERNEL);
|
||||
if (device->rdesc == NULL)
|
||||
return -ENOMEM;
|
||||
memcpy(device->rdesc, start, size);
|
||||
device->rsize = size;
|
||||
|
||||
parser = vmalloc(sizeof(struct hid_parser));
|
||||
|
@ -940,13 +939,8 @@ static void hid_output_field(struct hid_field *field, __u8 *data)
|
|||
unsigned count = field->report_count;
|
||||
unsigned offset = field->report_offset;
|
||||
unsigned size = field->report_size;
|
||||
unsigned bitsused = offset + count * size;
|
||||
unsigned n;
|
||||
|
||||
/* make sure the unused bits in the last byte are zeros */
|
||||
if (count > 0 && size > 0 && (bitsused % 8) != 0)
|
||||
data[(bitsused-1)/8] &= (1 << (bitsused % 8)) - 1;
|
||||
|
||||
for (n = 0; n < count; n++) {
|
||||
if (field->logical_minimum < 0) /* signed values */
|
||||
implement(data, offset + n * size, size, s32ton(field->value[n], size));
|
||||
|
@ -966,6 +960,7 @@ void hid_output_report(struct hid_report *report, __u8 *data)
|
|||
if (report->id > 0)
|
||||
*data++ = report->id;
|
||||
|
||||
memset(data, 0, ((report->size - 1) >> 3) + 1);
|
||||
for (n = 0; n < report->maxfield; n++)
|
||||
hid_output_field(report->field[n], data);
|
||||
}
|
||||
|
@ -1167,6 +1162,8 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
|
|||
unsigned int i;
|
||||
int len;
|
||||
|
||||
if (hdev->quirks & HID_QUIRK_HIDDEV_FORCE)
|
||||
connect_mask |= (HID_CONNECT_HIDDEV_FORCE | HID_CONNECT_HIDDEV);
|
||||
if (hdev->bus != BUS_USB)
|
||||
connect_mask &= ~HID_CONNECT_HIDDEV;
|
||||
if (hid_hiddev(hdev))
|
||||
|
@ -1246,6 +1243,7 @@ EXPORT_SYMBOL_GPL(hid_disconnect);
|
|||
/* a list of devices for which there is a specialized driver on HID bus */
|
||||
static const struct hid_device_id hid_blacklist[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) },
|
||||
|
@ -1290,6 +1288,7 @@ static const struct hid_device_id hid_blacklist[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
|
||||
|
@ -1343,6 +1342,7 @@ static const struct hid_device_id hid_blacklist[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
|
||||
|
@ -1359,8 +1359,10 @@ static const struct hid_device_id hid_blacklist[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) },
|
||||
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
|
||||
{ }
|
||||
|
@ -1757,7 +1759,7 @@ int hid_add_device(struct hid_device *hdev)
|
|||
|
||||
/* we need to kill them here, otherwise they will stay allocated to
|
||||
* wait for coming driver */
|
||||
if (hid_ignore(hdev))
|
||||
if (!(hdev->quirks & HID_QUIRK_NO_IGNORE) && hid_ignore(hdev))
|
||||
return -ENODEV;
|
||||
|
||||
/* XXX hack, any other cleaner solution after the driver core
|
||||
|
@ -1765,11 +1767,12 @@ int hid_add_device(struct hid_device *hdev)
|
|||
dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus,
|
||||
hdev->vendor, hdev->product, atomic_inc_return(&id));
|
||||
|
||||
hid_debug_register(hdev, dev_name(&hdev->dev));
|
||||
ret = device_add(&hdev->dev);
|
||||
if (!ret)
|
||||
hdev->status |= HID_STAT_ADDED;
|
||||
|
||||
hid_debug_register(hdev, dev_name(&hdev->dev));
|
||||
else
|
||||
hid_debug_unregister(hdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#define USB_VENDOR_ID_3M 0x0596
|
||||
#define USB_DEVICE_ID_3M1968 0x0500
|
||||
#define USB_DEVICE_ID_3M2256 0x0502
|
||||
|
||||
#define USB_VENDOR_ID_A4TECH 0x09da
|
||||
#define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006
|
||||
|
@ -123,6 +124,9 @@
|
|||
#define USB_VENDOR_ID_BERKSHIRE 0x0c98
|
||||
#define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140
|
||||
|
||||
#define USB_VENDOR_ID_BTC 0x046e
|
||||
#define USB_DEVICE_ID_BTC_EMPREX_REMOTE 0x5578
|
||||
|
||||
#define USB_VENDOR_ID_CH 0x068e
|
||||
#define USB_DEVICE_ID_CH_PRO_PEDALS 0x00f2
|
||||
#define USB_DEVICE_ID_CH_COMBATSTICK 0x00f4
|
||||
|
@ -171,6 +175,9 @@
|
|||
|
||||
#define USB_VENDOR_ID_DRAGONRISE 0x0079
|
||||
|
||||
#define USB_VENDOR_ID_EGALAX 0x0EEF
|
||||
#define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001
|
||||
|
||||
#define USB_VENDOR_ID_ELO 0x04E7
|
||||
#define USB_DEVICE_ID_ELO_TS2700 0x0020
|
||||
|
||||
|
@ -409,6 +416,7 @@
|
|||
|
||||
#define USB_VENDOR_ID_SAMSUNG 0x0419
|
||||
#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001
|
||||
#define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE 0x0600
|
||||
|
||||
#define USB_VENDOR_ID_SONY 0x054c
|
||||
#define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b
|
||||
|
@ -457,6 +465,7 @@
|
|||
|
||||
#define USB_VENDOR_ID_WACOM 0x056a
|
||||
#define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81
|
||||
#define USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH 0xbd
|
||||
|
||||
#define USB_VENDOR_ID_WISEGROUP 0x0925
|
||||
#define USB_DEVICE_ID_SMARTJOY_PLUS 0x0005
|
||||
|
@ -475,6 +484,9 @@
|
|||
|
||||
#define USB_VENDOR_ID_ZEROPLUS 0x0c12
|
||||
|
||||
#define USB_VENDOR_ID_ZYDACRON 0x13EC
|
||||
#define USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL 0x0006
|
||||
|
||||
#define USB_VENDOR_ID_KYE 0x0458
|
||||
#define USB_DEVICE_ID_KYE_ERGO_525V 0x0087
|
||||
#define USB_DEVICE_ID_KYE_GPEN_560 0x5003
|
||||
|
|
|
@ -126,6 +126,9 @@ static int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage,
|
|||
case 0x1004: lg_map_key_clear(KEY_VIDEO); break;
|
||||
case 0x1005: lg_map_key_clear(KEY_AUDIO); break;
|
||||
case 0x100a: lg_map_key_clear(KEY_DOCUMENTS); break;
|
||||
/* The following two entries are Playlist 1 and 2 on the MX3200 */
|
||||
case 0x100f: lg_map_key_clear(KEY_FN_1); break;
|
||||
case 0x1010: lg_map_key_clear(KEY_FN_2); break;
|
||||
case 0x1011: lg_map_key_clear(KEY_PREVIOUSSONG); break;
|
||||
case 0x1012: lg_map_key_clear(KEY_NEXTSONG); break;
|
||||
case 0x1013: lg_map_key_clear(KEY_CAMERA); break;
|
||||
|
@ -137,6 +140,7 @@ static int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage,
|
|||
case 0x1019: lg_map_key_clear(KEY_PROG1); break;
|
||||
case 0x101a: lg_map_key_clear(KEY_PROG2); break;
|
||||
case 0x101b: lg_map_key_clear(KEY_PROG3); break;
|
||||
case 0x101c: lg_map_key_clear(KEY_CYCLEWINDOWS); break;
|
||||
case 0x101f: lg_map_key_clear(KEY_ZOOMIN); break;
|
||||
case 0x1020: lg_map_key_clear(KEY_ZOOMOUT); break;
|
||||
case 0x1021: lg_map_key_clear(KEY_ZOOMRESET); break;
|
||||
|
@ -147,6 +151,11 @@ static int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage,
|
|||
case 0x1029: lg_map_key_clear(KEY_SHUFFLE); break;
|
||||
case 0x102a: lg_map_key_clear(KEY_BACK); break;
|
||||
case 0x102b: lg_map_key_clear(KEY_CYCLEWINDOWS); break;
|
||||
case 0x102d: lg_map_key_clear(KEY_WWW); break;
|
||||
/* The following two are 'Start/answer call' and 'End/reject call'
|
||||
on the MX3200 */
|
||||
case 0x1031: lg_map_key_clear(KEY_OK); break;
|
||||
case 0x1032: lg_map_key_clear(KEY_CANCEL); break;
|
||||
case 0x1041: lg_map_key_clear(KEY_BATTERY); break;
|
||||
case 0x1042: lg_map_key_clear(KEY_WORDPROCESSOR); break;
|
||||
case 0x1043: lg_map_key_clear(KEY_SPREADSHEET); break;
|
||||
|
|
|
@ -7,6 +7,18 @@
|
|||
* Copyright (c) 2006-2007 Jiri Kosina
|
||||
* Copyright (c) 2007 Paul Walmsley
|
||||
* Copyright (c) 2008 Jiri Slaby
|
||||
* Copyright (c) 2010 Don Prince <dhprince.devel@yahoo.co.uk>
|
||||
*
|
||||
*
|
||||
* This driver supports several HID devices:
|
||||
*
|
||||
* [0419:0001] Samsung IrDA remote controller (reports as Cypress USB Mouse).
|
||||
* various hid report fixups for different variants.
|
||||
*
|
||||
* [0419:0600] Creative Desktop Wireless 6000 keyboard/mouse combo
|
||||
* several key mappings used from the consumer usage page
|
||||
* deviate from the USB HUT 1.12 standard.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -17,14 +29,13 @@
|
|||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "hid-ids.h"
|
||||
|
||||
/*
|
||||
* Samsung IrDA remote controller (reports as Cypress USB Mouse).
|
||||
*
|
||||
* There are several variants for 0419:0001:
|
||||
*
|
||||
* 1. 184 byte report descriptor
|
||||
|
@ -43,21 +54,21 @@
|
|||
* 4. 171 byte report descriptor
|
||||
* Report #3 has an array field with logical range 0..1 instead of 1..3.
|
||||
*/
|
||||
static inline void samsung_dev_trace(struct hid_device *hdev,
|
||||
static inline void samsung_irda_dev_trace(struct hid_device *hdev,
|
||||
unsigned int rsize)
|
||||
{
|
||||
dev_info(&hdev->dev, "fixing up Samsung IrDA %d byte report "
|
||||
"descriptor\n", rsize);
|
||||
}
|
||||
|
||||
static void samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||
static void samsung_irda_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||
unsigned int rsize)
|
||||
{
|
||||
if (rsize == 184 && rdesc[175] == 0x25 && rdesc[176] == 0x40 &&
|
||||
rdesc[177] == 0x75 && rdesc[178] == 0x30 &&
|
||||
rdesc[179] == 0x95 && rdesc[180] == 0x01 &&
|
||||
rdesc[182] == 0x40) {
|
||||
samsung_dev_trace(hdev, 184);
|
||||
samsung_irda_dev_trace(hdev, 184);
|
||||
rdesc[176] = 0xff;
|
||||
rdesc[178] = 0x08;
|
||||
rdesc[180] = 0x06;
|
||||
|
@ -65,24 +76,80 @@ static void samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
} else
|
||||
if (rsize == 203 && rdesc[192] == 0x15 && rdesc[193] == 0x0 &&
|
||||
rdesc[194] == 0x25 && rdesc[195] == 0x12) {
|
||||
samsung_dev_trace(hdev, 203);
|
||||
samsung_irda_dev_trace(hdev, 203);
|
||||
rdesc[193] = 0x1;
|
||||
rdesc[195] = 0xf;
|
||||
} else
|
||||
if (rsize == 135 && rdesc[124] == 0x15 && rdesc[125] == 0x0 &&
|
||||
rdesc[126] == 0x25 && rdesc[127] == 0x11) {
|
||||
samsung_dev_trace(hdev, 135);
|
||||
samsung_irda_dev_trace(hdev, 135);
|
||||
rdesc[125] = 0x1;
|
||||
rdesc[127] = 0xe;
|
||||
} else
|
||||
if (rsize == 171 && rdesc[160] == 0x15 && rdesc[161] == 0x0 &&
|
||||
rdesc[162] == 0x25 && rdesc[163] == 0x01) {
|
||||
samsung_dev_trace(hdev, 171);
|
||||
samsung_irda_dev_trace(hdev, 171);
|
||||
rdesc[161] = 0x1;
|
||||
rdesc[163] = 0x3;
|
||||
}
|
||||
}
|
||||
|
||||
#define samsung_kbd_mouse_map_key_clear(c) \
|
||||
hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
|
||||
|
||||
static int samsung_kbd_mouse_input_mapping(struct hid_device *hdev,
|
||||
struct hid_input *hi, struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
|
||||
unsigned short ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
|
||||
|
||||
if (1 != ifnum || HID_UP_CONSUMER != (usage->hid & HID_USAGE_PAGE))
|
||||
return 0;
|
||||
|
||||
dbg_hid("samsung wireless keyboard/mouse input mapping event [0x%x]\n",
|
||||
usage->hid & HID_USAGE);
|
||||
|
||||
switch (usage->hid & HID_USAGE) {
|
||||
/* report 2 */
|
||||
case 0x183: samsung_kbd_mouse_map_key_clear(KEY_MEDIA); break;
|
||||
case 0x195: samsung_kbd_mouse_map_key_clear(KEY_EMAIL); break;
|
||||
case 0x196: samsung_kbd_mouse_map_key_clear(KEY_CALC); break;
|
||||
case 0x197: samsung_kbd_mouse_map_key_clear(KEY_COMPUTER); break;
|
||||
case 0x22b: samsung_kbd_mouse_map_key_clear(KEY_SEARCH); break;
|
||||
case 0x22c: samsung_kbd_mouse_map_key_clear(KEY_WWW); break;
|
||||
case 0x22d: samsung_kbd_mouse_map_key_clear(KEY_BACK); break;
|
||||
case 0x22e: samsung_kbd_mouse_map_key_clear(KEY_FORWARD); break;
|
||||
case 0x22f: samsung_kbd_mouse_map_key_clear(KEY_FAVORITES); break;
|
||||
case 0x230: samsung_kbd_mouse_map_key_clear(KEY_REFRESH); break;
|
||||
case 0x231: samsung_kbd_mouse_map_key_clear(KEY_STOP); break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||
unsigned int rsize)
|
||||
{
|
||||
if (USB_DEVICE_ID_SAMSUNG_IR_REMOTE == hdev->product)
|
||||
samsung_irda_report_fixup(hdev, rdesc, rsize);
|
||||
}
|
||||
|
||||
static int samsung_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE == hdev->product)
|
||||
ret = samsung_kbd_mouse_input_mapping(hdev,
|
||||
hi, field, usage, bit, max);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int samsung_probe(struct hid_device *hdev,
|
||||
const struct hid_device_id *id)
|
||||
{
|
||||
|
@ -95,10 +162,12 @@ static int samsung_probe(struct hid_device *hdev,
|
|||
goto err_free;
|
||||
}
|
||||
|
||||
if (hdev->rsize == 184) {
|
||||
/* disable hidinput, force hiddev */
|
||||
cmask = (cmask & ~HID_CONNECT_HIDINPUT) |
|
||||
HID_CONNECT_HIDDEV_FORCE;
|
||||
if (USB_DEVICE_ID_SAMSUNG_IR_REMOTE == hdev->product) {
|
||||
if (hdev->rsize == 184) {
|
||||
/* disable hidinput, force hiddev */
|
||||
cmask = (cmask & ~HID_CONNECT_HIDINPUT) |
|
||||
HID_CONNECT_HIDDEV_FORCE;
|
||||
}
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, cmask);
|
||||
|
@ -114,6 +183,7 @@ static int samsung_probe(struct hid_device *hdev,
|
|||
|
||||
static const struct hid_device_id samsung_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, samsung_devices);
|
||||
|
@ -122,6 +192,7 @@ static struct hid_driver samsung_driver = {
|
|||
.name = "samsung",
|
||||
.id_table = samsung_devices,
|
||||
.report_fixup = samsung_report_fixup,
|
||||
.input_mapping = samsung_input_mapping,
|
||||
.probe = samsung_probe,
|
||||
};
|
||||
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
*
|
||||
* Copyright (c) 2008 Lev Babiev
|
||||
* based on hid-cherry driver
|
||||
*
|
||||
* Modified to also support BTC "Emprex 3009URF III Vista MCE Remote" by
|
||||
* Wayne Thomas 2010.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -24,23 +27,29 @@ static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
if ((usage->hid & HID_USAGE_PAGE) != 0x0ffbc0000)
|
||||
if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
|
||||
return 0;
|
||||
|
||||
switch (usage->hid & HID_USAGE) {
|
||||
case 0x00d: ts_map_key_clear(KEY_HOME); break;
|
||||
case 0x024: ts_map_key_clear(KEY_MENU); break;
|
||||
case 0x025: ts_map_key_clear(KEY_TV); break;
|
||||
case 0x048: ts_map_key_clear(KEY_RED); break;
|
||||
case 0x047: ts_map_key_clear(KEY_GREEN); break;
|
||||
case 0x049: ts_map_key_clear(KEY_YELLOW); break;
|
||||
case 0x04a: ts_map_key_clear(KEY_BLUE); break;
|
||||
case 0x04b: ts_map_key_clear(KEY_ANGLE); break;
|
||||
case 0x04c: ts_map_key_clear(KEY_LANGUAGE); break;
|
||||
case 0x04d: ts_map_key_clear(KEY_SUBTITLE); break;
|
||||
case 0x031: ts_map_key_clear(KEY_AUDIO); break;
|
||||
case 0x032: ts_map_key_clear(KEY_TEXT); break;
|
||||
case 0x033: ts_map_key_clear(KEY_CHANNEL); break;
|
||||
case 0x00d: ts_map_key_clear(KEY_MEDIA); break;
|
||||
case 0x024: ts_map_key_clear(KEY_MENU); break;
|
||||
case 0x025: ts_map_key_clear(KEY_TV); break;
|
||||
case 0x031: ts_map_key_clear(KEY_AUDIO); break;
|
||||
case 0x032: ts_map_key_clear(KEY_TEXT); break;
|
||||
case 0x033: ts_map_key_clear(KEY_CHANNEL); break;
|
||||
case 0x047: ts_map_key_clear(KEY_MP3); break;
|
||||
case 0x048: ts_map_key_clear(KEY_TV2); break;
|
||||
case 0x049: ts_map_key_clear(KEY_CAMERA); break;
|
||||
case 0x04a: ts_map_key_clear(KEY_VIDEO); break;
|
||||
case 0x04b: ts_map_key_clear(KEY_ANGLE); break;
|
||||
case 0x04c: ts_map_key_clear(KEY_LANGUAGE); break;
|
||||
case 0x04d: ts_map_key_clear(KEY_SUBTITLE); break;
|
||||
case 0x050: ts_map_key_clear(KEY_RADIO); break;
|
||||
case 0x05a: ts_map_key_clear(KEY_TEXT); break;
|
||||
case 0x05b: ts_map_key_clear(KEY_RED); break;
|
||||
case 0x05c: ts_map_key_clear(KEY_GREEN); break;
|
||||
case 0x05d: ts_map_key_clear(KEY_YELLOW); break;
|
||||
case 0x05e: ts_map_key_clear(KEY_BLUE); break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -50,6 +59,7 @@ static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|||
|
||||
static const struct hid_device_id ts_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, ts_devices);
|
||||
|
|
|
@ -22,14 +22,159 @@
|
|||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
|
||||
#include <linux/power_supply.h>
|
||||
#endif
|
||||
|
||||
#include "hid-ids.h"
|
||||
|
||||
struct wacom_data {
|
||||
__u16 tool;
|
||||
unsigned char butstate;
|
||||
unsigned char high_speed;
|
||||
#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
|
||||
int battery_capacity;
|
||||
struct power_supply battery;
|
||||
struct power_supply ac;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
|
||||
/*percent of battery capacity, 0 means AC online*/
|
||||
static unsigned short batcap[8] = { 1, 15, 25, 35, 50, 70, 100, 0 };
|
||||
|
||||
static enum power_supply_property wacom_battery_props[] = {
|
||||
POWER_SUPPLY_PROP_PRESENT,
|
||||
POWER_SUPPLY_PROP_CAPACITY
|
||||
};
|
||||
|
||||
static enum power_supply_property wacom_ac_props[] = {
|
||||
POWER_SUPPLY_PROP_PRESENT,
|
||||
POWER_SUPPLY_PROP_ONLINE
|
||||
};
|
||||
|
||||
static int wacom_battery_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
struct wacom_data *wdata = container_of(psy,
|
||||
struct wacom_data, battery);
|
||||
int power_state = batcap[wdata->battery_capacity];
|
||||
int ret = 0;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_PRESENT:
|
||||
val->intval = 1;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CAPACITY:
|
||||
/* show 100% battery capacity when charging */
|
||||
if (power_state == 0)
|
||||
val->intval = 100;
|
||||
else
|
||||
val->intval = power_state;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wacom_ac_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
struct wacom_data *wdata = container_of(psy, struct wacom_data, ac);
|
||||
int power_state = batcap[wdata->battery_capacity];
|
||||
int ret = 0;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_PRESENT:
|
||||
/* fall through */
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
if (power_state == 0)
|
||||
val->intval = 1;
|
||||
else
|
||||
val->intval = 0;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void wacom_poke(struct hid_device *hdev, u8 speed)
|
||||
{
|
||||
struct wacom_data *wdata = hid_get_drvdata(hdev);
|
||||
int limit, ret;
|
||||
char rep_data[2];
|
||||
|
||||
rep_data[0] = 0x03 ; rep_data[1] = 0x00;
|
||||
limit = 3;
|
||||
do {
|
||||
ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
|
||||
HID_FEATURE_REPORT);
|
||||
} while (ret < 0 && limit-- > 0);
|
||||
|
||||
if (ret >= 0) {
|
||||
if (speed == 0)
|
||||
rep_data[0] = 0x05;
|
||||
else
|
||||
rep_data[0] = 0x06;
|
||||
|
||||
rep_data[1] = 0x00;
|
||||
limit = 3;
|
||||
do {
|
||||
ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
|
||||
HID_FEATURE_REPORT);
|
||||
} while (ret < 0 && limit-- > 0);
|
||||
|
||||
if (ret >= 0) {
|
||||
wdata->high_speed = speed;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that if the raw queries fail, it's not a hard failure and it
|
||||
* is safe to continue
|
||||
*/
|
||||
dev_warn(&hdev->dev, "failed to poke device, command %d, err %d\n",
|
||||
rep_data[0], ret);
|
||||
return;
|
||||
}
|
||||
|
||||
static ssize_t wacom_show_speed(struct device *dev,
|
||||
struct device_attribute
|
||||
*attr, char *buf)
|
||||
{
|
||||
struct wacom_data *wdata = dev_get_drvdata(dev);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%i\n", wdata->high_speed);
|
||||
}
|
||||
|
||||
static ssize_t wacom_store_speed(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct hid_device *hdev = container_of(dev, struct hid_device, dev);
|
||||
int new_speed;
|
||||
|
||||
if (sscanf(buf, "%1d", &new_speed ) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (new_speed == 0 || new_speed == 1) {
|
||||
wacom_poke(hdev, new_speed);
|
||||
return strnlen(buf, PAGE_SIZE);
|
||||
} else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(speed, S_IRUGO | S_IWUGO,
|
||||
wacom_show_speed, wacom_store_speed);
|
||||
|
||||
static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
|
||||
u8 *raw_data, int size)
|
||||
{
|
||||
|
@ -148,6 +293,12 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
|
|||
input_sync(input);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
|
||||
/* Store current battery capacity */
|
||||
rw = (data[7] >> 2 & 0x07);
|
||||
if (rw != wdata->battery_capacity)
|
||||
wdata->battery_capacity = rw;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -157,9 +308,7 @@ static int wacom_probe(struct hid_device *hdev,
|
|||
struct hid_input *hidinput;
|
||||
struct input_dev *input;
|
||||
struct wacom_data *wdata;
|
||||
char rep_data[2];
|
||||
int ret;
|
||||
int limit;
|
||||
|
||||
wdata = kzalloc(sizeof(*wdata), GFP_KERNEL);
|
||||
if (wdata == NULL) {
|
||||
|
@ -182,31 +331,53 @@ static int wacom_probe(struct hid_device *hdev,
|
|||
goto err_free;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that if the raw queries fail, it's not a hard failure and it
|
||||
* is safe to continue
|
||||
*/
|
||||
ret = device_create_file(&hdev->dev, &dev_attr_speed);
|
||||
if (ret)
|
||||
dev_warn(&hdev->dev,
|
||||
"can't create sysfs speed attribute err: %d\n", ret);
|
||||
|
||||
/* Set Wacom mode2 */
|
||||
rep_data[0] = 0x03; rep_data[1] = 0x00;
|
||||
limit = 3;
|
||||
do {
|
||||
ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
|
||||
HID_FEATURE_REPORT);
|
||||
} while (ret < 0 && limit-- > 0);
|
||||
if (ret < 0)
|
||||
dev_warn(&hdev->dev, "failed to poke device #1, %d\n", ret);
|
||||
/* Set Wacom mode 2 with high reporting speed */
|
||||
wacom_poke(hdev, 1);
|
||||
|
||||
/* 0x06 - high reporting speed, 0x05 - low speed */
|
||||
rep_data[0] = 0x06; rep_data[1] = 0x00;
|
||||
limit = 3;
|
||||
do {
|
||||
ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
|
||||
HID_FEATURE_REPORT);
|
||||
} while (ret < 0 && limit-- > 0);
|
||||
if (ret < 0)
|
||||
dev_warn(&hdev->dev, "failed to poke device #2, %d\n", ret);
|
||||
#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
|
||||
wdata->battery.properties = wacom_battery_props;
|
||||
wdata->battery.num_properties = ARRAY_SIZE(wacom_battery_props);
|
||||
wdata->battery.get_property = wacom_battery_get_property;
|
||||
wdata->battery.name = "wacom_battery";
|
||||
wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
|
||||
wdata->battery.use_for_apm = 0;
|
||||
|
||||
ret = power_supply_register(&hdev->dev, &wdata->battery);
|
||||
if (ret) {
|
||||
dev_warn(&hdev->dev,
|
||||
"can't create sysfs battery attribute, err: %d\n", ret);
|
||||
/*
|
||||
* battery attribute is not critical for the tablet, but if it
|
||||
* failed then there is no need to create ac attribute
|
||||
*/
|
||||
goto move_on;
|
||||
}
|
||||
|
||||
wdata->ac.properties = wacom_ac_props;
|
||||
wdata->ac.num_properties = ARRAY_SIZE(wacom_ac_props);
|
||||
wdata->ac.get_property = wacom_ac_get_property;
|
||||
wdata->ac.name = "wacom_ac";
|
||||
wdata->ac.type = POWER_SUPPLY_TYPE_MAINS;
|
||||
wdata->ac.use_for_apm = 0;
|
||||
|
||||
ret = power_supply_register(&hdev->dev, &wdata->ac);
|
||||
if (ret) {
|
||||
dev_warn(&hdev->dev,
|
||||
"can't create ac battery attribute, err: %d\n", ret);
|
||||
/*
|
||||
* ac attribute is not critical for the tablet, but if it
|
||||
* failed then we don't want to battery attribute to exist
|
||||
*/
|
||||
power_supply_unregister(&wdata->battery);
|
||||
}
|
||||
|
||||
move_on:
|
||||
#endif
|
||||
hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
|
||||
input = hidinput->input;
|
||||
|
||||
|
@ -251,13 +422,21 @@ static int wacom_probe(struct hid_device *hdev,
|
|||
|
||||
static void wacom_remove(struct hid_device *hdev)
|
||||
{
|
||||
#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
|
||||
struct wacom_data *wdata = hid_get_drvdata(hdev);
|
||||
#endif
|
||||
hid_hw_stop(hdev);
|
||||
|
||||
#ifdef CONFIG_HID_WACOM_POWER_SUPPLY
|
||||
power_supply_unregister(&wdata->battery);
|
||||
power_supply_unregister(&wdata->ac);
|
||||
#endif
|
||||
kfree(hid_get_drvdata(hdev));
|
||||
}
|
||||
|
||||
static const struct hid_device_id wacom_devices[] = {
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
|
||||
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, wacom_devices);
|
||||
|
|
237
drivers/hid/hid-zydacron.c
Normal file
237
drivers/hid/hid-zydacron.c
Normal file
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* HID driver for zydacron remote control
|
||||
*
|
||||
* Copyright (c) 2010 Don Prince <dhprince.devel@yahoo.co.uk>
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "hid-ids.h"
|
||||
|
||||
struct zc_device {
|
||||
struct input_dev *input_ep81;
|
||||
unsigned short last_key[4];
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Zydacron remote control has an invalid HID report descriptor,
|
||||
* that needs fixing before we can parse it.
|
||||
*/
|
||||
static void zc_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||
unsigned int rsize)
|
||||
{
|
||||
if (rsize >= 253 &&
|
||||
rdesc[0x96] == 0xbc && rdesc[0x97] == 0xff &&
|
||||
rdesc[0xca] == 0xbc && rdesc[0xcb] == 0xff &&
|
||||
rdesc[0xe1] == 0xbc && rdesc[0xe2] == 0xff) {
|
||||
dev_info(&hdev->dev,
|
||||
"fixing up zydacron remote control report "
|
||||
"descriptor\n");
|
||||
rdesc[0x96] = rdesc[0xca] = rdesc[0xe1] = 0x0c;
|
||||
rdesc[0x97] = rdesc[0xcb] = rdesc[0xe2] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
#define zc_map_key_clear(c) \
|
||||
hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
|
||||
|
||||
static int zc_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
int i;
|
||||
struct zc_device *zc = hid_get_drvdata(hdev);
|
||||
zc->input_ep81 = hi->input;
|
||||
|
||||
if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
|
||||
return 0;
|
||||
|
||||
dbg_hid("zynacron input mapping event [0x%x]\n",
|
||||
usage->hid & HID_USAGE);
|
||||
|
||||
switch (usage->hid & HID_USAGE) {
|
||||
/* report 2 */
|
||||
case 0x10:
|
||||
zc_map_key_clear(KEY_MODE);
|
||||
break;
|
||||
case 0x30:
|
||||
zc_map_key_clear(KEY_SCREEN);
|
||||
break;
|
||||
case 0x70:
|
||||
zc_map_key_clear(KEY_INFO);
|
||||
break;
|
||||
/* report 3 */
|
||||
case 0x04:
|
||||
zc_map_key_clear(KEY_RADIO);
|
||||
break;
|
||||
/* report 4 */
|
||||
case 0x0d:
|
||||
zc_map_key_clear(KEY_PVR);
|
||||
break;
|
||||
case 0x25:
|
||||
zc_map_key_clear(KEY_TV);
|
||||
break;
|
||||
case 0x47:
|
||||
zc_map_key_clear(KEY_AUDIO);
|
||||
break;
|
||||
case 0x49:
|
||||
zc_map_key_clear(KEY_AUX);
|
||||
break;
|
||||
case 0x4a:
|
||||
zc_map_key_clear(KEY_VIDEO);
|
||||
break;
|
||||
case 0x48:
|
||||
zc_map_key_clear(KEY_DVD);
|
||||
break;
|
||||
case 0x24:
|
||||
zc_map_key_clear(KEY_MENU);
|
||||
break;
|
||||
case 0x32:
|
||||
zc_map_key_clear(KEY_TEXT);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
zc->last_key[i] = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int zc_raw_event(struct hid_device *hdev, struct hid_report *report,
|
||||
u8 *data, int size)
|
||||
{
|
||||
struct zc_device *zc = hid_get_drvdata(hdev);
|
||||
int ret = 0;
|
||||
unsigned key;
|
||||
unsigned short index;
|
||||
|
||||
if (report->id == data[0]) {
|
||||
|
||||
/* break keys */
|
||||
for (index = 0; index < 4; index++) {
|
||||
key = zc->last_key[index];
|
||||
if (key) {
|
||||
input_event(zc->input_ep81, EV_KEY, key, 0);
|
||||
zc->last_key[index] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
key = 0;
|
||||
switch (report->id) {
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
switch (data[1]) {
|
||||
case 0x10:
|
||||
key = KEY_MODE;
|
||||
index = 0;
|
||||
break;
|
||||
case 0x30:
|
||||
key = KEY_SCREEN;
|
||||
index = 1;
|
||||
break;
|
||||
case 0x70:
|
||||
key = KEY_INFO;
|
||||
index = 2;
|
||||
break;
|
||||
case 0x04:
|
||||
key = KEY_RADIO;
|
||||
index = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
if (key) {
|
||||
input_event(zc->input_ep81, EV_KEY, key, 1);
|
||||
zc->last_key[index] = key;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int zc_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
struct zc_device *zc;
|
||||
|
||||
zc = kzalloc(sizeof(*zc), GFP_KERNEL);
|
||||
if (zc == NULL) {
|
||||
dev_err(&hdev->dev, "zydacron: can't alloc descriptor\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hid_set_drvdata(hdev, zc);
|
||||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "zydacron: parse failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "zydacron: hw start failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err_free:
|
||||
kfree(zc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void zc_remove(struct hid_device *hdev)
|
||||
{
|
||||
struct zc_device *zc = hid_get_drvdata(hdev);
|
||||
|
||||
hid_hw_stop(hdev);
|
||||
|
||||
if (NULL != zc)
|
||||
kfree(zc);
|
||||
}
|
||||
|
||||
static const struct hid_device_id zc_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, zc_devices);
|
||||
|
||||
static struct hid_driver zc_driver = {
|
||||
.name = "zydacron",
|
||||
.id_table = zc_devices,
|
||||
.report_fixup = zc_report_fixup,
|
||||
.input_mapping = zc_input_mapping,
|
||||
.raw_event = zc_raw_event,
|
||||
.probe = zc_probe,
|
||||
.remove = zc_remove,
|
||||
};
|
||||
|
||||
static int __init zc_init(void)
|
||||
{
|
||||
return hid_register_driver(&zc_driver);
|
||||
}
|
||||
|
||||
static void __exit zc_exit(void)
|
||||
{
|
||||
hid_unregister_driver(&zc_driver);
|
||||
}
|
||||
|
||||
module_init(zc_init);
|
||||
module_exit(zc_exit);
|
||||
MODULE_LICENSE("GPL");
|
|
@ -311,7 +311,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
|
|||
-EFAULT : len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = -ENOTTY;
|
||||
}
|
||||
|
|
|
@ -807,16 +807,36 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co
|
|||
struct usb_host_interface *interface = intf->cur_altsetting;
|
||||
int ret;
|
||||
|
||||
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
|
||||
HID_REQ_SET_REPORT,
|
||||
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
((report_type + 1) << 8) | *buf,
|
||||
interface->desc.bInterfaceNumber, buf + 1, count - 1,
|
||||
USB_CTRL_SET_TIMEOUT);
|
||||
|
||||
/* count also the report id */
|
||||
if (ret > 0)
|
||||
ret++;
|
||||
if (usbhid->urbout) {
|
||||
int actual_length;
|
||||
int skipped_report_id = 0;
|
||||
if (buf[0] == 0x0) {
|
||||
/* Don't send the Report ID */
|
||||
buf++;
|
||||
count--;
|
||||
skipped_report_id = 1;
|
||||
}
|
||||
ret = usb_interrupt_msg(dev, usbhid->urbout->pipe,
|
||||
buf, count, &actual_length,
|
||||
USB_CTRL_SET_TIMEOUT);
|
||||
/* return the number of bytes transferred */
|
||||
if (ret == 0) {
|
||||
ret = actual_length;
|
||||
/* count also the report id */
|
||||
if (skipped_report_id)
|
||||
ret++;
|
||||
}
|
||||
} else {
|
||||
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
|
||||
HID_REQ_SET_REPORT,
|
||||
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
((report_type + 1) << 8) | *buf,
|
||||
interface->desc.bInterfaceNumber, buf + 1, count - 1,
|
||||
USB_CTRL_SET_TIMEOUT);
|
||||
/* count also the report id */
|
||||
if (ret > 0)
|
||||
ret++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1019,12 +1039,15 @@ static int usbhid_start(struct hid_device *hid)
|
|||
/* Some keyboards don't work until their LEDs have been set.
|
||||
* Since BIOSes do set the LEDs, it must be safe for any device
|
||||
* that supports the keyboard boot protocol.
|
||||
* In addition, enable remote wakeup by default for all keyboard
|
||||
* devices supporting the boot protocol.
|
||||
*/
|
||||
if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT &&
|
||||
interface->desc.bInterfaceProtocol ==
|
||||
USB_INTERFACE_PROTOCOL_KEYBOARD)
|
||||
USB_INTERFACE_PROTOCOL_KEYBOARD) {
|
||||
usbhid_set_leds(hid);
|
||||
|
||||
device_set_wakeup_enable(&dev->dev, 1);
|
||||
}
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
@ -1133,6 +1156,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
|
|||
hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
|
||||
hid->product = le16_to_cpu(dev->descriptor.idProduct);
|
||||
hid->name[0] = 0;
|
||||
hid->quirks = usbhid_lookup_quirk(hid->vendor, hid->product);
|
||||
if (intf->cur_altsetting->desc.bInterfaceProtocol ==
|
||||
USB_INTERFACE_PROTOCOL_MOUSE)
|
||||
hid->type = HID_TYPE_USBMOUSE;
|
||||
|
|
|
@ -33,6 +33,7 @@ static const struct hid_blacklist {
|
|||
{ USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, 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_EGALAX, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT },
|
||||
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
|
||||
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
|
||||
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
|
||||
|
|
|
@ -313,6 +313,7 @@ static int usb_kbd_probe(struct usb_interface *iface,
|
|||
goto fail2;
|
||||
|
||||
usb_set_intfdata(iface, kbd);
|
||||
device_set_wakeup_enable(&dev->dev, 1);
|
||||
return 0;
|
||||
|
||||
fail2:
|
||||
|
|
|
@ -308,11 +308,13 @@ struct hid_item {
|
|||
#define HID_QUIRK_NOTOUCH 0x00000002
|
||||
#define HID_QUIRK_IGNORE 0x00000004
|
||||
#define HID_QUIRK_NOGET 0x00000008
|
||||
#define HID_QUIRK_HIDDEV_FORCE 0x00000010
|
||||
#define HID_QUIRK_BADPAD 0x00000020
|
||||
#define HID_QUIRK_MULTI_INPUT 0x00000040
|
||||
#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000
|
||||
#define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000
|
||||
#define HID_QUIRK_NO_INIT_REPORTS 0x20000000
|
||||
#define HID_QUIRK_NO_IGNORE 0x40000000
|
||||
|
||||
/*
|
||||
* This is the global environment of the parser. This information is
|
||||
|
|
Loading…
Reference in a new issue