Commit e1c9b9ff authored by Jiri Kosina's avatar Jiri Kosina

Merge branches 'for-4.5/upstream-fixes', 'for-4.6/cmedia', 'for-4.6/i2c-hid',...

Merge branches 'for-4.5/upstream-fixes', 'for-4.6/cmedia', 'for-4.6/i2c-hid', 'for-4.6/logitech', 'for-4.6/multitouch', 'for-4.6/penmount', 'for-4.6/sony', 'for-4.6/thingm', 'for-4.6/upstream' and 'for-4.6/wacom' into for-linus
...@@ -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);
...@@ -1965,6 +1965,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1965,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) },
...@@ -2049,6 +2050,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -2049,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) },
...@@ -2097,6 +2099,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -2097,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) },
{ } { }
}; };
......
...@@ -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), */
......
...@@ -249,6 +249,7 @@ ...@@ -249,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
...@@ -683,6 +684,7 @@ ...@@ -683,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
...@@ -877,6 +879,9 @@ ...@@ -877,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
...@@ -1052,7 +1057,7 @@ ...@@ -1052,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) {
hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); if (((usage->hid - 1) & HID_USAGE) == 0) {
return 1; hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
return 1;
} else {
return -1;
}
} }
return 0; return 0;
......
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,
{ enum led_brightness brightness)
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)
{ {
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);
......
This diff is collapsed.
...@@ -575,16 +575,102 @@ static int wacom_intuos_pad(struct wacom_wac *wacom) ...@@ -575,16 +575,102 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
return 1; return 1;
} }
static int wacom_intuos_get_tool_type(int tool_id)
{
int tool_type;
switch (tool_id) {
case 0x812: /* Inking pen */
case 0x801: /* Intuos3 Inking pen */
case 0x120802: /* Intuos4/5 Inking Pen */
case 0x012:
tool_type = BTN_TOOL_PENCIL;
break;
case 0x822: /* Pen */
case 0x842:
case 0x852:
case 0x823: /* Intuos3 Grip Pen */
case 0x813: /* Intuos3 Classic Pen */
case 0x885: /* Intuos3 Marker Pen */
case 0x802: /* Intuos4/5 13HD/24HD General Pen */
case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */
case 0x8e2: /* IntuosHT2 pen */
case 0x022:
case 0x100804: /* Intuos4/5 13HD/24HD Art Pen */
case 0x140802: /* Intuos4/5 13HD/24HD Classic Pen */
case 0x160802: /* Cintiq 13HD Pro Pen */
case 0x180802: /* DTH2242 Pen */
case 0x100802: /* Intuos4/5 13HD/24HD General Pen */
tool_type = BTN_TOOL_PEN;
break;
case 0x832: /* Stroke pen */
case 0x032:
tool_type = BTN_TOOL_BRUSH;
break;
case 0x007: /* Mouse 4D and 2D */
case 0x09c:
case 0x094:
case 0x017: /* Intuos3 2D Mouse */
case 0x806: /* Intuos4 Mouse */
tool_type = BTN_TOOL_MOUSE;
break;
case 0x096: /* Lens cursor */
case 0x097: /* Intuos3 Lens cursor */
case 0x006: /* Intuos4 Lens cursor */
tool_type = BTN_TOOL_LENS;
break;
case 0x82a: /* Eraser */
case 0x85a:
case 0x91a:
case 0xd1a:
case 0x0fa:
case 0x82b: /* Intuos3 Grip Pen Eraser */
case 0x81b: /* Intuos3 Classic Pen Eraser */
case 0x91b: /* Intuos3 Airbrush Eraser */
case 0x80c: /* Intuos4/5 13HD/24HD Marker Pen Eraser */
case 0x80a: /* Intuos4/5 13HD/24HD General Pen Eraser */
case 0x90a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
case 0x14080a: /* Intuos4/5 13HD/24HD Classic Pen Eraser */
case 0x10090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
case 0x10080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */
case 0x16080a: /* Cintiq 13HD Pro Pen Eraser */
case 0x18080a: /* DTH2242 Eraser */
case 0x10080a: /* Intuos4/5 13HD/24HD General Pen Eraser */
tool_type = BTN_TOOL_RUBBER;
break;
case 0xd12:
case 0x912:
case 0x112:
case 0x913: /* Intuos3 Airbrush */
case 0x902: /* Intuos4/5 13HD/24HD Airbrush */
case 0x100902: /* Intuos4/5 13HD/24HD Airbrush */
tool_type = BTN_TOOL_AIRBRUSH;
break;
default: /* Unknown tool */
tool_type = BTN_TOOL_PEN;
break;
}
return tool_type;
}
static int wacom_intuos_inout(struct wacom_wac *wacom) static int wacom_intuos_inout(struct wacom_wac *wacom)
{ {
struct wacom_features *features = &wacom->features; struct wacom_features *features = &wacom->features;
unsigned char *data = wacom->data; unsigned char *data = wacom->data;
struct input_dev *input = wacom->pen_input; struct input_dev *input = wacom->pen_input;
int idx = 0; int idx = (features->type == INTUOS) ? (data[1] & 0x01) : 0;
/* tool number */ if (!(((data[1] & 0xfc) == 0xc0) || /* in prox */
if (features->type == INTUOS) ((data[1] & 0xfe) == 0x20) || /* in range */
idx = data[1] & 0x01; ((data[1] & 0xfe) == 0x80))) /* out prox */
return 0;
/* Enter report */ /* Enter report */
if ((data[1] & 0xfc) == 0xc0) { if ((data[1] & 0xfc) == 0xc0) {
...@@ -596,116 +682,24 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) ...@@ -596,116 +682,24 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) | wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) |
((data[7] & 0x0f) << 20) | ((data[8] & 0xf0) << 12); ((data[7] & 0x0f) << 20) | ((data[8] & 0xf0) << 12);
switch (wacom->id[idx]) { wacom->tool[idx] = wacom_intuos_get_tool_type(wacom->id[idx]);
case 0x812: /* Inking pen */
case 0x801: /* Intuos3 Inking pen */
case 0x120802: /* Intuos4/5 Inking Pen */
case 0x012:
wacom->tool[idx] = BTN_TOOL_PENCIL;
break;
case 0x822: /* Pen */
case 0x842:
case 0x852:
case 0x823: /* Intuos3 Grip Pen */
case 0x813: /* Intuos3 Classic Pen */
case 0x885: /* Intuos3 Marker Pen */
case 0x802: /* Intuos4/5 13HD/24HD General Pen */
case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */
case 0x022:
case 0x100804: /* Intuos4/5 13HD/24HD Art Pen */
case 0x140802: /* Intuos4/5 13HD/24HD Classic Pen */
case 0x160802: /* Cintiq 13HD Pro Pen */
case 0x180802: /* DTH2242 Pen */
case 0x100802: /* Intuos4/5 13HD/24HD General Pen */
wacom->tool[idx] = BTN_TOOL_PEN;
break;
case 0x832: /* Stroke pen */
case 0x032:
wacom->tool[idx] = BTN_TOOL_BRUSH;
break;
case 0x007: /* Mouse 4D and 2D */
case 0x09c:
case 0x094:
case 0x017: /* Intuos3 2D Mouse */
case 0x806: /* Intuos4 Mouse */
wacom->tool[idx] = BTN_TOOL_MOUSE;
break;
case 0x096: /* Lens cursor */
case 0x097: /* Intuos3 Lens cursor */
case 0x006: /* Intuos4 Lens cursor */
wacom->tool[idx] = BTN_TOOL_LENS;
break;
case 0x82a: /* Eraser */
case 0x85a:
case 0x91a:
case 0xd1a:
case 0x0fa:
case 0x82b: /* Intuos3 Grip Pen Eraser */
case 0x81b: /* Intuos3 Classic Pen Eraser */
case 0x91b: /* Intuos3 Airbrush Eraser */
case 0x80c: /* Intuos4/5 13HD/24HD Marker Pen Eraser */
case 0x80a: /* Intuos4/5 13HD/24HD General Pen Eraser */
case 0x90a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
case 0x14080a: /* Intuos4/5 13HD/24HD Classic Pen Eraser */
case 0x10090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
case 0x10080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */
case 0x16080a: /* Cintiq 13HD Pro Pen Eraser */
case 0x18080a: /* DTH2242 Eraser */
case 0x10080a: /* Intuos4/5 13HD/24HD General Pen Eraser */
wacom->tool[idx] = BTN_TOOL_RUBBER;
break;
case 0xd12:
case 0x912:
case 0x112:
case 0x913: /* Intuos3 Airbrush */
case 0x902: /* Intuos4/5 13HD/24HD Airbrush */
case 0x100902: /* Intuos4/5 13HD/24HD Airbrush */
wacom->tool[idx] = BTN_TOOL_AIRBRUSH;
break;
default: /* Unknown tool */
wacom->tool[idx] = BTN_TOOL_PEN;
break;
}
return 1; return 1;
} }
/* /* in Range */
* don't report events for invalid data if ((data[1] & 0xfe) == 0x20) {
*/ if (features->type != INTUOSHT2)
/* older I4 styli don't work with new Cintiqs */ wacom->shared->stylus_in_proximity = true;
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;
wacom->shared->stylus_in_proximity = true; /* in Range while exiting */
if (wacom->shared->touch_down) if (wacom->reporting_data) {
input_report_key(input, BTN_TOUCH, 0);
input_report_abs(input, ABS_PRESSURE, 0);
input_report_abs(input, ABS_DISTANCE, wacom->features.distance_max);
return 2;
}
return 1; return 1;
/* in Range while exiting */
if (((data[1] & 0xfe) == 0x20) && wacom->reporting_data) {
input_report_key(input, BTN_TOUCH, 0);
input_report_abs(input, ABS_PRESSURE, 0);
input_report_abs(input, ABS_DISTANCE, wacom->features.distance_max);
return 2;
} }
/* Exit report */ /* Exit report */
...@@ -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