mirror of https://gitee.com/openkylin/linux.git
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID updates from Jiri Kosina: - open/close tracking improvements from Dmitry Torokhov - battery support improvements in Wacom driver from Jason Gerecke - Win8 support fixes from Benjamin Tissories and Hans de Geode - misc fixes to Intel-ISH driver from Arnd Bergmann - support for quite a few new devices and small assorted fixes here and there * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (35 commits) HID: intel-ish-hid: Enable Gemini Lake ish driver HID: intel-ish-hid: Enable Cannon Lake ish driver HID: wacom: fix mistake in printk HID: multitouch: optimize the sticky fingers timer HID: multitouch: fix rare Win 8 cases when the touch up event gets missing HID: multitouch: use BIT macro HID: Add driver for Retrode2 joypad adapter HID: multitouch: Add support for Google Rose Touchpad HID: multitouch: Support PTP Stick and Touchpad device HID: core: don't use negative operands when shift HID: apple: Use country code to detect ISO keyboards HID: remove no longer used hid->open field greybus: hid: remove custom locking from gb_hid_open/close HID: usbhid: remove custom locking from usbhid_open/close HID: i2c-hid: remove custom locking from i2c_hid_open/close HID: serialize hid_hw_open and hid_hw_close HID: usbhid: do not rely on hid->open when deciding to do IO HID: hiddev: use hid_hw_power instead of usbhid_get/put_power HID: hiddev: use hid_hw_open/close instead of usbhid_open/close HID: asus: Add support for Zen AiO MD-5110 keyboard ...
This commit is contained in:
commit
a91ab911df
|
@ -388,6 +388,13 @@ config HID_ICADE
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called hid-icade.
|
||||
|
||||
config HID_ITE
|
||||
tristate "ITE devices"
|
||||
depends on HID
|
||||
default !EXPERT
|
||||
---help---
|
||||
Support for ITE devices not fully compliant with HID standard.
|
||||
|
||||
config HID_TWINHAN
|
||||
tristate "Twinhan IR remote control"
|
||||
depends on HID
|
||||
|
@ -741,6 +748,14 @@ config HID_PRIMAX
|
|||
Support for Primax devices that are not fully compliant with the
|
||||
HID standard.
|
||||
|
||||
config HID_RETRODE
|
||||
tristate "Retrode"
|
||||
depends on USB_HID
|
||||
---help---
|
||||
Support for
|
||||
|
||||
* Retrode 2 cartridge and controller adapter
|
||||
|
||||
config HID_ROCCAT
|
||||
tristate "Roccat device support"
|
||||
depends on USB_HID
|
||||
|
|
|
@ -50,6 +50,7 @@ obj-$(CONFIG_HID_HOLTEK) += hid-holtek-mouse.o
|
|||
obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o
|
||||
obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o
|
||||
obj-$(CONFIG_HID_ICADE) += hid-icade.o
|
||||
obj-$(CONFIG_HID_ITE) += hid-ite.o
|
||||
obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o
|
||||
obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o
|
||||
obj-$(CONFIG_HID_KYE) += hid-kye.o
|
||||
|
@ -81,6 +82,7 @@ hid-picolcd-$(CONFIG_DEBUG_FS) += hid-picolcd_debugfs.o
|
|||
|
||||
obj-$(CONFIG_HID_PLANTRONICS) += hid-plantronics.o
|
||||
obj-$(CONFIG_HID_PRIMAX) += hid-primax.o
|
||||
obj-$(CONFIG_HID_RETRODE) += hid-retrode.o
|
||||
obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \
|
||||
hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
|
||||
hid-roccat-koneplus.o hid-roccat-konepure.o hid-roccat-kovaplus.o \
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#define APPLE_IGNORE_MOUSE 0x0002
|
||||
#define APPLE_HAS_FN 0x0004
|
||||
#define APPLE_HIDDEV 0x0008
|
||||
#define APPLE_ISO_KEYBOARD 0x0010
|
||||
/* 0x0010 reserved, was: APPLE_ISO_KEYBOARD */
|
||||
#define APPLE_MIGHTYMOUSE 0x0020
|
||||
#define APPLE_INVERT_HWHEEL 0x0040
|
||||
#define APPLE_IGNORE_HIDINPUT 0x0080
|
||||
|
@ -36,6 +36,8 @@
|
|||
|
||||
#define APPLE_FLAG_FKEY 0x01
|
||||
|
||||
#define HID_COUNTRY_INTERNATIONAL_ISO 13
|
||||
|
||||
static unsigned int fnmode = 1;
|
||||
module_param(fnmode, uint, 0644);
|
||||
MODULE_PARM_DESC(fnmode, "Mode of fn key on Apple keyboards (0 = disabled, "
|
||||
|
@ -247,7 +249,7 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
|
|||
}
|
||||
|
||||
if (iso_layout) {
|
||||
if (asc->quirks & APPLE_ISO_KEYBOARD) {
|
||||
if (hid->country == HID_COUNTRY_INTERNATIONAL_ISO) {
|
||||
trans = apple_find_translation(apple_iso_keyboard, usage->code);
|
||||
if (trans) {
|
||||
input_event(input, usage->type, trans->to, value);
|
||||
|
@ -412,60 +414,54 @@ static const struct hid_device_id apple_devices[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
|
||||
APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
|
||||
APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
|
||||
APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
|
||||
APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
|
||||
APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_ISO),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_JIS),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
|
||||
APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
|
||||
APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
|
||||
APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
|
||||
APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
|
||||
USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
|
@ -479,86 +475,85 @@ static const struct hid_device_id apple_devices[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
|
||||
APPLE_ISO_KEYBOARD },
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY),
|
||||
|
|
|
@ -422,6 +422,33 @@ static int asus_input_mapping(struct hid_device *hdev,
|
|||
return 1;
|
||||
}
|
||||
|
||||
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR) {
|
||||
set_bit(EV_REP, hi->input->evbit);
|
||||
switch (usage->hid & HID_USAGE) {
|
||||
case 0xff01: asus_map_key_clear(BTN_1); break;
|
||||
case 0xff02: asus_map_key_clear(BTN_2); break;
|
||||
case 0xff03: asus_map_key_clear(BTN_3); break;
|
||||
case 0xff04: asus_map_key_clear(BTN_4); break;
|
||||
case 0xff05: asus_map_key_clear(BTN_5); break;
|
||||
case 0xff06: asus_map_key_clear(BTN_6); break;
|
||||
case 0xff07: asus_map_key_clear(BTN_7); break;
|
||||
case 0xff08: asus_map_key_clear(BTN_8); break;
|
||||
case 0xff09: asus_map_key_clear(BTN_9); break;
|
||||
case 0xff0a: asus_map_key_clear(BTN_A); break;
|
||||
case 0xff0b: asus_map_key_clear(BTN_B); break;
|
||||
case 0x00f1: asus_map_key_clear(KEY_WLAN); break;
|
||||
case 0x00f2: asus_map_key_clear(KEY_BRIGHTNESSDOWN); break;
|
||||
case 0x00f3: asus_map_key_clear(KEY_BRIGHTNESSUP); break;
|
||||
case 0x00f4: asus_map_key_clear(KEY_DISPLAY_OFF); break;
|
||||
case 0x00f7: asus_map_key_clear(KEY_CAMERA); break;
|
||||
case 0x00f8: asus_map_key_clear(KEY_PROG1); break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (drvdata->quirks & QUIRK_NO_CONSUMER_USAGES &&
|
||||
(usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) {
|
||||
switch (usage->hid & HID_USAGE) {
|
||||
|
@ -572,6 +599,9 @@ static const struct hid_device_id asus_devices[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
|
||||
USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD),
|
||||
QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_ASUS_AK1D) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_ASUS_MD_5110) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_ASUS_MD_5112) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, asus_devices);
|
||||
|
|
|
@ -84,9 +84,7 @@ static __u8 *ch_switch12_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
static const struct hid_device_id ch_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_JESS_ZEN_AIO_KBD) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, ch_devices);
|
||||
|
|
|
@ -1070,7 +1070,7 @@ static s32 snto32(__u32 value, unsigned n)
|
|||
case 16: return ((__s16)value);
|
||||
case 32: return ((__s32)value);
|
||||
}
|
||||
return value & (1 << (n - 1)) ? value | (-1 << n) : value;
|
||||
return value & (1 << (n - 1)) ? value | (~0U << n) : value;
|
||||
}
|
||||
|
||||
s32 hid_snto32(__u32 value, unsigned n)
|
||||
|
@ -1774,6 +1774,94 @@ void hid_disconnect(struct hid_device *hdev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(hid_disconnect);
|
||||
|
||||
/**
|
||||
* hid_hw_start - start underlying HW
|
||||
* @hdev: hid device
|
||||
* @connect_mask: which outputs to connect, see HID_CONNECT_*
|
||||
*
|
||||
* Call this in probe function *after* hid_parse. This will setup HW
|
||||
* buffers and start the device (if not defeirred to device open).
|
||||
* hid_hw_stop must be called if this was successful.
|
||||
*/
|
||||
int hid_hw_start(struct hid_device *hdev, unsigned int connect_mask)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = hdev->ll_driver->start(hdev);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (connect_mask) {
|
||||
error = hid_connect(hdev, connect_mask);
|
||||
if (error) {
|
||||
hdev->ll_driver->stop(hdev);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hid_hw_start);
|
||||
|
||||
/**
|
||||
* hid_hw_stop - stop underlying HW
|
||||
* @hdev: hid device
|
||||
*
|
||||
* This is usually called from remove function or from probe when something
|
||||
* failed and hid_hw_start was called already.
|
||||
*/
|
||||
void hid_hw_stop(struct hid_device *hdev)
|
||||
{
|
||||
hid_disconnect(hdev);
|
||||
hdev->ll_driver->stop(hdev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hid_hw_stop);
|
||||
|
||||
/**
|
||||
* hid_hw_open - signal underlying HW to start delivering events
|
||||
* @hdev: hid device
|
||||
*
|
||||
* Tell underlying HW to start delivering events from the device.
|
||||
* This function should be called sometime after successful call
|
||||
* to hid_hiw_start().
|
||||
*/
|
||||
int hid_hw_open(struct hid_device *hdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mutex_lock_killable(&hdev->ll_open_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!hdev->ll_open_count++) {
|
||||
ret = hdev->ll_driver->open(hdev);
|
||||
if (ret)
|
||||
hdev->ll_open_count--;
|
||||
}
|
||||
|
||||
mutex_unlock(&hdev->ll_open_lock);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hid_hw_open);
|
||||
|
||||
/**
|
||||
* hid_hw_close - signal underlaying HW to stop delivering events
|
||||
*
|
||||
* @hdev: hid device
|
||||
*
|
||||
* This function indicates that we are not interested in the events
|
||||
* from this device anymore. Delivery of events may or may not stop,
|
||||
* depending on the number of users still outstanding.
|
||||
*/
|
||||
void hid_hw_close(struct hid_device *hdev)
|
||||
{
|
||||
mutex_lock(&hdev->ll_open_lock);
|
||||
if (!--hdev->ll_open_count)
|
||||
hdev->ll_driver->close(hdev);
|
||||
mutex_unlock(&hdev->ll_open_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hid_hw_close);
|
||||
|
||||
/*
|
||||
* A list of devices for which there is a specialized driver on HID bus.
|
||||
*
|
||||
|
@ -1892,6 +1980,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_ASUS_MD_5112) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_ASUS_MD_5110) },
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_HID_AUREAL)
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
|
||||
|
@ -1913,9 +2003,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
|||
#if IS_ENABLED(CONFIG_HID_CHICONY)
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_ASUS_AK1D) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_JESS_ZEN_AIO_KBD) },
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_HID_CMEDIA)
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM6533) },
|
||||
|
@ -1984,6 +2073,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
|||
#if IS_ENABLED(CONFIG_HID_ICADE)
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_HID_ITE)
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_HID_KENSINGTON)
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
|
||||
#endif
|
||||
|
@ -2151,6 +2243,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
|||
#if IS_ENABLED(CONFIG_HID_PRODIKEYS)
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_HID_RETRODE)
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_FUTURE_TECHNOLOGY, USB_DEVICE_ID_RETRODE2) },
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_HID_RMI)
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_COVER) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLADE_14) },
|
||||
|
@ -2914,6 +3009,7 @@ struct hid_device *hid_allocate_device(void)
|
|||
spin_lock_init(&hdev->debug_list_lock);
|
||||
sema_init(&hdev->driver_lock, 1);
|
||||
sema_init(&hdev->driver_input_lock, 1);
|
||||
mutex_init(&hdev->ll_open_lock);
|
||||
|
||||
return hdev;
|
||||
}
|
||||
|
|
|
@ -75,6 +75,8 @@
|
|||
|
||||
#define USB_VENDOR_ID_ALPS_JP 0x044E
|
||||
#define HID_DEVICE_ID_ALPS_U1_DUAL 0x120B
|
||||
#define HID_DEVICE_ID_ALPS_U1_DUAL_PTP 0x121F
|
||||
#define HID_DEVICE_ID_ALPS_U1_DUAL_3BTN_PTP 0x1220
|
||||
|
||||
#define USB_VENDOR_ID_AMI 0x046b
|
||||
#define USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE 0xff10
|
||||
|
@ -252,7 +254,7 @@
|
|||
#define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618
|
||||
#define USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE 0x1053
|
||||
#define USB_DEVICE_ID_CHICONY_WIRELESS2 0x1123
|
||||
#define USB_DEVICE_ID_CHICONY_AK1D 0x1125
|
||||
#define USB_DEVICE_ID_ASUS_AK1D 0x1125
|
||||
#define USB_DEVICE_ID_CHICONY_ACER_SWITCH12 0x1421
|
||||
|
||||
#define USB_VENDOR_ID_CHUNGHWAT 0x2247
|
||||
|
@ -386,6 +388,9 @@
|
|||
#define USB_VENDOR_ID_FUTABA 0x0547
|
||||
#define USB_DEVICE_ID_LED_DISPLAY 0x7000
|
||||
|
||||
#define USB_VENDOR_ID_FUTURE_TECHNOLOGY 0x0403
|
||||
#define USB_DEVICE_ID_RETRODE2 0x97c1
|
||||
|
||||
#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f
|
||||
#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
|
||||
|
||||
|
@ -428,6 +433,9 @@
|
|||
#define USB_VENDOR_ID_GOODTOUCH 0x1aad
|
||||
#define USB_DEVICE_ID_GOODTOUCH_000f 0x000f
|
||||
|
||||
#define USB_VENDOR_ID_GOOGLE 0x18d1
|
||||
#define USB_DEVICE_ID_GOOGLE_TOUCH_ROSE 0x5028
|
||||
|
||||
#define USB_VENDOR_ID_GOTOP 0x08f2
|
||||
#define USB_DEVICE_ID_SUPER_Q2 0x007f
|
||||
#define USB_DEVICE_ID_GOGOPEN 0x00ce
|
||||
|
@ -565,6 +573,7 @@
|
|||
#define USB_DEVICE_ID_ITE_LENOVO_YOGA 0x8386
|
||||
#define USB_DEVICE_ID_ITE_LENOVO_YOGA2 0x8350
|
||||
#define USB_DEVICE_ID_ITE_LENOVO_YOGA900 0x8396
|
||||
#define USB_DEVICE_ID_ITE8595 0x8595
|
||||
|
||||
#define USB_VENDOR_ID_JABRA 0x0b0e
|
||||
#define USB_DEVICE_ID_JABRA_SPEAK_410 0x0412
|
||||
|
@ -573,7 +582,7 @@
|
|||
|
||||
#define USB_VENDOR_ID_JESS 0x0c45
|
||||
#define USB_DEVICE_ID_JESS_YUREX 0x1010
|
||||
#define USB_DEVICE_ID_JESS_ZEN_AIO_KBD 0x5112
|
||||
#define USB_DEVICE_ID_ASUS_MD_5112 0x5112
|
||||
|
||||
#define USB_VENDOR_ID_JESS2 0x0f30
|
||||
#define USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD 0x0111
|
||||
|
@ -1024,6 +1033,7 @@
|
|||
|
||||
#define USB_VENDOR_ID_TURBOX 0x062a
|
||||
#define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201
|
||||
#define USB_DEVICE_ID_ASUS_MD_5110 0x5110
|
||||
#define USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART 0x7100
|
||||
|
||||
#define USB_VENDOR_ID_TWINHAN 0x6253
|
||||
|
|
|
@ -656,6 +656,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
|||
case HID_GD_START: map_key_clear(BTN_START); break;
|
||||
case HID_GD_SELECT: map_key_clear(BTN_SELECT); break;
|
||||
|
||||
case HID_GD_RFKILL_BTN:
|
||||
/* MS wireless radio ctl extension, also check CA */
|
||||
if (field->application == HID_GD_WIRELESS_RADIO_CTLS) {
|
||||
map_key_clear(KEY_RFKILL);
|
||||
/* We need to simulate the btn release */
|
||||
field->flags |= HID_MAIN_ITEM_RELATIVE;
|
||||
break;
|
||||
}
|
||||
|
||||
default: goto unknown;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* HID driver for some ITE "special" devices
|
||||
* Copyright (c) 2017 Hans de Goede <hdegoede@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "hid-ids.h"
|
||||
|
||||
static int ite_event(struct hid_device *hdev, struct hid_field *field,
|
||||
struct hid_usage *usage, __s32 value)
|
||||
{
|
||||
struct input_dev *input;
|
||||
|
||||
if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput)
|
||||
return 0;
|
||||
|
||||
input = field->hidinput->input;
|
||||
|
||||
/*
|
||||
* The ITE8595 always reports 0 as value for the rfkill button. Luckily
|
||||
* it is the only button in its report, and it sends a report on
|
||||
* release only, so receiving a report means the button was pressed.
|
||||
*/
|
||||
if (usage->hid == HID_GD_RFKILL_BTN) {
|
||||
input_event(input, EV_KEY, KEY_RFKILL, 1);
|
||||
input_sync(input);
|
||||
input_event(input, EV_KEY, KEY_RFKILL, 0);
|
||||
input_sync(input);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct hid_device_id ite_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, ite_devices);
|
||||
|
||||
static struct hid_driver ite_driver = {
|
||||
.name = "itetech",
|
||||
.id_table = ite_devices,
|
||||
.event = ite_event,
|
||||
};
|
||||
module_hid_driver(ite_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
|
@ -44,6 +44,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
|
||||
MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
|
||||
|
@ -54,28 +55,33 @@ MODULE_LICENSE("GPL");
|
|||
#include "hid-ids.h"
|
||||
|
||||
/* quirks to control the device */
|
||||
#define MT_QUIRK_NOT_SEEN_MEANS_UP (1 << 0)
|
||||
#define MT_QUIRK_SLOT_IS_CONTACTID (1 << 1)
|
||||
#define MT_QUIRK_CYPRESS (1 << 2)
|
||||
#define MT_QUIRK_SLOT_IS_CONTACTNUMBER (1 << 3)
|
||||
#define MT_QUIRK_ALWAYS_VALID (1 << 4)
|
||||
#define MT_QUIRK_VALID_IS_INRANGE (1 << 5)
|
||||
#define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 6)
|
||||
#define MT_QUIRK_CONFIDENCE (1 << 7)
|
||||
#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8)
|
||||
#define MT_QUIRK_NO_AREA (1 << 9)
|
||||
#define MT_QUIRK_IGNORE_DUPLICATES (1 << 10)
|
||||
#define MT_QUIRK_HOVERING (1 << 11)
|
||||
#define MT_QUIRK_CONTACT_CNT_ACCURATE (1 << 12)
|
||||
#define MT_QUIRK_FORCE_GET_FEATURE (1 << 13)
|
||||
#define MT_QUIRK_FIX_CONST_CONTACT_ID (1 << 14)
|
||||
#define MT_QUIRK_TOUCH_SIZE_SCALING (1 << 15)
|
||||
#define MT_QUIRK_NOT_SEEN_MEANS_UP BIT(0)
|
||||
#define MT_QUIRK_SLOT_IS_CONTACTID BIT(1)
|
||||
#define MT_QUIRK_CYPRESS BIT(2)
|
||||
#define MT_QUIRK_SLOT_IS_CONTACTNUMBER BIT(3)
|
||||
#define MT_QUIRK_ALWAYS_VALID BIT(4)
|
||||
#define MT_QUIRK_VALID_IS_INRANGE BIT(5)
|
||||
#define MT_QUIRK_VALID_IS_CONFIDENCE BIT(6)
|
||||
#define MT_QUIRK_CONFIDENCE BIT(7)
|
||||
#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE BIT(8)
|
||||
#define MT_QUIRK_NO_AREA BIT(9)
|
||||
#define MT_QUIRK_IGNORE_DUPLICATES BIT(10)
|
||||
#define MT_QUIRK_HOVERING BIT(11)
|
||||
#define MT_QUIRK_CONTACT_CNT_ACCURATE BIT(12)
|
||||
#define MT_QUIRK_FORCE_GET_FEATURE BIT(13)
|
||||
#define MT_QUIRK_FIX_CONST_CONTACT_ID BIT(14)
|
||||
#define MT_QUIRK_TOUCH_SIZE_SCALING BIT(15)
|
||||
#define MT_QUIRK_STICKY_FINGERS BIT(16)
|
||||
|
||||
#define MT_INPUTMODE_TOUCHSCREEN 0x02
|
||||
#define MT_INPUTMODE_TOUCHPAD 0x03
|
||||
|
||||
#define MT_BUTTONTYPE_CLICKPAD 0
|
||||
|
||||
#define MT_IO_FLAGS_RUNNING 0
|
||||
#define MT_IO_FLAGS_ACTIVE_SLOTS 1
|
||||
#define MT_IO_FLAGS_PENDING_SLOTS 2
|
||||
|
||||
struct mt_slot {
|
||||
__s32 x, y, cx, cy, p, w, h;
|
||||
__s32 contactid; /* the device ContactID assigned to this slot */
|
||||
|
@ -104,8 +110,10 @@ struct mt_fields {
|
|||
struct mt_device {
|
||||
struct mt_slot curdata; /* placeholder of incoming data */
|
||||
struct mt_class mtclass; /* our mt device class */
|
||||
struct timer_list release_timer; /* to release sticky fingers */
|
||||
struct mt_fields *fields; /* temporary placeholder for storing the
|
||||
multitouch fields */
|
||||
unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_*) */
|
||||
int cc_index; /* contact count field index in the report */
|
||||
int cc_value_index; /* contact count value index in the field */
|
||||
unsigned last_slot_field; /* the last field of a slot */
|
||||
|
@ -148,6 +156,7 @@ static void mt_post_parse(struct mt_device *td);
|
|||
/* reserved 0x0011 */
|
||||
#define MT_CLS_WIN_8 0x0012
|
||||
#define MT_CLS_EXPORT_ALL_INPUTS 0x0013
|
||||
#define MT_CLS_WIN_8_DUAL 0x0014
|
||||
|
||||
/* vendor specific classes */
|
||||
#define MT_CLS_3M 0x0101
|
||||
|
@ -161,6 +170,7 @@ static void mt_post_parse(struct mt_device *td);
|
|||
#define MT_CLS_GENERALTOUCH_PWT_TENFINGERS 0x0109
|
||||
#define MT_CLS_LG 0x010a
|
||||
#define MT_CLS_VTL 0x0110
|
||||
#define MT_CLS_GOOGLE 0x0111
|
||||
|
||||
#define MT_DEFAULT_MAXCONTACT 10
|
||||
#define MT_MAX_MAXCONTACT 250
|
||||
|
@ -212,11 +222,18 @@ static struct mt_class mt_classes[] = {
|
|||
.quirks = MT_QUIRK_ALWAYS_VALID |
|
||||
MT_QUIRK_IGNORE_DUPLICATES |
|
||||
MT_QUIRK_HOVERING |
|
||||
MT_QUIRK_CONTACT_CNT_ACCURATE },
|
||||
MT_QUIRK_CONTACT_CNT_ACCURATE |
|
||||
MT_QUIRK_STICKY_FINGERS },
|
||||
{ .name = MT_CLS_EXPORT_ALL_INPUTS,
|
||||
.quirks = MT_QUIRK_ALWAYS_VALID |
|
||||
MT_QUIRK_CONTACT_CNT_ACCURATE,
|
||||
.export_all_inputs = true },
|
||||
{ .name = MT_CLS_WIN_8_DUAL,
|
||||
.quirks = MT_QUIRK_ALWAYS_VALID |
|
||||
MT_QUIRK_IGNORE_DUPLICATES |
|
||||
MT_QUIRK_HOVERING |
|
||||
MT_QUIRK_CONTACT_CNT_ACCURATE,
|
||||
.export_all_inputs = true },
|
||||
|
||||
/*
|
||||
* vendor specific classes
|
||||
|
@ -278,6 +295,12 @@ static struct mt_class mt_classes[] = {
|
|||
MT_QUIRK_CONTACT_CNT_ACCURATE |
|
||||
MT_QUIRK_FORCE_GET_FEATURE,
|
||||
},
|
||||
{ .name = MT_CLS_GOOGLE,
|
||||
.quirks = MT_QUIRK_ALWAYS_VALID |
|
||||
MT_QUIRK_CONTACT_CNT_ACCURATE |
|
||||
MT_QUIRK_SLOT_IS_CONTACTID |
|
||||
MT_QUIRK_HOVERING
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -512,7 +535,8 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|||
mt_store_field(usage, td, hi);
|
||||
return 1;
|
||||
case HID_DG_CONFIDENCE:
|
||||
if (cls->name == MT_CLS_WIN_8 &&
|
||||
if ((cls->name == MT_CLS_WIN_8 ||
|
||||
cls->name == MT_CLS_WIN_8_DUAL) &&
|
||||
field->application == HID_DG_TOUCHPAD)
|
||||
cls->quirks |= MT_QUIRK_CONFIDENCE;
|
||||
mt_store_field(usage, td, hi);
|
||||
|
@ -579,7 +603,8 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|||
* MS PTP spec says that external buttons left and right have
|
||||
* usages 2 and 3.
|
||||
*/
|
||||
if (cls->name == MT_CLS_WIN_8 &&
|
||||
if ((cls->name == MT_CLS_WIN_8 ||
|
||||
cls->name == MT_CLS_WIN_8_DUAL) &&
|
||||
field->application == HID_DG_TOUCHPAD &&
|
||||
(usage->hid & HID_USAGE) > 1)
|
||||
code--;
|
||||
|
@ -682,6 +707,8 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
|
|||
input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
|
||||
input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
|
||||
input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
|
||||
|
||||
set_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -697,6 +724,11 @@ static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
|
|||
input_mt_sync_frame(input);
|
||||
input_sync(input);
|
||||
td->num_received = 0;
|
||||
if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags))
|
||||
set_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags);
|
||||
else
|
||||
clear_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags);
|
||||
clear_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags);
|
||||
}
|
||||
|
||||
static int mt_touch_event(struct hid_device *hid, struct hid_field *field,
|
||||
|
@ -788,6 +820,10 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
|
|||
unsigned count;
|
||||
int r, n;
|
||||
|
||||
/* sticky fingers release in progress, abort */
|
||||
if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Includes multi-packet support where subsequent
|
||||
* packets are sent with zero contactcount.
|
||||
|
@ -813,6 +849,34 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
|
|||
|
||||
if (td->num_received >= td->num_expected)
|
||||
mt_sync_frame(td, report->field[0]->hidinput->input);
|
||||
|
||||
/*
|
||||
* Windows 8 specs says 2 things:
|
||||
* - once a contact has been reported, it has to be reported in each
|
||||
* subsequent report
|
||||
* - the report rate when fingers are present has to be at least
|
||||
* the refresh rate of the screen, 60 or 120 Hz
|
||||
*
|
||||
* I interprete this that the specification forces a report rate of
|
||||
* at least 60 Hz for a touchscreen to be certified.
|
||||
* Which means that if we do not get a report whithin 16 ms, either
|
||||
* something wrong happens, either the touchscreen forgets to send
|
||||
* a release. Taking a reasonable margin allows to remove issues
|
||||
* with USB communication or the load of the machine.
|
||||
*
|
||||
* Given that Win 8 devices are forced to send a release, this will
|
||||
* only affect laggish machines and the ones that have a firmware
|
||||
* defect.
|
||||
*/
|
||||
if (td->mtclass.quirks & MT_QUIRK_STICKY_FINGERS) {
|
||||
if (test_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags))
|
||||
mod_timer(&td->release_timer,
|
||||
jiffies + msecs_to_jiffies(100));
|
||||
else
|
||||
del_timer(&td->release_timer);
|
||||
}
|
||||
|
||||
clear_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
|
||||
}
|
||||
|
||||
static int mt_touch_input_configured(struct hid_device *hdev,
|
||||
|
@ -1124,6 +1188,47 @@ static void mt_fix_const_fields(struct hid_device *hdev, unsigned int usage)
|
|||
}
|
||||
}
|
||||
|
||||
static void mt_release_contacts(struct hid_device *hid)
|
||||
{
|
||||
struct hid_input *hidinput;
|
||||
struct mt_device *td = hid_get_drvdata(hid);
|
||||
|
||||
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_mt_sync_frame(input_dev);
|
||||
input_sync(input_dev);
|
||||
}
|
||||
}
|
||||
|
||||
td->num_received = 0;
|
||||
}
|
||||
|
||||
static void mt_expired_timeout(unsigned long arg)
|
||||
{
|
||||
struct hid_device *hdev = (void *)arg;
|
||||
struct mt_device *td = hid_get_drvdata(hdev);
|
||||
|
||||
/*
|
||||
* An input report came in just before we release the sticky fingers,
|
||||
* it will take care of the sticky fingers.
|
||||
*/
|
||||
if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
|
||||
return;
|
||||
if (test_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags))
|
||||
mt_release_contacts(hdev);
|
||||
clear_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
|
||||
}
|
||||
|
||||
static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
{
|
||||
int ret, i;
|
||||
|
@ -1193,6 +1298,8 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
*/
|
||||
hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
|
||||
|
||||
setup_timer(&td->release_timer, mt_expired_timeout, (long)hdev);
|
||||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
@ -1220,28 +1327,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
}
|
||||
|
||||
#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_mt_sync_frame(input_dev);
|
||||
input_sync(input_dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int mt_reset_resume(struct hid_device *hdev)
|
||||
{
|
||||
mt_release_contacts(hdev);
|
||||
|
@ -1266,6 +1351,8 @@ static void mt_remove(struct hid_device *hdev)
|
|||
{
|
||||
struct mt_device *td = hid_get_drvdata(hdev);
|
||||
|
||||
del_timer_sync(&td->release_timer);
|
||||
|
||||
sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
|
||||
hid_hw_stop(hdev);
|
||||
hdev->quirks = td->initial_quirks;
|
||||
|
@ -1290,6 +1377,16 @@ static const struct hid_device_id mt_devices[] = {
|
|||
MT_USB_DEVICE(USB_VENDOR_ID_3M,
|
||||
USB_DEVICE_ID_3M3266) },
|
||||
|
||||
/* Alps devices */
|
||||
{ .driver_data = MT_CLS_WIN_8_DUAL,
|
||||
HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
|
||||
USB_VENDOR_ID_ALPS_JP,
|
||||
HID_DEVICE_ID_ALPS_U1_DUAL_PTP) },
|
||||
{ .driver_data = MT_CLS_WIN_8_DUAL,
|
||||
HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
|
||||
USB_VENDOR_ID_ALPS_JP,
|
||||
HID_DEVICE_ID_ALPS_U1_DUAL_3BTN_PTP) },
|
||||
|
||||
/* Anton devices */
|
||||
{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_ANTON,
|
||||
|
@ -1569,6 +1666,11 @@ static const struct hid_device_id mt_devices[] = {
|
|||
MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
|
||||
USB_DEVICE_ID_XIROKU_CSR2) },
|
||||
|
||||
/* Google MT devices */
|
||||
{ .driver_data = MT_CLS_GOOGLE,
|
||||
HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_GOOGLE,
|
||||
USB_DEVICE_ID_GOOGLE_TOUCH_ROSE) },
|
||||
|
||||
/* Generic MT device */
|
||||
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) },
|
||||
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* HID driver for Retrode 2 controller adapter and plug-in extensions
|
||||
*
|
||||
* Copyright (c) 2017 Bastien Nocera <hadess@hadess.net>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
#include "hid-ids.h"
|
||||
|
||||
#define CONTROLLER_NAME_BASE "Retrode"
|
||||
|
||||
static int retrode_input_configured(struct hid_device *hdev,
|
||||
struct hid_input *hi)
|
||||
{
|
||||
struct hid_field *field = hi->report->field[0];
|
||||
const char *suffix;
|
||||
int number = 0;
|
||||
char *name;
|
||||
|
||||
switch (field->report->id) {
|
||||
case 0:
|
||||
suffix = "SNES Mouse";
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
suffix = "SNES / N64";
|
||||
number = field->report->id;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
suffix = "Mega Drive";
|
||||
number = field->report->id - 2;
|
||||
break;
|
||||
default:
|
||||
hid_err(hdev, "Got unhandled report id %d\n", field->report->id);
|
||||
suffix = "Unknown";
|
||||
}
|
||||
|
||||
if (number)
|
||||
name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
|
||||
"%s %s #%d", CONTROLLER_NAME_BASE,
|
||||
suffix, number);
|
||||
else
|
||||
name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
|
||||
"%s %s", CONTROLLER_NAME_BASE, suffix);
|
||||
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
hi->input->name = name;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int retrode_probe(struct hid_device *hdev,
|
||||
const struct hid_device_id *id)
|
||||
{
|
||||
|
||||
int ret;
|
||||
|
||||
/* Has no effect on the mouse device */
|
||||
hdev->quirks |= HID_QUIRK_MULTI_INPUT;
|
||||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct hid_device_id retrode_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_FUTURE_TECHNOLOGY, USB_DEVICE_ID_RETRODE2) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, retrode_devices);
|
||||
|
||||
static struct hid_driver retrode_driver = {
|
||||
.name = "hid-retrode",
|
||||
.id_table = retrode_devices,
|
||||
.input_configured = retrode_input_configured,
|
||||
.probe = retrode_probe,
|
||||
};
|
||||
|
||||
module_hid_driver(retrode_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
|
@ -40,7 +40,7 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <linux/i2c/i2c-hid.h>
|
||||
#include <linux/platform_data/i2c-hid.h>
|
||||
|
||||
#include "../hid-ids.h"
|
||||
|
||||
|
@ -743,18 +743,12 @@ static int i2c_hid_open(struct hid_device *hid)
|
|||
struct i2c_hid *ihid = i2c_get_clientdata(client);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&i2c_hid_open_mut);
|
||||
if (!hid->open++) {
|
||||
ret = pm_runtime_get_sync(&client->dev);
|
||||
if (ret < 0) {
|
||||
hid->open--;
|
||||
goto done;
|
||||
}
|
||||
set_bit(I2C_HID_STARTED, &ihid->flags);
|
||||
}
|
||||
done:
|
||||
mutex_unlock(&i2c_hid_open_mut);
|
||||
return ret < 0 ? ret : 0;
|
||||
ret = pm_runtime_get_sync(&client->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
set_bit(I2C_HID_STARTED, &ihid->flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void i2c_hid_close(struct hid_device *hid)
|
||||
|
@ -762,18 +756,10 @@ static void i2c_hid_close(struct hid_device *hid)
|
|||
struct i2c_client *client = hid->driver_data;
|
||||
struct i2c_hid *ihid = i2c_get_clientdata(client);
|
||||
|
||||
/* protecting hid->open to make sure we don't restart
|
||||
* data acquistion due to a resumption we no longer
|
||||
* care about
|
||||
*/
|
||||
mutex_lock(&i2c_hid_open_mut);
|
||||
if (!--hid->open) {
|
||||
clear_bit(I2C_HID_STARTED, &ihid->flags);
|
||||
clear_bit(I2C_HID_STARTED, &ihid->flags);
|
||||
|
||||
/* Save some power */
|
||||
pm_runtime_put(&client->dev);
|
||||
}
|
||||
mutex_unlock(&i2c_hid_open_mut);
|
||||
/* Save some power */
|
||||
pm_runtime_put(&client->dev);
|
||||
}
|
||||
|
||||
static int i2c_hid_power(struct hid_device *hid, int lvl)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
menu "Intel ISH HID support"
|
||||
depends on X86_64 && PCI
|
||||
depends on (X86_64 || COMPILE_TEST) && PCI
|
||||
|
||||
config INTEL_ISH_HID
|
||||
tristate "Intel Integrated Sensor Hub"
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#define BXT_Bx_DEVICE_ID 0x1AA2
|
||||
#define APL_Ax_DEVICE_ID 0x5AA2
|
||||
#define SPT_Ax_DEVICE_ID 0x9D35
|
||||
#define CNL_Ax_DEVICE_ID 0x9DFC
|
||||
#define GLK_Ax_DEVICE_ID 0x31A2
|
||||
|
||||
#define REVISION_ID_CHT_A0 0x6
|
||||
#define REVISION_ID_CHT_Ax_SI 0x0
|
||||
|
|
|
@ -296,17 +296,12 @@ static int write_ipc_from_queue(struct ishtp_device *dev)
|
|||
/* If sending MNG_SYNC_FW_CLOCK, update clock again */
|
||||
if (IPC_HEADER_GET_PROTOCOL(doorbell_val) == IPC_PROTOCOL_MNG &&
|
||||
IPC_HEADER_GET_MNG_CMD(doorbell_val) == MNG_SYNC_FW_CLOCK) {
|
||||
struct timespec ts_system;
|
||||
struct timeval tv_utc;
|
||||
uint64_t usec_system, usec_utc;
|
||||
uint64_t usec_system, usec_utc;
|
||||
struct ipc_time_update_msg time_update;
|
||||
struct time_sync_format ts_format;
|
||||
|
||||
get_monotonic_boottime(&ts_system);
|
||||
do_gettimeofday(&tv_utc);
|
||||
usec_system = (timespec_to_ns(&ts_system)) / NSEC_PER_USEC;
|
||||
usec_utc = (uint64_t)tv_utc.tv_sec * 1000000 +
|
||||
((uint32_t)tv_utc.tv_usec);
|
||||
usec_system = ktime_to_us(ktime_get_boottime());
|
||||
usec_utc = ktime_to_us(ktime_get_real());
|
||||
ts_format.ts1_source = HOST_SYSTEM_TIME_USEC;
|
||||
ts_format.ts2_source = HOST_UTC_TIME_USEC;
|
||||
ts_format.reserved = 0;
|
||||
|
@ -575,15 +570,13 @@ static void fw_reset_work_fn(struct work_struct *unused)
|
|||
static void _ish_sync_fw_clock(struct ishtp_device *dev)
|
||||
{
|
||||
static unsigned long prev_sync;
|
||||
struct timespec ts;
|
||||
uint64_t usec;
|
||||
|
||||
if (prev_sync && jiffies - prev_sync < 20 * HZ)
|
||||
return;
|
||||
|
||||
prev_sync = jiffies;
|
||||
get_monotonic_boottime(&ts);
|
||||
usec = (timespec_to_ns(&ts)) / NSEC_PER_USEC;
|
||||
usec = ktime_to_us(ktime_get_boottime());
|
||||
ipc_send_mng_msg(dev, MNG_SYNC_FW_CLOCK, &usec, sizeof(uint64_t));
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@ static const struct pci_device_id ish_pci_tbl[] = {
|
|||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, BXT_Bx_DEVICE_ID)},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, APL_Ax_DEVICE_ID)},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_Ax_DEVICE_ID)},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, CNL_Ax_DEVICE_ID)},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, GLK_Ax_DEVICE_ID)},
|
||||
{0, }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
|
||||
|
|
|
@ -136,10 +136,9 @@ static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf,
|
|||
if (1 + sizeof(struct device_info) * i >=
|
||||
payload_len) {
|
||||
dev_err(&client_data->cl_device->dev,
|
||||
"[hid-ish]: [ENUM_DEVICES]: content size %lu is bigger than payload_len %u\n",
|
||||
"[hid-ish]: [ENUM_DEVICES]: content size %zu is bigger than payload_len %zu\n",
|
||||
1 + sizeof(struct device_info)
|
||||
* i,
|
||||
(unsigned int)payload_len);
|
||||
* i, payload_len);
|
||||
}
|
||||
|
||||
if (1 + sizeof(struct device_info) * i >=
|
||||
|
|
|
@ -803,7 +803,7 @@ void ishtp_cl_send_msg(struct ishtp_device *dev, struct ishtp_cl *cl)
|
|||
* @ishtp_hdr: Pointer to message header
|
||||
*
|
||||
* Receive and dispatch ISHTP client messages. This function executes in ISR
|
||||
* context
|
||||
* or work queue context
|
||||
*/
|
||||
void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
||||
struct ishtp_msg_hdr *ishtp_hdr)
|
||||
|
@ -813,7 +813,6 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
|||
struct ishtp_cl_rb *new_rb;
|
||||
unsigned char *buffer = NULL;
|
||||
struct ishtp_cl_rb *complete_rb = NULL;
|
||||
unsigned long dev_flags;
|
||||
unsigned long flags;
|
||||
int rb_count;
|
||||
|
||||
|
@ -828,7 +827,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
|||
goto eoi;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&dev->read_list_spinlock, dev_flags);
|
||||
spin_lock_irqsave(&dev->read_list_spinlock, flags);
|
||||
rb_count = -1;
|
||||
list_for_each_entry(rb, &dev->read_list.list, list) {
|
||||
++rb_count;
|
||||
|
@ -840,8 +839,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
|||
|
||||
/* If no Rx buffer is allocated, disband the rb */
|
||||
if (rb->buffer.size == 0 || rb->buffer.data == NULL) {
|
||||
spin_unlock_irqrestore(&dev->read_list_spinlock,
|
||||
dev_flags);
|
||||
spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
|
||||
dev_err(&cl->device->dev,
|
||||
"Rx buffer is not allocated.\n");
|
||||
list_del(&rb->list);
|
||||
|
@ -857,8 +855,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
|||
* back FC, so communication will be stuck anyway)
|
||||
*/
|
||||
if (rb->buffer.size < ishtp_hdr->length + rb->buf_idx) {
|
||||
spin_unlock_irqrestore(&dev->read_list_spinlock,
|
||||
dev_flags);
|
||||
spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
|
||||
dev_err(&cl->device->dev,
|
||||
"message overflow. size %d len %d idx %ld\n",
|
||||
rb->buffer.size, ishtp_hdr->length,
|
||||
|
@ -884,14 +881,13 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
|||
* the whole msg arrived, send a new FC, and add a new
|
||||
* rb buffer for the next coming msg
|
||||
*/
|
||||
spin_lock_irqsave(&cl->free_list_spinlock, flags);
|
||||
spin_lock(&cl->free_list_spinlock);
|
||||
|
||||
if (!list_empty(&cl->free_rb_list.list)) {
|
||||
new_rb = list_entry(cl->free_rb_list.list.next,
|
||||
struct ishtp_cl_rb, list);
|
||||
list_del_init(&new_rb->list);
|
||||
spin_unlock_irqrestore(&cl->free_list_spinlock,
|
||||
flags);
|
||||
spin_unlock(&cl->free_list_spinlock);
|
||||
new_rb->cl = cl;
|
||||
new_rb->buf_idx = 0;
|
||||
INIT_LIST_HEAD(&new_rb->list);
|
||||
|
@ -900,8 +896,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
|||
|
||||
ishtp_hbm_cl_flow_control_req(dev, cl);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&cl->free_list_spinlock,
|
||||
flags);
|
||||
spin_unlock(&cl->free_list_spinlock);
|
||||
}
|
||||
}
|
||||
/* One more fragment in message (even if this was last) */
|
||||
|
@ -914,7 +909,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
|||
break;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev->read_list_spinlock, dev_flags);
|
||||
spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
|
||||
/* If it's nobody's message, just read and discard it */
|
||||
if (!buffer) {
|
||||
uint8_t rd_msg_buf[ISHTP_RD_MSG_BUF_SIZE];
|
||||
|
@ -925,7 +920,8 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
|||
}
|
||||
|
||||
if (complete_rb) {
|
||||
getnstimeofday(&cl->ts_rx);
|
||||
cl = complete_rb->cl;
|
||||
cl->ts_rx = ktime_get();
|
||||
++cl->recv_msg_cnt_ipc;
|
||||
ishtp_cl_read_complete(complete_rb);
|
||||
}
|
||||
|
@ -940,7 +936,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
|
|||
* @hbm: hbm buffer
|
||||
*
|
||||
* Receive and dispatch ISHTP client messages using DMA. This function executes
|
||||
* in ISR context
|
||||
* in ISR or work queue context
|
||||
*/
|
||||
void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
|
||||
struct dma_xfer_hbm *hbm)
|
||||
|
@ -950,10 +946,10 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
|
|||
struct ishtp_cl_rb *new_rb;
|
||||
unsigned char *buffer = NULL;
|
||||
struct ishtp_cl_rb *complete_rb = NULL;
|
||||
unsigned long dev_flags;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dev->read_list_spinlock, dev_flags);
|
||||
spin_lock_irqsave(&dev->read_list_spinlock, flags);
|
||||
|
||||
list_for_each_entry(rb, &dev->read_list.list, list) {
|
||||
cl = rb->cl;
|
||||
if (!cl || !(cl->host_client_id == hbm->host_client_id &&
|
||||
|
@ -965,8 +961,7 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
|
|||
* If no Rx buffer is allocated, disband the rb
|
||||
*/
|
||||
if (rb->buffer.size == 0 || rb->buffer.data == NULL) {
|
||||
spin_unlock_irqrestore(&dev->read_list_spinlock,
|
||||
dev_flags);
|
||||
spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
|
||||
dev_err(&cl->device->dev,
|
||||
"response buffer is not allocated.\n");
|
||||
list_del(&rb->list);
|
||||
|
@ -982,8 +977,7 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
|
|||
* back FC, so communication will be stuck anyway)
|
||||
*/
|
||||
if (rb->buffer.size < hbm->msg_length) {
|
||||
spin_unlock_irqrestore(&dev->read_list_spinlock,
|
||||
dev_flags);
|
||||
spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
|
||||
dev_err(&cl->device->dev,
|
||||
"message overflow. size %d len %d idx %ld\n",
|
||||
rb->buffer.size, hbm->msg_length, rb->buf_idx);
|
||||
|
@ -1007,14 +1001,13 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
|
|||
* the whole msg arrived, send a new FC, and add a new
|
||||
* rb buffer for the next coming msg
|
||||
*/
|
||||
spin_lock_irqsave(&cl->free_list_spinlock, flags);
|
||||
spin_lock(&cl->free_list_spinlock);
|
||||
|
||||
if (!list_empty(&cl->free_rb_list.list)) {
|
||||
new_rb = list_entry(cl->free_rb_list.list.next,
|
||||
struct ishtp_cl_rb, list);
|
||||
list_del_init(&new_rb->list);
|
||||
spin_unlock_irqrestore(&cl->free_list_spinlock,
|
||||
flags);
|
||||
spin_unlock(&cl->free_list_spinlock);
|
||||
new_rb->cl = cl;
|
||||
new_rb->buf_idx = 0;
|
||||
INIT_LIST_HEAD(&new_rb->list);
|
||||
|
@ -1023,8 +1016,7 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
|
|||
|
||||
ishtp_hbm_cl_flow_control_req(dev, cl);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&cl->free_list_spinlock,
|
||||
flags);
|
||||
spin_unlock(&cl->free_list_spinlock);
|
||||
}
|
||||
|
||||
/* One more fragment in message (this is always last) */
|
||||
|
@ -1037,7 +1029,7 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
|
|||
break;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev->read_list_spinlock, dev_flags);
|
||||
spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
|
||||
/* If it's nobody's message, just read and discard it */
|
||||
if (!buffer) {
|
||||
dev_err(dev->devc, "Dropped Rx (DMA) msg - no request\n");
|
||||
|
@ -1045,7 +1037,8 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
|
|||
}
|
||||
|
||||
if (complete_rb) {
|
||||
getnstimeofday(&cl->ts_rx);
|
||||
cl = complete_rb->cl;
|
||||
cl->ts_rx = ktime_get();
|
||||
++cl->recv_msg_cnt_dma;
|
||||
ishtp_cl_read_complete(complete_rb);
|
||||
}
|
||||
|
|
|
@ -118,9 +118,9 @@ struct ishtp_cl {
|
|||
unsigned int out_flow_ctrl_cnt;
|
||||
|
||||
/* Rx msg ... out FC timing */
|
||||
struct timespec ts_rx;
|
||||
struct timespec ts_out_fc;
|
||||
struct timespec ts_max_fc_delay;
|
||||
ktime_t ts_rx;
|
||||
ktime_t ts_out_fc;
|
||||
ktime_t ts_max_fc_delay;
|
||||
void *client_data;
|
||||
};
|
||||
|
||||
|
|
|
@ -321,13 +321,10 @@ int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev,
|
|||
if (!rv) {
|
||||
++cl->out_flow_ctrl_creds;
|
||||
++cl->out_flow_ctrl_cnt;
|
||||
getnstimeofday(&cl->ts_out_fc);
|
||||
if (cl->ts_rx.tv_sec && cl->ts_rx.tv_nsec) {
|
||||
struct timespec ts_diff;
|
||||
|
||||
ts_diff = timespec_sub(cl->ts_out_fc, cl->ts_rx);
|
||||
if (timespec_compare(&ts_diff, &cl->ts_max_fc_delay)
|
||||
> 0)
|
||||
cl->ts_out_fc = ktime_get();
|
||||
if (cl->ts_rx) {
|
||||
ktime_t ts_diff = ktime_sub(cl->ts_out_fc, cl->ts_rx);
|
||||
if (ktime_after(ts_diff, cl->ts_max_fc_delay))
|
||||
cl->ts_max_fc_delay = ts_diff;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -70,8 +70,6 @@ MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying "
|
|||
/*
|
||||
* Input submission and I/O error handler.
|
||||
*/
|
||||
static DEFINE_MUTEX(hid_open_mut);
|
||||
|
||||
static void hid_io_error(struct hid_device *hid);
|
||||
static int hid_submit_out(struct hid_device *hid);
|
||||
static int hid_submit_ctrl(struct hid_device *hid);
|
||||
|
@ -85,10 +83,10 @@ static int hid_start_in(struct hid_device *hid)
|
|||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
|
||||
spin_lock_irqsave(&usbhid->lock, flags);
|
||||
if ((hid->open > 0 || hid->quirks & HID_QUIRK_ALWAYS_POLL) &&
|
||||
!test_bit(HID_DISCONNECTED, &usbhid->iofl) &&
|
||||
!test_bit(HID_SUSPENDED, &usbhid->iofl) &&
|
||||
!test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
|
||||
if (test_bit(HID_IN_POLLING, &usbhid->iofl) &&
|
||||
!test_bit(HID_DISCONNECTED, &usbhid->iofl) &&
|
||||
!test_bit(HID_SUSPENDED, &usbhid->iofl) &&
|
||||
!test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
|
||||
rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC);
|
||||
if (rc != 0) {
|
||||
clear_bit(HID_IN_RUNNING, &usbhid->iofl);
|
||||
|
@ -272,13 +270,13 @@ static int usbhid_restart_ctrl_queue(struct usbhid_device *usbhid)
|
|||
static void hid_irq_in(struct urb *urb)
|
||||
{
|
||||
struct hid_device *hid = urb->context;
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
int status;
|
||||
|
||||
switch (urb->status) {
|
||||
case 0: /* success */
|
||||
usbhid->retry_delay = 0;
|
||||
if ((hid->quirks & HID_QUIRK_ALWAYS_POLL) && !hid->open)
|
||||
if (!test_bit(HID_OPENED, &usbhid->iofl))
|
||||
break;
|
||||
usbhid_mark_busy(usbhid);
|
||||
if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
|
||||
|
@ -677,73 +675,74 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
|
|||
return result;
|
||||
}
|
||||
|
||||
int usbhid_open(struct hid_device *hid)
|
||||
static int usbhid_open(struct hid_device *hid)
|
||||
{
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
int res = 0;
|
||||
int res;
|
||||
|
||||
mutex_lock(&hid_open_mut);
|
||||
if (!hid->open++) {
|
||||
res = usb_autopm_get_interface(usbhid->intf);
|
||||
/* the device must be awake to reliably request remote wakeup */
|
||||
if (res < 0) {
|
||||
hid->open--;
|
||||
res = -EIO;
|
||||
goto done;
|
||||
}
|
||||
usbhid->intf->needs_remote_wakeup = 1;
|
||||
set_bit(HID_RESUME_RUNNING, &usbhid->iofl);
|
||||
res = hid_start_in(hid);
|
||||
if (res) {
|
||||
if (res != -ENOSPC) {
|
||||
hid_io_error(hid);
|
||||
res = 0;
|
||||
} else {
|
||||
/* no use opening if resources are insufficient */
|
||||
hid->open--;
|
||||
res = -EBUSY;
|
||||
usbhid->intf->needs_remote_wakeup = 0;
|
||||
}
|
||||
}
|
||||
usb_autopm_put_interface(usbhid->intf);
|
||||
if (hid->quirks & HID_QUIRK_ALWAYS_POLL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* In case events are generated while nobody was listening,
|
||||
* some are released when the device is re-opened.
|
||||
* Wait 50 msec for the queue to empty before allowing events
|
||||
* to go through hid.
|
||||
*/
|
||||
if (res == 0 && !(hid->quirks & HID_QUIRK_ALWAYS_POLL))
|
||||
msleep(50);
|
||||
clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
|
||||
res = usb_autopm_get_interface(usbhid->intf);
|
||||
/* the device must be awake to reliably request remote wakeup */
|
||||
if (res < 0)
|
||||
return -EIO;
|
||||
|
||||
usbhid->intf->needs_remote_wakeup = 1;
|
||||
|
||||
set_bit(HID_RESUME_RUNNING, &usbhid->iofl);
|
||||
set_bit(HID_OPENED, &usbhid->iofl);
|
||||
set_bit(HID_IN_POLLING, &usbhid->iofl);
|
||||
|
||||
res = hid_start_in(hid);
|
||||
if (res) {
|
||||
if (res != -ENOSPC) {
|
||||
hid_io_error(hid);
|
||||
res = 0;
|
||||
} else {
|
||||
/* no use opening if resources are insufficient */
|
||||
res = -EBUSY;
|
||||
clear_bit(HID_OPENED, &usbhid->iofl);
|
||||
clear_bit(HID_IN_POLLING, &usbhid->iofl);
|
||||
usbhid->intf->needs_remote_wakeup = 0;
|
||||
}
|
||||
}
|
||||
done:
|
||||
mutex_unlock(&hid_open_mut);
|
||||
|
||||
usb_autopm_put_interface(usbhid->intf);
|
||||
|
||||
/*
|
||||
* In case events are generated while nobody was listening,
|
||||
* some are released when the device is re-opened.
|
||||
* Wait 50 msec for the queue to empty before allowing events
|
||||
* to go through hid.
|
||||
*/
|
||||
if (res == 0)
|
||||
msleep(50);
|
||||
|
||||
clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
|
||||
return res;
|
||||
}
|
||||
|
||||
void usbhid_close(struct hid_device *hid)
|
||||
static void usbhid_close(struct hid_device *hid)
|
||||
{
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
|
||||
mutex_lock(&hid_open_mut);
|
||||
if (hid->quirks & HID_QUIRK_ALWAYS_POLL)
|
||||
return;
|
||||
|
||||
/* protecting hid->open to make sure we don't restart
|
||||
* data acquistion due to a resumption we no longer
|
||||
* care about
|
||||
/*
|
||||
* Make sure we don't restart data acquisition due to
|
||||
* a resumption we no longer care about by avoiding racing
|
||||
* with hid_start_in().
|
||||
*/
|
||||
spin_lock_irq(&usbhid->lock);
|
||||
if (!--hid->open) {
|
||||
spin_unlock_irq(&usbhid->lock);
|
||||
hid_cancel_delayed_stuff(usbhid);
|
||||
if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL)) {
|
||||
usb_kill_urb(usbhid->urbin);
|
||||
usbhid->intf->needs_remote_wakeup = 0;
|
||||
}
|
||||
} else {
|
||||
spin_unlock_irq(&usbhid->lock);
|
||||
}
|
||||
mutex_unlock(&hid_open_mut);
|
||||
clear_bit(HID_IN_POLLING, &usbhid->iofl);
|
||||
clear_bit(HID_OPENED, &usbhid->iofl);
|
||||
spin_unlock_irq(&usbhid->lock);
|
||||
|
||||
hid_cancel_delayed_stuff(usbhid);
|
||||
usb_kill_urb(usbhid->urbin);
|
||||
usbhid->intf->needs_remote_wakeup = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1135,6 +1134,7 @@ static int usbhid_start(struct hid_device *hid)
|
|||
ret = usb_autopm_get_interface(usbhid->intf);
|
||||
if (ret)
|
||||
goto fail;
|
||||
set_bit(HID_IN_POLLING, &usbhid->iofl);
|
||||
usbhid->intf->needs_remote_wakeup = 1;
|
||||
ret = hid_start_in(hid);
|
||||
if (ret) {
|
||||
|
@ -1176,8 +1176,10 @@ static void usbhid_stop(struct hid_device *hid)
|
|||
if (WARN_ON(!usbhid))
|
||||
return;
|
||||
|
||||
if (hid->quirks & HID_QUIRK_ALWAYS_POLL)
|
||||
if (hid->quirks & HID_QUIRK_ALWAYS_POLL) {
|
||||
clear_bit(HID_IN_POLLING, &usbhid->iofl);
|
||||
usbhid->intf->needs_remote_wakeup = 0;
|
||||
}
|
||||
|
||||
clear_bit(HID_STARTED, &usbhid->iofl);
|
||||
spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */
|
||||
|
@ -1203,16 +1205,19 @@ static void usbhid_stop(struct hid_device *hid)
|
|||
|
||||
static int usbhid_power(struct hid_device *hid, int lvl)
|
||||
{
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
int r = 0;
|
||||
|
||||
switch (lvl) {
|
||||
case PM_HINT_FULLON:
|
||||
r = usbhid_get_power(hid);
|
||||
r = usb_autopm_get_interface(usbhid->intf);
|
||||
break;
|
||||
|
||||
case PM_HINT_NORMAL:
|
||||
usbhid_put_power(hid);
|
||||
usb_autopm_put_interface(usbhid->intf);
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -1492,21 +1497,6 @@ static int hid_post_reset(struct usb_interface *intf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int usbhid_get_power(struct hid_device *hid)
|
||||
{
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
|
||||
return usb_autopm_get_interface(usbhid->intf);
|
||||
}
|
||||
|
||||
void usbhid_put_power(struct hid_device *hid)
|
||||
{
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
|
||||
usb_autopm_put_interface(usbhid->intf);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int hid_resume_common(struct hid_device *hid, bool driver_suspended)
|
||||
{
|
||||
|
|
|
@ -237,8 +237,8 @@ static int hiddev_release(struct inode * inode, struct file * file)
|
|||
mutex_lock(&list->hiddev->existancelock);
|
||||
if (!--list->hiddev->open) {
|
||||
if (list->hiddev->exist) {
|
||||
usbhid_close(list->hiddev->hid);
|
||||
usbhid_put_power(list->hiddev->hid);
|
||||
hid_hw_close(list->hiddev->hid);
|
||||
hid_hw_power(list->hiddev->hid, PM_HINT_NORMAL);
|
||||
} else {
|
||||
mutex_unlock(&list->hiddev->existancelock);
|
||||
kfree(list->hiddev);
|
||||
|
@ -282,11 +282,9 @@ static int hiddev_open(struct inode *inode, struct file *file)
|
|||
*/
|
||||
if (list->hiddev->exist) {
|
||||
if (!list->hiddev->open++) {
|
||||
res = usbhid_open(hiddev->hid);
|
||||
if (res < 0) {
|
||||
res = -EIO;
|
||||
res = hid_hw_open(hiddev->hid);
|
||||
if (res < 0)
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = -ENODEV;
|
||||
|
@ -301,15 +299,17 @@ static int hiddev_open(struct inode *inode, struct file *file)
|
|||
if (!list->hiddev->open++)
|
||||
if (list->hiddev->exist) {
|
||||
struct hid_device *hid = hiddev->hid;
|
||||
res = usbhid_get_power(hid);
|
||||
if (res < 0) {
|
||||
res = -EIO;
|
||||
res = hid_hw_power(hid, PM_HINT_FULLON);
|
||||
if (res < 0)
|
||||
goto bail_unlock;
|
||||
}
|
||||
usbhid_open(hid);
|
||||
res = hid_hw_open(hid);
|
||||
if (res < 0)
|
||||
goto bail_normal_power;
|
||||
}
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
return 0;
|
||||
bail_normal_power:
|
||||
hid_hw_power(hid, PM_HINT_NORMAL);
|
||||
bail_unlock:
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
bail:
|
||||
|
@ -935,7 +935,7 @@ void hiddev_disconnect(struct hid_device *hid)
|
|||
|
||||
if (hiddev->open) {
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
usbhid_close(hiddev->hid);
|
||||
hid_hw_close(hiddev->hid);
|
||||
wake_up_interruptible(&hiddev->wait);
|
||||
} else {
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
|
|
|
@ -34,11 +34,7 @@
|
|||
#include <linux/input.h>
|
||||
|
||||
/* API provided by hid-core.c for USB HID drivers */
|
||||
void usbhid_close(struct hid_device *hid);
|
||||
int usbhid_open(struct hid_device *hid);
|
||||
void usbhid_init_reports(struct hid_device *hid);
|
||||
int usbhid_get_power(struct hid_device *hid);
|
||||
void usbhid_put_power(struct hid_device *hid);
|
||||
struct usb_interface *usbhid_find_interface(int minor);
|
||||
|
||||
/* iofl flags */
|
||||
|
@ -53,6 +49,17 @@ struct usb_interface *usbhid_find_interface(int minor);
|
|||
#define HID_KEYS_PRESSED 10
|
||||
#define HID_NO_BANDWIDTH 11
|
||||
#define HID_RESUME_RUNNING 12
|
||||
/*
|
||||
* The device is opened, meaning there is a client that is interested
|
||||
* in data coming from the device.
|
||||
*/
|
||||
#define HID_OPENED 13
|
||||
/*
|
||||
* We are polling input endpoint by [re]submitting IN URB, because
|
||||
* either HID device is opened or ALWAYS POLL quirk is set for the
|
||||
* device.
|
||||
*/
|
||||
#define HID_IN_POLLING 14
|
||||
|
||||
/*
|
||||
* USB-specific HID struct, to be pointed to
|
||||
|
|
|
@ -138,6 +138,7 @@ struct wacom_battery {
|
|||
struct power_supply_desc bat_desc;
|
||||
struct power_supply *battery;
|
||||
char bat_name[WACOM_NAME_MAX];
|
||||
int bat_status;
|
||||
int battery_capacity;
|
||||
int bat_charging;
|
||||
int bat_connected;
|
||||
|
|
|
@ -1547,7 +1547,9 @@ static int wacom_battery_get_property(struct power_supply *psy,
|
|||
val->intval = battery->battery_capacity;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
if (battery->bat_charging)
|
||||
if (battery->bat_status != WACOM_POWER_SUPPLY_STATUS_AUTO)
|
||||
val->intval = battery->bat_status;
|
||||
else if (battery->bat_charging)
|
||||
val->intval = POWER_SUPPLY_STATUS_CHARGING;
|
||||
else if (battery->battery_capacity == 100 &&
|
||||
battery->ps_connected)
|
||||
|
|
|
@ -57,15 +57,18 @@ static unsigned short batcap_gr[8] = { 1, 15, 25, 35, 50, 70, 100, 100 };
|
|||
static unsigned short batcap_i4[8] = { 1, 15, 30, 45, 60, 70, 85, 100 };
|
||||
|
||||
static void __wacom_notify_battery(struct wacom_battery *battery,
|
||||
int bat_capacity, bool bat_charging,
|
||||
bool bat_connected, bool ps_connected)
|
||||
int bat_status, int bat_capacity,
|
||||
bool bat_charging, bool bat_connected,
|
||||
bool ps_connected)
|
||||
{
|
||||
bool changed = battery->battery_capacity != bat_capacity ||
|
||||
bool changed = battery->bat_status != bat_status ||
|
||||
battery->battery_capacity != bat_capacity ||
|
||||
battery->bat_charging != bat_charging ||
|
||||
battery->bat_connected != bat_connected ||
|
||||
battery->ps_connected != ps_connected;
|
||||
|
||||
if (changed) {
|
||||
battery->bat_status = bat_status;
|
||||
battery->battery_capacity = bat_capacity;
|
||||
battery->bat_charging = bat_charging;
|
||||
battery->bat_connected = bat_connected;
|
||||
|
@ -77,13 +80,13 @@ static void __wacom_notify_battery(struct wacom_battery *battery,
|
|||
}
|
||||
|
||||
static void wacom_notify_battery(struct wacom_wac *wacom_wac,
|
||||
int bat_capacity, bool bat_charging, bool bat_connected,
|
||||
bool ps_connected)
|
||||
int bat_status, int bat_capacity, bool bat_charging,
|
||||
bool bat_connected, bool ps_connected)
|
||||
{
|
||||
struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
|
||||
|
||||
__wacom_notify_battery(&wacom->battery, bat_capacity, bat_charging,
|
||||
bat_connected, ps_connected);
|
||||
__wacom_notify_battery(&wacom->battery, bat_status, bat_capacity,
|
||||
bat_charging, bat_connected, ps_connected);
|
||||
}
|
||||
|
||||
static int wacom_penpartner_irq(struct wacom_wac *wacom)
|
||||
|
@ -448,8 +451,9 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
|
|||
rw = (data[7] >> 2 & 0x07);
|
||||
battery_capacity = batcap_gr[rw];
|
||||
ps_connected = rw == 7;
|
||||
wacom_notify_battery(wacom, battery_capacity, ps_connected,
|
||||
1, ps_connected);
|
||||
wacom_notify_battery(wacom, WACOM_POWER_SUPPLY_STATUS_AUTO,
|
||||
battery_capacity, ps_connected, 1,
|
||||
ps_connected);
|
||||
}
|
||||
exit:
|
||||
return retval;
|
||||
|
@ -1071,7 +1075,8 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len)
|
|||
wacom->led.groups[i].select = touch_ring_mode;
|
||||
}
|
||||
|
||||
__wacom_notify_battery(&remote->remotes[index].battery, bat_percent,
|
||||
__wacom_notify_battery(&remote->remotes[index].battery,
|
||||
WACOM_POWER_SUPPLY_STATUS_AUTO, bat_percent,
|
||||
bat_charging, 1, bat_charging);
|
||||
|
||||
out:
|
||||
|
@ -1157,7 +1162,8 @@ static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len)
|
|||
bat_charging = (power_raw & 0x08) ? 1 : 0;
|
||||
ps_connected = (power_raw & 0x10) ? 1 : 0;
|
||||
battery_capacity = batcap_i4[power_raw & 0x07];
|
||||
wacom_notify_battery(wacom, battery_capacity, bat_charging,
|
||||
wacom_notify_battery(wacom, WACOM_POWER_SUPPLY_STATUS_AUTO,
|
||||
battery_capacity, bat_charging,
|
||||
battery_capacity || bat_charging,
|
||||
ps_connected);
|
||||
break;
|
||||
|
@ -1334,7 +1340,8 @@ static void wacom_intuos_pro2_bt_battery(struct wacom_wac *wacom)
|
|||
bool chg = data[284] & 0x80;
|
||||
int battery_status = data[284] & 0x7F;
|
||||
|
||||
wacom_notify_battery(wacom, battery_status, chg, 1, chg);
|
||||
wacom_notify_battery(wacom, WACOM_POWER_SUPPLY_STATUS_AUTO,
|
||||
battery_status, chg, 1, chg);
|
||||
}
|
||||
|
||||
static int wacom_intuos_pro2_bt_irq(struct wacom_wac *wacom, size_t len)
|
||||
|
@ -1696,6 +1703,82 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
|
|||
}
|
||||
}
|
||||
|
||||
static void wacom_wac_battery_usage_mapping(struct hid_device *hdev,
|
||||
struct hid_field *field, struct hid_usage *usage)
|
||||
{
|
||||
struct wacom *wacom = hid_get_drvdata(hdev);
|
||||
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
|
||||
struct wacom_features *features = &wacom_wac->features;
|
||||
unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
|
||||
|
||||
switch (equivalent_usage) {
|
||||
case HID_DG_BATTERYSTRENGTH:
|
||||
case WACOM_HID_WD_BATTERY_LEVEL:
|
||||
case WACOM_HID_WD_BATTERY_CHARGING:
|
||||
features->quirks |= WACOM_QUIRK_BATTERY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void wacom_wac_battery_event(struct hid_device *hdev, struct hid_field *field,
|
||||
struct hid_usage *usage, __s32 value)
|
||||
{
|
||||
struct wacom *wacom = hid_get_drvdata(hdev);
|
||||
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
|
||||
unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
|
||||
|
||||
switch (equivalent_usage) {
|
||||
case HID_DG_BATTERYSTRENGTH:
|
||||
if (value == 0) {
|
||||
wacom_wac->hid_data.bat_status = POWER_SUPPLY_STATUS_UNKNOWN;
|
||||
}
|
||||
else {
|
||||
value = value * 100 / (field->logical_maximum - field->logical_minimum);
|
||||
wacom_wac->hid_data.battery_capacity = value;
|
||||
wacom_wac->hid_data.bat_connected = 1;
|
||||
wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO;
|
||||
}
|
||||
break;
|
||||
case WACOM_HID_WD_BATTERY_LEVEL:
|
||||
value = value * 100 / (field->logical_maximum - field->logical_minimum);
|
||||
wacom_wac->hid_data.battery_capacity = value;
|
||||
wacom_wac->hid_data.bat_connected = 1;
|
||||
wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO;
|
||||
break;
|
||||
case WACOM_HID_WD_BATTERY_CHARGING:
|
||||
wacom_wac->hid_data.bat_charging = value;
|
||||
wacom_wac->hid_data.ps_connected = value;
|
||||
wacom_wac->hid_data.bat_connected = 1;
|
||||
wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void wacom_wac_battery_pre_report(struct hid_device *hdev,
|
||||
struct hid_report *report)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void wacom_wac_battery_report(struct hid_device *hdev,
|
||||
struct hid_report *report)
|
||||
{
|
||||
struct wacom *wacom = hid_get_drvdata(hdev);
|
||||
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
|
||||
struct wacom_features *features = &wacom_wac->features;
|
||||
|
||||
if (features->quirks & WACOM_QUIRK_BATTERY) {
|
||||
int status = wacom_wac->hid_data.bat_status;
|
||||
int capacity = wacom_wac->hid_data.battery_capacity;
|
||||
bool charging = wacom_wac->hid_data.bat_charging;
|
||||
bool connected = wacom_wac->hid_data.bat_connected;
|
||||
bool powered = wacom_wac->hid_data.ps_connected;
|
||||
|
||||
wacom_notify_battery(wacom_wac, status, capacity, charging,
|
||||
connected, powered);
|
||||
}
|
||||
}
|
||||
|
||||
static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
|
||||
struct hid_field *field, struct hid_usage *usage)
|
||||
{
|
||||
|
@ -1706,10 +1789,6 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
|
|||
unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
|
||||
|
||||
switch (equivalent_usage) {
|
||||
case WACOM_HID_WD_BATTERY_LEVEL:
|
||||
case WACOM_HID_WD_BATTERY_CHARGING:
|
||||
features->quirks |= WACOM_QUIRK_BATTERY;
|
||||
break;
|
||||
case WACOM_HID_WD_ACCELEROMETER_X:
|
||||
__set_bit(INPUT_PROP_ACCELEROMETER, input->propbit);
|
||||
wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 0);
|
||||
|
@ -1803,27 +1882,6 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
|
|||
}
|
||||
}
|
||||
|
||||
static void wacom_wac_pad_battery_event(struct hid_device *hdev, struct hid_field *field,
|
||||
struct hid_usage *usage, __s32 value)
|
||||
{
|
||||
struct wacom *wacom = hid_get_drvdata(hdev);
|
||||
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
|
||||
unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
|
||||
|
||||
switch (equivalent_usage) {
|
||||
case WACOM_HID_WD_BATTERY_LEVEL:
|
||||
wacom_wac->hid_data.battery_capacity = value;
|
||||
wacom_wac->hid_data.bat_connected = 1;
|
||||
break;
|
||||
|
||||
case WACOM_HID_WD_BATTERY_CHARGING:
|
||||
wacom_wac->hid_data.bat_charging = value;
|
||||
wacom_wac->hid_data.ps_connected = value;
|
||||
wacom_wac->hid_data.bat_connected = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field,
|
||||
struct hid_usage *usage, __s32 value)
|
||||
{
|
||||
|
@ -1897,24 +1955,6 @@ static void wacom_wac_pad_pre_report(struct hid_device *hdev,
|
|||
wacom_wac->hid_data.inrange_state = 0;
|
||||
}
|
||||
|
||||
static void wacom_wac_pad_battery_report(struct hid_device *hdev,
|
||||
struct hid_report *report)
|
||||
{
|
||||
struct wacom *wacom = hid_get_drvdata(hdev);
|
||||
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
|
||||
struct wacom_features *features = &wacom_wac->features;
|
||||
|
||||
if (features->quirks & WACOM_QUIRK_BATTERY) {
|
||||
int capacity = wacom_wac->hid_data.battery_capacity;
|
||||
bool charging = wacom_wac->hid_data.bat_charging;
|
||||
bool connected = wacom_wac->hid_data.bat_connected;
|
||||
bool powered = wacom_wac->hid_data.ps_connected;
|
||||
|
||||
wacom_notify_battery(wacom_wac, capacity, charging,
|
||||
connected, powered);
|
||||
}
|
||||
}
|
||||
|
||||
static void wacom_wac_pad_report(struct hid_device *hdev,
|
||||
struct hid_report *report)
|
||||
{
|
||||
|
@ -1960,9 +2000,6 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
|
|||
case HID_DG_INRANGE:
|
||||
wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
|
||||
break;
|
||||
case HID_DG_BATTERYSTRENGTH:
|
||||
features->quirks |= WACOM_QUIRK_BATTERY;
|
||||
break;
|
||||
case HID_DG_INVERT:
|
||||
wacom_map_usage(input, usage, field, EV_KEY,
|
||||
BTN_TOOL_RUBBER, 0);
|
||||
|
@ -2035,10 +2072,6 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
|
|||
if (!(features->quirks & WACOM_QUIRK_SENSE))
|
||||
wacom_wac->hid_data.sense_state = value;
|
||||
return;
|
||||
case HID_DG_BATTERYSTRENGTH:
|
||||
wacom_wac->hid_data.battery_capacity = value;
|
||||
wacom_wac->hid_data.bat_connected = 1;
|
||||
break;
|
||||
case HID_DG_INVERT:
|
||||
wacom_wac->hid_data.invert_state = value;
|
||||
return;
|
||||
|
@ -2077,28 +2110,28 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
|
|||
return;
|
||||
case WACOM_HID_WD_OFFSETLEFT:
|
||||
if (features->offset_left && value != features->offset_left)
|
||||
hid_warn(hdev, "%s: overriding exising left offset "
|
||||
hid_warn(hdev, "%s: overriding existing left offset "
|
||||
"%d -> %d\n", __func__, value,
|
||||
features->offset_left);
|
||||
features->offset_left = value;
|
||||
return;
|
||||
case WACOM_HID_WD_OFFSETRIGHT:
|
||||
if (features->offset_right && value != features->offset_right)
|
||||
hid_warn(hdev, "%s: overriding exising right offset "
|
||||
hid_warn(hdev, "%s: overriding existing right offset "
|
||||
"%d -> %d\n", __func__, value,
|
||||
features->offset_right);
|
||||
features->offset_right = value;
|
||||
return;
|
||||
case WACOM_HID_WD_OFFSETTOP:
|
||||
if (features->offset_top && value != features->offset_top)
|
||||
hid_warn(hdev, "%s: overriding exising top offset "
|
||||
hid_warn(hdev, "%s: overriding existing top offset "
|
||||
"%d -> %d\n", __func__, value,
|
||||
features->offset_top);
|
||||
features->offset_top = value;
|
||||
return;
|
||||
case WACOM_HID_WD_OFFSETBOTTOM:
|
||||
if (features->offset_bottom && value != features->offset_bottom)
|
||||
hid_warn(hdev, "%s: overriding exising bottom offset "
|
||||
hid_warn(hdev, "%s: overriding existing bottom offset "
|
||||
"%d -> %d\n", __func__, value,
|
||||
features->offset_bottom);
|
||||
features->offset_bottom = value;
|
||||
|
@ -2395,7 +2428,10 @@ void wacom_wac_usage_mapping(struct hid_device *hdev,
|
|||
if (WACOM_DIRECT_DEVICE(field))
|
||||
features->device_type |= WACOM_DEVICETYPE_DIRECT;
|
||||
|
||||
if (WACOM_PAD_FIELD(field))
|
||||
/* usage tests must precede field tests */
|
||||
if (WACOM_BATTERY_USAGE(usage))
|
||||
wacom_wac_battery_usage_mapping(hdev, field, usage);
|
||||
else if (WACOM_PAD_FIELD(field))
|
||||
wacom_wac_pad_usage_mapping(hdev, field, usage);
|
||||
else if (WACOM_PEN_FIELD(field))
|
||||
wacom_wac_pen_usage_mapping(hdev, field, usage);
|
||||
|
@ -2414,11 +2450,12 @@ void wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
|
|||
if (value > field->logical_maximum || value < field->logical_minimum)
|
||||
return;
|
||||
|
||||
if (WACOM_PAD_FIELD(field)) {
|
||||
wacom_wac_pad_battery_event(hdev, field, usage, value);
|
||||
if (wacom->wacom_wac.pad_input)
|
||||
wacom_wac_pad_event(hdev, field, usage, value);
|
||||
} else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
|
||||
/* usage tests must precede field tests */
|
||||
if (WACOM_BATTERY_USAGE(usage))
|
||||
wacom_wac_battery_event(hdev, field, usage, value);
|
||||
else if (WACOM_PAD_FIELD(field) && wacom->wacom_wac.pad_input)
|
||||
wacom_wac_pad_event(hdev, field, usage, value);
|
||||
else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
|
||||
wacom_wac_pen_event(hdev, field, usage, value);
|
||||
else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input)
|
||||
wacom_wac_finger_event(hdev, field, usage, value);
|
||||
|
@ -2452,6 +2489,8 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
|
|||
if (wacom_wac->features.type != HID_GENERIC)
|
||||
return;
|
||||
|
||||
wacom_wac_battery_pre_report(hdev, report);
|
||||
|
||||
if (WACOM_PAD_FIELD(field) && wacom->wacom_wac.pad_input)
|
||||
wacom_wac_pad_pre_report(hdev, report);
|
||||
else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
|
||||
|
@ -2471,11 +2510,11 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
|
|||
if (report->type != HID_INPUT_REPORT)
|
||||
return;
|
||||
|
||||
if (WACOM_PAD_FIELD(field)) {
|
||||
wacom_wac_pad_battery_report(hdev, report);
|
||||
if (wacom->wacom_wac.pad_input)
|
||||
wacom_wac_pad_report(hdev, report);
|
||||
} else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
|
||||
wacom_wac_battery_report(hdev, report);
|
||||
|
||||
if (WACOM_PAD_FIELD(field) && wacom->wacom_wac.pad_input)
|
||||
wacom_wac_pad_report(hdev, report);
|
||||
else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
|
||||
wacom_wac_pen_report(hdev, report);
|
||||
else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input)
|
||||
wacom_wac_finger_report(hdev, report);
|
||||
|
@ -2813,13 +2852,14 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
|
|||
wacom_schedule_work(wacom, WACOM_WORKER_WIRELESS);
|
||||
}
|
||||
|
||||
wacom_notify_battery(wacom, battery, charging, 1, 0);
|
||||
wacom_notify_battery(wacom, WACOM_POWER_SUPPLY_STATUS_AUTO,
|
||||
battery, charging, 1, 0);
|
||||
|
||||
} else if (wacom->pid != 0) {
|
||||
/* disconnected while previously connected */
|
||||
wacom->pid = 0;
|
||||
wacom_schedule_work(wacom, WACOM_WORKER_WIRELESS);
|
||||
wacom_notify_battery(wacom, 0, 0, 0, 0);
|
||||
wacom_notify_battery(wacom, POWER_SUPPLY_STATUS_UNKNOWN, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -2847,8 +2887,8 @@ static int wacom_status_irq(struct wacom_wac *wacom_wac, size_t len)
|
|||
int battery = (data[8] & 0x3f) * 100 / 31;
|
||||
bool charging = !!(data[8] & 0x80);
|
||||
|
||||
wacom_notify_battery(wacom_wac, battery, charging,
|
||||
battery || charging, 1);
|
||||
wacom_notify_battery(wacom_wac, WACOM_POWER_SUPPLY_STATUS_AUTO,
|
||||
battery, charging, battery || charging, 1);
|
||||
|
||||
if (!wacom->battery.battery &&
|
||||
!(features->quirks & WACOM_QUIRK_BATTERY)) {
|
||||
|
@ -2860,7 +2900,7 @@ static int wacom_status_irq(struct wacom_wac *wacom_wac, size_t len)
|
|||
wacom->battery.battery) {
|
||||
features->quirks &= ~WACOM_QUIRK_BATTERY;
|
||||
wacom_schedule_work(wacom_wac, WACOM_WORKER_BATTERY);
|
||||
wacom_notify_battery(wacom_wac, 0, 0, 0, 0);
|
||||
wacom_notify_battery(wacom_wac, POWER_SUPPLY_STATUS_UNKNOWN, 0, 0, 0, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -96,6 +96,8 @@
|
|||
#define WACOM_DEVICETYPE_WL_MONITOR 0x0008
|
||||
#define WACOM_DEVICETYPE_DIRECT 0x0010
|
||||
|
||||
#define WACOM_POWER_SUPPLY_STATUS_AUTO -1
|
||||
|
||||
#define WACOM_HID_UP_WACOMDIGITIZER 0xff0d0000
|
||||
#define WACOM_HID_SP_PAD 0x00040000
|
||||
#define WACOM_HID_SP_BUTTON 0x00090000
|
||||
|
@ -151,6 +153,10 @@
|
|||
#define WACOM_HID_WT_X (WACOM_HID_UP_WACOMTOUCH | 0x130)
|
||||
#define WACOM_HID_WT_Y (WACOM_HID_UP_WACOMTOUCH | 0x131)
|
||||
|
||||
#define WACOM_BATTERY_USAGE(f) (((f)->hid == HID_DG_BATTERYSTRENGTH) || \
|
||||
((f)->hid == WACOM_HID_WD_BATTERY_CHARGING) || \
|
||||
((f)->hid == WACOM_HID_WD_BATTERY_LEVEL))
|
||||
|
||||
#define WACOM_PAD_FIELD(f) (((f)->physical == HID_DG_TABLETFUNCTIONKEY) || \
|
||||
((f)->physical == WACOM_HID_WD_DIGITIZERFNKEYS) || \
|
||||
((f)->physical == WACOM_HID_WD_DIGITIZERINFO))
|
||||
|
@ -297,6 +303,7 @@ struct hid_data {
|
|||
int last_slot_field;
|
||||
int num_expected;
|
||||
int num_received;
|
||||
int bat_status;
|
||||
int battery_capacity;
|
||||
int bat_charging;
|
||||
int bat_connected;
|
||||
|
|
|
@ -32,8 +32,6 @@ struct gb_hid {
|
|||
char *inbuf;
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(gb_hid_open_mutex);
|
||||
|
||||
/* Routines to get controller's information over greybus */
|
||||
|
||||
/* Operations performed on greybus */
|
||||
|
@ -346,19 +344,14 @@ static void gb_hid_stop(struct hid_device *hid)
|
|||
static int gb_hid_open(struct hid_device *hid)
|
||||
{
|
||||
struct gb_hid *ghid = hid->driver_data;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&gb_hid_open_mutex);
|
||||
if (!hid->open++) {
|
||||
ret = gb_hid_set_power(ghid, GB_HID_TYPE_PWR_ON);
|
||||
if (ret < 0)
|
||||
hid->open--;
|
||||
else
|
||||
set_bit(GB_HID_STARTED, &ghid->flags);
|
||||
}
|
||||
mutex_unlock(&gb_hid_open_mutex);
|
||||
ret = gb_hid_set_power(ghid, GB_HID_TYPE_PWR_ON);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
set_bit(GB_HID_STARTED, &ghid->flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gb_hid_close(struct hid_device *hid)
|
||||
|
@ -366,21 +359,13 @@ static void gb_hid_close(struct hid_device *hid)
|
|||
struct gb_hid *ghid = hid->driver_data;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Protecting hid->open to make sure we don't restart data acquistion
|
||||
* due to a resumption we no longer care about..
|
||||
*/
|
||||
mutex_lock(&gb_hid_open_mutex);
|
||||
if (!--hid->open) {
|
||||
clear_bit(GB_HID_STARTED, &ghid->flags);
|
||||
clear_bit(GB_HID_STARTED, &ghid->flags);
|
||||
|
||||
/* Save some power */
|
||||
ret = gb_hid_set_power(ghid, GB_HID_TYPE_PWR_OFF);
|
||||
if (ret)
|
||||
dev_err(&ghid->connection->bundle->dev,
|
||||
"failed to power off (%d)\n", ret);
|
||||
}
|
||||
mutex_unlock(&gb_hid_open_mutex);
|
||||
/* Save some power */
|
||||
ret = gb_hid_set_power(ghid, GB_HID_TYPE_PWR_OFF);
|
||||
if (ret)
|
||||
dev_err(&ghid->connection->bundle->dev,
|
||||
"failed to power off (%d)\n", ret);
|
||||
}
|
||||
|
||||
static int gb_hid_power(struct hid_device *hid, int lvl)
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <linux/workqueue.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <uapi/linux/hid.h>
|
||||
|
||||
|
@ -182,6 +183,11 @@ struct hid_item {
|
|||
#define HID_GD_KEYBOARD 0x00010006
|
||||
#define HID_GD_KEYPAD 0x00010007
|
||||
#define HID_GD_MULTIAXIS 0x00010008
|
||||
/*
|
||||
* Microsoft Win8 Wireless Radio Controls extensions CA, see:
|
||||
* http://www.usb.org/developers/hidpage/HUTRR40RadioHIDUsagesFinal.pdf
|
||||
*/
|
||||
#define HID_GD_WIRELESS_RADIO_CTLS 0x0001000c
|
||||
#define HID_GD_X 0x00010030
|
||||
#define HID_GD_Y 0x00010031
|
||||
#define HID_GD_Z 0x00010032
|
||||
|
@ -210,6 +216,10 @@ struct hid_item {
|
|||
#define HID_GD_DOWN 0x00010091
|
||||
#define HID_GD_RIGHT 0x00010092
|
||||
#define HID_GD_LEFT 0x00010093
|
||||
/* Microsoft Win8 Wireless Radio Controls CA usage codes */
|
||||
#define HID_GD_RFKILL_BTN 0x000100c6
|
||||
#define HID_GD_RFKILL_LED 0x000100c7
|
||||
#define HID_GD_RFKILL_SWITCH 0x000100c8
|
||||
|
||||
#define HID_DC_BATTERYSTRENGTH 0x00060020
|
||||
|
||||
|
@ -520,7 +530,10 @@ struct hid_device { /* device report descriptor */
|
|||
struct semaphore driver_input_lock; /* protects the current driver */
|
||||
struct device dev; /* device */
|
||||
struct hid_driver *driver;
|
||||
|
||||
struct hid_ll_driver *ll_driver;
|
||||
struct mutex ll_open_lock;
|
||||
unsigned int ll_open_count;
|
||||
|
||||
#ifdef CONFIG_HID_BATTERY_STRENGTH
|
||||
/*
|
||||
|
@ -544,7 +557,6 @@ struct hid_device { /* device report descriptor */
|
|||
void *hiddev; /* The hiddev structure */
|
||||
void *hidraw;
|
||||
|
||||
int open; /* is the device open by anyone? */
|
||||
char name[128]; /* Device name */
|
||||
char phys[64]; /* Device physical location */
|
||||
char uniq[64]; /* Device unique identifier (serial #) */
|
||||
|
@ -937,69 +949,11 @@ static inline int __must_check hid_parse(struct hid_device *hdev)
|
|||
return hid_open_report(hdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* hid_hw_start - start underlaying HW
|
||||
*
|
||||
* @hdev: hid device
|
||||
* @connect_mask: which outputs to connect, see HID_CONNECT_*
|
||||
*
|
||||
* Call this in probe function *after* hid_parse. This will setup HW buffers
|
||||
* and start the device (if not deffered to device open). hid_hw_stop must be
|
||||
* called if this was successful.
|
||||
*/
|
||||
static inline int __must_check hid_hw_start(struct hid_device *hdev,
|
||||
unsigned int connect_mask)
|
||||
{
|
||||
int ret = hdev->ll_driver->start(hdev);
|
||||
if (ret || !connect_mask)
|
||||
return ret;
|
||||
ret = hid_connect(hdev, connect_mask);
|
||||
if (ret)
|
||||
hdev->ll_driver->stop(hdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* hid_hw_stop - stop underlaying HW
|
||||
*
|
||||
* @hdev: hid device
|
||||
*
|
||||
* This is usually called from remove function or from probe when something
|
||||
* failed and hid_hw_start was called already.
|
||||
*/
|
||||
static inline void hid_hw_stop(struct hid_device *hdev)
|
||||
{
|
||||
hid_disconnect(hdev);
|
||||
hdev->ll_driver->stop(hdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* hid_hw_open - signal underlaying HW to start delivering events
|
||||
*
|
||||
* @hdev: hid device
|
||||
*
|
||||
* Tell underlying HW to start delivering events from the device.
|
||||
* This function should be called sometime after successful call
|
||||
* to hid_hiw_start().
|
||||
*/
|
||||
static inline int __must_check hid_hw_open(struct hid_device *hdev)
|
||||
{
|
||||
return hdev->ll_driver->open(hdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* hid_hw_close - signal underlaying HW to stop delivering events
|
||||
*
|
||||
* @hdev: hid device
|
||||
*
|
||||
* This function indicates that we are not interested in the events
|
||||
* from this device anymore. Delivery of events may or may not stop,
|
||||
* depending on the number of users still outstanding.
|
||||
*/
|
||||
static inline void hid_hw_close(struct hid_device *hdev)
|
||||
{
|
||||
hdev->ll_driver->close(hdev);
|
||||
}
|
||||
int __must_check hid_hw_start(struct hid_device *hdev,
|
||||
unsigned int connect_mask);
|
||||
void hid_hw_stop(struct hid_device *hdev);
|
||||
int __must_check hid_hw_open(struct hid_device *hdev);
|
||||
void hid_hw_close(struct hid_device *hdev);
|
||||
|
||||
/**
|
||||
* hid_hw_power - requests underlying HW to go into given power mode
|
||||
|
|
Loading…
Reference in New Issue