Commit d66435cc authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid

Pull HID updates from Jiri Kosina:

 - functionally equivalent cleanups for wacom driver, making the code
   more readable, from Benjamin Tissoires

 - a bunch of improvements and fixes for thingm driver from Heiner
   Kallweit

 - bugfixes to out-of-bound access for generic parsing functions (which
   have been there since ever) extract() and implement(), from Dmitry
   Torokhov

 - a lot of added / improved device support in sony, wacom, microsoft,
   multitouch and logitech driver, from various people

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (44 commits)
  HID: microsoft: Add ID for MS Wireless Comfort Keyboard
  hid: thingm: reorder calls in thingm_probe
  HID: i2c-hid: fix OOB write in i2c_hid_set_or_send_report()
  HID: multitouch: Release all touch slots on reset_resume
  HID: usbhid: enable NO_INIT_REPORTS quirk for Semico USB Keykoard2
  HID: penmount: report only one button for PenMount 6000 USB touchscreen controller
  HID: i2c-hid: Fix suspend/resume when already runtime suspended
  HID: i2c-hid: Add hid-over-i2c name to i2c id table
  HID: multitouch: force retrieving of Win8 signature blob
  HID: Support for CMedia CM6533 HID audio jack controls
  HID: thingm: improve locking
  HID: thingm: switch to managed version of led_classdev_register
  HID: thingm: remove workqueue
  HID: corsair: fix mapping of non-keyboard usages
  HID: wacom: close the wireless receiver on remove()
  HID: wacom: cleanup input devices
  HID: wacom: reuse wacom_parse_and_register() in wireless_work
  HID: wacom: move down wireless_work()
  HID: wacom: break out parsing of device and registering of input
  HID: wacom: break out wacom_intuos_get_tool_type
  ...
parents 1a46712a e1c9b9ff
...@@ -196,6 +196,12 @@ config HID_PRODIKEYS ...@@ -196,6 +196,12 @@ config HID_PRODIKEYS
multimedia keyboard, but will lack support for the musical keyboard multimedia keyboard, but will lack support for the musical keyboard
and some additional multimedia keys. and some additional multimedia keys.
config HID_CMEDIA
tristate "CMedia CM6533 HID audio jack controls"
depends on HID
---help---
Support for CMedia CM6533 HID audio jack controls.
config HID_CP2112 config HID_CP2112
tristate "Silicon Labs CP2112 HID USB-to-SMBus Bridge support" tristate "Silicon Labs CP2112 HID USB-to-SMBus Bridge support"
depends on USB_HID && I2C && GPIOLIB depends on USB_HID && I2C && GPIOLIB
......
...@@ -29,6 +29,7 @@ obj-$(CONFIG_HID_BELKIN) += hid-belkin.o ...@@ -29,6 +29,7 @@ obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
obj-$(CONFIG_HID_BETOP_FF) += hid-betopff.o obj-$(CONFIG_HID_BETOP_FF) += hid-betopff.o
obj-$(CONFIG_HID_CHERRY) += hid-cherry.o obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
obj-$(CONFIG_HID_CHICONY) += hid-chicony.o obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
obj-$(CONFIG_HID_CMEDIA) += hid-cmedia.o
obj-$(CONFIG_HID_CORSAIR) += hid-corsair.o obj-$(CONFIG_HID_CORSAIR) += hid-corsair.o
obj-$(CONFIG_HID_CP2112) += hid-cp2112.o obj-$(CONFIG_HID_CP2112) += hid-cp2112.o
obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
......
/*
* HID driver for CMedia CM6533 audio jack controls
*
* Copyright (C) 2015 Ben Chen <ben_chen@bizlinktech.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include "hid-ids.h"
MODULE_AUTHOR("Ben Chen");
MODULE_DESCRIPTION("CM6533 HID jack controls");
MODULE_LICENSE("GPL");
#define CM6533_JD_TYPE_COUNT 1
#define CM6533_JD_RAWEV_LEN 16
#define CM6533_JD_SFX_OFFSET 8
/*
*
*CM6533 audio jack HID raw events:
*
*Plug in:
*01000600 002083xx 080008c0 10000000
*about 3 seconds later...
*01000a00 002083xx 08000380 10000000
*01000600 002083xx 08000380 10000000
*
*Plug out:
*01000400 002083xx 080008c0 x0000000
*/
static const u8 ji_sfx[] = { 0x08, 0x00, 0x08, 0xc0 };
static const u8 ji_in[] = { 0x01, 0x00, 0x06, 0x00 };
static const u8 ji_out[] = { 0x01, 0x00, 0x04, 0x00 };
static int jack_switch_types[CM6533_JD_TYPE_COUNT] = {
SW_HEADPHONE_INSERT,
};
struct cmhid {
struct input_dev *input_dev;
struct hid_device *hid;
unsigned short switch_map[CM6533_JD_TYPE_COUNT];
};
static void hp_ev(struct hid_device *hid, struct cmhid *cm, int value)
{
input_report_switch(cm->input_dev, SW_HEADPHONE_INSERT, value);
input_sync(cm->input_dev);
}
static int cmhid_raw_event(struct hid_device *hid, struct hid_report *report,
u8 *data, int len)
{
struct cmhid *cm = hid_get_drvdata(hid);
if (len != CM6533_JD_RAWEV_LEN)
goto out;
if (memcmp(data+CM6533_JD_SFX_OFFSET, ji_sfx, sizeof(ji_sfx)))
goto out;
if (!memcmp(data, ji_out, sizeof(ji_out))) {
hp_ev(hid, cm, 0);
goto out;
}
if (!memcmp(data, ji_in, sizeof(ji_in))) {
hp_ev(hid, cm, 1);
goto out;
}
out:
return 0;
}
static int cmhid_input_configured(struct hid_device *hid,
struct hid_input *hidinput)
{
struct input_dev *input_dev = hidinput->input;
struct cmhid *cm = hid_get_drvdata(hid);
int i;
cm->input_dev = input_dev;
memcpy(cm->switch_map, jack_switch_types, sizeof(cm->switch_map));
input_dev->evbit[0] = BIT(EV_SW);
for (i = 0; i < CM6533_JD_TYPE_COUNT; i++)
input_set_capability(cm->input_dev,
EV_SW, jack_switch_types[i]);
return 0;
}
static int cmhid_input_mapping(struct hid_device *hid,
struct hid_input *hi, struct hid_field *field,
struct hid_usage *usage, unsigned long **bit, int *max)
{
return -1;
}
static int cmhid_probe(struct hid_device *hid, const struct hid_device_id *id)
{
int ret;
struct cmhid *cm;
cm = kzalloc(sizeof(struct cmhid), GFP_KERNEL);
if (!cm) {
ret = -ENOMEM;
goto allocfail;
}
cm->hid = hid;
hid->quirks |= HID_QUIRK_HIDINPUT_FORCE;
hid_set_drvdata(hid, cm);
ret = hid_parse(hid);
if (ret) {
hid_err(hid, "parse failed\n");
goto fail;
}
ret = hid_hw_start(hid, HID_CONNECT_DEFAULT | HID_CONNECT_HIDDEV_FORCE);
if (ret) {
hid_err(hid, "hw start failed\n");
goto fail;
}
return 0;
fail:
kfree(cm);
allocfail:
return ret;
}
static void cmhid_remove(struct hid_device *hid)
{
struct cmhid *cm = hid_get_drvdata(hid);
hid_hw_stop(hid);
kfree(cm);
}
static const struct hid_device_id cmhid_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM6533) },
{ }
};
MODULE_DEVICE_TABLE(hid, cmhid_devices);
static struct hid_driver cmhid_driver = {
.name = "cm6533_jd",
.id_table = cmhid_devices,
.raw_event = cmhid_raw_event,
.input_configured = cmhid_input_configured,
.probe = cmhid_probe,
.remove = cmhid_remove,
.input_mapping = cmhid_input_mapping,
};
module_hid_driver(cmhid_driver);
...@@ -1075,7 +1075,7 @@ static u32 s32ton(__s32 value, unsigned n) ...@@ -1075,7 +1075,7 @@ static u32 s32ton(__s32 value, unsigned n)
* Extract/implement a data field from/to a little endian report (bit array). * Extract/implement a data field from/to a little endian report (bit array).
* *
* Code sort-of follows HID spec: * Code sort-of follows HID spec:
* http://www.usb.org/developers/devclass_docs/HID1_11.pdf * http://www.usb.org/developers/hidpage/HID1_11.pdf
* *
* While the USB HID spec allows unlimited length bit fields in "report * While the USB HID spec allows unlimited length bit fields in "report
* descriptors", most devices never use more than 16 bits. * descriptors", most devices never use more than 16 bits.
...@@ -1083,20 +1083,37 @@ static u32 s32ton(__s32 value, unsigned n) ...@@ -1083,20 +1083,37 @@ static u32 s32ton(__s32 value, unsigned n)
* Search linux-kernel and linux-usb-devel archives for "hid-core extract". * Search linux-kernel and linux-usb-devel archives for "hid-core extract".
*/ */
__u32 hid_field_extract(const struct hid_device *hid, __u8 *report, static u32 __extract(u8 *report, unsigned offset, int n)
unsigned offset, unsigned n)
{ {
u64 x; unsigned int idx = offset / 8;
unsigned int bit_nr = 0;
unsigned int bit_shift = offset % 8;
int bits_to_copy = 8 - bit_shift;
u32 value = 0;
u32 mask = n < 32 ? (1U << n) - 1 : ~0U;
while (n > 0) {
value |= ((u32)report[idx] >> bit_shift) << bit_nr;
n -= bits_to_copy;
bit_nr += bits_to_copy;
bits_to_copy = 8;
bit_shift = 0;
idx++;
}
return value & mask;
}
if (n > 32) u32 hid_field_extract(const struct hid_device *hid, u8 *report,
unsigned offset, unsigned n)
{
if (n > 32) {
hid_warn(hid, "hid_field_extract() called with n (%d) > 32! (%s)\n", hid_warn(hid, "hid_field_extract() called with n (%d) > 32! (%s)\n",
n, current->comm); n, current->comm);
n = 32;
}
report += offset >> 3; /* adjust byte index */ return __extract(report, offset, n);
offset &= 7; /* now only need bit offset into one byte */
x = get_unaligned_le64(report);
x = (x >> offset) & ((1ULL << n) - 1); /* extract bit field */
return (u32) x;
} }
EXPORT_SYMBOL_GPL(hid_field_extract); EXPORT_SYMBOL_GPL(hid_field_extract);
...@@ -1106,31 +1123,56 @@ EXPORT_SYMBOL_GPL(hid_field_extract); ...@@ -1106,31 +1123,56 @@ EXPORT_SYMBOL_GPL(hid_field_extract);
* The data mangled in the bit stream remains in little endian * The data mangled in the bit stream remains in little endian
* order the whole time. It make more sense to talk about * order the whole time. It make more sense to talk about
* endianness of register values by considering a register * endianness of register values by considering a register
* a "cached" copy of the little endiad bit stream. * a "cached" copy of the little endian bit stream.
*/ */
static void implement(const struct hid_device *hid, __u8 *report,
unsigned offset, unsigned n, __u32 value) static void __implement(u8 *report, unsigned offset, int n, u32 value)
{ {
u64 x; unsigned int idx = offset / 8;
u64 m = (1ULL << n) - 1; unsigned int size = offset + n;
unsigned int bit_shift = offset % 8;
int bits_to_set = 8 - bit_shift;
u8 bit_mask = 0xff << bit_shift;
if (n > 32) while (n - bits_to_set >= 0) {
report[idx] &= ~bit_mask;
report[idx] |= value << bit_shift;
value >>= bits_to_set;
n -= bits_to_set;
bits_to_set = 8;
bit_mask = 0xff;
bit_shift = 0;
idx++;
}
/* last nibble */
if (n) {
if (size % 8)
bit_mask &= (1U << (size % 8)) - 1;
report[idx] &= ~bit_mask;
report[idx] |= (value << bit_shift) & bit_mask;
}
}
static void implement(const struct hid_device *hid, u8 *report,
unsigned offset, unsigned n, u32 value)
{
u64 m;
if (n > 32) {
hid_warn(hid, "%s() called with n (%d) > 32! (%s)\n", hid_warn(hid, "%s() called with n (%d) > 32! (%s)\n",
__func__, n, current->comm); __func__, n, current->comm);
n = 32;
}
m = (1ULL << n) - 1;
if (value > m) if (value > m)
hid_warn(hid, "%s() called with too large value %d! (%s)\n", hid_warn(hid, "%s() called with too large value %d! (%s)\n",
__func__, value, current->comm); __func__, value, current->comm);
WARN_ON(value > m); WARN_ON(value > m);
value &= m; value &= m;
report += offset >> 3; __implement(report, offset, n, value);
offset &= 7;
x = get_unaligned_le64(report);
x &= ~(m << offset);
x |= ((u64)value) << offset;
put_unaligned_le64(x, report);
} }
/* /*
...@@ -1251,6 +1293,7 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, ...@@ -1251,6 +1293,7 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field,
/* Ignore report if ErrorRollOver */ /* Ignore report if ErrorRollOver */
if (!(field->flags & HID_MAIN_ITEM_VARIABLE) && if (!(field->flags & HID_MAIN_ITEM_VARIABLE) &&
value[n] >= min && value[n] <= max && value[n] >= min && value[n] <= max &&
value[n] - min < field->maxusage &&
field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1) field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
goto exit; goto exit;
} }
...@@ -1263,11 +1306,13 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, ...@@ -1263,11 +1306,13 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field,
} }
if (field->value[n] >= min && field->value[n] <= max if (field->value[n] >= min && field->value[n] <= max
&& field->value[n] - min < field->maxusage
&& field->usage[field->value[n] - min].hid && field->usage[field->value[n] - min].hid
&& search(value, field->value[n], count)) && search(value, field->value[n], count))
hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt); hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt);
if (value[n] >= min && value[n] <= max if (value[n] >= min && value[n] <= max
&& value[n] - min < field->maxusage
&& field->usage[value[n] - min].hid && field->usage[value[n] - min].hid
&& search(field->value, value[n], count)) && search(field->value, value[n], count))
hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt); hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt);
...@@ -1891,6 +1936,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1891,6 +1936,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DUAL_ACTION) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
...@@ -1919,6 +1965,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1919,6 +1965,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_KEYBOARD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K_JP) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K_JP) },
...@@ -2003,6 +2050,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -2003,6 +2050,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_SRWS1) }, { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_SRWS1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THINGM, USB_DEVICE_ID_BLINK1) }, { HID_USB_DEVICE(USB_VENDOR_ID_THINGM, USB_DEVICE_ID_BLINK1) },
...@@ -2051,6 +2099,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -2051,6 +2099,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE2) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLADE_14) }, { HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLADE_14) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM6533) },
{ } { }
}; };
...@@ -2615,9 +2664,10 @@ int hid_add_device(struct hid_device *hdev) ...@@ -2615,9 +2664,10 @@ int hid_add_device(struct hid_device *hdev)
/* /*
* Scan generic devices for group information * Scan generic devices for group information
*/ */
if (hid_ignore_special_drivers || if (hid_ignore_special_drivers) {
(!hdev->group && hdev->group = HID_GROUP_GENERIC;
!hid_match_id(hdev, hid_have_special_driver))) { } else if (!hdev->group &&
!hid_match_id(hdev, hid_have_special_driver)) {
ret = hid_scan_report(hdev); ret = hid_scan_report(hdev);
if (ret) if (ret)
hid_warn(hdev, "bad device descriptor (%d)\n", ret); hid_warn(hdev, "bad device descriptor (%d)\n", ret);
......
...@@ -595,6 +595,9 @@ static int corsair_input_mapping(struct hid_device *dev, ...@@ -595,6 +595,9 @@ static int corsair_input_mapping(struct hid_device *dev,
{ {
int gkey; int gkey;
if ((usage->hid & HID_USAGE_PAGE) != HID_UP_KEYBOARD)
return 0;
gkey = corsair_usage_to_gkey(usage->hid & HID_USAGE); gkey = corsair_usage_to_gkey(usage->hid & HID_USAGE);
if (gkey != 0) { if (gkey != 0) {
hid_map_usage_clear(input, usage, bit, max, EV_KEY, hid_map_usage_clear(input, usage, bit, max, EV_KEY,
......
...@@ -151,7 +151,7 @@ static inline int drff_init(struct hid_device *hid) ...@@ -151,7 +151,7 @@ static inline int drff_init(struct hid_device *hid)
* descriptor. In any case, it's a wonder it works on Windows. * descriptor. In any case, it's a wonder it works on Windows.
* *
* Usage Page (Desktop), ; Generic desktop controls (01h) * Usage Page (Desktop), ; Generic desktop controls (01h)
* Usage (Joystik), ; Joystik (04h, application collection) * Usage (Joystick), ; Joystick (04h, application collection)
* Collection (Application), * Collection (Application),
* Collection (Logical), * Collection (Logical),
* Report Size (8), * Report Size (8),
...@@ -207,7 +207,7 @@ static inline int drff_init(struct hid_device *hid) ...@@ -207,7 +207,7 @@ static inline int drff_init(struct hid_device *hid)
/* Fixed report descriptor for PID 0x011 joystick */ /* Fixed report descriptor for PID 0x011 joystick */
static __u8 pid0011_rdesc_fixed[] = { static __u8 pid0011_rdesc_fixed[] = {
0x05, 0x01, /* Usage Page (Desktop), */ 0x05, 0x01, /* Usage Page (Desktop), */
0x09, 0x04, /* Usage (Joystik), */ 0x09, 0x04, /* Usage (Joystick), */
0xA1, 0x01, /* Collection (Application), */ 0xA1, 0x01, /* Collection (Application), */
0xA1, 0x02, /* Collection (Logical), */ 0xA1, 0x02, /* Collection (Logical), */
0x14, /* Logical Minimum (0), */ 0x14, /* Logical Minimum (0), */
......
...@@ -61,6 +61,9 @@ ...@@ -61,6 +61,9 @@
#define USB_VENDOR_ID_AIREN 0x1a2c #define USB_VENDOR_ID_AIREN 0x1a2c
#define USB_DEVICE_ID_AIREN_SLIMPLUS 0x0002 #define USB_DEVICE_ID_AIREN_SLIMPLUS 0x0002
#define USB_VENDOR_ID_AKAI 0x2011
#define USB_DEVICE_ID_AKAI_MPKMINI2 0x0715
#define USB_VENDOR_ID_ALCOR 0x058f #define USB_VENDOR_ID_ALCOR 0x058f
#define USB_DEVICE_ID_ALCOR_USBRS232 0x9720 #define USB_DEVICE_ID_ALCOR_USBRS232 0x9720
...@@ -246,6 +249,7 @@ ...@@ -246,6 +249,7 @@
#define USB_VENDOR_ID_CMEDIA 0x0d8c #define USB_VENDOR_ID_CMEDIA 0x0d8c
#define USB_DEVICE_ID_CM109 0x000e #define USB_DEVICE_ID_CM109 0x000e
#define USB_DEVICE_ID_CM6533 0x0022
#define USB_VENDOR_ID_CODEMERCS 0x07c0 #define USB_VENDOR_ID_CODEMERCS 0x07c0
#define USB_DEVICE_ID_CODEMERCS_IOW_FIRST 0x1500 #define USB_DEVICE_ID_CODEMERCS_IOW_FIRST 0x1500
...@@ -680,6 +684,7 @@ ...@@ -680,6 +684,7 @@
#define USB_DEVICE_ID_MS_NE7K 0x071d #define USB_DEVICE_ID_MS_NE7K 0x071d
#define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K 0x0730 #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K 0x0730
#define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500 0x076c #define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500 0x076c
#define USB_DEVICE_ID_MS_COMFORT_KEYBOARD 0x00e3
#define USB_DEVICE_ID_MS_SURFACE_PRO_2 0x0799 #define USB_DEVICE_ID_MS_SURFACE_PRO_2 0x0799
#define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 #define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7
#define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 #define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9
...@@ -800,6 +805,7 @@ ...@@ -800,6 +805,7 @@
#define USB_VENDOR_ID_QUANTA 0x0408 #define USB_VENDOR_ID_QUANTA 0x0408
#define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH 0x3000 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH 0x3000
#define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001 0x3001 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001 0x3001
#define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003 0x3003
#define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008 0x3008 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008 0x3008
#define USB_VENDOR_ID_RAZER 0x1532 #define USB_VENDOR_ID_RAZER 0x1532
...@@ -839,6 +845,7 @@ ...@@ -839,6 +845,7 @@
#define USB_VENDOR_ID_SEMICO 0x1a2c #define USB_VENDOR_ID_SEMICO 0x1a2c
#define USB_DEVICE_ID_SEMICO_USB_KEYKOARD 0x0023 #define USB_DEVICE_ID_SEMICO_USB_KEYKOARD 0x0023
#define USB_DEVICE_ID_SEMICO_USB_KEYKOARD2 0x0027
#define USB_VENDOR_ID_SENNHEISER 0x1395 #define USB_VENDOR_ID_SENNHEISER 0x1395
#define USB_DEVICE_ID_SENNHEISER_BTD500USB 0x002c #define USB_DEVICE_ID_SENNHEISER_BTD500USB 0x002c
...@@ -872,6 +879,9 @@ ...@@ -872,6 +879,9 @@
#define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002 #define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002
#define USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER 0x1000 #define USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER 0x1000
#define USB_VENDOR_ID_SINO_LITE 0x1345
#define USB_DEVICE_ID_SINO_LITE_CONTROLLER 0x3008
#define USB_VENDOR_ID_SOUNDGRAPH 0x15c2 #define USB_VENDOR_ID_SOUNDGRAPH 0x15c2
#define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034 #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034
#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST 0x0046 #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST 0x0046
...@@ -1047,7 +1057,7 @@ ...@@ -1047,7 +1057,7 @@
#define USB_DEVICE_ID_RI_KA_WEBMAIL 0x1320 /* Webmail Notifier */ #define USB_DEVICE_ID_RI_KA_WEBMAIL 0x1320 /* Webmail Notifier */
#define USB_VENDOR_ID_MULTIPLE_1781 0x1781 #define USB_VENDOR_ID_MULTIPLE_1781 0x1781
#define USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD 0x0a8d #define USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD 0x0a9d
#define USB_VENDOR_ID_DRACAL_RAPHNET 0x289b #define USB_VENDOR_ID_DRACAL_RAPHNET 0x289b
#define USB_DEVICE_ID_RAPHNET_2NES2SNES 0x0002 #define USB_DEVICE_ID_RAPHNET_2NES2SNES 0x0002
......
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
*/ */
static __u8 df_rdesc_fixed[] = { static __u8 df_rdesc_fixed[] = {
0x05, 0x01, /* Usage Page (Desktop), */ 0x05, 0x01, /* Usage Page (Desktop), */
0x09, 0x04, /* Usage (Joystik), */ 0x09, 0x04, /* Usage (Joystick), */
0xA1, 0x01, /* Collection (Application), */ 0xA1, 0x01, /* Collection (Application), */
0xA1, 0x02, /* Collection (Logical), */ 0xA1, 0x02, /* Collection (Logical), */
0x95, 0x01, /* Report Count (1), */ 0x95, 0x01, /* Report Count (1), */
...@@ -127,7 +127,7 @@ static __u8 df_rdesc_fixed[] = { ...@@ -127,7 +127,7 @@ static __u8 df_rdesc_fixed[] = {
static __u8 dfp_rdesc_fixed[] = { static __u8 dfp_rdesc_fixed[] = {
0x05, 0x01, /* Usage Page (Desktop), */ 0x05, 0x01, /* Usage Page (Desktop), */
0x09, 0x04, /* Usage (Joystik), */ 0x09, 0x04, /* Usage (Joystick), */
0xA1, 0x01, /* Collection (Application), */ 0xA1, 0x01, /* Collection (Application), */
0xA1, 0x02, /* Collection (Logical), */ 0xA1, 0x02, /* Collection (Logical), */
0x95, 0x01, /* Report Count (1), */ 0x95, 0x01, /* Report Count (1), */
...@@ -175,7 +175,7 @@ static __u8 dfp_rdesc_fixed[] = { ...@@ -175,7 +175,7 @@ static __u8 dfp_rdesc_fixed[] = {
static __u8 fv_rdesc_fixed[] = { static __u8 fv_rdesc_fixed[] = {
0x05, 0x01, /* Usage Page (Desktop), */ 0x05, 0x01, /* Usage Page (Desktop), */
0x09, 0x04, /* Usage (Joystik), */ 0x09, 0x04, /* Usage (Joystick), */
0xA1, 0x01, /* Collection (Application), */ 0xA1, 0x01, /* Collection (Application), */
0xA1, 0x02, /* Collection (Logical), */ 0xA1, 0x02, /* Collection (Logical), */
0x95, 0x01, /* Report Count (1), */ 0x95, 0x01, /* Report Count (1), */
...@@ -242,7 +242,7 @@ static __u8 fv_rdesc_fixed[] = { ...@@ -242,7 +242,7 @@ static __u8 fv_rdesc_fixed[] = {
static __u8 momo_rdesc_fixed[] = { static __u8 momo_rdesc_fixed[] = {
0x05, 0x01, /* Usage Page (Desktop), */ 0x05, 0x01, /* Usage Page (Desktop), */
0x09, 0x04, /* Usage (Joystik), */ 0x09, 0x04, /* Usage (Joystick), */
0xA1, 0x01, /* Collection (Application), */ 0xA1, 0x01, /* Collection (Application), */
0xA1, 0x02, /* Collection (Logical), */ 0xA1, 0x02, /* Collection (Logical), */
0x95, 0x01, /* Report Count (1), */ 0x95, 0x01, /* Report Count (1), */
...@@ -288,7 +288,7 @@ static __u8 momo_rdesc_fixed[] = { ...@@ -288,7 +288,7 @@ static __u8 momo_rdesc_fixed[] = {
static __u8 momo2_rdesc_fixed[] = { static __u8 momo2_rdesc_fixed[] = {
0x05, 0x01, /* Usage Page (Desktop), */ 0x05, 0x01, /* Usage Page (Desktop), */
0x09, 0x04, /* Usage (Joystik), */ 0x09, 0x04, /* Usage (Joystick), */
0xA1, 0x01, /* Collection (Application), */ 0xA1, 0x01, /* Collection (Application), */
0xA1, 0x02, /* Collection (Logical), */ 0xA1, 0x02, /* Collection (Logical), */
0x95, 0x01, /* Report Count (1), */ 0x95, 0x01, /* Report Count (1), */
......
This diff is collapsed.
...@@ -286,6 +286,8 @@ static const struct hid_device_id ms_devices[] = { ...@@ -286,6 +286,8 @@ static const struct hid_device_id ms_devices[] = {
.driver_data = MS_HIDINPUT }, .driver_data = MS_HIDINPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER), { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER),
.driver_data = MS_HIDINPUT }, .driver_data = MS_HIDINPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_KEYBOARD),
.driver_data = MS_ERGONOMY},
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT), { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT),
.driver_data = MS_PRESENTER }, .driver_data = MS_PRESENTER },
......
...@@ -396,6 +396,11 @@ static void mt_feature_mapping(struct hid_device *hdev, ...@@ -396,6 +396,11 @@ static void mt_feature_mapping(struct hid_device *hdev,
td->is_buttonpad = true; td->is_buttonpad = true;
break; break;
case 0xff0000c5:
/* Retrieve the Win8 blob once to enable some devices */
if (usage->usage_index == 0)
mt_get_feature(hdev, field->report);
break;
} }
} }
...@@ -1133,6 +1138,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -1133,6 +1138,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
return ret; return ret;
ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group); ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group);
if (ret)
dev_warn(&hdev->dev, "Cannot allocate sysfs group for %s\n",
hdev->name);
mt_set_maxcontacts(hdev); mt_set_maxcontacts(hdev);
mt_set_input_mode(hdev); mt_set_input_mode(hdev);
...@@ -1145,8 +1153,30 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -1145,8 +1153,30 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static void mt_release_contacts(struct hid_device *hid)
{
struct hid_input *hidinput;
list_for_each_entry(hidinput, &hid->inputs, list) {
struct input_dev *input_dev = hidinput->input;
struct input_mt *mt = input_dev->mt;
int i;
if (mt) {
for (i = 0; i < mt->num_slots; i++) {
input_mt_slot(input_dev, i);
input_mt_report_slot_state(input_dev,
MT_TOOL_FINGER,
false);
}
input_sync(input_dev);
}
}
}
static int mt_reset_resume(struct hid_device *hdev) static int mt_reset_resume(struct hid_device *hdev)
{ {
mt_release_contacts(hdev);
mt_set_maxcontacts(hdev); mt_set_maxcontacts(hdev);
mt_set_input_mode(hdev); mt_set_input_mode(hdev);
return 0; return 0;
......
...@@ -23,8 +23,12 @@ static int penmount_input_mapping(struct hid_device *hdev, ...@@ -23,8 +23,12 @@ static int penmount_input_mapping(struct hid_device *hdev,
struct hid_usage *usage, unsigned long **bit, int *max) struct hid_usage *usage, unsigned long **bit, int *max)
{ {
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) { if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
if (((usage->hid - 1) & HID_USAGE) == 0) {
hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
return 1; return 1;
} else {
return -1;
}
} }
return 0; return 0;
......
...@@ -594,6 +594,9 @@ static int rmi_suspend(struct hid_device *hdev, pm_message_t message) ...@@ -594,6 +594,9 @@ static int rmi_suspend(struct hid_device *hdev, pm_message_t message)
int ret; int ret;
u8 buf[RMI_F11_CTRL_REG_COUNT]; u8 buf[RMI_F11_CTRL_REG_COUNT];
if (!(data->device_flags & RMI_DEVICE))
return 0;
ret = rmi_read_block(hdev, data->f11.control_base_addr, buf, ret = rmi_read_block(hdev, data->f11.control_base_addr, buf,
RMI_F11_CTRL_REG_COUNT); RMI_F11_CTRL_REG_COUNT);
if (ret) if (ret)
...@@ -613,6 +616,9 @@ static int rmi_post_reset(struct hid_device *hdev) ...@@ -613,6 +616,9 @@ static int rmi_post_reset(struct hid_device *hdev)
struct rmi_data *data = hid_get_drvdata(hdev); struct rmi_data *data = hid_get_drvdata(hdev);
int ret; int ret;
if (!(data->device_flags & RMI_DEVICE))
return 0;
ret = rmi_reset_attn_mode(hdev); ret = rmi_reset_attn_mode(hdev);
if (ret) { if (ret) {
hid_err(hdev, "can not set rmi mode\n"); hid_err(hdev, "can not set rmi mode\n");
...@@ -640,6 +646,11 @@ static int rmi_post_reset(struct hid_device *hdev) ...@@ -640,6 +646,11 @@ static int rmi_post_reset(struct hid_device *hdev)
static int rmi_post_resume(struct hid_device *hdev) static int rmi_post_resume(struct hid_device *hdev)
{ {
struct rmi_data *data = hid_get_drvdata(hdev);
if (!(data->device_flags & RMI_DEVICE))
return 0;
return rmi_reset_attn_mode(hdev); return rmi_reset_attn_mode(hdev);
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
......
This diff is collapsed.
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/workqueue.h>
#include "hid-ids.h" #include "hid-ids.h"
...@@ -56,7 +55,6 @@ struct thingm_rgb { ...@@ -56,7 +55,6 @@ struct thingm_rgb {
struct thingm_led red; struct thingm_led red;
struct thingm_led green; struct thingm_led green;
struct thingm_led blue; struct thingm_led blue;
struct work_struct work;
u8 num; u8 num;
}; };
...@@ -79,9 +77,13 @@ static int thingm_send(struct thingm_device *tdev, u8 buf[REPORT_SIZE]) ...@@ -79,9 +77,13 @@ static int thingm_send(struct thingm_device *tdev, u8 buf[REPORT_SIZE])
buf[0], buf[1], buf[2], buf[3], buf[4], buf[0], buf[1], buf[2], buf[3], buf[4],
buf[5], buf[6], buf[7], buf[8]); buf[5], buf[6], buf[7], buf[8]);
mutex_lock(&tdev->lock);
ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE, ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE,
HID_FEATURE_REPORT, HID_REQ_SET_REPORT); HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
mutex_unlock(&tdev->lock);
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
} }
...@@ -89,16 +91,31 @@ static int thingm_recv(struct thingm_device *tdev, u8 buf[REPORT_SIZE]) ...@@ -89,16 +91,31 @@ static int thingm_recv(struct thingm_device *tdev, u8 buf[REPORT_SIZE])
{ {
int ret; int ret;
/*
* A read consists of two operations: sending the read command
* and the actual read from the device. Use the mutex to protect
* the full sequence of both operations.
*/
mutex_lock(&tdev->lock);
ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE,
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
if (ret < 0)
goto err;
ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE, ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE,
HID_FEATURE_REPORT, HID_REQ_GET_REPORT); HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
if (ret < 0) if (ret < 0)
return ret; goto err;
ret = 0;
hid_dbg(tdev->hdev, "<- %d %c %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n", hid_dbg(tdev->hdev, "<- %d %c %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n",
buf[0], buf[1], buf[2], buf[3], buf[4], buf[0], buf[1], buf[2], buf[3], buf[4],
buf[5], buf[6], buf[7], buf[8]); buf[5], buf[6], buf[7], buf[8]);
err:
return 0; mutex_unlock(&tdev->lock);
return ret;
} }
static int thingm_version(struct thingm_device *tdev) static int thingm_version(struct thingm_device *tdev)
...@@ -106,10 +123,6 @@ static int thingm_version(struct thingm_device *tdev) ...@@ -106,10 +123,6 @@ static int thingm_version(struct thingm_device *tdev)
u8 buf[REPORT_SIZE] = { REPORT_ID, 'v', 0, 0, 0, 0, 0, 0, 0 }; u8 buf[REPORT_SIZE] = { REPORT_ID, 'v', 0, 0, 0, 0, 0, 0, 0 };
int err; int err;
err = thingm_send(tdev, buf);
if (err)
return err;
err = thingm_recv(tdev, buf); err = thingm_recv(tdev, buf);
if (err) if (err)
return err; return err;
...@@ -131,25 +144,17 @@ static int thingm_write_color(struct thingm_rgb *rgb) ...@@ -131,25 +144,17 @@ static int thingm_write_color(struct thingm_rgb *rgb)
return thingm_send(rgb->tdev, buf); return thingm_send(rgb->tdev, buf);
} }
static void thingm_work(struct work_struct *work) static int thingm_led_set(struct led_classdev *ldev,
{
struct thingm_rgb *rgb = container_of(work, struct thingm_rgb, work);
mutex_lock(&rgb->tdev->lock);
if (thingm_write_color(rgb))
hid_err(rgb->tdev->hdev, "failed to write color\n");
mutex_unlock(&rgb->tdev->lock);
}
static void thingm_led_set(struct led_classdev *ldev,
enum led_brightness brightness) enum led_brightness brightness)
{ {
struct thingm_led *led = container_of(ldev, struct thingm_led, ldev); struct thingm_led *led = container_of(ldev, struct thingm_led, ldev);
int ret;
ret = thingm_write_color(led->rgb);
if (ret)
hid_err(led->rgb->tdev->hdev, "failed to write color\n");
/* the ledclass has already stored the brightness value */ return ret;
schedule_work(&led->rgb->work);
} }
static int thingm_init_rgb(struct thingm_rgb *rgb) static int thingm_init_rgb(struct thingm_rgb *rgb)
...@@ -162,10 +167,11 @@ static int thingm_init_rgb(struct thingm_rgb *rgb) ...@@ -162,10 +167,11 @@ static int thingm_init_rgb(struct thingm_rgb *rgb)
"thingm%d:red:led%d", minor, rgb->num); "thingm%d:red:led%d", minor, rgb->num);
rgb->red.ldev.name = rgb->red.name; rgb->red.ldev.name = rgb->red.name;
rgb->red.ldev.max_brightness = 255; rgb->red.ldev.max_brightness = 255;
rgb->red.ldev.brightness_set = thingm_led_set; rgb->red.ldev.brightness_set_blocking = thingm_led_set;
rgb->red.rgb = rgb; rgb->red.rgb = rgb;
err = led_classdev_register(&rgb->tdev->hdev->dev, &rgb->red.ldev); err = devm_led_classdev_register(&rgb->tdev->hdev->dev,
&rgb->red.ldev);
if (err) if (err)
return err; return err;
...@@ -174,46 +180,27 @@ static int thingm_init_rgb(struct thingm_rgb *rgb) ...@@ -174,46 +180,27 @@ static int thingm_init_rgb(struct thingm_rgb *rgb)
"thingm%d:green:led%d", minor, rgb->num); "thingm%d:green:led%d", minor, rgb->num);
rgb->green.ldev.name = rgb->green.name; rgb->green.ldev.name = rgb->green.name;
rgb->green.ldev.max_brightness = 255; rgb->green.ldev.max_brightness = 255;
rgb->green.ldev.brightness_set = thingm_led_set; rgb->green.ldev.brightness_set_blocking = thingm_led_set;
rgb->green.rgb = rgb; rgb->green.rgb = rgb;
err = led_classdev_register(&rgb->tdev->hdev->dev, &rgb->green.ldev); err = devm_led_classdev_register(&rgb->tdev->hdev->dev,
&rgb->green.ldev);
if (err) if (err)
goto unregister_red; return err;
/* Register the blue diode */ /* Register the blue diode */
snprintf(rgb->blue.name, sizeof(rgb->blue.name), snprintf(rgb->blue.name, sizeof(rgb->blue.name),
"thingm%d:blue:led%d", minor, rgb->num); "thingm%d:blue:led%d", minor, rgb->num);
rgb->blue.ldev.name = rgb->blue.name; rgb->blue.ldev.name = rgb->blue.name;
rgb->blue.ldev.max_brightness = 255; rgb->blue.ldev.max_brightness = 255;
rgb->blue.ldev.brightness_set = thingm_led_set; rgb->blue.ldev.brightness_set_blocking = thingm_led_set;
rgb->blue.rgb = rgb; rgb->blue.rgb = rgb;
err = led_classdev_register(&rgb->tdev->hdev->dev, &rgb->blue.ldev); err = devm_led_classdev_register(&rgb->tdev->hdev->dev,
if (err) &rgb->blue.ldev);
goto unregister_green;
INIT_WORK(&rgb->work, thingm_work);
return 0;
unregister_green:
led_classdev_unregister(&rgb->green.ldev);
unregister_red:
led_classdev_unregister(&rgb->red.ldev);
return err; return err;
} }
static void thingm_remove_rgb(struct thingm_rgb *rgb)
{
led_classdev_unregister(&rgb->red.ldev);
led_classdev_unregister(&rgb->green.ldev);
led_classdev_unregister(&rgb->blue.ldev);
flush_work(&rgb->work);
}
static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id) static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id)
{ {
struct thingm_device *tdev; struct thingm_device *tdev;
...@@ -229,17 +216,13 @@ static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -229,17 +216,13 @@ static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id)
err = hid_parse(hdev); err = hid_parse(hdev);
if (err) if (err)
goto error; return err;
err = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
if (err)
goto error;
mutex_init(&tdev->lock); mutex_init(&tdev->lock);
err = thingm_version(tdev); err = thingm_version(tdev);
if (err) if (err)
goto stop; return err;
hid_dbg(hdev, "firmware version: %c.%c\n", hid_dbg(hdev, "firmware version: %c.%c\n",
tdev->version.major, tdev->version.minor); tdev->version.major, tdev->version.minor);
...@@ -250,17 +233,18 @@ static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -250,17 +233,18 @@ static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (!tdev->fwinfo) { if (!tdev->fwinfo) {
hid_err(hdev, "unsupported firmware %c\n", tdev->version.major); hid_err(hdev, "unsupported firmware %c\n", tdev->version.major);
err = -ENODEV; return -ENODEV;
goto stop;
} }
tdev->rgb = devm_kzalloc(&hdev->dev, tdev->rgb = devm_kzalloc(&hdev->dev,
sizeof(struct thingm_rgb) * tdev->fwinfo->numrgb, sizeof(struct thingm_rgb) * tdev->fwinfo->numrgb,
GFP_KERNEL); GFP_KERNEL);
if (!tdev->rgb) { if (!tdev->rgb)
err = -ENOMEM; return -ENOMEM;
goto stop;
} err = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
if (err)
return err;
for (i = 0; i < tdev->fwinfo->numrgb; ++i) { for (i = 0; i < tdev->fwinfo->numrgb; ++i) {
struct thingm_rgb *rgb = tdev->rgb + i; struct thingm_rgb *rgb = tdev->rgb + i;
...@@ -269,28 +253,12 @@ static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -269,28 +253,12 @@ static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id)
rgb->num = tdev->fwinfo->first + i; rgb->num = tdev->fwinfo->first + i;
err = thingm_init_rgb(rgb); err = thingm_init_rgb(rgb);
if (err) { if (err) {
while (--i >= 0) hid_hw_stop(hdev);
thingm_remove_rgb(tdev->rgb + i); return err;
goto stop;
} }
} }
return 0; return 0;
stop:
hid_hw_stop(hdev);
error:
return err;
}
static void thingm_remove(struct hid_device *hdev)
{
struct thingm_device *tdev = hid_get_drvdata(hdev);
int i;
hid_hw_stop(hdev);
for (i = 0; i < tdev->fwinfo->numrgb; ++i)
thingm_remove_rgb(tdev->rgb + i);
} }
static const struct hid_device_id thingm_table[] = { static const struct hid_device_id thingm_table[] = {
...@@ -302,7 +270,6 @@ MODULE_DEVICE_TABLE(hid, thingm_table); ...@@ -302,7 +270,6 @@ MODULE_DEVICE_TABLE(hid, thingm_table);
static struct hid_driver thingm_driver = { static struct hid_driver thingm_driver = {
.name = "thingm", .name = "thingm",
.probe = thingm_probe, .probe = thingm_probe,
.remove = thingm_remove,
.id_table = thingm_table, .id_table = thingm_table,
}; };
......
...@@ -283,17 +283,21 @@ static int i2c_hid_set_or_send_report(struct i2c_client *client, u8 reportType, ...@@ -283,17 +283,21 @@ static int i2c_hid_set_or_send_report(struct i2c_client *client, u8 reportType,
u16 dataRegister = le16_to_cpu(ihid->hdesc.wDataRegister); u16 dataRegister = le16_to_cpu(ihid->hdesc.wDataRegister);
u16 outputRegister = le16_to_cpu(ihid->hdesc.wOutputRegister); u16 outputRegister = le16_to_cpu(ihid->hdesc.wOutputRegister);
u16 maxOutputLength = le16_to_cpu(ihid->hdesc.wMaxOutputLength); u16 maxOutputLength = le16_to_cpu(ihid->hdesc.wMaxOutputLength);
u16 size;
int args_len;
int index = 0;
i2c_hid_dbg(ihid, "%s\n", __func__);
if (data_len > ihid->bufsize)
return -EINVAL;
/* hid_hw_* already checked that data_len < HID_MAX_BUFFER_SIZE */ size = 2 /* size */ +
u16 size = 2 /* size */ +
(reportID ? 1 : 0) /* reportID */ + (reportID ? 1 : 0) /* reportID */ +
data_len /* buf */; data_len /* buf */;
int args_len = (reportID >= 0x0F ? 1 : 0) /* optional third byte */ + args_len = (reportID >= 0x0F ? 1 : 0) /* optional third byte */ +
2 /* dataRegister */ + 2 /* dataRegister */ +
size /* args */; size /* args */;
int index = 0;
i2c_hid_dbg(ihid, "%s\n", __func__);
if (!use_data && maxOutputLength == 0) if (!use_data && maxOutputLength == 0)
return -ENOSYS; return -ENOSYS;
...@@ -1108,13 +1112,30 @@ static int i2c_hid_suspend(struct device *dev) ...@@ -1108,13 +1112,30 @@ static int i2c_hid_suspend(struct device *dev)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct i2c_hid *ihid = i2c_get_clientdata(client); struct i2c_hid *ihid = i2c_get_clientdata(client);
struct hid_device *hid = ihid->hid; struct hid_device *hid = ihid->hid;
int ret = 0; int ret;
int wake_status; int wake_status;
if (hid->driver && hid->driver->suspend) if (hid->driver && hid->driver->suspend) {
/*
* Wake up the device so that IO issues in
* HID driver's suspend code can succeed.
*/
ret = pm_runtime_resume(dev);
if (ret < 0)
return ret;
ret = hid->driver->suspend(hid, PMSG_SUSPEND); ret = hid->driver->suspend(hid, PMSG_SUSPEND);
if (ret < 0)
return ret;
}
if (!pm_runtime_suspended(dev)) {
/* Save some power */
i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
disable_irq(ihid->irq); disable_irq(ihid->irq);
}
if (device_may_wakeup(&client->dev)) { if (device_may_wakeup(&client->dev)) {
wake_status = enable_irq_wake(ihid->irq); wake_status = enable_irq_wake(ihid->irq);
if (!wake_status) if (!wake_status)
...@@ -1124,10 +1145,7 @@ static int i2c_hid_suspend(struct device *dev) ...@@ -1124,10 +1145,7 @@ static int i2c_hid_suspend(struct device *dev)
wake_status); wake_status);
} }
/* Save some power */ return 0;
i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
return ret;
} }
static int i2c_hid_resume(struct device *dev) static int i2c_hid_resume(struct device *dev)
...@@ -1138,11 +1156,6 @@ static int i2c_hid_resume(struct device *dev) ...@@ -1138,11 +1156,6 @@ static int i2c_hid_resume(struct device *dev)
struct hid_device *hid = ihid->hid; struct hid_device *hid = ihid->hid;
int wake_status; int wake_status;
enable_irq(ihid->irq);
ret = i2c_hid_hwreset(client);
if (ret)
return ret;
if (device_may_wakeup(&client->dev) && ihid->irq_wake_enabled) { if (device_may_wakeup(&client->dev) && ihid->irq_wake_enabled) {
wake_status = disable_irq_wake(ihid->irq); wake_status = disable_irq_wake(ihid->irq);
if (!wake_status) if (!wake_status)
...@@ -1152,6 +1165,16 @@ static int i2c_hid_resume(struct device *dev) ...@@ -1152,6 +1165,16 @@ static int i2c_hid_resume(struct device *dev)
wake_status); wake_status);
} }
/* We'll resume to full power */
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
enable_irq(ihid->irq);
ret = i2c_hid_hwreset(client);
if (ret)
return ret;
if (hid->driver && hid->driver->reset_resume) { if (hid->driver && hid->driver->reset_resume) {
ret = hid->driver->reset_resume(hid); ret = hid->driver->reset_resume(hid);
return ret; return ret;
...@@ -1191,6 +1214,7 @@ static const struct dev_pm_ops i2c_hid_pm = { ...@@ -1191,6 +1214,7 @@ static const struct dev_pm_ops i2c_hid_pm = {
static const struct i2c_device_id i2c_hid_id_table[] = { static const struct i2c_device_id i2c_hid_id_table[] = {
{ "hid", 0 }, { "hid", 0 },
{ "hid-over-i2c", 0 },
{ }, { },
}; };
MODULE_DEVICE_TABLE(i2c, i2c_hid_id_table); MODULE_DEVICE_TABLE(i2c, i2c_hid_id_table);
......
...@@ -55,6 +55,7 @@ static const struct hid_blacklist { ...@@ -55,6 +55,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_AKAI, USB_DEVICE_ID_AKAI_MPKMINI2, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
...@@ -106,6 +107,7 @@ static const struct hid_blacklist { ...@@ -106,6 +107,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4D22, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4D22, HID_QUIRK_ALWAYS_POLL },
{ USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET }, { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET }, { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET },
...@@ -140,6 +142,7 @@ static const struct hid_blacklist { ...@@ -140,6 +142,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD2, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD, HID_QUIRK_NO_INIT_REPORTS },
......
This diff is collapsed.
...@@ -575,33 +575,16 @@ static int wacom_intuos_pad(struct wacom_wac *wacom) ...@@ -575,33 +575,16 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
return 1; return 1;
} }
static int wacom_intuos_inout(struct wacom_wac *wacom) static int wacom_intuos_get_tool_type(int tool_id)
{ {
struct wacom_features *features = &wacom->features; int tool_type;
unsigned char *data = wacom->data;
struct input_dev *input = wacom->pen_input;
int idx = 0;
/* tool number */
if (features->type == INTUOS)
idx = data[1] & 0x01;
/* Enter report */
if ((data[1] & 0xfc) == 0xc0) {
/* serial number of the tool */
wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
(data[4] << 20) + (data[5] << 12) +
(data[6] << 4) + (data[7] >> 4);
wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) | switch (tool_id) {
((data[7] & 0x0f) << 20) | ((data[8] & 0xf0) << 12);
switch (wacom->id[idx]) {
case 0x812: /* Inking pen */ case 0x812: /* Inking pen */
case 0x801: /* Intuos3 Inking pen */ case 0x801: /* Intuos3 Inking pen */
case 0x120802: /* Intuos4/5 Inking Pen */ case 0x120802: /* Intuos4/5 Inking Pen */
case 0x012: case 0x012:
wacom->tool[idx] = BTN_TOOL_PENCIL; tool_type = BTN_TOOL_PENCIL;
break; break;
case 0x822: /* Pen */ case 0x822: /* Pen */
...@@ -612,18 +595,19 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) ...@@ -612,18 +595,19 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
case 0x885: /* Intuos3 Marker Pen */ case 0x885: /* Intuos3 Marker Pen */
case 0x802: /* Intuos4/5 13HD/24HD General Pen */ case 0x802: /* Intuos4/5 13HD/24HD General Pen */
case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */ case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */
case 0x8e2: /* IntuosHT2 pen */
case 0x022: case 0x022:
case 0x100804: /* Intuos4/5 13HD/24HD Art Pen */ case 0x100804: /* Intuos4/5 13HD/24HD Art Pen */
case 0x140802: /* Intuos4/5 13HD/24HD Classic Pen */ case 0x140802: /* Intuos4/5 13HD/24HD Classic Pen */
case 0x160802: /* Cintiq 13HD Pro Pen */ case 0x160802: /* Cintiq 13HD Pro Pen */
case 0x180802: /* DTH2242 Pen */ case 0x180802: /* DTH2242 Pen */
case 0x100802: /* Intuos4/5 13HD/24HD General Pen */ case 0x100802: /* Intuos4/5 13HD/24HD General Pen */
wacom->tool[idx] = BTN_TOOL_PEN; tool_type = BTN_TOOL_PEN;
break; break;
case 0x832: /* Stroke pen */ case 0x832: /* Stroke pen */
case 0x032: case 0x032:
wacom->tool[idx] = BTN_TOOL_BRUSH; tool_type = BTN_TOOL_BRUSH;
break; break;
case 0x007: /* Mouse 4D and 2D */ case 0x007: /* Mouse 4D and 2D */
...@@ -631,13 +615,13 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) ...@@ -631,13 +615,13 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
case 0x094: case 0x094:
case 0x017: /* Intuos3 2D Mouse */ case 0x017: /* Intuos3 2D Mouse */
case 0x806: /* Intuos4 Mouse */ case 0x806: /* Intuos4 Mouse */
wacom->tool[idx] = BTN_TOOL_MOUSE; tool_type = BTN_TOOL_MOUSE;
break; break;
case 0x096: /* Lens cursor */ case 0x096: /* Lens cursor */
case 0x097: /* Intuos3 Lens cursor */ case 0x097: /* Intuos3 Lens cursor */
case 0x006: /* Intuos4 Lens cursor */ case 0x006: /* Intuos4 Lens cursor */
wacom->tool[idx] = BTN_TOOL_LENS; tool_type = BTN_TOOL_LENS;
break; break;
case 0x82a: /* Eraser */ case 0x82a: /* Eraser */
...@@ -657,7 +641,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) ...@@ -657,7 +641,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
case 0x16080a: /* Cintiq 13HD Pro Pen Eraser */ case 0x16080a: /* Cintiq 13HD Pro Pen Eraser */
case 0x18080a: /* DTH2242 Eraser */ case 0x18080a: /* DTH2242 Eraser */
case 0x10080a: /* Intuos4/5 13HD/24HD General Pen Eraser */ case 0x10080a: /* Intuos4/5 13HD/24HD General Pen Eraser */
wacom->tool[idx] = BTN_TOOL_RUBBER; tool_type = BTN_TOOL_RUBBER;
break; break;
case 0xd12: case 0xd12:
...@@ -666,47 +650,57 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) ...@@ -666,47 +650,57 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
case 0x913: /* Intuos3 Airbrush */ case 0x913: /* Intuos3 Airbrush */
case 0x902: /* Intuos4/5 13HD/24HD Airbrush */ case 0x902: /* Intuos4/5 13HD/24HD Airbrush */
case 0x100902: /* Intuos4/5 13HD/24HD Airbrush */ case 0x100902: /* Intuos4/5 13HD/24HD Airbrush */
wacom->tool[idx] = BTN_TOOL_AIRBRUSH; tool_type = BTN_TOOL_AIRBRUSH;
break; break;
default: /* Unknown tool */ default: /* Unknown tool */
wacom->tool[idx] = BTN_TOOL_PEN; tool_type = BTN_TOOL_PEN;
break; break;
} }
return 1; return tool_type;
} }
static int wacom_intuos_inout(struct wacom_wac *wacom)
{
struct wacom_features *features = &wacom->features;
unsigned char *data = wacom->data;
struct input_dev *input = wacom->pen_input;
int idx = (features->type == INTUOS) ? (data[1] & 0x01) : 0;
if (!(((data[1] & 0xfc) == 0xc0) || /* in prox */
((data[1] & 0xfe) == 0x20) || /* in range */
((data[1] & 0xfe) == 0x80))) /* out prox */
return 0;
/* Enter report */
if ((data[1] & 0xfc) == 0xc0) {
/* serial number of the tool */
wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
(data[4] << 20) + (data[5] << 12) +
(data[6] << 4) + (data[7] >> 4);
wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) |
((data[7] & 0x0f) << 20) | ((data[8] & 0xf0) << 12);
wacom->tool[idx] = wacom_intuos_get_tool_type(wacom->id[idx]);
/*
* don't report events for invalid data
*/
/* older I4 styli don't work with new Cintiqs */
if ((!((wacom->id[idx] >> 20) & 0x01) &&
(features->type == WACOM_21UX2)) ||
/* Only large Intuos support Lense Cursor */
(wacom->tool[idx] == BTN_TOOL_LENS &&
(features->type == INTUOS3 ||
features->type == INTUOS3S ||
features->type == INTUOS4 ||
features->type == INTUOS4S ||
features->type == INTUOS5 ||
features->type == INTUOS5S ||
features->type == INTUOSPM ||
features->type == INTUOSPS)) ||
/* Cintiq doesn't send data when RDY bit isn't set */
(features->type == CINTIQ && !(data[1] & 0x40)))
return 1; return 1;
}
/* in Range */
if ((data[1] & 0xfe) == 0x20) {
if (features->type != INTUOSHT2)
wacom->shared->stylus_in_proximity = true; wacom->shared->stylus_in_proximity = true;
if (wacom->shared->touch_down)
return 1;
/* in Range while exiting */ /* in Range while exiting */
if (((data[1] & 0xfe) == 0x20) && wacom->reporting_data) { if (wacom->reporting_data) {
input_report_key(input, BTN_TOUCH, 0); input_report_key(input, BTN_TOUCH, 0);
input_report_abs(input, ABS_PRESSURE, 0); input_report_abs(input, ABS_PRESSURE, 0);
input_report_abs(input, ABS_DISTANCE, wacom->features.distance_max); input_report_abs(input, ABS_DISTANCE, wacom->features.distance_max);
return 2; return 2;
} }
return 1;
}
/* Exit report */ /* Exit report */
if ((data[1] & 0xfe) == 0x80) { if ((data[1] & 0xfe) == 0x80) {
...@@ -750,13 +744,6 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) ...@@ -750,13 +744,6 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
return 2; return 2;
} }
/* don't report other events if we don't know the ID */
if (!wacom->id[idx]) {
/* but reschedule a read of the current tool */
wacom_intuos_schedule_prox_event(wacom);
return 1;
}
return 0; return 0;
} }
...@@ -897,6 +884,36 @@ static int wacom_intuos_general(struct wacom_wac *wacom) ...@@ -897,6 +884,36 @@ static int wacom_intuos_general(struct wacom_wac *wacom)
data[0] != WACOM_REPORT_INTUOS_PEN) data[0] != WACOM_REPORT_INTUOS_PEN)
return 0; return 0;
if (wacom->shared->touch_down)
return 1;
/* don't report events if we don't know the tool ID */
if (!wacom->id[idx]) {
/* but reschedule a read of the current tool */
wacom_intuos_schedule_prox_event(wacom);
return 1;
}
/*
* don't report events for invalid data
*/
/* older I4 styli don't work with new Cintiqs */
if ((!((wacom->id[idx] >> 20) & 0x01) &&
(features->type == WACOM_21UX2)) ||
/* Only large Intuos support Lense Cursor */
(wacom->tool[idx] == BTN_TOOL_LENS &&
(features->type == INTUOS3 ||
features->type == INTUOS3S ||
features->type == INTUOS4 ||
features->type == INTUOS4S ||
features->type == INTUOS5 ||
features->type == INTUOS5S ||
features->type == INTUOSPM ||
features->type == INTUOSPS)) ||
/* Cintiq doesn't send data when RDY bit isn't set */
(features->type == CINTIQ && !(data[1] & 0x40)))
return 1;
x = (be16_to_cpup((__be16 *)&data[2]) << 1) | ((data[9] >> 1) & 1); x = (be16_to_cpup((__be16 *)&data[2]) << 1) | ((data[9] >> 1) & 1);
y = (be16_to_cpup((__be16 *)&data[4]) << 1) | (data[9] & 1); y = (be16_to_cpup((__be16 *)&data[4]) << 1) | (data[9] & 1);
distance = data[9] >> 2; distance = data[9] >> 2;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment