Commit a91ab911 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull HID updates from Jiri Kosina:

 - 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
  ...
parents af3c8d98 837c194a
...@@ -388,6 +388,13 @@ config HID_ICADE ...@@ -388,6 +388,13 @@ config HID_ICADE
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called hid-icade. 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 config HID_TWINHAN
tristate "Twinhan IR remote control" tristate "Twinhan IR remote control"
depends on HID depends on HID
...@@ -741,6 +748,14 @@ config HID_PRIMAX ...@@ -741,6 +748,14 @@ config HID_PRIMAX
Support for Primax devices that are not fully compliant with the Support for Primax devices that are not fully compliant with the
HID standard. HID standard.
config HID_RETRODE
tristate "Retrode"
depends on USB_HID
---help---
Support for
* Retrode 2 cartridge and controller adapter
config HID_ROCCAT config HID_ROCCAT
tristate "Roccat device support" tristate "Roccat device support"
depends on USB_HID depends on USB_HID
......
...@@ -50,6 +50,7 @@ obj-$(CONFIG_HID_HOLTEK) += hid-holtek-mouse.o ...@@ -50,6 +50,7 @@ obj-$(CONFIG_HID_HOLTEK) += hid-holtek-mouse.o
obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o
obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o
obj-$(CONFIG_HID_ICADE) += hid-icade.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_KENSINGTON) += hid-kensington.o
obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o
obj-$(CONFIG_HID_KYE) += hid-kye.o obj-$(CONFIG_HID_KYE) += hid-kye.o
...@@ -81,6 +82,7 @@ hid-picolcd-$(CONFIG_DEBUG_FS) += hid-picolcd_debugfs.o ...@@ -81,6 +82,7 @@ hid-picolcd-$(CONFIG_DEBUG_FS) += hid-picolcd_debugfs.o
obj-$(CONFIG_HID_PLANTRONICS) += hid-plantronics.o obj-$(CONFIG_HID_PLANTRONICS) += hid-plantronics.o
obj-$(CONFIG_HID_PRIMAX) += hid-primax.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 \ 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-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
hid-roccat-koneplus.o hid-roccat-konepure.o hid-roccat-kovaplus.o \ hid-roccat-koneplus.o hid-roccat-konepure.o hid-roccat-kovaplus.o \
......
This diff is collapsed.
...@@ -422,6 +422,33 @@ static int asus_input_mapping(struct hid_device *hdev, ...@@ -422,6 +422,33 @@ static int asus_input_mapping(struct hid_device *hdev,
return 1; 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 && if (drvdata->quirks & QUIRK_NO_CONSUMER_USAGES &&
(usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) { (usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) {
switch (usage->hid & HID_USAGE) { switch (usage->hid & HID_USAGE) {
...@@ -572,6 +599,9 @@ static const struct hid_device_id asus_devices[] = { ...@@ -572,6 +599,9 @@ static const struct hid_device_id asus_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD), USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD),
QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES }, 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); MODULE_DEVICE_TABLE(hid, asus_devices);
......
...@@ -84,9 +84,7 @@ static __u8 *ch_switch12_report_fixup(struct hid_device *hdev, __u8 *rdesc, ...@@ -84,9 +84,7 @@ static __u8 *ch_switch12_report_fixup(struct hid_device *hdev, __u8 *rdesc,
static const struct hid_device_id ch_devices[] = { 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_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_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_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); MODULE_DEVICE_TABLE(hid, ch_devices);
......
...@@ -1070,7 +1070,7 @@ static s32 snto32(__u32 value, unsigned n) ...@@ -1070,7 +1070,7 @@ static s32 snto32(__u32 value, unsigned n)
case 16: return ((__s16)value); case 16: return ((__s16)value);
case 32: return ((__s32)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) s32 hid_snto32(__u32 value, unsigned n)
...@@ -1774,6 +1774,94 @@ void hid_disconnect(struct hid_device *hdev) ...@@ -1774,6 +1774,94 @@ void hid_disconnect(struct hid_device *hdev)
} }
EXPORT_SYMBOL_GPL(hid_disconnect); 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. * 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[] = { ...@@ -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_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_ROG_KEYBOARD2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD) }, { 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 #endif
#if IS_ENABLED(CONFIG_HID_AUREAL) #if IS_ENABLED(CONFIG_HID_AUREAL)
{ HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) }, { 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[] = { ...@@ -1913,9 +2003,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
#if IS_ENABLED(CONFIG_HID_CHICONY) #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_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_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_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) },
{ HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_JESS_ZEN_AIO_KBD) },
#endif #endif
#if IS_ENABLED(CONFIG_HID_CMEDIA) #if IS_ENABLED(CONFIG_HID_CMEDIA)
{ HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM6533) }, { 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[] = { ...@@ -1984,6 +2073,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
#if IS_ENABLED(CONFIG_HID_ICADE) #if IS_ENABLED(CONFIG_HID_ICADE)
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
#endif #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) #if IS_ENABLED(CONFIG_HID_KENSINGTON)
{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
#endif #endif
...@@ -2151,6 +2243,9 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -2151,6 +2243,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
#if IS_ENABLED(CONFIG_HID_PRODIKEYS) #if IS_ENABLED(CONFIG_HID_PRODIKEYS)
{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
#endif #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) #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_LENOVO, USB_DEVICE_ID_LENOVO_X1_COVER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLADE_14) }, { HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLADE_14) },
...@@ -2914,6 +3009,7 @@ struct hid_device *hid_allocate_device(void) ...@@ -2914,6 +3009,7 @@ struct hid_device *hid_allocate_device(void)
spin_lock_init(&hdev->debug_list_lock); spin_lock_init(&hdev->debug_list_lock);
sema_init(&hdev->driver_lock, 1); sema_init(&hdev->driver_lock, 1);
sema_init(&hdev->driver_input_lock, 1); sema_init(&hdev->driver_input_lock, 1);
mutex_init(&hdev->ll_open_lock);
return hdev; return hdev;
} }
......
...@@ -75,6 +75,8 @@ ...@@ -75,6 +75,8 @@
#define USB_VENDOR_ID_ALPS_JP 0x044E #define USB_VENDOR_ID_ALPS_JP 0x044E
#define HID_DEVICE_ID_ALPS_U1_DUAL 0x120B #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_VENDOR_ID_AMI 0x046b
#define USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE 0xff10 #define USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE 0xff10
...@@ -252,7 +254,7 @@ ...@@ -252,7 +254,7 @@
#define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618 #define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618
#define USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE 0x1053 #define USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE 0x1053
#define USB_DEVICE_ID_CHICONY_WIRELESS2 0x1123 #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_DEVICE_ID_CHICONY_ACER_SWITCH12 0x1421
#define USB_VENDOR_ID_CHUNGHWAT 0x2247 #define USB_VENDOR_ID_CHUNGHWAT 0x2247
...@@ -386,6 +388,9 @@ ...@@ -386,6 +388,9 @@
#define USB_VENDOR_ID_FUTABA 0x0547 #define USB_VENDOR_ID_FUTABA 0x0547
#define USB_DEVICE_ID_LED_DISPLAY 0x7000 #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_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f
#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
...@@ -428,6 +433,9 @@ ...@@ -428,6 +433,9 @@
#define USB_VENDOR_ID_GOODTOUCH 0x1aad #define USB_VENDOR_ID_GOODTOUCH 0x1aad
#define USB_DEVICE_ID_GOODTOUCH_000f 0x000f #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_VENDOR_ID_GOTOP 0x08f2
#define USB_DEVICE_ID_SUPER_Q2 0x007f #define USB_DEVICE_ID_SUPER_Q2 0x007f
#define USB_DEVICE_ID_GOGOPEN 0x00ce #define USB_DEVICE_ID_GOGOPEN 0x00ce
...@@ -565,6 +573,7 @@ ...@@ -565,6 +573,7 @@
#define USB_DEVICE_ID_ITE_LENOVO_YOGA 0x8386 #define USB_DEVICE_ID_ITE_LENOVO_YOGA 0x8386
#define USB_DEVICE_ID_ITE_LENOVO_YOGA2 0x8350 #define USB_DEVICE_ID_ITE_LENOVO_YOGA2 0x8350
#define USB_DEVICE_ID_ITE_LENOVO_YOGA900 0x8396 #define USB_DEVICE_ID_ITE_LENOVO_YOGA900 0x8396
#define USB_DEVICE_ID_ITE8595 0x8595
#define USB_VENDOR_ID_JABRA 0x0b0e #define USB_VENDOR_ID_JABRA 0x0b0e
#define USB_DEVICE_ID_JABRA_SPEAK_410 0x0412 #define USB_DEVICE_ID_JABRA_SPEAK_410 0x0412
...@@ -573,7 +582,7 @@ ...@@ -573,7 +582,7 @@
#define USB_VENDOR_ID_JESS 0x0c45 #define USB_VENDOR_ID_JESS 0x0c45
#define USB_DEVICE_ID_JESS_YUREX 0x1010 #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_VENDOR_ID_JESS2 0x0f30
#define USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD 0x0111 #define USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD 0x0111
...@@ -1024,6 +1033,7 @@ ...@@ -1024,6 +1033,7 @@
#define USB_VENDOR_ID_TURBOX 0x062a #define USB_VENDOR_ID_TURBOX 0x062a
#define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 #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_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART 0x7100
#define USB_VENDOR_ID_TWINHAN 0x6253 #define USB_VENDOR_ID_TWINHAN 0x6253
......
...@@ -656,6 +656,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel ...@@ -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_START: map_key_clear(BTN_START); break;
case HID_GD_SELECT: map_key_clear(BTN_SELECT); 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; default: goto unknown;
} }
......
/*
* 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");
This diff is collapsed.
/*
* 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 @@ ...@@ -40,7 +40,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/i2c/i2c-hid.h> #include <linux/platform_data/i2c-hid.h>
#include "../hid-ids.h" #include "../hid-ids.h"
...@@ -743,18 +743,12 @@ static int i2c_hid_open(struct hid_device *hid) ...@@ -743,18 +743,12 @@ static int i2c_hid_open(struct hid_device *hid)
struct i2c_hid *ihid = i2c_get_clientdata(client); struct i2c_hid *ihid = i2c_get_clientdata(client);
int ret = 0; int ret = 0;
mutex_lock(&i2c_hid_open_mut);
if (!hid->open++) {
ret = pm_runtime_get_sync(&client->dev); ret = pm_runtime_get_sync(&client->dev);
if (ret < 0) { if (ret < 0)
hid->open--; return ret;
goto done;
}
set_bit(I2C_HID_STARTED, &ihid->flags); set_bit(I2C_HID_STARTED, &ihid->flags);
} return 0;
done:
mutex_unlock(&i2c_hid_open_mut);
return ret < 0 ? ret : 0;
} }
static void i2c_hid_close(struct hid_device *hid) static void i2c_hid_close(struct hid_device *hid)
...@@ -762,18 +756,10 @@ 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_client *client = hid->driver_data;
struct i2c_hid *ihid = i2c_get_clientdata(client); 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 */ /* Save some power */
pm_runtime_put(&client->dev); pm_runtime_put(&client->dev);
}
mutex_unlock(&i2c_hid_open_mut);
} }
static int i2c_hid_power(struct hid_device *hid, int lvl) static int i2c_hid_power(struct hid_device *hid, int lvl)
......
menu "Intel ISH HID support" menu "Intel ISH HID support"
depends on X86_64 && PCI depends on (X86_64 || COMPILE_TEST) && PCI
config INTEL_ISH_HID config INTEL_ISH_HID
tristate "Intel Integrated Sensor Hub" tristate "Intel Integrated Sensor Hub"
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
#define BXT_Bx_DEVICE_ID 0x1AA2 #define BXT_Bx_DEVICE_ID 0x1AA2
#define APL_Ax_DEVICE_ID 0x5AA2 #define APL_Ax_DEVICE_ID 0x5AA2
#define SPT_Ax_DEVICE_ID 0x9D35 #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_A0 0x6
#define REVISION_ID_CHT_Ax_SI 0x0 #define REVISION_ID_CHT_Ax_SI 0x0
......
...@@ -296,17 +296,12 @@ static int write_ipc_from_queue(struct ishtp_device *dev) ...@@ -296,17 +296,12 @@ static int write_ipc_from_queue(struct ishtp_device *dev)
/* If sending MNG_SYNC_FW_CLOCK, update clock again */ /* If sending MNG_SYNC_FW_CLOCK, update clock again */
if (IPC_HEADER_GET_PROTOCOL(doorbell_val) == IPC_PROTOCOL_MNG && if (IPC_HEADER_GET_PROTOCOL(doorbell_val) == IPC_PROTOCOL_MNG &&
IPC_HEADER_GET_MNG_CMD(doorbell_val) == MNG_SYNC_FW_CLOCK) { 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 ipc_time_update_msg time_update;
struct time_sync_format ts_format; struct time_sync_format ts_format;
get_monotonic_boottime(&ts_system); usec_system = ktime_to_us(ktime_get_boottime());
do_gettimeofday(&tv_utc); usec_utc = ktime_to_us(ktime_get_real());
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);
ts_format.ts1_source = HOST_SYSTEM_TIME_USEC; ts_format.ts1_source = HOST_SYSTEM_TIME_USEC;
ts_format.ts2_source = HOST_UTC_TIME_USEC; ts_format.ts2_source = HOST_UTC_TIME_USEC;
ts_format.reserved = 0; ts_format.reserved = 0;
...@@ -575,15 +570,13 @@ static void fw_reset_work_fn(struct work_struct *unused) ...@@ -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 void _ish_sync_fw_clock(struct ishtp_device *dev)
{ {
static unsigned long prev_sync; static unsigned long prev_sync;
struct timespec ts;
uint64_t usec; uint64_t usec;
if (prev_sync && jiffies - prev_sync < 20 * HZ) if (prev_sync && jiffies - prev_sync < 20 * HZ)
return; return;
prev_sync = jiffies; prev_sync = jiffies;
get_monotonic_boottime(&ts); usec = ktime_to_us(ktime_get_boottime());
usec = (timespec_to_ns(&ts)) / NSEC_PER_USEC;
ipc_send_mng_msg(dev, MNG_SYNC_FW_CLOCK, &usec, sizeof(uint64_t)); 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[] = { ...@@ -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, BXT_Bx_DEVICE_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, APL_Ax_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, 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, } {0, }
}; };
MODULE_DEVICE_TABLE(pci, ish_pci_tbl); MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
......
...@@ -136,10 +136,9 @@ static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf, ...@@ -136,10 +136,9 @@ static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf,
if (1 + sizeof(struct device_info) * i >= if (1 + sizeof(struct device_info) * i >=
payload_len) { payload_len) {
dev_err(&client_data->cl_device->dev, 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) 1 + sizeof(struct device_info)
* i, * i, payload_len);
(unsigned int)payload_len);
} }
if (1 + sizeof(struct device_info) * i >= if (1 + sizeof(struct device_info) * i >=
......
...@@ -803,7 +803,7 @@ void ishtp_cl_send_msg(struct ishtp_device *dev, struct ishtp_cl *cl) ...@@ -803,7 +803,7 @@ void ishtp_cl_send_msg(struct ishtp_device *dev, struct ishtp_cl *cl)
* @ishtp_hdr: Pointer to message header * @ishtp_hdr: Pointer to message header
* *
* Receive and dispatch ISHTP client messages. This function executes in ISR * 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, void recv_ishtp_cl_msg(struct ishtp_device *dev,
struct ishtp_msg_hdr *ishtp_hdr) struct ishtp_msg_hdr *ishtp_hdr)
...@@ -813,7 +813,6 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev, ...@@ -813,7 +813,6 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
struct ishtp_cl_rb *new_rb; struct ishtp_cl_rb *new_rb;
unsigned char *buffer = NULL; unsigned char *buffer = NULL;
struct ishtp_cl_rb *complete_rb = NULL; struct ishtp_cl_rb *complete_rb = NULL;
unsigned long dev_flags;
unsigned long flags; unsigned long flags;
int rb_count; int rb_count;
...@@ -828,7 +827,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev, ...@@ -828,7 +827,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
goto eoi; goto eoi;
} }
spin_lock_irqsave(&dev->read_list_spinlock, dev_flags); spin_lock_irqsave(&dev->read_list_spinlock, flags);
rb_count = -1; rb_count = -1;
list_for_each_entry(rb, &dev->read_list.list, list) { list_for_each_entry(rb, &dev->read_list.list, list) {
++rb_count; ++rb_count;
...@@ -840,8 +839,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev, ...@@ -840,8 +839,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
/* If no Rx buffer is allocated, disband the rb */ /* If no Rx buffer is allocated, disband the rb */
if (rb->buffer.size == 0 || rb->buffer.data == NULL) { if (rb->buffer.size == 0 || rb->buffer.data == NULL) {
spin_unlock_irqrestore(&dev->read_list_spinlock, spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
dev_flags);
dev_err(&cl->device->dev, dev_err(&cl->device->dev,
"Rx buffer is not allocated.\n"); "Rx buffer is not allocated.\n");
list_del(&rb->list); list_del(&rb->list);
...@@ -857,8 +855,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev, ...@@ -857,8 +855,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
* back FC, so communication will be stuck anyway) * back FC, so communication will be stuck anyway)
*/ */
if (rb->buffer.size < ishtp_hdr->length + rb->buf_idx) { if (rb->buffer.size < ishtp_hdr->length + rb->buf_idx) {
spin_unlock_irqrestore(&dev->read_list_spinlock, spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
dev_flags);
dev_err(&cl->device->dev, dev_err(&cl->device->dev,
"message overflow. size %d len %d idx %ld\n", "message overflow. size %d len %d idx %ld\n",
rb->buffer.size, ishtp_hdr->length, rb->buffer.size, ishtp_hdr->length,
...@@ -884,14 +881,13 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev, ...@@ -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 * the whole msg arrived, send a new FC, and add a new
* rb buffer for the next coming msg * 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)) { if (!list_empty(&cl->free_rb_list.list)) {
new_rb = list_entry(cl->free_rb_list.list.next, new_rb = list_entry(cl->free_rb_list.list.next,
struct ishtp_cl_rb, list); struct ishtp_cl_rb, list);
list_del_init(&new_rb->list); list_del_init(&new_rb->list);
spin_unlock_irqrestore(&cl->free_list_spinlock, spin_unlock(&cl->free_list_spinlock);
flags);
new_rb->cl = cl; new_rb->cl = cl;
new_rb->buf_idx = 0; new_rb->buf_idx = 0;
INIT_LIST_HEAD(&new_rb->list); INIT_LIST_HEAD(&new_rb->list);
...@@ -900,8 +896,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev, ...@@ -900,8 +896,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
ishtp_hbm_cl_flow_control_req(dev, cl); ishtp_hbm_cl_flow_control_req(dev, cl);
} else { } else {
spin_unlock_irqrestore(&cl->free_list_spinlock, spin_unlock(&cl->free_list_spinlock);
flags);
} }
} }
/* One more fragment in message (even if this was last) */ /* One more fragment in message (even if this was last) */
...@@ -914,7 +909,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev, ...@@ -914,7 +909,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
break; 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 it's nobody's message, just read and discard it */
if (!buffer) { if (!buffer) {
uint8_t rd_msg_buf[ISHTP_RD_MSG_BUF_SIZE]; uint8_t rd_msg_buf[ISHTP_RD_MSG_BUF_SIZE];
...@@ -925,7 +920,8 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev, ...@@ -925,7 +920,8 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
} }
if (complete_rb) { if (complete_rb) {
getnstimeofday(&cl->ts_rx); cl = complete_rb->cl;
cl->ts_rx = ktime_get();
++cl->recv_msg_cnt_ipc; ++cl->recv_msg_cnt_ipc;
ishtp_cl_read_complete(complete_rb); ishtp_cl_read_complete(complete_rb);
} }
...@@ -940,7 +936,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev, ...@@ -940,7 +936,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
* @hbm: hbm buffer * @hbm: hbm buffer
* *
* Receive and dispatch ISHTP client messages using DMA. This function executes * 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, void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
struct dma_xfer_hbm *hbm) struct dma_xfer_hbm *hbm)
...@@ -950,10 +946,10 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg, ...@@ -950,10 +946,10 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
struct ishtp_cl_rb *new_rb; struct ishtp_cl_rb *new_rb;
unsigned char *buffer = NULL; unsigned char *buffer = NULL;
struct ishtp_cl_rb *complete_rb = NULL; struct ishtp_cl_rb *complete_rb = NULL;
unsigned long dev_flags;
unsigned long 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) { list_for_each_entry(rb, &dev->read_list.list, list) {
cl = rb->cl; cl = rb->cl;
if (!cl || !(cl->host_client_id == hbm->host_client_id && 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, ...@@ -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 no Rx buffer is allocated, disband the rb
*/ */
if (rb->buffer.size == 0 || rb->buffer.data == NULL) { if (rb->buffer.size == 0 || rb->buffer.data == NULL) {
spin_unlock_irqrestore(&dev->read_list_spinlock, spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
dev_flags);
dev_err(&cl->device->dev, dev_err(&cl->device->dev,
"response buffer is not allocated.\n"); "response buffer is not allocated.\n");
list_del(&rb->list); list_del(&rb->list);
...@@ -982,8 +977,7 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg, ...@@ -982,8 +977,7 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
* back FC, so communication will be stuck anyway) * back FC, so communication will be stuck anyway)
*/ */
if (rb->buffer.size < hbm->msg_length) { if (rb->buffer.size < hbm->msg_length) {
spin_unlock_irqrestore(&dev->read_list_spinlock, spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
dev_flags);
dev_err(&cl->device->dev, dev_err(&cl->device->dev,
"message overflow. size %d len %d idx %ld\n", "message overflow. size %d len %d idx %ld\n",
rb->buffer.size, hbm->msg_length, rb->buf_idx); 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, ...@@ -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 * the whole msg arrived, send a new FC, and add a new
* rb buffer for the next coming msg * 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)) { if (!list_empty(&cl->free_rb_list.list)) {
new_rb = list_entry(cl->free_rb_list.list.next, new_rb = list_entry(cl->free_rb_list.list.next,
struct ishtp_cl_rb, list); struct ishtp_cl_rb, list);
list_del_init(&new_rb->list); list_del_init(&new_rb->list);
spin_unlock_irqrestore(&cl->free_list_spinlock, spin_unlock(&cl->free_list_spinlock);
flags);
new_rb->cl = cl; new_rb->cl = cl;
new_rb->buf_idx = 0; new_rb->buf_idx = 0;
INIT_LIST_HEAD(&new_rb->list); INIT_LIST_HEAD(&new_rb->list);
...@@ -1023,8 +1016,7 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg, ...@@ -1023,8 +1016,7 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
ishtp_hbm_cl_flow_control_req(dev, cl); ishtp_hbm_cl_flow_control_req(dev, cl);
} else { } else {
spin_unlock_irqrestore(&cl->free_list_spinlock, spin_unlock(&cl->free_list_spinlock);
flags);
} }
/* One more fragment in message (this is always last) */ /* 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, ...@@ -1037,7 +1029,7 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
break; 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 it's nobody's message, just read and discard it */
if (!buffer) { if (!buffer) {
dev_err(dev->devc, "Dropped Rx (DMA) msg - no request\n"); 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, ...@@ -1045,7 +1037,8 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
} }
if (complete_rb) { if (complete_rb) {
getnstimeofday(&cl->ts_rx); cl = complete_rb->cl;
cl->ts_rx = ktime_get();
++cl->recv_msg_cnt_dma; ++cl->recv_msg_cnt_dma;
ishtp_cl_read_complete(complete_rb); ishtp_cl_read_complete(complete_rb);
} }
......
...@@ -118,9 +118,9 @@ struct ishtp_cl { ...@@ -118,9 +118,9 @@ struct ishtp_cl {
unsigned int out_flow_ctrl_cnt; unsigned int out_flow_ctrl_cnt;
/* Rx msg ... out FC timing */ /* Rx msg ... out FC timing */
struct timespec ts_rx; ktime_t ts_rx;
struct timespec ts_out_fc; ktime_t ts_out_fc;
struct timespec ts_max_fc_delay; ktime_t ts_max_fc_delay;
void *client_data; void *client_data;
}; };
......
...@@ -321,13 +321,10 @@ int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev, ...@@ -321,13 +321,10 @@ int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev,
if (!rv) { if (!rv) {
++cl->out_flow_ctrl_creds; ++cl->out_flow_ctrl_creds;
++cl->out_flow_ctrl_cnt; ++cl->out_flow_ctrl_cnt;
getnstimeofday(&cl->ts_out_fc); cl->ts_out_fc = ktime_get();
if (cl->ts_rx.tv_sec && cl->ts_rx.tv_nsec) { if (cl->ts_rx) {
struct timespec ts_diff; ktime_t ts_diff = ktime_sub(cl->ts_out_fc, cl->ts_rx);
if (ktime_after(ts_diff, cl->ts_max_fc_delay))
ts_diff = timespec_sub(cl->ts_out_fc, cl->ts_rx);
if (timespec_compare(&ts_diff, &cl->ts_max_fc_delay)
> 0)
cl->ts_max_fc_delay = ts_diff; cl->ts_max_fc_delay = ts_diff;
} }
} else { } else {
......
...@@ -70,8 +70,6 @@ MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying " ...@@ -70,8 +70,6 @@ MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying "
/* /*
* Input submission and I/O error handler. * Input submission and I/O error handler.
*/ */
static DEFINE_MUTEX(hid_open_mut);
static void hid_io_error(struct hid_device *hid); static void hid_io_error(struct hid_device *hid);
static int hid_submit_out(struct hid_device *hid); static int hid_submit_out(struct hid_device *hid);
static int hid_submit_ctrl(struct hid_device *hid); static int hid_submit_ctrl(struct hid_device *hid);
...@@ -85,7 +83,7 @@ static int hid_start_in(struct hid_device *hid) ...@@ -85,7 +83,7 @@ static int hid_start_in(struct hid_device *hid)
struct usbhid_device *usbhid = hid->driver_data; struct usbhid_device *usbhid = hid->driver_data;
spin_lock_irqsave(&usbhid->lock, flags); spin_lock_irqsave(&usbhid->lock, flags);
if ((hid->open > 0 || hid->quirks & HID_QUIRK_ALWAYS_POLL) && if (test_bit(HID_IN_POLLING, &usbhid->iofl) &&
!test_bit(HID_DISCONNECTED, &usbhid->iofl) && !test_bit(HID_DISCONNECTED, &usbhid->iofl) &&
!test_bit(HID_SUSPENDED, &usbhid->iofl) && !test_bit(HID_SUSPENDED, &usbhid->iofl) &&
!test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
...@@ -278,7 +276,7 @@ static void hid_irq_in(struct urb *urb) ...@@ -278,7 +276,7 @@ static void hid_irq_in(struct urb *urb)
switch (urb->status) { switch (urb->status) {
case 0: /* success */ case 0: /* success */
usbhid->retry_delay = 0; usbhid->retry_delay = 0;
if ((hid->quirks & HID_QUIRK_ALWAYS_POLL) && !hid->open) if (!test_bit(HID_OPENED, &usbhid->iofl))
break; break;
usbhid_mark_busy(usbhid); usbhid_mark_busy(usbhid);
if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) { if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
...@@ -677,22 +675,25 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, ...@@ -677,22 +675,25 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
return result; return result;
} }
int usbhid_open(struct hid_device *hid) static int usbhid_open(struct hid_device *hid)
{ {
struct usbhid_device *usbhid = hid->driver_data; struct usbhid_device *usbhid = hid->driver_data;
int res = 0; int res;
if (hid->quirks & HID_QUIRK_ALWAYS_POLL)
return 0;
mutex_lock(&hid_open_mut);
if (!hid->open++) {
res = usb_autopm_get_interface(usbhid->intf); res = usb_autopm_get_interface(usbhid->intf);
/* the device must be awake to reliably request remote wakeup */ /* the device must be awake to reliably request remote wakeup */
if (res < 0) { if (res < 0)
hid->open--; return -EIO;
res = -EIO;
goto done;
}
usbhid->intf->needs_remote_wakeup = 1; usbhid->intf->needs_remote_wakeup = 1;
set_bit(HID_RESUME_RUNNING, &usbhid->iofl); 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); res = hid_start_in(hid);
if (res) { if (res) {
if (res != -ENOSPC) { if (res != -ENOSPC) {
...@@ -700,11 +701,13 @@ int usbhid_open(struct hid_device *hid) ...@@ -700,11 +701,13 @@ int usbhid_open(struct hid_device *hid)
res = 0; res = 0;
} else { } else {
/* no use opening if resources are insufficient */ /* no use opening if resources are insufficient */
hid->open--;
res = -EBUSY; res = -EBUSY;
clear_bit(HID_OPENED, &usbhid->iofl);
clear_bit(HID_IN_POLLING, &usbhid->iofl);
usbhid->intf->needs_remote_wakeup = 0; usbhid->intf->needs_remote_wakeup = 0;
} }
} }
usb_autopm_put_interface(usbhid->intf); usb_autopm_put_interface(usbhid->intf);
/* /*
...@@ -713,37 +716,33 @@ int usbhid_open(struct hid_device *hid) ...@@ -713,37 +716,33 @@ int usbhid_open(struct hid_device *hid)
* Wait 50 msec for the queue to empty before allowing events * Wait 50 msec for the queue to empty before allowing events
* to go through hid. * to go through hid.
*/ */
if (res == 0 && !(hid->quirks & HID_QUIRK_ALWAYS_POLL)) if (res == 0)
msleep(50); msleep(50);
clear_bit(HID_RESUME_RUNNING, &usbhid->iofl); clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
}
done:
mutex_unlock(&hid_open_mut);
return res; return res;
} }
void usbhid_close(struct hid_device *hid) static void usbhid_close(struct hid_device *hid)
{ {
struct usbhid_device *usbhid = hid->driver_data; 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 * Make sure we don't restart data acquisition due to
* care about * a resumption we no longer care about by avoiding racing
* with hid_start_in().
*/ */
spin_lock_irq(&usbhid->lock); spin_lock_irq(&usbhid->lock);
if (!--hid->open) { clear_bit(HID_IN_POLLING, &usbhid->iofl);
clear_bit(HID_OPENED, &usbhid->iofl);
spin_unlock_irq(&usbhid->lock); spin_unlock_irq(&usbhid->lock);
hid_cancel_delayed_stuff(usbhid); hid_cancel_delayed_stuff(usbhid);
if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL)) {
usb_kill_urb(usbhid->urbin); usb_kill_urb(usbhid->urbin);
usbhid->intf->needs_remote_wakeup = 0; usbhid->intf->needs_remote_wakeup = 0;
}
} else {
spin_unlock_irq(&usbhid->lock);
}
mutex_unlock(&hid_open_mut);
} }
/* /*
...@@ -1135,6 +1134,7 @@ static int usbhid_start(struct hid_device *hid) ...@@ -1135,6 +1134,7 @@ static int usbhid_start(struct hid_device *hid)
ret = usb_autopm_get_interface(usbhid->intf); ret = usb_autopm_get_interface(usbhid->intf);
if (ret) if (ret)
goto fail; goto fail;
set_bit(HID_IN_POLLING, &usbhid->iofl);
usbhid->intf->needs_remote_wakeup = 1; usbhid->intf->needs_remote_wakeup = 1;
ret = hid_start_in(hid); ret = hid_start_in(hid);
if (ret) { if (ret) {
...@@ -1176,8 +1176,10 @@ static void usbhid_stop(struct hid_device *hid) ...@@ -1176,8 +1176,10 @@ static void usbhid_stop(struct hid_device *hid)
if (WARN_ON(!usbhid)) if (WARN_ON(!usbhid))
return; 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; usbhid->intf->needs_remote_wakeup = 0;
}
clear_bit(HID_STARTED, &usbhid->iofl); clear_bit(HID_STARTED, &usbhid->iofl);
spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */ spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */
...@@ -1203,16 +1205,19 @@ static void usbhid_stop(struct hid_device *hid) ...@@ -1203,16 +1205,19 @@ static void usbhid_stop(struct hid_device *hid)
static int usbhid_power(struct hid_device *hid, int lvl) static int usbhid_power(struct hid_device *hid, int lvl)
{ {
struct usbhid_device *usbhid = hid->driver_data;
int r = 0; int r = 0;
switch (lvl) { switch (lvl) {
case PM_HINT_FULLON: case PM_HINT_FULLON:
r = usbhid_get_power(hid); r = usb_autopm_get_interface(usbhid->intf);
break; break;
case PM_HINT_NORMAL: case PM_HINT_NORMAL:
usbhid_put_power(hid); usb_autopm_put_interface(usbhid->intf);
break; break;
} }
return r; return r;
} }
...@@ -1492,21 +1497,6 @@ static int hid_post_reset(struct usb_interface *intf) ...@@ -1492,21 +1497,6 @@ static int hid_post_reset(struct usb_interface *intf)
return 0; 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 #ifdef CONFIG_PM
static int hid_resume_common(struct hid_device *hid, bool driver_suspended) 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) ...@@ -237,8 +237,8 @@ static int hiddev_release(struct inode * inode, struct file * file)
mutex_lock(&list->hiddev->existancelock); mutex_lock(&list->hiddev->existancelock);
if (!--list->hiddev->open) { if (!--list->hiddev->open) {
if (list->hiddev->exist) { if (list->hiddev->exist) {
usbhid_close(list->hiddev->hid); hid_hw_close(list->hiddev->hid);
usbhid_put_power(list->hiddev->hid); hid_hw_power(list->hiddev->hid, PM_HINT_NORMAL);
} else { } else {
mutex_unlock(&list->hiddev->existancelock); mutex_unlock(&list->hiddev->existancelock);
kfree(list->hiddev); kfree(list->hiddev);
...@@ -282,12 +282,10 @@ static int hiddev_open(struct inode *inode, struct file *file) ...@@ -282,12 +282,10 @@ static int hiddev_open(struct inode *inode, struct file *file)
*/ */
if (list->hiddev->exist) { if (list->hiddev->exist) {
if (!list->hiddev->open++) { if (!list->hiddev->open++) {
res = usbhid_open(hiddev->hid); res = hid_hw_open(hiddev->hid);
if (res < 0) { if (res < 0)
res = -EIO;
goto bail; goto bail;
} }
}
} else { } else {
res = -ENODEV; res = -ENODEV;
goto bail; goto bail;
...@@ -301,15 +299,17 @@ static int hiddev_open(struct inode *inode, struct file *file) ...@@ -301,15 +299,17 @@ static int hiddev_open(struct inode *inode, struct file *file)
if (!list->hiddev->open++) if (!list->hiddev->open++)
if (list->hiddev->exist) { if (list->hiddev->exist) {
struct hid_device *hid = hiddev->hid; struct hid_device *hid = hiddev->hid;
res = usbhid_get_power(hid); res = hid_hw_power(hid, PM_HINT_FULLON);
if (res < 0) { if (res < 0)
res = -EIO;
goto bail_unlock; goto bail_unlock;
} res = hid_hw_open(hid);
usbhid_open(hid); if (res < 0)
goto bail_normal_power;
} }
mutex_unlock(&hiddev->existancelock); mutex_unlock(&hiddev->existancelock);
return 0; return 0;
bail_normal_power:
hid_hw_power(hid, PM_HINT_NORMAL);
bail_unlock: bail_unlock:
mutex_unlock(&hiddev->existancelock); mutex_unlock(&hiddev->existancelock);
bail: bail:
...@@ -935,7 +935,7 @@ void hiddev_disconnect(struct hid_device *hid) ...@@ -935,7 +935,7 @@ void hiddev_disconnect(struct hid_device *hid)
if (hiddev->open) { if (hiddev->open) {
mutex_unlock(&hiddev->existancelock); mutex_unlock(&hiddev->existancelock);
usbhid_close(hiddev->hid); hid_hw_close(hiddev->hid);
wake_up_interruptible(&hiddev->wait); wake_up_interruptible(&hiddev->wait);
} else { } else {
mutex_unlock(&hiddev->existancelock); mutex_unlock(&hiddev->existancelock);
......
...@@ -34,11 +34,7 @@ ...@@ -34,11 +34,7 @@
#include <linux/input.h> #include <linux/input.h>
/* API provided by hid-core.c for USB HID drivers */ /* 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); 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); struct usb_interface *usbhid_find_interface(int minor);
/* iofl flags */ /* iofl flags */
...@@ -53,6 +49,17 @@ struct usb_interface *usbhid_find_interface(int minor); ...@@ -53,6 +49,17 @@ struct usb_interface *usbhid_find_interface(int minor);
#define HID_KEYS_PRESSED 10 #define HID_KEYS_PRESSED 10
#define HID_NO_BANDWIDTH 11 #define HID_NO_BANDWIDTH 11
#define HID_RESUME_RUNNING 12 #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 * USB-specific HID struct, to be pointed to
......
...@@ -138,6 +138,7 @@ struct wacom_battery { ...@@ -138,6 +138,7 @@ struct wacom_battery {
struct power_supply_desc bat_desc; struct power_supply_desc bat_desc;
struct power_supply *battery; struct power_supply *battery;
char bat_name[WACOM_NAME_MAX]; char bat_name[WACOM_NAME_MAX];
int bat_status;
int battery_capacity; int battery_capacity;
int bat_charging; int bat_charging;
int bat_connected; int bat_connected;
......
...@@ -1547,7 +1547,9 @@ static int wacom_battery_get_property(struct power_supply *psy, ...@@ -1547,7 +1547,9 @@ static int wacom_battery_get_property(struct power_supply *psy,
val->intval = battery->battery_capacity; val->intval = battery->battery_capacity;
break; break;
case POWER_SUPPLY_PROP_STATUS: 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; val->intval = POWER_SUPPLY_STATUS_CHARGING;
else if (battery->battery_capacity == 100 && else if (battery->battery_capacity == 100 &&
battery->ps_connected) battery->ps_connected)
......
This diff is collapsed.
...@@ -96,6 +96,8 @@ ...@@ -96,6 +96,8 @@
#define WACOM_DEVICETYPE_WL_MONITOR 0x0008 #define WACOM_DEVICETYPE_WL_MONITOR 0x0008
#define WACOM_DEVICETYPE_DIRECT 0x0010 #define WACOM_DEVICETYPE_DIRECT 0x0010
#define WACOM_POWER_SUPPLY_STATUS_AUTO -1
#define WACOM_HID_UP_WACOMDIGITIZER 0xff0d0000 #define WACOM_HID_UP_WACOMDIGITIZER 0xff0d0000
#define WACOM_HID_SP_PAD 0x00040000 #define WACOM_HID_SP_PAD 0x00040000
#define WACOM_HID_SP_BUTTON 0x00090000 #define WACOM_HID_SP_BUTTON 0x00090000
...@@ -151,6 +153,10 @@ ...@@ -151,6 +153,10 @@
#define WACOM_HID_WT_X (WACOM_HID_UP_WACOMTOUCH | 0x130) #define WACOM_HID_WT_X (WACOM_HID_UP_WACOMTOUCH | 0x130)
#define WACOM_HID_WT_Y (WACOM_HID_UP_WACOMTOUCH | 0x131) #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) || \ #define WACOM_PAD_FIELD(f) (((f)->physical == HID_DG_TABLETFUNCTIONKEY) || \
((f)->physical == WACOM_HID_WD_DIGITIZERFNKEYS) || \ ((f)->physical == WACOM_HID_WD_DIGITIZERFNKEYS) || \
((f)->physical == WACOM_HID_WD_DIGITIZERINFO)) ((f)->physical == WACOM_HID_WD_DIGITIZERINFO))
...@@ -297,6 +303,7 @@ struct hid_data { ...@@ -297,6 +303,7 @@ struct hid_data {
int last_slot_field; int last_slot_field;
int num_expected; int num_expected;
int num_received; int num_received;
int bat_status;
int battery_capacity; int battery_capacity;
int bat_charging; int bat_charging;
int bat_connected; int bat_connected;
......
...@@ -32,8 +32,6 @@ struct gb_hid { ...@@ -32,8 +32,6 @@ struct gb_hid {
char *inbuf; char *inbuf;
}; };
static DEFINE_MUTEX(gb_hid_open_mutex);
/* Routines to get controller's information over greybus */ /* Routines to get controller's information over greybus */
/* Operations performed on greybus */ /* Operations performed on greybus */
...@@ -346,19 +344,14 @@ static void gb_hid_stop(struct hid_device *hid) ...@@ -346,19 +344,14 @@ static void gb_hid_stop(struct hid_device *hid)
static int gb_hid_open(struct hid_device *hid) static int gb_hid_open(struct hid_device *hid)
{ {
struct gb_hid *ghid = hid->driver_data; 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); ret = gb_hid_set_power(ghid, GB_HID_TYPE_PWR_ON);
if (ret < 0) if (ret < 0)
hid->open--;
else
set_bit(GB_HID_STARTED, &ghid->flags);
}
mutex_unlock(&gb_hid_open_mutex);
return ret; return ret;
set_bit(GB_HID_STARTED, &ghid->flags);
return 0;
} }
static void gb_hid_close(struct hid_device *hid) static void gb_hid_close(struct hid_device *hid)
...@@ -366,12 +359,6 @@ static void gb_hid_close(struct hid_device *hid) ...@@ -366,12 +359,6 @@ static void gb_hid_close(struct hid_device *hid)
struct gb_hid *ghid = hid->driver_data; struct gb_hid *ghid = hid->driver_data;
int ret; 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 */ /* Save some power */
...@@ -379,8 +366,6 @@ static void gb_hid_close(struct hid_device *hid) ...@@ -379,8 +366,6 @@ static void gb_hid_close(struct hid_device *hid)
if (ret) if (ret)
dev_err(&ghid->connection->bundle->dev, dev_err(&ghid->connection->bundle->dev,
"failed to power off (%d)\n", ret); "failed to power off (%d)\n", ret);
}
mutex_unlock(&gb_hid_open_mutex);
} }
static int gb_hid_power(struct hid_device *hid, int lvl) static int gb_hid_power(struct hid_device *hid, int lvl)
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/semaphore.h> #include <linux/semaphore.h>
#include <linux/mutex.h>
#include <linux/power_supply.h> #include <linux/power_supply.h>
#include <uapi/linux/hid.h> #include <uapi/linux/hid.h>
...@@ -182,6 +183,11 @@ struct hid_item { ...@@ -182,6 +183,11 @@ struct hid_item {
#define HID_GD_KEYBOARD 0x00010006 #define HID_GD_KEYBOARD 0x00010006
#define HID_GD_KEYPAD 0x00010007 #define HID_GD_KEYPAD 0x00010007
#define HID_GD_MULTIAXIS 0x00010008 #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_X 0x00010030
#define HID_GD_Y 0x00010031 #define HID_GD_Y 0x00010031
#define HID_GD_Z 0x00010032 #define HID_GD_Z 0x00010032
...@@ -210,6 +216,10 @@ struct hid_item { ...@@ -210,6 +216,10 @@ struct hid_item {
#define HID_GD_DOWN 0x00010091 #define HID_GD_DOWN 0x00010091
#define HID_GD_RIGHT 0x00010092 #define HID_GD_RIGHT 0x00010092
#define HID_GD_LEFT 0x00010093 #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 #define HID_DC_BATTERYSTRENGTH 0x00060020
...@@ -520,7 +530,10 @@ struct hid_device { /* device report descriptor */ ...@@ -520,7 +530,10 @@ struct hid_device { /* device report descriptor */
struct semaphore driver_input_lock; /* protects the current driver */ struct semaphore driver_input_lock; /* protects the current driver */
struct device dev; /* device */ struct device dev; /* device */
struct hid_driver *driver; struct hid_driver *driver;
struct hid_ll_driver *ll_driver; struct hid_ll_driver *ll_driver;
struct mutex ll_open_lock;
unsigned int ll_open_count;
#ifdef CONFIG_HID_BATTERY_STRENGTH #ifdef CONFIG_HID_BATTERY_STRENGTH
/* /*
...@@ -544,7 +557,6 @@ struct hid_device { /* device report descriptor */ ...@@ -544,7 +557,6 @@ struct hid_device { /* device report descriptor */
void *hiddev; /* The hiddev structure */ void *hiddev; /* The hiddev structure */
void *hidraw; void *hidraw;
int open; /* is the device open by anyone? */
char name[128]; /* Device name */ char name[128]; /* Device name */
char phys[64]; /* Device physical location */ char phys[64]; /* Device physical location */
char uniq[64]; /* Device unique identifier (serial #) */ char uniq[64]; /* Device unique identifier (serial #) */
...@@ -937,69 +949,11 @@ static inline int __must_check hid_parse(struct hid_device *hdev) ...@@ -937,69 +949,11 @@ static inline int __must_check hid_parse(struct hid_device *hdev)
return hid_open_report(hdev); return hid_open_report(hdev);
} }
/** int __must_check hid_hw_start(struct hid_device *hdev,
* hid_hw_start - start underlaying HW unsigned int connect_mask);
* void hid_hw_stop(struct hid_device *hdev);
* @hdev: hid device int __must_check hid_hw_open(struct hid_device *hdev);
* @connect_mask: which outputs to connect, see HID_CONNECT_* void hid_hw_close(struct hid_device *hdev);
*
* 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);
}
/** /**
* hid_hw_power - requests underlying HW to go into given power mode * hid_hw_power - requests underlying HW to go into given power mode
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment