Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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
...

+2360 -95
+145
Documentation/hid/amd-sfh-hid.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + 4 + AMD Sensor Fusion Hub 5 + ===================== 6 + AMD Sensor Fusion Hub (SFH) is part of an SOC starting from Ryzen based platforms. 7 + The solution is working well on several OEM products. AMD SFH uses HID over PCIe bus. 8 + In terms of architecture it resembles ISH, however the major difference is all 9 + the HID reports are generated as part of the kernel driver. 10 + 11 + 1. 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 + 45 + AMD HID Transport Layer 46 + ----------------------- 47 + AMD SFH transport is also implemented as a bus. Each client application executing in the AMD MP2 is 48 + registered as a device on this bus. Here: MP2 which is an ARM core connected to x86 for processing 49 + sensor data. The layer, which binds each device (AMD SFH HID driver) identifies the device type and 50 + registers with the hid core. Transport layer attach a constant "struct hid_ll_driver" object with 51 + each device. Once a device is registered with HID core, the callbacks provided via this struct are 52 + used by HID core to communicate with the device. AMD HID Transport layer implements the synchronous calls. 53 + 54 + AMD HID Client Layer 55 + -------------------- 56 + This layer is responsible to implement HID request and descriptors. As firmware is OS agnostic, HID 57 + client layer fills the HID request structure and descriptors. HID client layer is complex as it is 58 + interface between MP2 PCIe layer and HID. HID client layer initialized the MP2 PCIe layer and holds 59 + the instance of MP2 layer. It identifies the number of sensors connected using MP2-PCIe layer. Base 60 + on that allocates the DRAM address for each and every sensor and pass it to MP2-PCIe driver.On 61 + enumeration of each the sensor, client layer fills the HID Descriptor structure and HID input repor 62 + structure. HID Feature report structure is optional. The report descriptor structure varies from 63 + sensor to sensor. 64 + 65 + AMD MP2 PCIe layer 66 + ------------------ 67 + MP2 PCIe Layer is responsible for making all transactions with the firmware over PCIe. 68 + The connection establishment between firmware and PCIe happens here. 69 + 70 + The communication between X86 and MP2 is split into three parts. 71 + 1. Command transfer via the C2P mailbox registers. 72 + 2. Data transfer via DRAM. 73 + 3. Supported sensor info via P2C registers. 74 + 75 + Commands are sent to MP2 using C2P Mailbox registers. Writing into C2P Message registers generate 76 + interrupt to MP2. The client layer allocates the physical memory and the same is sent to MP2 via 77 + the PCI layer. MP2 firmware writes the command output to the access DRAM memory which the client 78 + layer has allocated. Firmware always writes minimum of 32 bytes into DRAM. So as a protocol driver 79 + shall allocate minimum of 32 bytes DRAM space. 80 + 81 + Enumeration 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 + 120 + Data 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 + <-------| | | | |
+43 -2
Documentation/hid/hidraw.rst
··· 123 123 This ioctl will request a feature report from the device using the control 124 124 endpoint. The first byte of the supplied buffer should be set to the report 125 125 number of the requested report. For devices which do not use numbered 126 - reports, set the first byte to 0. The report will be returned starting at 127 - the first byte of the buffer (ie: the report number is not returned). 126 + reports, set the first byte to 0. The returned report buffer will contain the 127 + report number in the first byte, followed by the report data read from the 128 + device. For devices which do not use numbered reports, the report data will 129 + begin at the first byte of the returned buffer. 130 + 131 + HIDIOCSINPUT(len): 132 + Send an Input Report 133 + 134 + This ioctl will send an input report to the device, using the control endpoint. 135 + In most cases, setting an input HID report on a device is meaningless and has 136 + no effect, but some devices may choose to use this to set or reset an initial 137 + state of a report. The format of the buffer issued with this report is identical 138 + to that of HIDIOCSFEATURE. 139 + 140 + HIDIOCGINPUT(len): 141 + Get an Input Report 142 + 143 + This ioctl will request an input report from the device using the control 144 + endpoint. This is slower on most devices where a dedicated In endpoint exists 145 + for regular input reports, but allows the host to request the value of a 146 + specific report number. Typically, this is used to request the initial states of 147 + an input report of a device, before an application listens for normal reports via 148 + the regular device read() interface. The format of the buffer issued with this report 149 + is identical to that of HIDIOCGFEATURE. 150 + 151 + HIDIOCSOUTPUT(len): 152 + Send an Output Report 153 + 154 + This ioctl will send an output report to the device, using the control endpoint. 155 + This is slower on most devices where a dedicated Out endpoint exists for regular 156 + output reports, but is added for completeness. Typically, this is used to set 157 + the initial states of an output report of a device, before an application sends 158 + updates via the regular device write() interface. The format of the buffer issued 159 + with this report is identical to that of HIDIOCSFEATURE. 160 + 161 + HIDIOCGOUTPUT(len): 162 + Get an Output Report 163 + 164 + This ioctl will request an output report from the device using the control 165 + endpoint. Typically, this is used to retrive the initial state of 166 + an output report of a device, before an application updates it as necessary either 167 + via a HIDIOCSOUTPUT request, or the regular device write() interface. The format 168 + of the buffer issued with this report is identical to that of HIDIOCGFEATURE. 128 169 129 170 Example 130 171 -------
+1
Documentation/hid/index.rst
··· 16 16 17 17 hid-alps 18 18 intel-ish-hid 19 + amd-sfh-hid
+8
MAINTAINERS
··· 956 956 F: arch/arm64/boot/dts/amd/amd-seattle-xgbe*.dtsi 957 957 F: drivers/net/ethernet/amd/xgbe/ 958 958 959 + AMD SENSOR FUSION HUB DRIVER 960 + M: Nehal Shah <nehal-bakulchandra.shah@amd.com> 961 + M: Sandeep Singh <sandeep.singh@amd.com> 962 + L: linux-input@vger.kernel.org 963 + S: Maintained 964 + F: Documentation/hid/amd-sfh* 965 + F: drivers/hid/amd-sfh-hid/ 966 + 959 967 AMS AS73211 DRIVER 960 968 M: Christian Eggers <ceggers@arri.de> 961 969 L: linux-iio@vger.kernel.org
+3
drivers/hid/Kconfig
··· 907 907 * Buzz controllers 908 908 * Sony PS3 Blue-ray Disk Remote Control (Bluetooth) 909 909 * Logitech Harmony adapter for Sony Playstation 3 (Bluetooth) 910 + * Guitar Hero Live PS3 and Wii U guitar dongles 910 911 911 912 config SONY_FF 912 913 bool "Sony PS2/3/4 accessories force feedback support" ··· 1183 1182 source "drivers/hid/i2c-hid/Kconfig" 1184 1183 1185 1184 source "drivers/hid/intel-ish-hid/Kconfig" 1185 + 1186 + source "drivers/hid/amd-sfh-hid/Kconfig" 1186 1187 1187 1188 endmenu
+2
drivers/hid/Makefile
··· 142 142 143 143 obj-$(CONFIG_INTEL_ISH_HID) += intel-ish-hid/ 144 144 obj-$(INTEL_ISH_FIRMWARE_DOWNLOADER) += intel-ish-hid/ 145 + 146 + obj-$(CONFIG_AMD_SFH_HID) += amd-sfh-hid/
+18
drivers/hid/amd-sfh-hid/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0-or-later 2 + menu "AMD SFH HID Support" 3 + depends on X86_64 || COMPILE_TEST 4 + depends on PCI 5 + depends on HID 6 + 7 + config 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. 18 + endmenu
+13
drivers/hid/amd-sfh-hid/Makefile
··· 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 + # 7 + obj-$(CONFIG_AMD_SFH_HID) += amd_sfh.o 8 + amd_sfh-objs := amd_sfh_hid.o 9 + amd_sfh-objs += amd_sfh_client.o 10 + amd_sfh-objs += amd_sfh_pcie.o 11 + amd_sfh-objs += hid_descriptor/amd_sfh_hid_desc.o 12 + 13 + ccflags-y += -I $(srctree)/$(src)/
+246
drivers/hid/amd-sfh-hid/amd_sfh_client.c
··· 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 + 22 + struct 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 + 31 + static struct request_list req_list; 32 + 33 + void 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 + 49 + int 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 + 77 + static 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 + 118 + static 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 + 134 + int 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 + 210 + cleanup: 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 + 225 + int 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 + }
+174
drivers/hid/amd-sfh-hid/amd_sfh_hid.c
··· 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 + */ 24 + static 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 */ 34 + static int amdtp_hid_start(struct hid_device *hid) 35 + { 36 + return 0; 37 + } 38 + 39 + static void amdtp_hid_stop(struct hid_device *hid) 40 + { 41 + } 42 + 43 + static int amdtp_hid_open(struct hid_device *hid) 44 + { 45 + return 0; 46 + } 47 + 48 + static void amdtp_hid_close(struct hid_device *hid) 49 + { 50 + } 51 + 52 + static 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 + 58 + static 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 + 76 + static 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 + 99 + void 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 + 108 + static 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 + 119 + int 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 + 153 + err_hid_device: 154 + kfree(hid_data); 155 + err_hid_data: 156 + hid_destroy_device(hid); 157 + return rc; 158 + } 159 + 160 + void 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 + }
+67
drivers/hid/amd-sfh-hid/amd_sfh_hid.h
··· 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 + 17 + struct 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 + */ 53 + struct 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 */ 60 + void hid_amdtp_set_feature(struct hid_device *hid, char *buf, u32 len, int report_id); 61 + void hid_amdtp_get_report(struct hid_device *hid, int report_id, int report_type); 62 + int amdtp_hid_probe(u32 cur_hid_dev, struct amdtp_cl_data *cli_data); 63 + void amdtp_hid_remove(struct amdtp_cl_data *cli_data); 64 + int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type); 65 + void amd_sfh_set_report(struct hid_device *hid, int report_id, int report_type); 66 + void amdtp_hid_wakeup(struct hid_device *hid); 67 + #endif
+152
drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
··· 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 + 28 + void 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 + 49 + void 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 + 63 + void 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 + 76 + int 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 + 97 + static void amd_mp2_pci_remove(void *privdata) 98 + { 99 + amd_sfh_hid_client_deinit(privdata); 100 + amd_stop_all_sensors(privdata); 101 + } 102 + 103 + static 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 + 136 + static const struct pci_device_id amd_mp2_pci_tbl[] = { 137 + { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_MP2) }, 138 + { } 139 + }; 140 + MODULE_DEVICE_TABLE(pci, amd_mp2_pci_tbl); 141 + 142 + static 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 + }; 147 + module_pci_driver(amd_mp2_pci_driver); 148 + 149 + MODULE_DESCRIPTION(DRIVER_DESC); 150 + MODULE_LICENSE("Dual BSD/GPL"); 151 + MODULE_AUTHOR("Shyam Sundar S K <Shyam-sundar.S-k@amd.com>"); 152 + MODULE_AUTHOR("Sandeep Singh <Sandeep.singh@amd.com>");
+79
drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
··· 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 */ 29 + union 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 + 38 + union 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 + 47 + struct 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 + 53 + enum sensor_idx { 54 + accel_idx = 0, 55 + gyro_idx = 1, 56 + mag_idx = 2, 57 + als_idx = 19 58 + }; 59 + 60 + struct amd_mp2_dev { 61 + struct pci_dev *pdev; 62 + struct amdtp_cl_data *cl_data; 63 + void __iomem *mmio; 64 + u32 activecontrolstatus; 65 + }; 66 + 67 + struct amd_mp2_sensor_info { 68 + u8 sensor_idx; 69 + u32 period; 70 + phys_addr_t phys_address; 71 + }; 72 + 73 + void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info); 74 + void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx); 75 + void amd_stop_all_sensors(struct amd_mp2_dev *privdata); 76 + int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id); 77 + int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata); 78 + int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata); 79 + #endif
+224
drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c
··· 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 + 29 + int 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 + 58 + u32 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 + 107 + static 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 + 117 + u8 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 + 170 + static 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 + 177 + u8 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 + }
+107
drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h
··· 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 + 12 + enum desc_type { 13 + /* Report descriptor name */ 14 + descr_size = 1, 15 + input_size, 16 + feature_size, 17 + }; 18 + 19 + struct 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 + 29 + struct common_input_property { 30 + /* common properties */ 31 + u8 report_id; 32 + u8 sensor_state; 33 + u8 event_type; 34 + } __packed; 35 + 36 + struct 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 + 44 + struct 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 + 54 + struct 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 + 62 + struct 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 + 70 + struct 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 + 81 + struct 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 + 89 + struct 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 + 97 + struct als_input_report { 98 + struct common_input_property common_property; 99 + /* values specific to this sensor */ 100 + int illuminance_value; 101 + } __packed; 102 + 103 + int get_report_descriptor(int sensor_idx, u8 rep_desc[]); 104 + u32 get_descr_sz(int sensor_idx, int descriptor_name); 105 + u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report); 106 + u8 get_input_report(int sensor_idx, int report_id, u8 *input_report, u32 *sensor_virt_addr); 107 + #endif
+645
drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h
··· 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 13 + static const u8 accel3_report_descriptor[] = { 14 + 0x05, 0x20, /* Usage page */ 15 + 0x09, 0x73, /* Motion type Accel 3D */ 16 + 0xA1, 0x00, /* HID Collection (Physical) */ 17 + 18 + //feature reports(xmit/receive) 19 + 0x85, 1, /* HID Report ID */ 20 + 0x05, 0x20, /* HID usage page sensor */ 21 + 0x0A, 0x09, 0x03, /* Sensor property and sensor connection type */ 22 + 0x15, 0, /* HID logical MIN_8(0) */ 23 + 0x25, 2, /* HID logical MAX_8(2) */ 24 + 0x75, 8, /* HID report size(8) */ 25 + 0x95, 1, /* HID report count(1) */ 26 + 0xA1, 0x02, /* HID collection (logical) */ 27 + 0x0A, 0x30, 0x08, /* Sensor property connection type intergated sel*/ 28 + 0x0A, 0x31, 0x08, /* Sensor property connection type attached sel */ 29 + 0x0A, 0x32, 0x08, /* Sensor property connection type external sel */ 30 + 0xB1, 0x00, /* HID feature (Data_Arr_Abs) */ 31 + 0xC0, /* HID end collection */ 32 + 0x0A, 0x16, 0x03, /* HID usage sensor property reporting state */ 33 + 0x15, 0, /* HID logical Min_8(0) */ 34 + 0x25, 5, /* HID logical Max_8(5) */ 35 + 0x75, 8, /* HID report size(8) */ 36 + 0x95, 1, /* HID report count(1) */ 37 + 0xA1, 0x02, /* HID collection(logical) */ 38 + 0x0A, 0x40, 0x08, /* Sensor property report state no events sel */ 39 + 0x0A, 0x41, 0x08, /* Sensor property report state all events sel */ 40 + 0x0A, 0x42, 0x08, /* Sensor property report state threshold events sel */ 41 + 0x0A, 0x43, 0x08, /* Sensor property report state no events wake sel */ 42 + 0x0A, 0x44, 0x08, /* Sensor property report state all events wake sel */ 43 + 0x0A, 0x45, 0x08, /* Sensor property report state threshold events wake sel */ 44 + 0xB1, 0x00, /* HID feature (Data_Arr_Abs) */ 45 + 0xC0, /* HID end collection */ 46 + 0x0A, 0x19, 0x03, /* HID usage sensor property power state */ 47 + 0x15, 0, /* HID logical Min_8(0) */ 48 + 0x25, 5, /* HID logical Max_8(5) */ 49 + 0x75, 8, /* HID report size(8) */ 50 + 0x95, 1, /* HID report count(1) */ 51 + 0xA1, 0x02, /* HID collection(logical) */ 52 + 0x0A, 0x50, 0x08, /* Sensor property power state undefined sel */ 53 + 0x0A, 0x51, 0x08, /* Sensor property power state D0 full power sel */ 54 + 0x0A, 0x52, 0x08, /* Sensor property power state D1 low power sel */ 55 + 0x0A, 0x53, 0x08, /* Sensor property power state D2 standby with wake sel */ 56 + 0x0A, 0x54, 0x08, /* Sensor property power state D3 sleep with wake sel */ 57 + 0x0A, 0x55, 0x08, /* Sensor property power state D4 power off sel */ 58 + 0xB1, 0x00, /* HID feature (Data_Arr_Abs) */ 59 + 0xC0, /* HID end collection */ 60 + 0x0A, 0x01, 0x02, /* HID usage sensor state */ 61 + 0x15, 0, /* HID logical Min_8(0) */ 62 + 0x25, 6, /* HID logical Max_8(6) */ 63 + 0x75, 8, /* HID report size(8) */ 64 + 0x95, 1, /* HID report count(1) */ 65 + 0xA1, 0x02, /* HID collection(logical) */ 66 + 0x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */ 67 + 0x0A, 0x01, 0x08, /* HID usage sensor state ready sel */ 68 + 0x0A, 0x02, 0x08, /* HID usage sensor state not available sel */ 69 + 0x0A, 0x03, 0x08, /* HID usage sensor state no data sel */ 70 + 0x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */ 71 + 0x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */ 72 + 0x0A, 0x06, 0x08, /* HID usage sensor state error sel */ 73 + 0xB1, 0x00, /* HID feature (Data_Arr_Abs) */ 74 + 0xC0, /* HID end collection */ 75 + 0x0A, 0x0E, 0x03, /* HID usage sensor property report interval */ 76 + 0x15, 0, /* HID logical Min_8(0) */ 77 + 0x27, 0xFF, 0xFF, 0xFF, 0xFF, /* HID logical Max_32 */ 78 + 79 + 0x75, 32, /* HID report size(32) */ 80 + 0x95, 1, /* HID report count(1) */ 81 + 0x55, 0, /* HID unit exponent(0) */ 82 + 0xB1, 0x02, /* HID feature (Data_Arr_Abs) */ 83 + 0x0A, 0x52, 0x14, /* Sensor data motion accel and mod change sensitivity ABS) */ 84 + 85 + 0x15, 0, /* HID logical Min_8(0) */ 86 + 0x26, 0xFF, 0xFF, /* HID logical Max_16(0xFF,0xFF) */ 87 + 88 + 0x75, 16, /* HID report size(16) */ 89 + 0x95, 1, /* HID report count(1) */ 90 + 0x55, 0x0E, /* HID unit exponent(0x0E) */ 91 + 0xB1, 0x02, /* HID feature (Data_Arr_Abs) */ 92 + 0x0A, 0x52, 0x24, /* HID usage sensor data (motion accel and mod max) */ 93 + 94 + 0x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */ 95 + 96 + 0x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */ 97 + 98 + 0x75, 16, /* HID report size(16) */ 99 + 0x95, 1, /* HID report count(1) */ 100 + 0x55, 0x0E, /* HID unit exponent(0x0E) */ 101 + 0xB1, 0x02, /* HID feature (Data_Arr_Abs) */ 102 + 0x0A, 0x52, 0x34, /* HID usage sensor data (motion accel and mod min) */ 103 + 104 + 0x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */ 105 + 106 + 0x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */ 107 + 108 + 0x75, 16, /* HID report size(16) */ 109 + 0x95, 1, /* HID report count(1) */ 110 + 0x55, 0x0E, /* HID unit exponent(0x0E) */ 111 + 0xB1, 0x02, /* HID feature (Data_Arr_Abs) */ 112 + 113 + //input report (transmit) 114 + 0x05, 0x20, /* HID usage page sensors */ 115 + 0x0A, 0x01, 0x02, /* HID usage sensor state */ 116 + 0x15, 0, /* HID logical Min_8(0) */ 117 + 0x25, 6, /* HID logical Max_8(6) */ 118 + 0x75, 8, /* HID report size(8) */ 119 + 0x95, 1, /* HID report count (1) */ 120 + 0xA1, 0x02, /* HID end collection (logical) */ 121 + 0x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */ 122 + 0x0A, 0x01, 0x08, /* HID usage sensor state ready sel */ 123 + 0x0A, 0x02, 0x08, /* HID usage sensor state not available sel */ 124 + 0x0A, 0x03, 0x08, /* HID usage sensor state no data sel */ 125 + 0x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */ 126 + 0x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */ 127 + 0x0A, 0x06, 0x08, /* HID usage sensor state error sel */ 128 + 0X81, 0x00, /* HID Input (Data_Arr_Abs) */ 129 + 0xC0, /* HID end collection */ 130 + 0x0A, 0x02, 0x02, /* HID usage sensor event */ 131 + 0x15, 0, /* HID logical Min_8(0) */ 132 + 0x25, 5, /* HID logical Max_8(5) */ 133 + 0x75, 8, /* HID report size(8) */ 134 + 0x95, 1, /* HID report count (1) */ 135 + 0xA1, 0x02, /* HID end collection (logical) */ 136 + 0x0A, 0x10, 0x08, /* HID usage sensor event unknown sel */ 137 + 0x0A, 0x11, 0x08, /* HID usage sensor event state changed sel */ 138 + 0x0A, 0x12, 0x08, /* HID usage sensor event property changed sel */ 139 + 0x0A, 0x13, 0x08, /* HID usage sensor event data updated sel */ 140 + 0x0A, 0x14, 0x08, /* HID usage sensor event poll response sel */ 141 + 0x0A, 0x15, 0x08, /* HID usage sensor event change sensitivity sel */ 142 + 0X81, 0x00, /* HID Input (Data_Arr_Abs) */ 143 + 0xC0, /* HID end collection */ 144 + 0x0A, 0x53, 0x04, /* HID usage sensor data motion Acceleration X axis */ 145 + 0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */ 146 + 147 + 0x27, 0xFF, 0xff, 0XFF, 0XFF, /* HID logical Max_32 */ 148 + 149 + 0x75, 32, /* HID report size(32) */ 150 + 0x95, 1, /* HID report count (1) */ 151 + 0x55, 0x0E, /* HID unit exponent(0x0E) */ 152 + 0X81, 0x02, /* HID Input (Data_Arr_Abs) */ 153 + 0x0A, 0x54, 0x04, /* HID usage sensor data motion Acceleration Y axis */ 154 + 0x17, 0X00, 0X00, 0x01, 0x80, /* HID logical Min_32 */ 155 + 156 + 0x27, 0xFF, 0xFF, 0XFF, 0XFF, /* HID logical Max_32 */ 157 + 158 + 0x75, 32, /* HID report size(32) */ 159 + 0x95, 1, /* HID report count (1) */ 160 + 0x55, 0x0E, /* HID unit exponent(0x0E) */ 161 + 0X81, 0x02, /* HID Input (Data_Arr_Abs) */ 162 + 0x0A, 0x55, 0x04, /* HID usage sensor data motion Acceleration Z axis */ 163 + 0x17, 0X00, 0X00, 0x01, 0x80, /* HID logical Min_32 */ 164 + 165 + 0x27, 0XFF, 0XFF, 0xFF, 0x7F, /* HID logical Max_32 */ 166 + 167 + 0x75, 32, /* HID report size(32) */ 168 + 0x95, 1, /* HID report count (1) */ 169 + 0x55, 0x0E, /* HID unit exponent(0x0E) */ 170 + 0X81, 0x02, /* HID Input (Data_Arr_Abs) */ 171 + 172 + 0x0A, 0x51, 0x04, /* HID usage sensor data motion state */ 173 + 0x15, 0, /* HID logical Min_8(0) False = Still*/ 174 + 0x25, 1, /* HID logical Min_8(1) True = In motion */ 175 + 0x75, 8, /* HID report size(8) */ 176 + 0x95, 1, /* HID report count (1) */ 177 + 0X81, 0x02, /* HID Input (Data_Arr_Abs) */ 178 + 0xC0 /* HID end collection */ 179 + }; 180 + 181 + const u8 gyro3_report_descriptor[] = { 182 + 0x05, 0x20, /* Usage page */ 183 + 0x09, 0x76, /* Motion type Gyro3D */ 184 + 0xA1, 0x00, /* HID Collection (Physical) */ 185 + 186 + 0x85, 2, /* HID Report ID */ 187 + 0x05, 0x20, /* HID usage page sensor */ 188 + 0x0A, 0x09, 0x03, /* Sensor property and sensor connection type */ 189 + 0x15, 0, /* HID logical MIN_8(0) */ 190 + 0x25, 2, /* HID logical MAX_8(2) */ 191 + 0x75, 8, /* HID report size(8) */ 192 + 0x95, 1, /* HID report count(1) */ 193 + 0xA1, 0x02, /* HID collection (logical) */ 194 + 0x0A, 0x30, 0x08, /* Sensor property connection type intergated sel */ 195 + 0x0A, 0x31, 0x08, /* Sensor property connection type attached sel */ 196 + 0x0A, 0x32, 0x08, /* Sensor property connection type external sel */ 197 + 0xB1, 0x00, /* HID feature (Data_Arr_Abs) */ 198 + 0xC0, /* HID end collection */ 199 + 0x0A, 0x16, 0x03, /* HID usage sensor property reporting state */ 200 + 0x15, 0, /* HID logical Min_8(0) */ 201 + 0x25, 5, /* HID logical Max_8(5) */ 202 + 0x75, 8, /* HID report size(8) */ 203 + 0x95, 1, /* HID report count(1) */ 204 + 0xA1, 0x02, /* HID collection(logical) */ 205 + 0x0A, 0x40, 0x08, /* Sensor reporting state no events sel */ 206 + 0x0A, 0x41, 0x08, /* Sensor reporting state all events sel */ 207 + 0x0A, 0x42, 0x08, /* Sensor reporting state threshold events sel */ 208 + 0x0A, 0x43, 0x08, /* Sensor reporting state no events wake sel */ 209 + 0x0A, 0x44, 0x08, /* Sensor reporting state all events wake sel */ 210 + 0x0A, 0x45, 0x08, /* Sensor reporting state threshold events wake sel */ 211 + 0xB1, 0x00, /* HID feature (Data_Arr_Abs) */ 212 + 0xC0, /* HID end collection */ 213 + 0x0A, 0x19, 0x03, /* HID usage sensor property power state */ 214 + 0x15, 0, /* HID logical Min_8(0) */ 215 + 0x25, 5, /* HID logical Max_8(5) */ 216 + 0x75, 8, /* HID report size(8) */ 217 + 0x95, 1, /* HID report count(1) */ 218 + 0xA1, 0x02, /* HID collection(logical) */ 219 + 0x0A, 0x50, 0x08, /* Sensor power state undefined sel */ 220 + 0x0A, 0x51, 0x08, /* Sensor power state D0 full power sel */ 221 + 0x0A, 0x52, 0x08, /* Sensor power state D1 low power sel */ 222 + 0x0A, 0x53, 0x08, /* Sensor power state D2 standby with wake sel */ 223 + 0x0A, 0x54, 0x08, /* Sensor power state D3 sleep with wake sel */ 224 + 0x0A, 0x55, 0x08, /* Sensor power state D4 power off sel */ 225 + 0xB1, 0x00, /* HID feature (Data_Arr_Abs) */ 226 + 0xC0, /* HID end collection */ 227 + 0x0A, 0x01, 0x02, /* HID usage sensor state */ 228 + 0x15, 0, /* HID logical Min_8(0) */ 229 + 0x25, 6, /* HID logical Max_8(6) */ 230 + 0x75, 8, /* HID report size(8) */ 231 + 0x95, 1, /* HID report count(1) */ 232 + 0xA1, 0x02, /* HID collection(logical) */ 233 + 0x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */ 234 + 0x0A, 0x01, 0x08, /* HID usage sensor state ready sel */ 235 + 0x0A, 0x02, 0x08, /* HID usage sensor state not available sel */ 236 + 0x0A, 0x03, 0x08, /* HID usage sensor state no data sel */ 237 + 0x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */ 238 + 0x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */ 239 + 0x0A, 0x06, 0x08, /* HID usage sensor state error sel */ 240 + 0xB1, 0x00, /* HID feature (Data_Arr_Abs) */ 241 + 0xC0, /* HID end collection */ 242 + 0x0A, 0x0E, 0x03, /* HID usage sensor property report interval */ 243 + 0x15, 0, /* HID logical Min_8(0) */ 244 + 0x27, 0xFF, 0xFF, 0xFF, 0xFF, /* HID logical Max_32 */ 245 + 246 + 0x75, 32, /* HID report size(32) */ 247 + 0x95, 1, /* HID report count(1) */ 248 + 0x55, 0, /* HID unit exponent(0) */ 249 + 0xB1, 0x02, /* HID feature (Data_Arr_Abs) */ 250 + 0x0A, 0x56, 0x14, /* Angular velocity and mod change sensitivity ABS)*/ 251 + 252 + 0x15, 0, /* HID logical Min_8(0) */ 253 + 0x26, 0xFF, 0xFF, /* HID logical Max_16(0xFF,0xFF) */ 254 + 255 + 0x75, 16, /* HID report size(16) */ 256 + 0x95, 1, /* HID report count(1) */ 257 + 0x55, 0x0E, /* HID unit exponent(0x0E) */ 258 + 0xB1, 0x02, /* HID feature (Data_Arr_Abs) */ 259 + 0x0A, 0x56, 0x24, /* Sensor data (motion angular velocity and mod max) */ 260 + 261 + 0x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */ 262 + 263 + 0x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */ 264 + 265 + 0x75, 16, /* HID report size(16) */ 266 + 0x95, 1, /* HID report count(1) */ 267 + 0x55, 0x0E, /* HID unit exponent(0x0E) */ 268 + 0xB1, 0x02, /* HID feature (Data_Arr_Abs) */ 269 + 0x0A, 0x56, 0x34, /* HID usage sensor data (motion accel and mod min) */ 270 + 271 + 0x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */ 272 + 273 + 0x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */ 274 + 275 + 0x75, 16, /* HID report size(16) */ 276 + 0x95, 1, /* HID report count(1) */ 277 + 0x55, 0x0E, /* HID unit exponent(0x0E) */ 278 + 0xB1, 0x02, /* HID feature (Data_Arr_Abs) */ 279 + 280 + //Input reports(transmit) 281 + 0x05, 0x20, /* HID usage page sensors */ 282 + 0x0A, 0x01, 0x02, /* HID usage sensor state */ 283 + 0x15, 0, /* HID logical Min_8(0) */ 284 + 0x25, 6, /* HID logical Max_8(6) */ 285 + 0x75, 8, /* HID report size(8) */ 286 + 0x95, 1, /* HID report count (1) */ 287 + 0xA1, 0x02, /* HID end collection (logical) */ 288 + 0x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */ 289 + 0x0A, 0x01, 0x08, /* HID usage sensor state ready sel */ 290 + 0x0A, 0x02, 0x08, /* HID usage sensor state not available sel */ 291 + 0x0A, 0x03, 0x08, /* HID usage sensor state no data sel */ 292 + 0x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */ 293 + 0x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */ 294 + 0x0A, 0x06, 0x08, /* HID usage sensor state error sel */ 295 + 0X81, 0x00, /* HID Input (Data_Arr_Abs) */ 296 + 0xC0, /* HID end collection */ 297 + 0x0A, 0x02, 0x02, /* HID usage sensor event */ 298 + 0x15, 0, /* HID logical Min_8(0) */ 299 + 0x25, 5, /* HID logical Max_8(5) */ 300 + 0x75, 8, /* HID report size(8) */ 301 + 0x95, 1, /* HID report count (1) */ 302 + 0xA1, 0x02, /* HID end collection (logical) */ 303 + 0x0A, 0x10, 0x08, /* HID usage sensor event unknown sel */ 304 + 0x0A, 0x11, 0x08, /* HID usage sensor event state changed sel */ 305 + 0x0A, 0x12, 0x08, /* HID usage sensor event property changed sel */ 306 + 0x0A, 0x13, 0x08, /* HID usage sensor event data updated sel */ 307 + 0x0A, 0x14, 0x08, /* HID usage sensor event poll response sel */ 308 + 0x0A, 0x15, 0x08, /* HID usage sensor event change sensitivity sel */ 309 + 0X81, 0x00, /* HID Input (Data_Arr_Abs) */ 310 + 0xC0, /* HID end collection */ 311 + 0x0A, 0x57, 0x04, /* Sensor data motion Angular velocity X axis */ 312 + 0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */ 313 + 314 + 0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */ 315 + 316 + 0x75, 32, /* HID report size(32) */ 317 + 0x95, 1, /* HID report count (1) */ 318 + 0x55, 0x0E, /* HID unit exponent(0x0E) */ 319 + 0X81, 0x02, /* HID Input (Data_Arr_Abs) */ 320 + 0x0A, 0x58, 0x04, /* Sensor data motion Angular velocity Y axis */ 321 + 0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */ 322 + 323 + 0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */ 324 + 325 + 0x75, 32, /* HID report size(32) */ 326 + 0x95, 1, /* HID report count (1) */ 327 + 0x55, 0x0E, /* HID unit exponent(0x0E) */ 328 + 0X81, 0x02, /* HID Input (Data_Arr_Abs) */ 329 + 0x0A, 0x59, 0x04, /* Sensor data motion Angular velocity Z axis */ 330 + 0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */ 331 + 332 + 0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */ 333 + 334 + 0x75, 32, /* HID report size(32) */ 335 + 0x95, 1, /* HID report count (1) */ 336 + 0x55, 0x0E, /* HID unit exponent(0x0E) */ 337 + 0X81, 0x02, /* HID Input (Data_Arr_Abs) */ 338 + 339 + 0xC0, /* HID end collection */ 340 + }; 341 + 342 + const u8 comp3_report_descriptor[] = { 343 + 0x05, 0x20, /* Usage page */ 344 + 0x09, 0x83, /* Motion type Orientation compass 3D */ 345 + 0xA1, 0x00, /* HID Collection (Physical) */ 346 + 347 + 0x85, 3, /* HID Report ID */ 348 + 0x05, 0x20, /* HID usage page sensor */ 349 + 0x0A, 0x09, 0x03, /* Sensor property and sensor connection type */ 350 + 0x15, 0, /* HID logical MIN_8(0) */ 351 + 0x25, 2, /* HID logical MAX_8(2) */ 352 + 0x75, 8, /* HID report size(8) */ 353 + 0x95, 1, /* HID report count(1) */ 354 + 0xA1, 0x02, /* HID collection (logical) */ 355 + 0x0A, 0x30, 0x08, /* Sensor property connection type intergated sel */ 356 + 0x0A, 0x31, 0x08, /* Sensor property connection type attached sel */ 357 + 0x0A, 0x32, 0x08, /* Sensor property connection type external sel */ 358 + 0xB1, 0x00, /* HID feature (Data_Arr_Abs) */ 359 + 0xC0, /* HID end collection */ 360 + 0x0A, 0x16, 0x03, /* HID usage sensor property reporting state */ 361 + 0x15, 0, /* HID logical Min_8(0) */ 362 + 0x25, 5, /* HID logical Max_8(5) */ 363 + 0x75, 8, /* HID report size(8) */ 364 + 0x95, 1, /* HID report count(1) */ 365 + 0xA1, 0x02, /* HID collection(logical) */ 366 + 0x0A, 0x40, 0x08, /* Sensor reporting state no events sel */ 367 + 0x0A, 0x41, 0x08, /* Sensor reporting state all events sel */ 368 + 0x0A, 0x42, 0x08, /* Sensor reporting state threshold events sel */ 369 + 0x0A, 0x43, 0x08, /* Sensor reporting state no events wake sel */ 370 + 0x0A, 0x44, 0x08, /* Sensor reporting state all events wake sel */ 371 + 0x0A, 0x45, 0x08, /* Sensor reporting state threshold events wake sel */ 372 + 0xB1, 0x00, /* HID feature (Data_Arr_Abs) */ 373 + 0xC0, /* HID end collection */ 374 + 0x0A, 0x19, 0x03, /* HID usage sensor property power state */ 375 + 0x15, 0, /* HID logical Min_8(0) */ 376 + 0x25, 5, /* HID logical Max_8(5) */ 377 + 0x75, 8, /* HID report size(8) */ 378 + 0x95, 1, /* HID report count(1) */ 379 + 0xA1, 0x02, /* HID collection(logical) */ 380 + 0x0A, 0x50, 0x08, /* Sensor power state undefined sel */ 381 + 0x0A, 0x51, 0x08, /* Sensor power state D0 full power sel */ 382 + 0x0A, 0x52, 0x08, /* Sensor power state D1 low power sel */ 383 + 0x0A, 0x53, 0x08, /* Sensor power state D2 standby with wake sel */ 384 + 0x0A, 0x54, 0x08, /* Sensor power state D3 sleep with wake sel */ 385 + 0x0A, 0x55, 0x08, /* Sensor power state D4 power off sel */ 386 + 0xB1, 0x00, /* HID feature (Data_Arr_Abs) */ 387 + 0xC0, /* HID end collection */ 388 + 0x0A, 0x01, 0x02, /* HID usage sensor state */ 389 + 0x15, 0, /* HID logical Min_8(0) */ 390 + 0x25, 6, /* HID logical Max_8(6) */ 391 + 0x75, 8, /* HID report size(8) */ 392 + 0x95, 1, /* HID report count(1) */ 393 + 0xA1, 0x02, /* HID collection(logical) */ 394 + 0x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */ 395 + 0x0A, 0x01, 0x08, /* HID usage sensor state ready sel */ 396 + 0x0A, 0x02, 0x08, /* HID usage sensor state not available sel */ 397 + 0x0A, 0x03, 0x08, /* HID usage sensor state no data sel */ 398 + 0x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */ 399 + 0x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */ 400 + 0x0A, 0x06, 0x08, /* HID usage sensor state error sel */ 401 + 0xB1, 0x00, /* HID feature (Data_Arr_Abs) */ 402 + 0xC0, /* HID end collection */ 403 + 0x0A, 0x0E, 0x03, /* HID usage sensor property report interval */ 404 + 0x15, 0, /* HID logical Min_8(0) */ 405 + 0x27, 0xFF, 0xFF, 0xFF, 0xFF, /* HID logical Max_32 */ 406 + 0x75, 32, /* HID report size(32) */ 407 + 0x95, 1, /* HID report count(1) */ 408 + 0x55, 0, /* HID unit exponent(0) */ 409 + 0xB1, 0x02, /* HID feature (Data_Arr_Abs) */ 410 + 0x0A, 0x71, 0x14, /* Orientation and mod change sensitivity ABS)*/ 411 + 0x15, 0, /* HID logical Min_8(0) */ 412 + 0x26, 0xFF, 0xFF, /* HID logical Max_16(0xFF,0xFF) */ 413 + 0x75, 16, /* HID report size(16) */ 414 + 0x95, 1, /* HID report count(1) */ 415 + 0x55, 0x0E, /* HID unit exponent(0x0E) */ 416 + 0xB1, 0x02, /* HID feature (Data_Arr_Abs) */ 417 + 0x0A, 0x71, 0x24, /* Sensor data (motion orientation and mod max) */ 418 + 0x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */ 419 + 0x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */ 420 + 0x75, 16, /* HID report size(16) */ 421 + 0x95, 1, /* HID report count(1) */ 422 + 0x55, 0x0F, /* HID unit exponent(0x0F) */ 423 + 0xB1, 0x02, /* HID feature (Data_Arr_Abs) */ 424 + 0x0A, 0x71, 0x34, /* Sensor data (motion orientation and mod min) */ 425 + 0x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */ 426 + 0x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */ 427 + 0x75, 16, /* HID report size(16) */ 428 + 0x95, 1, /* HID report count(1) */ 429 + 0x55, 0x0F, /* HID unit exponent(0x0F) */ 430 + 0xB1, 0x02, /* HID feature (Data_Arr_Abs) */ 431 + 0x0A, 0x84, 0x14, /* Maganetic flux and change sensitivity ABS) */ 432 + 0x15, 0, /* HID logical Min_8(0) */ 433 + 0x26, 0xFF, 0xFF, /* HID logical Max_16(0xFF,0xFF) */ 434 + 0x75, 16, /* HID report size(16) */ 435 + 0x95, 1, /* HID report count(1) */ 436 + 0x55, 0x0E, /* HID unit exponent(0x0E) */ 437 + 0xB1, 0x02, /* HID feature (Data_Arr_Abs) */ 438 + 0x0A, 0x84, 0x24, /* Maganetic flux and mod change sensitivity Max) */ 439 + 0x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */ 440 + 0x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */ 441 + 0x75, 16, /* HID report size(16) */ 442 + 0x95, 1, /* HID report count(1) */ 443 + 0x55, 0x0F, /* HID unit exponent(0x0F) */ 444 + 0xB1, 0x02, /* HID feature (Data_Arr_Abs) */ 445 + 0x0A, 0x84, 0x34, /* Maganetic flux and mod change sensitivity Min */ 446 + 0x16, 0x01, 0x80, /* HID logical Min_16(0x01,0x80) */ 447 + 0x26, 0xFF, 0x7F, /* HID logical Max_16(0xFF,0x7F) */ 448 + 0x75, 16, /* HID report size(16) */ 449 + 0x95, 1, /* HID report count(1) */ 450 + 0x55, 0x0F, /* HID unit exponent(0x0F) */ 451 + 0xB1, 0x02, /* HID feature (Data_Arr_Abs) */ 452 + 453 + //Input reports(transmit) 454 + 0x05, 0x20, /* HID usage page sensors */ 455 + 0x0A, 0x01, 0x02, /* HID usage sensor state */ 456 + 0x15, 0, /* HID logical Min_8(0) */ 457 + 0x25, 6, /* HID logical Max_8(6) */ 458 + 0x75, 8, /* HID report size(8) */ 459 + 0x95, 1, /* HID report count (1) */ 460 + 0xA1, 0x02, /* HID end collection (logical) */ 461 + 0x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */ 462 + 0x0A, 0x01, 0x08, /* HID usage sensor state ready sel */ 463 + 0x0A, 0x02, 0x08, /* HID usage sensor state not available sel */ 464 + 0x0A, 0x03, 0x08, /* HID usage sensor state no data sel */ 465 + 0x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */ 466 + 0x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */ 467 + 0x0A, 0x06, 0x08, /* HID usage sensor state error sel */ 468 + 0X81, 0x00, /* HID Input (Data_Arr_Abs) */ 469 + 0xC0, /* HID end collection */ 470 + 0x0A, 0x02, 0x02, /* HID usage sensor event */ 471 + 0x15, 0, /* HID logical Min_8(0) */ 472 + 0x25, 5, /* HID logical Max_8(5) */ 473 + 0x75, 8, /* HID report size(8) */ 474 + 0x95, 1, /* HID report count (1) */ 475 + 0xA1, 0x02, /* HID end collection (logical) */ 476 + 0x0A, 0x10, 0x08, /* HID usage sensor event unknown sel */ 477 + 0x0A, 0x11, 0x08, /* HID usage sensor event state changed sel */ 478 + 0x0A, 0x12, 0x08, /* HID usage sensor event property changed sel */ 479 + 0x0A, 0x13, 0x08, /* HID usage sensor event data updated sel */ 480 + 0x0A, 0x14, 0x08, /* HID usage sensor event poll response sel */ 481 + 0x0A, 0x15, 0x08, /* HID usage sensor event change sensitivity sel */ 482 + 0X81, 0x00, /* HID Input (Data_Arr_Abs) */ 483 + 0xC0, /* HID end collection */ 484 + 0x0A, 0x85, 0x04, /* Sensor data orientation magnetic flux X axis */ 485 + 0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */ 486 + 0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */ 487 + 0x75, 32, /* HID report size(32) */ 488 + 0x95, 1, /* HID report count (1) */ 489 + 0x55, 0x0D, /* HID unit exponent(0x0D) */ 490 + 0X81, 0x02, /* HID Input (Data_Arr_Abs) */ 491 + 0x0A, 0x86, 0x04, /* Sensor data orientation magnetic flux Y axis */ 492 + 0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */ 493 + 0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */ 494 + 0x75, 32, /* HID report size(32) */ 495 + 0x95, 1, /* HID report count (1) */ 496 + 0x55, 0x0D, /* HID unit exponent(0x0D) */ 497 + 0X81, 0x02, /* HID Input (Data_Arr_Abs) */ 498 + 0x0A, 0x87, 0x04, /* Sensor data orientation magnetic flux Z axis */ 499 + 0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */ 500 + 0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */ 501 + 0x75, 32, /* HID report size(32) */ 502 + 0x95, 1, /* HID report count (1) */ 503 + 0x55, 0x0D, /* HID unit exponent(0x0D) */ 504 + 0X81, 0x02, /* HID Input (Data_Arr_Abs) */ 505 + 0x0A, 0x88, 0x04, /* Sensor data orientation magnetometer accuracy */ 506 + 0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */ 507 + 0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */ 508 + 0x75, 32, /* HID report size(32) */ 509 + 0x95, 1, /* HID report count (1) */ 510 + 0X81, 0x02, /* HID Input (Data_Arr_Abs) */ 511 + 0xC0 /* HID end collection */ 512 + }; 513 + 514 + const u8 als_report_descriptor[] = { 515 + 0x05, 0x20, /* HID usage page sensor */ 516 + 0x09, 0x41, /* HID usage sensor type Ambientlight */ 517 + 0xA1, 0x00, /* HID Collection (Physical) */ 518 + 519 + //feature reports(xmit/receive)// 520 + 0x85, 4, /* HID Report ID */ 521 + 0x05, 0x20, /* HID usage page sensor */ 522 + 0x0A, 0x09, 0x03, /* Sensor property and sensor connection type */ 523 + 0x15, 0, /* HID logical MIN_8(0) */ 524 + 0x25, 2, /* HID logical MAX_8(2) */ 525 + 0x75, 8, /* HID report size(8) */ 526 + 0x95, 1, /* HID report count(1) */ 527 + 0xA1, 0x02, /* HID collection (logical) */ 528 + 0x0A, 0x30, 0x08, /* Sensor property connection type intergated sel */ 529 + 0x0A, 0x31, 0x08, /* Sensor property connection type attached sel */ 530 + 0x0A, 0x32, 0x08, /* Sensor property connection type external sel */ 531 + 0xB1, 0x00, /* HID feature (Data_Arr_Abs) */ 532 + 0xC0, /* HID end collection */ 533 + 0x0A, 0x16, 0x03, /* HID usage sensor property reporting state */ 534 + 0x15, 0, /* HID logical Min_8(0) */ 535 + 0x25, 5, /* HID logical Max_8(5) */ 536 + 0x75, 8, /* HID report size(8) */ 537 + 0x95, 1, /* HID report count(1) */ 538 + 0xA1, 0x02, /* HID collection(logical) */ 539 + 0x0A, 0x40, 0x08, /* Sensor reporting state no events sel */ 540 + 0x0A, 0x41, 0x08, /* Sensor reporting state all events sel */ 541 + 0x0A, 0x42, 0x08, /* Sensor reporting state threshold events sel */ 542 + 0x0A, 0x43, 0x08, /* Sensor reporting state no events wake sel */ 543 + 0x0A, 0x44, 0x08, /* Sensor reporting state all events wake sel */ 544 + 0x0A, 0x45, 0x08, /* Sensor reporting state threshold events wake sel */ 545 + 0xB1, 0x00, /* HID feature (Data_Arr_Abs) */ 546 + 0xC0, /* HID end collection */ 547 + 0x0A, 0x19, 0x03, /* HID usage sensor property power state */ 548 + 0x15, 0, /* HID logical Min_8(0) */ 549 + 0x25, 5, /* HID logical Max_8(5) */ 550 + 0x75, 8, /* HID report size(8) */ 551 + 0x95, 1, /* HID report count(1) */ 552 + 0xA1, 0x02, /* HID collection(logical) */ 553 + 0x0A, 0x50, 0x08, /* Sensor power state undefined sel */ 554 + 0x0A, 0x51, 0x08, /* Sensor power state D0 full power sel */ 555 + 0x0A, 0x52, 0x08, /* Sensor power state D1 low power sel */ 556 + 0x0A, 0x53, 0x08, /* Sensor power state D2 standby with wake sel */ 557 + 0x0A, 0x54, 0x08, /* Sensor power state D3 sleep with wake sel */ 558 + 0x0A, 0x55, 0x08, /* Sensor power state D4 power off sel */ 559 + 0xB1, 0x00, /* HID feature (Data_Arr_Abs) */ 560 + 0xC0, /* HID end collection */ 561 + 0x0A, 0x01, 0x02, /* HID usage sensor state */ 562 + 0x15, 0, /* HID logical Min_8(0) */ 563 + 0x25, 6, /* HID logical Max_8(6) */ 564 + 0x75, 8, /* HID report size(8) */ 565 + 0x95, 1, /* HID report count(1) */ 566 + 0xA1, 0x02, /* HID collection(logical) */ 567 + 0x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */ 568 + 0x0A, 0x01, 0x08, /* HID usage sensor state ready sel */ 569 + 0x0A, 0x02, 0x08, /* HID usage sensor state not available sel */ 570 + 0x0A, 0x03, 0x08, /* HID usage sensor state no data sel */ 571 + 0x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */ 572 + 0x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */ 573 + 0x0A, 0x06, 0x08, /* HID usage sensor state error sel */ 574 + 0xB1, 0x00, /* HID feature (Data_Arr_Abs) */ 575 + 0xC0, /* HID end collection */ 576 + 0x0A, 0x0E, 0x03, /* HID usage sensor property report interval */ 577 + 0x15, 0, /* HID logical Min_8(0) */ 578 + 0x27, 0xFF, 0xFF, 0xFF, 0xFF, /* HID logical Max_32 */ 579 + 0x75, 32, /* HID report size(32) */ 580 + 0x95, 1, /* HID report count(1) */ 581 + 0x55, 0, /* HID unit exponent(0) */ 582 + 0xB1, 0x02, /* HID feature (Data_Arr_Abs) */ 583 + 0x0A, 0xD1, 0xE4, /* Light illuminance and sensitivity REL PCT) */ 584 + 0x15, 0, /* HID logical Min_8(0) */ 585 + 0x26, 0x10, 0x27, /* HID logical Max_16(0x10,0x27) */ 586 + 0x75, 16, /* HID report size(16) */ 587 + 0x95, 1, /* HID report count(1) */ 588 + 0x55, 0x0E, /* HID unit exponent(0x0E) */ 589 + 0xB1, 0x02, /* HID feature (Data_Arr_Abs) */ 590 + 0x0A, 0xD1, 0x24, /* Sensor data (Light illuminance and mod max) */ 591 + 0x15, 0, /* HID logical Min_8(0) */ 592 + 0x26, 0xFF, 0xFF, /* HID logical Max_16(0xFF,0xFF) */ 593 + 0x75, 16, /* HID report size(16) */ 594 + 0x95, 1, /* HID report count(1) */ 595 + 0x55, 0x0F, /* HID unit exponent(0x0F) */ 596 + 0xB1, 0x02, /* HID feature (Data_Arr_Abs) */ 597 + 0x0A, 0xD1, 0x34, /* Sensor data (Light illuminance and mod min) */ 598 + 0x15, 0, /* HID logical Min_8(0) */ 599 + 0x26, 0xFF, 0xFF, /* HID logical Max_16(0xFF,0xFF) */ 600 + 0x75, 16, /* HID report size(16) */ 601 + 0x95, 1, /* HID report count(1) */ 602 + 0x55, 0x0F, /* HID unit exponent(0x0F) */ 603 + 0xB1, 0x02, /* HID feature (Data_Arr_Abs) */ 604 + 605 + //Input reports (transmit) 606 + 0x05, 0x20, /* HID usage page sensors */ 607 + 0x0A, 0x01, 0x02, /* HID usage sensor state */ 608 + 0x15, 0, /* HID logical Min_8(0) */ 609 + 0x25, 6, /* HID logical Max_8(6) */ 610 + 0x75, 8, /* HID report size(8) */ 611 + 0x95, 1, /* HID report count (1) */ 612 + 0xA1, 0x02, /* HID end collection (logical) */ 613 + 0x0A, 0x00, 0x08, /* HID usage sensor state unknown sel */ 614 + 0x0A, 0x01, 0x08, /* HID usage sensor state ready sel */ 615 + 0x0A, 0x02, 0x08, /* HID usage sensor state not available sel */ 616 + 0x0A, 0x03, 0x08, /* HID usage sensor state no data sel */ 617 + 0x0A, 0x04, 0x08, /* HID usage sensor state initializing sel */ 618 + 0x0A, 0x05, 0x08, /* HID usage sensor state access denied sel */ 619 + 0x0A, 0x06, 0x08, /* HID usage sensor state error sel */ 620 + 0X81, 0x00, /* HID Input (Data_Arr_Abs) */ 621 + 0xC0, /* HID end collection */ 622 + 0x0A, 0x02, 0x02, /* HID usage sensor event */ 623 + 0x15, 0, /* HID logical Min_8(0) */ 624 + 0x25, 5, /* HID logical Max_8(5) */ 625 + 0x75, 8, /* HID report size(8) */ 626 + 0x95, 1, /* HID report count (1) */ 627 + 0xA1, 0x02, /* HID end collection (logical) */ 628 + 0x0A, 0x10, 0x08, /* HID usage sensor event unknown sel */ 629 + 0x0A, 0x11, 0x08, /* HID usage sensor event state changed sel */ 630 + 0x0A, 0x12, 0x08, /* HID usage sensor event property changed sel */ 631 + 0x0A, 0x13, 0x08, /* HID usage sensor event data updated sel */ 632 + 0x0A, 0x14, 0x08, /* HID usage sensor event poll response sel */ 633 + 0x0A, 0x15, 0x08, /* HID usage sensor event change sensitivity sel */ 634 + 0X81, 0x00, /* HID Input (Data_Arr_Abs) */ 635 + 0xC0, /* HID end collection */ 636 + 0x0A, 0xD1, 0x04, /* HID usage sensor data light illuminance */ 637 + 0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */ 638 + 0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */ 639 + 0x55, 0x0F, /* HID unit exponent(0x0F) */ 640 + 0x75, 32, /* HID report size(32) */ 641 + 0x95, 1, /* HID report count (1) */ 642 + 0X81, 0x02, /* HID Input (Data_Arr_Abs) */ 643 + 0xC0 /* HID end collection */ 644 + }; 645 + #endif
+109 -14
drivers/hid/hid-asus.c
··· 48 48 #define INPUT_REPORT_ID 0x5d 49 49 #define FEATURE_KBD_REPORT_ID 0x5a 50 50 #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 54 #define SUPPORT_KBD_BACKLIGHT BIT(0) 53 55 ··· 82 80 #define QUIRK_T101HA_DOCK BIT(9) 83 81 #define QUIRK_T90CHI BIT(10) 84 82 #define QUIRK_MEDION_E1239T BIT(11) 83 + #define QUIRK_ROG_NKEY_KEYBOARD BIT(12) 85 84 86 85 #define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \ 87 86 QUIRK_NO_INIT_REPORTS | \ ··· 335 332 if (drvdata->quirks & QUIRK_MEDION_E1239T) 336 333 return asus_e1239t_event(drvdata, data, size); 337 334 335 + if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD) { 336 + /* 337 + * Skip these report ID, the device emits a continuous stream associated 338 + * with the AURA mode it is in which looks like an 'echo'. 339 + */ 340 + if (report->id == FEATURE_KBD_LED_REPORT_ID1 || 341 + report->id == FEATURE_KBD_LED_REPORT_ID2) { 342 + return -1; 343 + /* Additional report filtering */ 344 + } else if (report->id == FEATURE_KBD_REPORT_ID) { 345 + /* 346 + * G14 and G15 send these codes on some keypresses with no 347 + * discernable reason for doing so. We'll filter them out to avoid 348 + * unmapped warning messages later. 349 + */ 350 + if (data[1] == 0xea || data[1] == 0xec || data[1] == 0x02 || 351 + data[1] == 0x8a || data[1] == 0x9e) { 352 + return -1; 353 + } 354 + } 355 + } 356 + 338 357 return 0; 339 358 } 340 359 ··· 369 344 if (!dmabuf) 370 345 return -ENOMEM; 371 346 372 - ret = hid_hw_raw_request(hdev, FEATURE_KBD_REPORT_ID, dmabuf, 347 + /* 348 + * The report ID should be set from the incoming buffer due to LED and key 349 + * interfaces having different pages 350 + */ 351 + ret = hid_hw_raw_request(hdev, buf[0], dmabuf, 373 352 buf_size, HID_FEATURE_REPORT, 374 353 HID_REQ_SET_REPORT); 375 354 kfree(dmabuf); ··· 423 394 *kbd_func = readbuf[6]; 424 395 425 396 kfree(readbuf); 397 + return ret; 398 + } 399 + 400 + static int rog_nkey_led_init(struct hid_device *hdev) 401 + { 402 + u8 buf_init_start[] = { FEATURE_KBD_LED_REPORT_ID1, 0xB9 }; 403 + u8 buf_init2[] = { FEATURE_KBD_LED_REPORT_ID1, 0x41, 0x53, 0x55, 0x53, 0x20, 404 + 0x54, 0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 }; 405 + u8 buf_init3[] = { FEATURE_KBD_LED_REPORT_ID1, 406 + 0x05, 0x20, 0x31, 0x00, 0x08 }; 407 + int ret; 408 + 409 + hid_info(hdev, "Asus initialise N-KEY Device"); 410 + /* The first message is an init start */ 411 + ret = asus_kbd_set_report(hdev, buf_init_start, sizeof(buf_init_start)); 412 + if (ret < 0) { 413 + hid_warn(hdev, "Asus failed to send init start command: %d\n", ret); 414 + return ret; 415 + } 416 + /* Followed by a string */ 417 + ret = asus_kbd_set_report(hdev, buf_init2, sizeof(buf_init2)); 418 + if (ret < 0) { 419 + hid_warn(hdev, "Asus failed to send init command 1.0: %d\n", ret); 420 + return ret; 421 + } 422 + /* Followed by a string */ 423 + ret = asus_kbd_set_report(hdev, buf_init3, sizeof(buf_init3)); 424 + if (ret < 0) { 425 + hid_warn(hdev, "Asus failed to send init command 1.1: %d\n", ret); 426 + return ret; 427 + } 428 + 429 + /* begin second report ID with same data */ 430 + buf_init2[0] = FEATURE_KBD_LED_REPORT_ID2; 431 + buf_init3[0] = FEATURE_KBD_LED_REPORT_ID2; 432 + 433 + ret = asus_kbd_set_report(hdev, buf_init2, sizeof(buf_init2)); 434 + if (ret < 0) { 435 + hid_warn(hdev, "Asus failed to send init command 2.0: %d\n", ret); 436 + return ret; 437 + } 438 + ret = asus_kbd_set_report(hdev, buf_init3, sizeof(buf_init3)); 439 + if (ret < 0) 440 + hid_warn(hdev, "Asus failed to send init command 2.1: %d\n", ret); 441 + 426 442 return ret; 427 443 } 428 444 ··· 534 460 unsigned char kbd_func; 535 461 int ret; 536 462 537 - /* Initialize keyboard */ 538 - ret = asus_kbd_init(hdev); 539 - if (ret < 0) 540 - return ret; 463 + if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD) { 464 + ret = rog_nkey_led_init(hdev); 465 + if (ret < 0) 466 + return ret; 467 + } else { 468 + /* Initialize keyboard */ 469 + ret = asus_kbd_init(hdev); 470 + if (ret < 0) 471 + return ret; 541 472 542 - /* Get keyboard functions */ 543 - ret = asus_kbd_get_functions(hdev, &kbd_func); 544 - if (ret < 0) 545 - return ret; 473 + /* Get keyboard functions */ 474 + ret = asus_kbd_get_functions(hdev, &kbd_func); 475 + if (ret < 0) 476 + return ret; 546 477 547 - /* Check for backlight support */ 548 - if (!(kbd_func & SUPPORT_KBD_BACKLIGHT)) 549 - return -ENODEV; 478 + /* Check for backlight support */ 479 + if (!(kbd_func & SUPPORT_KBD_BACKLIGHT)) 480 + return -ENODEV; 481 + } 550 482 551 483 drvdata->kbd_backlight = devm_kzalloc(&hdev->dev, 552 484 sizeof(struct asus_kbd_leds), ··· 831 751 usage->hid == (HID_UP_GENDEVCTRLS | 0x0026))) 832 752 return -1; 833 753 834 - /* ASUS-specific keyboard hotkeys */ 835 - if ((usage->hid & HID_USAGE_PAGE) == 0xff310000) { 754 + /* ASUS-specific keyboard hotkeys and led backlight */ 755 + if ((usage->hid & HID_USAGE_PAGE) == HID_UP_ASUSVENDOR) { 836 756 switch (usage->hid & HID_USAGE) { 837 757 case 0x10: asus_map_key_clear(KEY_BRIGHTNESSDOWN); break; 838 758 case 0x20: asus_map_key_clear(KEY_BRIGHTNESSUP); break; ··· 859 779 860 780 /* Fn+F5 "fan" symbol on FX503VD */ 861 781 case 0x99: asus_map_key_clear(KEY_PROG4); break; 782 + 783 + /* Fn+F5 "fan" symbol on N-Key keyboard */ 784 + case 0xae: asus_map_key_clear(KEY_PROG4); break; 785 + 786 + /* Fn+Ret "Calc" symbol on N-Key keyboard */ 787 + case 0x92: asus_map_key_clear(KEY_CALC); break; 788 + 789 + /* Fn+Left Aura mode previous on N-Key keyboard */ 790 + case 0xb2: asus_map_key_clear(KEY_PROG2); break; 791 + 792 + /* Fn+Right Aura mode next on N-Key keyboard */ 793 + case 0xb3: asus_map_key_clear(KEY_PROG3); break; 862 794 863 795 default: 864 796 /* ASUS lazily declares 256 usages, ignore the rest, ··· 1218 1126 { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, 1219 1127 USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD), 1220 1128 QUIRK_USE_KBD_BACKLIGHT }, 1129 + { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, 1130 + USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD), 1131 + QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD }, 1221 1132 { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, 1222 1133 USB_DEVICE_ID_ASUSTEK_T100TA_KEYBOARD), 1223 1134 QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },
+39 -12
drivers/hid/hid-elecom.c
··· 11 11 * Copyright (c) 2017 Diego Elio Pettenò <flameeyes@flameeyes.eu> 12 12 * Copyright (c) 2017 Alex Manoussakis <amanou@gnu.org> 13 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 /* ··· 30 29 * report descriptor but it does not appear that these enable software to 31 30 * control what the extra buttons map to. The only simple and straightforward 32 31 * solution seems to involve fixing up the report descriptor. 33 - * 34 - * Report descriptor format: 35 - * Positions 13, 15, 21 and 31 store the button bit count, button usage minimum, 36 - * button usage maximum and padding bit count respectively. 37 32 */ 38 33 #define MOUSE_BUTTONS_MAX 8 39 34 static void mouse_button_fixup(struct hid_device *hdev, 40 35 __u8 *rdesc, unsigned int rsize, 36 + unsigned int button_bit_count, 37 + unsigned int padding_bit, 38 + unsigned int button_report_size, 39 + unsigned int button_usage_maximum, 41 40 int nbuttons) 42 41 { 43 - if (rsize < 32 || rdesc[12] != 0x95 || 44 - rdesc[14] != 0x75 || rdesc[15] != 0x01 || 45 - rdesc[20] != 0x29 || rdesc[30] != 0x75) 42 + if (rsize < 32 || rdesc[button_bit_count] != 0x95 || 43 + rdesc[button_report_size] != 0x75 || 44 + rdesc[button_report_size + 1] != 0x01 || 45 + rdesc[button_usage_maximum] != 0x29 || rdesc[padding_bit] != 0x75) 46 46 return; 47 47 hid_info(hdev, "Fixing up Elecom mouse button count\n"); 48 48 nbuttons = clamp(nbuttons, 0, MOUSE_BUTTONS_MAX); 49 - rdesc[13] = nbuttons; 50 - rdesc[21] = nbuttons; 51 - rdesc[31] = MOUSE_BUTTONS_MAX - nbuttons; 49 + rdesc[button_bit_count + 1] = nbuttons; 50 + rdesc[button_usage_maximum + 1] = nbuttons; 51 + rdesc[padding_bit + 1] = MOUSE_BUTTONS_MAX - nbuttons; 52 52 } 53 53 54 54 static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, ··· 64 62 rdesc[47] = 0x00; 65 63 } 66 64 break; 65 + case USB_DEVICE_ID_ELECOM_M_XGL20DLBK: 66 + /* 67 + * Report descriptor format: 68 + * 20: button bit count 69 + * 28: padding bit count 70 + * 22: button report size 71 + * 14: button usage maximum 72 + */ 73 + mouse_button_fixup(hdev, rdesc, *rsize, 20, 28, 22, 14, 8); 74 + break; 67 75 case USB_DEVICE_ID_ELECOM_M_XT3URBK: 68 76 case USB_DEVICE_ID_ELECOM_M_XT3DRBK: 69 77 case USB_DEVICE_ID_ELECOM_M_XT4DRBK: 70 - mouse_button_fixup(hdev, rdesc, *rsize, 6); 78 + /* 79 + * Report descriptor format: 80 + * 12: button bit count 81 + * 30: padding bit count 82 + * 14: button report size 83 + * 20: button usage maximum 84 + */ 85 + mouse_button_fixup(hdev, rdesc, *rsize, 12, 30, 14, 20, 6); 71 86 break; 72 87 case USB_DEVICE_ID_ELECOM_M_DT1URBK: 73 88 case USB_DEVICE_ID_ELECOM_M_DT1DRBK: 74 89 case USB_DEVICE_ID_ELECOM_M_HT1URBK: 75 90 case USB_DEVICE_ID_ELECOM_M_HT1DRBK: 76 - mouse_button_fixup(hdev, rdesc, *rsize, 8); 91 + /* 92 + * Report descriptor format: 93 + * 12: button bit count 94 + * 30: padding bit count 95 + * 14: button report size 96 + * 20: button usage maximum 97 + */ 98 + mouse_button_fixup(hdev, rdesc, *rsize, 12, 30, 14, 20, 8); 77 99 break; 78 100 } 79 101 return rdesc; ··· 105 79 106 80 static const struct hid_device_id elecom_devices[] = { 107 81 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, 82 + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XGL20DLBK) }, 108 83 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK) }, 109 84 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK) }, 110 85 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) },
+7
drivers/hid/hid-ids.h
··· 190 190 #define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1 0x1854 191 191 #define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2 0x1837 192 192 #define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3 0x1822 193 + #define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD 0x1866 193 194 #define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869 194 195 195 196 #define USB_VENDOR_ID_ATEN 0x0557 ··· 360 359 #define USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR 0x1803 361 360 #define USB_DEVICE_ID_DRAGONRISE_GAMECUBE1 0x1843 362 361 #define USB_DEVICE_ID_DRAGONRISE_GAMECUBE2 0x1844 362 + #define USB_DEVICE_ID_DRAGONRISE_GAMECUBE3 0x1846 363 363 364 364 #define USB_VENDOR_ID_DWAV 0x0eef 365 365 #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 ··· 392 390 393 391 #define USB_VENDOR_ID_ELECOM 0x056e 394 392 #define USB_DEVICE_ID_ELECOM_BM084 0x0061 393 + #define USB_DEVICE_ID_ELECOM_M_XGL20DLBK 0x00e6 395 394 #define USB_DEVICE_ID_ELECOM_M_XT3URBK 0x00fb 396 395 #define USB_DEVICE_ID_ELECOM_M_XT3DRBK 0x00fc 397 396 #define USB_DEVICE_ID_ELECOM_M_XT4DRBK 0x00fd ··· 1077 1074 #define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002 1078 1075 #define USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER 0x1000 1079 1076 1077 + #define USB_VENDOR_ID_SONY_GHLIVE 0x12ba 1078 + #define USB_DEVICE_ID_SONY_PS3WIIU_GHLIVE_DONGLE 0x074b 1079 + 1080 1080 #define USB_VENDOR_ID_SINO_LITE 0x1345 1081 1081 #define USB_DEVICE_ID_SINO_LITE_CONTROLLER 0x3008 1082 1082 ··· 1139 1133 #define USB_DEVICE_ID_SYNAPTICS_DELL_K12A 0x2819 1140 1134 #define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012 0x2968 1141 1135 #define USB_DEVICE_ID_SYNAPTICS_TP_V103 0x5710 1136 + #define USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1002 0x73f4 1142 1137 #define USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1003 0x73f5 1143 1138 #define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5 0x81a7 1144 1139
+5 -1
drivers/hid/hid-input.c
··· 537 537 capacity = hidinput_scale_battery_capacity(dev, value); 538 538 539 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 542 dev->battery_capacity = capacity; 542 543 dev->battery_status = HID_BATTERY_REPORTED; 544 + dev->battery_ratelimit_time = 545 + ktime_add_ms(ktime_get_coarse(), 30 * 1000); 543 546 power_supply_changed(dev->battery); 544 547 } 545 548 } ··· 749 746 field->flags |= HID_MAIN_ITEM_RELATIVE; 750 747 break; 751 748 } 749 + goto unknown; 752 750 753 751 default: goto unknown; 754 752 }
+12 -1
drivers/hid/hid-ite.c
··· 18 18 unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); 19 19 20 20 if (quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) { 21 + /* For Acer Aspire Switch 10 SW5-012 keyboard-dock */ 21 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 24 rdesc[163] = HID_MAIN_ITEM_RELATIVE; 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; 24 30 } 25 31 } 26 32 ··· 105 99 { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, 106 100 USB_VENDOR_ID_SYNAPTICS, 107 101 USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012), 102 + .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT }, 103 + /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */ 104 + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, 105 + USB_VENDOR_ID_SYNAPTICS, 106 + USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1002), 108 107 .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT }, 109 108 /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */ 110 109 { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+2
drivers/hid/hid-logitech-hidpp.c
··· 4048 4048 { /* MX5500 keyboard over Bluetooth */ 4049 4049 HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb30b), 4050 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 4053 { /* MX Master mouse over Bluetooth */ 4052 4054 HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb012), 4053 4055 .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
+2
drivers/hid/hid-mf.c
··· 153 153 .driver_data = HID_QUIRK_MULTI_INPUT }, 154 154 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE2), 155 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 }; 158 160 MODULE_DEVICE_TABLE(hid, mf_devices);
+3
drivers/hid/hid-quirks.c
··· 72 72 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_REDRAGON_SEYMUR2), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE }, 73 73 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR), HID_QUIRK_MULTI_INPUT }, 74 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 76 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3), HID_QUIRK_MULTI_INPUT }, 76 77 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU), HID_QUIRK_MULTI_INPUT }, 77 78 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER), HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, ··· 367 366 #endif 368 367 #if IS_ENABLED(CONFIG_HID_ELECOM) 369 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_M_XGL20DLBK) }, 370 370 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK) }, 371 371 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK) }, 372 372 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) }, ··· 486 484 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR) }, 487 485 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1) }, 488 486 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE2) }, 487 + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE3) }, 489 488 #endif 490 489 #if IS_ENABLED(CONFIG_HID_MICROSOFT) 491 490 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) },
+198 -49
drivers/hid/hid-sony.c
··· 11 11 * Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com> 12 12 * Copyright (c) 2014-2016 Frank Praznik <frank.praznik@gmail.com> 13 13 * Copyright (c) 2018 Todd Kelner 14 + * Copyright (c) 2020 Pascal Giard <pascal.giard@etsmtl.ca> 14 15 */ 15 16 16 17 /* ··· 36 35 #include <linux/idr.h> 37 36 #include <linux/input/mt.h> 38 37 #include <linux/crc32.h> 38 + #include <linux/usb.h> 39 + #include <linux/timer.h> 39 40 #include <asm/unaligned.h> 40 41 41 42 #include "hid-ids.h" ··· 59 56 #define NSG_MR5U_REMOTE_BT BIT(14) 60 57 #define NSG_MR7U_REMOTE_BT BIT(15) 61 58 #define SHANWAN_GAMEPAD BIT(16) 59 + #define GHL_GUITAR_PS3WIIU BIT(17) 62 60 63 61 #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT) 64 62 #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT) ··· 83 79 #define NSG_MRXU_MAX_X 1667 84 80 #define NSG_MRXU_MAX_Y 1868 85 81 82 + #define GHL_GUITAR_POKE_INTERVAL 10 /* In seconds */ 83 + #define GHL_GUITAR_TILT_USAGE 44 84 + 85 + /* Magic value and data taken from GHLtarUtility: 86 + * https://github.com/ghlre/GHLtarUtility/blob/master/PS3Guitar.cs 87 + * Note: The Wii U and PS3 dongles happen to share the same! 88 + */ 89 + static const u16 ghl_ps3wiiu_magic_value = 0x201; 90 + static const char ghl_ps3wiiu_magic_data[] = { 91 + 0x02, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00 92 + }; 86 93 87 94 /* PS/3 Motion controller */ 88 95 static u8 motion_rdesc[] = { ··· 565 550 struct power_supply_desc battery_desc; 566 551 int device_id; 567 552 unsigned fw_version; 553 + bool fw_version_created; 568 554 unsigned hw_version; 555 + bool hw_version_created; 569 556 u8 *output_report_dmabuf; 570 557 571 558 #ifdef CONFIG_SONY_FF ··· 579 562 u8 hotplug_worker_initialized; 580 563 u8 state_worker_initialized; 581 564 u8 defer_initialization; 582 - u8 cable_state; 583 - u8 battery_charging; 584 565 u8 battery_capacity; 566 + int battery_status; 585 567 u8 led_state[MAX_LEDS]; 586 568 u8 led_delay_on[MAX_LEDS]; 587 569 u8 led_delay_off[MAX_LEDS]; ··· 594 578 enum ds4_dongle_state ds4_dongle_state; 595 579 /* DS4 calibration data */ 596 580 struct ds4_calibration_data ds4_calib_data[6]; 581 + /* GH Live */ 582 + struct timer_list ghl_poke_timer; 583 + struct usb_ctrlrequest *ghl_cr; 584 + u8 *ghl_databuf; 597 585 }; 598 586 599 587 static void sony_set_leds(struct sony_sc *sc); ··· 619 599 schedule_work(&sc->hotplug_worker); 620 600 break; 621 601 } 602 + } 603 + 604 + static void ghl_magic_poke_cb(struct urb *urb) 605 + { 606 + if (urb) { 607 + /* Free sc->ghl_cr and sc->ghl_databuf allocated in 608 + * ghl_magic_poke() 609 + */ 610 + kfree(urb->setup_packet); 611 + kfree(urb->transfer_buffer); 612 + } 613 + } 614 + 615 + static void ghl_magic_poke(struct timer_list *t) 616 + { 617 + struct sony_sc *sc = from_timer(sc, t, ghl_poke_timer); 618 + 619 + int ret; 620 + unsigned int pipe; 621 + struct urb *urb; 622 + struct usb_device *usbdev = to_usb_device(sc->hdev->dev.parent->parent); 623 + const u16 poke_size = 624 + ARRAY_SIZE(ghl_ps3wiiu_magic_data); 625 + 626 + pipe = usb_sndctrlpipe(usbdev, 0); 627 + 628 + if (!sc->ghl_cr) { 629 + sc->ghl_cr = kzalloc(sizeof(*sc->ghl_cr), GFP_ATOMIC); 630 + if (!sc->ghl_cr) 631 + goto resched; 632 + } 633 + 634 + if (!sc->ghl_databuf) { 635 + sc->ghl_databuf = kzalloc(poke_size, GFP_ATOMIC); 636 + if (!sc->ghl_databuf) 637 + goto resched; 638 + } 639 + 640 + urb = usb_alloc_urb(0, GFP_ATOMIC); 641 + if (!urb) 642 + goto resched; 643 + 644 + sc->ghl_cr->bRequestType = 645 + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT; 646 + sc->ghl_cr->bRequest = USB_REQ_SET_CONFIGURATION; 647 + sc->ghl_cr->wValue = cpu_to_le16(ghl_ps3wiiu_magic_value); 648 + sc->ghl_cr->wIndex = 0; 649 + sc->ghl_cr->wLength = cpu_to_le16(poke_size); 650 + memcpy(sc->ghl_databuf, ghl_ps3wiiu_magic_data, poke_size); 651 + 652 + usb_fill_control_urb( 653 + urb, usbdev, pipe, 654 + (unsigned char *) sc->ghl_cr, sc->ghl_databuf, 655 + poke_size, ghl_magic_poke_cb, NULL); 656 + ret = usb_submit_urb(urb, GFP_ATOMIC); 657 + if (ret < 0) { 658 + kfree(sc->ghl_databuf); 659 + kfree(sc->ghl_cr); 660 + } 661 + usb_free_urb(urb); 662 + 663 + resched: 664 + /* Reschedule for next time */ 665 + mod_timer(&sc->ghl_poke_timer, jiffies + GHL_GUITAR_POKE_INTERVAL*HZ); 666 + } 667 + 668 + static int guitar_mapping(struct hid_device *hdev, struct hid_input *hi, 669 + struct hid_field *field, struct hid_usage *usage, 670 + unsigned long **bit, int *max) 671 + { 672 + if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR) { 673 + unsigned int abs = usage->hid & HID_USAGE; 674 + 675 + if (abs == GHL_GUITAR_TILT_USAGE) { 676 + hid_map_usage_clear(hi, usage, bit, max, EV_ABS, ABS_RY); 677 + return 1; 678 + } 679 + } 680 + return 0; 622 681 } 623 682 624 683 static ssize_t ds4_show_poll_interval(struct device *dev, ··· 991 892 static const u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 }; 992 893 unsigned long flags; 993 894 int offset; 994 - u8 cable_state, battery_capacity, battery_charging; 895 + u8 battery_capacity; 896 + int battery_status; 995 897 996 898 /* 997 899 * The sixaxis is charging if the battery value is 0xee ··· 1004 904 1005 905 if (rd[offset] >= 0xee) { 1006 906 battery_capacity = 100; 1007 - battery_charging = !(rd[offset] & 0x01); 1008 - cable_state = 1; 907 + battery_status = (rd[offset] & 0x01) ? POWER_SUPPLY_STATUS_FULL : POWER_SUPPLY_STATUS_CHARGING; 1009 908 } else { 1010 909 u8 index = rd[offset] <= 5 ? rd[offset] : 5; 1011 910 battery_capacity = sixaxis_battery_capacity[index]; 1012 - battery_charging = 0; 1013 - cable_state = 0; 911 + battery_status = POWER_SUPPLY_STATUS_DISCHARGING; 1014 912 } 1015 913 1016 914 spin_lock_irqsave(&sc->lock, flags); 1017 - sc->cable_state = cable_state; 1018 915 sc->battery_capacity = battery_capacity; 1019 - sc->battery_charging = battery_charging; 916 + sc->battery_status = battery_status; 1020 917 spin_unlock_irqrestore(&sc->lock, flags); 1021 918 1022 919 if (sc->quirks & SIXAXIS_CONTROLLER) { ··· 1041 944 struct input_dev *input_dev = hidinput->input; 1042 945 unsigned long flags; 1043 946 int n, m, offset, num_touch_data, max_touch_data; 1044 - u8 cable_state, battery_capacity, battery_charging; 947 + u8 cable_state, battery_capacity; 948 + int battery_status; 1045 949 u16 timestamp; 1046 950 1047 951 /* When using Bluetooth the header is 2 bytes longer, so skip these. */ ··· 1147 1049 */ 1148 1050 offset = data_offset + DS4_INPUT_REPORT_BATTERY_OFFSET; 1149 1051 cable_state = (rd[offset] >> 4) & 0x01; 1150 - battery_capacity = rd[offset] & 0x0F; 1151 1052 1152 1053 /* 1153 - * When a USB power source is connected the battery level ranges from 1154 - * 0 to 10, and when running on battery power it ranges from 0 to 9. 1155 - * A battery level above 10 when plugged in means charge completed. 1054 + * Interpretation of the battery_capacity data depends on the cable state. 1055 + * When no cable is connected (bit4 is 0): 1056 + * - 0:10: percentage in units of 10%. 1057 + * When a cable is plugged in: 1058 + * - 0-10: percentage in units of 10%. 1059 + * - 11: battery is full 1060 + * - 14: not charging due to Voltage or temperature error 1061 + * - 15: charge error 1156 1062 */ 1157 - if (!cable_state || battery_capacity > 10) 1158 - battery_charging = 0; 1159 - else 1160 - battery_charging = 1; 1063 + if (cable_state) { 1064 + u8 battery_data = rd[offset] & 0xf; 1161 1065 1162 - if (!cable_state) 1163 - battery_capacity++; 1164 - if (battery_capacity > 10) 1165 - battery_capacity = 10; 1066 + if (battery_data < 10) { 1067 + /* Take the mid-point for each battery capacity value, 1068 + * because on the hardware side 0 = 0-9%, 1=10-19%, etc. 1069 + * This matches official platform behavior, which does 1070 + * the same. 1071 + */ 1072 + battery_capacity = battery_data * 10 + 5; 1073 + battery_status = POWER_SUPPLY_STATUS_CHARGING; 1074 + } else if (battery_data == 10) { 1075 + battery_capacity = 100; 1076 + battery_status = POWER_SUPPLY_STATUS_CHARGING; 1077 + } else if (battery_data == 11) { 1078 + battery_capacity = 100; 1079 + battery_status = POWER_SUPPLY_STATUS_FULL; 1080 + } else { /* 14, 15 and undefined values */ 1081 + battery_capacity = 0; 1082 + battery_status = POWER_SUPPLY_STATUS_UNKNOWN; 1083 + } 1084 + } else { 1085 + u8 battery_data = rd[offset] & 0xf; 1166 1086 1167 - battery_capacity *= 10; 1087 + if (battery_data < 10) 1088 + battery_capacity = battery_data * 10 + 5; 1089 + else /* 10 */ 1090 + battery_capacity = 100; 1091 + 1092 + battery_status = POWER_SUPPLY_STATUS_DISCHARGING; 1093 + } 1168 1094 1169 1095 spin_lock_irqsave(&sc->lock, flags); 1170 - sc->cable_state = cable_state; 1171 1096 sc->battery_capacity = battery_capacity; 1172 - sc->battery_charging = battery_charging; 1097 + sc->battery_status = battery_status; 1173 1098 spin_unlock_irqrestore(&sc->lock, flags); 1174 1099 1175 1100 /* ··· 1481 1360 if (sc->quirks & DUALSHOCK4_CONTROLLER) 1482 1361 return ds4_mapping(hdev, hi, field, usage, bit, max); 1483 1362 1363 + if (sc->quirks & GHL_GUITAR_PS3WIIU) 1364 + return guitar_mapping(hdev, hi, field, usage, bit, max); 1484 1365 1485 1366 /* Let hid-core decide for the others */ 1486 1367 return 0; ··· 1720 1597 * of the controller, so that it sends input reports of type 0x11. 1721 1598 */ 1722 1599 if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) { 1600 + int retries; 1601 + 1723 1602 buf = kmalloc(DS4_FEATURE_REPORT_0x02_SIZE, GFP_KERNEL); 1724 1603 if (!buf) 1725 1604 return -ENOMEM; 1726 1605 1727 - ret = hid_hw_raw_request(sc->hdev, 0x02, buf, 1728 - DS4_FEATURE_REPORT_0x02_SIZE, 1729 - HID_FEATURE_REPORT, 1730 - HID_REQ_GET_REPORT); 1731 - if (ret < 0) 1732 - goto err_stop; 1606 + /* We should normally receive the feature report data we asked 1607 + * for, but hidraw applications such as Steam can issue feature 1608 + * reports as well. In particular for Dongle reconnects, Steam 1609 + * and this function are competing resulting in often receiving 1610 + * data for a different HID report, so retry a few times. 1611 + */ 1612 + for (retries = 0; retries < 3; retries++) { 1613 + ret = hid_hw_raw_request(sc->hdev, 0x02, buf, 1614 + DS4_FEATURE_REPORT_0x02_SIZE, 1615 + HID_FEATURE_REPORT, 1616 + HID_REQ_GET_REPORT); 1617 + if (ret < 0) 1618 + goto err_stop; 1619 + 1620 + if (buf[0] != 0x02) { 1621 + if (retries < 2) { 1622 + hid_warn(sc->hdev, "Retrying DualShock 4 get calibration report (0x02) request\n"); 1623 + continue; 1624 + } else { 1625 + ret = -EILSEQ; 1626 + goto err_stop; 1627 + } 1628 + } else { 1629 + break; 1630 + } 1631 + } 1733 1632 } else { 1734 1633 u8 bthdr = 0xA3; 1735 1634 u32 crc; ··· 2445 2300 struct sony_sc *sc = power_supply_get_drvdata(psy); 2446 2301 unsigned long flags; 2447 2302 int ret = 0; 2448 - u8 battery_charging, battery_capacity, cable_state; 2303 + u8 battery_capacity; 2304 + int battery_status; 2449 2305 2450 2306 spin_lock_irqsave(&sc->lock, flags); 2451 - battery_charging = sc->battery_charging; 2452 2307 battery_capacity = sc->battery_capacity; 2453 - cable_state = sc->cable_state; 2308 + battery_status = sc->battery_status; 2454 2309 spin_unlock_irqrestore(&sc->lock, flags); 2455 2310 2456 2311 switch (psp) { ··· 2464 2319 val->intval = battery_capacity; 2465 2320 break; 2466 2321 case POWER_SUPPLY_PROP_STATUS: 2467 - if (battery_charging) 2468 - val->intval = POWER_SUPPLY_STATUS_CHARGING; 2469 - else 2470 - if (battery_capacity == 100 && cable_state) 2471 - val->intval = POWER_SUPPLY_STATUS_FULL; 2472 - else 2473 - val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 2322 + val->intval = battery_status; 2474 2323 break; 2475 2324 default: 2476 2325 ret = -EINVAL; ··· 2862 2723 2863 2724 ret = device_create_file(&sc->hdev->dev, &dev_attr_firmware_version); 2864 2725 if (ret) { 2865 - /* Make zero for cleanup reasons of sysfs entries. */ 2866 - sc->fw_version = 0; 2867 - sc->hw_version = 0; 2868 2726 hid_err(sc->hdev, "can't create sysfs firmware_version attribute err: %d\n", ret); 2869 2727 goto err_stop; 2870 2728 } 2729 + sc->fw_version_created = true; 2871 2730 2872 2731 ret = device_create_file(&sc->hdev->dev, &dev_attr_hardware_version); 2873 2732 if (ret) { 2874 - sc->hw_version = 0; 2875 2733 hid_err(sc->hdev, "can't create sysfs hardware_version attribute err: %d\n", ret); 2876 2734 goto err_stop; 2877 2735 } 2736 + sc->hw_version_created = true; 2878 2737 2879 2738 /* 2880 2739 * The Dualshock 4 touchpad supports 2 touches and has a ··· 2964 2827 */ 2965 2828 if (sc->ds4_bt_poll_interval) 2966 2829 device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval); 2967 - if (sc->fw_version) 2830 + if (sc->fw_version_created) 2968 2831 device_remove_file(&sc->hdev->dev, &dev_attr_firmware_version); 2969 - if (sc->hw_version) 2832 + if (sc->hw_version_created) 2970 2833 device_remove_file(&sc->hdev->dev, &dev_attr_hardware_version); 2971 2834 sony_cancel_work_sync(sc); 2972 2835 sony_remove_dev_list(sc); ··· 3039 2902 return -ENODEV; 3040 2903 } 3041 2904 2905 + if (sc->quirks & GHL_GUITAR_PS3WIIU) { 2906 + timer_setup(&sc->ghl_poke_timer, ghl_magic_poke, 0); 2907 + mod_timer(&sc->ghl_poke_timer, 2908 + jiffies + GHL_GUITAR_POKE_INTERVAL*HZ); 2909 + } 2910 + 3042 2911 return ret; 3043 2912 } 3044 2913 ··· 3052 2909 { 3053 2910 struct sony_sc *sc = hid_get_drvdata(hdev); 3054 2911 2912 + if (sc->quirks & GHL_GUITAR_PS3WIIU) 2913 + del_timer_sync(&sc->ghl_poke_timer); 2914 + 3055 2915 hid_hw_close(hdev); 3056 2916 3057 2917 if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) 3058 2918 device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval); 3059 2919 3060 - if (sc->fw_version) 2920 + if (sc->fw_version_created) 3061 2921 device_remove_file(&sc->hdev->dev, &dev_attr_firmware_version); 3062 2922 3063 - if (sc->hw_version) 2923 + if (sc->hw_version_created) 3064 2924 device_remove_file(&sc->hdev->dev, &dev_attr_hardware_version); 3065 2925 3066 2926 sony_cancel_work_sync(sc); ··· 3166 3020 /* SMK-Link NSG-MR7U Remote Control */ 3167 3021 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_NSG_MR7U_REMOTE), 3168 3022 .driver_data = NSG_MR7U_REMOTE_BT }, 3023 + /* Guitar Hero Live PS3 and Wii U guitar dongles */ 3024 + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_GHLIVE, USB_DEVICE_ID_SONY_PS3WIIU_GHLIVE_DONGLE), 3025 + .driver_data = GHL_GUITAR_PS3WIIU}, 3169 3026 { } 3170 3027 }; 3171 3028 MODULE_DEVICE_TABLE(hid, sony_devices);
+23 -1
drivers/hid/hidraw.c
··· 170 170 /* 171 171 * This function performs a Get_Report transfer over the control endpoint 172 172 * 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 not 173 + * of buffer is the report number to request, or 0x0 if the device does not 174 174 * use numbered reports. The report_type parameter can be HID_FEATURE_REPORT 175 175 * or HID_INPUT_REPORT. 176 176 */ ··· 425 425 if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGFEATURE(0))) { 426 426 int len = _IOC_SIZE(cmd); 427 427 ret = hidraw_get_report(file, user_arg, len, HID_FEATURE_REPORT); 428 + break; 429 + } 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); 428 450 break; 429 451 } 430 452
+4 -1
drivers/hid/i2c-hid/i2c-hid-core.c
··· 1106 1106 } 1107 1107 1108 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 1112 goto err_regulator; 1113 + } 1111 1114 1112 1115 ret = i2c_hid_init_irq(client); 1113 1116 if (ret < 0)
+8
drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
··· 405 405 }, 406 406 .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 416 { } /* Terminate list */ 409 417 }; 410 418
+2 -4
drivers/hid/intel-ish-hid/ishtp-hid.c
··· 211 211 struct ishtp_hid_data *hid_data; 212 212 213 213 hid = hid_allocate_device(); 214 - if (IS_ERR(hid)) { 215 - rv = PTR_ERR(hid); 216 - return -ENOMEM; 217 - } 214 + if (IS_ERR(hid)) 215 + return PTR_ERR(hid); 218 216 219 217 hid_data = kzalloc(sizeof(*hid_data), GFP_KERNEL); 220 218 if (!hid_data) {
+2
drivers/hid/usbhid/hid-core.c
··· 438 438 break; 439 439 case -ESHUTDOWN: /* unplug */ 440 440 unplug = 1; 441 + break; 441 442 case -EILSEQ: /* protocol error or unplug */ 442 443 case -EPROTO: /* protocol error or unplug */ 443 444 case -ECONNRESET: /* unlink */ ··· 490 489 break; 491 490 case -ESHUTDOWN: /* unplug */ 492 491 unplug = 1; 492 + break; 493 493 case -EILSEQ: /* protocol error or unplug */ 494 494 case -EPROTO: /* protocol error or unplug */ 495 495 case -ECONNRESET: /* unlink */
+8 -8
drivers/hid/wacom_sys.c
··· 1173 1173 NULL 1174 1174 }; 1175 1175 1176 - static struct attribute_group cintiq_led_attr_group = { 1176 + static const struct attribute_group cintiq_led_attr_group = { 1177 1177 .name = "wacom_led", 1178 1178 .attrs = cintiq_led_attrs, 1179 1179 }; ··· 1194 1194 NULL 1195 1195 }; 1196 1196 1197 - static struct attribute_group intuos4_led_attr_group = { 1197 + static const struct attribute_group intuos4_led_attr_group = { 1198 1198 .name = "wacom_led", 1199 1199 .attrs = intuos4_led_attrs, 1200 1200 }; ··· 1205 1205 NULL 1206 1206 }; 1207 1207 1208 - static struct attribute_group intuos5_led_attr_group = { 1208 + static const struct attribute_group intuos5_led_attr_group = { 1209 1209 .name = "wacom_led", 1210 1210 .attrs = intuos5_led_attrs, 1211 1211 }; ··· 1216 1216 NULL 1217 1217 }; 1218 1218 1219 - static struct attribute_group generic_led_attr_group = { 1219 + static const struct attribute_group generic_led_attr_group = { 1220 1220 .name = "wacom_led", 1221 1221 .attrs = generic_led_attrs, 1222 1222 }; 1223 1223 1224 1224 struct wacom_sysfs_group_devres { 1225 - struct attribute_group *group; 1225 + const struct attribute_group *group; 1226 1226 struct kobject *root; 1227 1227 }; 1228 1228 ··· 1238 1238 1239 1239 static int __wacom_devm_sysfs_create_group(struct wacom *wacom, 1240 1240 struct kobject *root, 1241 - struct attribute_group *group) 1241 + const struct attribute_group *group) 1242 1242 { 1243 1243 struct wacom_sysfs_group_devres *devres; 1244 1244 int error; ··· 1264 1264 } 1265 1265 1266 1266 static int wacom_devm_sysfs_create_group(struct wacom *wacom, 1267 - struct attribute_group *group) 1267 + const struct attribute_group *group) 1268 1268 { 1269 1269 return __wacom_devm_sysfs_create_group(wacom, &wacom->hdev->dev.kobj, 1270 1270 group); ··· 1847 1847 &remote##SET_ID##_mode_attr.attr, \ 1848 1848 NULL \ 1849 1849 }; \ 1850 - static struct attribute_group remote##SET_ID##_serial_group = { \ 1850 + static const struct attribute_group remote##SET_ID##_serial_group = { \ 1851 1851 .name = NULL, \ 1852 1852 .attrs = remote##SET_ID##_serial_attrs, \ 1853 1853 }
+2 -1
include/linux/hid.h
··· 494 494 }; 495 495 496 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 498 #define HID_CONTROL_FIFO_SIZE 256 /* to init devices with >100 reports */ 499 499 #define HID_OUTPUT_FIFO_SIZE 64 500 500 ··· 585 585 __s32 battery_report_id; 586 586 enum hid_battery_status battery_status; 587 587 bool battery_avoid_query; 588 + ktime_t battery_ratelimit_time; 588 589 #endif 589 590 590 591 unsigned long status; /* see STAT flags above */
+6
include/uapi/linux/hidraw.h
··· 40 40 #define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len) 41 41 #define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len) 42 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 50 #define HIDRAW_FIRST_MINOR 0 45 51 #define HIDRAW_MAX_DEVICES 64
+1 -1
samples/hidraw/hid-example.c
··· 128 128 perror("HIDIOCGFEATURE"); 129 129 } else { 130 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 132 for (i = 0; i < res; i++) 133 133 printf("%hhx ", buf[i]); 134 134 puts("\n");