Commit 0349678c 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:
 - i2c-hid race condition fix from Jean-Baptiste Maneyrol
 - Logitech driver now supports vendor-specific HID++ protocol, allowing
   us to deliver a full multitouch support on wider range of Logitech
   touchpads.  Written by Benjamin Tissoires
 - MS Surface Pro 3 Type Cover support added by Alan Wu
 - RMI touchpad support improvements from Andrew Duggan
 - a lot of updates to Wacom driver from Jason Gerecke and Ping Cheng
 - various small fixes all over the place

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (56 commits)
  HID: rmi: The address of query8 must be calculated based on which query registers are present
  HID: rmi: Check for additional ACM registers appended to F11 data report
  HID: i2c-hid: prevent buffer overflow in early IRQ
  HID: logitech-hidpp: disable io in probe error path
  HID: logitech-hidpp: add boundary check for name retrieval
  HID: logitech-hidpp: check name retrieval return code
  HID: logitech-hidpp: do not return the name length
  HID: wacom: Report input events for each finger on generic devices
  HID: wacom: Initialize MT slots for generic devices at post_parse_hid
  HID: wacom: Update maximum X/Y accounding to outbound offset
  HID: wacom: Add support for DTU-1031X
  HID: wacom: add defines for new Cintiq and DTU outbound tracking
  HID: wacom: fix freeze on open when autosuspend is on
  HID: wacom: re-add accidentally dropped Lenovo PID
  HID: make hid_report_len as a static inline function in hid.h
  HID: wacom: Consult the application usage when determining field type
  HID: wacom: PAD is independent with pen/touch
  HID: multitouch: Add quirk for VTL touch panels
  HID: i2c-hid: fix race condition reading reports
  HID: wacom: Add angular resolution data to some ABS axes
  ...
parents a7cb7bb6 019e129f
...@@ -371,6 +371,7 @@ config HID_LOGITECH_DJ ...@@ -371,6 +371,7 @@ config HID_LOGITECH_DJ
tristate "Logitech Unifying receivers full support" tristate "Logitech Unifying receivers full support"
depends on HIDRAW depends on HIDRAW
depends on HID_LOGITECH depends on HID_LOGITECH
select HID_LOGITECH_HIDPP
---help--- ---help---
Say Y if you want support for Logitech Unifying receivers and devices. Say Y if you want support for Logitech Unifying receivers and devices.
Unifying receivers are capable of pairing up to 6 Logitech compliant Unifying receivers are capable of pairing up to 6 Logitech compliant
...@@ -378,6 +379,17 @@ config HID_LOGITECH_DJ ...@@ -378,6 +379,17 @@ config HID_LOGITECH_DJ
generic USB_HID driver and all incoming events will be multiplexed generic USB_HID driver and all incoming events will be multiplexed
into a single mouse and a single keyboard device. into a single mouse and a single keyboard device.
config HID_LOGITECH_HIDPP
tristate "Logitech HID++ devices support"
depends on HID_LOGITECH
---help---
Support for Logitech devices relyingon the HID++ Logitech specification
Say Y if you want support for Logitech devices relying on the HID++
specification. Such devices are the various Logitech Touchpads (T650,
T651, TK820), some mice (Zone Touch mouse), or even keyboards (Solar
Keayboard).
config LOGITECH_FF config LOGITECH_FF
bool "Logitech force feedback support" bool "Logitech force feedback support"
depends on HID_LOGITECH depends on HID_LOGITECH
...@@ -613,6 +625,13 @@ config HID_PICOLCD_CIR ...@@ -613,6 +625,13 @@ config HID_PICOLCD_CIR
---help--- ---help---
Provide access to PicoLCD's CIR interface via remote control (LIRC). Provide access to PicoLCD's CIR interface via remote control (LIRC).
config HID_PLANTRONICS
tristate "Plantronics USB HID Driver"
default !EXPERT
depends on HID
---help---
Provides HID support for Plantronics telephony devices.
config HID_PRIMAX config HID_PRIMAX
tristate "Primax non-fully HID-compliant devices" tristate "Primax non-fully HID-compliant devices"
depends on HID depends on HID
...@@ -629,7 +648,7 @@ config HID_ROCCAT ...@@ -629,7 +648,7 @@ config HID_ROCCAT
support for its special functionalities. support for its special functionalities.
config HID_SAITEK config HID_SAITEK
tristate "Saitek non-fully HID-compliant devices" tristate "Saitek (Mad Catz) non-fully HID-compliant devices"
depends on HID depends on HID
---help--- ---help---
Support for Saitek devices that are not fully compliant with the Support for Saitek devices that are not fully compliant with the
...@@ -637,6 +656,7 @@ config HID_SAITEK ...@@ -637,6 +656,7 @@ config HID_SAITEK
Supported devices: Supported devices:
- PS1000 Dual Analog Pad - PS1000 Dual Analog Pad
- R.A.T.9 Gaming Mouse
- R.A.T.7 Gaming Mouse - R.A.T.7 Gaming Mouse
- M.M.O.7 Gaming Mouse - M.M.O.7 Gaming Mouse
......
...@@ -63,6 +63,7 @@ obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o ...@@ -63,6 +63,7 @@ obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o
obj-$(CONFIG_HID_LENOVO) += hid-lenovo.o obj-$(CONFIG_HID_LENOVO) += hid-lenovo.o
obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o
obj-$(CONFIG_HID_LOGITECH_HIDPP) += hid-logitech-hidpp.o
obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o
obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o
obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o
...@@ -94,6 +95,7 @@ ifdef CONFIG_DEBUG_FS ...@@ -94,6 +95,7 @@ ifdef CONFIG_DEBUG_FS
hid-picolcd-y += hid-picolcd_debugfs.o hid-picolcd-y += hid-picolcd_debugfs.o
endif endif
obj-$(CONFIG_HID_PLANTRONICS) += hid-plantronics.o
obj-$(CONFIG_HID_PRIMAX) += hid-primax.o obj-$(CONFIG_HID_PRIMAX) += hid-primax.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 \
......
...@@ -702,6 +702,11 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type) ...@@ -702,6 +702,11 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type)
if (((parser->global.usage_page << 16) == HID_UP_SENSOR) && if (((parser->global.usage_page << 16) == HID_UP_SENSOR) &&
type == HID_COLLECTION_PHYSICAL) type == HID_COLLECTION_PHYSICAL)
hid->group = HID_GROUP_SENSOR_HUB; hid->group = HID_GROUP_SENSOR_HUB;
if (hid->vendor == USB_VENDOR_ID_MICROSOFT &&
hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 &&
hid->group == HID_GROUP_MULTITOUCH)
hid->group = HID_GROUP_GENERIC;
} }
static int hid_scan_main(struct hid_parser *parser, struct hid_item *item) static int hid_scan_main(struct hid_parser *parser, struct hid_item *item)
...@@ -779,16 +784,6 @@ static int hid_scan_report(struct hid_device *hid) ...@@ -779,16 +784,6 @@ static int hid_scan_report(struct hid_device *hid)
(hid->group == HID_GROUP_MULTITOUCH)) (hid->group == HID_GROUP_MULTITOUCH))
hid->group = HID_GROUP_MULTITOUCH_WIN_8; hid->group = HID_GROUP_MULTITOUCH_WIN_8;
/*
* Vendor specific handlings
*/
if ((hid->vendor == USB_VENDOR_ID_SYNAPTICS) &&
(hid->group == HID_GROUP_GENERIC) &&
/* only bind to the mouse interface of composite USB devices */
(hid->bus != BUS_USB || hid->type == HID_TYPE_USBMOUSE))
/* hid-rmi should take care of them, not hid-generic */
hid->group = HID_GROUP_RMI;
/* /*
* Vendor specific handlings * Vendor specific handlings
*/ */
...@@ -796,6 +791,13 @@ static int hid_scan_report(struct hid_device *hid) ...@@ -796,6 +791,13 @@ static int hid_scan_report(struct hid_device *hid)
case USB_VENDOR_ID_WACOM: case USB_VENDOR_ID_WACOM:
hid->group = HID_GROUP_WACOM; hid->group = HID_GROUP_WACOM;
break; break;
case USB_VENDOR_ID_SYNAPTICS:
if ((hid->group == HID_GROUP_GENERIC) &&
(hid->bus != BUS_USB || hid->type == HID_TYPE_USBMOUSE))
/* hid-rmi should only bind to the mouse interface of
* composite USB devices */
hid->group = HID_GROUP_RMI;
break;
} }
vfree(parser); vfree(parser);
...@@ -1280,12 +1282,6 @@ void hid_output_report(struct hid_report *report, __u8 *data) ...@@ -1280,12 +1282,6 @@ void hid_output_report(struct hid_report *report, __u8 *data)
} }
EXPORT_SYMBOL_GPL(hid_output_report); EXPORT_SYMBOL_GPL(hid_output_report);
static int hid_report_len(struct hid_report *report)
{
/* equivalent to DIV_ROUND_UP(report->size, 8) + !!(report->id > 0) */
return ((report->size - 1) >> 3) + 1 + (report->id > 0);
}
/* /*
* Allocator for buffer that is going to be passed to hid_output_report() * Allocator for buffer that is going to be passed to hid_output_report()
*/ */
...@@ -1822,6 +1818,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1822,6 +1818,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_T651) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) },
...@@ -1862,6 +1859,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1862,6 +1859,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
...@@ -1887,6 +1885,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1887,6 +1885,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_6000) }, { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_6000) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
#if IS_ENABLED(CONFIG_HID_ROCCAT) #if IS_ENABLED(CONFIG_HID_ROCCAT)
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
...@@ -1910,10 +1909,12 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1910,10 +1909,12 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9) },
#endif #endif
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) },
...@@ -2539,7 +2540,8 @@ int hid_add_device(struct hid_device *hdev) ...@@ -2539,7 +2540,8 @@ int hid_add_device(struct hid_device *hdev)
* Scan generic devices for group information * Scan generic devices for group information
*/ */
if (hid_ignore_special_drivers || if (hid_ignore_special_drivers ||
!hid_match_id(hdev, hid_have_special_driver)) { (!hdev->group &&
!hid_match_id(hdev, hid_have_special_driver))) {
ret = hid_scan_report(hdev); ret = hid_scan_report(hdev);
if (ret) if (ret)
hid_warn(hdev, "bad device descriptor (%d)\n", ret); hid_warn(hdev, "bad device descriptor (%d)\n", ret);
......
...@@ -300,6 +300,7 @@ ...@@ -300,6 +300,7 @@
#define USB_DEVICE_ID_ELAN_TOUCHSCREEN 0x0089 #define USB_DEVICE_ID_ELAN_TOUCHSCREEN 0x0089
#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B 0x009b #define USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B 0x009b
#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103 0x0103 #define USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103 0x0103
#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_010c 0x010c
#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F 0x016f #define USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F 0x016f
#define USB_VENDOR_ID_ELECOM 0x056e #define USB_VENDOR_ID_ELECOM 0x056e
...@@ -578,6 +579,7 @@ ...@@ -578,6 +579,7 @@
#define USB_VENDOR_ID_LOGITECH 0x046d #define USB_VENDOR_ID_LOGITECH 0x046d
#define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
#define USB_DEVICE_ID_LOGITECH_T651 0xb00c
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
#define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110
#define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f #define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f
...@@ -620,6 +622,7 @@ ...@@ -620,6 +622,7 @@
#define USB_VENDOR_ID_MADCATZ 0x0738 #define USB_VENDOR_ID_MADCATZ 0x0738
#define USB_DEVICE_ID_MADCATZ_BEATPAD 0x4540 #define USB_DEVICE_ID_MADCATZ_BEATPAD 0x4540
#define USB_DEVICE_ID_MADCATZ_RAT9 0x1709
#define USB_VENDOR_ID_MCC 0x09db #define USB_VENDOR_ID_MCC 0x09db
#define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076
...@@ -649,6 +652,7 @@ ...@@ -649,6 +652,7 @@
#define USB_DEVICE_ID_MS_SURFACE_PRO_2 0x0799 #define USB_DEVICE_ID_MS_SURFACE_PRO_2 0x0799
#define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 #define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7
#define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 #define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9
#define USB_DEVICE_ID_MS_TYPE_COVER_3 0x07dc
#define USB_VENDOR_ID_MOJO 0x8282 #define USB_VENDOR_ID_MOJO 0x8282
#define USB_DEVICE_ID_RETRO_ADAPTER 0x3201 #define USB_DEVICE_ID_RETRO_ADAPTER 0x3201
...@@ -716,6 +720,8 @@ ...@@ -716,6 +720,8 @@
#define USB_DEVICE_ID_ORTEK_PKB1700 0x1700 #define USB_DEVICE_ID_ORTEK_PKB1700 0x1700
#define USB_DEVICE_ID_ORTEK_WKB2000 0x2000 #define USB_DEVICE_ID_ORTEK_WKB2000 0x2000
#define USB_VENDOR_ID_PLANTRONICS 0x047f
#define USB_VENDOR_ID_PANASONIC 0x04da #define USB_VENDOR_ID_PANASONIC 0x04da
#define USB_DEVICE_ID_PANABOARD_UBT780 0x1044 #define USB_DEVICE_ID_PANABOARD_UBT780 0x1044
#define USB_DEVICE_ID_PANABOARD_UBT880 0x104d #define USB_DEVICE_ID_PANABOARD_UBT880 0x104d
...@@ -813,6 +819,9 @@ ...@@ -813,6 +819,9 @@
#define USB_VENDOR_ID_SKYCABLE 0x1223 #define USB_VENDOR_ID_SKYCABLE 0x1223
#define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07
#define USB_VENDOR_ID_SMK 0x0609
#define USB_DEVICE_ID_SMK_PS3_BDREMOTE 0x0306
#define USB_VENDOR_ID_SONY 0x054c #define USB_VENDOR_ID_SONY 0x054c
#define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b #define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b
#define USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE 0x0374 #define USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE 0x0374
...@@ -931,6 +940,9 @@ ...@@ -931,6 +940,9 @@
#define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004 #define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004
#define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006 #define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006
#define USB_VENDOR_ID_VTL 0x0306
#define USB_DEVICE_ID_VTL_MULTITOUCH_FF3F 0xff3f
#define USB_VENDOR_ID_WACOM 0x056a #define USB_VENDOR_ID_WACOM 0x056a
#define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81 #define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81
#define USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH 0x00BD #define USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH 0x00BD
......
...@@ -872,7 +872,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel ...@@ -872,7 +872,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x2cb: map_key_clear(KEY_KBDINPUTASSIST_ACCEPT); break; case 0x2cb: map_key_clear(KEY_KBDINPUTASSIST_ACCEPT); break;
case 0x2cc: map_key_clear(KEY_KBDINPUTASSIST_CANCEL); break; case 0x2cc: map_key_clear(KEY_KBDINPUTASSIST_CANCEL); break;
default: goto ignore; default: map_key_clear(KEY_UNKNOWN);
} }
break; break;
...@@ -1215,7 +1215,7 @@ static void hidinput_led_worker(struct work_struct *work) ...@@ -1215,7 +1215,7 @@ static void hidinput_led_worker(struct work_struct *work)
return hid->ll_driver->request(hid, report, HID_REQ_SET_REPORT); return hid->ll_driver->request(hid, report, HID_REQ_SET_REPORT);
/* fall back to generic raw-output-report */ /* fall back to generic raw-output-report */
len = ((report->size - 1) >> 3) + 1 + (report->id > 0); len = hid_report_len(report);
buf = hid_alloc_report_buf(report, GFP_KERNEL); buf = hid_alloc_report_buf(report, GFP_KERNEL);
if (!buf) if (!buf)
return; return;
......
...@@ -62,7 +62,6 @@ static int lenovo_input_mapping_cptkbd(struct hid_device *hdev, ...@@ -62,7 +62,6 @@ static int lenovo_input_mapping_cptkbd(struct hid_device *hdev,
/* HID_UP_LNVENDOR = USB, HID_UP_MSVENDOR = BT */ /* HID_UP_LNVENDOR = USB, HID_UP_MSVENDOR = BT */
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR || if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR ||
(usage->hid & HID_USAGE_PAGE) == HID_UP_LNVENDOR) { (usage->hid & HID_USAGE_PAGE) == HID_UP_LNVENDOR) {
set_bit(EV_REP, hi->input->evbit);
switch (usage->hid & HID_USAGE) { switch (usage->hid & HID_USAGE) {
case 0x00f1: /* Fn-F4: Mic mute */ case 0x00f1: /* Fn-F4: Mic mute */
map_key_clear(KEY_MICMUTE); map_key_clear(KEY_MICMUTE);
...@@ -85,13 +84,13 @@ static int lenovo_input_mapping_cptkbd(struct hid_device *hdev, ...@@ -85,13 +84,13 @@ static int lenovo_input_mapping_cptkbd(struct hid_device *hdev,
case 0x00f8: /* Fn-F11: View open applications (3 boxes) */ case 0x00f8: /* Fn-F11: View open applications (3 boxes) */
map_key_clear(KEY_SCALE); map_key_clear(KEY_SCALE);
return 1; return 1;
case 0x00fa: /* Fn-Esc: Fn-lock toggle */ case 0x00f9: /* Fn-F12: Open My computer (6 boxes) USB-only */
map_key_clear(KEY_FN_ESC);
return 1;
case 0x00fb: /* Fn-F12: Open My computer (6 boxes) USB-only */
/* NB: This mapping is invented in raw_event below */ /* NB: This mapping is invented in raw_event below */
map_key_clear(KEY_FILE); map_key_clear(KEY_FILE);
return 1; return 1;
case 0x00fa: /* Fn-Esc: Fn-lock toggle */
map_key_clear(KEY_FN_ESC);
return 1;
} }
} }
...@@ -207,8 +206,8 @@ static int lenovo_raw_event(struct hid_device *hdev, ...@@ -207,8 +206,8 @@ static int lenovo_raw_event(struct hid_device *hdev,
&& data[0] == 0x15 && data[0] == 0x15
&& data[1] == 0x94 && data[1] == 0x94
&& data[2] == 0x01)) { && data[2] == 0x01)) {
data[1] = 0x0; data[1] = 0x00;
data[2] = 0x4; data[2] = 0x01;
} }
return 0; return 0;
......
This diff is collapsed.
#ifndef __HID_LOGITECH_DJ_H
#define __HID_LOGITECH_DJ_H
/*
* HID driver for Logitech Unifying receivers
*
* Copyright (c) 2011 Logitech
*/
/*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/kfifo.h>
#define DJ_MAX_PAIRED_DEVICES 6
#define DJ_MAX_NUMBER_NOTIFICATIONS 8
#define DJ_RECEIVER_INDEX 0
#define DJ_DEVICE_INDEX_MIN 1
#define DJ_DEVICE_INDEX_MAX 6
#define DJREPORT_SHORT_LENGTH 15
#define DJREPORT_LONG_LENGTH 32
#define REPORT_ID_DJ_SHORT 0x20
#define REPORT_ID_DJ_LONG 0x21
#define REPORT_TYPE_RFREPORT_FIRST 0x01
#define REPORT_TYPE_RFREPORT_LAST 0x1F
/* Command Switch to DJ mode */
#define REPORT_TYPE_CMD_SWITCH 0x80
#define CMD_SWITCH_PARAM_DEVBITFIELD 0x00
#define CMD_SWITCH_PARAM_TIMEOUT_SECONDS 0x01
#define TIMEOUT_NO_KEEPALIVE 0x00
/* Command to Get the list of Paired devices */
#define REPORT_TYPE_CMD_GET_PAIRED_DEVICES 0x81
/* Device Paired Notification */
#define REPORT_TYPE_NOTIF_DEVICE_PAIRED 0x41
#define SPFUNCTION_MORE_NOTIF_EXPECTED 0x01
#define SPFUNCTION_DEVICE_LIST_EMPTY 0x02
#define DEVICE_PAIRED_PARAM_SPFUNCTION 0x00
#define DEVICE_PAIRED_PARAM_EQUAD_ID_LSB 0x01
#define DEVICE_PAIRED_PARAM_EQUAD_ID_MSB 0x02
#define DEVICE_PAIRED_RF_REPORT_TYPE 0x03
/* Device Un-Paired Notification */
#define REPORT_TYPE_NOTIF_DEVICE_UNPAIRED 0x40
/* Connection Status Notification */
#define REPORT_TYPE_NOTIF_CONNECTION_STATUS 0x42
#define CONNECTION_STATUS_PARAM_STATUS 0x00
#define STATUS_LINKLOSS 0x01
/* Error Notification */
#define REPORT_TYPE_NOTIF_ERROR 0x7F
#define NOTIF_ERROR_PARAM_ETYPE 0x00
#define ETYPE_KEEPALIVE_TIMEOUT 0x01
/* supported DJ HID && RF report types */
#define REPORT_TYPE_KEYBOARD 0x01
#define REPORT_TYPE_MOUSE 0x02
#define REPORT_TYPE_CONSUMER_CONTROL 0x03
#define REPORT_TYPE_SYSTEM_CONTROL 0x04
#define REPORT_TYPE_MEDIA_CENTER 0x08
#define REPORT_TYPE_LEDS 0x0E
/* RF Report types bitfield */
#define STD_KEYBOARD 0x00000002
#define STD_MOUSE 0x00000004
#define MULTIMEDIA 0x00000008
#define POWER_KEYS 0x00000010
#define MEDIA_CENTER 0x00000100
#define KBD_LEDS 0x00004000
struct dj_report {
u8 report_id;
u8 device_index;
u8 report_type;
u8 report_params[DJREPORT_SHORT_LENGTH - 3];
};
struct dj_receiver_dev {
struct hid_device *hdev;
struct dj_device *paired_dj_devices[DJ_MAX_PAIRED_DEVICES +
DJ_DEVICE_INDEX_MIN];
struct work_struct work;
struct kfifo notif_fifo;
spinlock_t lock;
bool querying_devices;
};
struct dj_device {
struct hid_device *hdev;
struct dj_receiver_dev *dj_receiver_dev;
u32 reports_supported;
u8 device_index;
};
/**
* is_dj_device - know if the given dj_device is not the receiver.
* @dj_dev: the dj device to test
*
* This macro tests if a struct dj_device pointer is a device created
* by the bus enumarator.
*/
#define is_dj_device(dj_dev) \
(&(dj_dev)->dj_receiver_dev->hdev->dev == (dj_dev)->hdev->dev.parent)
#endif
This diff is collapsed.
...@@ -274,6 +274,8 @@ static const struct hid_device_id ms_devices[] = { ...@@ -274,6 +274,8 @@ static const struct hid_device_id ms_devices[] = {
.driver_data = MS_NOGET }, .driver_data = MS_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
.driver_data = MS_DUPLICATE_USAGES }, .driver_data = MS_DUPLICATE_USAGES },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3),
.driver_data = MS_HIDINPUT },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT), { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT),
.driver_data = MS_PRESENTER }, .driver_data = MS_PRESENTER },
......
...@@ -67,6 +67,7 @@ MODULE_LICENSE("GPL"); ...@@ -67,6 +67,7 @@ MODULE_LICENSE("GPL");
#define MT_QUIRK_IGNORE_DUPLICATES (1 << 10) #define MT_QUIRK_IGNORE_DUPLICATES (1 << 10)
#define MT_QUIRK_HOVERING (1 << 11) #define MT_QUIRK_HOVERING (1 << 11)
#define MT_QUIRK_CONTACT_CNT_ACCURATE (1 << 12) #define MT_QUIRK_CONTACT_CNT_ACCURATE (1 << 12)
#define MT_QUIRK_FORCE_GET_FEATURE (1 << 13)
#define MT_INPUTMODE_TOUCHSCREEN 0x02 #define MT_INPUTMODE_TOUCHSCREEN 0x02
#define MT_INPUTMODE_TOUCHPAD 0x03 #define MT_INPUTMODE_TOUCHPAD 0x03
...@@ -150,6 +151,7 @@ static void mt_post_parse(struct mt_device *td); ...@@ -150,6 +151,7 @@ static void mt_post_parse(struct mt_device *td);
#define MT_CLS_FLATFROG 0x0107 #define MT_CLS_FLATFROG 0x0107
#define MT_CLS_GENERALTOUCH_TWOFINGERS 0x0108 #define MT_CLS_GENERALTOUCH_TWOFINGERS 0x0108
#define MT_CLS_GENERALTOUCH_PWT_TENFINGERS 0x0109 #define MT_CLS_GENERALTOUCH_PWT_TENFINGERS 0x0109
#define MT_CLS_VTL 0x0110
#define MT_DEFAULT_MAXCONTACT 10 #define MT_DEFAULT_MAXCONTACT 10
#define MT_MAX_MAXCONTACT 250 #define MT_MAX_MAXCONTACT 250
...@@ -255,6 +257,11 @@ static struct mt_class mt_classes[] = { ...@@ -255,6 +257,11 @@ static struct mt_class mt_classes[] = {
.sn_move = 2048, .sn_move = 2048,
.maxcontacts = 40, .maxcontacts = 40,
}, },
{ .name = MT_CLS_VTL,
.quirks = MT_QUIRK_ALWAYS_VALID |
MT_QUIRK_CONTACT_CNT_ACCURATE |
MT_QUIRK_FORCE_GET_FEATURE,
},
{ } { }
}; };
...@@ -809,6 +816,9 @@ static void mt_set_input_mode(struct hid_device *hdev) ...@@ -809,6 +816,9 @@ static void mt_set_input_mode(struct hid_device *hdev)
struct mt_device *td = hid_get_drvdata(hdev); struct mt_device *td = hid_get_drvdata(hdev);
struct hid_report *r; struct hid_report *r;
struct hid_report_enum *re; struct hid_report_enum *re;
struct mt_class *cls = &td->mtclass;
char *buf;
int report_len;
if (td->inputmode < 0) if (td->inputmode < 0)
return; return;
...@@ -816,6 +826,18 @@ static void mt_set_input_mode(struct hid_device *hdev) ...@@ -816,6 +826,18 @@ static void mt_set_input_mode(struct hid_device *hdev)
re = &(hdev->report_enum[HID_FEATURE_REPORT]); re = &(hdev->report_enum[HID_FEATURE_REPORT]);
r = re->report_id_hash[td->inputmode]; r = re->report_id_hash[td->inputmode];
if (r) { if (r) {
if (cls->quirks & MT_QUIRK_FORCE_GET_FEATURE) {
report_len = hid_report_len(r);
buf = hid_alloc_report_buf(r, GFP_KERNEL);
if (!buf) {
hid_err(hdev, "failed to allocate buffer for report\n");
return;
}
hid_hw_raw_request(hdev, r->id, buf, report_len,
HID_FEATURE_REPORT,
HID_REQ_GET_REPORT);
kfree(buf);
}
r->field[0]->value[td->inputmode_index] = td->inputmode_value; r->field[0]->value[td->inputmode_index] = td->inputmode_value;
hid_hw_request(hdev, r, HID_REQ_SET_REPORT); hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
} }
...@@ -1281,6 +1303,11 @@ static const struct hid_device_id mt_devices[] = { ...@@ -1281,6 +1303,11 @@ static const struct hid_device_id mt_devices[] = {
MT_USB_DEVICE(USB_VENDOR_ID_UNITEC, MT_USB_DEVICE(USB_VENDOR_ID_UNITEC,
USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) }, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
/* VTL panels */
{ .driver_data = MT_CLS_VTL,
MT_USB_DEVICE(USB_VENDOR_ID_VTL,
USB_DEVICE_ID_VTL_MULTITOUCH_FF3F) },
/* Wistron panels */ /* Wistron panels */
{ .driver_data = MT_CLS_NSMU, { .driver_data = MT_CLS_NSMU,
MT_USB_DEVICE(USB_VENDOR_ID_WISTRON, MT_USB_DEVICE(USB_VENDOR_ID_WISTRON,
......
/*
* Plantronics USB HID Driver
*
* Copyright (c) 2014 JD Cole <jd.cole@plantronics.com>
* Copyright (c) 2014 Terry Junge <terry.junge@plantronics.com>
*/
/*
* 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 "hid-ids.h"
#include <linux/hid.h>
#include <linux/module.h>
static int plantronics_input_mapping(struct hid_device *hdev,
struct hid_input *hi,
struct hid_field *field,
struct hid_usage *usage,
unsigned long **bit, int *max)
{
if (field->application == HID_CP_CONSUMERCONTROL
&& (usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) {
hid_dbg(hdev, "usage: %08x (appl: %08x) - defaulted\n",
usage->hid, field->application);
return 0;
}
hid_dbg(hdev, "usage: %08x (appl: %08x) - ignored\n",
usage->hid, field->application);
return -1;
}
static const struct hid_device_id plantronics_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) },
{ }
};
MODULE_DEVICE_TABLE(hid, plantronics_devices);
static struct hid_driver plantronics_driver = {
.name = "plantronics",
.id_table = plantronics_devices,
.input_mapping = plantronics_input_mapping,
};
module_hid_driver(plantronics_driver);
MODULE_AUTHOR("JD Cole <jd.cole@plantronics.com>");
MODULE_AUTHOR("Terry Junge <terry.junge@plantronics.com>");
MODULE_DESCRIPTION("Plantronics USB HID Driver");
MODULE_LICENSE("GPL");
...@@ -584,11 +584,15 @@ static int rmi_populate_f11(struct hid_device *hdev) ...@@ -584,11 +584,15 @@ static int rmi_populate_f11(struct hid_device *hdev)
bool has_query10 = false; bool has_query10 = false;
bool has_query11; bool has_query11;
bool has_query12; bool has_query12;
bool has_query27;
bool has_query28;
bool has_query36 = false;
bool has_physical_props; bool has_physical_props;
bool has_gestures; bool has_gestures;
bool has_rel; bool has_rel;
bool has_data40 = false;
unsigned x_size, y_size; unsigned x_size, y_size;
u16 query12_offset; u16 query_offset;
if (!data->f11.query_base_addr) { if (!data->f11.query_base_addr) {
hid_err(hdev, "No 2D sensor found, giving up.\n"); hid_err(hdev, "No 2D sensor found, giving up.\n");
...@@ -604,6 +608,8 @@ static int rmi_populate_f11(struct hid_device *hdev) ...@@ -604,6 +608,8 @@ static int rmi_populate_f11(struct hid_device *hdev)
has_query9 = !!(buf[0] & BIT(3)); has_query9 = !!(buf[0] & BIT(3));
has_query11 = !!(buf[0] & BIT(4)); has_query11 = !!(buf[0] & BIT(4));
has_query12 = !!(buf[0] & BIT(5)); has_query12 = !!(buf[0] & BIT(5));
has_query27 = !!(buf[0] & BIT(6));
has_query28 = !!(buf[0] & BIT(7));
/* query 1 to get the max number of fingers */ /* query 1 to get the max number of fingers */
ret = rmi_read(hdev, data->f11.query_base_addr + 1, buf); ret = rmi_read(hdev, data->f11.query_base_addr + 1, buf);
...@@ -626,43 +632,43 @@ static int rmi_populate_f11(struct hid_device *hdev) ...@@ -626,43 +632,43 @@ static int rmi_populate_f11(struct hid_device *hdev)
has_rel = !!(buf[0] & BIT(3)); has_rel = !!(buf[0] & BIT(3));
has_gestures = !!(buf[0] & BIT(5)); has_gestures = !!(buf[0] & BIT(5));
/*
* At least 4 queries are guaranteed to be present in F11
* +1 for query 5 which is present since absolute events are
* reported and +1 for query 12.
*/
query_offset = 6;
if (has_rel)
++query_offset; /* query 6 is present */
if (has_gestures) { if (has_gestures) {
/* query 8 to find out if query 10 exists */ /* query 8 to find out if query 10 exists */
ret = rmi_read(hdev, data->f11.query_base_addr + 8, buf); ret = rmi_read(hdev,
data->f11.query_base_addr + query_offset + 1, buf);
if (ret) { if (ret) {
hid_err(hdev, "can not read gesture information: %d.\n", hid_err(hdev, "can not read gesture information: %d.\n",
ret); ret);
return ret; return ret;
} }
has_query10 = !!(buf[0] & BIT(2)); has_query10 = !!(buf[0] & BIT(2));
}
/* query_offset += 2; /* query 7 and 8 are present */
* At least 4 queries are guaranteed to be present in F11 }
* +1 for query 5 which is present since absolute events are
* reported and +1 for query 12.
*/
query12_offset = 6;
if (has_rel)
++query12_offset; /* query 6 is present */
if (has_gestures)
query12_offset += 2; /* query 7 and 8 are present */
if (has_query9) if (has_query9)
++query12_offset; ++query_offset;
if (has_query10) if (has_query10)
++query12_offset; ++query_offset;
if (has_query11) if (has_query11)
++query12_offset; ++query_offset;
/* query 12 to know if the physical properties are reported */ /* query 12 to know if the physical properties are reported */
if (has_query12) { if (has_query12) {
ret = rmi_read(hdev, data->f11.query_base_addr ret = rmi_read(hdev, data->f11.query_base_addr
+ query12_offset, buf); + query_offset, buf);
if (ret) { if (ret) {
hid_err(hdev, "can not get query 12: %d.\n", ret); hid_err(hdev, "can not get query 12: %d.\n", ret);
return ret; return ret;
...@@ -670,9 +676,10 @@ static int rmi_populate_f11(struct hid_device *hdev) ...@@ -670,9 +676,10 @@ static int rmi_populate_f11(struct hid_device *hdev)
has_physical_props = !!(buf[0] & BIT(5)); has_physical_props = !!(buf[0] & BIT(5));
if (has_physical_props) { if (has_physical_props) {
query_offset += 1;
ret = rmi_read_block(hdev, ret = rmi_read_block(hdev,
data->f11.query_base_addr data->f11.query_base_addr
+ query12_offset + 1, buf, 4); + query_offset, buf, 4);
if (ret) { if (ret) {
hid_err(hdev, "can not read query 15-18: %d.\n", hid_err(hdev, "can not read query 15-18: %d.\n",
ret); ret);
...@@ -687,9 +694,45 @@ static int rmi_populate_f11(struct hid_device *hdev) ...@@ -687,9 +694,45 @@ static int rmi_populate_f11(struct hid_device *hdev)
hid_info(hdev, "%s: size in mm: %d x %d\n", hid_info(hdev, "%s: size in mm: %d x %d\n",
__func__, data->x_size_mm, data->y_size_mm); __func__, data->x_size_mm, data->y_size_mm);
/*
* query 15 - 18 contain the size of the sensor
* and query 19 - 26 contain bezel dimensions
*/
query_offset += 12;
}
}
if (has_query27)
++query_offset;
if (has_query28) {
ret = rmi_read(hdev, data->f11.query_base_addr
+ query_offset, buf);
if (ret) {
hid_err(hdev, "can not get query 28: %d.\n", ret);
return ret;
}
has_query36 = !!(buf[0] & BIT(6));
}
if (has_query36) {
query_offset += 2;
ret = rmi_read(hdev, data->f11.query_base_addr
+ query_offset, buf);
if (ret) {
hid_err(hdev, "can not get query 36: %d.\n", ret);
return ret;
} }
has_data40 = !!(buf[0] & BIT(5));
} }
if (has_data40)
data->f11.report_size += data->max_fingers * 2;
/* /*
* retrieve the ctrl registers * retrieve the ctrl registers
* the ctrl register has a size of 20 but a fw bug split it into 16 + 4, * the ctrl register has a size of 20 but a fw bug split it into 16 + 4,
......
...@@ -46,6 +46,7 @@ static void kone_profile_activated(struct kone_device *kone, uint new_profile) ...@@ -46,6 +46,7 @@ static void kone_profile_activated(struct kone_device *kone, uint new_profile)
static void kone_profile_report(struct kone_device *kone, uint new_profile) static void kone_profile_report(struct kone_device *kone, uint new_profile)
{ {
struct kone_roccat_report roccat_report; struct kone_roccat_report roccat_report;
roccat_report.event = kone_mouse_event_switch_profile; roccat_report.event = kone_mouse_event_switch_profile;
roccat_report.value = new_profile; roccat_report.value = new_profile;
roccat_report.key = 0; roccat_report.key = 0;
...@@ -163,6 +164,7 @@ static int kone_set_settings(struct usb_device *usb_dev, ...@@ -163,6 +164,7 @@ static int kone_set_settings(struct usb_device *usb_dev,
struct kone_settings const *settings) struct kone_settings const *settings)
{ {
int retval; int retval;
retval = kone_send(usb_dev, kone_command_settings, retval = kone_send(usb_dev, kone_command_settings,
settings, sizeof(struct kone_settings)); settings, sizeof(struct kone_settings));
if (retval) if (retval)
...@@ -387,7 +389,7 @@ static struct bin_attribute bin_attr_profile##number = { \ ...@@ -387,7 +389,7 @@ static struct bin_attribute bin_attr_profile##number = { \
.read = kone_sysfs_read_profilex, \ .read = kone_sysfs_read_profilex, \
.write = kone_sysfs_write_profilex, \ .write = kone_sysfs_write_profilex, \
.private = &profile_numbers[number-1], \ .private = &profile_numbers[number-1], \
}; }
PROFILE_ATTR(1); PROFILE_ATTR(1);
PROFILE_ATTR(2); PROFILE_ATTR(2);
PROFILE_ATTR(3); PROFILE_ATTR(3);
...@@ -456,6 +458,7 @@ static ssize_t kone_sysfs_show_tcu(struct device *dev, ...@@ -456,6 +458,7 @@ static ssize_t kone_sysfs_show_tcu(struct device *dev,
static int kone_tcu_command(struct usb_device *usb_dev, int number) static int kone_tcu_command(struct usb_device *usb_dev, int number)
{ {
unsigned char value; unsigned char value;
value = number; value = number;
return kone_send(usb_dev, kone_command_calibrate, &value, 1); return kone_send(usb_dev, kone_command_calibrate, &value, 1);
} }
...@@ -697,10 +700,8 @@ static int kone_init_specials(struct hid_device *hdev) ...@@ -697,10 +700,8 @@ static int kone_init_specials(struct hid_device *hdev)
== USB_INTERFACE_PROTOCOL_MOUSE) { == USB_INTERFACE_PROTOCOL_MOUSE) {
kone = kzalloc(sizeof(*kone), GFP_KERNEL); kone = kzalloc(sizeof(*kone), GFP_KERNEL);
if (!kone) { if (!kone)
hid_err(hdev, "can't alloc device descriptor\n");
return -ENOMEM; return -ENOMEM;
}
hid_set_drvdata(hdev, kone); hid_set_drvdata(hdev, kone);
retval = kone_init_kone_device_struct(usb_dev, kone); retval = kone_init_kone_device_struct(usb_dev, kone);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* (This module is based on "hid-ortek".) * (This module is based on "hid-ortek".)
* Copyright (c) 2012 Andreas Hübner * Copyright (c) 2012 Andreas Hübner
* *
* R.A.T.7, M.M.O.7 (USB gaming mice): * R.A.T.7, R.A.T.9, M.M.O.7 (USB gaming mice):
* Fixes the mode button which cycles through three constantly pressed * Fixes the mode button which cycles through three constantly pressed
* buttons. All three press events are mapped to one button and the * buttons. All three press events are mapped to one button and the
* missing release event is generated immediately. * missing release event is generated immediately.
...@@ -179,6 +179,8 @@ static const struct hid_device_id saitek_devices[] = { ...@@ -179,6 +179,8 @@ static const struct hid_device_id saitek_devices[] = {
.driver_data = SAITEK_FIX_PS1000 }, .driver_data = SAITEK_FIX_PS1000 },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7), { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7),
.driver_data = SAITEK_RELEASE_MODE_RAT7 }, .driver_data = SAITEK_RELEASE_MODE_RAT7 },
{ HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9),
.driver_data = SAITEK_RELEASE_MODE_RAT7 },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7), { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7),
.driver_data = SAITEK_RELEASE_MODE_MMO7 }, .driver_data = SAITEK_RELEASE_MODE_MMO7 },
{ } { }
......
...@@ -798,6 +798,12 @@ union sixaxis_output_report_01 { ...@@ -798,6 +798,12 @@ union sixaxis_output_report_01 {
__u8 buf[36]; __u8 buf[36];
}; };
#define DS4_REPORT_0x02_SIZE 37
#define DS4_REPORT_0x05_SIZE 32
#define DS4_REPORT_0x11_SIZE 78
#define DS4_REPORT_0x81_SIZE 7
#define SIXAXIS_REPORT_0xF2_SIZE 18
static spinlock_t sony_dev_list_lock; static spinlock_t sony_dev_list_lock;
static LIST_HEAD(sony_device_list); static LIST_HEAD(sony_device_list);
static DEFINE_IDA(sony_device_id_allocator); static DEFINE_IDA(sony_device_id_allocator);
...@@ -811,6 +817,7 @@ struct sony_sc { ...@@ -811,6 +817,7 @@ struct sony_sc {
struct work_struct state_worker; struct work_struct state_worker;
struct power_supply battery; struct power_supply battery;
int device_id; int device_id;
__u8 *output_report_dmabuf;
#ifdef CONFIG_SONY_FF #ifdef CONFIG_SONY_FF
__u8 left; __u8 left;
...@@ -1142,9 +1149,20 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev) ...@@ -1142,9 +1149,20 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev)
static int sixaxis_set_operational_bt(struct hid_device *hdev) static int sixaxis_set_operational_bt(struct hid_device *hdev)
{ {
unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; static const __u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 };
return hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf), __u8 *buf;
int ret;
buf = kmemdup(report, sizeof(report), GFP_KERNEL);
if (!buf)
return -ENOMEM;
ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report),
HID_FEATURE_REPORT, HID_REQ_SET_REPORT); HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
kfree(buf);
return ret;
} }
/* /*
...@@ -1153,10 +1171,19 @@ static int sixaxis_set_operational_bt(struct hid_device *hdev) ...@@ -1153,10 +1171,19 @@ static int sixaxis_set_operational_bt(struct hid_device *hdev)
*/ */
static int dualshock4_set_operational_bt(struct hid_device *hdev) static int dualshock4_set_operational_bt(struct hid_device *hdev)
{ {
__u8 buf[37] = { 0 }; __u8 *buf;
int ret;
buf = kmalloc(DS4_REPORT_0x02_SIZE, GFP_KERNEL);
if (!buf)
return -ENOMEM;
return hid_hw_raw_request(hdev, 0x02, buf, sizeof(buf), ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_REPORT_0x02_SIZE,
HID_FEATURE_REPORT, HID_REQ_GET_REPORT); HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
kfree(buf);
return ret;
} }
static void sixaxis_set_leds_from_id(int id, __u8 values[MAX_LEDS]) static void sixaxis_set_leds_from_id(int id, __u8 values[MAX_LEDS])
...@@ -1471,9 +1498,7 @@ static int sony_leds_init(struct sony_sc *sc) ...@@ -1471,9 +1498,7 @@ static int sony_leds_init(struct sony_sc *sc)
static void sixaxis_state_worker(struct work_struct *work) static void sixaxis_state_worker(struct work_struct *work)
{ {
struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); static const union sixaxis_output_report_01 default_report = {
int n;
union sixaxis_output_report_01 report = {
.buf = { .buf = {
0x01, 0x01,
0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00,
...@@ -1485,20 +1510,27 @@ static void sixaxis_state_worker(struct work_struct *work) ...@@ -1485,20 +1510,27 @@ static void sixaxis_state_worker(struct work_struct *work)
0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00
} }
}; };
struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
struct sixaxis_output_report *report =
(struct sixaxis_output_report *)sc->output_report_dmabuf;
int n;
/* Initialize the report with default values */
memcpy(report, &default_report, sizeof(struct sixaxis_output_report));
#ifdef CONFIG_SONY_FF #ifdef CONFIG_SONY_FF
report.data.rumble.right_motor_on = sc->right ? 1 : 0; report->rumble.right_motor_on = sc->right ? 1 : 0;
report.data.rumble.left_motor_force = sc->left; report->rumble.left_motor_force = sc->left;
#endif #endif
report.data.leds_bitmap |= sc->led_state[0] << 1; report->leds_bitmap |= sc->led_state[0] << 1;
report.data.leds_bitmap |= sc->led_state[1] << 2; report->leds_bitmap |= sc->led_state[1] << 2;
report.data.leds_bitmap |= sc->led_state[2] << 3; report->leds_bitmap |= sc->led_state[2] << 3;
report.data.leds_bitmap |= sc->led_state[3] << 4; report->leds_bitmap |= sc->led_state[3] << 4;
/* Set flag for all leds off, required for 3rd party INTEC controller */ /* Set flag for all leds off, required for 3rd party INTEC controller */
if ((report.data.leds_bitmap & 0x1E) == 0) if ((report->leds_bitmap & 0x1E) == 0)
report.data.leds_bitmap |= 0x20; report->leds_bitmap |= 0x20;
/* /*
* The LEDs in the report are indexed in reverse order to their * The LEDs in the report are indexed in reverse order to their
...@@ -1511,28 +1543,30 @@ static void sixaxis_state_worker(struct work_struct *work) ...@@ -1511,28 +1543,30 @@ static void sixaxis_state_worker(struct work_struct *work)
*/ */
for (n = 0; n < 4; n++) { for (n = 0; n < 4; n++) {
if (sc->led_delay_on[n] || sc->led_delay_off[n]) { if (sc->led_delay_on[n] || sc->led_delay_off[n]) {
report.data.led[3 - n].duty_off = sc->led_delay_off[n]; report->led[3 - n].duty_off = sc->led_delay_off[n];
report.data.led[3 - n].duty_on = sc->led_delay_on[n]; report->led[3 - n].duty_on = sc->led_delay_on[n];
} }
} }
hid_hw_raw_request(sc->hdev, report.data.report_id, report.buf, hid_hw_raw_request(sc->hdev, report->report_id, (__u8 *)report,
sizeof(report), HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); sizeof(struct sixaxis_output_report),
HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
} }
static void dualshock4_state_worker(struct work_struct *work) static void dualshock4_state_worker(struct work_struct *work)
{ {
struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
struct hid_device *hdev = sc->hdev; struct hid_device *hdev = sc->hdev;
__u8 *buf = sc->output_report_dmabuf;
int offset; int offset;
__u8 buf[78] = { 0 };
if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
memset(buf, 0, DS4_REPORT_0x05_SIZE);
buf[0] = 0x05; buf[0] = 0x05;
buf[1] = 0xFF; buf[1] = 0xFF;
offset = 4; offset = 4;
} else { } else {
memset(buf, 0, DS4_REPORT_0x11_SIZE);
buf[0] = 0x11; buf[0] = 0x11;
buf[1] = 0xB0; buf[1] = 0xB0;
buf[3] = 0x0F; buf[3] = 0x0F;
...@@ -1560,12 +1594,33 @@ static void dualshock4_state_worker(struct work_struct *work) ...@@ -1560,12 +1594,33 @@ static void dualshock4_state_worker(struct work_struct *work)
buf[offset++] = sc->led_delay_off[3]; buf[offset++] = sc->led_delay_off[3];
if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
hid_hw_output_report(hdev, buf, 32); hid_hw_output_report(hdev, buf, DS4_REPORT_0x05_SIZE);
else else
hid_hw_raw_request(hdev, 0x11, buf, 78, hid_hw_raw_request(hdev, 0x11, buf, DS4_REPORT_0x11_SIZE,
HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
} }
static int sony_allocate_output_report(struct sony_sc *sc)
{
if (sc->quirks & SIXAXIS_CONTROLLER)
sc->output_report_dmabuf =
kmalloc(sizeof(union sixaxis_output_report_01),
GFP_KERNEL);
else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x11_SIZE,
GFP_KERNEL);
else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE,
GFP_KERNEL);
else
return 0;
if (!sc->output_report_dmabuf)
return -ENOMEM;
return 0;
}
#ifdef CONFIG_SONY_FF #ifdef CONFIG_SONY_FF
static int sony_play_effect(struct input_dev *dev, void *data, static int sony_play_effect(struct input_dev *dev, void *data,
struct ff_effect *effect) struct ff_effect *effect)
...@@ -1754,6 +1809,7 @@ static int sony_get_bt_devaddr(struct sony_sc *sc) ...@@ -1754,6 +1809,7 @@ static int sony_get_bt_devaddr(struct sony_sc *sc)
static int sony_check_add(struct sony_sc *sc) static int sony_check_add(struct sony_sc *sc)
{ {
__u8 *buf = NULL;
int n, ret; int n, ret;
if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) || if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) ||
...@@ -1769,36 +1825,44 @@ static int sony_check_add(struct sony_sc *sc) ...@@ -1769,36 +1825,44 @@ static int sony_check_add(struct sony_sc *sc)
return 0; return 0;
} }
} else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { } else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
__u8 buf[7]; buf = kmalloc(DS4_REPORT_0x81_SIZE, GFP_KERNEL);
if (!buf)
return -ENOMEM;
/* /*
* The MAC address of a DS4 controller connected via USB can be * The MAC address of a DS4 controller connected via USB can be
* retrieved with feature report 0x81. The address begins at * retrieved with feature report 0x81. The address begins at
* offset 1. * offset 1.
*/ */
ret = hid_hw_raw_request(sc->hdev, 0x81, buf, sizeof(buf), ret = hid_hw_raw_request(sc->hdev, 0x81, buf,
HID_FEATURE_REPORT, HID_REQ_GET_REPORT); DS4_REPORT_0x81_SIZE, HID_FEATURE_REPORT,
HID_REQ_GET_REPORT);
if (ret != 7) { if (ret != DS4_REPORT_0x81_SIZE) {
hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n"); hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n");
return ret < 0 ? ret : -EINVAL; ret = ret < 0 ? ret : -EINVAL;
goto out_free;
} }
memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address)); memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address));
} else if (sc->quirks & SIXAXIS_CONTROLLER_USB) { } else if (sc->quirks & SIXAXIS_CONTROLLER_USB) {
__u8 buf[18]; buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL);
if (!buf)
return -ENOMEM;
/* /*
* The MAC address of a Sixaxis controller connected via USB can * The MAC address of a Sixaxis controller connected via USB can
* be retrieved with feature report 0xf2. The address begins at * be retrieved with feature report 0xf2. The address begins at
* offset 4. * offset 4.
*/ */
ret = hid_hw_raw_request(sc->hdev, 0xf2, buf, sizeof(buf), ret = hid_hw_raw_request(sc->hdev, 0xf2, buf,
HID_FEATURE_REPORT, HID_REQ_GET_REPORT); SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT,
HID_REQ_GET_REPORT);
if (ret != 18) { if (ret != SIXAXIS_REPORT_0xF2_SIZE) {
hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n"); hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n");
return ret < 0 ? ret : -EINVAL; ret = ret < 0 ? ret : -EINVAL;
goto out_free;
} }
/* /*
...@@ -1811,7 +1875,13 @@ static int sony_check_add(struct sony_sc *sc) ...@@ -1811,7 +1875,13 @@ static int sony_check_add(struct sony_sc *sc)
return 0; return 0;
} }
return sony_check_add_dev_list(sc); ret = sony_check_add_dev_list(sc);
out_free:
kfree(buf);
return ret;
} }
static int sony_set_device_id(struct sony_sc *sc) static int sony_set_device_id(struct sony_sc *sc)
...@@ -1895,6 +1965,12 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -1895,6 +1965,12 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
return ret; return ret;
} }
ret = sony_allocate_output_report(sc);
if (ret < 0) {
hid_err(hdev, "failed to allocate the output report buffer\n");
goto err_stop;
}
ret = sony_set_device_id(sc); ret = sony_set_device_id(sc);
if (ret < 0) { if (ret < 0) {
hid_err(hdev, "failed to allocate the device id\n"); hid_err(hdev, "failed to allocate the device id\n");
...@@ -1984,6 +2060,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -1984,6 +2060,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (sc->quirks & SONY_BATTERY_SUPPORT) if (sc->quirks & SONY_BATTERY_SUPPORT)
sony_battery_remove(sc); sony_battery_remove(sc);
sony_cancel_work_sync(sc); sony_cancel_work_sync(sc);
kfree(sc->output_report_dmabuf);
sony_remove_dev_list(sc); sony_remove_dev_list(sc);
sony_release_device_id(sc); sony_release_device_id(sc);
hid_hw_stop(hdev); hid_hw_stop(hdev);
...@@ -2004,6 +2081,8 @@ static void sony_remove(struct hid_device *hdev) ...@@ -2004,6 +2081,8 @@ static void sony_remove(struct hid_device *hdev)
sony_cancel_work_sync(sc); sony_cancel_work_sync(sc);
kfree(sc->output_report_dmabuf);
sony_remove_dev_list(sc); sony_remove_dev_list(sc);
sony_release_device_id(sc); sony_release_device_id(sc);
...@@ -2034,6 +2113,9 @@ static const struct hid_device_id sony_devices[] = { ...@@ -2034,6 +2113,9 @@ static const struct hid_device_id sony_devices[] = {
/* Logitech Harmony Adapter for PS3 */ /* Logitech Harmony Adapter for PS3 */
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3), { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3),
.driver_data = PS3REMOTE }, .driver_data = PS3REMOTE },
/* SMK-Link PS3 BD Remote Control */
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE),
.driver_data = PS3REMOTE },
/* Sony Dualshock 4 controllers for PS4 */ /* Sony Dualshock 4 controllers for PS4 */
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
.driver_data = DUALSHOCK4_CONTROLLER_USB }, .driver_data = DUALSHOCK4_CONTROLLER_USB },
......
...@@ -137,6 +137,7 @@ struct i2c_hid { ...@@ -137,6 +137,7 @@ struct i2c_hid {
* descriptor. */ * descriptor. */
unsigned int bufsize; /* i2c buffer size */ unsigned int bufsize; /* i2c buffer size */
char *inbuf; /* Input buffer */ char *inbuf; /* Input buffer */
char *rawbuf; /* Raw Input buffer */
char *cmdbuf; /* Command buffer */ char *cmdbuf; /* Command buffer */
char *argsbuf; /* Command arguments buffer */ char *argsbuf; /* Command arguments buffer */
...@@ -369,7 +370,7 @@ static int i2c_hid_hwreset(struct i2c_client *client) ...@@ -369,7 +370,7 @@ static int i2c_hid_hwreset(struct i2c_client *client)
static void i2c_hid_get_input(struct i2c_hid *ihid) static void i2c_hid_get_input(struct i2c_hid *ihid)
{ {
int ret, ret_size; int ret, ret_size;
int size = le16_to_cpu(ihid->hdesc.wMaxInputLength); int size = ihid->bufsize;
ret = i2c_master_recv(ihid->client, ihid->inbuf, size); ret = i2c_master_recv(ihid->client, ihid->inbuf, size);
if (ret != size) { if (ret != size) {
...@@ -437,7 +438,7 @@ static void i2c_hid_init_report(struct hid_report *report, u8 *buffer, ...@@ -437,7 +438,7 @@ static void i2c_hid_init_report(struct hid_report *report, u8 *buffer,
report->id, buffer, size)) report->id, buffer, size))
return; return;
i2c_hid_dbg(ihid, "report (len=%d): %*ph\n", size, size, ihid->inbuf); i2c_hid_dbg(ihid, "report (len=%d): %*ph\n", size, size, buffer);
ret_size = buffer[0] | (buffer[1] << 8); ret_size = buffer[0] | (buffer[1] << 8);
...@@ -504,9 +505,11 @@ static void i2c_hid_find_max_report(struct hid_device *hid, unsigned int type, ...@@ -504,9 +505,11 @@ static void i2c_hid_find_max_report(struct hid_device *hid, unsigned int type,
static void i2c_hid_free_buffers(struct i2c_hid *ihid) static void i2c_hid_free_buffers(struct i2c_hid *ihid)
{ {
kfree(ihid->inbuf); kfree(ihid->inbuf);
kfree(ihid->rawbuf);
kfree(ihid->argsbuf); kfree(ihid->argsbuf);
kfree(ihid->cmdbuf); kfree(ihid->cmdbuf);
ihid->inbuf = NULL; ihid->inbuf = NULL;
ihid->rawbuf = NULL;
ihid->cmdbuf = NULL; ihid->cmdbuf = NULL;
ihid->argsbuf = NULL; ihid->argsbuf = NULL;
ihid->bufsize = 0; ihid->bufsize = 0;
...@@ -522,10 +525,11 @@ static int i2c_hid_alloc_buffers(struct i2c_hid *ihid, size_t report_size) ...@@ -522,10 +525,11 @@ static int i2c_hid_alloc_buffers(struct i2c_hid *ihid, size_t report_size)
report_size; /* report */ report_size; /* report */
ihid->inbuf = kzalloc(report_size, GFP_KERNEL); ihid->inbuf = kzalloc(report_size, GFP_KERNEL);
ihid->rawbuf = kzalloc(report_size, GFP_KERNEL);
ihid->argsbuf = kzalloc(args_len, GFP_KERNEL); ihid->argsbuf = kzalloc(args_len, GFP_KERNEL);
ihid->cmdbuf = kzalloc(sizeof(union command) + args_len, GFP_KERNEL); ihid->cmdbuf = kzalloc(sizeof(union command) + args_len, GFP_KERNEL);
if (!ihid->inbuf || !ihid->argsbuf || !ihid->cmdbuf) { if (!ihid->inbuf || !ihid->rawbuf || !ihid->argsbuf || !ihid->cmdbuf) {
i2c_hid_free_buffers(ihid); i2c_hid_free_buffers(ihid);
return -ENOMEM; return -ENOMEM;
} }
...@@ -552,12 +556,12 @@ static int i2c_hid_get_raw_report(struct hid_device *hid, ...@@ -552,12 +556,12 @@ static int i2c_hid_get_raw_report(struct hid_device *hid,
ret = i2c_hid_get_report(client, ret = i2c_hid_get_report(client,
report_type == HID_FEATURE_REPORT ? 0x03 : 0x01, report_type == HID_FEATURE_REPORT ? 0x03 : 0x01,
report_number, ihid->inbuf, ask_count); report_number, ihid->rawbuf, ask_count);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret_count = ihid->inbuf[0] | (ihid->inbuf[1] << 8); ret_count = ihid->rawbuf[0] | (ihid->rawbuf[1] << 8);
if (ret_count <= 2) if (ret_count <= 2)
return 0; return 0;
...@@ -566,7 +570,7 @@ static int i2c_hid_get_raw_report(struct hid_device *hid, ...@@ -566,7 +570,7 @@ static int i2c_hid_get_raw_report(struct hid_device *hid,
/* The query buffer contains the size, dropping it in the reply */ /* The query buffer contains the size, dropping it in the reply */
count = min(count, ret_count - 2); count = min(count, ret_count - 2);
memcpy(buf, ihid->inbuf + 2, count); memcpy(buf, ihid->rawbuf + 2, count);
return count; return count;
} }
......
...@@ -278,18 +278,20 @@ static void hid_irq_in(struct urb *urb) ...@@ -278,18 +278,20 @@ static void hid_irq_in(struct urb *urb)
usbhid->retry_delay = 0; usbhid->retry_delay = 0;
if ((hid->quirks & HID_QUIRK_ALWAYS_POLL) && !hid->open) if ((hid->quirks & HID_QUIRK_ALWAYS_POLL) && !hid->open)
break; break;
hid_input_report(urb->context, HID_INPUT_REPORT, if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
urb->transfer_buffer, hid_input_report(urb->context, HID_INPUT_REPORT,
urb->actual_length, 1); urb->transfer_buffer,
/* urb->actual_length, 1);
* autosuspend refused while keys are pressed /*
* because most keyboards don't wake up when * autosuspend refused while keys are pressed
* a key is released * because most keyboards don't wake up when
*/ * a key is released
if (hid_check_keys_pressed(hid)) */
set_bit(HID_KEYS_PRESSED, &usbhid->iofl); if (hid_check_keys_pressed(hid))
else set_bit(HID_KEYS_PRESSED, &usbhid->iofl);
clear_bit(HID_KEYS_PRESSED, &usbhid->iofl); else
clear_bit(HID_KEYS_PRESSED, &usbhid->iofl);
}
break; break;
case -EPIPE: /* stall */ case -EPIPE: /* stall */
usbhid_mark_busy(usbhid); usbhid_mark_busy(usbhid);
...@@ -338,8 +340,7 @@ static int hid_submit_out(struct hid_device *hid) ...@@ -338,8 +340,7 @@ static int hid_submit_out(struct hid_device *hid)
report = usbhid->out[usbhid->outtail].report; report = usbhid->out[usbhid->outtail].report;
raw_report = usbhid->out[usbhid->outtail].raw_report; raw_report = usbhid->out[usbhid->outtail].raw_report;
usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + usbhid->urbout->transfer_buffer_length = hid_report_len(report);
1 + (report->id > 0);
usbhid->urbout->dev = hid_to_usb_dev(hid); usbhid->urbout->dev = hid_to_usb_dev(hid);
if (raw_report) { if (raw_report) {
memcpy(usbhid->outbuf, raw_report, memcpy(usbhid->outbuf, raw_report,
...@@ -688,6 +689,7 @@ int usbhid_open(struct hid_device *hid) ...@@ -688,6 +689,7 @@ int usbhid_open(struct hid_device *hid)
goto done; goto done;
} }
usbhid->intf->needs_remote_wakeup = 1; usbhid->intf->needs_remote_wakeup = 1;
set_bit(HID_RESUME_RUNNING, &usbhid->iofl);
res = hid_start_in(hid); res = hid_start_in(hid);
if (res) { if (res) {
if (res != -ENOSPC) { if (res != -ENOSPC) {
...@@ -701,6 +703,15 @@ int usbhid_open(struct hid_device *hid) ...@@ -701,6 +703,15 @@ int usbhid_open(struct hid_device *hid)
} }
} }
usb_autopm_put_interface(usbhid->intf); 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.
*/
msleep(50);
clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
} }
done: done:
mutex_unlock(&hid_open_mut); mutex_unlock(&hid_open_mut);
......
...@@ -73,11 +73,13 @@ static const struct hid_blacklist { ...@@ -73,11 +73,13 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN, HID_QUIRK_ALWAYS_POLL },
{ USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B, HID_QUIRK_ALWAYS_POLL },
{ USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103, HID_QUIRK_ALWAYS_POLL },
{ USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_010c, HID_QUIRK_ALWAYS_POLL },
{ USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F, HID_QUIRK_ALWAYS_POLL },
{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
......
...@@ -52,6 +52,7 @@ struct usb_interface *usbhid_find_interface(int minor); ...@@ -52,6 +52,7 @@ struct usb_interface *usbhid_find_interface(int minor);
#define HID_STARTED 8 #define HID_STARTED 8
#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
/* /*
* USB-specific HID struct, to be pointed to * USB-specific HID struct, to be pointed to
......
...@@ -140,7 +140,7 @@ extern const struct hid_device_id wacom_ids[]; ...@@ -140,7 +140,7 @@ extern const struct hid_device_id wacom_ids[];
void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
void wacom_setup_device_quirks(struct wacom_features *features); void wacom_setup_device_quirks(struct wacom_features *features);
int wacom_setup_input_capabilities(struct input_dev *input_dev, int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev,
struct wacom_wac *wacom_wac); struct wacom_wac *wacom_wac);
int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
struct wacom_wac *wacom_wac); struct wacom_wac *wacom_wac);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "wacom_wac.h" #include "wacom_wac.h"
#include "wacom.h" #include "wacom.h"
#include <linux/input/mt.h>
#define WAC_MSG_RETRIES 5 #define WAC_MSG_RETRIES 5
...@@ -70,22 +71,15 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, ...@@ -70,22 +71,15 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
static int wacom_open(struct input_dev *dev) static int wacom_open(struct input_dev *dev)
{ {
struct wacom *wacom = input_get_drvdata(dev); struct wacom *wacom = input_get_drvdata(dev);
int retval;
mutex_lock(&wacom->lock);
retval = hid_hw_open(wacom->hdev);
mutex_unlock(&wacom->lock);
return retval; return hid_hw_open(wacom->hdev);
} }
static void wacom_close(struct input_dev *dev) static void wacom_close(struct input_dev *dev)
{ {
struct wacom *wacom = input_get_drvdata(dev); struct wacom *wacom = input_get_drvdata(dev);
mutex_lock(&wacom->lock);
hid_hw_close(wacom->hdev); hid_hw_close(wacom->hdev);
mutex_unlock(&wacom->lock);
} }
/* /*
...@@ -192,9 +186,15 @@ static void wacom_usage_mapping(struct hid_device *hdev, ...@@ -192,9 +186,15 @@ static void wacom_usage_mapping(struct hid_device *hdev,
if (!pen && !finger) if (!pen && !finger)
return; return;
if (finger && !features->touch_max) /*
/* touch device at least supports one touch point */ * Bamboo models do not support HID_DG_CONTACTMAX.
features->touch_max = 1; * And, Bamboo Pen only descriptor contains touch.
*/
if (features->type != BAMBOO_PT) {
/* ISDv4 touch devices at least supports one touch point */
if (finger && !features->touch_max)
features->touch_max = 1;
}
switch (usage->hid) { switch (usage->hid) {
case HID_GD_X: case HID_GD_X:
...@@ -230,6 +230,21 @@ static void wacom_usage_mapping(struct hid_device *hdev, ...@@ -230,6 +230,21 @@ static void wacom_usage_mapping(struct hid_device *hdev,
wacom_wac_usage_mapping(hdev, field, usage); wacom_wac_usage_mapping(hdev, field, usage);
} }
static void wacom_post_parse_hid(struct hid_device *hdev,
struct wacom_features *features)
{
struct wacom *wacom = hid_get_drvdata(hdev);
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
if (features->type == HID_GENERIC) {
/* Any last-minute generic device setup */
if (features->touch_max > 1) {
input_mt_init_slots(wacom_wac->input, wacom_wac->features.touch_max,
INPUT_MT_DIRECT);
}
}
}
static void wacom_parse_hid(struct hid_device *hdev, static void wacom_parse_hid(struct hid_device *hdev,
struct wacom_features *features) struct wacom_features *features)
{ {
...@@ -264,6 +279,8 @@ static void wacom_parse_hid(struct hid_device *hdev, ...@@ -264,6 +279,8 @@ static void wacom_parse_hid(struct hid_device *hdev,
wacom_usage_mapping(hdev, hreport->field[i], wacom_usage_mapping(hdev, hreport->field[i],
hreport->field[i]->usage + j); hreport->field[i]->usage + j);
} }
wacom_post_parse_hid(hdev, features);
} }
static int wacom_hid_set_device_mode(struct hid_device *hdev) static int wacom_hid_set_device_mode(struct hid_device *hdev)
...@@ -1129,7 +1146,7 @@ static void wacom_clean_inputs(struct wacom *wacom) ...@@ -1129,7 +1146,7 @@ static void wacom_clean_inputs(struct wacom *wacom)
input_free_device(wacom->wacom_wac.input); input_free_device(wacom->wacom_wac.input);
} }
if (wacom->wacom_wac.pad_input) { if (wacom->wacom_wac.pad_input) {
if (wacom->wacom_wac.input_registered) if (wacom->wacom_wac.pad_registered)
input_unregister_device(wacom->wacom_wac.pad_input); input_unregister_device(wacom->wacom_wac.pad_input);
else else
input_free_device(wacom->wacom_wac.pad_input); input_free_device(wacom->wacom_wac.pad_input);
...@@ -1151,13 +1168,13 @@ static int wacom_register_inputs(struct wacom *wacom) ...@@ -1151,13 +1168,13 @@ static int wacom_register_inputs(struct wacom *wacom)
if (!input_dev || !pad_input_dev) if (!input_dev || !pad_input_dev)
return -EINVAL; return -EINVAL;
error = wacom_setup_input_capabilities(input_dev, wacom_wac); error = wacom_setup_pentouch_input_capabilities(input_dev, wacom_wac);
if (error) if (!error) {
return error; error = input_register_device(input_dev);
if (error)
error = input_register_device(input_dev); return error;
if (error) wacom_wac->input_registered = true;
return error; }
error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac); error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac);
if (error) { if (error) {
...@@ -1169,22 +1186,23 @@ static int wacom_register_inputs(struct wacom *wacom) ...@@ -1169,22 +1186,23 @@ static int wacom_register_inputs(struct wacom *wacom)
error = input_register_device(pad_input_dev); error = input_register_device(pad_input_dev);
if (error) if (error)
goto fail_register_pad_input; goto fail_register_pad_input;
wacom_wac->pad_registered = true;
error = wacom_initialize_leds(wacom); error = wacom_initialize_leds(wacom);
if (error) if (error)
goto fail_leds; goto fail_leds;
} }
wacom_wac->input_registered = true;
return 0; return 0;
fail_leds: fail_leds:
input_unregister_device(pad_input_dev); input_unregister_device(pad_input_dev);
pad_input_dev = NULL; pad_input_dev = NULL;
wacom_wac->pad_registered = false;
fail_register_pad_input: fail_register_pad_input:
input_unregister_device(input_dev); input_unregister_device(input_dev);
wacom_wac->input = NULL; wacom_wac->input = NULL;
wacom_wac->input_registered = false;
return error; return error;
} }
...@@ -1321,12 +1339,6 @@ static void wacom_calculate_res(struct wacom_features *features) ...@@ -1321,12 +1339,6 @@ static void wacom_calculate_res(struct wacom_features *features)
features->unitExpo); features->unitExpo);
} }
static int wacom_hid_report_len(struct hid_report *report)
{
/* equivalent to DIV_ROUND_UP(report->size, 8) + !!(report->id > 0) */
return ((report->size - 1) >> 3) + 1 + (report->id > 0);
}
static size_t wacom_compute_pktlen(struct hid_device *hdev) static size_t wacom_compute_pktlen(struct hid_device *hdev)
{ {
struct hid_report_enum *report_enum; struct hid_report_enum *report_enum;
...@@ -1336,7 +1348,7 @@ static size_t wacom_compute_pktlen(struct hid_device *hdev) ...@@ -1336,7 +1348,7 @@ static size_t wacom_compute_pktlen(struct hid_device *hdev)
report_enum = hdev->report_enum + HID_INPUT_REPORT; report_enum = hdev->report_enum + HID_INPUT_REPORT;
list_for_each_entry(report, &report_enum->report_list, list) { list_for_each_entry(report, &report_enum->report_list, list) {
size_t report_size = wacom_hid_report_len(report); size_t report_size = hid_report_len(report);
if (report_size > size) if (report_size > size)
size = report_size; size = report_size;
} }
......
This diff is collapsed.
...@@ -80,6 +80,7 @@ enum { ...@@ -80,6 +80,7 @@ enum {
PL, PL,
DTU, DTU,
DTUS, DTUS,
DTUSX,
INTUOS, INTUOS,
INTUOS3S, INTUOS3S,
INTUOS3, INTUOS3,
...@@ -144,6 +145,7 @@ struct wacom_features { ...@@ -144,6 +145,7 @@ struct wacom_features {
int pktlen; int pktlen;
bool check_for_hid_type; bool check_for_hid_type;
int hid_type; int hid_type;
int last_slot_field;
}; };
struct wacom_shared { struct wacom_shared {
...@@ -183,6 +185,7 @@ struct wacom_wac { ...@@ -183,6 +185,7 @@ struct wacom_wac {
struct input_dev *input; struct input_dev *input;
struct input_dev *pad_input; struct input_dev *pad_input;
bool input_registered; bool input_registered;
bool pad_registered;
int pid; int pid;
int battery_capacity; int battery_capacity;
int num_contacts_left; int num_contacts_left;
......
...@@ -103,6 +103,9 @@ static const struct usb_device_id usb_quirk_list[] = { ...@@ -103,6 +103,9 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x04f3, 0x009b), .driver_info = { USB_DEVICE(0x04f3, 0x009b), .driver_info =
USB_QUIRK_DEVICE_QUALIFIER }, USB_QUIRK_DEVICE_QUALIFIER },
{ USB_DEVICE(0x04f3, 0x010c), .driver_info =
USB_QUIRK_DEVICE_QUALIFIER },
{ USB_DEVICE(0x04f3, 0x016f), .driver_info = { USB_DEVICE(0x04f3, 0x016f), .driver_info =
USB_QUIRK_DEVICE_QUALIFIER }, USB_QUIRK_DEVICE_QUALIFIER },
......
...@@ -234,6 +234,33 @@ struct hid_item { ...@@ -234,6 +234,33 @@ struct hid_item {
#define HID_DG_BARRELSWITCH 0x000d0044 #define HID_DG_BARRELSWITCH 0x000d0044
#define HID_DG_ERASER 0x000d0045 #define HID_DG_ERASER 0x000d0045
#define HID_DG_TABLETPICK 0x000d0046 #define HID_DG_TABLETPICK 0x000d0046
#define HID_CP_CONSUMERCONTROL 0x000c0001
#define HID_CP_NUMERICKEYPAD 0x000c0002
#define HID_CP_PROGRAMMABLEBUTTONS 0x000c0003
#define HID_CP_MICROPHONE 0x000c0004
#define HID_CP_HEADPHONE 0x000c0005
#define HID_CP_GRAPHICEQUALIZER 0x000c0006
#define HID_CP_FUNCTIONBUTTONS 0x000c0036
#define HID_CP_SELECTION 0x000c0080
#define HID_CP_MEDIASELECTION 0x000c0087
#define HID_CP_SELECTDISC 0x000c00ba
#define HID_CP_PLAYBACKSPEED 0x000c00f1
#define HID_CP_PROXIMITY 0x000c0109
#define HID_CP_SPEAKERSYSTEM 0x000c0160
#define HID_CP_CHANNELLEFT 0x000c0161
#define HID_CP_CHANNELRIGHT 0x000c0162
#define HID_CP_CHANNELCENTER 0x000c0163
#define HID_CP_CHANNELFRONT 0x000c0164
#define HID_CP_CHANNELCENTERFRONT 0x000c0165
#define HID_CP_CHANNELSIDE 0x000c0166
#define HID_CP_CHANNELSURROUND 0x000c0167
#define HID_CP_CHANNELLOWFREQUENCYENHANCEMENT 0x000c0168
#define HID_CP_CHANNELTOP 0x000c0169
#define HID_CP_CHANNELUNKNOWN 0x000c016a
#define HID_CP_APPLICATIONLAUNCHBUTTONS 0x000c0180
#define HID_CP_GENERICGUIAPPLICATIONCONTROLS 0x000c0200
#define HID_DG_CONFIDENCE 0x000d0047 #define HID_DG_CONFIDENCE 0x000d0047
#define HID_DG_WIDTH 0x000d0048 #define HID_DG_WIDTH 0x000d0048
#define HID_DG_HEIGHT 0x000d0049 #define HID_DG_HEIGHT 0x000d0049
...@@ -312,11 +339,8 @@ struct hid_item { ...@@ -312,11 +339,8 @@ struct hid_item {
* Vendor specific HID device groups * Vendor specific HID device groups
*/ */
#define HID_GROUP_RMI 0x0100 #define HID_GROUP_RMI 0x0100
/*
* Vendor specific HID device groups
*/
#define HID_GROUP_WACOM 0x0101 #define HID_GROUP_WACOM 0x0101
#define HID_GROUP_LOGITECH_DJ_DEVICE 0x0102
/* /*
* This is the global environment of the parser. This information is * This is the global environment of the parser. This information is
...@@ -1063,6 +1087,17 @@ static inline void hid_hw_wait(struct hid_device *hdev) ...@@ -1063,6 +1087,17 @@ static inline void hid_hw_wait(struct hid_device *hdev)
hdev->ll_driver->wait(hdev); hdev->ll_driver->wait(hdev);
} }
/**
* hid_report_len - calculate the report length
*
* @report: the report we want to know the length
*/
static inline int hid_report_len(struct hid_report *report)
{
/* equivalent to DIV_ROUND_UP(report->size, 8) + !!(report->id > 0) */
return ((report->size - 1) >> 3) + 1 + (report->id > 0);
}
int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
int interrupt); int interrupt);
......
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