History

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

Pull HID updates from Jiri Kosina: - AMD SFH (Sensor Fusion Hub) support (Sandeep Singh) - increase of maximum HID report size to 16KB in order to support some of the modern devices (Dean Camera) - control interface support for hidraw (Dean Camera) - Sony DS4 power and firmware reporting fixes (Roderick Colenbrander) - support for ghlive PS3/WII U dongles (Pascal Giard) * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (27 commits) HID: i2c-hid: add Vero K147 to descriptor override HID: ite: Add support for Acer S1002 keyboard-dock HID: sony: support for ghlive ps3/wii u dongles HID: hidraw: Add additional hidraw input/output report ioctls. HID: Increase HID maximum report size to 16KB HID: elecom: drop stray comment HID: mf: add support for 0079:1846 Mayflash/Dragonrise USB Gamecube Adapter HID: elecom: add support for EX-G M-XGL20DLBK wireless mouse HID: elecom: rewrite report based on model specific parameters HID: wacom: Constify attribute_groups HID: input: Fix fall-through warnings for Clang HID: usbhid: Fix fall-through warnings for Clang HID: logitech-hidpp: Add hid_device_id for V470 bluetooth mouse HID: intel-ish-hid: Remove unnecessary assignment to variable rv HID: sony: Workaround for DS4 dongle hotplug kernel crash. HID: sony: Don't use fw_version/hw_version for sysfs cleanup. HID: sony: Report more accurate DS4 power status. SFH: fix error return check for -ERESTARTSYS HID: SFH: Add documentation HID: hid-input: occasionally report stylus battery even if not changed ...

Linus Torvalds committed 5 years ago

Commit de925e22 parents 62746f9 85a694734 files · +2360 −95Browse files

Unified · Split

34 files
  1. Documentation/hid/amd-sfh-hid.rst +145 −0
  2. Documentation/hid/hidraw.rst +43 −2
  3. Documentation/hid/index.rst +1 −0
  4. MAINTAINERS +8 −0
  5. drivers/hid/Kconfig +3 −0
  6. drivers/hid/Makefile +2 −0
  7. drivers/hid/amd-sfh-hid/Kconfig +18 −0
  8. drivers/hid/amd-sfh-hid/Makefile +13 −0
  9. drivers/hid/amd-sfh-hid/amd_sfh_client.c +246 −0
  10. drivers/hid/amd-sfh-hid/amd_sfh_hid.c +174 −0
  11. drivers/hid/amd-sfh-hid/amd_sfh_hid.h +67 −0
  12. drivers/hid/amd-sfh-hid/amd_sfh_pcie.c +152 −0
  13. drivers/hid/amd-sfh-hid/amd_sfh_pcie.h +79 −0
  14. drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c +224 −0
  15. drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h +107 −0
  16. drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h +645 −0
  17. drivers/hid/hid-asus.c +109 −14
  18. drivers/hid/hid-elecom.c +39 −12
  19. drivers/hid/hid-ids.h +7 −0
  20. drivers/hid/hid-input.c +5 −1
  21. drivers/hid/hid-ite.c +12 −1
  22. drivers/hid/hid-logitech-hidpp.c +2 −0
  23. drivers/hid/hid-mf.c +2 −0
  24. drivers/hid/hid-quirks.c +3 −0
  25. drivers/hid/hid-sony.c +198 −49
  26. drivers/hid/hidraw.c +23 −1
  27. drivers/hid/i2c-hid/i2c-hid-core.c +4 −1
  28. drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c +8 −0
  29. drivers/hid/intel-ish-hid/ishtp-hid.c +2 −4
  30. drivers/hid/usbhid/hid-core.c +2 −0
  31. drivers/hid/wacom_sys.c +8 −8
  32. include/linux/hid.h +2 −1
  33. include/uapi/linux/hidraw.h +6 −0
  34. samples/hidraw/hid-example.c +1 −1
Documentation/hid/amd-sfh-hid.rst+145−0
@@ -0,0 +1,145 @@
1.. SPDX-License-Identifier: GPL-2.0
2
3
4AMD Sensor Fusion Hub
5=====================
6AMD Sensor Fusion Hub (SFH) is part of an SOC starting from Ryzen based platforms.
7The solution is working well on several OEM products. AMD SFH uses HID over PCIe bus.
8In terms of architecture it resembles ISH, however the major difference is all
9the HID reports are generated as part of the kernel driver.
10
111. Block Diagram
12================
13
14::
15
16 ---------------------------------
17 | HID User Space Applications |
18 - -------------------------------
19
20 ---------------------------------------------
21 ---------------------------------
22 | HID Core |
23 ---------------------------------
24
25 ---------------------------------
26 | AMD HID Transport |
27 ---------------------------------
28
29 --------------------------------
30 | AMD HID Client |
31 | with HID Report Generator|
32 --------------------------------
33
34 --------------------------------
35 | AMD MP2 PCIe Driver |
36 --------------------------------
37 OS
38 ---------------------------------------------
39 Hardware + Firmware
40 --------------------------------
41 | SFH MP2 Processor |
42 --------------------------------
43
44
45AMD HID Transport Layer
46-----------------------
47AMD SFH transport is also implemented as a bus. Each client application executing in the AMD MP2 is
48registered as a device on this bus. Here: MP2 which is an ARM core connected to x86 for processing
49sensor data. The layer, which binds each device (AMD SFH HID driver) identifies the device type and
50registers with the hid core. Transport layer attach a constant "struct hid_ll_driver" object with
51each device. Once a device is registered with HID core, the callbacks provided via this struct are
52used by HID core to communicate with the device. AMD HID Transport layer implements the synchronous calls.
53
54AMD HID Client Layer
55--------------------
56This layer is responsible to implement HID request and descriptors. As firmware is OS agnostic, HID
57client layer fills the HID request structure and descriptors. HID client layer is complex as it is
58interface between MP2 PCIe layer and HID. HID client layer initialized the MP2 PCIe layer and holds
59the instance of MP2 layer. It identifies the number of sensors connected using MP2-PCIe layer. Base
60on that allocates the DRAM address for each and every sensor and pass it to MP2-PCIe driver.On
61enumeration of each the sensor, client layer fills the HID Descriptor structure and HID input repor
62structure. HID Feature report structure is optional. The report descriptor structure varies from
63sensor to sensor.
64
65AMD MP2 PCIe layer
66------------------
67MP2 PCIe Layer is responsible for making all transactions with the firmware over PCIe.
68The connection establishment between firmware and PCIe happens here.
69
70The communication between X86 and MP2 is split into three parts.
711. Command transfer via the C2P mailbox registers.
722. Data transfer via DRAM.
733. Supported sensor info via P2C registers.
74
75Commands are sent to MP2 using C2P Mailbox registers. Writing into C2P Message registers generate
76interrupt to MP2. The client layer allocates the physical memory and the same is sent to MP2 via
77the PCI layer. MP2 firmware writes the command output to the access DRAM memory which the client
78layer has allocated. Firmware always writes minimum of 32 bytes into DRAM. So as a protocol driver
79shall allocate minimum of 32 bytes DRAM space.
80
81Enumeration and Probing flow
82----------------------------
83::
84
85 HID AMD AMD AMD -PCIe MP2
86 Core Transport Client layer layer FW
87 | | | | |
88 | | | on Boot Driver Loaded |
89 | | | | |
90 | | | MP2-PCIe Int |
91 | | | | |
92 | | |---Get Number of sensors-> | |
93 | | | Read P2C |
94 | | | Register |
95 | | | | |
96 | | | Loop(for No of Sensors) | |
97 | | |----------------------| | |
98 | | | Create HID Descriptor| | |
99 | | | Create Input report | | |
100 | | | Descriptor Map | | |
101 | | | the MP2 FW Index to | | |
102 | | | HID Index | | |
103 | | | Allocate the DRAM | Enable |
104 | | | address | Sensors |
105 | | |----------------------| | |
106 | | HID transport| | Enable |
107 | |<--Probe------| |---Sensor CMD--> |
108 | | Create the | | |
109 | | HID device | | |
110 | | (MFD) | | |
111 | | by Populating| | |
112 | | the HID | | |
113 | | ll_driver | | |
114 | HID | | | |
115 | add | | | |
116 |Device | | | |
117 |<------------- | | | |
118
119
120Data Flow from Application to the AMD SFH Driver
121------------------------------------------------
122
123::
124
125 | | | | |
126 | | | | |
127 | | | | |
128 | | | | |
129 | | | | |
130 |HID_req | | | |
131 |get_report | | | |
132 |------------->| | | |
133 | | HID_get_input| | |
134 | | report | | |
135 | |------------->|------------------------| | |
136 | | | Read the DRAM data for| | |
137 | | | requested sensor and | | |
138 | | | create the HID input | | |
139 | | | report | | |
140 | | |------------------------| | |
141 | |Data received | | |
142 | | in HID report| | |
143 To |<-------------|<-------------| | |
144 Applications| | | | |
145 <-------| | | | |
Documentation/hid/hidraw.rst+43−2
@@ -123,8 +123,49 @@ HIDIOCGFEATURE(len): · 122 unmodified lines
123This ioctl will request a feature report from the device using the control123This ioctl will request a feature report from the device using the control
124endpoint. The first byte of the supplied buffer should be set to the report124endpoint. The first byte of the supplied buffer should be set to the report
125number of the requested report. For devices which do not use numbered125number of the requested report. For devices which do not use numbered
126reports, set the first byte to 0. The report will be returned starting at126reports, set the first byte to 0. The returned report buffer will contain the
127the first byte of the buffer (ie: the report number is not returned).127report number in the first byte, followed by the report data read from the
128device. For devices which do not use numbered reports, the report data will
129begin at the first byte of the returned buffer.
130
131HIDIOCSINPUT(len):
132 Send an Input Report
133
134This ioctl will send an input report to the device, using the control endpoint.
135In most cases, setting an input HID report on a device is meaningless and has
136no effect, but some devices may choose to use this to set or reset an initial
137state of a report. The format of the buffer issued with this report is identical
138to that of HIDIOCSFEATURE.
139
140HIDIOCGINPUT(len):
141 Get an Input Report
142
143This ioctl will request an input report from the device using the control
144endpoint. This is slower on most devices where a dedicated In endpoint exists
145for regular input reports, but allows the host to request the value of a
146specific report number. Typically, this is used to request the initial states of
147an input report of a device, before an application listens for normal reports via
148the regular device read() interface. The format of the buffer issued with this report
149is identical to that of HIDIOCGFEATURE.
150
151HIDIOCSOUTPUT(len):
152 Send an Output Report
153
154This ioctl will send an output report to the device, using the control endpoint.
155This is slower on most devices where a dedicated Out endpoint exists for regular
156output reports, but is added for completeness. Typically, this is used to set
157the initial states of an output report of a device, before an application sends
158updates via the regular device write() interface. The format of the buffer issued
159with this report is identical to that of HIDIOCSFEATURE.
160
161HIDIOCGOUTPUT(len):
162 Get an Output Report
163
164This ioctl will request an output report from the device using the control
165endpoint. Typically, this is used to retrive the initial state of
166an output report of a device, before an application updates it as necessary either
167via a HIDIOCSOUTPUT request, or the regular device write() interface. The format
168of the buffer issued with this report is identical to that of HIDIOCGFEATURE.
128 169
129Example170Example
130-------171-------
Documentation/hid/index.rst+1−0
@@ -16,3 +16,4 @@ Human Interface Devices (HID) · 15 unmodified lines
16 16
17 hid-alps17 hid-alps
18 intel-ish-hid18 intel-ish-hid
19 amd-sfh-hid
MAINTAINERS+8−0
@@ -956,6 +956,14 @@ S: Supported · 955 unmodified lines
956F: arch/arm64/boot/dts/amd/amd-seattle-xgbe*.dtsi956F: arch/arm64/boot/dts/amd/amd-seattle-xgbe*.dtsi
957F: drivers/net/ethernet/amd/xgbe/957F: drivers/net/ethernet/amd/xgbe/
958 958
959AMD SENSOR FUSION HUB DRIVER
960M: Nehal Shah <nehal-bakulchandra.shah@amd.com>
961M: Sandeep Singh <sandeep.singh@amd.com>
962L: linux-input@vger.kernel.org
963S: Maintained
964F: Documentation/hid/amd-sfh*
965F: drivers/hid/amd-sfh-hid/
966
959AMS AS73211 DRIVER967AMS AS73211 DRIVER
960M: Christian Eggers <ceggers@arri.de>968M: Christian Eggers <ceggers@arri.de>
961L: linux-iio@vger.kernel.org969L: linux-iio@vger.kernel.org
drivers/hid/Kconfig+3−0
@@ -907,6 +907,7 @@ config HID_SONY · 906 unmodified lines
907 * Buzz controllers907 * Buzz controllers
908 * Sony PS3 Blue-ray Disk Remote Control (Bluetooth)908 * Sony PS3 Blue-ray Disk Remote Control (Bluetooth)
909 * Logitech Harmony adapter for Sony Playstation 3 (Bluetooth)909 * Logitech Harmony adapter for Sony Playstation 3 (Bluetooth)
910 * Guitar Hero Live PS3 and Wii U guitar dongles
910 911
911config SONY_FF912config SONY_FF
912 bool "Sony PS2/3/4 accessories force feedback support" 913 bool "Sony PS2/3/4 accessories force feedback support"
@@ -1183,4 +1184,6 @@ source "drivers/hid/i2c-hid/Kconfig" · 270 unmodified lines
1183 1184
1184source "drivers/hid/intel-ish-hid/Kconfig"1185source "drivers/hid/intel-ish-hid/Kconfig"
1185 1186
1187source "drivers/hid/amd-sfh-hid/Kconfig"
1188
1186endmenu1189endmenu
drivers/hid/Makefile+2−0
@@ -142,3 +142,5 @@ obj-$(CONFIG_I2C_HID) += i2c-hid/ · 141 unmodified lines
142 142
143obj-$(CONFIG_INTEL_ISH_HID) += intel-ish-hid/143obj-$(CONFIG_INTEL_ISH_HID) += intel-ish-hid/
144obj-$(INTEL_ISH_FIRMWARE_DOWNLOADER) += intel-ish-hid/144obj-$(INTEL_ISH_FIRMWARE_DOWNLOADER) += intel-ish-hid/
145
146obj-$(CONFIG_AMD_SFH_HID) += amd-sfh-hid/
drivers/hid/amd-sfh-hid/Kconfig+18−0
@@ -0,0 +1,18 @@
1# SPDX-License-Identifier: GPL-2.0-or-later
2menu "AMD SFH HID Support"
3 depends on X86_64 || COMPILE_TEST
4 depends on PCI
5 depends on HID
6
7config AMD_SFH_HID
8 tristate "AMD Sensor Fusion Hub"
9 help
10 If you say yes to this option, support will be included for the
11 AMD Sensor Fusion Hub.
12 This driver will enable sensors functionality on AMD platforms
13 starting from 17h family of RYZEN parts.
14
15 This driver can also be built as a module. If so, the module will
16 be called amd-sfh.
17 Say Y or M here if you want to support AMD SFH. If unsure, say N.
18endmenu
drivers/hid/amd-sfh-hid/Makefile+13−0
@@ -0,0 +1,13 @@
1# SPDX-License-Identifier: GPL-2.0-or-later
2#
3# Makefile - AMD SFH HID drivers
4# Copyright (c) 2019-2020, Advanced Micro Devices, Inc.
5#
6#
7obj-$(CONFIG_AMD_SFH_HID) += amd_sfh.o
8amd_sfh-objs := amd_sfh_hid.o
9amd_sfh-objs += amd_sfh_client.o
10amd_sfh-objs += amd_sfh_pcie.o
11amd_sfh-objs += hid_descriptor/amd_sfh_hid_desc.o
12
13ccflags-y += -I $(srctree)/$(src)/
drivers/hid/amd-sfh-hid/amd_sfh_client.c+246−0
@@ -0,0 +1,246 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * AMD SFH Client Layer
4 * Copyright 2020 Advanced Micro Devices, Inc.
5 * Authors: Nehal Bakulchandra Shah <Nehal-Bakulchandra.Shah@amd.com>
6 * Sandeep Singh <Sandeep.singh@amd.com>
7 */
8
9#include <linux/dma-mapping.h>
10#include <linux/hid.h>
11#include <linux/list.h>
12#include <linux/slab.h>
13#include <linux/workqueue.h>
14#include <linux/errno.h>
15
16#include "hid_descriptor/amd_sfh_hid_desc.h"
17#include "amd_sfh_pcie.h"
18#include "amd_sfh_hid.h"
19
20#define AMD_SFH_IDLE_LOOP 200
21
22struct request_list {
23 struct hid_device *hid;
24 struct list_head list;
25 u8 report_id;
26 u8 sensor_idx;
27 u8 report_type;
28 u8 current_index;
29};
30
31static struct request_list req_list;
32
33void amd_sfh_set_report(struct hid_device *hid, int report_id,
34 int report_type)
35{
36 struct amdtp_hid_data *hid_data = hid->driver_data;
37 struct amdtp_cl_data *cli_data = hid_data->cli_data;
38 int i;
39
40 for (i = 0; i < cli_data->num_hid_devices; i++) {
41 if (cli_data->hid_sensor_hubs[i] == hid) {
42 cli_data->cur_hid_dev = i;
43 break;
44 }
45 }
46 amdtp_hid_wakeup(hid);
47}
48
49int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type)
50{
51 struct amdtp_hid_data *hid_data = hid->driver_data;
52 struct amdtp_cl_data *cli_data = hid_data->cli_data;
53 int i;
54
55 for (i = 0; i < cli_data->num_hid_devices; i++) {
56 if (cli_data->hid_sensor_hubs[i] == hid) {
57 struct request_list *new = kzalloc(sizeof(*new), GFP_KERNEL);
58
59 if (!new)
60 return -ENOMEM;
61
62 new->current_index = i;
63 new->sensor_idx = cli_data->sensor_idx[i];
64 new->hid = hid;
65 new->report_type = report_type;
66 new->report_id = report_id;
67 cli_data->report_id[i] = report_id;
68 cli_data->request_done[i] = false;
69 list_add(&new->list, &req_list.list);
70 break;
71 }
72 }
73 schedule_delayed_work(&cli_data->work, 0);
74 return 0;
75}
76
77static void amd_sfh_work(struct work_struct *work)
78{
79 struct amdtp_cl_data *cli_data = container_of(work, struct amdtp_cl_data, work.work);
80 struct request_list *req_node;
81 u8 current_index, sensor_index;
82 u8 report_id, node_type;
83 u8 report_size = 0;
84
85 req_node = list_last_entry(&req_list.list, struct request_list, list);
86 list_del(&req_node->list);
87 current_index = req_node->current_index;
88 sensor_index = req_node->sensor_idx;
89 report_id = req_node->report_id;
90 node_type = req_node->report_type;
91
92 if (node_type == HID_FEATURE_REPORT) {
93 report_size = get_feature_report(sensor_index, report_id,
94 cli_data->feature_report[current_index]);
95 if (report_size)
96 hid_input_report(cli_data->hid_sensor_hubs[current_index],
97 cli_data->report_type[current_index],
98 cli_data->feature_report[current_index], report_size, 0);
99 else
100 pr_err("AMDSFH: Invalid report size\n");
101
102 } else if (node_type == HID_INPUT_REPORT) {
103 report_size = get_input_report(sensor_index, report_id,
104 cli_data->input_report[current_index],
105 cli_data->sensor_virt_addr[current_index]);
106 if (report_size)
107 hid_input_report(cli_data->hid_sensor_hubs[current_index],
108 cli_data->report_type[current_index],
109 cli_data->input_report[current_index], report_size, 0);
110 else
111 pr_err("AMDSFH: Invalid report size\n");
112 }
113 cli_data->cur_hid_dev = current_index;
114 cli_data->sensor_requested_cnt[current_index] = 0;
115 amdtp_hid_wakeup(cli_data->hid_sensor_hubs[current_index]);
116}
117
118static void amd_sfh_work_buffer(struct work_struct *work)
119{
120 struct amdtp_cl_data *cli_data = container_of(work, struct amdtp_cl_data, work_buffer.work);
121 u8 report_size;
122 int i;
123
124 for (i = 0; i < cli_data->num_hid_devices; i++) {
125 report_size = get_input_report(cli_data->sensor_idx[i], cli_data->report_id[i],
126 cli_data->input_report[i],
127 cli_data->sensor_virt_addr[i]);
128 hid_input_report(cli_data->hid_sensor_hubs[i], HID_INPUT_REPORT,
129 cli_data->input_report[i], report_size, 0);
130 }
131 schedule_delayed_work(&cli_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
132}
133
134int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
135{
136 struct amdtp_cl_data *cl_data = privdata->cl_data;
137 struct amd_mp2_sensor_info info;
138 struct device *dev;
139 u32 feature_report_size;
140 u32 input_report_size;
141 u8 cl_idx;
142 int rc, i;
143
144 dev = &privdata->pdev->dev;
145 cl_data = kzalloc(sizeof(*cl_data), GFP_KERNEL);
146 if (!cl_data)
147 return -ENOMEM;
148
149 cl_data->num_hid_devices = amd_mp2_get_sensor_num(privdata, &cl_data->sensor_idx[0]);
150
151 INIT_DELAYED_WORK(&cl_data->work, amd_sfh_work);
152 INIT_DELAYED_WORK(&cl_data->work_buffer, amd_sfh_work_buffer);
153 INIT_LIST_HEAD(&req_list.list);
154
155 for (i = 0; i < cl_data->num_hid_devices; i++) {
156 cl_data->sensor_virt_addr[i] = dma_alloc_coherent(dev, sizeof(int) * 8,
157 &cl_data->sensor_phys_addr[i],
158 GFP_KERNEL);
159 cl_data->sensor_sts[i] = 0;
160 cl_data->sensor_requested_cnt[i] = 0;
161 cl_data->cur_hid_dev = i;
162 cl_idx = cl_data->sensor_idx[i];
163 cl_data->report_descr_sz[i] = get_descr_sz(cl_idx, descr_size);
164 if (!cl_data->report_descr_sz[i]) {
165 rc = -EINVAL;
166 goto cleanup;
167 }
168 feature_report_size = get_descr_sz(cl_idx, feature_size);
169 if (!feature_report_size) {
170 rc = -EINVAL;
171 goto cleanup;
172 }
173 input_report_size = get_descr_sz(cl_idx, input_size);
174 if (!input_report_size) {
175 rc = -EINVAL;
176 goto cleanup;
177 }
178 cl_data->feature_report[i] = kzalloc(feature_report_size, GFP_KERNEL);
179 if (!cl_data->feature_report[i]) {
180 rc = -ENOMEM;
181 goto cleanup;
182 }
183 cl_data->input_report[i] = kzalloc(input_report_size, GFP_KERNEL);
184 if (!cl_data->input_report[i]) {
185 rc = -ENOMEM;
186 goto cleanup;
187 }
188 info.period = msecs_to_jiffies(AMD_SFH_IDLE_LOOP);
189 info.sensor_idx = cl_idx;
190 info.phys_address = cl_data->sensor_phys_addr[i];
191
192 cl_data->report_descr[i] = kzalloc(cl_data->report_descr_sz[i], GFP_KERNEL);
193 if (!cl_data->report_descr[i]) {
194 rc = -ENOMEM;
195 goto cleanup;
196 }
197 rc = get_report_descriptor(cl_idx, cl_data->report_descr[i]);
198 if (rc)
199 return rc;
200 rc = amdtp_hid_probe(cl_data->cur_hid_dev, cl_data);
201 if (rc)
202 return rc;
203 amd_start_sensor(privdata, info);
204 cl_data->sensor_sts[i] = 1;
205 }
206 privdata->cl_data = cl_data;
207 schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
208 return 0;
209
210cleanup:
211 for (i = 0; i < cl_data->num_hid_devices; i++) {
212 if (cl_data->sensor_virt_addr[i]) {
213 dma_free_coherent(&privdata->pdev->dev, 8 * sizeof(int),
214 cl_data->sensor_virt_addr[i],
215 cl_data->sensor_phys_addr[i]);
216 }
217 kfree(cl_data->feature_report[i]);
218 kfree(cl_data->input_report[i]);
219 kfree(cl_data->report_descr[i]);
220 }
221 kfree(cl_data);
222 return rc;
223}
224
225int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
226{
227 struct amdtp_cl_data *cl_data = privdata->cl_data;
228 int i;
229
230 for (i = 0; i < cl_data->num_hid_devices; i++)
231 amd_stop_sensor(privdata, i);
232
233 cancel_delayed_work_sync(&cl_data->work);
234 cancel_delayed_work_sync(&cl_data->work_buffer);
235 amdtp_hid_remove(cl_data);
236
237 for (i = 0; i < cl_data->num_hid_devices; i++) {
238 if (cl_data->sensor_virt_addr[i]) {
239 dma_free_coherent(&privdata->pdev->dev, 8 * sizeof(int),
240 cl_data->sensor_virt_addr[i],
241 cl_data->sensor_phys_addr[i]);
242 }
243 }
244 kfree(cl_data);
245 return 0;
246}
drivers/hid/amd-sfh-hid/amd_sfh_hid.c+174−0
@@ -0,0 +1,174 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * AMD MP2 Sensors transport driver
4 *
5 * Authors: Nehal Bakulchandra Shah <Nehal-bakulchandra.shah@amd.com>
6 * Sandeep Singh <sandeep.singh@amd.com>
7 */
8#include <linux/hid.h>
9#include <linux/wait.h>
10#include <linux/sched.h>
11
12#include "amd_sfh_hid.h"
13
14#define AMD_SFH_RESPONSE_TIMEOUT 1500
15
16/**
17 * amdtp_hid_parse() - hid-core .parse() callback
18 * @hid: hid device instance
19 *
20 * This function gets called during call to hid_add_device
21 *
22 * Return: 0 on success and non zero on error
23 */
24static int amdtp_hid_parse(struct hid_device *hid)
25{
26 struct amdtp_hid_data *hid_data = hid->driver_data;
27 struct amdtp_cl_data *cli_data = hid_data->cli_data;
28
29 return hid_parse_report(hid, cli_data->report_descr[hid_data->index],
30 cli_data->report_descr_sz[hid_data->index]);
31}
32
33/* Empty callbacks with success return code */
34static int amdtp_hid_start(struct hid_device *hid)
35{
36 return 0;
37}
38
39static void amdtp_hid_stop(struct hid_device *hid)
40{
41}
42
43static int amdtp_hid_open(struct hid_device *hid)
44{
45 return 0;
46}
47
48static void amdtp_hid_close(struct hid_device *hid)
49{
50}
51
52static int amdtp_raw_request(struct hid_device *hdev, u8 reportnum,
53 u8 *buf, size_t len, u8 rtype, int reqtype)
54{
55 return 0;
56}
57
58static void amdtp_hid_request(struct hid_device *hid, struct hid_report *rep, int reqtype)
59{
60 int rc;
61
62 switch (reqtype) {
63 case HID_REQ_GET_REPORT:
64 rc = amd_sfh_get_report(hid, rep->id, rep->type);
65 if (rc)
66 dev_err(&hid->dev, "AMDSFH get report error\n");
67 break;
68 case HID_REQ_SET_REPORT:
69 amd_sfh_set_report(hid, rep->id, reqtype);
70 break;
71 default:
72 break;
73 }
74}
75
76static int amdtp_wait_for_response(struct hid_device *hid)
77{
78 struct amdtp_hid_data *hid_data = hid->driver_data;
79 struct amdtp_cl_data *cli_data = hid_data->cli_data;
80 int i, ret = 0;
81
82 for (i = 0; i < cli_data->num_hid_devices; i++) {
83 if (cli_data->hid_sensor_hubs[i] == hid)
84 break;
85 }
86
87 if (!cli_data->request_done[i])
88 ret = wait_event_interruptible_timeout(hid_data->hid_wait,
89 cli_data->request_done[i],
90 msecs_to_jiffies(AMD_SFH_RESPONSE_TIMEOUT));
91 if (ret == -ERESTARTSYS)
92 return -ERESTARTSYS;
93 else if (ret < 0)
94 return -ETIMEDOUT;
95 else
96 return 0;
97}
98
99void amdtp_hid_wakeup(struct hid_device *hid)
100{
101 struct amdtp_hid_data *hid_data = hid->driver_data;
102 struct amdtp_cl_data *cli_data = hid_data->cli_data;
103
104 cli_data->request_done[cli_data->cur_hid_dev] = true;
105 wake_up_interruptible(&hid_data->hid_wait);
106}
107
108static struct hid_ll_driver amdtp_hid_ll_driver = {
109 .parse = amdtp_hid_parse,
110 .start = amdtp_hid_start,
111 .stop = amdtp_hid_stop,
112 .open = amdtp_hid_open,
113 .close = amdtp_hid_close,
114 .request = amdtp_hid_request,
115 .wait = amdtp_wait_for_response,
116 .raw_request = amdtp_raw_request,
117};
118
119int amdtp_hid_probe(u32 cur_hid_dev, struct amdtp_cl_data *cli_data)
120{
121 struct hid_device *hid;
122 struct amdtp_hid_data *hid_data;
123 int rc;
124
125 hid = hid_allocate_device();
126 if (IS_ERR(hid))
127 return PTR_ERR(hid);
128
129 hid_data = kzalloc(sizeof(*hid_data), GFP_KERNEL);
130 if (!hid_data) {
131 rc = -ENOMEM;
132 goto err_hid_data;
133 }
134
135 hid->ll_driver = &amdtp_hid_ll_driver;
136 hid_data->index = cur_hid_dev;
137 hid_data->cli_data = cli_data;
138 init_waitqueue_head(&hid_data->hid_wait);
139
140 hid->driver_data = hid_data;
141 cli_data->hid_sensor_hubs[cur_hid_dev] = hid;
142 hid->bus = BUS_AMD_AMDTP;
143 hid->vendor = AMD_SFH_HID_VENDOR;
144 hid->product = AMD_SFH_HID_PRODUCT;
145 snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "hid-amdtp",
146 hid->vendor, hid->product);
147
148 rc = hid_add_device(hid);
149 if (rc)
150 goto err_hid_device;
151 return 0;
152
153err_hid_device:
154 kfree(hid_data);
155err_hid_data:
156 hid_destroy_device(hid);
157 return rc;
158}
159
160void amdtp_hid_remove(struct amdtp_cl_data *cli_data)
161{
162 int i;
163
164 for (i = 0; i < cli_data->num_hid_devices; ++i) {
165 kfree(cli_data->feature_report[i]);
166 kfree(cli_data->input_report[i]);
167 kfree(cli_data->report_descr[i]);
168 if (cli_data->hid_sensor_hubs[i]) {
169 kfree(cli_data->hid_sensor_hubs[i]->driver_data);
170 hid_destroy_device(cli_data->hid_sensor_hubs[i]);
171 cli_data->hid_sensor_hubs[i] = NULL;
172 }
173 }
174}
drivers/hid/amd-sfh-hid/amd_sfh_hid.h+67−0
@@ -0,0 +1,67 @@
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * AMD MP2 Sensors transport driver
4 *
5 * Authors: Nehal Bakulchandra Shah <Nehal-bakulchandra.shah@amd.com>
6 * Sandeep Singh <sandeep.singh@amd.com>
7 */
8
9#ifndef AMDSFH_HID_H
10#define AMDSFH_HID_H
11
12#define MAX_HID_DEVICES 4
13#define BUS_AMD_AMDTP 0x20
14#define AMD_SFH_HID_VENDOR 0x1022
15#define AMD_SFH_HID_PRODUCT 0x0001
16
17struct amdtp_cl_data {
18 u8 init_done;
19 u32 cur_hid_dev;
20 u32 hid_dev_count;
21 u32 num_hid_devices;
22 struct device_info *hid_devices;
23 u8 *report_descr[MAX_HID_DEVICES];
24 int report_descr_sz[MAX_HID_DEVICES];
25 struct hid_device *hid_sensor_hubs[MAX_HID_DEVICES];
26 u8 *hid_descr[MAX_HID_DEVICES];
27 int hid_descr_size[MAX_HID_DEVICES];
28 phys_addr_t phys_addr_base;
29 u32 *sensor_virt_addr[MAX_HID_DEVICES];
30 phys_addr_t sensor_phys_addr[MAX_HID_DEVICES];
31 u32 sensor_sts[MAX_HID_DEVICES];
32 u32 sensor_requested_cnt[MAX_HID_DEVICES];
33 u8 report_type[MAX_HID_DEVICES];
34 u8 report_id[MAX_HID_DEVICES];
35 u8 sensor_idx[MAX_HID_DEVICES];
36 u8 *feature_report[MAX_HID_DEVICES];
37 u8 *input_report[MAX_HID_DEVICES];
38 u8 request_done[MAX_HID_DEVICES];
39 struct delayed_work work;
40 struct delayed_work work_buffer;
41};
42
43/**
44 * struct amdtp_hid_data - Per instance HID data
45 * @index: Device index in the order of enumeration
46 * @request_done: Get Feature/Input report complete flag
47 * used during get/set request from hid core
48 * @cli_data: Link to the client instance
49 * @hid_wait: Completion waitq
50 *
51 * Used to tie hid->driver data to driver client instance
52 */
53struct amdtp_hid_data {
54 int index;
55 struct amdtp_cl_data *cli_data;
56 wait_queue_head_t hid_wait;
57};
58
59/* Interface functions between HID LL driver and AMD SFH client */
60void hid_amdtp_set_feature(struct hid_device *hid, char *buf, u32 len, int report_id);
61void hid_amdtp_get_report(struct hid_device *hid, int report_id, int report_type);
62int amdtp_hid_probe(u32 cur_hid_dev, struct amdtp_cl_data *cli_data);
63void amdtp_hid_remove(struct amdtp_cl_data *cli_data);
64int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type);
65void amd_sfh_set_report(struct hid_device *hid, int report_id, int report_type);
66void amdtp_hid_wakeup(struct hid_device *hid);
67#endif
drivers/hid/amd-sfh-hid/amd_sfh_pcie.c+152−0
@@ -0,0 +1,152 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * AMD MP2 PCIe communication driver
4 * Copyright 2020 Advanced Micro Devices, Inc.
5 *
6 * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
7 * Sandeep Singh <Sandeep.singh@amd.com>
8 */
9
10#include <linux/bitops.h>
11#include <linux/delay.h>
12#include <linux/dma-mapping.h>
13#include <linux/interrupt.h>
14#include <linux/io-64-nonatomic-lo-hi.h>
15#include <linux/module.h>
16#include <linux/slab.h>
17
18#include "amd_sfh_pcie.h"
19
20#define DRIVER_NAME "pcie_mp2_amd"
21#define DRIVER_DESC "AMD(R) PCIe MP2 Communication Driver"
22
23#define ACEL_EN BIT(0)
24#define GYRO_EN BIT(1)
25#define MAGNO_EN BIT(2)
26#define ALS_EN BIT(19)
27
28void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
29{
30 union sfh_cmd_param cmd_param;
31 union sfh_cmd_base cmd_base;
32
33 /* fill up command register */
34 memset(&cmd_base, 0, sizeof(cmd_base));
35 cmd_base.s.cmd_id = ENABLE_SENSOR;
36 cmd_base.s.period = info.period;
37 cmd_base.s.sensor_id = info.sensor_idx;
38
39 /* fill up command param register */
40 memset(&cmd_param, 0, sizeof(cmd_param));
41 cmd_param.s.buf_layout = 1;
42 cmd_param.s.buf_length = 16;
43
44 writeq(info.phys_address, privdata->mmio + AMD_C2P_MSG2);
45 writel(cmd_param.ul, privdata->mmio + AMD_C2P_MSG1);
46 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
47}
48
49void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx)
50{
51 union sfh_cmd_base cmd_base;
52
53 /* fill up command register */
54 memset(&cmd_base, 0, sizeof(cmd_base));
55 cmd_base.s.cmd_id = DISABLE_SENSOR;
56 cmd_base.s.period = 0;
57 cmd_base.s.sensor_id = sensor_idx;
58
59 writeq(0x0, privdata->mmio + AMD_C2P_MSG2);
60 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
61}
62
63void amd_stop_all_sensors(struct amd_mp2_dev *privdata)
64{
65 union sfh_cmd_base cmd_base;
66
67 /* fill up command register */
68 memset(&cmd_base, 0, sizeof(cmd_base));
69 cmd_base.s.cmd_id = STOP_ALL_SENSORS;
70 cmd_base.s.period = 0;
71 cmd_base.s.sensor_id = 0;
72
73 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
74}
75
76int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id)
77{
78 int activestatus, num_of_sensors = 0;
79
80 privdata->activecontrolstatus = readl(privdata->mmio + AMD_P2C_MSG3);
81 activestatus = privdata->activecontrolstatus >> 4;
82 if (ACEL_EN & activestatus)
83 sensor_id[num_of_sensors++] = accel_idx;
84
85 if (GYRO_EN & activestatus)
86 sensor_id[num_of_sensors++] = gyro_idx;
87
88 if (MAGNO_EN & activestatus)
89 sensor_id[num_of_sensors++] = mag_idx;
90
91 if (ALS_EN & activestatus)
92 sensor_id[num_of_sensors++] = als_idx;
93
94 return num_of_sensors;
95}
96
97static void amd_mp2_pci_remove(void *privdata)
98{
99 amd_sfh_hid_client_deinit(privdata);
100 amd_stop_all_sensors(privdata);
101}
102
103static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
104{
105 struct amd_mp2_dev *privdata;
106 int rc;
107
108 privdata = devm_kzalloc(&pdev->dev, sizeof(*privdata), GFP_KERNEL);
109 if (!privdata)
110 return -ENOMEM;
111
112 privdata->pdev = pdev;
113 pci_set_drvdata(pdev, privdata);
114 rc = pcim_enable_device(pdev);
115 if (rc)
116 return rc;
117
118 rc = pcim_iomap_regions(pdev, BIT(2), DRIVER_NAME);
119 if (rc)
120 return rc;
121
122 privdata->mmio = pcim_iomap_table(pdev)[2];
123 pci_set_master(pdev);
124 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
125 if (rc) {
126 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
127 return rc;
128 }
129 rc = devm_add_action_or_reset(&pdev->dev, amd_mp2_pci_remove, privdata);
130 if (rc)
131 return rc;
132
133 return amd_sfh_hid_client_init(privdata);
134}
135
136static const struct pci_device_id amd_mp2_pci_tbl[] = {
137 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_MP2) },
138 { }
139};
140MODULE_DEVICE_TABLE(pci, amd_mp2_pci_tbl);
141
142static struct pci_driver amd_mp2_pci_driver = {
143 .name = DRIVER_NAME,
144 .id_table = amd_mp2_pci_tbl,
145 .probe = amd_mp2_pci_probe,
146};
147module_pci_driver(amd_mp2_pci_driver);
148
149MODULE_DESCRIPTION(DRIVER_DESC);
150MODULE_LICENSE("Dual BSD/GPL");
151MODULE_AUTHOR("Shyam Sundar S K <Shyam-sundar.S-k@amd.com>");
152MODULE_AUTHOR("Sandeep Singh <Sandeep.singh@amd.com>");
drivers/hid/amd-sfh-hid/amd_sfh_pcie.h+79−0
@@ -0,0 +1,79 @@
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * AMD MP2 PCIe communication driver
4 * Copyright 2020 Advanced Micro Devices, Inc.
5 * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
6 * Sandeep Singh <Sandeep.singh@amd.com>
7 */
8
9#ifndef PCIE_MP2_AMD_H
10#define PCIE_MP2_AMD_H
11
12#include <linux/pci.h>
13
14#define PCI_DEVICE_ID_AMD_MP2 0x15E4
15
16#define ENABLE_SENSOR 1
17#define DISABLE_SENSOR 2
18#define STOP_ALL_SENSORS 8
19
20/* MP2 C2P Message Registers */
21#define AMD_C2P_MSG0 0x10500
22#define AMD_C2P_MSG1 0x10504
23#define AMD_C2P_MSG2 0x10508
24
25/* MP2 P2C Message Registers */
26#define AMD_P2C_MSG3 0x1068C /* Supported Sensors info */
27
28/* SFH Command register */
29union sfh_cmd_base {
30 u32 ul;
31 struct {
32 u32 cmd_id : 8;
33 u32 sensor_id : 8;
34 u32 period : 16;
35 } s;
36};
37
38union sfh_cmd_param {
39 u32 ul;
40 struct {
41 u32 buf_layout : 2;
42 u32 buf_length : 6;
43 u32 rsvd : 24;
44 } s;
45};
46
47struct sfh_cmd_reg {
48 union sfh_cmd_base cmd_base;
49 union sfh_cmd_param cmd_param;
50 phys_addr_t phys_addr;
51};
52
53enum sensor_idx {
54 accel_idx = 0,
55 gyro_idx = 1,
56 mag_idx = 2,
57 als_idx = 19
58};
59
60struct amd_mp2_dev {
61 struct pci_dev *pdev;
62 struct amdtp_cl_data *cl_data;
63 void __iomem *mmio;
64 u32 activecontrolstatus;
65};
66
67struct amd_mp2_sensor_info {
68 u8 sensor_idx;
69 u32 period;
70 phys_addr_t phys_address;
71};
72
73void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info);
74void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx);
75void amd_stop_all_sensors(struct amd_mp2_dev *privdata);
76int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id);
77int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata);
78int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata);
79#endif
drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c+224−0
@@ -0,0 +1,224 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * AMD SFH Report Descriptor generator
4 * Copyright 2020 Advanced Micro Devices, Inc.
5 * Authors: Nehal Bakulchandra Shah <Nehal-Bakulchandra.Shah@amd.com>
6 * Sandeep Singh <sandeep.singh@amd.com>
7 */
8
9#include <linux/kernel.h>
10#include <linux/string.h>
11#include <linux/slab.h>
12#include "amd_sfh_pcie.h"
13#include "amd_sfh_hid_desc.h"
14#include "amd_sfh_hid_report_desc.h"
15
16#define AMD_SFH_FW_MULTIPLIER (1000)
17#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM 0x41
18#define HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM 0x51
19#define HID_DEFAULT_REPORT_INTERVAL 0x50
20#define HID_DEFAULT_MIN_VALUE 0X7F
21#define HID_DEFAULT_MAX_VALUE 0x80
22#define HID_DEFAULT_SENSITIVITY 0x7F
23#define HID_USAGE_SENSOR_PROPERTY_CONNECTION_TYPE_PC_INTEGRATED_ENUM 0x01
24/* state enums */
25#define HID_USAGE_SENSOR_STATE_READY_ENUM 0x02
26#define HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM 0x05
27#define HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM 0x04
28
29int get_report_descriptor(int sensor_idx, u8 *rep_desc)
30{
31 switch (sensor_idx) {
32 case accel_idx: /* accel */
33 memset(rep_desc, 0, sizeof(accel3_report_descriptor));
34 memcpy(rep_desc, accel3_report_descriptor,
35 sizeof(accel3_report_descriptor));
36 break;
37 case gyro_idx: /* gyro */
38 memset(rep_desc, 0, sizeof(gyro3_report_descriptor));
39 memcpy(rep_desc, gyro3_report_descriptor,
40 sizeof(gyro3_report_descriptor));
41 break;
42 case mag_idx: /* Magnetometer */
43 memset(rep_desc, 0, sizeof(comp3_report_descriptor));
44 memcpy(rep_desc, comp3_report_descriptor,
45 sizeof(comp3_report_descriptor));
46 break;
47 case als_idx: /* ambient light sensor */
48 memset(rep_desc, 0, sizeof(als_report_descriptor));
49 memcpy(rep_desc, als_report_descriptor,
50 sizeof(als_report_descriptor));
51 break;
52 default:
53 break;
54 }
55 return 0;
56}
57
58u32 get_descr_sz(int sensor_idx, int descriptor_name)
59{
60 switch (sensor_idx) {
61 case accel_idx:
62 switch (descriptor_name) {
63 case descr_size:
64 return sizeof(accel3_report_descriptor);
65 case input_size:
66 return sizeof(struct accel3_input_report);
67 case feature_size:
68 return sizeof(struct accel3_feature_report);
69 }
70 break;
71 case gyro_idx:
72 switch (descriptor_name) {
73 case descr_size:
74 return sizeof(gyro3_report_descriptor);
75 case input_size:
76 return sizeof(struct gyro_input_report);
77 case feature_size:
78 return sizeof(struct gyro_feature_report);
79 }
80 break;
81 case mag_idx:
82 switch (descriptor_name) {
83 case descr_size:
84 return sizeof(comp3_report_descriptor);
85 case input_size:
86 return sizeof(struct magno_input_report);
87 case feature_size:
88 return sizeof(struct magno_feature_report);
89 }
90 break;
91 case als_idx:
92 switch (descriptor_name) {
93 case descr_size:
94 return sizeof(als_report_descriptor);
95 case input_size:
96 return sizeof(struct als_input_report);
97 case feature_size:
98 return sizeof(struct als_feature_report);
99 }
100 break;
101 default:
102 break;
103 }
104 return 0;
105}
106
107static void get_common_features(struct common_feature_property *common, int report_id)
108{
109 common->report_id = report_id;
110 common->connection_type = HID_USAGE_SENSOR_PROPERTY_CONNECTION_TYPE_PC_INTEGRATED_ENUM;
111 common->report_state = HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM;
112 common->power_state = HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM;
113 common->sensor_state = HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM;
114 common->report_interval = HID_DEFAULT_REPORT_INTERVAL;
115}
116
117u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report)
118{
119 struct accel3_feature_report acc_feature;
120 struct gyro_feature_report gyro_feature;
121 struct magno_feature_report magno_feature;
122 struct als_feature_report als_feature;
123 u8 report_size = 0;
124
125 if (!feature_report)
126 return report_size;
127
128 switch (sensor_idx) {
129 case accel_idx: /* accel */
130 get_common_features(&acc_feature.common_property, report_id);
131 acc_feature.accel_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
132 acc_feature.accel_sensitivity_min = HID_DEFAULT_MIN_VALUE;
133 acc_feature.accel_sensitivity_max = HID_DEFAULT_MAX_VALUE;
134 memcpy(feature_report, &acc_feature, sizeof(acc_feature));
135 report_size = sizeof(acc_feature);
136 break;
137 case gyro_idx: /* gyro */
138 get_common_features(&gyro_feature.common_property, report_id);
139 gyro_feature.gyro_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
140 gyro_feature.gyro_sensitivity_min = HID_DEFAULT_MIN_VALUE;
141 gyro_feature.gyro_sensitivity_max = HID_DEFAULT_MAX_VALUE;
142 memcpy(feature_report, &gyro_feature, sizeof(gyro_feature));
143 report_size = sizeof(gyro_feature);
144 break;
145 case mag_idx: /* Magnetometer */
146 get_common_features(&magno_feature.common_property, report_id);
147 magno_feature.magno_headingchange_sensitivity = HID_DEFAULT_SENSITIVITY;
148 magno_feature.heading_min = HID_DEFAULT_MIN_VALUE;
149 magno_feature.heading_max = HID_DEFAULT_MAX_VALUE;
150 magno_feature.flux_change_sensitivity = HID_DEFAULT_MIN_VALUE;
151 magno_feature.flux_min = HID_DEFAULT_MIN_VALUE;
152 magno_feature.flux_max = HID_DEFAULT_MAX_VALUE;
153 memcpy(feature_report, &magno_feature, sizeof(magno_feature));
154 report_size = sizeof(magno_feature);
155 break;
156 case als_idx: /* ambient light sensor */
157 get_common_features(&als_feature.common_property, report_id);
158 als_feature.als_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
159 als_feature.als_sensitivity_min = HID_DEFAULT_MIN_VALUE;
160 als_feature.als_sensitivity_max = HID_DEFAULT_MAX_VALUE;
161 memcpy(feature_report, &als_feature, sizeof(als_feature));
162 report_size = sizeof(als_feature);
163 break;
164 default:
165 break;
166 }
167 return report_size;
168}
169
170static void get_common_inputs(struct common_input_property *common, int report_id)
171{
172 common->report_id = report_id;
173 common->sensor_state = HID_USAGE_SENSOR_STATE_READY_ENUM;
174 common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM;
175}
176
177u8 get_input_report(int sensor_idx, int report_id, u8 *input_report, u32 *sensor_virt_addr)
178{
179 struct accel3_input_report acc_input;
180 struct gyro_input_report gyro_input;
181 struct magno_input_report magno_input;
182 struct als_input_report als_input;
183 u8 report_size = 0;
184
185 if (!sensor_virt_addr || !input_report)
186 return report_size;
187
188 switch (sensor_idx) {
189 case accel_idx: /* accel */
190 get_common_inputs(&acc_input.common_property, report_id);
191 acc_input.in_accel_x_value = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
192 acc_input.in_accel_y_value = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
193 acc_input.in_accel_z_value = (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
194 memcpy(input_report, &acc_input, sizeof(acc_input));
195 report_size = sizeof(acc_input);
196 break;
197 case gyro_idx: /* gyro */
198 get_common_inputs(&gyro_input.common_property, report_id);
199 gyro_input.in_angel_x_value = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
200 gyro_input.in_angel_y_value = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
201 gyro_input.in_angel_z_value = (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
202 memcpy(input_report, &gyro_input, sizeof(gyro_input));
203 report_size = sizeof(gyro_input);
204 break;
205 case mag_idx: /* Magnetometer */
206 get_common_inputs(&magno_input.common_property, report_id);
207 magno_input.in_magno_x = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
208 magno_input.in_magno_y = (int)sensor_virt_addr[1] / AMD_SFH_FW_MULTIPLIER;
209 magno_input.in_magno_z = (int)sensor_virt_addr[2] / AMD_SFH_FW_MULTIPLIER;
210 magno_input.in_magno_accuracy = (u16)sensor_virt_addr[3] / AMD_SFH_FW_MULTIPLIER;
211 memcpy(input_report, &magno_input, sizeof(magno_input));
212 report_size = sizeof(magno_input);
213 break;
214 case als_idx: /* Als */
215 get_common_inputs(&als_input.common_property, report_id);
216 als_input.illuminance_value = (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
217 report_size = sizeof(als_input);
218 memcpy(input_report, &als_input, sizeof(als_input));
219 break;
220 default:
221 break;
222 }
223 return report_size;
224}
drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h+107−0
@@ -0,0 +1,107 @@
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * HID report descriptors, structures and routines
4 * Copyright 2020 Advanced Micro Devices, Inc.
5 * Authors: Nehal Bakulchandra Shah <Nehal-bakulchandra.shah@amd.com>
6 * Sandeep Singh <Sandeep.singh@amd.com>
7 */
8
9#ifndef AMD_SFH_HID_DESCRIPTOR_H
10#define AMD_SFH_HID_DESCRIPTOR_H
11
12enum desc_type {
13 /* Report descriptor name */
14 descr_size = 1,
15 input_size,
16 feature_size,
17};
18
19struct common_feature_property {
20 /* common properties */
21 u8 report_id;
22 u8 connection_type;
23 u8 report_state;
24 u8 power_state;
25 u8 sensor_state;
26 u32 report_interval;
27} __packed;
28
29struct common_input_property {
30 /* common properties */
31 u8 report_id;
32 u8 sensor_state;
33 u8 event_type;
34} __packed;
35
36struct accel3_feature_report {
37 struct common_feature_property common_property;
38 /* properties specific to this sensor */
39 u16 accel_change_sesnitivity;
40 s16 accel_sensitivity_max;
41 s16 accel_sensitivity_min;
42} __packed;
43
44struct accel3_input_report {
45 struct common_input_property common_property;
46 /* values specific to this sensor */
47 int in_accel_x_value;
48 int in_accel_y_value;
49 int in_accel_z_value;
50 /* include if required to support the "shake" event */
51 u8 in_accel_shake_detection;
52} __packed;
53
54struct gyro_feature_report {
55 struct common_feature_property common_property;
56 /* properties specific to this sensor */
57 u16 gyro_change_sesnitivity;
58 s16 gyro_sensitivity_max;
59 s16 gyro_sensitivity_min;
60} __packed;
61
62struct gyro_input_report {
63 struct common_input_property common_property;
64 /* values specific to this sensor */
65 int in_angel_x_value;
66 int in_angel_y_value;
67 int in_angel_z_value;
68} __packed;
69
70struct magno_feature_report {
71 struct common_feature_property common_property;
72 /*properties specific to this sensor */
73 u16 magno_headingchange_sensitivity;
74 s16 heading_min;
75 s16 heading_max;
76 u16 flux_change_sensitivity;
77 s16 flux_min;
78 s16 flux_max;
79} __packed;
80
81struct magno_input_report {
82 struct common_input_property common_property;
83 int in_magno_x;
84 int in_magno_y;
85 int in_magno_z;
86 int in_magno_accuracy;
87} __packed;
88
89struct als_feature_report {
90 struct common_feature_property common_property;
91 /* properties specific to this sensor */
92 u16 als_change_sesnitivity;
93 s16 als_sensitivity_max;
94 s16 als_sensitivity_min;
95} __packed;
96
97struct als_input_report {
98 struct common_input_property common_property;
99 /* values specific to this sensor */
100 int illuminance_value;
101} __packed;
102
103int get_report_descriptor(int sensor_idx, u8 rep_desc[]);
104u32 get_descr_sz(int sensor_idx, int descriptor_name);
105u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report);
106u8 get_input_report(int sensor_idx, int report_id, u8 *input_report, u32 *sensor_virt_addr);
107#endif
drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h+645−0
@@ -0,0 +1,645 @@
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * HID descriptor stuructures
4 * Copyright 2020 Advanced Micro Devices, Inc.
5 * Authors: Nehal Bakulchandra Shah <Nehal-bakulchandra.shah@amd.com>
6 * Sandeep Singh <Sandeep.singh@amd.com>
7 */
8
9#ifndef AMD_SFH_HID_REPORT_DESCRIPTOR_H
10#define AMD_SFH_HID_REPORT_DESCRIPTOR_H
11
12// Accelerometer 3D Sensor
13static const u8 accel3_report_descriptor[] = {
140x05, 0x20, /* Usage page */
150x09, 0x73, /* Motion type Accel 3D */
160xA1, 0x00, /* HID Collection (Physical) */
17
18//feature reports(xmit/receive)
190x85, 1, /* HID Report ID */
200x05, 0x20, /* HID usage page sensor */
210x0A, 0x09, 0x03, /* Sensor property and sensor connection type */
220x15, 0, /* HID logical MIN_8(0) */
230x25, 2, /* HID logical MAX_8(2) */
240x75, 8, /* HID report size(8) */
250x95, 1, /* HID report count(1) */
260xA1, 0x02, /* HID collection (logical) */
270x0A, 0x30, 0x08, /* Sensor property connection type intergated sel*/
280x0A, 0x31, 0x08, /* Sensor property connection type attached sel */
290x0A, 0x32, 0x08, /* Sensor property connection type external sel */
300xB1, 0x00, /* HID feature (Data_Arr_Abs) */
310xC0, /* HID end collection */
320x0A, 0x16, 0x03, /* HID usage sensor property reporting state */
330x15, 0, /* HID logical Min_8(0) */
340x25, 5, /* HID logical Max_8(5) */
350x75, 8, /* HID report size(8) */
360x95, 1, /* HID report count(1) */
370xA1, 0x02, /* HID collection(logical) */
380x0A, 0x40, 0x08, /* Sensor property report state no events sel */
390x0A, 0x41, 0x08, /* Sensor property report state all events sel */
400x0A, 0x42, 0x08, /* Sensor property report state threshold events sel */
410x0A, 0x43, 0x08, /* Sensor property report state no events wake sel */
420x0A, 0x44, 0x08, /* Sensor property report state all events wake sel */
430x0A, 0x45, 0x08, /* Sensor property report state threshold events wake sel */
440xB1, 0x00, /* HID feature (Data_Arr_Abs) */
450xC0, /* HID end collection */
460x0A, 0x19, 0x03, /* HID usage sensor property power state */
470x15, 0, /* HID logical Min_8(0) */
480x25, 5, /* HID logical Max_8(5) */
490x75, 8, /* HID report size(8) */
500x95, 1, /* HID report count(1) */
510xA1, 0x02, /* HID collection(logical) */
520x0A, 0x50, 0x08, /* Sensor property power state undefined sel */
530x0A, 0x51, 0x08, /* Sensor property power state D0 full power sel */
540x0A, 0x52, 0x08, /* Sensor property power state D1 low power sel */
550x0A, 0x53, 0x08, /* Sensor property power state D2 standby with wake sel */
560x0A, 0x54, 0x08, /* Sensor property power state D3 sleep with wake sel */
570x0A, 0x55, 0x08, /* Sensor property power state D4 power off sel */
580xB1, 0x00, /* HID feature (Data_Arr_Abs) */
590xC0, /* HID end collection */
600x0A, 0x01, 0x02, /* HID usage sensor state */
610x15, 0, /* HID logical Min_8(0) */
620x25, 6, /* HID logical Max_8(6) */
630x75, 8, /* HID report size(8) */
640x95, 1, /* HID report count(1) */
650xA1, 0x02, /* HID collection(logical) */
660x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */
670x0A, 0x01, 0x08, /* HID usage sensor state ready sel */
680x0A, 0x02, 0x08, /* HID usage sensor state not available sel */
690x0A, 0x03, 0x08, /* HID usage sensor state no data sel */
700x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */
710x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */
720x0A, 0x06, 0x08, /* HID usage sensor state error sel */
730xB1, 0x00, /* HID feature (Data_Arr_Abs) */
740xC0, /* HID end collection */
750x0A, 0x0E, 0x03, /* HID usage sensor property report interval */
760x15, 0, /* HID logical Min_8(0) */
770x27, 0xFF, 0xFF, 0xFF, 0xFF, /* HID logical Max_32 */
78
790x75, 32, /* HID report size(32) */
800x95, 1, /* HID report count(1) */
810x55, 0, /* HID unit exponent(0) */
820xB1, 0x02, /* HID feature (Data_Arr_Abs) */
830x0A, 0x52, 0x14, /* Sensor data motion accel and mod change sensitivity ABS) */
84
850x15, 0, /* HID logical Min_8(0) */
860x26, 0xFF, 0xFF, /* HID logical Max_16(0xFF,0xFF) */
87
880x75, 16, /* HID report size(16) */
890x95, 1, /* HID report count(1) */
900x55, 0x0E, /* HID unit exponent(0x0E) */
910xB1, 0x02, /* HID feature (Data_Arr_Abs) */
920x0A, 0x52, 0x24, /* HID usage sensor data (motion accel and mod max) */
93
940x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */
95
960x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */
97
980x75, 16, /* HID report size(16) */
990x95, 1, /* HID report count(1) */
1000x55, 0x0E, /* HID unit exponent(0x0E) */
1010xB1, 0x02, /* HID feature (Data_Arr_Abs) */
1020x0A, 0x52, 0x34, /* HID usage sensor data (motion accel and mod min) */
103
1040x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */
105
1060x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */
107
1080x75, 16, /* HID report size(16) */
1090x95, 1, /* HID report count(1) */
1100x55, 0x0E, /* HID unit exponent(0x0E) */
1110xB1, 0x02, /* HID feature (Data_Arr_Abs) */
112
113//input report (transmit)
1140x05, 0x20, /* HID usage page sensors */
1150x0A, 0x01, 0x02, /* HID usage sensor state */
1160x15, 0, /* HID logical Min_8(0) */
1170x25, 6, /* HID logical Max_8(6) */
1180x75, 8, /* HID report size(8) */
1190x95, 1, /* HID report count (1) */
1200xA1, 0x02, /* HID end collection (logical) */
1210x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */
1220x0A, 0x01, 0x08, /* HID usage sensor state ready sel */
1230x0A, 0x02, 0x08, /* HID usage sensor state not available sel */
1240x0A, 0x03, 0x08, /* HID usage sensor state no data sel */
1250x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */
1260x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */
1270x0A, 0x06, 0x08, /* HID usage sensor state error sel */
1280X81, 0x00, /* HID Input (Data_Arr_Abs) */
1290xC0, /* HID end collection */
1300x0A, 0x02, 0x02, /* HID usage sensor event */
1310x15, 0, /* HID logical Min_8(0) */
1320x25, 5, /* HID logical Max_8(5) */
1330x75, 8, /* HID report size(8) */
1340x95, 1, /* HID report count (1) */
1350xA1, 0x02, /* HID end collection (logical) */
1360x0A, 0x10, 0x08, /* HID usage sensor event unknown sel */
1370x0A, 0x11, 0x08, /* HID usage sensor event state changed sel */
1380x0A, 0x12, 0x08, /* HID usage sensor event property changed sel */
1390x0A, 0x13, 0x08, /* HID usage sensor event data updated sel */
1400x0A, 0x14, 0x08, /* HID usage sensor event poll response sel */
1410x0A, 0x15, 0x08, /* HID usage sensor event change sensitivity sel */
1420X81, 0x00, /* HID Input (Data_Arr_Abs) */
1430xC0, /* HID end collection */
1440x0A, 0x53, 0x04, /* HID usage sensor data motion Acceleration X axis */
1450x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
146
1470x27, 0xFF, 0xff, 0XFF, 0XFF, /* HID logical Max_32 */
148
1490x75, 32, /* HID report size(32) */
1500x95, 1, /* HID report count (1) */
1510x55, 0x0E, /* HID unit exponent(0x0E) */
1520X81, 0x02, /* HID Input (Data_Arr_Abs) */
1530x0A, 0x54, 0x04, /* HID usage sensor data motion Acceleration Y axis */
1540x17, 0X00, 0X00, 0x01, 0x80, /* HID logical Min_32 */
155
1560x27, 0xFF, 0xFF, 0XFF, 0XFF, /* HID logical Max_32 */
157
1580x75, 32, /* HID report size(32) */
1590x95, 1, /* HID report count (1) */
1600x55, 0x0E, /* HID unit exponent(0x0E) */
1610X81, 0x02, /* HID Input (Data_Arr_Abs) */
1620x0A, 0x55, 0x04, /* HID usage sensor data motion Acceleration Z axis */
1630x17, 0X00, 0X00, 0x01, 0x80, /* HID logical Min_32 */
164
1650x27, 0XFF, 0XFF, 0xFF, 0x7F, /* HID logical Max_32 */
166
1670x75, 32, /* HID report size(32) */
1680x95, 1, /* HID report count (1) */
1690x55, 0x0E, /* HID unit exponent(0x0E) */
1700X81, 0x02, /* HID Input (Data_Arr_Abs) */
171
1720x0A, 0x51, 0x04, /* HID usage sensor data motion state */
1730x15, 0, /* HID logical Min_8(0) False = Still*/
1740x25, 1, /* HID logical Min_8(1) True = In motion */
1750x75, 8, /* HID report size(8) */
1760x95, 1, /* HID report count (1) */
1770X81, 0x02, /* HID Input (Data_Arr_Abs) */
1780xC0 /* HID end collection */
179};
180
181const u8 gyro3_report_descriptor[] = {
1820x05, 0x20, /* Usage page */
1830x09, 0x76, /* Motion type Gyro3D */
1840xA1, 0x00, /* HID Collection (Physical) */
185
1860x85, 2, /* HID Report ID */
1870x05, 0x20, /* HID usage page sensor */
1880x0A, 0x09, 0x03, /* Sensor property and sensor connection type */
1890x15, 0, /* HID logical MIN_8(0) */
1900x25, 2, /* HID logical MAX_8(2) */
1910x75, 8, /* HID report size(8) */
1920x95, 1, /* HID report count(1) */
1930xA1, 0x02, /* HID collection (logical) */
1940x0A, 0x30, 0x08, /* Sensor property connection type intergated sel */
1950x0A, 0x31, 0x08, /* Sensor property connection type attached sel */
1960x0A, 0x32, 0x08, /* Sensor property connection type external sel */
1970xB1, 0x00, /* HID feature (Data_Arr_Abs) */
1980xC0, /* HID end collection */
1990x0A, 0x16, 0x03, /* HID usage sensor property reporting state */
2000x15, 0, /* HID logical Min_8(0) */
2010x25, 5, /* HID logical Max_8(5) */
2020x75, 8, /* HID report size(8) */
2030x95, 1, /* HID report count(1) */
2040xA1, 0x02, /* HID collection(logical) */
2050x0A, 0x40, 0x08, /* Sensor reporting state no events sel */
2060x0A, 0x41, 0x08, /* Sensor reporting state all events sel */
2070x0A, 0x42, 0x08, /* Sensor reporting state threshold events sel */
2080x0A, 0x43, 0x08, /* Sensor reporting state no events wake sel */
2090x0A, 0x44, 0x08, /* Sensor reporting state all events wake sel */
2100x0A, 0x45, 0x08, /* Sensor reporting state threshold events wake sel */
2110xB1, 0x00, /* HID feature (Data_Arr_Abs) */
2120xC0, /* HID end collection */
2130x0A, 0x19, 0x03, /* HID usage sensor property power state */
2140x15, 0, /* HID logical Min_8(0) */
2150x25, 5, /* HID logical Max_8(5) */
2160x75, 8, /* HID report size(8) */
2170x95, 1, /* HID report count(1) */
2180xA1, 0x02, /* HID collection(logical) */
2190x0A, 0x50, 0x08, /* Sensor power state undefined sel */
2200x0A, 0x51, 0x08, /* Sensor power state D0 full power sel */
2210x0A, 0x52, 0x08, /* Sensor power state D1 low power sel */
2220x0A, 0x53, 0x08, /* Sensor power state D2 standby with wake sel */
2230x0A, 0x54, 0x08, /* Sensor power state D3 sleep with wake sel */
2240x0A, 0x55, 0x08, /* Sensor power state D4 power off sel */
2250xB1, 0x00, /* HID feature (Data_Arr_Abs) */
2260xC0, /* HID end collection */
2270x0A, 0x01, 0x02, /* HID usage sensor state */
2280x15, 0, /* HID logical Min_8(0) */
2290x25, 6, /* HID logical Max_8(6) */
2300x75, 8, /* HID report size(8) */
2310x95, 1, /* HID report count(1) */
2320xA1, 0x02, /* HID collection(logical) */
2330x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */
2340x0A, 0x01, 0x08, /* HID usage sensor state ready sel */
2350x0A, 0x02, 0x08, /* HID usage sensor state not available sel */
2360x0A, 0x03, 0x08, /* HID usage sensor state no data sel */
2370x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */
2380x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */
2390x0A, 0x06, 0x08, /* HID usage sensor state error sel */
2400xB1, 0x00, /* HID feature (Data_Arr_Abs) */
2410xC0, /* HID end collection */
2420x0A, 0x0E, 0x03, /* HID usage sensor property report interval */
2430x15, 0, /* HID logical Min_8(0) */
2440x27, 0xFF, 0xFF, 0xFF, 0xFF, /* HID logical Max_32 */
245
2460x75, 32, /* HID report size(32) */
2470x95, 1, /* HID report count(1) */
2480x55, 0, /* HID unit exponent(0) */
2490xB1, 0x02, /* HID feature (Data_Arr_Abs) */
2500x0A, 0x56, 0x14, /* Angular velocity and mod change sensitivity ABS)*/
251
2520x15, 0, /* HID logical Min_8(0) */
2530x26, 0xFF, 0xFF, /* HID logical Max_16(0xFF,0xFF) */
254
2550x75, 16, /* HID report size(16) */
2560x95, 1, /* HID report count(1) */
2570x55, 0x0E, /* HID unit exponent(0x0E) */
2580xB1, 0x02, /* HID feature (Data_Arr_Abs) */
2590x0A, 0x56, 0x24, /* Sensor data (motion angular velocity and mod max) */
260
2610x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */
262
2630x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */
264
2650x75, 16, /* HID report size(16) */
2660x95, 1, /* HID report count(1) */
2670x55, 0x0E, /* HID unit exponent(0x0E) */
2680xB1, 0x02, /* HID feature (Data_Arr_Abs) */
2690x0A, 0x56, 0x34, /* HID usage sensor data (motion accel and mod min) */
270
2710x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */
272
2730x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */
274
2750x75, 16, /* HID report size(16) */
2760x95, 1, /* HID report count(1) */
2770x55, 0x0E, /* HID unit exponent(0x0E) */
2780xB1, 0x02, /* HID feature (Data_Arr_Abs) */
279
280//Input reports(transmit)
2810x05, 0x20, /* HID usage page sensors */
2820x0A, 0x01, 0x02, /* HID usage sensor state */
2830x15, 0, /* HID logical Min_8(0) */
2840x25, 6, /* HID logical Max_8(6) */
2850x75, 8, /* HID report size(8) */
2860x95, 1, /* HID report count (1) */
2870xA1, 0x02, /* HID end collection (logical) */
2880x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */
2890x0A, 0x01, 0x08, /* HID usage sensor state ready sel */
2900x0A, 0x02, 0x08, /* HID usage sensor state not available sel */
2910x0A, 0x03, 0x08, /* HID usage sensor state no data sel */
2920x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */
2930x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */
2940x0A, 0x06, 0x08, /* HID usage sensor state error sel */
2950X81, 0x00, /* HID Input (Data_Arr_Abs) */
2960xC0, /* HID end collection */
2970x0A, 0x02, 0x02, /* HID usage sensor event */
2980x15, 0, /* HID logical Min_8(0) */
2990x25, 5, /* HID logical Max_8(5) */
3000x75, 8, /* HID report size(8) */
3010x95, 1, /* HID report count (1) */
3020xA1, 0x02, /* HID end collection (logical) */
3030x0A, 0x10, 0x08, /* HID usage sensor event unknown sel */
3040x0A, 0x11, 0x08, /* HID usage sensor event state changed sel */
3050x0A, 0x12, 0x08, /* HID usage sensor event property changed sel */
3060x0A, 0x13, 0x08, /* HID usage sensor event data updated sel */
3070x0A, 0x14, 0x08, /* HID usage sensor event poll response sel */
3080x0A, 0x15, 0x08, /* HID usage sensor event change sensitivity sel */
3090X81, 0x00, /* HID Input (Data_Arr_Abs) */
3100xC0, /* HID end collection */
3110x0A, 0x57, 0x04, /* Sensor data motion Angular velocity X axis */
3120x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
313
3140x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
315
3160x75, 32, /* HID report size(32) */
3170x95, 1, /* HID report count (1) */
3180x55, 0x0E, /* HID unit exponent(0x0E) */
3190X81, 0x02, /* HID Input (Data_Arr_Abs) */
3200x0A, 0x58, 0x04, /* Sensor data motion Angular velocity Y axis */
3210x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
322
3230x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
324
3250x75, 32, /* HID report size(32) */
3260x95, 1, /* HID report count (1) */
3270x55, 0x0E, /* HID unit exponent(0x0E) */
3280X81, 0x02, /* HID Input (Data_Arr_Abs) */
3290x0A, 0x59, 0x04, /* Sensor data motion Angular velocity Z axis */
3300x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
331
3320x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
333
3340x75, 32, /* HID report size(32) */
3350x95, 1, /* HID report count (1) */
3360x55, 0x0E, /* HID unit exponent(0x0E) */
3370X81, 0x02, /* HID Input (Data_Arr_Abs) */
338
3390xC0, /* HID end collection */
340};
341
342const u8 comp3_report_descriptor[] = {
3430x05, 0x20, /* Usage page */
3440x09, 0x83, /* Motion type Orientation compass 3D */
3450xA1, 0x00, /* HID Collection (Physical) */
346
3470x85, 3, /* HID Report ID */
3480x05, 0x20, /* HID usage page sensor */
3490x0A, 0x09, 0x03, /* Sensor property and sensor connection type */
3500x15, 0, /* HID logical MIN_8(0) */
3510x25, 2, /* HID logical MAX_8(2) */
3520x75, 8, /* HID report size(8) */
3530x95, 1, /* HID report count(1) */
3540xA1, 0x02, /* HID collection (logical) */
3550x0A, 0x30, 0x08, /* Sensor property connection type intergated sel */
3560x0A, 0x31, 0x08, /* Sensor property connection type attached sel */
3570x0A, 0x32, 0x08, /* Sensor property connection type external sel */
3580xB1, 0x00, /* HID feature (Data_Arr_Abs) */
3590xC0, /* HID end collection */
3600x0A, 0x16, 0x03, /* HID usage sensor property reporting state */
3610x15, 0, /* HID logical Min_8(0) */
3620x25, 5, /* HID logical Max_8(5) */
3630x75, 8, /* HID report size(8) */
3640x95, 1, /* HID report count(1) */
3650xA1, 0x02, /* HID collection(logical) */
3660x0A, 0x40, 0x08, /* Sensor reporting state no events sel */
3670x0A, 0x41, 0x08, /* Sensor reporting state all events sel */
3680x0A, 0x42, 0x08, /* Sensor reporting state threshold events sel */
3690x0A, 0x43, 0x08, /* Sensor reporting state no events wake sel */
3700x0A, 0x44, 0x08, /* Sensor reporting state all events wake sel */
3710x0A, 0x45, 0x08, /* Sensor reporting state threshold events wake sel */
3720xB1, 0x00, /* HID feature (Data_Arr_Abs) */
3730xC0, /* HID end collection */
3740x0A, 0x19, 0x03, /* HID usage sensor property power state */
3750x15, 0, /* HID logical Min_8(0) */
3760x25, 5, /* HID logical Max_8(5) */
3770x75, 8, /* HID report size(8) */
3780x95, 1, /* HID report count(1) */
3790xA1, 0x02, /* HID collection(logical) */
3800x0A, 0x50, 0x08, /* Sensor power state undefined sel */
3810x0A, 0x51, 0x08, /* Sensor power state D0 full power sel */
3820x0A, 0x52, 0x08, /* Sensor power state D1 low power sel */
3830x0A, 0x53, 0x08, /* Sensor power state D2 standby with wake sel */
3840x0A, 0x54, 0x08, /* Sensor power state D3 sleep with wake sel */
3850x0A, 0x55, 0x08, /* Sensor power state D4 power off sel */
3860xB1, 0x00, /* HID feature (Data_Arr_Abs) */
3870xC0, /* HID end collection */
3880x0A, 0x01, 0x02, /* HID usage sensor state */
3890x15, 0, /* HID logical Min_8(0) */
3900x25, 6, /* HID logical Max_8(6) */
3910x75, 8, /* HID report size(8) */
3920x95, 1, /* HID report count(1) */
3930xA1, 0x02, /* HID collection(logical) */
3940x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */
3950x0A, 0x01, 0x08, /* HID usage sensor state ready sel */
3960x0A, 0x02, 0x08, /* HID usage sensor state not available sel */
3970x0A, 0x03, 0x08, /* HID usage sensor state no data sel */
3980x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */
3990x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */
4000x0A, 0x06, 0x08, /* HID usage sensor state error sel */
4010xB1, 0x00, /* HID feature (Data_Arr_Abs) */
4020xC0, /* HID end collection */
4030x0A, 0x0E, 0x03, /* HID usage sensor property report interval */
4040x15, 0, /* HID logical Min_8(0) */
4050x27, 0xFF, 0xFF, 0xFF, 0xFF, /* HID logical Max_32 */
4060x75, 32, /* HID report size(32) */
4070x95, 1, /* HID report count(1) */
4080x55, 0, /* HID unit exponent(0) */
4090xB1, 0x02, /* HID feature (Data_Arr_Abs) */
4100x0A, 0x71, 0x14, /* Orientation and mod change sensitivity ABS)*/
4110x15, 0, /* HID logical Min_8(0) */
4120x26, 0xFF, 0xFF, /* HID logical Max_16(0xFF,0xFF) */
4130x75, 16, /* HID report size(16) */
4140x95, 1, /* HID report count(1) */
4150x55, 0x0E, /* HID unit exponent(0x0E) */
4160xB1, 0x02, /* HID feature (Data_Arr_Abs) */
4170x0A, 0x71, 0x24, /* Sensor data (motion orientation and mod max) */
4180x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */
4190x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */
4200x75, 16, /* HID report size(16) */
4210x95, 1, /* HID report count(1) */
4220x55, 0x0F, /* HID unit exponent(0x0F) */
4230xB1, 0x02, /* HID feature (Data_Arr_Abs) */
4240x0A, 0x71, 0x34, /* Sensor data (motion orientation and mod min) */
4250x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */
4260x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */
4270x75, 16, /* HID report size(16) */
4280x95, 1, /* HID report count(1) */
4290x55, 0x0F, /* HID unit exponent(0x0F) */
4300xB1, 0x02, /* HID feature (Data_Arr_Abs) */
4310x0A, 0x84, 0x14, /* Maganetic flux and change sensitivity ABS) */
4320x15, 0, /* HID logical Min_8(0) */
4330x26, 0xFF, 0xFF, /* HID logical Max_16(0xFF,0xFF) */
4340x75, 16, /* HID report size(16) */
4350x95, 1, /* HID report count(1) */
4360x55, 0x0E, /* HID unit exponent(0x0E) */
4370xB1, 0x02, /* HID feature (Data_Arr_Abs) */
4380x0A, 0x84, 0x24, /* Maganetic flux and mod change sensitivity Max) */
4390x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */
4400x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */
4410x75, 16, /* HID report size(16) */
4420x95, 1, /* HID report count(1) */
4430x55, 0x0F, /* HID unit exponent(0x0F) */
4440xB1, 0x02, /* HID feature (Data_Arr_Abs) */
4450x0A, 0x84, 0x34, /* Maganetic flux and mod change sensitivity Min */
4460x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */
4470x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */
4480x75, 16, /* HID report size(16) */
4490x95, 1, /* HID report count(1) */
4500x55, 0x0F, /* HID unit exponent(0x0F) */
4510xB1, 0x02, /* HID feature (Data_Arr_Abs) */
452
453//Input reports(transmit)
4540x05, 0x20, /* HID usage page sensors */
4550x0A, 0x01, 0x02, /* HID usage sensor state */
4560x15, 0, /* HID logical Min_8(0) */
4570x25, 6, /* HID logical Max_8(6) */
4580x75, 8, /* HID report size(8) */
4590x95, 1, /* HID report count (1) */
4600xA1, 0x02, /* HID end collection (logical) */
4610x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */
4620x0A, 0x01, 0x08, /* HID usage sensor state ready sel */
4630x0A, 0x02, 0x08, /* HID usage sensor state not available sel */
4640x0A, 0x03, 0x08, /* HID usage sensor state no data sel */
4650x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */
4660x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */
4670x0A, 0x06, 0x08, /* HID usage sensor state error sel */
4680X81, 0x00, /* HID Input (Data_Arr_Abs) */
4690xC0, /* HID end collection */
4700x0A, 0x02, 0x02, /* HID usage sensor event */
4710x15, 0, /* HID logical Min_8(0) */
4720x25, 5, /* HID logical Max_8(5) */
4730x75, 8, /* HID report size(8) */
4740x95, 1, /* HID report count (1) */
4750xA1, 0x02, /* HID end collection (logical) */
4760x0A, 0x10, 0x08, /* HID usage sensor event unknown sel */
4770x0A, 0x11, 0x08, /* HID usage sensor event state changed sel */
4780x0A, 0x12, 0x08, /* HID usage sensor event property changed sel */
4790x0A, 0x13, 0x08, /* HID usage sensor event data updated sel */
4800x0A, 0x14, 0x08, /* HID usage sensor event poll response sel */
4810x0A, 0x15, 0x08, /* HID usage sensor event change sensitivity sel */
4820X81, 0x00, /* HID Input (Data_Arr_Abs) */
4830xC0, /* HID end collection */
4840x0A, 0x85, 0x04, /* Sensor data orientation magnetic flux X axis */
4850x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
4860x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
4870x75, 32, /* HID report size(32) */
4880x95, 1, /* HID report count (1) */
4890x55, 0x0D, /* HID unit exponent(0x0D) */
4900X81, 0x02, /* HID Input (Data_Arr_Abs) */
4910x0A, 0x86, 0x04, /* Sensor data orientation magnetic flux Y axis */
4920x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
4930x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
4940x75, 32, /* HID report size(32) */
4950x95, 1, /* HID report count (1) */
4960x55, 0x0D, /* HID unit exponent(0x0D) */
4970X81, 0x02, /* HID Input (Data_Arr_Abs) */
4980x0A, 0x87, 0x04, /* Sensor data orientation magnetic flux Z axis */
4990x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
5000x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
5010x75, 32, /* HID report size(32) */
5020x95, 1, /* HID report count (1) */
5030x55, 0x0D, /* HID unit exponent(0x0D) */
5040X81, 0x02, /* HID Input (Data_Arr_Abs) */
5050x0A, 0x88, 0x04, /* Sensor data orientation magnetometer accuracy */
5060x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
5070x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
5080x75, 32, /* HID report size(32) */
5090x95, 1, /* HID report count (1) */
5100X81, 0x02, /* HID Input (Data_Arr_Abs) */
5110xC0 /* HID end collection */
512};
513
514const u8 als_report_descriptor[] = {
5150x05, 0x20, /* HID usage page sensor */
5160x09, 0x41, /* HID usage sensor type Ambientlight */
5170xA1, 0x00, /* HID Collection (Physical) */
518
519//feature reports(xmit/receive)//
5200x85, 4, /* HID Report ID */
5210x05, 0x20, /* HID usage page sensor */
5220x0A, 0x09, 0x03, /* Sensor property and sensor connection type */
5230x15, 0, /* HID logical MIN_8(0) */
5240x25, 2, /* HID logical MAX_8(2) */
5250x75, 8, /* HID report size(8) */
5260x95, 1, /* HID report count(1) */
5270xA1, 0x02, /* HID collection (logical) */
5280x0A, 0x30, 0x08, /* Sensor property connection type intergated sel */
5290x0A, 0x31, 0x08, /* Sensor property connection type attached sel */
5300x0A, 0x32, 0x08, /* Sensor property connection type external sel */
5310xB1, 0x00, /* HID feature (Data_Arr_Abs) */
5320xC0, /* HID end collection */
5330x0A, 0x16, 0x03, /* HID usage sensor property reporting state */
5340x15, 0, /* HID logical Min_8(0) */
5350x25, 5, /* HID logical Max_8(5) */
5360x75, 8, /* HID report size(8) */
5370x95, 1, /* HID report count(1) */
5380xA1, 0x02, /* HID collection(logical) */
5390x0A, 0x40, 0x08, /* Sensor reporting state no events sel */
5400x0A, 0x41, 0x08, /* Sensor reporting state all events sel */
5410x0A, 0x42, 0x08, /* Sensor reporting state threshold events sel */
5420x0A, 0x43, 0x08, /* Sensor reporting state no events wake sel */
5430x0A, 0x44, 0x08, /* Sensor reporting state all events wake sel */
5440x0A, 0x45, 0x08, /* Sensor reporting state threshold events wake sel */
5450xB1, 0x00, /* HID feature (Data_Arr_Abs) */
5460xC0, /* HID end collection */
5470x0A, 0x19, 0x03, /* HID usage sensor property power state */
5480x15, 0, /* HID logical Min_8(0) */
5490x25, 5, /* HID logical Max_8(5) */
5500x75, 8, /* HID report size(8) */
5510x95, 1, /* HID report count(1) */
5520xA1, 0x02, /* HID collection(logical) */
5530x0A, 0x50, 0x08, /* Sensor power state undefined sel */
5540x0A, 0x51, 0x08, /* Sensor power state D0 full power sel */
5550x0A, 0x52, 0x08, /* Sensor power state D1 low power sel */
5560x0A, 0x53, 0x08, /* Sensor power state D2 standby with wake sel */
5570x0A, 0x54, 0x08, /* Sensor power state D3 sleep with wake sel */
5580x0A, 0x55, 0x08, /* Sensor power state D4 power off sel */
5590xB1, 0x00, /* HID feature (Data_Arr_Abs) */
5600xC0, /* HID end collection */
5610x0A, 0x01, 0x02, /* HID usage sensor state */
5620x15, 0, /* HID logical Min_8(0) */
5630x25, 6, /* HID logical Max_8(6) */
5640x75, 8, /* HID report size(8) */
5650x95, 1, /* HID report count(1) */
5660xA1, 0x02, /* HID collection(logical) */
5670x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */
5680x0A, 0x01, 0x08, /* HID usage sensor state ready sel */
5690x0A, 0x02, 0x08, /* HID usage sensor state not available sel */
5700x0A, 0x03, 0x08, /* HID usage sensor state no data sel */
5710x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */
5720x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */
5730x0A, 0x06, 0x08, /* HID usage sensor state error sel */
5740xB1, 0x00, /* HID feature (Data_Arr_Abs) */
5750xC0, /* HID end collection */
5760x0A, 0x0E, 0x03, /* HID usage sensor property report interval */
5770x15, 0, /* HID logical Min_8(0) */
5780x27, 0xFF, 0xFF, 0xFF, 0xFF, /* HID logical Max_32 */
5790x75, 32, /* HID report size(32) */
5800x95, 1, /* HID report count(1) */
5810x55, 0, /* HID unit exponent(0) */
5820xB1, 0x02, /* HID feature (Data_Arr_Abs) */
5830x0A, 0xD1, 0xE4, /* Light illuminance and sensitivity REL PCT) */
5840x15, 0, /* HID logical Min_8(0) */
5850x26, 0x10, 0x27, /* HID logical Max_16(0x10,0x27) */
5860x75, 16, /* HID report size(16) */
5870x95, 1, /* HID report count(1) */
5880x55, 0x0E, /* HID unit exponent(0x0E) */
5890xB1, 0x02, /* HID feature (Data_Arr_Abs) */
5900x0A, 0xD1, 0x24, /* Sensor data (Light illuminance and mod max) */
5910x15, 0, /* HID logical Min_8(0) */
5920x26, 0xFF, 0xFF, /* HID logical Max_16(0xFF,0xFF) */
5930x75, 16, /* HID report size(16) */
5940x95, 1, /* HID report count(1) */
5950x55, 0x0F, /* HID unit exponent(0x0F) */
5960xB1, 0x02, /* HID feature (Data_Arr_Abs) */
5970x0A, 0xD1, 0x34, /* Sensor data (Light illuminance and mod min) */
5980x15, 0, /* HID logical Min_8(0) */
5990x26, 0xFF, 0xFF, /* HID logical Max_16(0xFF,0xFF) */
6000x75, 16, /* HID report size(16) */
6010x95, 1, /* HID report count(1) */
6020x55, 0x0F, /* HID unit exponent(0x0F) */
6030xB1, 0x02, /* HID feature (Data_Arr_Abs) */
604
605//Input reports (transmit)
6060x05, 0x20, /* HID usage page sensors */
6070x0A, 0x01, 0x02, /* HID usage sensor state */
6080x15, 0, /* HID logical Min_8(0) */
6090x25, 6, /* HID logical Max_8(6) */
6100x75, 8, /* HID report size(8) */
6110x95, 1, /* HID report count (1) */
6120xA1, 0x02, /* HID end collection (logical) */
6130x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */
6140x0A, 0x01, 0x08, /* HID usage sensor state ready sel */
6150x0A, 0x02, 0x08, /* HID usage sensor state not available sel */
6160x0A, 0x03, 0x08, /* HID usage sensor state no data sel */
6170x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */
6180x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */
6190x0A, 0x06, 0x08, /* HID usage sensor state error sel */
6200X81, 0x00, /* HID Input (Data_Arr_Abs) */
6210xC0, /* HID end collection */
6220x0A, 0x02, 0x02, /* HID usage sensor event */
6230x15, 0, /* HID logical Min_8(0) */
6240x25, 5, /* HID logical Max_8(5) */
6250x75, 8, /* HID report size(8) */
6260x95, 1, /* HID report count (1) */
6270xA1, 0x02, /* HID end collection (logical) */
6280x0A, 0x10, 0x08, /* HID usage sensor event unknown sel */
6290x0A, 0x11, 0x08, /* HID usage sensor event state changed sel */
6300x0A, 0x12, 0x08, /* HID usage sensor event property changed sel */
6310x0A, 0x13, 0x08, /* HID usage sensor event data updated sel */
6320x0A, 0x14, 0x08, /* HID usage sensor event poll response sel */
6330x0A, 0x15, 0x08, /* HID usage sensor event change sensitivity sel */
6340X81, 0x00, /* HID Input (Data_Arr_Abs) */
6350xC0, /* HID end collection */
6360x0A, 0xD1, 0x04, /* HID usage sensor data light illuminance */
6370x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
6380x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
6390x55, 0x0F, /* HID unit exponent(0x0F) */
6400x75, 32, /* HID report size(32) */
6410x95, 1, /* HID report count (1) */
6420X81, 0x02, /* HID Input (Data_Arr_Abs) */
6430xC0 /* HID end collection */
644};
645#endif
drivers/hid/hid-asus.c+109−14
@@ -48,6 +48,8 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad"); · 47 unmodified lines
48#define INPUT_REPORT_ID 0x5d48#define INPUT_REPORT_ID 0x5d
49#define FEATURE_KBD_REPORT_ID 0x5a49#define FEATURE_KBD_REPORT_ID 0x5a
50#define FEATURE_KBD_REPORT_SIZE 1650#define FEATURE_KBD_REPORT_SIZE 16
51#define FEATURE_KBD_LED_REPORT_ID1 0x5d
52#define FEATURE_KBD_LED_REPORT_ID2 0x5e
51 53
52#define SUPPORT_KBD_BACKLIGHT BIT(0)54#define SUPPORT_KBD_BACKLIGHT BIT(0)
53 55
@@ -80,6 +82,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad"); · 26 unmodified lines
80#define QUIRK_T101HA_DOCK BIT(9)82#define QUIRK_T101HA_DOCK BIT(9)
81#define QUIRK_T90CHI BIT(10)83#define QUIRK_T90CHI BIT(10)
82#define QUIRK_MEDION_E1239T BIT(11)84#define QUIRK_MEDION_E1239T BIT(11)
85#define QUIRK_ROG_NKEY_KEYBOARD BIT(12)
83 86
84#define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \87#define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \
85 QUIRK_NO_INIT_REPORTS | \88 QUIRK_NO_INIT_REPORTS | \
@@ -332,6 +335,28 @@ static int asus_raw_event(struct hid_device *hdev, · 246 unmodified lines
332 if (drvdata->quirks & QUIRK_MEDION_E1239T)335 if (drvdata->quirks & QUIRK_MEDION_E1239T)
333 return asus_e1239t_event(drvdata, data, size);336 return asus_e1239t_event(drvdata, data, size);
334 337
338 if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD) {
339 /*
340 * Skip these report ID, the device emits a continuous stream associated
341 * with the AURA mode it is in which looks like an 'echo'.
342 */
343 if (report->id == FEATURE_KBD_LED_REPORT_ID1 ||
344 report->id == FEATURE_KBD_LED_REPORT_ID2) {
345 return -1;
346 /* Additional report filtering */
347 } else if (report->id == FEATURE_KBD_REPORT_ID) {
348 /*
349 * G14 and G15 send these codes on some keypresses with no
350 * discernable reason for doing so. We'll filter them out to avoid
351 * unmapped warning messages later.
352 */
353 if (data[1] == 0xea || data[1] == 0xec || data[1] == 0x02 ||
354 data[1] == 0x8a || data[1] == 0x9e) {
355 return -1;
356 }
357 }
358 }
359
335 return 0;360 return 0;
336}361}
337 362
@@ -344,7 +369,11 @@ static int asus_kbd_set_report(struct hid_device *hdev, u8 *buf, size_t buf_size · 6 unmodified lines
344 if (!dmabuf)369 if (!dmabuf)
345 return -ENOMEM;370 return -ENOMEM;
346 371
347 ret = hid_hw_raw_request(hdev, FEATURE_KBD_REPORT_ID, dmabuf,372 /*
373 * The report ID should be set from the incoming buffer due to LED and key
374 * interfaces having different pages
375 */
376 ret = hid_hw_raw_request(hdev, buf[0], dmabuf,
348 buf_size, HID_FEATURE_REPORT,377 buf_size, HID_FEATURE_REPORT,
349 HID_REQ_SET_REPORT);378 HID_REQ_SET_REPORT);
350 kfree(dmabuf);379 kfree(dmabuf);
@@ -397,6 +426,51 @@ static int asus_kbd_get_functions(struct hid_device *hdev, · 46 unmodified lines
397 return ret;426 return ret;
398}427}
399 428
429static int rog_nkey_led_init(struct hid_device *hdev)
430{
431 u8 buf_init_start[] = { FEATURE_KBD_LED_REPORT_ID1, 0xB9 };
432 u8 buf_init2[] = { FEATURE_KBD_LED_REPORT_ID1, 0x41, 0x53, 0x55, 0x53, 0x20,
433 0x54, 0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 };
434 u8 buf_init3[] = { FEATURE_KBD_LED_REPORT_ID1,
435 0x05, 0x20, 0x31, 0x00, 0x08 };
436 int ret;
437
438 hid_info(hdev, "Asus initialise N-KEY Device");
439 /* The first message is an init start */
440 ret = asus_kbd_set_report(hdev, buf_init_start, sizeof(buf_init_start));
441 if (ret < 0) {
442 hid_warn(hdev, "Asus failed to send init start command: %d\n", ret);
443 return ret;
444 }
445 /* Followed by a string */
446 ret = asus_kbd_set_report(hdev, buf_init2, sizeof(buf_init2));
447 if (ret < 0) {
448 hid_warn(hdev, "Asus failed to send init command 1.0: %d\n", ret);
449 return ret;
450 }
451 /* Followed by a string */
452 ret = asus_kbd_set_report(hdev, buf_init3, sizeof(buf_init3));
453 if (ret < 0) {
454 hid_warn(hdev, "Asus failed to send init command 1.1: %d\n", ret);
455 return ret;
456 }
457
458 /* begin second report ID with same data */
459 buf_init2[0] = FEATURE_KBD_LED_REPORT_ID2;
460 buf_init3[0] = FEATURE_KBD_LED_REPORT_ID2;
461
462 ret = asus_kbd_set_report(hdev, buf_init2, sizeof(buf_init2));
463 if (ret < 0) {
464 hid_warn(hdev, "Asus failed to send init command 2.0: %d\n", ret);
465 return ret;
466 }
467 ret = asus_kbd_set_report(hdev, buf_init3, sizeof(buf_init3));
468 if (ret < 0)
469 hid_warn(hdev, "Asus failed to send init command 2.1: %d\n", ret);
470
471 return ret;
472}
473
400static void asus_kbd_backlight_set(struct led_classdev *led_cdev,474static void asus_kbd_backlight_set(struct led_classdev *led_cdev,
401 enum led_brightness brightness)475 enum led_brightness brightness)
402{476{
@@ -460,19 +534,25 @@ static int asus_kbd_register_leds(struct hid_device *hdev) · 57 unmodified lines
460 unsigned char kbd_func;534 unsigned char kbd_func;
461 int ret;535 int ret;
462 536
463 /* Initialize keyboard */537 if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD) {
464 ret = asus_kbd_init(hdev);538 ret = rog_nkey_led_init(hdev);
465 if (ret < 0)539 if (ret < 0)
466 return ret;540 return ret;
541 } else {
542 /* Initialize keyboard */
543 ret = asus_kbd_init(hdev);
544 if (ret < 0)
545 return ret;
467 546
468 /* Get keyboard functions */547 /* Get keyboard functions */
469 ret = asus_kbd_get_functions(hdev, &kbd_func);548 ret = asus_kbd_get_functions(hdev, &kbd_func);
470 if (ret < 0)549 if (ret < 0)
471 return ret;550 return ret;
472 551
473 /* Check for backlight support */552 /* Check for backlight support */
474 if (!(kbd_func & SUPPORT_KBD_BACKLIGHT))553 if (!(kbd_func & SUPPORT_KBD_BACKLIGHT))
475 return -ENODEV;554 return -ENODEV;
555 }
476 556
477 drvdata->kbd_backlight = devm_kzalloc(&hdev->dev,557 drvdata->kbd_backlight = devm_kzalloc(&hdev->dev,
478 sizeof(struct asus_kbd_leds),558 sizeof(struct asus_kbd_leds),
@@ -751,8 +831,8 @@ static int asus_input_mapping(struct hid_device *hdev, · 272 unmodified lines
751 usage->hid == (HID_UP_GENDEVCTRLS | 0x0026)))831 usage->hid == (HID_UP_GENDEVCTRLS | 0x0026)))
752 return -1;832 return -1;
753 833
754 /* ASUS-specific keyboard hotkeys */834 /* ASUS-specific keyboard hotkeys and led backlight */
755 if ((usage->hid & HID_USAGE_PAGE) == 0xff310000) {835 if ((usage->hid & HID_USAGE_PAGE) == HID_UP_ASUSVENDOR) {
756 switch (usage->hid & HID_USAGE) {836 switch (usage->hid & HID_USAGE) {
757 case 0x10: asus_map_key_clear(KEY_BRIGHTNESSDOWN); break;837 case 0x10: asus_map_key_clear(KEY_BRIGHTNESSDOWN); break;
758 case 0x20: asus_map_key_clear(KEY_BRIGHTNESSUP); break;838 case 0x20: asus_map_key_clear(KEY_BRIGHTNESSUP); break;
@@ -780,6 +860,18 @@ static int asus_input_mapping(struct hid_device *hdev, · 21 unmodified lines
780 /* Fn+F5 "fan" symbol on FX503VD */860 /* Fn+F5 "fan" symbol on FX503VD */
781 case 0x99: asus_map_key_clear(KEY_PROG4); break;861 case 0x99: asus_map_key_clear(KEY_PROG4); break;
782 862
863 /* Fn+F5 "fan" symbol on N-Key keyboard */
864 case 0xae: asus_map_key_clear(KEY_PROG4); break;
865
866 /* Fn+Ret "Calc" symbol on N-Key keyboard */
867 case 0x92: asus_map_key_clear(KEY_CALC); break;
868
869 /* Fn+Left Aura mode previous on N-Key keyboard */
870 case 0xb2: asus_map_key_clear(KEY_PROG2); break;
871
872 /* Fn+Right Aura mode next on N-Key keyboard */
873 case 0xb3: asus_map_key_clear(KEY_PROG3); break;
874
783 default:875 default:
784 /* ASUS lazily declares 256 usages, ignore the rest,876 /* ASUS lazily declares 256 usages, ignore the rest,
785 * as some make the keyboard appear as a pointer device. */877 * as some make the keyboard appear as a pointer device. */
@@ -1126,6 +1218,9 @@ static const struct hid_device_id asus_devices[] = { · 340 unmodified lines
1126 { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,1218 { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
1127 USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD),1219 USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD),
1128 QUIRK_USE_KBD_BACKLIGHT },1220 QUIRK_USE_KBD_BACKLIGHT },
1221 { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
1222 USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD),
1223 QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD },
1129 { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,1224 { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
1130 USB_DEVICE_ID_ASUSTEK_T100TA_KEYBOARD),1225 USB_DEVICE_ID_ASUSTEK_T100TA_KEYBOARD),
1131 QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },1226 QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },
drivers/hid/hid-elecom.c+39−12
@@ -11,6 +11,7 @@ · 10 unmodified lines
11 * Copyright (c) 2017 Diego Elio Pettenò <flameeyes@flameeyes.eu>11 * Copyright (c) 2017 Diego Elio Pettenò <flameeyes@flameeyes.eu>
12 * Copyright (c) 2017 Alex Manoussakis <amanou@gnu.org>12 * Copyright (c) 2017 Alex Manoussakis <amanou@gnu.org>
13 * Copyright (c) 2017 Tomasz Kramkowski <tk@the-tk.com>13 * Copyright (c) 2017 Tomasz Kramkowski <tk@the-tk.com>
14 * Copyright (c) 2020 YOSHIOKA Takuma <lo48576@hard-wi.red>
14 */15 */
15 16
16/*17/*
@@ -29,25 +30,26 @@ · 12 unmodified lines
29 * report descriptor but it does not appear that these enable software to30 * report descriptor but it does not appear that these enable software to
30 * control what the extra buttons map to. The only simple and straightforward31 * control what the extra buttons map to. The only simple and straightforward
31 * solution seems to involve fixing up the report descriptor.32 * solution seems to involve fixing up the report descriptor.
32 *
33 * Report descriptor format:
34 * Positions 13, 15, 21 and 31 store the button bit count, button usage minimum,
35 * button usage maximum and padding bit count respectively.
36 */33 */
37#define MOUSE_BUTTONS_MAX 834#define MOUSE_BUTTONS_MAX 8
38static void mouse_button_fixup(struct hid_device *hdev,35static void mouse_button_fixup(struct hid_device *hdev,
39 __u8 *rdesc, unsigned int rsize,36 __u8 *rdesc, unsigned int rsize,
37 unsigned int button_bit_count,
38 unsigned int padding_bit,
39 unsigned int button_report_size,
40 unsigned int button_usage_maximum,
40 int nbuttons)41 int nbuttons)
41{42{
42 if (rsize < 32 || rdesc[12] != 0x95 ||43 if (rsize < 32 || rdesc[button_bit_count] != 0x95 ||
43 rdesc[14] != 0x75 || rdesc[15] != 0x01 ||44 rdesc[button_report_size] != 0x75 ||
44 rdesc[20] != 0x29 || rdesc[30] != 0x75)45 rdesc[button_report_size + 1] != 0x01 ||
46 rdesc[button_usage_maximum] != 0x29 || rdesc[padding_bit] != 0x75)
45 return;47 return;
46 hid_info(hdev, "Fixing up Elecom mouse button count\n");48 hid_info(hdev, "Fixing up Elecom mouse button count\n");
47 nbuttons = clamp(nbuttons, 0, MOUSE_BUTTONS_MAX);49 nbuttons = clamp(nbuttons, 0, MOUSE_BUTTONS_MAX);
48 rdesc[13] = nbuttons;50 rdesc[button_bit_count + 1] = nbuttons;
49 rdesc[21] = nbuttons;51 rdesc[button_usage_maximum + 1] = nbuttons;
50 rdesc[31] = MOUSE_BUTTONS_MAX - nbuttons;52 rdesc[padding_bit + 1] = MOUSE_BUTTONS_MAX - nbuttons;
51}53}
52 54
53static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,55static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
@@ -62,16 +64,40 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, · 8 unmodified lines
62 rdesc[47] = 0x00;64 rdesc[47] = 0x00;
63 }65 }
64 break;66 break;
67 case USB_DEVICE_ID_ELECOM_M_XGL20DLBK:
68 /*
69 * Report descriptor format:
70 * 20: button bit count
71 * 28: padding bit count
72 * 22: button report size
73 * 14: button usage maximum
74 */
75 mouse_button_fixup(hdev, rdesc, *rsize, 20, 28, 22, 14, 8);
76 break;
65 case USB_DEVICE_ID_ELECOM_M_XT3URBK:77 case USB_DEVICE_ID_ELECOM_M_XT3URBK:
66 case USB_DEVICE_ID_ELECOM_M_XT3DRBK:78 case USB_DEVICE_ID_ELECOM_M_XT3DRBK:
67 case USB_DEVICE_ID_ELECOM_M_XT4DRBK:79 case USB_DEVICE_ID_ELECOM_M_XT4DRBK:
68 mouse_button_fixup(hdev, rdesc, *rsize, 6);80 /*
81 * Report descriptor format:
82 * 12: button bit count
83 * 30: padding bit count
84 * 14: button report size
85 * 20: button usage maximum
86 */
87 mouse_button_fixup(hdev, rdesc, *rsize, 12, 30, 14, 20, 6);
69 break;88 break;
70 case USB_DEVICE_ID_ELECOM_M_DT1URBK:89 case USB_DEVICE_ID_ELECOM_M_DT1URBK:
71 case USB_DEVICE_ID_ELECOM_M_DT1DRBK:90 case USB_DEVICE_ID_ELECOM_M_DT1DRBK:
72 case USB_DEVICE_ID_ELECOM_M_HT1URBK:91 case USB_DEVICE_ID_ELECOM_M_HT1URBK:
73 case USB_DEVICE_ID_ELECOM_M_HT1DRBK:92 case USB_DEVICE_ID_ELECOM_M_HT1DRBK:
74 mouse_button_fixup(hdev, rdesc, *rsize, 8);93 /*
94 * Report descriptor format:
95 * 12: button bit count
96 * 30: padding bit count
97 * 14: button report size
98 * 20: button usage maximum
99 */
100 mouse_button_fixup(hdev, rdesc, *rsize, 12, 30, 14, 20, 8);
75 break;101 break;
76 }102 }
77 return rdesc;103 return rdesc;
@@ -79,6 +105,7 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, · 1 unmodified line
79 105
80static const struct hid_device_id elecom_devices[] = {106static const struct hid_device_id elecom_devices[] = {
81 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },107 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
108 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XGL20DLBK) },
82 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK) },109 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK) },
83 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK) },110 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK) },
84 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) },111 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) },
drivers/hid/hid-ids.h+7−0
@@ -190,6 +190,7 @@ · 189 unmodified lines
190#define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1 0x1854190#define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1 0x1854
191#define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2 0x1837191#define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2 0x1837
192#define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3 0x1822192#define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3 0x1822
193#define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD 0x1866
193#define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869194#define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869
194 195
195#define USB_VENDOR_ID_ATEN 0x0557196#define USB_VENDOR_ID_ATEN 0x0557
@@ -359,6 +360,7 @@ · 163 unmodified lines
359#define USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR 0x1803360#define USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR 0x1803
360#define USB_DEVICE_ID_DRAGONRISE_GAMECUBE1 0x1843361#define USB_DEVICE_ID_DRAGONRISE_GAMECUBE1 0x1843
361#define USB_DEVICE_ID_DRAGONRISE_GAMECUBE2 0x1844362#define USB_DEVICE_ID_DRAGONRISE_GAMECUBE2 0x1844
363#define USB_DEVICE_ID_DRAGONRISE_GAMECUBE3 0x1846
362 364
363#define USB_VENDOR_ID_DWAV 0x0eef365#define USB_VENDOR_ID_DWAV 0x0eef
364#define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001366#define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001
@@ -390,6 +392,7 @@ · 25 unmodified lines
390 392
391#define USB_VENDOR_ID_ELECOM 0x056e393#define USB_VENDOR_ID_ELECOM 0x056e
392#define USB_DEVICE_ID_ELECOM_BM084 0x0061394#define USB_DEVICE_ID_ELECOM_BM084 0x0061
395#define USB_DEVICE_ID_ELECOM_M_XGL20DLBK 0x00e6
393#define USB_DEVICE_ID_ELECOM_M_XT3URBK 0x00fb396#define USB_DEVICE_ID_ELECOM_M_XT3URBK 0x00fb
394#define USB_DEVICE_ID_ELECOM_M_XT3DRBK 0x00fc397#define USB_DEVICE_ID_ELECOM_M_XT3DRBK 0x00fc
395#define USB_DEVICE_ID_ELECOM_M_XT4DRBK 0x00fd398#define USB_DEVICE_ID_ELECOM_M_XT4DRBK 0x00fd
@@ -1074,6 +1077,9 @@ · 678 unmodified lines
1074#define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x00021077#define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002
1075#define USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER 0x10001078#define USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER 0x1000
1076 1079
1080#define USB_VENDOR_ID_SONY_GHLIVE 0x12ba
1081#define USB_DEVICE_ID_SONY_PS3WIIU_GHLIVE_DONGLE 0x074b
1082
1077#define USB_VENDOR_ID_SINO_LITE 0x13451083#define USB_VENDOR_ID_SINO_LITE 0x1345
1078#define USB_DEVICE_ID_SINO_LITE_CONTROLLER 0x30081084#define USB_DEVICE_ID_SINO_LITE_CONTROLLER 0x3008
1079 1085
@@ -1133,6 +1139,7 @@ · 53 unmodified lines
1133#define USB_DEVICE_ID_SYNAPTICS_DELL_K12A 0x28191139#define USB_DEVICE_ID_SYNAPTICS_DELL_K12A 0x2819
1134#define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012 0x29681140#define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012 0x2968
1135#define USB_DEVICE_ID_SYNAPTICS_TP_V103 0x57101141#define USB_DEVICE_ID_SYNAPTICS_TP_V103 0x5710
1142#define USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1002 0x73f4
1136#define USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1003 0x73f51143#define USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1003 0x73f5
1137#define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5 0x81a71144#define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5 0x81a7
1138 1145
drivers/hid/hid-input.c+5−1
@@ -537,9 +537,12 @@ static void hidinput_update_battery(struct hid_device *dev, int value) · 536 unmodified lines
537 capacity = hidinput_scale_battery_capacity(dev, value);537 capacity = hidinput_scale_battery_capacity(dev, value);
538 538
539 if (dev->battery_status != HID_BATTERY_REPORTED ||539 if (dev->battery_status != HID_BATTERY_REPORTED ||
540 capacity != dev->battery_capacity) {540 capacity != dev->battery_capacity ||
541 ktime_after(ktime_get_coarse(), dev->battery_ratelimit_time)) {
541 dev->battery_capacity = capacity;542 dev->battery_capacity = capacity;
542 dev->battery_status = HID_BATTERY_REPORTED;543 dev->battery_status = HID_BATTERY_REPORTED;
544 dev->battery_ratelimit_time =
545 ktime_add_ms(ktime_get_coarse(), 30 * 1000);
543 power_supply_changed(dev->battery);546 power_supply_changed(dev->battery);
544 }547 }
545}548}
@@ -746,6 +749,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel · 200 unmodified lines
746 field->flags |= HID_MAIN_ITEM_RELATIVE;749 field->flags |= HID_MAIN_ITEM_RELATIVE;
747 break;750 break;
748 }751 }
752 goto unknown;
749 753
750 default: goto unknown;754 default: goto unknown;
751 }755 }
drivers/hid/hid-ite.c+12−1
@@ -18,10 +18,16 @@ static __u8 *ite_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int · 17 unmodified lines
18 unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);18 unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
19 19
20 if (quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) {20 if (quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) {
21 /* For Acer Aspire Switch 10 SW5-012 keyboard-dock */
21 if (*rsize == 188 && rdesc[162] == 0x81 && rdesc[163] == 0x02) {22 if (*rsize == 188 && rdesc[162] == 0x81 && rdesc[163] == 0x02) {
22 hid_info(hdev, "Fixing up ITE keyboard report descriptor\n");23 hid_info(hdev, "Fixing up Acer Sw5-012 ITE keyboard report descriptor\n");
23 rdesc[163] = HID_MAIN_ITEM_RELATIVE;24 rdesc[163] = HID_MAIN_ITEM_RELATIVE;
24 }25 }
26 /* For Acer One S1002 keyboard-dock */
27 if (*rsize == 188 && rdesc[185] == 0x81 && rdesc[186] == 0x02) {
28 hid_info(hdev, "Fixing up Acer S1002 ITE keyboard report descriptor\n");
29 rdesc[186] = HID_MAIN_ITEM_RELATIVE;
30 }
25 }31 }
26 32
27 return rdesc;33 return rdesc;
@@ -101,6 +107,11 @@ static const struct hid_device_id ite_devices[] = { · 73 unmodified lines
101 USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012),107 USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012),
102 .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },108 .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },
103 /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */109 /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */
110 { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
111 USB_VENDOR_ID_SYNAPTICS,
112 USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1002),
113 .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },
114 /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */
104 { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,115 { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
105 USB_VENDOR_ID_SYNAPTICS,116 USB_VENDOR_ID_SYNAPTICS,
106 USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1003) },117 USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1003) },
drivers/hid/hid-logitech-hidpp.c+2−0
@@ -4048,6 +4048,8 @@ static const struct hid_device_id hidpp_devices[] = { · 4047 unmodified lines
4048 { /* MX5500 keyboard over Bluetooth */4048 { /* MX5500 keyboard over Bluetooth */
4049 HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb30b),4049 HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb30b),
4050 .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },4050 .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
4051 { /* M-RCQ142 V470 Cordless Laser Mouse over Bluetooth */
4052 HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb008) },
4051 { /* MX Master mouse over Bluetooth */4053 { /* MX Master mouse over Bluetooth */
4052 HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb012),4054 HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb012),
4053 .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },4055 .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
drivers/hid/hid-mf.c+2−0
@@ -153,6 +153,8 @@ static const struct hid_device_id mf_devices[] = { · 152 unmodified lines
153 .driver_data = HID_QUIRK_MULTI_INPUT },153 .driver_data = HID_QUIRK_MULTI_INPUT },
154 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE2),154 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE2),
155 .driver_data = 0 }, /* No quirk required */155 .driver_data = 0 }, /* No quirk required */
156 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE3),
157 .driver_data = HID_QUIRK_MULTI_INPUT },
156 { }158 { }
157};159};
158MODULE_DEVICE_TABLE(hid, mf_devices);160MODULE_DEVICE_TABLE(hid, mf_devices);
drivers/hid/hid-quirks.c+3−0
@@ -72,6 +72,7 @@ static const struct hid_device_id hid_quirks[] = { · 71 unmodified lines
72 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_REDRAGON_SEYMUR2), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },72 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_REDRAGON_SEYMUR2), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
73 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR), HID_QUIRK_MULTI_INPUT },73 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR), HID_QUIRK_MULTI_INPUT },
74 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1), HID_QUIRK_MULTI_INPUT },74 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1), HID_QUIRK_MULTI_INPUT },
75 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE3), HID_QUIRK_MULTI_INPUT },
75 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3), HID_QUIRK_MULTI_INPUT },76 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3), HID_QUIRK_MULTI_INPUT },
76 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU), HID_QUIRK_MULTI_INPUT },77 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU), HID_QUIRK_MULTI_INPUT },
77 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER), HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET },78 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER), HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET },
@@ -366,6 +367,7 @@ static const struct hid_device_id hid_have_special_driver[] = { · 288 unmodified lines
366#endif367#endif
367#if IS_ENABLED(CONFIG_HID_ELECOM)368#if IS_ENABLED(CONFIG_HID_ELECOM)
368 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },369 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
370 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XGL20DLBK) },
369 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK) },371 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK) },
370 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK) },372 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK) },
371 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) },373 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) },
@@ -484,6 +486,7 @@ static const struct hid_device_id hid_have_special_driver[] = { · 112 unmodified lines
484 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR) },486 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR) },
485 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1) },487 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1) },
486 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE2) },488 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE2) },
489 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE3) },
487#endif490#endif
488#if IS_ENABLED(CONFIG_HID_MICROSOFT)491#if IS_ENABLED(CONFIG_HID_MICROSOFT)
489 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) },492 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) },
drivers/hid/hid-sony.c+198−49
@@ -11,6 +11,7 @@ · 10 unmodified lines
11 * Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com>11 * Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com>
12 * Copyright (c) 2014-2016 Frank Praznik <frank.praznik@gmail.com>12 * Copyright (c) 2014-2016 Frank Praznik <frank.praznik@gmail.com>
13 * Copyright (c) 2018 Todd Kelner13 * Copyright (c) 2018 Todd Kelner
14 * Copyright (c) 2020 Pascal Giard <pascal.giard@etsmtl.ca>
14 */15 */
15 16
16/*17/*
@@ -35,6 +36,8 @@ · 18 unmodified lines
35#include <linux/idr.h>36#include <linux/idr.h>
36#include <linux/input/mt.h>37#include <linux/input/mt.h>
37#include <linux/crc32.h>38#include <linux/crc32.h>
39#include <linux/usb.h>
40#include <linux/timer.h>
38#include <asm/unaligned.h>41#include <asm/unaligned.h>
39 42
40#include "hid-ids.h"43#include "hid-ids.h"
@@ -56,6 +59,7 @@ · 15 unmodified lines
56#define NSG_MR5U_REMOTE_BT BIT(14)59#define NSG_MR5U_REMOTE_BT BIT(14)
57#define NSG_MR7U_REMOTE_BT BIT(15)60#define NSG_MR7U_REMOTE_BT BIT(15)
58#define SHANWAN_GAMEPAD BIT(16)61#define SHANWAN_GAMEPAD BIT(16)
62#define GHL_GUITAR_PS3WIIU BIT(17)
59 63
60#define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)64#define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
61#define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT)65#define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT)
@@ -79,6 +83,17 @@ · 17 unmodified lines
79#define NSG_MRXU_MAX_X 166783#define NSG_MRXU_MAX_X 1667
80#define NSG_MRXU_MAX_Y 186884#define NSG_MRXU_MAX_Y 1868
81 85
86#define GHL_GUITAR_POKE_INTERVAL 10 /* In seconds */
87#define GHL_GUITAR_TILT_USAGE 44
88
89/* Magic value and data taken from GHLtarUtility:
90 * https://github.com/ghlre/GHLtarUtility/blob/master/PS3Guitar.cs
91 * Note: The Wii U and PS3 dongles happen to share the same!
92 */
93static const u16 ghl_ps3wiiu_magic_value = 0x201;
94static const char ghl_ps3wiiu_magic_data[] = {
95 0x02, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00
96};
82 97
83/* PS/3 Motion controller */98/* PS/3 Motion controller */
84static u8 motion_rdesc[] = {99static u8 motion_rdesc[] = {
@@ -550,7 +565,9 @@ struct sony_sc { · 465 unmodified lines
550 struct power_supply_desc battery_desc;565 struct power_supply_desc battery_desc;
551 int device_id;566 int device_id;
552 unsigned fw_version;567 unsigned fw_version;
568 bool fw_version_created;
553 unsigned hw_version;569 unsigned hw_version;
570 bool hw_version_created;
554 u8 *output_report_dmabuf;571 u8 *output_report_dmabuf;
555 572
556#ifdef CONFIG_SONY_FF573#ifdef CONFIG_SONY_FF
@@ -562,9 +579,8 @@ struct sony_sc { · 5 unmodified lines
562 u8 hotplug_worker_initialized;579 u8 hotplug_worker_initialized;
563 u8 state_worker_initialized;580 u8 state_worker_initialized;
564 u8 defer_initialization;581 u8 defer_initialization;
565 u8 cable_state;
566 u8 battery_charging;
567 u8 battery_capacity;582 u8 battery_capacity;
583 int battery_status;
568 u8 led_state[MAX_LEDS];584 u8 led_state[MAX_LEDS];
569 u8 led_delay_on[MAX_LEDS];585 u8 led_delay_on[MAX_LEDS];
570 u8 led_delay_off[MAX_LEDS];586 u8 led_delay_off[MAX_LEDS];
@@ -578,6 +594,10 @@ struct sony_sc { · 7 unmodified lines
578 enum ds4_dongle_state ds4_dongle_state;594 enum ds4_dongle_state ds4_dongle_state;
579 /* DS4 calibration data */595 /* DS4 calibration data */
580 struct ds4_calibration_data ds4_calib_data[6];596 struct ds4_calibration_data ds4_calib_data[6];
597 /* GH Live */
598 struct timer_list ghl_poke_timer;
599 struct usb_ctrlrequest *ghl_cr;
600 u8 *ghl_databuf;
581};601};
582 602
583static void sony_set_leds(struct sony_sc *sc);603static void sony_set_leds(struct sony_sc *sc);
@@ -601,6 +621,85 @@ static inline void sony_schedule_work(struct sony_sc *sc, · 17 unmodified lines
601 }621 }
602}622}
603 623
624static void ghl_magic_poke_cb(struct urb *urb)
625{
626 if (urb) {
627 /* Free sc->ghl_cr and sc->ghl_databuf allocated in
628 * ghl_magic_poke()
629 */
630 kfree(urb->setup_packet);
631 kfree(urb->transfer_buffer);
632 }
633}
634
635static void ghl_magic_poke(struct timer_list *t)
636{
637 struct sony_sc *sc = from_timer(sc, t, ghl_poke_timer);
638
639 int ret;
640 unsigned int pipe;
641 struct urb *urb;
642 struct usb_device *usbdev = to_usb_device(sc->hdev->dev.parent->parent);
643 const u16 poke_size =
644 ARRAY_SIZE(ghl_ps3wiiu_magic_data);
645
646 pipe = usb_sndctrlpipe(usbdev, 0);
647
648 if (!sc->ghl_cr) {
649 sc->ghl_cr = kzalloc(sizeof(*sc->ghl_cr), GFP_ATOMIC);
650 if (!sc->ghl_cr)
651 goto resched;
652 }
653
654 if (!sc->ghl_databuf) {
655 sc->ghl_databuf = kzalloc(poke_size, GFP_ATOMIC);
656 if (!sc->ghl_databuf)
657 goto resched;
658 }
659
660 urb = usb_alloc_urb(0, GFP_ATOMIC);
661 if (!urb)
662 goto resched;
663
664 sc->ghl_cr->bRequestType =
665 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT;
666 sc->ghl_cr->bRequest = USB_REQ_SET_CONFIGURATION;
667 sc->ghl_cr->wValue = cpu_to_le16(ghl_ps3wiiu_magic_value);
668 sc->ghl_cr->wIndex = 0;
669 sc->ghl_cr->wLength = cpu_to_le16(poke_size);
670 memcpy(sc->ghl_databuf, ghl_ps3wiiu_magic_data, poke_size);
671
672 usb_fill_control_urb(
673 urb, usbdev, pipe,
674 (unsigned char *) sc->ghl_cr, sc->ghl_databuf,
675 poke_size, ghl_magic_poke_cb, NULL);
676 ret = usb_submit_urb(urb, GFP_ATOMIC);
677 if (ret < 0) {
678 kfree(sc->ghl_databuf);
679 kfree(sc->ghl_cr);
680 }
681 usb_free_urb(urb);
682
683resched:
684 /* Reschedule for next time */
685 mod_timer(&sc->ghl_poke_timer, jiffies + GHL_GUITAR_POKE_INTERVAL*HZ);
686}
687
688static int guitar_mapping(struct hid_device *hdev, struct hid_input *hi,
689 struct hid_field *field, struct hid_usage *usage,
690 unsigned long **bit, int *max)
691{
692 if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR) {
693 unsigned int abs = usage->hid & HID_USAGE;
694
695 if (abs == GHL_GUITAR_TILT_USAGE) {
696 hid_map_usage_clear(hi, usage, bit, max, EV_ABS, ABS_RY);
697 return 1;
698 }
699 }
700 return 0;
701}
702
604static ssize_t ds4_show_poll_interval(struct device *dev,703static ssize_t ds4_show_poll_interval(struct device *dev,
605 struct device_attribute704 struct device_attribute
606 *attr, char *buf)705 *attr, char *buf)
@@ -892,7 +991,8 @@ static void sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size) · 285 unmodified lines
892 static const u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 };991 static const u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 };
893 unsigned long flags;992 unsigned long flags;
894 int offset;993 int offset;
895 u8 cable_state, battery_capacity, battery_charging;994 u8 battery_capacity;
995 int battery_status;
896 996
897 /*997 /*
898 * The sixaxis is charging if the battery value is 0xee998 * The sixaxis is charging if the battery value is 0xee
@@ -904,19 +1004,16 @@ static void sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size) · 5 unmodified lines
904 1004
905 if (rd[offset] >= 0xee) {1005 if (rd[offset] >= 0xee) {
906 battery_capacity = 100;1006 battery_capacity = 100;
907 battery_charging = !(rd[offset] & 0x01);1007 battery_status = (rd[offset] & 0x01) ? POWER_SUPPLY_STATUS_FULL : POWER_SUPPLY_STATUS_CHARGING;
908 cable_state = 1;
909 } else {1008 } else {
910 u8 index = rd[offset] <= 5 ? rd[offset] : 5;1009 u8 index = rd[offset] <= 5 ? rd[offset] : 5;
911 battery_capacity = sixaxis_battery_capacity[index];1010 battery_capacity = sixaxis_battery_capacity[index];
912 battery_charging = 0;1011 battery_status = POWER_SUPPLY_STATUS_DISCHARGING;
913 cable_state = 0;
914 }1012 }
915 1013
916 spin_lock_irqsave(&sc->lock, flags);1014 spin_lock_irqsave(&sc->lock, flags);
917 sc->cable_state = cable_state;
918 sc->battery_capacity = battery_capacity;1015 sc->battery_capacity = battery_capacity;
919 sc->battery_charging = battery_charging;1016 sc->battery_status = battery_status;
920 spin_unlock_irqrestore(&sc->lock, flags);1017 spin_unlock_irqrestore(&sc->lock, flags);
921 1018
922 if (sc->quirks & SIXAXIS_CONTROLLER) {1019 if (sc->quirks & SIXAXIS_CONTROLLER) {
@@ -944,7 +1041,8 @@ static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) · 21 unmodified lines
944 struct input_dev *input_dev = hidinput->input;1041 struct input_dev *input_dev = hidinput->input;
945 unsigned long flags;1042 unsigned long flags;
946 int n, m, offset, num_touch_data, max_touch_data;1043 int n, m, offset, num_touch_data, max_touch_data;
947 u8 cable_state, battery_capacity, battery_charging;1044 u8 cable_state, battery_capacity;
1045 int battery_status;
948 u16 timestamp;1046 u16 timestamp;
949 1047
950 /* When using Bluetooth the header is 2 bytes longer, so skip these. */1048 /* When using Bluetooth the header is 2 bytes longer, so skip these. */
@@ -1049,29 +1147,52 @@ static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) · 98 unmodified lines
1049 */1147 */
1050 offset = data_offset + DS4_INPUT_REPORT_BATTERY_OFFSET;1148 offset = data_offset + DS4_INPUT_REPORT_BATTERY_OFFSET;
1051 cable_state = (rd[offset] >> 4) & 0x01;1149 cable_state = (rd[offset] >> 4) & 0x01;
1052 battery_capacity = rd[offset] & 0x0F;
1053 1150
1054 /*1151 /*
1055 * When a USB power source is connected the battery level ranges from1152 * Interpretation of the battery_capacity data depends on the cable state.
1056 * 0 to 10, and when running on battery power it ranges from 0 to 9.1153 * When no cable is connected (bit4 is 0):
1057 * A battery level above 10 when plugged in means charge completed.1154 * - 0:10: percentage in units of 10%.
1155 * When a cable is plugged in:
1156 * - 0-10: percentage in units of 10%.
1157 * - 11: battery is full
1158 * - 14: not charging due to Voltage or temperature error
1159 * - 15: charge error
1058 */1160 */
1059 if (!cable_state || battery_capacity > 10)1161 if (cable_state) {
1060 battery_charging = 0;1162 u8 battery_data = rd[offset] & 0xf;
1061 else1163
1062 battery_charging = 1;1164 if (battery_data < 10) {
1165 /* Take the mid-point for each battery capacity value,
1166 * because on the hardware side 0 = 0-9%, 1=10-19%, etc.
1167 * This matches official platform behavior, which does
1168 * the same.
1169 */
1170 battery_capacity = battery_data * 10 + 5;
1171 battery_status = POWER_SUPPLY_STATUS_CHARGING;
1172 } else if (battery_data == 10) {
1173 battery_capacity = 100;
1174 battery_status = POWER_SUPPLY_STATUS_CHARGING;
1175 } else if (battery_data == 11) {
1176 battery_capacity = 100;
1177 battery_status = POWER_SUPPLY_STATUS_FULL;
1178 } else { /* 14, 15 and undefined values */
1179 battery_capacity = 0;
1180 battery_status = POWER_SUPPLY_STATUS_UNKNOWN;
1181 }
1182 } else {
1183 u8 battery_data = rd[offset] & 0xf;
1063 1184
1064 if (!cable_state)1185 if (battery_data < 10)
1065 battery_capacity++;1186 battery_capacity = battery_data * 10 + 5;
1066 if (battery_capacity > 10)1187 else /* 10 */
1067 battery_capacity = 10;1188 battery_capacity = 100;
1068 1189
1069 battery_capacity *= 10;1190 battery_status = POWER_SUPPLY_STATUS_DISCHARGING;
1191 }
1070 1192
1071 spin_lock_irqsave(&sc->lock, flags);1193 spin_lock_irqsave(&sc->lock, flags);
1072 sc->cable_state = cable_state;
1073 sc->battery_capacity = battery_capacity;1194 sc->battery_capacity = battery_capacity;
1074 sc->battery_charging = battery_charging;1195 sc->battery_status = battery_status;
1075 spin_unlock_irqrestore(&sc->lock, flags);1196 spin_unlock_irqrestore(&sc->lock, flags);
1076 1197
1077 /*1198 /*
@@ -1360,6 +1481,8 @@ static int sony_mapping(struct hid_device *hdev, struct hid_input *hi, · 282 unmodified lines
1360 if (sc->quirks & DUALSHOCK4_CONTROLLER)1481 if (sc->quirks & DUALSHOCK4_CONTROLLER)
1361 return ds4_mapping(hdev, hi, field, usage, bit, max);1482 return ds4_mapping(hdev, hi, field, usage, bit, max);
1362 1483
1484 if (sc->quirks & GHL_GUITAR_PS3WIIU)
1485 return guitar_mapping(hdev, hi, field, usage, bit, max);
1363 1486
1364 /* Let hid-core decide for the others */1487 /* Let hid-core decide for the others */
1365 return 0;1488 return 0;
@@ -1597,16 +1720,38 @@ static int dualshock4_get_calibration_data(struct sony_sc *sc) · 231 unmodified lines
1597 * of the controller, so that it sends input reports of type 0x11.1720 * of the controller, so that it sends input reports of type 0x11.
1598 */1721 */
1599 if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) {1722 if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) {
1723 int retries;
1724
1600 buf = kmalloc(DS4_FEATURE_REPORT_0x02_SIZE, GFP_KERNEL);1725 buf = kmalloc(DS4_FEATURE_REPORT_0x02_SIZE, GFP_KERNEL);
1601 if (!buf)1726 if (!buf)
1602 return -ENOMEM;1727 return -ENOMEM;
1603 1728
1604 ret = hid_hw_raw_request(sc->hdev, 0x02, buf,1729 /* We should normally receive the feature report data we asked
1605 DS4_FEATURE_REPORT_0x02_SIZE,1730 * for, but hidraw applications such as Steam can issue feature
1606 HID_FEATURE_REPORT,1731 * reports as well. In particular for Dongle reconnects, Steam
1607 HID_REQ_GET_REPORT);1732 * and this function are competing resulting in often receiving
1608 if (ret < 0)1733 * data for a different HID report, so retry a few times.
1609 goto err_stop;1734 */
1735 for (retries = 0; retries < 3; retries++) {
1736 ret = hid_hw_raw_request(sc->hdev, 0x02, buf,
1737 DS4_FEATURE_REPORT_0x02_SIZE,
1738 HID_FEATURE_REPORT,
1739 HID_REQ_GET_REPORT);
1740 if (ret < 0)
1741 goto err_stop;
1742
1743 if (buf[0] != 0x02) {
1744 if (retries < 2) {
1745 hid_warn(sc->hdev, "Retrying DualShock 4 get calibration report (0x02) request\n");
1746 continue;
1747 } else {
1748 ret = -EILSEQ;
1749 goto err_stop;
1750 }
1751 } else {
1752 break;
1753 }
1754 }
1610 } else {1755 } else {
1611 u8 bthdr = 0xA3;1756 u8 bthdr = 0xA3;
1612 u32 crc;1757 u32 crc;
@@ -2300,12 +2445,12 @@ static int sony_battery_get_property(struct power_supply *psy, · 687 unmodified lines
2300 struct sony_sc *sc = power_supply_get_drvdata(psy);2445 struct sony_sc *sc = power_supply_get_drvdata(psy);
2301 unsigned long flags;2446 unsigned long flags;
2302 int ret = 0;2447 int ret = 0;
2303 u8 battery_charging, battery_capacity, cable_state;2448 u8 battery_capacity;
2449 int battery_status;
2304 2450
2305 spin_lock_irqsave(&sc->lock, flags);2451 spin_lock_irqsave(&sc->lock, flags);
2306 battery_charging = sc->battery_charging;
2307 battery_capacity = sc->battery_capacity;2452 battery_capacity = sc->battery_capacity;
2308 cable_state = sc->cable_state;2453 battery_status = sc->battery_status;
2309 spin_unlock_irqrestore(&sc->lock, flags);2454 spin_unlock_irqrestore(&sc->lock, flags);
2310 2455
2311 switch (psp) {2456 switch (psp) {
@@ -2319,13 +2464,7 @@ static int sony_battery_get_property(struct power_supply *psy, · 7 unmodified lines
2319 val->intval = battery_capacity;2464 val->intval = battery_capacity;
2320 break;2465 break;
2321 case POWER_SUPPLY_PROP_STATUS:2466 case POWER_SUPPLY_PROP_STATUS:
2322 if (battery_charging)2467 val->intval = battery_status;
2323 val->intval = POWER_SUPPLY_STATUS_CHARGING;
2324 else
2325 if (battery_capacity == 100 && cable_state)
2326 val->intval = POWER_SUPPLY_STATUS_FULL;
2327 else
2328 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
2329 break;2468 break;
2330 default:2469 default:
2331 ret = -EINVAL;2470 ret = -EINVAL;
@@ -2723,19 +2862,17 @@ static int sony_input_configured(struct hid_device *hdev, · 391 unmodified lines
2723 2862
2724 ret = device_create_file(&sc->hdev->dev, &dev_attr_firmware_version);2863 ret = device_create_file(&sc->hdev->dev, &dev_attr_firmware_version);
2725 if (ret) {2864 if (ret) {
2726 /* Make zero for cleanup reasons of sysfs entries. */
2727 sc->fw_version = 0;
2728 sc->hw_version = 0;
2729 hid_err(sc->hdev, "can't create sysfs firmware_version attribute err: %d\n", ret);2865 hid_err(sc->hdev, "can't create sysfs firmware_version attribute err: %d\n", ret);
2730 goto err_stop;2866 goto err_stop;
2731 }2867 }
2868 sc->fw_version_created = true;
2732 2869
2733 ret = device_create_file(&sc->hdev->dev, &dev_attr_hardware_version);2870 ret = device_create_file(&sc->hdev->dev, &dev_attr_hardware_version);
2734 if (ret) {2871 if (ret) {
2735 sc->hw_version = 0;
2736 hid_err(sc->hdev, "can't create sysfs hardware_version attribute err: %d\n", ret);2872 hid_err(sc->hdev, "can't create sysfs hardware_version attribute err: %d\n", ret);
2737 goto err_stop;2873 goto err_stop;
2738 }2874 }
2875 sc->hw_version_created = true;
2739 2876
2740 /*2877 /*
2741 * The Dualshock 4 touchpad supports 2 touches and has a2878 * The Dualshock 4 touchpad supports 2 touches and has a
@@ -2827,9 +2964,9 @@ err_stop: · 85 unmodified lines
2827 */2964 */
2828 if (sc->ds4_bt_poll_interval)2965 if (sc->ds4_bt_poll_interval)
2829 device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval);2966 device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval);
2830 if (sc->fw_version)2967 if (sc->fw_version_created)
2831 device_remove_file(&sc->hdev->dev, &dev_attr_firmware_version);2968 device_remove_file(&sc->hdev->dev, &dev_attr_firmware_version);
2832 if (sc->hw_version)2969 if (sc->hw_version_created)
2833 device_remove_file(&sc->hdev->dev, &dev_attr_hardware_version);2970 device_remove_file(&sc->hdev->dev, &dev_attr_hardware_version);
2834 sony_cancel_work_sync(sc);2971 sony_cancel_work_sync(sc);
2835 sony_remove_dev_list(sc);2972 sony_remove_dev_list(sc);
@@ -2902,6 +3039,12 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) · 66 unmodified lines
2902 return -ENODEV;3039 return -ENODEV;
2903 }3040 }
2904 3041
3042 if (sc->quirks & GHL_GUITAR_PS3WIIU) {
3043 timer_setup(&sc->ghl_poke_timer, ghl_magic_poke, 0);
3044 mod_timer(&sc->ghl_poke_timer,
3045 jiffies + GHL_GUITAR_POKE_INTERVAL*HZ);
3046 }
3047
2905 return ret;3048 return ret;
2906}3049}
2907 3050
@@ -2909,15 +3052,18 @@ static void sony_remove(struct hid_device *hdev) · 1 unmodified line
2909{3052{
2910 struct sony_sc *sc = hid_get_drvdata(hdev);3053 struct sony_sc *sc = hid_get_drvdata(hdev);
2911 3054
3055 if (sc->quirks & GHL_GUITAR_PS3WIIU)
3056 del_timer_sync(&sc->ghl_poke_timer);
3057
2912 hid_hw_close(hdev);3058 hid_hw_close(hdev);
2913 3059
2914 if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)3060 if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
2915 device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval);3061 device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval);
2916 3062
2917 if (sc->fw_version)3063 if (sc->fw_version_created)
2918 device_remove_file(&sc->hdev->dev, &dev_attr_firmware_version);3064 device_remove_file(&sc->hdev->dev, &dev_attr_firmware_version);
2919 3065
2920 if (sc->hw_version)3066 if (sc->hw_version_created)
2921 device_remove_file(&sc->hdev->dev, &dev_attr_hardware_version);3067 device_remove_file(&sc->hdev->dev, &dev_attr_hardware_version);
2922 3068
2923 sony_cancel_work_sync(sc);3069 sony_cancel_work_sync(sc);
@@ -3020,6 +3166,9 @@ static const struct hid_device_id sony_devices[] = { · 96 unmodified lines
3020 /* SMK-Link NSG-MR7U Remote Control */3166 /* SMK-Link NSG-MR7U Remote Control */
3021 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_NSG_MR7U_REMOTE),3167 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_NSG_MR7U_REMOTE),
3022 .driver_data = NSG_MR7U_REMOTE_BT },3168 .driver_data = NSG_MR7U_REMOTE_BT },
3169 /* Guitar Hero Live PS3 and Wii U guitar dongles */
3170 { HID_USB_DEVICE(USB_VENDOR_ID_SONY_GHLIVE, USB_DEVICE_ID_SONY_PS3WIIU_GHLIVE_DONGLE),
3171 .driver_data = GHL_GUITAR_PS3WIIU},
3023 { }3172 { }
3024};3173};
3025MODULE_DEVICE_TABLE(hid, sony_devices);3174MODULE_DEVICE_TABLE(hid, sony_devices);
drivers/hid/hidraw.c+23−1
@@ -170,7 +170,7 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t · 169 unmodified lines
170/*170/*
171 * This function performs a Get_Report transfer over the control endpoint171 * This function performs a Get_Report transfer over the control endpoint
172 * per section 7.2.1 of the HID specification, version 1.1. The first byte172 * per section 7.2.1 of the HID specification, version 1.1. The first byte
173 * of buffer is the report number to request, or 0x0 if the defice does not173 * of buffer is the report number to request, or 0x0 if the device does not
174 * use numbered reports. The report_type parameter can be HID_FEATURE_REPORT174 * use numbered reports. The report_type parameter can be HID_FEATURE_REPORT
175 * or HID_INPUT_REPORT.175 * or HID_INPUT_REPORT.
176 */176 */
@@ -428,6 +428,28 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, · 251 unmodified lines
428 break;428 break;
429 }429 }
430 430
431 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCSINPUT(0))) {
432 int len = _IOC_SIZE(cmd);
433 ret = hidraw_send_report(file, user_arg, len, HID_INPUT_REPORT);
434 break;
435 }
436 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGINPUT(0))) {
437 int len = _IOC_SIZE(cmd);
438 ret = hidraw_get_report(file, user_arg, len, HID_INPUT_REPORT);
439 break;
440 }
441
442 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCSOUTPUT(0))) {
443 int len = _IOC_SIZE(cmd);
444 ret = hidraw_send_report(file, user_arg, len, HID_OUTPUT_REPORT);
445 break;
446 }
447 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGOUTPUT(0))) {
448 int len = _IOC_SIZE(cmd);
449 ret = hidraw_get_report(file, user_arg, len, HID_OUTPUT_REPORT);
450 break;
451 }
452
431 /* Begin Read-only ioctls. */453 /* Begin Read-only ioctls. */
432 if (_IOC_DIR(cmd) != _IOC_READ) {454 if (_IOC_DIR(cmd) != _IOC_READ) {
433 ret = -EINVAL;455 ret = -EINVAL;
drivers/hid/i2c-hid/i2c-hid-core.c+4−1
@@ -1106,8 +1106,11 @@ static int i2c_hid_probe(struct i2c_client *client, · 1105 unmodified lines
1106 }1106 }
1107 1107
1108 ret = i2c_hid_fetch_hid_descriptor(ihid);1108 ret = i2c_hid_fetch_hid_descriptor(ihid);
1109 if (ret < 0)1109 if (ret < 0) {
1110 dev_err(&client->dev,
1111 "Failed to fetch the HID Descriptor\n");
1110 goto err_regulator;1112 goto err_regulator;
1113 }
1111 1114
1112 ret = i2c_hid_init_irq(client);1115 ret = i2c_hid_init_irq(client);
1113 if (ret < 0)1116 if (ret < 0)
drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c+8−0
@@ -405,6 +405,14 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = { · 404 unmodified lines
405 },405 },
406 .driver_data = (void *)&sipodev_desc406 .driver_data = (void *)&sipodev_desc
407 },407 },
408 {
409 .ident = "Vero K147",
410 .matches = {
411 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VERO"),
412 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "K147"),
413 },
414 .driver_data = (void *)&sipodev_desc
415 },
408 { } /* Terminate list */416 { } /* Terminate list */
409};417};
410 418
drivers/hid/intel-ish-hid/ishtp-hid.c+2−4
@@ -211,10 +211,8 @@ int ishtp_hid_probe(unsigned int cur_hid_dev, · 210 unmodified lines
211 struct ishtp_hid_data *hid_data;211 struct ishtp_hid_data *hid_data;
212 212
213 hid = hid_allocate_device();213 hid = hid_allocate_device();
214 if (IS_ERR(hid)) {214 if (IS_ERR(hid))
215 rv = PTR_ERR(hid);215 return PTR_ERR(hid);
216 return -ENOMEM;
217 }
218 216
219 hid_data = kzalloc(sizeof(*hid_data), GFP_KERNEL);217 hid_data = kzalloc(sizeof(*hid_data), GFP_KERNEL);
220 if (!hid_data) {218 if (!hid_data) {
drivers/hid/usbhid/hid-core.c+2−0
@@ -438,6 +438,7 @@ static void hid_irq_out(struct urb *urb) · 437 unmodified lines
438 break;438 break;
439 case -ESHUTDOWN: /* unplug */439 case -ESHUTDOWN: /* unplug */
440 unplug = 1;440 unplug = 1;
441 break;
441 case -EILSEQ: /* protocol error or unplug */442 case -EILSEQ: /* protocol error or unplug */
442 case -EPROTO: /* protocol error or unplug */443 case -EPROTO: /* protocol error or unplug */
443 case -ECONNRESET: /* unlink */444 case -ECONNRESET: /* unlink */
@@ -489,6 +490,7 @@ static void hid_ctrl(struct urb *urb) · 45 unmodified lines
489 break;490 break;
490 case -ESHUTDOWN: /* unplug */491 case -ESHUTDOWN: /* unplug */
491 unplug = 1;492 unplug = 1;
493 break;
492 case -EILSEQ: /* protocol error or unplug */494 case -EILSEQ: /* protocol error or unplug */
493 case -EPROTO: /* protocol error or unplug */495 case -EPROTO: /* protocol error or unplug */
494 case -ECONNRESET: /* unlink */496 case -ECONNRESET: /* unlink */
drivers/hid/wacom_sys.c+8−8
@@ -1173,7 +1173,7 @@ static struct attribute *cintiq_led_attrs[] = { · 1172 unmodified lines
1173 NULL1173 NULL
1174};1174};
1175 1175
1176static struct attribute_group cintiq_led_attr_group = {1176static const struct attribute_group cintiq_led_attr_group = {
1177 .name = "wacom_led",1177 .name = "wacom_led",
1178 .attrs = cintiq_led_attrs,1178 .attrs = cintiq_led_attrs,
1179};1179};
@@ -1194,7 +1194,7 @@ static struct attribute *intuos4_led_attrs[] = { · 14 unmodified lines
1194 NULL1194 NULL
1195};1195};
1196 1196
1197static struct attribute_group intuos4_led_attr_group = {1197static const struct attribute_group intuos4_led_attr_group = {
1198 .name = "wacom_led",1198 .name = "wacom_led",
1199 .attrs = intuos4_led_attrs,1199 .attrs = intuos4_led_attrs,
1200};1200};
@@ -1205,7 +1205,7 @@ static struct attribute *intuos5_led_attrs[] = { · 4 unmodified lines
1205 NULL1205 NULL
1206};1206};
1207 1207
1208static struct attribute_group intuos5_led_attr_group = {1208static const struct attribute_group intuos5_led_attr_group = {
1209 .name = "wacom_led",1209 .name = "wacom_led",
1210 .attrs = intuos5_led_attrs,1210 .attrs = intuos5_led_attrs,
1211};1211};
@@ -1216,13 +1216,13 @@ static struct attribute *generic_led_attrs[] = { · 4 unmodified lines
1216 NULL1216 NULL
1217};1217};
1218 1218
1219static struct attribute_group generic_led_attr_group = {1219static const struct attribute_group generic_led_attr_group = {
1220 .name = "wacom_led",1220 .name = "wacom_led",
1221 .attrs = generic_led_attrs,1221 .attrs = generic_led_attrs,
1222};1222};
1223 1223
1224struct wacom_sysfs_group_devres {1224struct wacom_sysfs_group_devres {
1225 struct attribute_group *group;1225 const struct attribute_group *group;
1226 struct kobject *root;1226 struct kobject *root;
1227};1227};
1228 1228
@@ -1238,7 +1238,7 @@ static void wacom_devm_sysfs_group_release(struct device *dev, void *res) · 9 unmodified lines
1238 1238
1239static int __wacom_devm_sysfs_create_group(struct wacom *wacom,1239static int __wacom_devm_sysfs_create_group(struct wacom *wacom,
1240 struct kobject *root,1240 struct kobject *root,
1241 struct attribute_group *group)1241 const struct attribute_group *group)
1242{1242{
1243 struct wacom_sysfs_group_devres *devres;1243 struct wacom_sysfs_group_devres *devres;
1244 int error;1244 int error;
@@ -1264,7 +1264,7 @@ static int __wacom_devm_sysfs_create_group(struct wacom *wacom, · 19 unmodified lines
1264}1264}
1265 1265
1266static int wacom_devm_sysfs_create_group(struct wacom *wacom,1266static int wacom_devm_sysfs_create_group(struct wacom *wacom,
1267 struct attribute_group *group)1267 const struct attribute_group *group)
1268{1268{
1269 return __wacom_devm_sysfs_create_group(wacom, &wacom->hdev->dev.kobj,1269 return __wacom_devm_sysfs_create_group(wacom, &wacom->hdev->dev.kobj,
1270 group);1270 group);
@@ -1847,7 +1847,7 @@ static struct attribute *remote##SET_ID##_serial_attrs[] = { \ · 576 unmodified lines
1847 &remote##SET_ID##_mode_attr.attr, \1847 &remote##SET_ID##_mode_attr.attr, \
1848 NULL \1848 NULL \
1849}; \1849}; \
1850static struct attribute_group remote##SET_ID##_serial_group = { \1850static const struct attribute_group remote##SET_ID##_serial_group = { \
1851 .name = NULL, \1851 .name = NULL, \
1852 .attrs = remote##SET_ID##_serial_attrs, \1852 .attrs = remote##SET_ID##_serial_attrs, \
1853}1853}
include/linux/hid.h+2−1
@@ -494,7 +494,7 @@ struct hid_report_enum { · 493 unmodified lines
494};494};
495 495
496#define HID_MIN_BUFFER_SIZE 64 /* make sure there is at least a packet size of space */496#define HID_MIN_BUFFER_SIZE 64 /* make sure there is at least a packet size of space */
497#define HID_MAX_BUFFER_SIZE 8192 /* 8kb */497#define HID_MAX_BUFFER_SIZE 16384 /* 16kb */
498#define HID_CONTROL_FIFO_SIZE 256 /* to init devices with >100 reports */498#define HID_CONTROL_FIFO_SIZE 256 /* to init devices with >100 reports */
499#define HID_OUTPUT_FIFO_SIZE 64499#define HID_OUTPUT_FIFO_SIZE 64
500 500
@@ -585,6 +585,7 @@ struct hid_device { /* device report descriptor */ · 84 unmodified lines
585 __s32 battery_report_id;585 __s32 battery_report_id;
586 enum hid_battery_status battery_status;586 enum hid_battery_status battery_status;
587 bool battery_avoid_query;587 bool battery_avoid_query;
588 ktime_t battery_ratelimit_time;
588#endif589#endif
589 590
590 unsigned long status; /* see STAT flags above */591 unsigned long status; /* see STAT flags above */
include/uapi/linux/hidraw.h+6−0
@@ -40,6 +40,12 @@ struct hidraw_devinfo { · 39 unmodified lines
40#define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)40#define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)
41#define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)41#define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)
42#define HIDIOCGRAWUNIQ(len) _IOC(_IOC_READ, 'H', 0x08, len)42#define HIDIOCGRAWUNIQ(len) _IOC(_IOC_READ, 'H', 0x08, len)
43/* The first byte of SINPUT and GINPUT is the report number */
44#define HIDIOCSINPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x09, len)
45#define HIDIOCGINPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0A, len)
46/* The first byte of SOUTPUT and GOUTPUT is the report number */
47#define HIDIOCSOUTPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0B, len)
48#define HIDIOCGOUTPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0C, len)
43 49
44#define HIDRAW_FIRST_MINOR 050#define HIDRAW_FIRST_MINOR 0
45#define HIDRAW_MAX_DEVICES 6451#define HIDRAW_MAX_DEVICES 64
samples/hidraw/hid-example.c+1−1
@@ -128,7 +128,7 @@ int main(int argc, char **argv) · 127 unmodified lines
128 perror("HIDIOCGFEATURE");128 perror("HIDIOCGFEATURE");
129 } else {129 } else {
130 printf("ioctl HIDIOCGFEATURE returned: %d\n", res);130 printf("ioctl HIDIOCGFEATURE returned: %d\n", res);
131 printf("Report data (not containing the report number):\n\t");131 printf("Report data:\n\t");
132 for (i = 0; i < res; i++)132 for (i = 0; i < res; i++)
133 printf("%hhx ", buf[i]);133 printf("%hhx ", buf[i]);
134 puts("\n");134 puts("\n");