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 ...
Unified · Split
| @@ -0,0 +1,145 @@ | ||
| 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 | + <-------| | | | | | |
| @@ -123,8 +123,49 @@ HIDIOCGFEATURE(len): · 122 unmodified lines | ||
| 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 | ------- |
| @@ -16,3 +16,4 @@ Human Interface Devices (HID) · 15 unmodified lines | ||
| 16 | 16 | |
| 17 | 17 | hid-alps |
| 18 | 18 | intel-ish-hid |
| 19 | + amd-sfh-hid | |
| @@ -956,6 +956,14 @@ S: Supported · 955 unmodified lines | ||
| 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 |
| @@ -907,6 +907,7 @@ config HID_SONY · 906 unmodified lines | ||
| 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,4 +1184,6 @@ source "drivers/hid/i2c-hid/Kconfig" · 270 unmodified lines | ||
| 1183 | 1184 | |
| 1184 | 1185 | source "drivers/hid/intel-ish-hid/Kconfig" |
| 1185 | 1186 | |
| 1187 | +source "drivers/hid/amd-sfh-hid/Kconfig" | |
| 1188 | + | |
| 1186 | 1189 | endmenu |
| @@ -142,3 +142,5 @@ obj-$(CONFIG_I2C_HID) += i2c-hid/ · 141 unmodified lines | ||
| 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/ | |
| @@ -0,0 +1,18 @@ | ||
| 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 | |
| @@ -0,0 +1,13 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0-or-later | |
| 2 | +# | |
| 3 | +# Makefile - AMD SFH HID drivers | |
| 4 | +# Copyright (c) 2019-2020, Advanced Micro Devices, Inc. | |
| 5 | +# | |
| 6 | +# | |
| 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)/ | |
| @@ -0,0 +1,246 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later | |
| 2 | +/* | |
| 3 | + * AMD SFH Client Layer | |
| 4 | + * Copyright 2020 Advanced Micro Devices, Inc. | |
| 5 | + * Authors: Nehal Bakulchandra Shah <Nehal-Bakulchandra.Shah@amd.com> | |
| 6 | + * Sandeep Singh <Sandeep.singh@amd.com> | |
| 7 | + */ | |
| 8 | + | |
| 9 | +#include <linux/dma-mapping.h> | |
| 10 | +#include <linux/hid.h> | |
| 11 | +#include <linux/list.h> | |
| 12 | +#include <linux/slab.h> | |
| 13 | +#include <linux/workqueue.h> | |
| 14 | +#include <linux/errno.h> | |
| 15 | + | |
| 16 | +#include "hid_descriptor/amd_sfh_hid_desc.h" | |
| 17 | +#include "amd_sfh_pcie.h" | |
| 18 | +#include "amd_sfh_hid.h" | |
| 19 | + | |
| 20 | +#define AMD_SFH_IDLE_LOOP 200 | |
| 21 | + | |
| 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 | +} | |
| @@ -0,0 +1,174 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later | |
| 2 | +/* | |
| 3 | + * AMD MP2 Sensors transport driver | |
| 4 | + * | |
| 5 | + * Authors: Nehal Bakulchandra Shah <Nehal-bakulchandra.shah@amd.com> | |
| 6 | + * Sandeep Singh <sandeep.singh@amd.com> | |
| 7 | + */ | |
| 8 | +#include <linux/hid.h> | |
| 9 | +#include <linux/wait.h> | |
| 10 | +#include <linux/sched.h> | |
| 11 | + | |
| 12 | +#include "amd_sfh_hid.h" | |
| 13 | + | |
| 14 | +#define AMD_SFH_RESPONSE_TIMEOUT 1500 | |
| 15 | + | |
| 16 | +/** | |
| 17 | + * amdtp_hid_parse() - hid-core .parse() callback | |
| 18 | + * @hid: hid device instance | |
| 19 | + * | |
| 20 | + * This function gets called during call to hid_add_device | |
| 21 | + * | |
| 22 | + * Return: 0 on success and non zero on error | |
| 23 | + */ | |
| 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 | +} | |
| @@ -0,0 +1,67 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0-or-later */ | |
| 2 | +/* | |
| 3 | + * AMD MP2 Sensors transport driver | |
| 4 | + * | |
| 5 | + * Authors: Nehal Bakulchandra Shah <Nehal-bakulchandra.shah@amd.com> | |
| 6 | + * Sandeep Singh <sandeep.singh@amd.com> | |
| 7 | + */ | |
| 8 | + | |
| 9 | +#ifndef AMDSFH_HID_H | |
| 10 | +#define AMDSFH_HID_H | |
| 11 | + | |
| 12 | +#define MAX_HID_DEVICES 4 | |
| 13 | +#define BUS_AMD_AMDTP 0x20 | |
| 14 | +#define AMD_SFH_HID_VENDOR 0x1022 | |
| 15 | +#define AMD_SFH_HID_PRODUCT 0x0001 | |
| 16 | + | |
| 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 | |
| @@ -0,0 +1,152 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later | |
| 2 | +/* | |
| 3 | + * AMD MP2 PCIe communication driver | |
| 4 | + * Copyright 2020 Advanced Micro Devices, Inc. | |
| 5 | + * | |
| 6 | + * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> | |
| 7 | + * Sandeep Singh <Sandeep.singh@amd.com> | |
| 8 | + */ | |
| 9 | + | |
| 10 | +#include <linux/bitops.h> | |
| 11 | +#include <linux/delay.h> | |
| 12 | +#include <linux/dma-mapping.h> | |
| 13 | +#include <linux/interrupt.h> | |
| 14 | +#include <linux/io-64-nonatomic-lo-hi.h> | |
| 15 | +#include <linux/module.h> | |
| 16 | +#include <linux/slab.h> | |
| 17 | + | |
| 18 | +#include "amd_sfh_pcie.h" | |
| 19 | + | |
| 20 | +#define DRIVER_NAME "pcie_mp2_amd" | |
| 21 | +#define DRIVER_DESC "AMD(R) PCIe MP2 Communication Driver" | |
| 22 | + | |
| 23 | +#define ACEL_EN BIT(0) | |
| 24 | +#define GYRO_EN BIT(1) | |
| 25 | +#define MAGNO_EN BIT(2) | |
| 26 | +#define ALS_EN BIT(19) | |
| 27 | + | |
| 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>"); | |
| @@ -0,0 +1,79 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0-or-later */ | |
| 2 | +/* | |
| 3 | + * AMD MP2 PCIe communication driver | |
| 4 | + * Copyright 2020 Advanced Micro Devices, Inc. | |
| 5 | + * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> | |
| 6 | + * Sandeep Singh <Sandeep.singh@amd.com> | |
| 7 | + */ | |
| 8 | + | |
| 9 | +#ifndef PCIE_MP2_AMD_H | |
| 10 | +#define PCIE_MP2_AMD_H | |
| 11 | + | |
| 12 | +#include <linux/pci.h> | |
| 13 | + | |
| 14 | +#define PCI_DEVICE_ID_AMD_MP2 0x15E4 | |
| 15 | + | |
| 16 | +#define ENABLE_SENSOR 1 | |
| 17 | +#define DISABLE_SENSOR 2 | |
| 18 | +#define STOP_ALL_SENSORS 8 | |
| 19 | + | |
| 20 | +/* MP2 C2P Message Registers */ | |
| 21 | +#define AMD_C2P_MSG0 0x10500 | |
| 22 | +#define AMD_C2P_MSG1 0x10504 | |
| 23 | +#define AMD_C2P_MSG2 0x10508 | |
| 24 | + | |
| 25 | +/* MP2 P2C Message Registers */ | |
| 26 | +#define AMD_P2C_MSG3 0x1068C /* Supported Sensors info */ | |
| 27 | + | |
| 28 | +/* SFH Command register */ | |
| 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 | |
| @@ -0,0 +1,224 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later | |
| 2 | +/* | |
| 3 | + * AMD SFH Report Descriptor generator | |
| 4 | + * Copyright 2020 Advanced Micro Devices, Inc. | |
| 5 | + * Authors: Nehal Bakulchandra Shah <Nehal-Bakulchandra.Shah@amd.com> | |
| 6 | + * Sandeep Singh <sandeep.singh@amd.com> | |
| 7 | + */ | |
| 8 | + | |
| 9 | +#include <linux/kernel.h> | |
| 10 | +#include <linux/string.h> | |
| 11 | +#include <linux/slab.h> | |
| 12 | +#include "amd_sfh_pcie.h" | |
| 13 | +#include "amd_sfh_hid_desc.h" | |
| 14 | +#include "amd_sfh_hid_report_desc.h" | |
| 15 | + | |
| 16 | +#define AMD_SFH_FW_MULTIPLIER (1000) | |
| 17 | +#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM 0x41 | |
| 18 | +#define HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM 0x51 | |
| 19 | +#define HID_DEFAULT_REPORT_INTERVAL 0x50 | |
| 20 | +#define HID_DEFAULT_MIN_VALUE 0X7F | |
| 21 | +#define HID_DEFAULT_MAX_VALUE 0x80 | |
| 22 | +#define HID_DEFAULT_SENSITIVITY 0x7F | |
| 23 | +#define HID_USAGE_SENSOR_PROPERTY_CONNECTION_TYPE_PC_INTEGRATED_ENUM 0x01 | |
| 24 | +/* state enums */ | |
| 25 | +#define HID_USAGE_SENSOR_STATE_READY_ENUM 0x02 | |
| 26 | +#define HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM 0x05 | |
| 27 | +#define HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM 0x04 | |
| 28 | + | |
| 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 | +} | |
| @@ -0,0 +1,107 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0-or-later */ | |
| 2 | +/* | |
| 3 | + * HID report descriptors, structures and routines | |
| 4 | + * Copyright 2020 Advanced Micro Devices, Inc. | |
| 5 | + * Authors: Nehal Bakulchandra Shah <Nehal-bakulchandra.shah@amd.com> | |
| 6 | + * Sandeep Singh <Sandeep.singh@amd.com> | |
| 7 | + */ | |
| 8 | + | |
| 9 | +#ifndef AMD_SFH_HID_DESCRIPTOR_H | |
| 10 | +#define AMD_SFH_HID_DESCRIPTOR_H | |
| 11 | + | |
| 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 | |
| @@ -0,0 +1,645 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0-or-later */ | |
| 2 | +/* | |
| 3 | + * HID descriptor stuructures | |
| 4 | + * Copyright 2020 Advanced Micro Devices, Inc. | |
| 5 | + * Authors: Nehal Bakulchandra Shah <Nehal-bakulchandra.shah@amd.com> | |
| 6 | + * Sandeep Singh <Sandeep.singh@amd.com> | |
| 7 | + */ | |
| 8 | + | |
| 9 | +#ifndef AMD_SFH_HID_REPORT_DESCRIPTOR_H | |
| 10 | +#define AMD_SFH_HID_REPORT_DESCRIPTOR_H | |
| 11 | + | |
| 12 | +// Accelerometer 3D Sensor | |
| 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 | |
| @@ -48,6 +48,8 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad"); · 47 unmodified lines | ||
| 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 | |
| @@ -80,6 +82,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad"); · 26 unmodified lines | ||
| 80 | 82 | #define QUIRK_T101HA_DOCK BIT(9) |
| 81 | 83 | #define QUIRK_T90CHI BIT(10) |
| 82 | 84 | #define QUIRK_MEDION_E1239T BIT(11) |
| 85 | +#define QUIRK_ROG_NKEY_KEYBOARD BIT(12) | |
| 83 | 86 | |
| 84 | 87 | #define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \ |
| 85 | 88 | QUIRK_NO_INIT_REPORTS | \ |
| @@ -332,6 +335,28 @@ static int asus_raw_event(struct hid_device *hdev, · 246 unmodified lines | ||
| 332 | 335 | if (drvdata->quirks & QUIRK_MEDION_E1239T) |
| 333 | 336 | return asus_e1239t_event(drvdata, data, size); |
| 334 | 337 | |
| 338 | + if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD) { | |
| 339 | + /* | |
| 340 | + * Skip these report ID, the device emits a continuous stream associated | |
| 341 | + * with the AURA mode it is in which looks like an 'echo'. | |
| 342 | + */ | |
| 343 | + if (report->id == FEATURE_KBD_LED_REPORT_ID1 || | |
| 344 | + report->id == FEATURE_KBD_LED_REPORT_ID2) { | |
| 345 | + return -1; | |
| 346 | + /* Additional report filtering */ | |
| 347 | + } else if (report->id == FEATURE_KBD_REPORT_ID) { | |
| 348 | + /* | |
| 349 | + * G14 and G15 send these codes on some keypresses with no | |
| 350 | + * discernable reason for doing so. We'll filter them out to avoid | |
| 351 | + * unmapped warning messages later. | |
| 352 | + */ | |
| 353 | + if (data[1] == 0xea || data[1] == 0xec || data[1] == 0x02 || | |
| 354 | + data[1] == 0x8a || data[1] == 0x9e) { | |
| 355 | + return -1; | |
| 356 | + } | |
| 357 | + } | |
| 358 | + } | |
| 359 | + | |
| 335 | 360 | return 0; |
| 336 | 361 | } |
| 337 | 362 | |
| @@ -344,7 +369,11 @@ static int asus_kbd_set_report(struct hid_device *hdev, u8 *buf, size_t buf_size · 6 unmodified lines | ||
| 344 | 369 | if (!dmabuf) |
| 345 | 370 | return -ENOMEM; |
| 346 | 371 | |
| 347 | − ret = hid_hw_raw_request(hdev, FEATURE_KBD_REPORT_ID, dmabuf, | |
| 372 | + /* | |
| 373 | + * The report ID should be set from the incoming buffer due to LED and key | |
| 374 | + * interfaces having different pages | |
| 375 | + */ | |
| 376 | + ret = hid_hw_raw_request(hdev, buf[0], dmabuf, | |
| 348 | 377 | buf_size, HID_FEATURE_REPORT, |
| 349 | 378 | HID_REQ_SET_REPORT); |
| 350 | 379 | kfree(dmabuf); |
| @@ -397,6 +426,51 @@ static int asus_kbd_get_functions(struct hid_device *hdev, · 46 unmodified lines | ||
| 397 | 426 | return ret; |
| 398 | 427 | } |
| 399 | 428 | |
| 429 | +static int rog_nkey_led_init(struct hid_device *hdev) | |
| 430 | +{ | |
| 431 | + u8 buf_init_start[] = { FEATURE_KBD_LED_REPORT_ID1, 0xB9 }; | |
| 432 | + u8 buf_init2[] = { FEATURE_KBD_LED_REPORT_ID1, 0x41, 0x53, 0x55, 0x53, 0x20, | |
| 433 | + 0x54, 0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 }; | |
| 434 | + u8 buf_init3[] = { FEATURE_KBD_LED_REPORT_ID1, | |
| 435 | + 0x05, 0x20, 0x31, 0x00, 0x08 }; | |
| 436 | + int ret; | |
| 437 | + | |
| 438 | + hid_info(hdev, "Asus initialise N-KEY Device"); | |
| 439 | + /* The first message is an init start */ | |
| 440 | + ret = asus_kbd_set_report(hdev, buf_init_start, sizeof(buf_init_start)); | |
| 441 | + if (ret < 0) { | |
| 442 | + hid_warn(hdev, "Asus failed to send init start command: %d\n", ret); | |
| 443 | + return ret; | |
| 444 | + } | |
| 445 | + /* Followed by a string */ | |
| 446 | + ret = asus_kbd_set_report(hdev, buf_init2, sizeof(buf_init2)); | |
| 447 | + if (ret < 0) { | |
| 448 | + hid_warn(hdev, "Asus failed to send init command 1.0: %d\n", ret); | |
| 449 | + return ret; | |
| 450 | + } | |
| 451 | + /* Followed by a string */ | |
| 452 | + ret = asus_kbd_set_report(hdev, buf_init3, sizeof(buf_init3)); | |
| 453 | + if (ret < 0) { | |
| 454 | + hid_warn(hdev, "Asus failed to send init command 1.1: %d\n", ret); | |
| 455 | + return ret; | |
| 456 | + } | |
| 457 | + | |
| 458 | + /* begin second report ID with same data */ | |
| 459 | + buf_init2[0] = FEATURE_KBD_LED_REPORT_ID2; | |
| 460 | + buf_init3[0] = FEATURE_KBD_LED_REPORT_ID2; | |
| 461 | + | |
| 462 | + ret = asus_kbd_set_report(hdev, buf_init2, sizeof(buf_init2)); | |
| 463 | + if (ret < 0) { | |
| 464 | + hid_warn(hdev, "Asus failed to send init command 2.0: %d\n", ret); | |
| 465 | + return ret; | |
| 466 | + } | |
| 467 | + ret = asus_kbd_set_report(hdev, buf_init3, sizeof(buf_init3)); | |
| 468 | + if (ret < 0) | |
| 469 | + hid_warn(hdev, "Asus failed to send init command 2.1: %d\n", ret); | |
| 470 | + | |
| 471 | + return ret; | |
| 472 | +} | |
| 473 | + | |
| 400 | 474 | static void asus_kbd_backlight_set(struct led_classdev *led_cdev, |
| 401 | 475 | enum led_brightness brightness) |
| 402 | 476 | { |
| @@ -460,19 +534,25 @@ static int asus_kbd_register_leds(struct hid_device *hdev) · 57 unmodified lines | ||
| 460 | 534 | unsigned char kbd_func; |
| 461 | 535 | int ret; |
| 462 | 536 | |
| 463 | − /* Initialize keyboard */ | |
| 464 | − ret = asus_kbd_init(hdev); | |
| 465 | − if (ret < 0) | |
| 466 | − return ret; | |
| 537 | + if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD) { | |
| 538 | + ret = rog_nkey_led_init(hdev); | |
| 539 | + if (ret < 0) | |
| 540 | + return ret; | |
| 541 | + } else { | |
| 542 | + /* Initialize keyboard */ | |
| 543 | + ret = asus_kbd_init(hdev); | |
| 544 | + if (ret < 0) | |
| 545 | + return ret; | |
| 467 | 546 | |
| 468 | − /* Get keyboard functions */ | |
| 469 | − ret = asus_kbd_get_functions(hdev, &kbd_func); | |
| 470 | − if (ret < 0) | |
| 471 | − return ret; | |
| 547 | + /* Get keyboard functions */ | |
| 548 | + ret = asus_kbd_get_functions(hdev, &kbd_func); | |
| 549 | + if (ret < 0) | |
| 550 | + return ret; | |
| 472 | 551 | |
| 473 | − /* Check for backlight support */ | |
| 474 | − if (!(kbd_func & SUPPORT_KBD_BACKLIGHT)) | |
| 475 | − return -ENODEV; | |
| 552 | + /* Check for backlight support */ | |
| 553 | + if (!(kbd_func & SUPPORT_KBD_BACKLIGHT)) | |
| 554 | + return -ENODEV; | |
| 555 | + } | |
| 476 | 556 | |
| 477 | 557 | drvdata->kbd_backlight = devm_kzalloc(&hdev->dev, |
| 478 | 558 | sizeof(struct asus_kbd_leds), |
| @@ -751,8 +831,8 @@ static int asus_input_mapping(struct hid_device *hdev, · 272 unmodified lines | ||
| 751 | 831 | usage->hid == (HID_UP_GENDEVCTRLS | 0x0026))) |
| 752 | 832 | return -1; |
| 753 | 833 | |
| 754 | − /* ASUS-specific keyboard hotkeys */ | |
| 755 | − if ((usage->hid & HID_USAGE_PAGE) == 0xff310000) { | |
| 834 | + /* ASUS-specific keyboard hotkeys and led backlight */ | |
| 835 | + if ((usage->hid & HID_USAGE_PAGE) == HID_UP_ASUSVENDOR) { | |
| 756 | 836 | switch (usage->hid & HID_USAGE) { |
| 757 | 837 | case 0x10: asus_map_key_clear(KEY_BRIGHTNESSDOWN); break; |
| 758 | 838 | case 0x20: asus_map_key_clear(KEY_BRIGHTNESSUP); break; |
| @@ -780,6 +860,18 @@ static int asus_input_mapping(struct hid_device *hdev, · 21 unmodified lines | ||
| 780 | 860 | /* Fn+F5 "fan" symbol on FX503VD */ |
| 781 | 861 | case 0x99: asus_map_key_clear(KEY_PROG4); break; |
| 782 | 862 | |
| 863 | + /* Fn+F5 "fan" symbol on N-Key keyboard */ | |
| 864 | + case 0xae: asus_map_key_clear(KEY_PROG4); break; | |
| 865 | + | |
| 866 | + /* Fn+Ret "Calc" symbol on N-Key keyboard */ | |
| 867 | + case 0x92: asus_map_key_clear(KEY_CALC); break; | |
| 868 | + | |
| 869 | + /* Fn+Left Aura mode previous on N-Key keyboard */ | |
| 870 | + case 0xb2: asus_map_key_clear(KEY_PROG2); break; | |
| 871 | + | |
| 872 | + /* Fn+Right Aura mode next on N-Key keyboard */ | |
| 873 | + case 0xb3: asus_map_key_clear(KEY_PROG3); break; | |
| 874 | + | |
| 783 | 875 | default: |
| 784 | 876 | /* ASUS lazily declares 256 usages, ignore the rest, |
| 785 | 877 | * as some make the keyboard appear as a pointer device. */ |
| @@ -1126,6 +1218,9 @@ static const struct hid_device_id asus_devices[] = { · 340 unmodified lines | ||
| 1126 | 1218 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, |
| 1127 | 1219 | USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD), |
| 1128 | 1220 | QUIRK_USE_KBD_BACKLIGHT }, |
| 1221 | + { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, | |
| 1222 | + USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD), | |
| 1223 | + QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD }, | |
| 1129 | 1224 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, |
| 1130 | 1225 | USB_DEVICE_ID_ASUSTEK_T100TA_KEYBOARD), |
| 1131 | 1226 | QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES }, |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 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 | /* |
| @@ -29,25 +30,26 @@ · 12 unmodified lines | ||
| 29 | 30 | * report descriptor but it does not appear that these enable software to |
| 30 | 31 | * control what the extra buttons map to. The only simple and straightforward |
| 31 | 32 | * solution seems to involve fixing up the report descriptor. |
| 32 | − * | |
| 33 | − * Report descriptor format: | |
| 34 | − * Positions 13, 15, 21 and 31 store the button bit count, button usage minimum, | |
| 35 | − * button usage maximum and padding bit count respectively. | |
| 36 | 33 | */ |
| 37 | 34 | #define MOUSE_BUTTONS_MAX 8 |
| 38 | 35 | static void mouse_button_fixup(struct hid_device *hdev, |
| 39 | 36 | __u8 *rdesc, unsigned int rsize, |
| 37 | + unsigned int button_bit_count, | |
| 38 | + unsigned int padding_bit, | |
| 39 | + unsigned int button_report_size, | |
| 40 | + unsigned int button_usage_maximum, | |
| 40 | 41 | int nbuttons) |
| 41 | 42 | { |
| 42 | − if (rsize < 32 || rdesc[12] != 0x95 || | |
| 43 | − rdesc[14] != 0x75 || rdesc[15] != 0x01 || | |
| 44 | − rdesc[20] != 0x29 || rdesc[30] != 0x75) | |
| 43 | + if (rsize < 32 || rdesc[button_bit_count] != 0x95 || | |
| 44 | + rdesc[button_report_size] != 0x75 || | |
| 45 | + rdesc[button_report_size + 1] != 0x01 || | |
| 46 | + rdesc[button_usage_maximum] != 0x29 || rdesc[padding_bit] != 0x75) | |
| 45 | 47 | return; |
| 46 | 48 | hid_info(hdev, "Fixing up Elecom mouse button count\n"); |
| 47 | 49 | nbuttons = clamp(nbuttons, 0, MOUSE_BUTTONS_MAX); |
| 48 | − rdesc[13] = nbuttons; | |
| 49 | − rdesc[21] = nbuttons; | |
| 50 | − rdesc[31] = MOUSE_BUTTONS_MAX - nbuttons; | |
| 50 | + rdesc[button_bit_count + 1] = nbuttons; | |
| 51 | + rdesc[button_usage_maximum + 1] = nbuttons; | |
| 52 | + rdesc[padding_bit + 1] = MOUSE_BUTTONS_MAX - nbuttons; | |
| 51 | 53 | } |
| 52 | 54 | |
| 53 | 55 | static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| @@ -62,16 +64,40 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, · 8 unmodified lines | ||
| 62 | 64 | rdesc[47] = 0x00; |
| 63 | 65 | } |
| 64 | 66 | break; |
| 67 | + case USB_DEVICE_ID_ELECOM_M_XGL20DLBK: | |
| 68 | + /* | |
| 69 | + * Report descriptor format: | |
| 70 | + * 20: button bit count | |
| 71 | + * 28: padding bit count | |
| 72 | + * 22: button report size | |
| 73 | + * 14: button usage maximum | |
| 74 | + */ | |
| 75 | + mouse_button_fixup(hdev, rdesc, *rsize, 20, 28, 22, 14, 8); | |
| 76 | + break; | |
| 65 | 77 | case USB_DEVICE_ID_ELECOM_M_XT3URBK: |
| 66 | 78 | case USB_DEVICE_ID_ELECOM_M_XT3DRBK: |
| 67 | 79 | case USB_DEVICE_ID_ELECOM_M_XT4DRBK: |
| 68 | − mouse_button_fixup(hdev, rdesc, *rsize, 6); | |
| 80 | + /* | |
| 81 | + * Report descriptor format: | |
| 82 | + * 12: button bit count | |
| 83 | + * 30: padding bit count | |
| 84 | + * 14: button report size | |
| 85 | + * 20: button usage maximum | |
| 86 | + */ | |
| 87 | + mouse_button_fixup(hdev, rdesc, *rsize, 12, 30, 14, 20, 6); | |
| 69 | 88 | break; |
| 70 | 89 | case USB_DEVICE_ID_ELECOM_M_DT1URBK: |
| 71 | 90 | case USB_DEVICE_ID_ELECOM_M_DT1DRBK: |
| 72 | 91 | case USB_DEVICE_ID_ELECOM_M_HT1URBK: |
| 73 | 92 | case USB_DEVICE_ID_ELECOM_M_HT1DRBK: |
| 74 | − mouse_button_fixup(hdev, rdesc, *rsize, 8); | |
| 93 | + /* | |
| 94 | + * Report descriptor format: | |
| 95 | + * 12: button bit count | |
| 96 | + * 30: padding bit count | |
| 97 | + * 14: button report size | |
| 98 | + * 20: button usage maximum | |
| 99 | + */ | |
| 100 | + mouse_button_fixup(hdev, rdesc, *rsize, 12, 30, 14, 20, 8); | |
| 75 | 101 | break; |
| 76 | 102 | } |
| 77 | 103 | return rdesc; |
| @@ -79,6 +105,7 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, · 1 unmodified line | ||
| 79 | 105 | |
| 80 | 106 | static const struct hid_device_id elecom_devices[] = { |
| 81 | 107 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, |
| 108 | + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XGL20DLBK) }, | |
| 82 | 109 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK) }, |
| 83 | 110 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK) }, |
| 84 | 111 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) }, |
| @@ -190,6 +190,7 @@ · 189 unmodified lines | ||
| 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 |
| @@ -359,6 +360,7 @@ · 163 unmodified lines | ||
| 359 | 360 | #define USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR 0x1803 |
| 360 | 361 | #define USB_DEVICE_ID_DRAGONRISE_GAMECUBE1 0x1843 |
| 361 | 362 | #define USB_DEVICE_ID_DRAGONRISE_GAMECUBE2 0x1844 |
| 363 | +#define USB_DEVICE_ID_DRAGONRISE_GAMECUBE3 0x1846 | |
| 362 | 364 | |
| 363 | 365 | #define USB_VENDOR_ID_DWAV 0x0eef |
| 364 | 366 | #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 |
| @@ -390,6 +392,7 @@ · 25 unmodified lines | ||
| 390 | 392 | |
| 391 | 393 | #define USB_VENDOR_ID_ELECOM 0x056e |
| 392 | 394 | #define USB_DEVICE_ID_ELECOM_BM084 0x0061 |
| 395 | +#define USB_DEVICE_ID_ELECOM_M_XGL20DLBK 0x00e6 | |
| 393 | 396 | #define USB_DEVICE_ID_ELECOM_M_XT3URBK 0x00fb |
| 394 | 397 | #define USB_DEVICE_ID_ELECOM_M_XT3DRBK 0x00fc |
| 395 | 398 | #define USB_DEVICE_ID_ELECOM_M_XT4DRBK 0x00fd |
| @@ -1074,6 +1077,9 @@ · 678 unmodified lines | ||
| 1074 | 1077 | #define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002 |
| 1075 | 1078 | #define USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER 0x1000 |
| 1076 | 1079 | |
| 1080 | +#define USB_VENDOR_ID_SONY_GHLIVE 0x12ba | |
| 1081 | +#define USB_DEVICE_ID_SONY_PS3WIIU_GHLIVE_DONGLE 0x074b | |
| 1082 | + | |
| 1077 | 1083 | #define USB_VENDOR_ID_SINO_LITE 0x1345 |
| 1078 | 1084 | #define USB_DEVICE_ID_SINO_LITE_CONTROLLER 0x3008 |
| 1079 | 1085 | |
| @@ -1133,6 +1139,7 @@ · 53 unmodified lines | ||
| 1133 | 1139 | #define USB_DEVICE_ID_SYNAPTICS_DELL_K12A 0x2819 |
| 1134 | 1140 | #define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012 0x2968 |
| 1135 | 1141 | #define USB_DEVICE_ID_SYNAPTICS_TP_V103 0x5710 |
| 1142 | +#define USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1002 0x73f4 | |
| 1136 | 1143 | #define USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1003 0x73f5 |
| 1137 | 1144 | #define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5 0x81a7 |
| 1138 | 1145 | |
| @@ -537,9 +537,12 @@ static void hidinput_update_battery(struct hid_device *dev, int value) · 536 unmodified lines | ||
| 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 | } |
| @@ -746,6 +749,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel · 200 unmodified lines | ||
| 746 | 749 | field->flags |= HID_MAIN_ITEM_RELATIVE; |
| 747 | 750 | break; |
| 748 | 751 | } |
| 752 | + goto unknown; | |
| 749 | 753 | |
| 750 | 754 | default: goto unknown; |
| 751 | 755 | } |
| @@ -18,10 +18,16 @@ static __u8 *ite_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int · 17 unmodified lines | ||
| 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; |
| 24 | 25 | } |
| 26 | + /* For Acer One S1002 keyboard-dock */ | |
| 27 | + if (*rsize == 188 && rdesc[185] == 0x81 && rdesc[186] == 0x02) { | |
| 28 | + hid_info(hdev, "Fixing up Acer S1002 ITE keyboard report descriptor\n"); | |
| 29 | + rdesc[186] = HID_MAIN_ITEM_RELATIVE; | |
| 30 | + } | |
| 25 | 31 | } |
| 26 | 32 | |
| 27 | 33 | return rdesc; |
| @@ -101,6 +107,11 @@ static const struct hid_device_id ite_devices[] = { · 73 unmodified lines | ||
| 101 | 107 | USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012), |
| 102 | 108 | .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT }, |
| 103 | 109 | /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */ |
| 110 | + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, | |
| 111 | + USB_VENDOR_ID_SYNAPTICS, | |
| 112 | + USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1002), | |
| 113 | + .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT }, | |
| 114 | + /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */ | |
| 104 | 115 | { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, |
| 105 | 116 | USB_VENDOR_ID_SYNAPTICS, |
| 106 | 117 | USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1003) }, |
| @@ -4048,6 +4048,8 @@ static const struct hid_device_id hidpp_devices[] = { · 4047 unmodified lines | ||
| 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 }, |
| @@ -153,6 +153,8 @@ static const struct hid_device_id mf_devices[] = { · 152 unmodified lines | ||
| 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); |
| @@ -72,6 +72,7 @@ static const struct hid_device_id hid_quirks[] = { · 71 unmodified lines | ||
| 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 }, |
| @@ -366,6 +367,7 @@ static const struct hid_device_id hid_have_special_driver[] = { · 288 unmodified lines | ||
| 366 | 367 | #endif |
| 367 | 368 | #if IS_ENABLED(CONFIG_HID_ELECOM) |
| 368 | 369 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, |
| 370 | + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XGL20DLBK) }, | |
| 369 | 371 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK) }, |
| 370 | 372 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK) }, |
| 371 | 373 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) }, |
| @@ -484,6 +486,7 @@ static const struct hid_device_id hid_have_special_driver[] = { · 112 unmodified lines | ||
| 484 | 486 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR) }, |
| 485 | 487 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1) }, |
| 486 | 488 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE2) }, |
| 489 | + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE3) }, | |
| 487 | 490 | #endif |
| 488 | 491 | #if IS_ENABLED(CONFIG_HID_MICROSOFT) |
| 489 | 492 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) }, |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 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 | /* |
| @@ -35,6 +36,8 @@ · 18 unmodified lines | ||
| 35 | 36 | #include <linux/idr.h> |
| 36 | 37 | #include <linux/input/mt.h> |
| 37 | 38 | #include <linux/crc32.h> |
| 39 | +#include <linux/usb.h> | |
| 40 | +#include <linux/timer.h> | |
| 38 | 41 | #include <asm/unaligned.h> |
| 39 | 42 | |
| 40 | 43 | #include "hid-ids.h" |
| @@ -56,6 +59,7 @@ · 15 unmodified lines | ||
| 56 | 59 | #define NSG_MR5U_REMOTE_BT BIT(14) |
| 57 | 60 | #define NSG_MR7U_REMOTE_BT BIT(15) |
| 58 | 61 | #define SHANWAN_GAMEPAD BIT(16) |
| 62 | +#define GHL_GUITAR_PS3WIIU BIT(17) | |
| 59 | 63 | |
| 60 | 64 | #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT) |
| 61 | 65 | #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT) |
| @@ -79,6 +83,17 @@ · 17 unmodified lines | ||
| 79 | 83 | #define NSG_MRXU_MAX_X 1667 |
| 80 | 84 | #define NSG_MRXU_MAX_Y 1868 |
| 81 | 85 | |
| 86 | +#define GHL_GUITAR_POKE_INTERVAL 10 /* In seconds */ | |
| 87 | +#define GHL_GUITAR_TILT_USAGE 44 | |
| 88 | + | |
| 89 | +/* Magic value and data taken from GHLtarUtility: | |
| 90 | + * https://github.com/ghlre/GHLtarUtility/blob/master/PS3Guitar.cs | |
| 91 | + * Note: The Wii U and PS3 dongles happen to share the same! | |
| 92 | + */ | |
| 93 | +static const u16 ghl_ps3wiiu_magic_value = 0x201; | |
| 94 | +static const char ghl_ps3wiiu_magic_data[] = { | |
| 95 | + 0x02, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00 | |
| 96 | +}; | |
| 82 | 97 | |
| 83 | 98 | /* PS/3 Motion controller */ |
| 84 | 99 | static u8 motion_rdesc[] = { |
| @@ -550,7 +565,9 @@ struct sony_sc { · 465 unmodified lines | ||
| 550 | 565 | struct power_supply_desc battery_desc; |
| 551 | 566 | int device_id; |
| 552 | 567 | unsigned fw_version; |
| 568 | + bool fw_version_created; | |
| 553 | 569 | unsigned hw_version; |
| 570 | + bool hw_version_created; | |
| 554 | 571 | u8 *output_report_dmabuf; |
| 555 | 572 | |
| 556 | 573 | #ifdef CONFIG_SONY_FF |
| @@ -562,9 +579,8 @@ struct sony_sc { · 5 unmodified lines | ||
| 562 | 579 | u8 hotplug_worker_initialized; |
| 563 | 580 | u8 state_worker_initialized; |
| 564 | 581 | u8 defer_initialization; |
| 565 | − u8 cable_state; | |
| 566 | − u8 battery_charging; | |
| 567 | 582 | u8 battery_capacity; |
| 583 | + int battery_status; | |
| 568 | 584 | u8 led_state[MAX_LEDS]; |
| 569 | 585 | u8 led_delay_on[MAX_LEDS]; |
| 570 | 586 | u8 led_delay_off[MAX_LEDS]; |
| @@ -578,6 +594,10 @@ struct sony_sc { · 7 unmodified lines | ||
| 578 | 594 | enum ds4_dongle_state ds4_dongle_state; |
| 579 | 595 | /* DS4 calibration data */ |
| 580 | 596 | struct ds4_calibration_data ds4_calib_data[6]; |
| 597 | + /* GH Live */ | |
| 598 | + struct timer_list ghl_poke_timer; | |
| 599 | + struct usb_ctrlrequest *ghl_cr; | |
| 600 | + u8 *ghl_databuf; | |
| 581 | 601 | }; |
| 582 | 602 | |
| 583 | 603 | static void sony_set_leds(struct sony_sc *sc); |
| @@ -601,6 +621,85 @@ static inline void sony_schedule_work(struct sony_sc *sc, · 17 unmodified lines | ||
| 601 | 621 | } |
| 602 | 622 | } |
| 603 | 623 | |
| 624 | +static void ghl_magic_poke_cb(struct urb *urb) | |
| 625 | +{ | |
| 626 | + if (urb) { | |
| 627 | + /* Free sc->ghl_cr and sc->ghl_databuf allocated in | |
| 628 | + * ghl_magic_poke() | |
| 629 | + */ | |
| 630 | + kfree(urb->setup_packet); | |
| 631 | + kfree(urb->transfer_buffer); | |
| 632 | + } | |
| 633 | +} | |
| 634 | + | |
| 635 | +static void ghl_magic_poke(struct timer_list *t) | |
| 636 | +{ | |
| 637 | + struct sony_sc *sc = from_timer(sc, t, ghl_poke_timer); | |
| 638 | + | |
| 639 | + int ret; | |
| 640 | + unsigned int pipe; | |
| 641 | + struct urb *urb; | |
| 642 | + struct usb_device *usbdev = to_usb_device(sc->hdev->dev.parent->parent); | |
| 643 | + const u16 poke_size = | |
| 644 | + ARRAY_SIZE(ghl_ps3wiiu_magic_data); | |
| 645 | + | |
| 646 | + pipe = usb_sndctrlpipe(usbdev, 0); | |
| 647 | + | |
| 648 | + if (!sc->ghl_cr) { | |
| 649 | + sc->ghl_cr = kzalloc(sizeof(*sc->ghl_cr), GFP_ATOMIC); | |
| 650 | + if (!sc->ghl_cr) | |
| 651 | + goto resched; | |
| 652 | + } | |
| 653 | + | |
| 654 | + if (!sc->ghl_databuf) { | |
| 655 | + sc->ghl_databuf = kzalloc(poke_size, GFP_ATOMIC); | |
| 656 | + if (!sc->ghl_databuf) | |
| 657 | + goto resched; | |
| 658 | + } | |
| 659 | + | |
| 660 | + urb = usb_alloc_urb(0, GFP_ATOMIC); | |
| 661 | + if (!urb) | |
| 662 | + goto resched; | |
| 663 | + | |
| 664 | + sc->ghl_cr->bRequestType = | |
| 665 | + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT; | |
| 666 | + sc->ghl_cr->bRequest = USB_REQ_SET_CONFIGURATION; | |
| 667 | + sc->ghl_cr->wValue = cpu_to_le16(ghl_ps3wiiu_magic_value); | |
| 668 | + sc->ghl_cr->wIndex = 0; | |
| 669 | + sc->ghl_cr->wLength = cpu_to_le16(poke_size); | |
| 670 | + memcpy(sc->ghl_databuf, ghl_ps3wiiu_magic_data, poke_size); | |
| 671 | + | |
| 672 | + usb_fill_control_urb( | |
| 673 | + urb, usbdev, pipe, | |
| 674 | + (unsigned char *) sc->ghl_cr, sc->ghl_databuf, | |
| 675 | + poke_size, ghl_magic_poke_cb, NULL); | |
| 676 | + ret = usb_submit_urb(urb, GFP_ATOMIC); | |
| 677 | + if (ret < 0) { | |
| 678 | + kfree(sc->ghl_databuf); | |
| 679 | + kfree(sc->ghl_cr); | |
| 680 | + } | |
| 681 | + usb_free_urb(urb); | |
| 682 | + | |
| 683 | +resched: | |
| 684 | + /* Reschedule for next time */ | |
| 685 | + mod_timer(&sc->ghl_poke_timer, jiffies + GHL_GUITAR_POKE_INTERVAL*HZ); | |
| 686 | +} | |
| 687 | + | |
| 688 | +static int guitar_mapping(struct hid_device *hdev, struct hid_input *hi, | |
| 689 | + struct hid_field *field, struct hid_usage *usage, | |
| 690 | + unsigned long **bit, int *max) | |
| 691 | +{ | |
| 692 | + if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR) { | |
| 693 | + unsigned int abs = usage->hid & HID_USAGE; | |
| 694 | + | |
| 695 | + if (abs == GHL_GUITAR_TILT_USAGE) { | |
| 696 | + hid_map_usage_clear(hi, usage, bit, max, EV_ABS, ABS_RY); | |
| 697 | + return 1; | |
| 698 | + } | |
| 699 | + } | |
| 700 | + return 0; | |
| 701 | +} | |
| 702 | + | |
| 604 | 703 | static ssize_t ds4_show_poll_interval(struct device *dev, |
| 605 | 704 | struct device_attribute |
| 606 | 705 | *attr, char *buf) |
| @@ -892,7 +991,8 @@ static void sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size) · 285 unmodified lines | ||
| 892 | 991 | static const u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 }; |
| 893 | 992 | unsigned long flags; |
| 894 | 993 | int offset; |
| 895 | − u8 cable_state, battery_capacity, battery_charging; | |
| 994 | + u8 battery_capacity; | |
| 995 | + int battery_status; | |
| 896 | 996 | |
| 897 | 997 | /* |
| 898 | 998 | * The sixaxis is charging if the battery value is 0xee |
| @@ -904,19 +1004,16 @@ static void sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size) · 5 unmodified lines | ||
| 904 | 1004 | |
| 905 | 1005 | if (rd[offset] >= 0xee) { |
| 906 | 1006 | battery_capacity = 100; |
| 907 | − battery_charging = !(rd[offset] & 0x01); | |
| 908 | − cable_state = 1; | |
| 1007 | + battery_status = (rd[offset] & 0x01) ? POWER_SUPPLY_STATUS_FULL : POWER_SUPPLY_STATUS_CHARGING; | |
| 909 | 1008 | } else { |
| 910 | 1009 | u8 index = rd[offset] <= 5 ? rd[offset] : 5; |
| 911 | 1010 | battery_capacity = sixaxis_battery_capacity[index]; |
| 912 | − battery_charging = 0; | |
| 913 | − cable_state = 0; | |
| 1011 | + battery_status = POWER_SUPPLY_STATUS_DISCHARGING; | |
| 914 | 1012 | } |
| 915 | 1013 | |
| 916 | 1014 | spin_lock_irqsave(&sc->lock, flags); |
| 917 | − sc->cable_state = cable_state; | |
| 918 | 1015 | sc->battery_capacity = battery_capacity; |
| 919 | − sc->battery_charging = battery_charging; | |
| 1016 | + sc->battery_status = battery_status; | |
| 920 | 1017 | spin_unlock_irqrestore(&sc->lock, flags); |
| 921 | 1018 | |
| 922 | 1019 | if (sc->quirks & SIXAXIS_CONTROLLER) { |
| @@ -944,7 +1041,8 @@ static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) · 21 unmodified lines | ||
| 944 | 1041 | struct input_dev *input_dev = hidinput->input; |
| 945 | 1042 | unsigned long flags; |
| 946 | 1043 | int n, m, offset, num_touch_data, max_touch_data; |
| 947 | − u8 cable_state, battery_capacity, battery_charging; | |
| 1044 | + u8 cable_state, battery_capacity; | |
| 1045 | + int battery_status; | |
| 948 | 1046 | u16 timestamp; |
| 949 | 1047 | |
| 950 | 1048 | /* When using Bluetooth the header is 2 bytes longer, so skip these. */ |
| @@ -1049,29 +1147,52 @@ static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) · 98 unmodified lines | ||
| 1049 | 1147 | */ |
| 1050 | 1148 | offset = data_offset + DS4_INPUT_REPORT_BATTERY_OFFSET; |
| 1051 | 1149 | cable_state = (rd[offset] >> 4) & 0x01; |
| 1052 | − battery_capacity = rd[offset] & 0x0F; | |
| 1053 | 1150 | |
| 1054 | 1151 | /* |
| 1055 | − * When a USB power source is connected the battery level ranges from | |
| 1056 | − * 0 to 10, and when running on battery power it ranges from 0 to 9. | |
| 1057 | − * A battery level above 10 when plugged in means charge completed. | |
| 1152 | + * Interpretation of the battery_capacity data depends on the cable state. | |
| 1153 | + * When no cable is connected (bit4 is 0): | |
| 1154 | + * - 0:10: percentage in units of 10%. | |
| 1155 | + * When a cable is plugged in: | |
| 1156 | + * - 0-10: percentage in units of 10%. | |
| 1157 | + * - 11: battery is full | |
| 1158 | + * - 14: not charging due to Voltage or temperature error | |
| 1159 | + * - 15: charge error | |
| 1058 | 1160 | */ |
| 1059 | − if (!cable_state || battery_capacity > 10) | |
| 1060 | − battery_charging = 0; | |
| 1061 | − else | |
| 1062 | − battery_charging = 1; | |
| 1161 | + if (cable_state) { | |
| 1162 | + u8 battery_data = rd[offset] & 0xf; | |
| 1163 | + | |
| 1164 | + if (battery_data < 10) { | |
| 1165 | + /* Take the mid-point for each battery capacity value, | |
| 1166 | + * because on the hardware side 0 = 0-9%, 1=10-19%, etc. | |
| 1167 | + * This matches official platform behavior, which does | |
| 1168 | + * the same. | |
| 1169 | + */ | |
| 1170 | + battery_capacity = battery_data * 10 + 5; | |
| 1171 | + battery_status = POWER_SUPPLY_STATUS_CHARGING; | |
| 1172 | + } else if (battery_data == 10) { | |
| 1173 | + battery_capacity = 100; | |
| 1174 | + battery_status = POWER_SUPPLY_STATUS_CHARGING; | |
| 1175 | + } else if (battery_data == 11) { | |
| 1176 | + battery_capacity = 100; | |
| 1177 | + battery_status = POWER_SUPPLY_STATUS_FULL; | |
| 1178 | + } else { /* 14, 15 and undefined values */ | |
| 1179 | + battery_capacity = 0; | |
| 1180 | + battery_status = POWER_SUPPLY_STATUS_UNKNOWN; | |
| 1181 | + } | |
| 1182 | + } else { | |
| 1183 | + u8 battery_data = rd[offset] & 0xf; | |
| 1063 | 1184 | |
| 1064 | − if (!cable_state) | |
| 1065 | − battery_capacity++; | |
| 1066 | − if (battery_capacity > 10) | |
| 1067 | − battery_capacity = 10; | |
| 1185 | + if (battery_data < 10) | |
| 1186 | + battery_capacity = battery_data * 10 + 5; | |
| 1187 | + else /* 10 */ | |
| 1188 | + battery_capacity = 100; | |
| 1068 | 1189 | |
| 1069 | − battery_capacity *= 10; | |
| 1190 | + battery_status = POWER_SUPPLY_STATUS_DISCHARGING; | |
| 1191 | + } | |
| 1070 | 1192 | |
| 1071 | 1193 | spin_lock_irqsave(&sc->lock, flags); |
| 1072 | − sc->cable_state = cable_state; | |
| 1073 | 1194 | sc->battery_capacity = battery_capacity; |
| 1074 | − sc->battery_charging = battery_charging; | |
| 1195 | + sc->battery_status = battery_status; | |
| 1075 | 1196 | spin_unlock_irqrestore(&sc->lock, flags); |
| 1076 | 1197 | |
| 1077 | 1198 | /* |
| @@ -1360,6 +1481,8 @@ static int sony_mapping(struct hid_device *hdev, struct hid_input *hi, · 282 unmodified lines | ||
| 1360 | 1481 | if (sc->quirks & DUALSHOCK4_CONTROLLER) |
| 1361 | 1482 | return ds4_mapping(hdev, hi, field, usage, bit, max); |
| 1362 | 1483 | |
| 1484 | + if (sc->quirks & GHL_GUITAR_PS3WIIU) | |
| 1485 | + return guitar_mapping(hdev, hi, field, usage, bit, max); | |
| 1363 | 1486 | |
| 1364 | 1487 | /* Let hid-core decide for the others */ |
| 1365 | 1488 | return 0; |
| @@ -1597,16 +1720,38 @@ static int dualshock4_get_calibration_data(struct sony_sc *sc) · 231 unmodified lines | ||
| 1597 | 1720 | * of the controller, so that it sends input reports of type 0x11. |
| 1598 | 1721 | */ |
| 1599 | 1722 | if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) { |
| 1723 | + int retries; | |
| 1724 | + | |
| 1600 | 1725 | buf = kmalloc(DS4_FEATURE_REPORT_0x02_SIZE, GFP_KERNEL); |
| 1601 | 1726 | if (!buf) |
| 1602 | 1727 | return -ENOMEM; |
| 1603 | 1728 | |
| 1604 | − ret = hid_hw_raw_request(sc->hdev, 0x02, buf, | |
| 1605 | − DS4_FEATURE_REPORT_0x02_SIZE, | |
| 1606 | − HID_FEATURE_REPORT, | |
| 1607 | − HID_REQ_GET_REPORT); | |
| 1608 | − if (ret < 0) | |
| 1609 | − goto err_stop; | |
| 1729 | + /* We should normally receive the feature report data we asked | |
| 1730 | + * for, but hidraw applications such as Steam can issue feature | |
| 1731 | + * reports as well. In particular for Dongle reconnects, Steam | |
| 1732 | + * and this function are competing resulting in often receiving | |
| 1733 | + * data for a different HID report, so retry a few times. | |
| 1734 | + */ | |
| 1735 | + for (retries = 0; retries < 3; retries++) { | |
| 1736 | + ret = hid_hw_raw_request(sc->hdev, 0x02, buf, | |
| 1737 | + DS4_FEATURE_REPORT_0x02_SIZE, | |
| 1738 | + HID_FEATURE_REPORT, | |
| 1739 | + HID_REQ_GET_REPORT); | |
| 1740 | + if (ret < 0) | |
| 1741 | + goto err_stop; | |
| 1742 | + | |
| 1743 | + if (buf[0] != 0x02) { | |
| 1744 | + if (retries < 2) { | |
| 1745 | + hid_warn(sc->hdev, "Retrying DualShock 4 get calibration report (0x02) request\n"); | |
| 1746 | + continue; | |
| 1747 | + } else { | |
| 1748 | + ret = -EILSEQ; | |
| 1749 | + goto err_stop; | |
| 1750 | + } | |
| 1751 | + } else { | |
| 1752 | + break; | |
| 1753 | + } | |
| 1754 | + } | |
| 1610 | 1755 | } else { |
| 1611 | 1756 | u8 bthdr = 0xA3; |
| 1612 | 1757 | u32 crc; |
| @@ -2300,12 +2445,12 @@ static int sony_battery_get_property(struct power_supply *psy, · 687 unmodified lines | ||
| 2300 | 2445 | struct sony_sc *sc = power_supply_get_drvdata(psy); |
| 2301 | 2446 | unsigned long flags; |
| 2302 | 2447 | int ret = 0; |
| 2303 | − u8 battery_charging, battery_capacity, cable_state; | |
| 2448 | + u8 battery_capacity; | |
| 2449 | + int battery_status; | |
| 2304 | 2450 | |
| 2305 | 2451 | spin_lock_irqsave(&sc->lock, flags); |
| 2306 | − battery_charging = sc->battery_charging; | |
| 2307 | 2452 | battery_capacity = sc->battery_capacity; |
| 2308 | − cable_state = sc->cable_state; | |
| 2453 | + battery_status = sc->battery_status; | |
| 2309 | 2454 | spin_unlock_irqrestore(&sc->lock, flags); |
| 2310 | 2455 | |
| 2311 | 2456 | switch (psp) { |
| @@ -2319,13 +2464,7 @@ static int sony_battery_get_property(struct power_supply *psy, · 7 unmodified lines | ||
| 2319 | 2464 | val->intval = battery_capacity; |
| 2320 | 2465 | break; |
| 2321 | 2466 | case POWER_SUPPLY_PROP_STATUS: |
| 2322 | − if (battery_charging) | |
| 2323 | − val->intval = POWER_SUPPLY_STATUS_CHARGING; | |
| 2324 | − else | |
| 2325 | − if (battery_capacity == 100 && cable_state) | |
| 2326 | − val->intval = POWER_SUPPLY_STATUS_FULL; | |
| 2327 | − else | |
| 2328 | − val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | |
| 2467 | + val->intval = battery_status; | |
| 2329 | 2468 | break; |
| 2330 | 2469 | default: |
| 2331 | 2470 | ret = -EINVAL; |
| @@ -2723,19 +2862,17 @@ static int sony_input_configured(struct hid_device *hdev, · 391 unmodified lines | ||
| 2723 | 2862 | |
| 2724 | 2863 | ret = device_create_file(&sc->hdev->dev, &dev_attr_firmware_version); |
| 2725 | 2864 | if (ret) { |
| 2726 | − /* Make zero for cleanup reasons of sysfs entries. */ | |
| 2727 | − sc->fw_version = 0; | |
| 2728 | − sc->hw_version = 0; | |
| 2729 | 2865 | hid_err(sc->hdev, "can't create sysfs firmware_version attribute err: %d\n", ret); |
| 2730 | 2866 | goto err_stop; |
| 2731 | 2867 | } |
| 2868 | + sc->fw_version_created = true; | |
| 2732 | 2869 | |
| 2733 | 2870 | ret = device_create_file(&sc->hdev->dev, &dev_attr_hardware_version); |
| 2734 | 2871 | if (ret) { |
| 2735 | − sc->hw_version = 0; | |
| 2736 | 2872 | hid_err(sc->hdev, "can't create sysfs hardware_version attribute err: %d\n", ret); |
| 2737 | 2873 | goto err_stop; |
| 2738 | 2874 | } |
| 2875 | + sc->hw_version_created = true; | |
| 2739 | 2876 | |
| 2740 | 2877 | /* |
| 2741 | 2878 | * The Dualshock 4 touchpad supports 2 touches and has a |
| @@ -2827,9 +2964,9 @@ err_stop: · 85 unmodified lines | ||
| 2827 | 2964 | */ |
| 2828 | 2965 | if (sc->ds4_bt_poll_interval) |
| 2829 | 2966 | device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval); |
| 2830 | − if (sc->fw_version) | |
| 2967 | + if (sc->fw_version_created) | |
| 2831 | 2968 | device_remove_file(&sc->hdev->dev, &dev_attr_firmware_version); |
| 2832 | − if (sc->hw_version) | |
| 2969 | + if (sc->hw_version_created) | |
| 2833 | 2970 | device_remove_file(&sc->hdev->dev, &dev_attr_hardware_version); |
| 2834 | 2971 | sony_cancel_work_sync(sc); |
| 2835 | 2972 | sony_remove_dev_list(sc); |
| @@ -2902,6 +3039,12 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) · 66 unmodified lines | ||
| 2902 | 3039 | return -ENODEV; |
| 2903 | 3040 | } |
| 2904 | 3041 | |
| 3042 | + if (sc->quirks & GHL_GUITAR_PS3WIIU) { | |
| 3043 | + timer_setup(&sc->ghl_poke_timer, ghl_magic_poke, 0); | |
| 3044 | + mod_timer(&sc->ghl_poke_timer, | |
| 3045 | + jiffies + GHL_GUITAR_POKE_INTERVAL*HZ); | |
| 3046 | + } | |
| 3047 | + | |
| 2905 | 3048 | return ret; |
| 2906 | 3049 | } |
| 2907 | 3050 | |
| @@ -2909,15 +3052,18 @@ static void sony_remove(struct hid_device *hdev) · 1 unmodified line | ||
| 2909 | 3052 | { |
| 2910 | 3053 | struct sony_sc *sc = hid_get_drvdata(hdev); |
| 2911 | 3054 | |
| 3055 | + if (sc->quirks & GHL_GUITAR_PS3WIIU) | |
| 3056 | + del_timer_sync(&sc->ghl_poke_timer); | |
| 3057 | + | |
| 2912 | 3058 | hid_hw_close(hdev); |
| 2913 | 3059 | |
| 2914 | 3060 | if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) |
| 2915 | 3061 | device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval); |
| 2916 | 3062 | |
| 2917 | − if (sc->fw_version) | |
| 3063 | + if (sc->fw_version_created) | |
| 2918 | 3064 | device_remove_file(&sc->hdev->dev, &dev_attr_firmware_version); |
| 2919 | 3065 | |
| 2920 | − if (sc->hw_version) | |
| 3066 | + if (sc->hw_version_created) | |
| 2921 | 3067 | device_remove_file(&sc->hdev->dev, &dev_attr_hardware_version); |
| 2922 | 3068 | |
| 2923 | 3069 | sony_cancel_work_sync(sc); |
| @@ -3020,6 +3166,9 @@ static const struct hid_device_id sony_devices[] = { · 96 unmodified lines | ||
| 3020 | 3166 | /* SMK-Link NSG-MR7U Remote Control */ |
| 3021 | 3167 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_NSG_MR7U_REMOTE), |
| 3022 | 3168 | .driver_data = NSG_MR7U_REMOTE_BT }, |
| 3169 | + /* Guitar Hero Live PS3 and Wii U guitar dongles */ | |
| 3170 | + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_GHLIVE, USB_DEVICE_ID_SONY_PS3WIIU_GHLIVE_DONGLE), | |
| 3171 | + .driver_data = GHL_GUITAR_PS3WIIU}, | |
| 3023 | 3172 | { } |
| 3024 | 3173 | }; |
| 3025 | 3174 | MODULE_DEVICE_TABLE(hid, sony_devices); |
| @@ -170,7 +170,7 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t · 169 unmodified lines | ||
| 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 | */ |
| @@ -428,6 +428,28 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, · 251 unmodified lines | ||
| 428 | 428 | break; |
| 429 | 429 | } |
| 430 | 430 | |
| 431 | + if (_IOC_NR(cmd) == _IOC_NR(HIDIOCSINPUT(0))) { | |
| 432 | + int len = _IOC_SIZE(cmd); | |
| 433 | + ret = hidraw_send_report(file, user_arg, len, HID_INPUT_REPORT); | |
| 434 | + break; | |
| 435 | + } | |
| 436 | + if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGINPUT(0))) { | |
| 437 | + int len = _IOC_SIZE(cmd); | |
| 438 | + ret = hidraw_get_report(file, user_arg, len, HID_INPUT_REPORT); | |
| 439 | + break; | |
| 440 | + } | |
| 441 | + | |
| 442 | + if (_IOC_NR(cmd) == _IOC_NR(HIDIOCSOUTPUT(0))) { | |
| 443 | + int len = _IOC_SIZE(cmd); | |
| 444 | + ret = hidraw_send_report(file, user_arg, len, HID_OUTPUT_REPORT); | |
| 445 | + break; | |
| 446 | + } | |
| 447 | + if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGOUTPUT(0))) { | |
| 448 | + int len = _IOC_SIZE(cmd); | |
| 449 | + ret = hidraw_get_report(file, user_arg, len, HID_OUTPUT_REPORT); | |
| 450 | + break; | |
| 451 | + } | |
| 452 | + | |
| 431 | 453 | /* Begin Read-only ioctls. */ |
| 432 | 454 | if (_IOC_DIR(cmd) != _IOC_READ) { |
| 433 | 455 | ret = -EINVAL; |
| @@ -1106,8 +1106,11 @@ static int i2c_hid_probe(struct i2c_client *client, · 1105 unmodified lines | ||
| 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) |
| @@ -405,6 +405,14 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = { · 404 unmodified lines | ||
| 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 | |
| @@ -211,10 +211,8 @@ int ishtp_hid_probe(unsigned int cur_hid_dev, · 210 unmodified lines | ||
| 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) { |
| @@ -438,6 +438,7 @@ static void hid_irq_out(struct urb *urb) · 437 unmodified lines | ||
| 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 */ |
| @@ -489,6 +490,7 @@ static void hid_ctrl(struct urb *urb) · 45 unmodified lines | ||
| 489 | 490 | break; |
| 490 | 491 | case -ESHUTDOWN: /* unplug */ |
| 491 | 492 | unplug = 1; |
| 493 | + break; | |
| 492 | 494 | case -EILSEQ: /* protocol error or unplug */ |
| 493 | 495 | case -EPROTO: /* protocol error or unplug */ |
| 494 | 496 | case -ECONNRESET: /* unlink */ |
| @@ -1173,7 +1173,7 @@ static struct attribute *cintiq_led_attrs[] = { · 1172 unmodified lines | ||
| 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,7 +1194,7 @@ static struct attribute *intuos4_led_attrs[] = { · 14 unmodified lines | ||
| 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,7 +1205,7 @@ static struct attribute *intuos5_led_attrs[] = { · 4 unmodified lines | ||
| 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,13 +1216,13 @@ static struct attribute *generic_led_attrs[] = { · 4 unmodified lines | ||
| 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,7 +1238,7 @@ static void wacom_devm_sysfs_group_release(struct device *dev, void *res) · 9 unmodified lines | ||
| 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,7 +1264,7 @@ static int __wacom_devm_sysfs_create_group(struct wacom *wacom, · 19 unmodified lines | ||
| 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,7 +1847,7 @@ static struct attribute *remote##SET_ID##_serial_attrs[] = { \ · 576 unmodified lines | ||
| 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 | } |
| @@ -494,7 +494,7 @@ struct hid_report_enum { · 493 unmodified lines | ||
| 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,6 +585,7 @@ struct hid_device { /* device report descriptor */ · 84 unmodified lines | ||
| 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 */ |
| @@ -40,6 +40,12 @@ struct hidraw_devinfo { · 39 unmodified lines | ||
| 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 |
| @@ -128,7 +128,7 @@ int main(int argc, char **argv) · 127 unmodified lines | ||
| 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"); |