Commit 4832a4da authored by Linus Torvalds's avatar Linus Torvalds

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

Pull HID updates from Jiri Kosina:

 - Documentation conversion to ReST, from Mauro Carvalho Chehab

 - Wacom MobileStudio Pro support, from Ping Cheng

 - Wacom 2nd Gen Intuos Pro Small support, from Aaron Armstrong Skomra

 - assorted small fixes and device ID additions

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid:
  HID: Add another Primax PIXART OEM mouse quirk
  HID: wacom: generic: add touchring adjustment for 2nd Gen Pro Small
  docs: hid: convert to ReST
  HID: remove NO_D3 flag when remove driver
  HID: wacom: add new MobileStudio Pro support
  HID: wacom: generic: read the number of expected touches on a per collection basis
  HID: wacom: generic: support the 'report valid' usage for touch
  HID: wacom: generic: read HID_DG_CONTACTMAX from any feature report
  HID: wacom: Add 2nd gen Intuos Pro Small support
  HID: uclogic: Add support for Ugee Rainbow CV720
  HID: logitech-dj: fix return value of logi_dj_recv_query_hidpp_devices
  HID: logitech-hidpp: HID: make const array consumer_rdesc_start static
  HID: logitech-dj: make const array template static
  HID: wacom: correct touch resolution x/y typo
  HID: wacom: generic: Correct pad syncing
  HID: wacom: generic: only switch the mode on devices with LEDs
  HID: logitech-dj: Add usb-id for the 27MHz MX3000 receiver
parents db045733 86766756
==========================
ALPS HID Touchpad Protocol ALPS HID Touchpad Protocol
---------------------- ==========================
Introduction Introduction
------------ ------------
Currently ALPS HID driver supports U1 Touchpad device. Currently ALPS HID driver supports U1 Touchpad device.
U1 devuce basic information. U1 device basic information.
========== ======
Vender ID 0x044E Vender ID 0x044E
Product ID 0x120B Product ID 0x120B
Version ID 0x0121 Version ID 0x0121
========== ======
HID Descriptor HID Descriptor
------------ --------------
======= ==================== ===== =======================================
Byte Field Value Notes Byte Field Value Notes
======= ==================== ===== =======================================
0 wHIDDescLength 001E Length of HID Descriptor : 30 bytes 0 wHIDDescLength 001E Length of HID Descriptor : 30 bytes
2 bcdVersion 0100 Compliant with Version 1.00 2 bcdVersion 0100 Compliant with Version 1.00
4 wReportDescLength 00B2 Report Descriptor is 178 Bytes (0x00B2) 4 wReportDescLength 00B2 Report Descriptor is 178 Bytes (0x00B2)
...@@ -28,32 +35,42 @@ Byte Field Value Notes ...@@ -28,32 +35,42 @@ Byte Field Value Notes
22 wProductID 120B Product ID 0x120B 22 wProductID 120B Product ID 0x120B
24 wVersionID 0121 Version 01.21 24 wVersionID 0121 Version 01.21
26 RESERVED 0000 RESERVED 26 RESERVED 0000 RESERVED
======= ==================== ===== =======================================
Report ID Report ID
------------ ---------
ReportID-1 (Input Reports) (HIDUsage-Mouse) for TP&SP
ReportID-2 (Input Reports) (HIDUsage-keyboard) for TP ========== ================= =========================================
ReportID-3 (Input Reports) (Vendor Usage: Max 10 finger data) for TP ReportID-1 (Input Reports) (HIDUsage-Mouse) for TP&SP
ReportID-4 (Input Reports) (Vendor Usage: ON bit data) for GP ReportID-2 (Input Reports) (HIDUsage-keyboard) for TP
ReportID-5 (Feature Reports) Feature Reports ReportID-3 (Input Reports) (Vendor Usage: Max 10 finger data) for TP
ReportID-6 (Input Reports) (Vendor Usage: StickPointer data) for SP ReportID-4 (Input Reports) (Vendor Usage: ON bit data) for GP
ReportID-7 (Feature Reports) Flash update (Bootloader) ReportID-5 (Feature Reports) Feature Reports
ReportID-6 (Input Reports) (Vendor Usage: StickPointer data) for SP
ReportID-7 (Feature Reports) Flash update (Bootloader)
========== ================= =========================================
Data pattern Data pattern
------------ ------------
===== ========== ===== =================
Case1 ReportID_1 TP/SP Relative/Relative Case1 ReportID_1 TP/SP Relative/Relative
Case2 ReportID_3 TP Absolute Case2 ReportID_3 TP Absolute
ReportID_6 SP Absolute ReportID_6 SP Absolute
===== ========== ===== =================
Command Read/Write Command Read/Write
------------------ ------------------
To read/write to RAM, need to send a commands to the device. To read/write to RAM, need to send a commands to the device.
The command format is as below. The command format is as below.
DataByte(SET_REPORT) DataByte(SET_REPORT)
===== ======================
Byte1 Command Byte Byte1 Command Byte
Byte2 Address - Byte 0 (LSB) Byte2 Address - Byte 0 (LSB)
Byte3 Address - Byte 1 Byte3 Address - Byte 1
...@@ -61,13 +78,19 @@ Byte4 Address - Byte 2 ...@@ -61,13 +78,19 @@ Byte4 Address - Byte 2
Byte5 Address - Byte 3 (MSB) Byte5 Address - Byte 3 (MSB)
Byte6 Value Byte Byte6 Value Byte
Byte7 Checksum Byte7 Checksum
===== ======================
Command Byte is read=0xD1/write=0xD2 . Command Byte is read=0xD1/write=0xD2 .
Address is read/write RAM address. Address is read/write RAM address.
Value Byte is writing data when you send the write commands. Value Byte is writing data when you send the write commands.
When you read RAM, there is no meaning. When you read RAM, there is no meaning.
DataByte(GET_REPORT) DataByte(GET_REPORT)
===== ======================
Byte1 Response Byte Byte1 Response Byte
Byte2 Address - Byte 0 (LSB) Byte2 Address - Byte 0 (LSB)
Byte3 Address - Byte 1 Byte3 Address - Byte 1
...@@ -75,6 +98,7 @@ Byte4 Address - Byte 2 ...@@ -75,6 +98,7 @@ Byte4 Address - Byte 2
Byte5 Address - Byte 3 (MSB) Byte5 Address - Byte 3 (MSB)
Byte6 Value Byte Byte6 Value Byte
Byte7 Checksum Byte7 Checksum
===== ======================
Read value is stored in Value Byte. Read value is stored in Value Byte.
...@@ -82,7 +106,11 @@ Read value is stored in Value Byte. ...@@ -82,7 +106,11 @@ Read value is stored in Value Byte.
Packet Format Packet Format
Touchpad data byte Touchpad data byte
------------------ ------------------
b7 b6 b5 b4 b3 b2 b1 b0
======= ======= ======= ======= ======= ======= ======= ======= =====
- b7 b6 b5 b4 b3 b2 b1 b0
======= ======= ======= ======= ======= ======= ======= ======= =====
1 0 0 SW6 SW5 SW4 SW3 SW2 SW1 1 0 0 SW6 SW5 SW4 SW3 SW2 SW1
2 0 0 0 Fcv Fn3 Fn2 Fn1 Fn0 2 0 0 0 Fcv Fn3 Fn2 Fn1 Fn0
3 Xa0_7 Xa0_6 Xa0_5 Xa0_4 Xa0_3 Xa0_2 Xa0_1 Xa0_0 3 Xa0_7 Xa0_6 Xa0_5 Xa0_4 Xa0_3 Xa0_2 Xa0_1 Xa0_0
...@@ -114,17 +142,25 @@ Touchpad data byte ...@@ -114,17 +142,25 @@ Touchpad data byte
25 Ya4_7 Ya4_6 Ya4_5 Ya4_4 Ya4_3 Ya4_2 Ya4_1 Ya4_0 25 Ya4_7 Ya4_6 Ya4_5 Ya4_4 Ya4_3 Ya4_2 Ya4_1 Ya4_0
26 Ya4_15 Ya4_14 Ya4_13 Ya4_12 Ya4_11 Ya4_10 Ya4_9 Ya4_8 26 Ya4_15 Ya4_14 Ya4_13 Ya4_12 Ya4_11 Ya4_10 Ya4_9 Ya4_8
27 LFB4 Zs4_6 Zs4_5 Zs4_4 Zs4_3 Zs4_2 Zs4_1 Zs4_0 27 LFB4 Zs4_6 Zs4_5 Zs4_4 Zs4_3 Zs4_2 Zs4_1 Zs4_0
======= ======= ======= ======= ======= ======= ======= ======= =====
SW1-SW6: SW ON/OFF status SW1-SW6:
Xan_15-0(16bit):X Absolute data of the "n"th finger SW ON/OFF status
Yan_15-0(16bit):Y Absolute data of the "n"th finger Xan_15-0(16bit):
Zsn_6-0(7bit): Operation area of the "n"th finger X Absolute data of the "n"th finger
Yan_15-0(16bit):
Y Absolute data of the "n"th finger
Zsn_6-0(7bit):
Operation area of the "n"th finger
StickPointer data byte StickPointer data byte
------------------ ----------------------
b7 b6 b5 b4 b3 b2 b1 b0
======= ======= ======= ======= ======= ======= ======= ======= =====
- b7 b6 b5 b4 b3 b2 b1 b0
======= ======= ======= ======= ======= ======= ======= ======= =====
Byte1 1 1 1 0 1 SW3 SW2 SW1 Byte1 1 1 1 0 1 SW3 SW2 SW1
Byte2 X7 X6 X5 X4 X3 X2 X1 X0 Byte2 X7 X6 X5 X4 X3 X2 X1 X0
Byte3 X15 X14 X13 X12 X11 X10 X9 X8 Byte3 X15 X14 X13 X12 X11 X10 X9 X8
...@@ -132,8 +168,13 @@ Byte4 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 ...@@ -132,8 +168,13 @@ Byte4 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
Byte5 Y15 Y14 Y13 Y12 Y11 Y10 Y9 Y8 Byte5 Y15 Y14 Y13 Y12 Y11 Y10 Y9 Y8
Byte6 Z7 Z6 Z5 Z4 Z3 Z2 Z1 Z0 Byte6 Z7 Z6 Z5 Z4 Z3 Z2 Z1 Z0
Byte7 T&P Z14 Z13 Z12 Z11 Z10 Z9 Z8 Byte7 T&P Z14 Z13 Z12 Z11 Z10 Z9 Z8
======= ======= ======= ======= ======= ======= ======= ======= =====
SW1-SW3: SW ON/OFF status
Xn_15-0(16bit):X Absolute data SW1-SW3:
Yn_15-0(16bit):Y Absolute data SW ON/OFF status
Zn_14-0(15bit):Z Xn_15-0(16bit):
X Absolute data
Yn_15-0(16bit):
Y Absolute data
Zn_14-0(15bit):
Z
=====================
HID Sensors Framework HID Sensors Framework
====================== =====================
HID sensor framework provides necessary interfaces to implement sensor drivers, HID sensor framework provides necessary interfaces to implement sensor drivers,
which are connected to a sensor hub. The sensor hub is a HID device and it provides which are connected to a sensor hub. The sensor hub is a HID device and it provides
a report descriptor conforming to HID 1.12 sensor usage tables. a report descriptor conforming to HID 1.12 sensor usage tables.
...@@ -15,22 +15,22 @@ the drivers themselves." ...@@ -15,22 +15,22 @@ the drivers themselves."
This specification describes many usage IDs, which describe the type of sensor This specification describes many usage IDs, which describe the type of sensor
and also the individual data fields. Each sensor can have variable number of and also the individual data fields. Each sensor can have variable number of
data fields. The length and order is specified in the report descriptor. For data fields. The length and order is specified in the report descriptor. For
example a part of report descriptor can look like: example a part of report descriptor can look like::
INPUT(1)[INPUT] INPUT(1)[INPUT]
.. ..
Field(2) Field(2)
Physical(0020.0073) Physical(0020.0073)
Usage(1) Usage(1)
0020.045f 0020.045f
Logical Minimum(-32767) Logical Minimum(-32767)
Logical Maximum(32767) Logical Maximum(32767)
Report Size(8) Report Size(8)
Report Count(1) Report Count(1)
Report Offset(16) Report Offset(16)
Flags(Variable Absolute) Flags(Variable Absolute)
.. ..
.. ..
The report is indicating "sensor page (0x20)" contains an accelerometer-3D (0x73). The report is indicating "sensor page (0x20)" contains an accelerometer-3D (0x73).
This accelerometer-3D has some fields. Here for example field 2 is motion intensity This accelerometer-3D has some fields. Here for example field 2 is motion intensity
...@@ -40,13 +40,14 @@ data will use this format. ...@@ -40,13 +40,14 @@ data will use this format.
Implementation Implementation
================= ==============
This specification defines many different types of sensors with different sets of This specification defines many different types of sensors with different sets of
data fields. It is difficult to have a common input event to user space applications, data fields. It is difficult to have a common input event to user space applications,
for different sensors. For example an accelerometer can send X,Y and Z data, whereas for different sensors. For example an accelerometer can send X,Y and Z data, whereas
an ambient light sensor can send illumination data. an ambient light sensor can send illumination data.
So the implementation has two parts: So the implementation has two parts:
- Core hid driver - Core hid driver
- Individual sensor processing part (sensor drivers) - Individual sensor processing part (sensor drivers)
...@@ -55,8 +56,11 @@ Core driver ...@@ -55,8 +56,11 @@ Core driver
The core driver registers (hid-sensor-hub) registers as a HID driver. It parses The core driver registers (hid-sensor-hub) registers as a HID driver. It parses
report descriptors and identifies all the sensors present. It adds an MFD device report descriptors and identifies all the sensors present. It adds an MFD device
with name HID-SENSOR-xxxx (where xxxx is usage id from the specification). with name HID-SENSOR-xxxx (where xxxx is usage id from the specification).
For example
For example:
HID-SENSOR-200073 is registered for an Accelerometer 3D driver. HID-SENSOR-200073 is registered for an Accelerometer 3D driver.
So if any driver with this name is inserted, then the probe routine for that So if any driver with this name is inserted, then the probe routine for that
function will be called. So an accelerometer processing driver can register function will be called. So an accelerometer processing driver can register
with this name and will be probed if there is an accelerometer-3D detected. with this name and will be probed if there is an accelerometer-3D detected.
...@@ -66,7 +70,8 @@ drivers to register and get events for that usage id. Also it provides parsing ...@@ -66,7 +70,8 @@ drivers to register and get events for that usage id. Also it provides parsing
functions, which get and set each input/feature/output report. functions, which get and set each input/feature/output report.
Individual sensor processing part (sensor drivers) Individual sensor processing part (sensor drivers)
----------- --------------------------------------------------
The processing driver will use an interface provided by the core driver to parse The processing driver will use an interface provided by the core driver to parse
the report and get the indexes of the fields and also can get events. This driver the report and get the indexes of the fields and also can get events. This driver
can use IIO interface to use the standard ABI defined for a type of sensor. can use IIO interface to use the standard ABI defined for a type of sensor.
...@@ -75,31 +80,34 @@ can use IIO interface to use the standard ABI defined for a type of sensor. ...@@ -75,31 +80,34 @@ can use IIO interface to use the standard ABI defined for a type of sensor.
Core driver Interface Core driver Interface
===================== =====================
Callback structure: Callback structure::
Each processing driver can use this structure to set some callbacks.
Each processing driver can use this structure to set some callbacks.
int (*suspend)(..): Callback when HID suspend is received int (*suspend)(..): Callback when HID suspend is received
int (*resume)(..): Callback when HID resume is received int (*resume)(..): Callback when HID resume is received
int (*capture_sample)(..): Capture a sample for one of its data fields int (*capture_sample)(..): Capture a sample for one of its data fields
int (*send_event)(..): One complete event is received which can have int (*send_event)(..): One complete event is received which can have
multiple data fields. multiple data fields.
Registration functions: Registration functions::
int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev,
int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev,
u32 usage_id, u32 usage_id,
struct hid_sensor_hub_callbacks *usage_callback): struct hid_sensor_hub_callbacks *usage_callback):
Registers callbacks for an usage id. The callback functions are not allowed Registers callbacks for an usage id. The callback functions are not allowed
to sleep. to sleep::
int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev, int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev,
u32 usage_id): u32 usage_id):
Removes callbacks for an usage id. Removes callbacks for an usage id.
Parsing function: Parsing function::
int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
u8 type, u8 type,
u32 usage_id, u32 attr_usage_id, u32 usage_id, u32 attr_usage_id,
struct hid_sensor_hub_attribute_info *info); struct hid_sensor_hub_attribute_info *info);
...@@ -110,26 +118,27 @@ so that fields can be set or get individually. ...@@ -110,26 +118,27 @@ so that fields can be set or get individually.
These indexes avoid searching every time and getting field index to get or set. These indexes avoid searching every time and getting field index to get or set.
Set Feature report Set Feature report::
int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
u32 field_index, s32 value); u32 field_index, s32 value);
This interface is used to set a value for a field in feature report. For example This interface is used to set a value for a field in feature report. For example
if there is a field report_interval, which is parsed by a call to if there is a field report_interval, which is parsed by a call to
sensor_hub_input_get_attribute_info before, then it can directly set that individual sensor_hub_input_get_attribute_info before, then it can directly set that
field. individual field::
int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
u32 field_index, s32 *value); u32 field_index, s32 *value);
This interface is used to get a value for a field in input report. For example This interface is used to get a value for a field in input report. For example
if there is a field report_interval, which is parsed by a call to if there is a field report_interval, which is parsed by a call to
sensor_hub_input_get_attribute_info before, then it can directly get that individual sensor_hub_input_get_attribute_info before, then it can directly get that
field value. individual field value::
int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev, int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
u32 usage_id, u32 usage_id,
u32 attr_usage_id, u32 report_id); u32 attr_usage_id, u32 report_id);
...@@ -143,6 +152,8 @@ registered callback function to process the sample. ...@@ -143,6 +152,8 @@ registered callback function to process the sample.
---------- ----------
HID Custom and generic Sensors HID Custom and generic Sensors
------------------------------
HID Sensor specification defines two special sensor usage types. Since they HID Sensor specification defines two special sensor usage types. Since they
don't represent a standard sensor, it is not possible to define using Linux IIO don't represent a standard sensor, it is not possible to define using Linux IIO
...@@ -158,66 +169,73 @@ keyboard attached/detached or lid open/close. ...@@ -158,66 +169,73 @@ keyboard attached/detached or lid open/close.
To allow application to utilize these sensors, here they are exported uses sysfs To allow application to utilize these sensors, here they are exported uses sysfs
attribute groups, attributes and misc device interface. attribute groups, attributes and misc device interface.
An example of this representation on sysfs: An example of this representation on sysfs::
/sys/devices/pci0000:00/INT33C2:00/i2c-0/i2c-INT33D1:00/0018:8086:09FA.0001/HID-SENSOR-2000e1.6.auto$ tree -R
. /sys/devices/pci0000:00/INT33C2:00/i2c-0/i2c-INT33D1:00/0018:8086:09FA.0001/HID-SENSOR-2000e1.6.auto$ tree -R
????????? enable_sensor .
????????? feature-0-200316 │   ├── enable_sensor
??????? ????????? feature-0-200316-maximum │   │   ├── feature-0-200316
??????? ????????? feature-0-200316-minimum │   │   │   ├── feature-0-200316-maximum
??????? ????????? feature-0-200316-name │   │   │   ├── feature-0-200316-minimum
??????? ????????? feature-0-200316-size │   │   │   ├── feature-0-200316-name
??????? ????????? feature-0-200316-unit-expo │   │   │   ├── feature-0-200316-size
??????? ????????? feature-0-200316-units │   │   │   ├── feature-0-200316-unit-expo
??????? ????????? feature-0-200316-value │   │   │   ├── feature-0-200316-units
????????? feature-1-200201 │   │   │   ├── feature-0-200316-value
??????? ????????? feature-1-200201-maximum │   │   ├── feature-1-200201
??????? ????????? feature-1-200201-minimum │   │   │   ├── feature-1-200201-maximum
??????? ????????? feature-1-200201-name │   │   │   ├── feature-1-200201-minimum
??????? ????????? feature-1-200201-size │   │   │   ├── feature-1-200201-name
??????? ????????? feature-1-200201-unit-expo │   │   │   ├── feature-1-200201-size
??????? ????????? feature-1-200201-units │   │   │   ├── feature-1-200201-unit-expo
??????? ????????? feature-1-200201-value │   │   │   ├── feature-1-200201-units
????????? input-0-200201 │   │   │   ├── feature-1-200201-value
??????? ????????? input-0-200201-maximum │   │   ├── input-0-200201
??????? ????????? input-0-200201-minimum │   │   │   ├── input-0-200201-maximum
??????? ????????? input-0-200201-name │   │   │   ├── input-0-200201-minimum
??????? ????????? input-0-200201-size │   │   │   ├── input-0-200201-name
??????? ????????? input-0-200201-unit-expo │   │   │   ├── input-0-200201-size
??????? ????????? input-0-200201-units │   │   │   ├── input-0-200201-unit-expo
??????? ????????? input-0-200201-value │   │   │   ├── input-0-200201-units
????????? input-1-200202 │   │   │   ├── input-0-200201-value
??????? ????????? input-1-200202-maximum │   │   ├── input-1-200202
??????? ????????? input-1-200202-minimum │   │   │   ├── input-1-200202-maximum
??????? ????????? input-1-200202-name │   │   │   ├── input-1-200202-minimum
??????? ????????? input-1-200202-size │   │   │   ├── input-1-200202-name
??????? ????????? input-1-200202-unit-expo │   │   │   ├── input-1-200202-size
??????? ????????? input-1-200202-units │   │   │   ├── input-1-200202-unit-expo
??????? ????????? input-1-200202-value │   │   │   ├── input-1-200202-units
│   │   │   ├── input-1-200202-value
Here there is a custom sensors with four fields, two feature and two inputs. Here there is a custom sensors with four fields, two feature and two inputs.
Each field is represented by a set of attributes. All fields except the "value" Each field is represented by a set of attributes. All fields except the "value"
are read only. The value field is a RW field. are read only. The value field is a RW field.
Example
/sys/bus/platform/devices/HID-SENSOR-2000e1.6.auto/feature-0-200316$ grep -r . * Example::
feature-0-200316-maximum:6
feature-0-200316-minimum:0 /sys/bus/platform/devices/HID-SENSOR-2000e1.6.auto/feature-0-200316$ grep -r . *
feature-0-200316-name:property-reporting-state feature-0-200316-maximum:6
feature-0-200316-size:1 feature-0-200316-minimum:0
feature-0-200316-unit-expo:0 feature-0-200316-name:property-reporting-state
feature-0-200316-units:25 feature-0-200316-size:1
feature-0-200316-value:1 feature-0-200316-unit-expo:0
feature-0-200316-units:25
feature-0-200316-value:1
How to enable such sensor? How to enable such sensor?
^^^^^^^^^^^^^^^^^^^^^^^^^^
By default sensor can be power gated. To enable sysfs attribute "enable" can be By default sensor can be power gated. To enable sysfs attribute "enable" can be
used. used::
$ echo 1 > enable_sensor
$ echo 1 > enable_sensor
Once enabled and powered on, sensor can report value using HID reports. Once enabled and powered on, sensor can report value using HID reports.
These reports are pushed using misc device interface in a FIFO order. These reports are pushed using misc device interface in a FIFO order::
/dev$ tree | grep HID-SENSOR-2000e1.6.auto
??????? ????????? 10:53 -> ../HID-SENSOR-2000e1.6.auto /dev$ tree | grep HID-SENSOR-2000e1.6.auto
????????? HID-SENSOR-2000e1.6.auto │   │   │   ├── 10:53 -> ../HID-SENSOR-2000e1.6.auto
│   ├── HID-SENSOR-2000e1.6.auto
Each reports can be of variable length preceded by a header. This header Each reports can be of variable length preceded by a header. This header
consist of a 32 bit usage id, 64 bit time stamp and 32 bit length field of raw consist of a 32 bit usage id, 64 bit time stamp and 32 bit length field of raw
......
HID I/O Transport Drivers =========================
=========================== HID I/O Transport Drivers
=========================
The HID subsystem is independent of the underlying transport driver. Initially, The HID subsystem is independent of the underlying transport driver. Initially,
only USB was supported, but other specifications adopted the HID design and only USB was supported, but other specifications adopted the HID design and
...@@ -16,6 +17,8 @@ transport and device setup/management. HID core is responsible of ...@@ -16,6 +17,8 @@ transport and device setup/management. HID core is responsible of
report-parsing, report interpretation and the user-space API. Device specifics report-parsing, report interpretation and the user-space API. Device specifics
and quirks are handled by all layers depending on the quirk. and quirks are handled by all layers depending on the quirk.
::
+-----------+ +-----------+ +-----------+ +-----------+ +-----------+ +-----------+ +-----------+ +-----------+
| Device #1 | | Device #i | | Device #j | | Device #k | | Device #1 | | Device #i | | Device #j | | Device #k |
+-----------+ +-----------+ +-----------+ +-----------+ +-----------+ +-----------+ +-----------+ +-----------+
...@@ -42,8 +45,9 @@ and quirks are handled by all layers depending on the quirk. ...@@ -42,8 +45,9 @@ and quirks are handled by all layers depending on the quirk.
+----------------+ +-----------+ +------------------+ +------------------+ +----------------+ +-----------+ +------------------+ +------------------+
Example Drivers: Example Drivers:
I/O: USB, I2C, Bluetooth-l2cap
Transport: USB-HID, I2C-HID, BT-HIDP - I/O: USB, I2C, Bluetooth-l2cap
- Transport: USB-HID, I2C-HID, BT-HIDP
Everything below "HID Core" is simplified in this graph as it is only of Everything below "HID Core" is simplified in this graph as it is only of
interest to HID device drivers. Transport drivers do not need to know the interest to HID device drivers. Transport drivers do not need to know the
...@@ -183,7 +187,7 @@ Other ctrl-channel requests are supported by USB-HID but are not available ...@@ -183,7 +187,7 @@ Other ctrl-channel requests are supported by USB-HID but are not available
------------------- -------------------
Transport drivers normally use the following procedure to register a new device Transport drivers normally use the following procedure to register a new device
with HID core: with HID core::
struct hid_device *hid; struct hid_device *hid;
int ret; int ret;
...@@ -215,7 +219,7 @@ Once hid_add_device() is entered, HID core might use the callbacks provided in ...@@ -215,7 +219,7 @@ Once hid_add_device() is entered, HID core might use the callbacks provided in
"custom_ll_driver". Note that fields like "country" can be ignored by underlying "custom_ll_driver". Note that fields like "country" can be ignored by underlying
transport-drivers if not supported. transport-drivers if not supported.
To unregister a device, use: To unregister a device, use::
hid_destroy_device(hid); hid_destroy_device(hid);
...@@ -226,73 +230,110 @@ driver callbacks. ...@@ -226,73 +230,110 @@ driver callbacks.
----------------------------- -----------------------------
The available HID callbacks are: The available HID callbacks are:
- int (*start) (struct hid_device *hdev)
::
int (*start) (struct hid_device *hdev)
Called from HID device drivers once they want to use the device. Transport Called from HID device drivers once they want to use the device. Transport
drivers can choose to setup their device in this callback. However, normally drivers can choose to setup their device in this callback. However, normally
devices are already set up before transport drivers register them to HID core devices are already set up before transport drivers register them to HID core
so this is mostly only used by USB-HID. so this is mostly only used by USB-HID.
- void (*stop) (struct hid_device *hdev) ::
void (*stop) (struct hid_device *hdev)
Called from HID device drivers once they are done with a device. Transport Called from HID device drivers once they are done with a device. Transport
drivers can free any buffers and deinitialize the device. But note that drivers can free any buffers and deinitialize the device. But note that
->start() might be called again if another HID device driver is loaded on the ->start() might be called again if another HID device driver is loaded on the
device. device.
Transport drivers are free to ignore it and deinitialize devices after they Transport drivers are free to ignore it and deinitialize devices after they
destroyed them via hid_destroy_device(). destroyed them via hid_destroy_device().
- int (*open) (struct hid_device *hdev) ::
int (*open) (struct hid_device *hdev)
Called from HID device drivers once they are interested in data reports. Called from HID device drivers once they are interested in data reports.
Usually, while user-space didn't open any input API/etc., device drivers are Usually, while user-space didn't open any input API/etc., device drivers are
not interested in device data and transport drivers can put devices asleep. not interested in device data and transport drivers can put devices asleep.
However, once ->open() is called, transport drivers must be ready for I/O. However, once ->open() is called, transport drivers must be ready for I/O.
->open() calls are nested for each client that opens the HID device. ->open() calls are nested for each client that opens the HID device.
- void (*close) (struct hid_device *hdev) ::
void (*close) (struct hid_device *hdev)
Called from HID device drivers after ->open() was called but they are no Called from HID device drivers after ->open() was called but they are no
longer interested in device reports. (Usually if user-space closed any input longer interested in device reports. (Usually if user-space closed any input
devices of the driver). devices of the driver).
Transport drivers can put devices asleep and terminate any I/O of all Transport drivers can put devices asleep and terminate any I/O of all
->open() calls have been followed by a ->close() call. However, ->start() may ->open() calls have been followed by a ->close() call. However, ->start() may
be called again if the device driver is interested in input reports again. be called again if the device driver is interested in input reports again.
- int (*parse) (struct hid_device *hdev) ::
int (*parse) (struct hid_device *hdev)
Called once during device setup after ->start() has been called. Transport Called once during device setup after ->start() has been called. Transport
drivers must read the HID report-descriptor from the device and tell HID core drivers must read the HID report-descriptor from the device and tell HID core
about it via hid_parse_report(). about it via hid_parse_report().
- int (*power) (struct hid_device *hdev, int level) ::
int (*power) (struct hid_device *hdev, int level)
Called by HID core to give PM hints to transport drivers. Usually this is Called by HID core to give PM hints to transport drivers. Usually this is
analogical to the ->open() and ->close() hints and redundant. analogical to the ->open() and ->close() hints and redundant.
- void (*request) (struct hid_device *hdev, struct hid_report *report, ::
int reqtype)
void (*request) (struct hid_device *hdev, struct hid_report *report,
int reqtype)
Send an HID request on the ctrl channel. "report" contains the report that Send an HID request on the ctrl channel. "report" contains the report that
should be sent and "reqtype" the request type. Request-type can be should be sent and "reqtype" the request type. Request-type can be
HID_REQ_SET_REPORT or HID_REQ_GET_REPORT. HID_REQ_SET_REPORT or HID_REQ_GET_REPORT.
This callback is optional. If not provided, HID core will assemble a raw This callback is optional. If not provided, HID core will assemble a raw
report following the HID specs and send it via the ->raw_request() callback. report following the HID specs and send it via the ->raw_request() callback.
The transport driver is free to implement this asynchronously. The transport driver is free to implement this asynchronously.
- int (*wait) (struct hid_device *hdev) ::
int (*wait) (struct hid_device *hdev)
Used by HID core before calling ->request() again. A transport driver can use Used by HID core before calling ->request() again. A transport driver can use
it to wait for any pending requests to complete if only one request is it to wait for any pending requests to complete if only one request is
allowed at a time. allowed at a time.
- int (*raw_request) (struct hid_device *hdev, unsigned char reportnum, ::
__u8 *buf, size_t count, unsigned char rtype,
int reqtype) int (*raw_request) (struct hid_device *hdev, unsigned char reportnum,
__u8 *buf, size_t count, unsigned char rtype,
int reqtype)
Same as ->request() but provides the report as raw buffer. This request shall Same as ->request() but provides the report as raw buffer. This request shall
be synchronous. A transport driver must not use ->wait() to complete such be synchronous. A transport driver must not use ->wait() to complete such
requests. This request is mandatory and hid core will reject the device if requests. This request is mandatory and hid core will reject the device if
it is missing. it is missing.
- int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len) ::
int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len)
Send raw output report via intr channel. Used by some HID device drivers Send raw output report via intr channel. Used by some HID device drivers
which require high throughput for outgoing requests on the intr channel. This which require high throughput for outgoing requests on the intr channel. This
must not cause SET_REPORT calls! This must be implemented as asynchronous must not cause SET_REPORT calls! This must be implemented as asynchronous
output report on the intr channel! output report on the intr channel!
- int (*idle) (struct hid_device *hdev, int report, int idle, int reqtype) ::
int (*idle) (struct hid_device *hdev, int report, int idle, int reqtype)
Perform SET/GET_IDLE request. Only used by USB-HID, do not implement! Perform SET/GET_IDLE request. Only used by USB-HID, do not implement!
2.3) Data Path 2.3) Data Path
...@@ -314,4 +355,5 @@ transport driver and not passed to hid_input_report(). ...@@ -314,4 +355,5 @@ transport driver and not passed to hid_input_report().
Acknowledgements to SET_REPORT requests are not of interest to HID core. Acknowledgements to SET_REPORT requests are not of interest to HID core.
---------------------------------------------------- ----------------------------------------------------
Written 2013, David Herrmann <dh.herrmann@gmail.com> Written 2013, David Herrmann <dh.herrmann@gmail.com>
================================================
Care and feeding of your Human Interface Devices Care and feeding of your Human Interface Devices
================================================
INTRODUCTION Introduction
============
In addition to the normal input type HID devices, USB also uses the In addition to the normal input type HID devices, USB also uses the
human interface device protocols for things that are not really human human interface device protocols for things that are not really human
...@@ -16,38 +19,40 @@ normalised event interface - see Documentation/input/input.rst ...@@ -16,38 +19,40 @@ normalised event interface - see Documentation/input/input.rst
* the hiddev interface, which provides fairly raw HID events * the hiddev interface, which provides fairly raw HID events
The data flow for a HID event produced by a device is something like The data flow for a HID event produced by a device is something like
the following : the following::
usb.c ---> hid-core.c ----> hid-input.c ----> [keyboard/mouse/joystick/event] usb.c ---> hid-core.c ----> hid-input.c ----> [keyboard/mouse/joystick/event]
| |
| |
--> hiddev.c ----> POWER / MONITOR CONTROL --> hiddev.c ----> POWER / MONITOR CONTROL
In addition, other subsystems (apart from USB) can potentially feed In addition, other subsystems (apart from USB) can potentially feed
events into the input subsystem, but these have no effect on the hid events into the input subsystem, but these have no effect on the hid
device interface. device interface.
USING THE HID DEVICE INTERFACE Using the HID Device Interface
==============================
The hiddev interface is a char interface using the normal USB major, The hiddev interface is a char interface using the normal USB major,
with the minor numbers starting at 96 and finishing at 111. Therefore, with the minor numbers starting at 96 and finishing at 111. Therefore,
you need the following commands: you need the following commands::
mknod /dev/usb/hiddev0 c 180 96
mknod /dev/usb/hiddev1 c 180 97 mknod /dev/usb/hiddev0 c 180 96
mknod /dev/usb/hiddev2 c 180 98 mknod /dev/usb/hiddev1 c 180 97
mknod /dev/usb/hiddev3 c 180 99 mknod /dev/usb/hiddev2 c 180 98
mknod /dev/usb/hiddev4 c 180 100 mknod /dev/usb/hiddev3 c 180 99
mknod /dev/usb/hiddev5 c 180 101 mknod /dev/usb/hiddev4 c 180 100
mknod /dev/usb/hiddev6 c 180 102 mknod /dev/usb/hiddev5 c 180 101
mknod /dev/usb/hiddev7 c 180 103 mknod /dev/usb/hiddev6 c 180 102
mknod /dev/usb/hiddev8 c 180 104 mknod /dev/usb/hiddev7 c 180 103
mknod /dev/usb/hiddev9 c 180 105 mknod /dev/usb/hiddev8 c 180 104
mknod /dev/usb/hiddev10 c 180 106 mknod /dev/usb/hiddev9 c 180 105
mknod /dev/usb/hiddev11 c 180 107 mknod /dev/usb/hiddev10 c 180 106
mknod /dev/usb/hiddev12 c 180 108 mknod /dev/usb/hiddev11 c 180 107
mknod /dev/usb/hiddev13 c 180 109 mknod /dev/usb/hiddev12 c 180 108
mknod /dev/usb/hiddev14 c 180 110 mknod /dev/usb/hiddev13 c 180 109
mknod /dev/usb/hiddev15 c 180 111 mknod /dev/usb/hiddev14 c 180 110
mknod /dev/usb/hiddev15 c 180 111
So you point your hiddev compliant user-space program at the correct So you point your hiddev compliant user-space program at the correct
interface for your device, and it all just works. interface for your device, and it all just works.
...@@ -56,7 +61,9 @@ Assuming that you have a hiddev compliant user-space program, of ...@@ -56,7 +61,9 @@ Assuming that you have a hiddev compliant user-space program, of
course. If you need to write one, read on. course. If you need to write one, read on.
THE HIDDEV API The HIDDEV API
==============
This description should be read in conjunction with the HID This description should be read in conjunction with the HID
specification, freely available from http://www.usb.org, and specification, freely available from http://www.usb.org, and
conveniently linked of http://www.linux-usb.org. conveniently linked of http://www.linux-usb.org.
...@@ -69,12 +76,14 @@ each of which can have one or more "usages". In the hid-core, ...@@ -69,12 +76,14 @@ each of which can have one or more "usages". In the hid-core,
each one of these usages has a single signed 32 bit value. each one of these usages has a single signed 32 bit value.
read(): read():
-------
This is the event interface. When the HID device's state changes, This is the event interface. When the HID device's state changes,
it performs an interrupt transfer containing a report which contains it performs an interrupt transfer containing a report which contains
the changed value. The hid-core.c module parses the report, and the changed value. The hid-core.c module parses the report, and
returns to hiddev.c the individual usages that have changed within returns to hiddev.c the individual usages that have changed within
the report. In its basic mode, the hiddev will make these individual the report. In its basic mode, the hiddev will make these individual
usage changes available to the reader using a struct hiddev_event: usage changes available to the reader using a struct hiddev_event::
struct hiddev_event { struct hiddev_event {
unsigned hid; unsigned hid;
...@@ -90,13 +99,19 @@ behavior of the read() function can be modified using the HIDIOCSFLAG ...@@ -90,13 +99,19 @@ behavior of the read() function can be modified using the HIDIOCSFLAG
ioctl() described below. ioctl() described below.
ioctl(): ioctl():
This is the control interface. There are a number of controls: --------
This is the control interface. There are a number of controls:
HIDIOCGVERSION
- int (read)
Gets the version code out of the hiddev driver.
HIDIOCGVERSION - int (read) HIDIOCAPPLICATION
Gets the version code out of the hiddev driver. - (none)
HIDIOCAPPLICATION - (none)
This ioctl call returns the HID application usage associated with the This ioctl call returns the HID application usage associated with the
hid device. The third argument to ioctl() specifies which application hid device. The third argument to ioctl() specifies which application
index to get. This is useful when the device has more than one index to get. This is useful when the device has more than one
...@@ -104,25 +119,33 @@ application collection. If the index is invalid (greater or equal to ...@@ -104,25 +119,33 @@ application collection. If the index is invalid (greater or equal to
the number of application collections this device has) the ioctl the number of application collections this device has) the ioctl
returns -1. You can find out beforehand how many application returns -1. You can find out beforehand how many application
collections the device has from the num_applications field from the collections the device has from the num_applications field from the
hiddev_devinfo structure. hiddev_devinfo structure.
HIDIOCGCOLLECTIONINFO
- struct hiddev_collection_info (read/write)
HIDIOCGCOLLECTIONINFO - struct hiddev_collection_info (read/write)
This returns a superset of the information above, providing not only This returns a superset of the information above, providing not only
application collections, but all the collections the device has. It application collections, but all the collections the device has. It
also returns the level the collection lives in the hierarchy. also returns the level the collection lives in the hierarchy.
The user passes in a hiddev_collection_info struct with the index The user passes in a hiddev_collection_info struct with the index
field set to the index that should be returned. The ioctl fills in field set to the index that should be returned. The ioctl fills in
the other fields. If the index is larger than the last collection the other fields. If the index is larger than the last collection
index, the ioctl returns -1 and sets errno to -EINVAL. index, the ioctl returns -1 and sets errno to -EINVAL.
HIDIOCGDEVINFO - struct hiddev_devinfo (read) HIDIOCGDEVINFO
- struct hiddev_devinfo (read)
Gets a hiddev_devinfo structure which describes the device. Gets a hiddev_devinfo structure which describes the device.
HIDIOCGSTRING - struct hiddev_string_descriptor (read/write) HIDIOCGSTRING
- struct hiddev_string_descriptor (read/write)
Gets a string descriptor from the device. The caller must fill in the Gets a string descriptor from the device. The caller must fill in the
"index" field to indicate which descriptor should be returned. "index" field to indicate which descriptor should be returned.
HIDIOCINITREPORT - (none) HIDIOCINITREPORT
- (none)
Instructs the kernel to retrieve all input and feature report values Instructs the kernel to retrieve all input and feature report values
from the device. At this point, all the usage structures will contain from the device. At this point, all the usage structures will contain
current values for the device, and will maintain it as the device current values for the device, and will maintain it as the device
...@@ -130,21 +153,29 @@ changes. Note that the use of this ioctl is unnecessary in general, ...@@ -130,21 +153,29 @@ changes. Note that the use of this ioctl is unnecessary in general,
since later kernels automatically initialize the reports from the since later kernels automatically initialize the reports from the
device at attach time. device at attach time.
HIDIOCGNAME - string (variable length) HIDIOCGNAME
- string (variable length)
Gets the device name Gets the device name
HIDIOCGREPORT - struct hiddev_report_info (write) HIDIOCGREPORT
- struct hiddev_report_info (write)
Instructs the kernel to get a feature or input report from the device, Instructs the kernel to get a feature or input report from the device,
in order to selectively update the usage structures (in contrast to in order to selectively update the usage structures (in contrast to
INITREPORT). INITREPORT).
HIDIOCSREPORT - struct hiddev_report_info (write) HIDIOCSREPORT
- struct hiddev_report_info (write)
Instructs the kernel to send a report to the device. This report can Instructs the kernel to send a report to the device. This report can
be filled in by the user through HIDIOCSUSAGE calls (below) to fill in be filled in by the user through HIDIOCSUSAGE calls (below) to fill in
individual usage values in the report before sending the report in full individual usage values in the report before sending the report in full
to the device. to the device.
HIDIOCGREPORTINFO
- struct hiddev_report_info (read/write)
HIDIOCGREPORTINFO - struct hiddev_report_info (read/write)
Fills in a hiddev_report_info structure for the user. The report is Fills in a hiddev_report_info structure for the user. The report is
looked up by type (input, output or feature) and id, so these fields looked up by type (input, output or feature) and id, so these fields
must be filled in by the user. The ID can be absolute -- the actual must be filled in by the user. The ID can be absolute -- the actual
...@@ -154,52 +185,67 @@ report_id) for the next report after report_id. Without a-priori ...@@ -154,52 +185,67 @@ report_id) for the next report after report_id. Without a-priori
information about report ids, the right way to use this ioctl is to information about report ids, the right way to use this ioctl is to
use the relative IDs above to enumerate the valid IDs. The ioctl use the relative IDs above to enumerate the valid IDs. The ioctl
returns non-zero when there is no more next ID. The real report ID is returns non-zero when there is no more next ID. The real report ID is
filled into the returned hiddev_report_info structure. filled into the returned hiddev_report_info structure.
HIDIOCGFIELDINFO
- struct hiddev_field_info (read/write)
HIDIOCGFIELDINFO - struct hiddev_field_info (read/write)
Returns the field information associated with a report in a Returns the field information associated with a report in a
hiddev_field_info structure. The user must fill in report_id and hiddev_field_info structure. The user must fill in report_id and
report_type in this structure, as above. The field_index should also report_type in this structure, as above. The field_index should also
be filled in, which should be a number from 0 and maxfield-1, as be filled in, which should be a number from 0 and maxfield-1, as
returned from a previous HIDIOCGREPORTINFO call. returned from a previous HIDIOCGREPORTINFO call.
HIDIOCGUCODE
- struct hiddev_usage_ref (read/write)
HIDIOCGUCODE - struct hiddev_usage_ref (read/write)
Returns the usage_code in a hiddev_usage_ref structure, given that Returns the usage_code in a hiddev_usage_ref structure, given that
given its report type, report id, field index, and index within the given its report type, report id, field index, and index within the
field have already been filled into the structure. field have already been filled into the structure.
HIDIOCGUSAGE - struct hiddev_usage_ref (read/write) HIDIOCGUSAGE
- struct hiddev_usage_ref (read/write)
Returns the value of a usage in a hiddev_usage_ref structure. The Returns the value of a usage in a hiddev_usage_ref structure. The
usage to be retrieved can be specified as above, or the user can usage to be retrieved can be specified as above, or the user can
choose to fill in the report_type field and specify the report_id as choose to fill in the report_type field and specify the report_id as
HID_REPORT_ID_UNKNOWN. In this case, the hiddev_usage_ref will be HID_REPORT_ID_UNKNOWN. In this case, the hiddev_usage_ref will be
filled in with the report and field information associated with this filled in with the report and field information associated with this
usage if it is found. usage if it is found.
HIDIOCSUSAGE
- struct hiddev_usage_ref (write)
HIDIOCSUSAGE - struct hiddev_usage_ref (write)
Sets the value of a usage in an output report. The user fills in Sets the value of a usage in an output report. The user fills in
the hiddev_usage_ref structure as above, but additionally fills in the hiddev_usage_ref structure as above, but additionally fills in
the value field. the value field.
HIDIOGCOLLECTIONINDEX - struct hiddev_usage_ref (write) HIDIOGCOLLECTIONINDEX
- struct hiddev_usage_ref (write)
Returns the collection index associated with this usage. This Returns the collection index associated with this usage. This
indicates where in the collection hierarchy this usage sits. indicates where in the collection hierarchy this usage sits.
HIDIOCGFLAG - int (read) HIDIOCGFLAG
HIDIOCSFLAG - int (write) - int (read)
HIDIOCSFLAG
- int (write)
These operations respectively inspect and replace the mode flags These operations respectively inspect and replace the mode flags
that influence the read() call above. The flags are as follows: that influence the read() call above. The flags are as follows:
HIDDEV_FLAG_UREF - read() calls will now return HIDDEV_FLAG_UREF
- read() calls will now return
struct hiddev_usage_ref instead of struct hiddev_event. struct hiddev_usage_ref instead of struct hiddev_event.
This is a larger structure, but in situations where the This is a larger structure, but in situations where the
device has more than one usage in its reports with the device has more than one usage in its reports with the
same usage code, this mode serves to resolve such same usage code, this mode serves to resolve such
ambiguity. ambiguity.
HIDDEV_FLAG_REPORT - This flag can only be used in conjunction HIDDEV_FLAG_REPORT
- This flag can only be used in conjunction
with HIDDEV_FLAG_UREF. With this flag set, when the device with HIDDEV_FLAG_UREF. With this flag set, when the device
sends a report, a struct hiddev_usage_ref will be returned sends a report, a struct hiddev_usage_ref will be returned
to read() filled in with the report_type and report_id, but to read() filled in with the report_type and report_id, but
with field_index set to FIELD_INDEX_NONE. This serves as with field_index set to FIELD_INDEX_NONE. This serves as
additional notification when the device has sent a report. additional notification when the device has sent a report.
HIDRAW - Raw Access to USB and Bluetooth Human Interface Devices ================================================================
================================================================== HIDRAW - Raw Access to USB and Bluetooth Human Interface Devices
================================================================
The hidraw driver provides a raw interface to USB and Bluetooth Human The hidraw driver provides a raw interface to USB and Bluetooth Human
Interface Devices (HIDs). It differs from hiddev in that reports sent and Interface Devices (HIDs). It differs from hiddev in that reports sent and
...@@ -31,6 +32,7 @@ directly under /dev (eg: /dev/hidraw0). As this location is distribution- ...@@ -31,6 +32,7 @@ directly under /dev (eg: /dev/hidraw0). As this location is distribution-
and udev rule-dependent, applications should use libudev to locate hidraw and udev rule-dependent, applications should use libudev to locate hidraw
devices attached to the system. There is a tutorial on libudev with a devices attached to the system. There is a tutorial on libudev with a
working example at: working example at:
http://www.signal11.us/oss/udev/ http://www.signal11.us/oss/udev/
The HIDRAW API The HIDRAW API
...@@ -51,7 +53,7 @@ byte. For devices which do not use numbered reports, the report data ...@@ -51,7 +53,7 @@ byte. For devices which do not use numbered reports, the report data
will begin at the first byte. will begin at the first byte.
write() write()
-------- -------
The write() function will write a report to the device. For USB devices, if The write() function will write a report to the device. For USB devices, if
the device has an INTERRUPT OUT endpoint, the report will be sent on that the device has an INTERRUPT OUT endpoint, the report will be sent on that
endpoint. If it does not, the report will be sent over the control endpoint, endpoint. If it does not, the report will be sent over the control endpoint,
...@@ -62,38 +64,52 @@ number. If the device does not use numbered reports, the first byte should ...@@ -62,38 +64,52 @@ number. If the device does not use numbered reports, the first byte should
be set to 0. The report data itself should begin at the second byte. be set to 0. The report data itself should begin at the second byte.
ioctl() ioctl()
-------- -------
Hidraw supports the following ioctls: Hidraw supports the following ioctls:
HIDIOCGRDESCSIZE: Get Report Descriptor Size HIDIOCGRDESCSIZE:
Get Report Descriptor Size
This ioctl will get the size of the device's report descriptor. This ioctl will get the size of the device's report descriptor.
HIDIOCGRDESC: Get Report Descriptor HIDIOCGRDESC:
Get Report Descriptor
This ioctl returns the device's report descriptor using a This ioctl returns the device's report descriptor using a
hidraw_report_descriptor struct. Make sure to set the size field of the hidraw_report_descriptor struct. Make sure to set the size field of the
hidraw_report_descriptor struct to the size returned from HIDIOCGRDESCSIZE. hidraw_report_descriptor struct to the size returned from HIDIOCGRDESCSIZE.
HIDIOCGRAWINFO: Get Raw Info HIDIOCGRAWINFO:
Get Raw Info
This ioctl will return a hidraw_devinfo struct containing the bus type, the This ioctl will return a hidraw_devinfo struct containing the bus type, the
vendor ID (VID), and product ID (PID) of the device. The bus type can be one vendor ID (VID), and product ID (PID) of the device. The bus type can be one
of: of::
BUS_USB
BUS_HIL - BUS_USB
BUS_BLUETOOTH - BUS_HIL
BUS_VIRTUAL - BUS_BLUETOOTH
- BUS_VIRTUAL
which are defined in uapi/linux/input.h. which are defined in uapi/linux/input.h.
HIDIOCGRAWNAME(len): Get Raw Name HIDIOCGRAWNAME(len):
Get Raw Name
This ioctl returns a string containing the vendor and product strings of This ioctl returns a string containing the vendor and product strings of
the device. The returned string is Unicode, UTF-8 encoded. the device. The returned string is Unicode, UTF-8 encoded.
HIDIOCGRAWPHYS(len): Get Physical Address HIDIOCGRAWPHYS(len):
Get Physical Address
This ioctl returns a string representing the physical address of the device. This ioctl returns a string representing the physical address of the device.
For USB devices, the string contains the physical path to the device (the For USB devices, the string contains the physical path to the device (the
USB controller, hubs, ports, etc). For Bluetooth devices, the string USB controller, hubs, ports, etc). For Bluetooth devices, the string
contains the hardware (MAC) address of the device. contains the hardware (MAC) address of the device.
HIDIOCSFEATURE(len): Send a Feature Report HIDIOCSFEATURE(len):
Send a Feature Report
This ioctl will send a feature report to the device. Per the HID This ioctl will send a feature report to the device. Per the HID
specification, feature reports are always sent using the control endpoint. specification, feature reports are always sent using the control endpoint.
Set the first byte of the supplied buffer to the report number. For devices Set the first byte of the supplied buffer to the report number. For devices
...@@ -101,7 +117,9 @@ which do not use numbered reports, set the first byte to 0. The report data ...@@ -101,7 +117,9 @@ which do not use numbered reports, set the first byte to 0. The report data
begins in the second byte. Make sure to set len accordingly, to one more begins in the second byte. Make sure to set len accordingly, to one more
than the length of the report (to account for the report number). than the length of the report (to account for the report number).
HIDIOCGFEATURE(len): Get a Feature Report HIDIOCGFEATURE(len):
Get a Feature Report
This ioctl will request a feature report from the device using the control This ioctl will request a feature report from the device using the control
endpoint. The first byte of the supplied buffer should be set to the report endpoint. The first byte of the supplied buffer should be set to the report
number of the requested report. For devices which do not use numbered number of the requested report. For devices which do not use numbered
...@@ -109,11 +127,12 @@ reports, set the first byte to 0. The report will be returned starting at ...@@ -109,11 +127,12 @@ reports, set the first byte to 0. The report will be returned starting at
the first byte of the buffer (ie: the report number is not returned). the first byte of the buffer (ie: the report number is not returned).
Example Example
--------- -------
In samples/, find hid-example.c, which shows examples of read(), write(), In samples/, find hid-example.c, which shows examples of read(), write(),
and all the ioctls for hidraw. The code may be used by anyone for any and all the ioctls for hidraw. The code may be used by anyone for any
purpose, and can serve as a starting point for developing applications using purpose, and can serve as a starting point for developing applications using
hidraw. hidraw.
Document by: Document by:
Alan Ott <alan@signal11.us>, Signal 11 Software Alan Ott <alan@signal11.us>, Signal 11 Software
:orphan:
=============================
Human Interface Devices (HID)
=============================
.. toctree::
:maxdepth: 1
hiddev
hidraw
hid-sensor
hid-transport
uhid
hid-alps
intel-ish-hid
=================================
Intel Integrated Sensor Hub (ISH) Intel Integrated Sensor Hub (ISH)
=============================== =================================
A sensor hub enables the ability to offload sensor polling and algorithm A sensor hub enables the ability to offload sensor polling and algorithm
processing to a dedicated low power co-processor. This allows the core processing to a dedicated low power co-processor. This allows the core
...@@ -18,9 +19,10 @@ transport protocol used for communication. The current external sensor hubs ...@@ -18,9 +19,10 @@ transport protocol used for communication. The current external sensor hubs
mainly use HID over i2C or USB. But ISH doesn't use either i2c or USB. mainly use HID over i2C or USB. But ISH doesn't use either i2c or USB.
1. Overview 1. Overview
===========
Using a analogy with a usbhid implementation, the ISH follows a similar model Using a analogy with a usbhid implementation, the ISH follows a similar model
for a very high speed communication: for a very high speed communication::
----------------- ---------------------- ----------------- ----------------------
| USB HID | --> | ISH HID | | USB HID | --> | ISH HID |
...@@ -57,12 +59,15 @@ is registered as a device on this bus. The driver, which binds each device ...@@ -57,12 +59,15 @@ is registered as a device on this bus. The driver, which binds each device
(ISH HID driver) identifies the device type and registers with the hid core. (ISH HID driver) identifies the device type and registers with the hid core.
2. ISH Implementation: Block Diagram 2. ISH Implementation: Block Diagram
====================================
::
--------------------------- ---------------------------
| User Space Applications | | User Space Applications |
--------------------------- ---------------------------
----------------IIO ABI---------------- ----------------IIO ABI----------------
-------------------------- --------------------------
| IIO Sensor Drivers | | IIO Sensor Drivers |
-------------------------- --------------------------
...@@ -84,16 +89,18 @@ is registered as a device on this bus. The driver, which binds each device ...@@ -84,16 +89,18 @@ is registered as a device on this bus. The driver, which binds each device
-------------------------- --------------------------
| IPC Drivers | | IPC Drivers |
-------------------------- --------------------------
OS OS
---------------- PCI ----------------- ---------------- PCI -----------------
Hardware + Firmware Hardware + Firmware
---------------------------- ----------------------------
| ISH Hardware/Firmware(FW) | | ISH Hardware/Firmware(FW) |
---------------------------- ----------------------------
3. High level processing in above blocks 3. High level processing in above blocks
========================================
3.1 Hardware Interface 3.1 Hardware Interface
----------------------
The ISH is exposed as "Non-VGA unclassified PCI device" to the host. The PCI The ISH is exposed as "Non-VGA unclassified PCI device" to the host. The PCI
product and vendor IDs are changed from different generations of processors. So product and vendor IDs are changed from different generations of processors. So
...@@ -101,17 +108,21 @@ the source code which enumerate drivers needs to update from generation to ...@@ -101,17 +108,21 @@ the source code which enumerate drivers needs to update from generation to
generation. generation.
3.2 Inter Processor Communication (IPC) driver 3.2 Inter Processor Communication (IPC) driver
----------------------------------------------
Location: drivers/hid/intel-ish-hid/ipc Location: drivers/hid/intel-ish-hid/ipc
The IPC message used memory mapped I/O. The registers are defined in The IPC message used memory mapped I/O. The registers are defined in
hw-ish-regs.h. hw-ish-regs.h.
3.2.1 IPC/FW message types 3.2.1 IPC/FW message types
^^^^^^^^^^^^^^^^^^^^^^^^^^
There are two types of messages, one for management of link and other messages There are two types of messages, one for management of link and other messages
are to and from transport layers. are to and from transport layers.
TX and RX of Transport messages TX and RX of Transport messages
...............................
A set of memory mapped register offers support of multi byte messages TX and A set of memory mapped register offers support of multi byte messages TX and
RX (E.g.IPC_REG_ISH2HOST_MSG, IPC_REG_HOST2ISH_MSG). The IPC layer maintains RX (E.g.IPC_REG_ISH2HOST_MSG, IPC_REG_HOST2ISH_MSG). The IPC layer maintains
...@@ -131,15 +142,19 @@ Bit 31: doorbell trigger (signal H/W interrupt to the other side) ...@@ -131,15 +142,19 @@ Bit 31: doorbell trigger (signal H/W interrupt to the other side)
Other bits are reserved, should be 0. Other bits are reserved, should be 0.
3.2.2 Transport layer interface 3.2.2 Transport layer interface
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
To abstract HW level IPC communication, a set of callbacks are registered. To abstract HW level IPC communication, a set of callbacks are registered.
The transport layer uses them to send and receive messages. The transport layer uses them to send and receive messages.
Refer to struct ishtp_hw_ops for callbacks. Refer to struct ishtp_hw_ops for callbacks.
3.3 ISH Transport layer 3.3 ISH Transport layer
-----------------------
Location: drivers/hid/intel-ish-hid/ishtp/ Location: drivers/hid/intel-ish-hid/ishtp/
3.3.1 A Generic Transport Layer 3.3.1 A Generic Transport Layer
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The transport layer is a bi-directional protocol, which defines: The transport layer is a bi-directional protocol, which defines:
- Set of commands to start, stop, connect, disconnect and flow control - Set of commands to start, stop, connect, disconnect and flow control
...@@ -151,6 +166,7 @@ http://www.intel.com/content/dam/www/public/us/en/documents/technical-\ ...@@ -151,6 +166,7 @@ http://www.intel.com/content/dam/www/public/us/en/documents/technical-\
specifications/dcmi-hi-1-0-spec.pdf "Chapter 7: Bus Message Layer" specifications/dcmi-hi-1-0-spec.pdf "Chapter 7: Bus Message Layer"
3.3.2 Connection and Flow Control Mechanism 3.3.2 Connection and Flow Control Mechanism
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Each FW client and a protocol is identified by an UUID. In order to communicate Each FW client and a protocol is identified by an UUID. In order to communicate
to a FW client, a connection must be established using connect request and to a FW client, a connection must be established using connect request and
...@@ -165,6 +181,7 @@ Either side can send disconnect request bus message to end communication. Also ...@@ -165,6 +181,7 @@ Either side can send disconnect request bus message to end communication. Also
the link will be dropped if major FW reset occurs. the link will be dropped if major FW reset occurs.
3.3.3 Peer to Peer data transfer 3.3.3 Peer to Peer data transfer
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Peer to Peer data transfer can happen with or without using DMA. Depending on Peer to Peer data transfer can happen with or without using DMA. Depending on
the sensor bandwidth requirement DMA can be enabled by using module parameter the sensor bandwidth requirement DMA can be enabled by using module parameter
...@@ -200,6 +217,7 @@ Currently, ISH FW decides to send over DMA if ISHTP message is more than 3 IPC ...@@ -200,6 +217,7 @@ Currently, ISH FW decides to send over DMA if ISHTP message is more than 3 IPC
fragments and via IPC otherwise. fragments and via IPC otherwise.
3.3.4 Ring Buffers 3.3.4 Ring Buffers
^^^^^^^^^^^^^^^^^^
When a client initiate a connection, a ring or RX and TX buffers are allocated. When a client initiate a connection, a ring or RX and TX buffers are allocated.
The size of ring can be specified by the client. HID client set 16 and 32 for The size of ring can be specified by the client. HID client set 16 and 32 for
...@@ -210,6 +228,7 @@ have processed the last message and may not have enough flow control credits ...@@ -210,6 +228,7 @@ have processed the last message and may not have enough flow control credits
to send. Same thing holds true on receive side and flow control is required. to send. Same thing holds true on receive side and flow control is required.
3.3.5 Host Enumeration 3.3.5 Host Enumeration
^^^^^^^^^^^^^^^^^^^^^^
The host enumeration bus command allow discovery of clients present in the FW. The host enumeration bus command allow discovery of clients present in the FW.
There can be multiple sensor clients and clients for calibration function. There can be multiple sensor clients and clients for calibration function.
...@@ -219,22 +238,26 @@ this transport layer takes advantage of Linux Bus driver model. Each ...@@ -219,22 +238,26 @@ this transport layer takes advantage of Linux Bus driver model. Each
client is registered as device on the the transport bus (ishtp bus). client is registered as device on the the transport bus (ishtp bus).
Enumeration sequence of messages: Enumeration sequence of messages:
- Host sends HOST_START_REQ_CMD, indicating that host ISHTP layer is up. - Host sends HOST_START_REQ_CMD, indicating that host ISHTP layer is up.
- FW responds with HOST_START_RES_CMD - FW responds with HOST_START_RES_CMD
- Host sends HOST_ENUM_REQ_CMD (enumerate FW clients) - Host sends HOST_ENUM_REQ_CMD (enumerate FW clients)
- FW responds with HOST_ENUM_RES_CMD that includes bitmap of available FW - FW responds with HOST_ENUM_RES_CMD that includes bitmap of available FW
client IDs client IDs
- For each FW ID found in that bitmap host sends - For each FW ID found in that bitmap host sends
HOST_CLIENT_PROPERTIES_REQ_CMD HOST_CLIENT_PROPERTIES_REQ_CMD
- FW responds with HOST_CLIENT_PROPERTIES_RES_CMD. Properties include UUID, - FW responds with HOST_CLIENT_PROPERTIES_RES_CMD. Properties include UUID,
max ISHTP message size, etc. max ISHTP message size, etc.
- Once host received properties for that last discovered client, it considers - Once host received properties for that last discovered client, it considers
ISHTP device fully functional (and allocates DMA buffers) ISHTP device fully functional (and allocates DMA buffers)
3.4 HID over ISH Client 3.4 HID over ISH Client
-----------------------
Location: drivers/hid/intel-ish-hid Location: drivers/hid/intel-ish-hid
The ISHTP client driver is responsible for: The ISHTP client driver is responsible for:
- enumerate HID devices under FW ISH client - enumerate HID devices under FW ISH client
- Get Report descriptor - Get Report descriptor
- Register with HID core as a LL driver - Register with HID core as a LL driver
...@@ -242,213 +265,221 @@ The ISHTP client driver is responsible for: ...@@ -242,213 +265,221 @@ The ISHTP client driver is responsible for:
- Get input reports - Get input reports
3.5 HID Sensor Hub MFD and IIO sensor drivers 3.5 HID Sensor Hub MFD and IIO sensor drivers
---------------------------------------------
The functionality in these drivers is the same as an external sensor hub. The functionality in these drivers is the same as an external sensor hub.
Refer to Refer to
Documentation/hid/hid-sensor.txt for HID sensor Documentation/hid/hid-sensor.rst for HID sensor
Documentation/ABI/testing/sysfs-bus-iio for IIO ABIs to user space Documentation/ABI/testing/sysfs-bus-iio for IIO ABIs to user space
3.6 End to End HID transport Sequence Diagram 3.6 End to End HID transport Sequence Diagram
---------------------------------------------
HID-ISH-CLN ISHTP IPC HW
| | | | ::
| | |-----WAKE UP------------------>|
| | | | HID-ISH-CLN ISHTP IPC HW
| | |-----HOST READY--------------->| | | | |
| | | | | | |-----WAKE UP------------------>|
| | |<----MNG_RESET_NOTIFY_ACK----- | | | | |
| | | | | | |-----HOST READY--------------->|
| |<----ISHTP_START------ | | | | | |
| | | | | | |<----MNG_RESET_NOTIFY_ACK----- |
| |<-----------------HOST_START_RES_CMD-------------------| | | | |
| | | | | |<----ISHTP_START------ | |
| |------------------QUERY_SUBSCRIBER-------------------->| | | | |
| | | | | |<-----------------HOST_START_RES_CMD-------------------|
| |------------------HOST_ENUM_REQ_CMD------------------->| | | | |
| | | | | |------------------QUERY_SUBSCRIBER-------------------->|
| |<-----------------HOST_ENUM_RES_CMD--------------------| | | | |
| | | | | |------------------HOST_ENUM_REQ_CMD------------------->|
| |------------------HOST_CLIENT_PROPERTIES_REQ_CMD------>| | | | |
| | | | | |<-----------------HOST_ENUM_RES_CMD--------------------|
| |<-----------------HOST_CLIENT_PROPERTIES_RES_CMD-------| | | | |
| Create new device on in ishtp bus | | | |------------------HOST_CLIENT_PROPERTIES_REQ_CMD------>|
| | | | | | | |
| |------------------HOST_CLIENT_PROPERTIES_REQ_CMD------>| | |<-----------------HOST_CLIENT_PROPERTIES_RES_CMD-------|
| | | | | Create new device on in ishtp bus | |
| |<-----------------HOST_CLIENT_PROPERTIES_RES_CMD-------| | | | |
| Create new device on in ishtp bus | | | |------------------HOST_CLIENT_PROPERTIES_REQ_CMD------>|
| | | | | | | |
| |--Repeat HOST_CLIENT_PROPERTIES_REQ_CMD-till last one--| | |<-----------------HOST_CLIENT_PROPERTIES_RES_CMD-------|
| | | | | Create new device on in ishtp bus | |
probed() | | | |
|----ishtp_cl_connect-->|----------------- CLIENT_CONNECT_REQ_CMD-------------->| | |--Repeat HOST_CLIENT_PROPERTIES_REQ_CMD-till last one--|
| | | | | | | |
| |<----------------CLIENT_CONNECT_RES_CMD----------------| probed()
| | | | |----ishtp_cl_connect--->|----------------- CLIENT_CONNECT_REQ_CMD-------------->|
|register event callback| | | | | | |
| | | | | |<----------------CLIENT_CONNECT_RES_CMD----------------|
|ishtp_cl_send( | | | |
HOSTIF_DM_ENUM_DEVICES) |----------fill ishtp_msg_hdr struct write to HW----- >| |register event callback | | |
| | | | | | | |
| | |<-----IRQ(IPC_PROTOCOL_ISHTP---| |ishtp_cl_send(
| | | | HOSTIF_DM_ENUM_DEVICES) |----------fill ishtp_msg_hdr struct write to HW----- >|
|<--ENUM_DEVICE RSP-----| | | | | | |
| | | | | | |<-----IRQ(IPC_PROTOCOL_ISHTP---|
for each enumerated device | | | |
|ishtp_cl_send( |<--ENUM_DEVICE RSP------| | |
HOSTIF_GET_HID_DESCRIPTOR |----------fill ishtp_msg_hdr struct write to HW--- >| | | | |
| | | | for each enumerated device
...Response |ishtp_cl_send(
| | | | HOSTIF_GET_HID_DESCRIPTOR|----------fill ishtp_msg_hdr struct write to HW----- >|
for each enumerated device | | | |
|ishtp_cl_send( ...Response
HOSTIF_GET_REPORT_DESCRIPTOR |----------fill ishtp_msg_hdr struct write to HW- >| | | | |
| | | | for each enumerated device
| | | | |ishtp_cl_send(
hid_allocate_device HOSTIF_GET_REPORT_DESCRIPTOR|--------------fill ishtp_msg_hdr struct write to HW-- >|
| | | | | | | |
hid_add_device | | | | | | |
| | | | hid_allocate_device
| | | |
hid_add_device | | |
| | | |
3.7 ISH Debugging 3.7 ISH Debugging
-----------------
To debug ISH, event tracing mechanism is used. To enable debug logs To debug ISH, event tracing mechanism is used. To enable debug logs
echo 1 > /sys/kernel/debug/tracing/events/intel_ish/enable echo 1 > /sys/kernel/debug/tracing/events/intel_ish/enable
cat sys/kernel/debug/tracing/trace cat sys/kernel/debug/tracing/trace
3.8 ISH IIO sysfs Example on Lenovo thinkpad Yoga 260 3.8 ISH IIO sysfs Example on Lenovo thinkpad Yoga 260
-----------------------------------------------------
root@otcpl-ThinkPad-Yoga-260:~# tree -l /sys/bus/iio/devices/
/sys/bus/iio/devices/ ::
├── iio:device0 -> ../../../devices/0044:8086:22D8.0001/HID-SENSOR-200073.9.auto/iio:device0
│   ├── buffer root@otcpl-ThinkPad-Yoga-260:~# tree -l /sys/bus/iio/devices/
│   │   ├── enable /sys/bus/iio/devices/
│   │   ├── length ├── iio:device0 -> ../../../devices/0044:8086:22D8.0001/HID-SENSOR-200073.9.auto/iio:device0
│   │   └── watermark │   ├── buffer
... │   │   ├── enable
│   ├── in_accel_hysteresis │   │   ├── length
│   ├── in_accel_offset │   │   └── watermark
│   ├── in_accel_sampling_frequency ...
│   ├── in_accel_scale │   ├── in_accel_hysteresis
│   ├── in_accel_x_raw │   ├── in_accel_offset
│   ├── in_accel_y_raw │   ├── in_accel_sampling_frequency
│   ├── in_accel_z_raw │   ├── in_accel_scale
│   ├── name │   ├── in_accel_x_raw
│   ├── scan_elements │   ├── in_accel_y_raw
│   │   ├── in_accel_x_en │   ├── in_accel_z_raw
│   │   ├── in_accel_x_index │   ├── name
│   │   ├── in_accel_x_type │   ├── scan_elements
│   │   ├── in_accel_y_en │   │   ├── in_accel_x_en
│   │   ├── in_accel_y_index │   │   ├── in_accel_x_index
│   │   ├── in_accel_y_type │   │   ├── in_accel_x_type
│   │   ├── in_accel_z_en │   │   ├── in_accel_y_en
│   │   ├── in_accel_z_index │   │   ├── in_accel_y_index
│   │   └── in_accel_z_type │   │   ├── in_accel_y_type
... │   │   ├── in_accel_z_en
│   │   ├── devices │   │   ├── in_accel_z_index
│   │   │   │   ├── buffer │   │   └── in_accel_z_type
│   │   │   │   │   ├── enable ...
│   │   │   │   │   ├── length │   │   ├── devices
│   │   │   │   │   └── watermark │   │   │   │   ├── buffer
│   │   │   │   ├── dev │   │   │   │   │   ├── enable
│   │   │   │   ├── in_intensity_both_raw │   │   │   │   │   ├── length
│   │   │   │   ├── in_intensity_hysteresis │   │   │   │   │   └── watermark
│   │   │   │   ├── in_intensity_offset │   │   │   │   ├── dev
│   │   │   │   ├── in_intensity_sampling_frequency │   │   │   │   ├── in_intensity_both_raw
│   │   │   │   ├── in_intensity_scale │   │   │   │   ├── in_intensity_hysteresis
│   │   │   │   ├── name │   │   │   │   ├── in_intensity_offset
│   │   │   │   ├── scan_elements │   │   │   │   ├── in_intensity_sampling_frequency
│   │   │   │   │   ├── in_intensity_both_en │   │   │   │   ├── in_intensity_scale
│   │   │   │   │   ├── in_intensity_both_index │   │   │   │   ├── name
│   │   │   │   │   └── in_intensity_both_type │   │   │   │   ├── scan_elements
│   │   │   │   ├── trigger │   │   │   │   │   ├── in_intensity_both_en
│   │   │   │   │   └── current_trigger │   │   │   │   │   ├── in_intensity_both_index
... │   │   │   │   │   └── in_intensity_both_type
│   │   │   │   ├── buffer │   │   │   │   ├── trigger
│   │   │   │   │   ├── enable │   │   │   │   │   └── current_trigger
│   │   │   │   │   ├── length ...
│   │   │   │   │   └── watermark │   │   │   │   ├── buffer
│   │   │   │   ├── dev │   │   │   │   │   ├── enable
│   │   │   │   ├── in_magn_hysteresis │   │   │   │   │   ├── length
│   │   │   │   ├── in_magn_offset │   │   │   │   │   └── watermark
│   │   │   │   ├── in_magn_sampling_frequency │   │   │   │   ├── dev
│   │   │   │   ├── in_magn_scale │   │   │   │   ├── in_magn_hysteresis
│   │   │   │   ├── in_magn_x_raw │   │   │   │   ├── in_magn_offset
│   │   │   │   ├── in_magn_y_raw │   │   │   │   ├── in_magn_sampling_frequency
│   │   │   │   ├── in_magn_z_raw │   │   │   │   ├── in_magn_scale
│   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_raw │   │   │   │   ├── in_magn_x_raw
│   │   │   │   ├── in_rot_hysteresis │   │   │   │   ├── in_magn_y_raw
│   │   │   │   ├── in_rot_offset │   │   │   │   ├── in_magn_z_raw
│   │   │   │   ├── in_rot_sampling_frequency │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_raw
│   │   │   │   ├── in_rot_scale │   │   │   │   ├── in_rot_hysteresis
│   │   │   │   ├── name │   │   │   │   ├── in_rot_offset
... │   │   │   │   ├── in_rot_sampling_frequency
│   │   │   │   ├── scan_elements │   │   │   │   ├── in_rot_scale
│   │   │   │   │   ├── in_magn_x_en │   │   │   │   ├── name
│   │   │   │   │   ├── in_magn_x_index ...
│   │   │   │   │   ├── in_magn_x_type │   │   │   │   ├── scan_elements
│   │   │   │   │   ├── in_magn_y_en │   │   │   │   │   ├── in_magn_x_en
│   │   │   │   │   ├── in_magn_y_index │   │   │   │   │   ├── in_magn_x_index
│   │   │   │   │   ├── in_magn_y_type │   │   │   │   │   ├── in_magn_x_type
│   │   │   │   │   ├── in_magn_z_en │   │   │   │   │   ├── in_magn_y_en
│   │   │   │   │   ├── in_magn_z_index │   │   │   │   │   ├── in_magn_y_index
│   │   │   │   │   ├── in_magn_z_type │   │   │   │   │   ├── in_magn_y_type
│   │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_en │   │   │   │   │   ├── in_magn_z_en
│   │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_index │   │   │   │   │   ├── in_magn_z_index
│   │   │   │   │   └── in_rot_from_north_magnetic_tilt_comp_type │   │   │   │   │   ├── in_magn_z_type
│   │   │   │   ├── trigger │   │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_en
│   │   │   │   │   └── current_trigger │   │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_index
... │   │   │   │   │   └── in_rot_from_north_magnetic_tilt_comp_type
│   │   │   │   ├── buffer │   │   │   │   ├── trigger
│   │   │   │   │   ├── enable │   │   │   │   │   └── current_trigger
│   │   │   │   │   ├── length ...
│   │   │   │   │   └── watermark │   │   │   │   ├── buffer
│   │   │   │   ├── dev │   │   │   │   │   ├── enable
│   │   │   │   ├── in_anglvel_hysteresis │   │   │   │   │   ├── length
│   │   │   │   ├── in_anglvel_offset │   │   │   │   │   └── watermark
│   │   │   │   ├── in_anglvel_sampling_frequency │   │   │   │   ├── dev
│   │   │   │   ├── in_anglvel_scale │   │   │   │   ├── in_anglvel_hysteresis
│   │   │   │   ├── in_anglvel_x_raw │   │   │   │   ├── in_anglvel_offset
│   │   │   │   ├── in_anglvel_y_raw │   │   │   │   ├── in_anglvel_sampling_frequency
│   │   │   │   ├── in_anglvel_z_raw │   │   │   │   ├── in_anglvel_scale
│   │   │   │   ├── name │   │   │   │   ├── in_anglvel_x_raw
│   │   │   │   ├── scan_elements │   │   │   │   ├── in_anglvel_y_raw
│   │   │   │   │   ├── in_anglvel_x_en │   │   │   │   ├── in_anglvel_z_raw
│   │   │   │   │   ├── in_anglvel_x_index │   │   │   │   ├── name
│   │   │   │   │   ├── in_anglvel_x_type │   │   │   │   ├── scan_elements
│   │   │   │   │   ├── in_anglvel_y_en │   │   │   │   │   ├── in_anglvel_x_en
│   │   │   │   │   ├── in_anglvel_y_index │   │   │   │   │   ├── in_anglvel_x_index
│   │   │   │   │   ├── in_anglvel_y_type │   │   │   │   │   ├── in_anglvel_x_type
│   │   │   │   │   ├── in_anglvel_z_en │   │   │   │   │   ├── in_anglvel_y_en
│   │   │   │   │   ├── in_anglvel_z_index │   │   │   │   │   ├── in_anglvel_y_index
│   │   │   │   │   └── in_anglvel_z_type │   │   │   │   │   ├── in_anglvel_y_type
│   │   │   │   ├── trigger │   │   │   │   │   ├── in_anglvel_z_en
│   │   │   │   │   └── current_trigger │   │   │   │   │   ├── in_anglvel_z_index
... │   │   │   │   │   └── in_anglvel_z_type
│   │   │   │   ├── buffer │   │   │   │   ├── trigger
│   │   │   │   │   ├── enable │   │   │   │   │   └── current_trigger
│   │   │   │   │   ├── length ...
│   │   │   │   │   └── watermark │   │   │   │   ├── buffer
│   │   │   │   ├── dev │   │   │   │   │   ├── enable
│   │   │   │   ├── in_anglvel_hysteresis │   │   │   │   │   ├── length
│   │   │   │   ├── in_anglvel_offset │   │   │   │   │   └── watermark
│   │   │   │   ├── in_anglvel_sampling_frequency │   │   │   │   ├── dev
│   │   │   │   ├── in_anglvel_scale │   │   │   │   ├── in_anglvel_hysteresis
│   │   │   │   ├── in_anglvel_x_raw │   │   │   │   ├── in_anglvel_offset
│   │   │   │   ├── in_anglvel_y_raw │   │   │   │   ├── in_anglvel_sampling_frequency
│   │   │   │   ├── in_anglvel_z_raw │   │   │   │   ├── in_anglvel_scale
│   │   │   │   ├── name │   │   │   │   ├── in_anglvel_x_raw
│   │   │   │   ├── scan_elements │   │   │   │   ├── in_anglvel_y_raw
│   │   │   │   │   ├── in_anglvel_x_en │   │   │   │   ├── in_anglvel_z_raw
│   │   │   │   │   ├── in_anglvel_x_index │   │   │   │   ├── name
│   │   │   │   │   ├── in_anglvel_x_type │   │   │   │   ├── scan_elements
│   │   │   │   │   ├── in_anglvel_y_en │   │   │   │   │   ├── in_anglvel_x_en
│   │   │   │   │   ├── in_anglvel_y_index │   │   │   │   │   ├── in_anglvel_x_index
│   │   │   │   │   ├── in_anglvel_y_type │   │   │   │   │   ├── in_anglvel_x_type
│   │   │   │   │   ├── in_anglvel_z_en │   │   │   │   │   ├── in_anglvel_y_en
│   │   │   │   │   ├── in_anglvel_z_index │   │   │   │   │   ├── in_anglvel_y_index
│   │   │   │   │   └── in_anglvel_z_type │   │   │   │   │   ├── in_anglvel_y_type
│   │   │   │   ├── trigger │   │   │   │   │   ├── in_anglvel_z_en
│   │   │   │   │   └── current_trigger │   │   │   │   │   ├── in_anglvel_z_index
... │   │   │   │   │   └── in_anglvel_z_type
│   │   │   │   ├── trigger
│   │   │   │   │   └── current_trigger
...
UHID - User-space I/O driver support for HID subsystem ======================================================
======================================================== UHID - User-space I/O driver support for HID subsystem
======================================================
UHID allows user-space to implement HID transport drivers. Please see UHID allows user-space to implement HID transport drivers. Please see
hid-transport.txt for an introduction into HID transport drivers. This document hid-transport.txt for an introduction into HID transport drivers. This document
...@@ -22,9 +23,9 @@ If a new device is detected by your HID I/O Driver and you want to register this ...@@ -22,9 +23,9 @@ If a new device is detected by your HID I/O Driver and you want to register this
device with the HID subsystem, then you need to open /dev/uhid once for each device with the HID subsystem, then you need to open /dev/uhid once for each
device you want to register. All further communication is done by read()'ing or device you want to register. All further communication is done by read()'ing or
write()'ing "struct uhid_event" objects. Non-blocking operations are supported write()'ing "struct uhid_event" objects. Non-blocking operations are supported
by setting O_NONBLOCK. by setting O_NONBLOCK::
struct uhid_event { struct uhid_event {
__u32 type; __u32 type;
union { union {
struct uhid_create2_req create2; struct uhid_create2_req create2;
...@@ -32,7 +33,7 @@ struct uhid_event { ...@@ -32,7 +33,7 @@ struct uhid_event {
struct uhid_input2_req input2; struct uhid_input2_req input2;
... ...
} u; } u;
}; };
The "type" field contains the ID of the event. Depending on the ID different The "type" field contains the ID of the event. Depending on the ID different
payloads are sent. You must not split a single event across multiple read()'s or payloads are sent. You must not split a single event across multiple read()'s or
...@@ -86,31 +87,31 @@ the request was handled successfully. O_NONBLOCK does not affect write() as ...@@ -86,31 +87,31 @@ the request was handled successfully. O_NONBLOCK does not affect write() as
writes are always handled immediately in a non-blocking fashion. Future requests writes are always handled immediately in a non-blocking fashion. Future requests
might make use of O_NONBLOCK, though. might make use of O_NONBLOCK, though.
UHID_CREATE2: UHID_CREATE2:
This creates the internal HID device. No I/O is possible until you send this This creates the internal HID device. No I/O is possible until you send this
event to the kernel. The payload is of type struct uhid_create2_req and event to the kernel. The payload is of type struct uhid_create2_req and
contains information about your device. You can start I/O now. contains information about your device. You can start I/O now.
UHID_DESTROY: UHID_DESTROY:
This destroys the internal HID device. No further I/O will be accepted. There This destroys the internal HID device. No further I/O will be accepted. There
may still be pending messages that you can receive with read() but no further may still be pending messages that you can receive with read() but no further
UHID_INPUT events can be sent to the kernel. UHID_INPUT events can be sent to the kernel.
You can create a new device by sending UHID_CREATE2 again. There is no need to You can create a new device by sending UHID_CREATE2 again. There is no need to
reopen the character device. reopen the character device.
UHID_INPUT2: UHID_INPUT2:
You must send UHID_CREATE2 before sending input to the kernel! This event You must send UHID_CREATE2 before sending input to the kernel! This event
contains a data-payload. This is the raw data that you read from your device contains a data-payload. This is the raw data that you read from your device
on the interrupt channel. The kernel will parse the HID reports. on the interrupt channel. The kernel will parse the HID reports.
UHID_GET_REPORT_REPLY: UHID_GET_REPORT_REPLY:
If you receive a UHID_GET_REPORT request you must answer with this request. If you receive a UHID_GET_REPORT request you must answer with this request.
You must copy the "id" field from the request into the answer. Set the "err" You must copy the "id" field from the request into the answer. Set the "err"
field to 0 if no error occurred or to EIO if an I/O error occurred. field to 0 if no error occurred or to EIO if an I/O error occurred.
If "err" is 0 then you should fill the buffer of the answer with the results If "err" is 0 then you should fill the buffer of the answer with the results
of the GET_REPORT request and set "size" correspondingly. of the GET_REPORT request and set "size" correspondingly.
UHID_SET_REPORT_REPLY: UHID_SET_REPORT_REPLY:
This is the SET_REPORT equivalent of UHID_GET_REPORT_REPLY. Unlike GET_REPORT, This is the SET_REPORT equivalent of UHID_GET_REPORT_REPLY. Unlike GET_REPORT,
SET_REPORT never returns a data buffer, therefore, it's sufficient to set the SET_REPORT never returns a data buffer, therefore, it's sufficient to set the
"id" and "err" fields correctly. "id" and "err" fields correctly.
...@@ -120,16 +121,18 @@ read() ...@@ -120,16 +121,18 @@ read()
read() will return a queued output report. No reaction is required to any of read() will return a queued output report. No reaction is required to any of
them but you should handle them according to your needs. them but you should handle them according to your needs.
UHID_START: UHID_START:
This is sent when the HID device is started. Consider this as an answer to This is sent when the HID device is started. Consider this as an answer to
UHID_CREATE2. This is always the first event that is sent. Note that this UHID_CREATE2. This is always the first event that is sent. Note that this
event might not be available immediately after write(UHID_CREATE2) returns. event might not be available immediately after write(UHID_CREATE2) returns.
Device drivers might required delayed setups. Device drivers might required delayed setups.
This event contains a payload of type uhid_start_req. The "dev_flags" field This event contains a payload of type uhid_start_req. The "dev_flags" field
describes special behaviors of a device. The following flags are defined: describes special behaviors of a device. The following flags are defined:
UHID_DEV_NUMBERED_FEATURE_REPORTS:
UHID_DEV_NUMBERED_OUTPUT_REPORTS: - UHID_DEV_NUMBERED_FEATURE_REPORTS
UHID_DEV_NUMBERED_INPUT_REPORTS: - UHID_DEV_NUMBERED_OUTPUT_REPORTS
- UHID_DEV_NUMBERED_INPUT_REPORTS
Each of these flags defines whether a given report-type uses numbered Each of these flags defines whether a given report-type uses numbered
reports. If numbered reports are used for a type, all messages from reports. If numbered reports are used for a type, all messages from
the kernel already have the report-number as prefix. Otherwise, no the kernel already have the report-number as prefix. Otherwise, no
...@@ -137,33 +140,35 @@ them but you should handle them according to your needs. ...@@ -137,33 +140,35 @@ them but you should handle them according to your needs.
For messages sent by user-space to the kernel, you must adjust the For messages sent by user-space to the kernel, you must adjust the
prefixes according to these flags. prefixes according to these flags.
UHID_STOP: UHID_STOP:
This is sent when the HID device is stopped. Consider this as an answer to This is sent when the HID device is stopped. Consider this as an answer to
UHID_DESTROY. UHID_DESTROY.
If you didn't destroy your device via UHID_DESTROY, but the kernel sends an If you didn't destroy your device via UHID_DESTROY, but the kernel sends an
UHID_STOP event, this should usually be ignored. It means that the kernel UHID_STOP event, this should usually be ignored. It means that the kernel
reloaded/changed the device driver loaded on your HID device (or some other reloaded/changed the device driver loaded on your HID device (or some other
maintenance actions happened). maintenance actions happened).
You can usually ignored any UHID_STOP events safely. You can usually ignored any UHID_STOP events safely.
UHID_OPEN: UHID_OPEN:
This is sent when the HID device is opened. That is, the data that the HID This is sent when the HID device is opened. That is, the data that the HID
device provides is read by some other process. You may ignore this event but device provides is read by some other process. You may ignore this event but
it is useful for power-management. As long as you haven't received this event it is useful for power-management. As long as you haven't received this event
there is actually no other process that reads your data so there is no need to there is actually no other process that reads your data so there is no need to
send UHID_INPUT2 events to the kernel. send UHID_INPUT2 events to the kernel.
UHID_CLOSE: UHID_CLOSE:
This is sent when there are no more processes which read the HID data. It is This is sent when there are no more processes which read the HID data. It is
the counterpart of UHID_OPEN and you may as well ignore this event. the counterpart of UHID_OPEN and you may as well ignore this event.
UHID_OUTPUT: UHID_OUTPUT:
This is sent if the HID device driver wants to send raw data to the I/O This is sent if the HID device driver wants to send raw data to the I/O
device on the interrupt channel. You should read the payload and forward it to device on the interrupt channel. You should read the payload and forward it to
the device. The payload is of type "struct uhid_output_req". the device. The payload is of type "struct uhid_output_req".
This may be received even though you haven't received UHID_OPEN, yet. This may be received even though you haven't received UHID_OPEN, yet.
UHID_GET_REPORT: UHID_GET_REPORT:
This event is sent if the kernel driver wants to perform a GET_REPORT request This event is sent if the kernel driver wants to perform a GET_REPORT request
on the control channeld as described in the HID specs. The report-type and on the control channeld as described in the HID specs. The report-type and
report-number are available in the payload. report-number are available in the payload.
...@@ -177,11 +182,12 @@ them but you should handle them according to your needs. ...@@ -177,11 +182,12 @@ them but you should handle them according to your needs.
timed out, the kernel will ignore the response silently. The "id" field is timed out, the kernel will ignore the response silently. The "id" field is
never re-used, so conflicts cannot happen. never re-used, so conflicts cannot happen.
UHID_SET_REPORT: UHID_SET_REPORT:
This is the SET_REPORT equivalent of UHID_GET_REPORT. On receipt, you shall This is the SET_REPORT equivalent of UHID_GET_REPORT. On receipt, you shall
send a SET_REPORT request to your hid device. Once it replies, you must tell send a SET_REPORT request to your hid device. Once it replies, you must tell
the kernel about it via UHID_SET_REPORT_REPLY. the kernel about it via UHID_SET_REPORT_REPLY.
The same restrictions as for UHID_GET_REPORT apply. The same restrictions as for UHID_GET_REPORT apply.
---------------------------------------------------- ----------------------------------------------------
Written 2012, David Herrmann <dh.herrmann@gmail.com> Written 2012, David Herrmann <dh.herrmann@gmail.com>
...@@ -188,7 +188,7 @@ LCDs and many other purposes. ...@@ -188,7 +188,7 @@ LCDs and many other purposes.
The monitor and speaker controls should be easy to add to the hid/input The monitor and speaker controls should be easy to add to the hid/input
interface, but for the UPSs and LCDs it doesn't make much sense. For this, interface, but for the UPSs and LCDs it doesn't make much sense. For this,
the hiddev interface was designed. See Documentation/hid/hiddev.txt the hiddev interface was designed. See Documentation/hid/hiddev.rst
for more information about it. for more information about it.
The usage of the usbhid module is very simple, it takes no parameters, The usage of the usbhid module is very simple, it takes no parameters,
......
...@@ -16432,7 +16432,7 @@ M: Benjamin Tissoires <benjamin.tissoires@redhat.com> ...@@ -16432,7 +16432,7 @@ M: Benjamin Tissoires <benjamin.tissoires@redhat.com>
L: linux-usb@vger.kernel.org L: linux-usb@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git
S: Maintained S: Maintained
F: Documentation/hid/hiddev.txt F: Documentation/hid/hiddev.rst
F: drivers/hid/usbhid/ F: drivers/hid/usbhid/
USB INTEL XHCI ROLE MUX DRIVER USB INTEL XHCI ROLE MUX DRIVER
......
...@@ -1157,6 +1157,7 @@ ...@@ -1157,6 +1157,7 @@
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01 0x0042 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01 0x0042
#define USB_DEVICE_ID_UGEE_TABLET_G5 0x0074 #define USB_DEVICE_ID_UGEE_TABLET_G5 0x0074
#define USB_DEVICE_ID_UGEE_TABLET_EX07S 0x0071 #define USB_DEVICE_ID_UGEE_TABLET_EX07S 0x0071
#define USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720 0x0055
#define USB_VENDOR_ID_UNITEC 0x227d #define USB_VENDOR_ID_UNITEC 0x227d
#define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709 #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709
...@@ -1241,6 +1242,7 @@ ...@@ -1241,6 +1242,7 @@
#define USB_DEVICE_ID_PRIMAX_KEYBOARD 0x4e05 #define USB_DEVICE_ID_PRIMAX_KEYBOARD 0x4e05
#define USB_DEVICE_ID_PRIMAX_REZEL 0x4e72 #define USB_DEVICE_ID_PRIMAX_REZEL 0x4e72
#define USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D0F 0x4d0f #define USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D0F 0x4d0f
#define USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D65 0x4d65
#define USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4E22 0x4e22 #define USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4E22 0x4e22
......
...@@ -869,8 +869,6 @@ static void lg_remove(struct hid_device *hdev) ...@@ -869,8 +869,6 @@ static void lg_remove(struct hid_device *hdev)
} }
static const struct hid_device_id lg_devices[] = { static const struct hid_device_id lg_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
.driver_data = LG_RDESC | LG_WIRELESS },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER), { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER),
.driver_data = LG_RDESC | LG_WIRELESS }, .driver_data = LG_RDESC | LG_WIRELESS },
......
...@@ -1103,12 +1103,14 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, ...@@ -1103,12 +1103,14 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,
static int logi_dj_recv_query_hidpp_devices(struct dj_receiver_dev *djrcv_dev) static int logi_dj_recv_query_hidpp_devices(struct dj_receiver_dev *djrcv_dev)
{ {
const u8 template[] = {REPORT_ID_HIDPP_SHORT, static const u8 template[] = {
HIDPP_RECEIVER_INDEX, REPORT_ID_HIDPP_SHORT,
HIDPP_SET_REGISTER, HIDPP_RECEIVER_INDEX,
HIDPP_REG_CONNECTION_STATE, HIDPP_SET_REGISTER,
HIDPP_FAKE_DEVICE_ARRIVAL, HIDPP_REG_CONNECTION_STATE,
0x00, 0x00}; HIDPP_FAKE_DEVICE_ARRIVAL,
0x00, 0x00
};
u8 *hidpp_report; u8 *hidpp_report;
int retval; int retval;
...@@ -1123,7 +1125,7 @@ static int logi_dj_recv_query_hidpp_devices(struct dj_receiver_dev *djrcv_dev) ...@@ -1123,7 +1125,7 @@ static int logi_dj_recv_query_hidpp_devices(struct dj_receiver_dev *djrcv_dev)
HID_REQ_SET_REPORT); HID_REQ_SET_REPORT);
kfree(hidpp_report); kfree(hidpp_report);
return 0; return retval;
} }
static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
...@@ -1834,6 +1836,9 @@ static const struct hid_device_id logi_dj_receivers[] = { ...@@ -1834,6 +1836,9 @@ static const struct hid_device_id logi_dj_receivers[] = {
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_GAMING), USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_GAMING),
.driver_data = recvr_type_gaming_hidpp}, .driver_data = recvr_type_gaming_hidpp},
{ /* Logitech 27 MHz HID++ 1.0 receiver (0xc513) */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
.driver_data = recvr_type_27mhz},
{ /* Logitech 27 MHz HID++ 1.0 receiver (0xc517) */ { /* Logitech 27 MHz HID++ 1.0 receiver (0xc517) */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
USB_DEVICE_ID_S510_RECEIVER_2), USB_DEVICE_ID_S510_RECEIVER_2),
......
...@@ -2858,7 +2858,7 @@ static u8 *hidpp10_consumer_keys_report_fixup(struct hidpp_device *hidpp, ...@@ -2858,7 +2858,7 @@ static u8 *hidpp10_consumer_keys_report_fixup(struct hidpp_device *hidpp,
u8 *_rdesc, unsigned int *rsize) u8 *_rdesc, unsigned int *rsize)
{ {
/* Note 0 terminated so we can use strnstr to search for this. */ /* Note 0 terminated so we can use strnstr to search for this. */
const char consumer_rdesc_start[] = { static const char consumer_rdesc_start[] = {
0x05, 0x0C, /* USAGE_PAGE (Consumer Devices) */ 0x05, 0x0C, /* USAGE_PAGE (Consumer Devices) */
0x09, 0x01, /* USAGE (Consumer Control) */ 0x09, 0x01, /* USAGE (Consumer Control) */
0xA1, 0x01, /* COLLECTION (Application) */ 0xA1, 0x01, /* COLLECTION (Application) */
......
...@@ -130,6 +130,7 @@ static const struct hid_device_id hid_quirks[] = { ...@@ -130,6 +130,7 @@ static const struct hid_device_id hid_quirks[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4D22), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4D22), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D0F), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D0F), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D65), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4E22), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4E22), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS), HID_QUIRK_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS), HID_QUIRK_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001), HID_QUIRK_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001), HID_QUIRK_NOGET },
......
...@@ -389,6 +389,8 @@ static const struct hid_device_id uclogic_devices[] = { ...@@ -389,6 +389,8 @@ static const struct hid_device_id uclogic_devices[] = {
USB_DEVICE_ID_UGEE_TABLET_G5) }, USB_DEVICE_ID_UGEE_TABLET_G5) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_TABLET_EX07S) }, USB_DEVICE_ID_UGEE_TABLET_EX07S) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540) }, USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
......
...@@ -1001,6 +1001,8 @@ int uclogic_params_init(struct uclogic_params *params, ...@@ -1001,6 +1001,8 @@ int uclogic_params_init(struct uclogic_params *params,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540): USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540):
case VID_PID(USB_VENDOR_ID_UGEE, case VID_PID(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640): USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640):
case VID_PID(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720):
/* If this is the pen interface */ /* If this is the pen interface */
if (bInterfaceNumber == 1) { if (bInterfaceNumber == 1) {
/* Probe v1 pen parameters */ /* Probe v1 pen parameters */
......
...@@ -184,6 +184,7 @@ static void ish_remove(struct pci_dev *pdev) ...@@ -184,6 +184,7 @@ static void ish_remove(struct pci_dev *pdev)
struct ishtp_device *ishtp_dev = pci_get_drvdata(pdev); struct ishtp_device *ishtp_dev = pci_get_drvdata(pdev);
ishtp_bus_remove_all_clients(ishtp_dev, false); ishtp_bus_remove_all_clients(ishtp_dev, false);
pdev->dev_flags &= ~PCI_DEV_FLAGS_NO_D3;
ish_device_disable(ishtp_dev); ish_device_disable(ishtp_dev);
} }
......
...@@ -304,18 +304,23 @@ static void wacom_feature_mapping(struct hid_device *hdev, ...@@ -304,18 +304,23 @@ static void wacom_feature_mapping(struct hid_device *hdev,
wacom_hid_usage_quirk(hdev, field, usage); wacom_hid_usage_quirk(hdev, field, usage);
switch (equivalent_usage) { switch (equivalent_usage) {
case WACOM_HID_WD_TOUCH_RING_SETTING:
wacom->generic_has_leds = true;
break;
case HID_DG_CONTACTMAX: case HID_DG_CONTACTMAX:
/* leave touch_max as is if predefined */ /* leave touch_max as is if predefined */
if (!features->touch_max) { if (!features->touch_max) {
/* read manually */ /* read manually */
data = kzalloc(2, GFP_KERNEL); n = hid_report_len(field->report);
data = hid_alloc_report_buf(field->report, GFP_KERNEL);
if (!data) if (!data)
break; break;
data[0] = field->report->id; data[0] = field->report->id;
ret = wacom_get_report(hdev, HID_FEATURE_REPORT, ret = wacom_get_report(hdev, HID_FEATURE_REPORT,
data, 2, WAC_CMD_RETRIES); data, n, WAC_CMD_RETRIES);
if (ret == 2) { if (ret == n) {
features->touch_max = data[1]; ret = hid_report_raw_event(hdev,
HID_FEATURE_REPORT, data, n, 0);
} else { } else {
features->touch_max = 16; features->touch_max = 16;
hid_warn(hdev, "wacom_feature_mapping: " hid_warn(hdev, "wacom_feature_mapping: "
......
...@@ -1216,7 +1216,8 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom) ...@@ -1216,7 +1216,8 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
unsigned char *data = wacom->data; unsigned char *data = wacom->data;
int i; int i;
if (wacom->features.type == INTUOSP2_BT) { if (wacom->features.type == INTUOSP2_BT ||
wacom->features.type == INTUOSP2S_BT) {
wacom->serial[0] = get_unaligned_le64(&data[99]); wacom->serial[0] = get_unaligned_le64(&data[99]);
wacom->id[0] = get_unaligned_le16(&data[107]); wacom->id[0] = get_unaligned_le16(&data[107]);
pen_frame_len = 14; pen_frame_len = 14;
...@@ -1268,7 +1269,8 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom) ...@@ -1268,7 +1269,8 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
input_report_abs(pen_input, ABS_X, get_unaligned_le16(&frame[1])); input_report_abs(pen_input, ABS_X, get_unaligned_le16(&frame[1]));
input_report_abs(pen_input, ABS_Y, get_unaligned_le16(&frame[3])); input_report_abs(pen_input, ABS_Y, get_unaligned_le16(&frame[3]));
if (wacom->features.type == INTUOSP2_BT) { if (wacom->features.type == INTUOSP2_BT ||
wacom->features.type == INTUOSP2S_BT) {
/* Fix rotation alignment: userspace expects zero at left */ /* Fix rotation alignment: userspace expects zero at left */
int16_t rotation = int16_t rotation =
(int16_t)get_unaligned_le16(&frame[9]); (int16_t)get_unaligned_le16(&frame[9]);
...@@ -1286,7 +1288,6 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom) ...@@ -1286,7 +1288,6 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
get_unaligned_le16(&frame[11])); get_unaligned_le16(&frame[11]));
} }
} }
if (wacom->tool[0]) { if (wacom->tool[0]) {
input_report_abs(pen_input, ABS_PRESSURE, get_unaligned_le16(&frame[5])); input_report_abs(pen_input, ABS_PRESSURE, get_unaligned_le16(&frame[5]));
if (wacom->features.type == INTUOSP2_BT) { if (wacom->features.type == INTUOSP2_BT) {
...@@ -1456,7 +1457,8 @@ static int wacom_intuos_pro2_bt_irq(struct wacom_wac *wacom, size_t len) ...@@ -1456,7 +1457,8 @@ static int wacom_intuos_pro2_bt_irq(struct wacom_wac *wacom, size_t len)
} }
wacom_intuos_pro2_bt_pen(wacom); wacom_intuos_pro2_bt_pen(wacom);
if (wacom->features.type == INTUOSP2_BT) { if (wacom->features.type == INTUOSP2_BT ||
wacom->features.type == INTUOSP2S_BT) {
wacom_intuos_pro2_bt_touch(wacom); wacom_intuos_pro2_bt_touch(wacom);
wacom_intuos_pro2_bt_pad(wacom); wacom_intuos_pro2_bt_pad(wacom);
wacom_intuos_pro2_bt_battery(wacom); wacom_intuos_pro2_bt_battery(wacom);
...@@ -1768,6 +1770,9 @@ int wacom_equivalent_usage(int usage) ...@@ -1768,6 +1770,9 @@ int wacom_equivalent_usage(int usage)
int subpage = (usage & 0xFF00) << 8; int subpage = (usage & 0xFF00) << 8;
int subusage = (usage & 0xFF); int subusage = (usage & 0xFF);
if (usage == WACOM_HID_WT_REPORT_VALID)
return usage;
if (subpage == HID_UP_UNDEFINED) if (subpage == HID_UP_UNDEFINED)
subpage = WACOM_HID_SP_DIGITIZER; subpage = WACOM_HID_SP_DIGITIZER;
...@@ -1926,8 +1931,6 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, ...@@ -1926,8 +1931,6 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
features->device_type |= WACOM_DEVICETYPE_PAD; features->device_type |= WACOM_DEVICETYPE_PAD;
break; break;
case WACOM_HID_WD_BUTTONCENTER: case WACOM_HID_WD_BUTTONCENTER:
wacom->generic_has_leds = true;
/* fall through */
case WACOM_HID_WD_BUTTONHOME: case WACOM_HID_WD_BUTTONHOME:
case WACOM_HID_WD_BUTTONUP: case WACOM_HID_WD_BUTTONUP:
case WACOM_HID_WD_BUTTONDOWN: case WACOM_HID_WD_BUTTONDOWN:
...@@ -2043,12 +2046,16 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field ...@@ -2043,12 +2046,16 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
*/ */
if (hdev->vendor == 0x56a && if (hdev->vendor == 0x56a &&
(hdev->product == 0x34d || hdev->product == 0x34e || /* MobileStudio Pro */ (hdev->product == 0x34d || hdev->product == 0x34e || /* MobileStudio Pro */
hdev->product == 0x357 || hdev->product == 0x358)) { /* Intuos Pro 2 */ hdev->product == 0x357 || hdev->product == 0x358 || /* Intuos Pro 2 */
hdev->product == 0x392 || /* Intuos Pro 2 */
hdev->product == 0x399)) { /* MobileStudio Pro */
value = (field->logical_maximum - value); value = (field->logical_maximum - value);
if (hdev->product == 0x357 || hdev->product == 0x358) if (hdev->product == 0x357 || hdev->product == 0x358 ||
hdev->product == 0x392)
value = wacom_offset_rotation(input, usage, value, 3, 16); value = wacom_offset_rotation(input, usage, value, 3, 16);
else if (hdev->product == 0x34d || hdev->product == 0x34e) else if (hdev->product == 0x34d || hdev->product == 0x34e ||
hdev->product == 0x399)
value = wacom_offset_rotation(input, usage, value, 1, 2); value = wacom_offset_rotation(input, usage, value, 1, 2);
} }
else { else {
...@@ -2119,14 +2126,12 @@ static void wacom_wac_pad_report(struct hid_device *hdev, ...@@ -2119,14 +2126,12 @@ static void wacom_wac_pad_report(struct hid_device *hdev,
bool active = wacom_wac->hid_data.inrange_state != 0; bool active = wacom_wac->hid_data.inrange_state != 0;
/* report prox for expresskey events */ /* report prox for expresskey events */
if ((wacom_equivalent_usage(field->physical) == HID_DG_TABLETFUNCTIONKEY) && if (wacom_wac->hid_data.pad_input_event_flag) {
wacom_wac->hid_data.pad_input_event_flag) {
input_event(input, EV_ABS, ABS_MISC, active ? PAD_DEVICE_ID : 0); input_event(input, EV_ABS, ABS_MISC, active ? PAD_DEVICE_ID : 0);
input_sync(input); input_sync(input);
if (!active) if (!active)
wacom_wac->hid_data.pad_input_event_flag = false; wacom_wac->hid_data.pad_input_event_flag = false;
} }
} }
static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
...@@ -2512,6 +2517,10 @@ static void wacom_wac_finger_event(struct hid_device *hdev, ...@@ -2512,6 +2517,10 @@ static void wacom_wac_finger_event(struct hid_device *hdev,
struct wacom *wacom = hid_get_drvdata(hdev); struct wacom *wacom = hid_get_drvdata(hdev);
struct wacom_wac *wacom_wac = &wacom->wacom_wac; struct wacom_wac *wacom_wac = &wacom->wacom_wac;
unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
struct wacom_features *features = &wacom->wacom_wac.features;
if (wacom_wac->is_invalid_bt_frame)
return;
switch (equivalent_usage) { switch (equivalent_usage) {
case HID_GD_X: case HID_GD_X:
...@@ -2532,9 +2541,14 @@ static void wacom_wac_finger_event(struct hid_device *hdev, ...@@ -2532,9 +2541,14 @@ static void wacom_wac_finger_event(struct hid_device *hdev,
case HID_DG_TIPSWITCH: case HID_DG_TIPSWITCH:
wacom_wac->hid_data.tipswitch = value; wacom_wac->hid_data.tipswitch = value;
break; break;
case WACOM_HID_WT_REPORT_VALID:
wacom_wac->is_invalid_bt_frame = !value;
return;
case HID_DG_CONTACTMAX:
features->touch_max = value;
return;
} }
if (usage->usage_index + 1 == field->report_count) { if (usage->usage_index + 1 == field->report_count) {
if (equivalent_usage == wacom_wac->hid_data.last_slot_field) if (equivalent_usage == wacom_wac->hid_data.last_slot_field)
wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input); wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input);
...@@ -2549,6 +2563,8 @@ static void wacom_wac_finger_pre_report(struct hid_device *hdev, ...@@ -2549,6 +2563,8 @@ static void wacom_wac_finger_pre_report(struct hid_device *hdev,
struct hid_data* hid_data = &wacom_wac->hid_data; struct hid_data* hid_data = &wacom_wac->hid_data;
int i; int i;
wacom_wac->is_invalid_bt_frame = false;
for (i = 0; i < report->maxfield; i++) { for (i = 0; i < report->maxfield; i++) {
struct hid_field *field = report->field[i]; struct hid_field *field = report->field[i];
int j; int j;
...@@ -2569,25 +2585,9 @@ static void wacom_wac_finger_pre_report(struct hid_device *hdev, ...@@ -2569,25 +2585,9 @@ static void wacom_wac_finger_pre_report(struct hid_device *hdev,
case HID_DG_TIPSWITCH: case HID_DG_TIPSWITCH:
hid_data->last_slot_field = equivalent_usage; hid_data->last_slot_field = equivalent_usage;
break; break;
case HID_DG_CONTACTCOUNT:
hid_data->cc_report = report->id;
hid_data->cc_index = i;
hid_data->cc_value_index = j;
break;
} }
} }
} }
if (hid_data->cc_report != 0 &&
hid_data->cc_index >= 0) {
struct hid_field *field = report->field[hid_data->cc_index];
int value = field->value[hid_data->cc_value_index];
if (value)
hid_data->num_expected = value;
}
else {
hid_data->num_expected = wacom_wac->features.touch_max;
}
} }
static void wacom_wac_finger_report(struct hid_device *hdev, static void wacom_wac_finger_report(struct hid_device *hdev,
...@@ -2597,6 +2597,7 @@ static void wacom_wac_finger_report(struct hid_device *hdev, ...@@ -2597,6 +2597,7 @@ static void wacom_wac_finger_report(struct hid_device *hdev,
struct wacom_wac *wacom_wac = &wacom->wacom_wac; struct wacom_wac *wacom_wac = &wacom->wacom_wac;
struct input_dev *input = wacom_wac->touch_input; struct input_dev *input = wacom_wac->touch_input;
unsigned touch_max = wacom_wac->features.touch_max; unsigned touch_max = wacom_wac->features.touch_max;
struct hid_data *hid_data = &wacom_wac->hid_data;
/* If more packets of data are expected, give us a chance to /* If more packets of data are expected, give us a chance to
* process them rather than immediately syncing a partial * process them rather than immediately syncing a partial
...@@ -2610,6 +2611,7 @@ static void wacom_wac_finger_report(struct hid_device *hdev, ...@@ -2610,6 +2611,7 @@ static void wacom_wac_finger_report(struct hid_device *hdev,
input_sync(input); input_sync(input);
wacom_wac->hid_data.num_received = 0; wacom_wac->hid_data.num_received = 0;
hid_data->num_expected = 0;
/* keep touch state for pen event */ /* keep touch state for pen event */
wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(wacom_wac); wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(wacom_wac);
...@@ -2684,12 +2686,73 @@ static void wacom_report_events(struct hid_device *hdev, ...@@ -2684,12 +2686,73 @@ static void wacom_report_events(struct hid_device *hdev,
} }
} }
static void wacom_set_num_expected(struct hid_device *hdev,
struct hid_report *report,
int collection_index,
struct hid_field *field,
int field_index)
{
struct wacom *wacom = hid_get_drvdata(hdev);
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
struct hid_data *hid_data = &wacom_wac->hid_data;
unsigned int original_collection_level =
hdev->collection[collection_index].level;
bool end_collection = false;
int i;
if (hid_data->num_expected)
return;
// find the contact count value for this segment
for (i = field_index; i < report->maxfield && !end_collection; i++) {
struct hid_field *field = report->field[i];
unsigned int field_level =
hdev->collection[field->usage[0].collection_index].level;
unsigned int j;
if (field_level != original_collection_level)
continue;
for (j = 0; j < field->maxusage; j++) {
struct hid_usage *usage = &field->usage[j];
if (usage->collection_index != collection_index) {
end_collection = true;
break;
}
if (wacom_equivalent_usage(usage->hid) == HID_DG_CONTACTCOUNT) {
hid_data->cc_report = report->id;
hid_data->cc_index = i;
hid_data->cc_value_index = j;
if (hid_data->cc_report != 0 &&
hid_data->cc_index >= 0) {
struct hid_field *field =
report->field[hid_data->cc_index];
int value =
field->value[hid_data->cc_value_index];
if (value)
hid_data->num_expected = value;
}
}
}
}
if (hid_data->cc_report == 0 || hid_data->cc_index < 0)
hid_data->num_expected = wacom_wac->features.touch_max;
}
static int wacom_wac_collection(struct hid_device *hdev, struct hid_report *report, static int wacom_wac_collection(struct hid_device *hdev, struct hid_report *report,
int collection_index, struct hid_field *field, int collection_index, struct hid_field *field,
int field_index) int field_index)
{ {
struct wacom *wacom = hid_get_drvdata(hdev); struct wacom *wacom = hid_get_drvdata(hdev);
if (WACOM_FINGER_FIELD(field))
wacom_set_num_expected(hdev, report, collection_index, field,
field_index);
wacom_report_events(hdev, report, collection_index, field_index); wacom_report_events(hdev, report, collection_index, field_index);
/* /*
...@@ -2702,9 +2765,7 @@ static int wacom_wac_collection(struct hid_device *hdev, struct hid_report *repo ...@@ -2702,9 +2765,7 @@ static int wacom_wac_collection(struct hid_device *hdev, struct hid_report *repo
if (report->type != HID_INPUT_REPORT) if (report->type != HID_INPUT_REPORT)
return -1; return -1;
if (WACOM_PAD_FIELD(field) && wacom->wacom_wac.pad_input) if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
wacom_wac_pad_report(hdev, report, field);
else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
wacom_wac_pen_report(hdev, report); wacom_wac_pen_report(hdev, report);
else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input) else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input)
wacom_wac_finger_report(hdev, report); wacom_wac_finger_report(hdev, report);
...@@ -2718,7 +2779,7 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report) ...@@ -2718,7 +2779,7 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
struct wacom_wac *wacom_wac = &wacom->wacom_wac; struct wacom_wac *wacom_wac = &wacom->wacom_wac;
struct hid_field *field; struct hid_field *field;
bool pad_in_hid_field = false, pen_in_hid_field = false, bool pad_in_hid_field = false, pen_in_hid_field = false,
finger_in_hid_field = false; finger_in_hid_field = false, true_pad = false;
int r; int r;
int prev_collection = -1; int prev_collection = -1;
...@@ -2734,6 +2795,8 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report) ...@@ -2734,6 +2795,8 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
pen_in_hid_field = true; pen_in_hid_field = true;
if (WACOM_FINGER_FIELD(field)) if (WACOM_FINGER_FIELD(field))
finger_in_hid_field = true; finger_in_hid_field = true;
if (wacom_equivalent_usage(field->physical) == HID_DG_TABLETFUNCTIONKEY)
true_pad = true;
} }
wacom_wac_battery_pre_report(hdev, report); wacom_wac_battery_pre_report(hdev, report);
...@@ -2757,6 +2820,9 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report) ...@@ -2757,6 +2820,9 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
} }
wacom_wac_battery_report(hdev, report); wacom_wac_battery_report(hdev, report);
if (true_pad && wacom->wacom_wac.pad_input)
wacom_wac_pad_report(hdev, report, field);
} }
static int wacom_bpt_touch(struct wacom_wac *wacom) static int wacom_bpt_touch(struct wacom_wac *wacom)
...@@ -3225,6 +3291,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) ...@@ -3225,6 +3291,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
break; break;
case INTUOSP2_BT: case INTUOSP2_BT:
case INTUOSP2S_BT:
case INTUOSHT3_BT: case INTUOSHT3_BT:
sync = wacom_intuos_pro2_bt_irq(wacom_wac, len); sync = wacom_intuos_pro2_bt_irq(wacom_wac, len);
break; break;
...@@ -3405,7 +3472,8 @@ void wacom_setup_device_quirks(struct wacom *wacom) ...@@ -3405,7 +3472,8 @@ void wacom_setup_device_quirks(struct wacom *wacom)
if (features->type == REMOTE) if (features->type == REMOTE)
features->device_type = WACOM_DEVICETYPE_PAD; features->device_type = WACOM_DEVICETYPE_PAD;
if (features->type == INTUOSP2_BT) { if (features->type == INTUOSP2_BT ||
features->type == INTUOSP2S_BT) {
features->device_type |= WACOM_DEVICETYPE_PEN | features->device_type |= WACOM_DEVICETYPE_PEN |
WACOM_DEVICETYPE_PAD | WACOM_DEVICETYPE_PAD |
WACOM_DEVICETYPE_TOUCH; WACOM_DEVICETYPE_TOUCH;
...@@ -3586,6 +3654,7 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, ...@@ -3586,6 +3654,7 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev,
case INTUOS5S: case INTUOS5S:
case INTUOSPS: case INTUOSPS:
case INTUOSP2_BT: case INTUOSP2_BT:
case INTUOSP2S_BT:
input_set_abs_params(input_dev, ABS_DISTANCE, 0, input_set_abs_params(input_dev, ABS_DISTANCE, 0,
features->distance_max, features->distance_max,
features->distance_fuzz, 0); features->distance_fuzz, 0);
...@@ -3697,6 +3766,7 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev, ...@@ -3697,6 +3766,7 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
switch (features->type) { switch (features->type) {
case INTUOSP2_BT: case INTUOSP2_BT:
case INTUOSP2S_BT:
input_dev->evbit[0] |= BIT_MASK(EV_SW); input_dev->evbit[0] |= BIT_MASK(EV_SW);
__set_bit(SW_MUTE_DEVICE, input_dev->swbit); __set_bit(SW_MUTE_DEVICE, input_dev->swbit);
...@@ -3712,8 +3782,14 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev, ...@@ -3712,8 +3782,14 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
0, 5920, 4, 0); 0, 5920, 4, 0);
} }
else if (wacom_wac->shared->touch->product == 0x393) {
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
0, 6400, 4, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
0, 4000, 4, 0);
}
input_abs_set_res(input_dev, ABS_MT_POSITION_X, 40); input_abs_set_res(input_dev, ABS_MT_POSITION_X, 40);
input_abs_set_res(input_dev, ABS_MT_POSITION_X, 40); input_abs_set_res(input_dev, ABS_MT_POSITION_Y, 40);
/* fall through */ /* fall through */
...@@ -4021,6 +4097,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, ...@@ -4021,6 +4097,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
case INTUOS5S: case INTUOS5S:
case INTUOSPS: case INTUOSPS:
case INTUOSP2_BT: case INTUOSP2_BT:
case INTUOSP2S_BT:
input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
break; break;
...@@ -4598,6 +4675,10 @@ static const struct wacom_features wacom_features_0x37A = ...@@ -4598,6 +4675,10 @@ static const struct wacom_features wacom_features_0x37A =
static const struct wacom_features wacom_features_0x37B = static const struct wacom_features wacom_features_0x37B =
{ "Wacom One by Wacom M", 21600, 13500, 2047, 63, { "Wacom One by Wacom M", 21600, 13500, 2047, 63,
BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x393 =
{ "Wacom Intuos Pro S", 31920, 19950, 8191, 63,
INTUOSP2S_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7,
.touch_max = 10 };
static const struct wacom_features wacom_features_HID_ANY_ID = static const struct wacom_features wacom_features_HID_ANY_ID =
{ "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID }; { "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID };
...@@ -4770,6 +4851,7 @@ const struct hid_device_id wacom_ids[] = { ...@@ -4770,6 +4851,7 @@ const struct hid_device_id wacom_ids[] = {
{ BT_DEVICE_WACOM(0x379) }, { BT_DEVICE_WACOM(0x379) },
{ USB_DEVICE_WACOM(0x37A) }, { USB_DEVICE_WACOM(0x37A) },
{ USB_DEVICE_WACOM(0x37B) }, { USB_DEVICE_WACOM(0x37B) },
{ BT_DEVICE_WACOM(0x393) },
{ USB_DEVICE_WACOM(0x4001) }, { USB_DEVICE_WACOM(0x4001) },
{ USB_DEVICE_WACOM(0x4004) }, { USB_DEVICE_WACOM(0x4004) },
{ USB_DEVICE_WACOM(0x5000) }, { USB_DEVICE_WACOM(0x5000) },
......
...@@ -141,6 +141,7 @@ ...@@ -141,6 +141,7 @@
#define WACOM_HID_WD_OFFSETBOTTOM (WACOM_HID_UP_WACOMDIGITIZER | 0x0d33) #define WACOM_HID_WD_OFFSETBOTTOM (WACOM_HID_UP_WACOMDIGITIZER | 0x0d33)
#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002) #define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
#define WACOM_HID_WD_DIGITIZERINFO (WACOM_HID_UP_WACOMDIGITIZER | 0x1013) #define WACOM_HID_WD_DIGITIZERINFO (WACOM_HID_UP_WACOMDIGITIZER | 0x1013)
#define WACOM_HID_WD_TOUCH_RING_SETTING (WACOM_HID_UP_WACOMDIGITIZER | 0x1032)
#define WACOM_HID_UP_G9 0xff090000 #define WACOM_HID_UP_G9 0xff090000
#define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02) #define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02)
#define WACOM_HID_G9_TOUCHSCREEN (WACOM_HID_UP_G9 | 0x11) #define WACOM_HID_G9_TOUCHSCREEN (WACOM_HID_UP_G9 | 0x11)
...@@ -154,6 +155,7 @@ ...@@ -154,6 +155,7 @@
#define WACOM_HID_WT_SERIALNUMBER (WACOM_HID_UP_WACOMTOUCH | 0x5b) #define WACOM_HID_WT_SERIALNUMBER (WACOM_HID_UP_WACOMTOUCH | 0x5b)
#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_HID_WT_REPORT_VALID (WACOM_HID_UP_WACOMTOUCH | 0x1d0)
#define WACOM_BATTERY_USAGE(f) (((f)->hid == HID_DG_BATTERYSTRENGTH) || \ #define WACOM_BATTERY_USAGE(f) (((f)->hid == HID_DG_BATTERYSTRENGTH) || \
((f)->hid == WACOM_HID_WD_BATTERY_CHARGING) || \ ((f)->hid == WACOM_HID_WD_BATTERY_CHARGING) || \
...@@ -210,6 +212,7 @@ enum { ...@@ -210,6 +212,7 @@ enum {
INTUOSPM, INTUOSPM,
INTUOSPL, INTUOSPL,
INTUOSP2_BT, INTUOSP2_BT,
INTUOSP2S_BT,
INTUOSHT3_BT, INTUOSHT3_BT,
WACOM_21UX2, WACOM_21UX2,
WACOM_22HD, WACOM_22HD,
......
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