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

HID: intel-thc-hid: intel-quicki2c: Add THC QuickI2C driver hid layer

Add HID Low level driver callbacks and hid probe function to register
QucikI2C as a HID driver, and external touch device as a HID device.

Co-developed-by: Xinpeng Sun <xinpeng.sun@intel.com>
Signed-off-by: Xinpeng Sun <xinpeng.sun@intel.com>
Signed-off-by: Even Xu <even.xu@intel.com>
Tested-by: Rui Zhang <rui1.zhang@intel.com>
Tested-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Reviewed-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Tested-by: Aaron Ma <aaron.ma@canonical.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>

authored by

Even Xu and committed by
Jiri Kosina
ba38d7f8 61bb2714

+212
+1
drivers/hid/intel-thc-hid/Makefile
··· 16 16 17 17 obj-$(CONFIG_INTEL_QUICKI2C) += intel-quicki2c.o 18 18 intel-quicki2c-objs += intel-quicki2c/pci-quicki2c.o 19 + intel-quicki2c-objs += intel-quicki2c/quicki2c-hid.o 19 20 20 21 ccflags-y += -I $(src)/intel-thc
+11
drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h
··· 4 4 #ifndef _QUICKI2C_DEV_H_ 5 5 #define _QUICKI2C_DEV_H_ 6 6 7 + #include <linux/hid-over-i2c.h> 8 + 7 9 #define THC_LNL_DEVICE_ID_I2C_PORT1 0xA848 8 10 #define THC_LNL_DEVICE_ID_I2C_PORT2 0xA84A 9 11 #define THC_PTL_H_DEVICE_ID_I2C_PORT1 0xE348 ··· 28 26 struct device; 29 27 struct pci_dev; 30 28 struct thc_device; 29 + struct hid_device; 31 30 32 31 /** 33 32 * struct quicki2c_device - THC QuickI2C device struct 34 33 * @dev: point to kernel device 35 34 * @pdev: point to PCI device 36 35 * @thc_hw: point to THC device 36 + * @hid_dev: point to hid device 37 37 * @driver_data: point to quicki2c specific driver data 38 38 * @state: THC I2C device state 39 39 * @mem_addr: MMIO memory address 40 + * @dev_desc: device descriptor for HIDI2C protocol 41 + * @report_descriptor: store a copy of device report descriptor 40 42 */ 41 43 struct quicki2c_device { 42 44 struct device *dev; 43 45 struct pci_dev *pdev; 44 46 struct thc_device *thc_hw; 47 + struct hid_device *hid_dev; 45 48 enum quicki2c_dev_state state; 46 49 47 50 void __iomem *mem_addr; 51 + 52 + struct hidi2c_dev_descriptor dev_desc; 53 + 54 + u8 *report_descriptor; 48 55 }; 49 56 50 57 #endif /* _QUICKI2C_DEV_H_ */
+142
drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-hid.c
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2024 Intel Corporation */ 3 + 4 + #include <linux/hid.h> 5 + #include <linux/input.h> 6 + 7 + #include "quicki2c-dev.h" 8 + #include "quicki2c-hid.h" 9 + 10 + /** 11 + * quicki2c_hid_parse() - HID core parse() callback 12 + * 13 + * @hid: HID device instance 14 + * 15 + * This function gets called during call to hid_add_device 16 + * 17 + * Return: 0 on success and non zero on error. 18 + */ 19 + static int quicki2c_hid_parse(struct hid_device *hid) 20 + { 21 + struct quicki2c_device *qcdev = hid->driver_data; 22 + 23 + if (qcdev->report_descriptor) 24 + return hid_parse_report(hid, qcdev->report_descriptor, 25 + le16_to_cpu(qcdev->dev_desc.report_desc_len)); 26 + 27 + dev_err_once(qcdev->dev, "invalid report descriptor\n"); 28 + return -EINVAL; 29 + } 30 + 31 + static int quicki2c_hid_start(struct hid_device *hid) 32 + { 33 + return 0; 34 + } 35 + 36 + static void quicki2c_hid_stop(struct hid_device *hid) 37 + { 38 + } 39 + 40 + static int quicki2c_hid_open(struct hid_device *hid) 41 + { 42 + return 0; 43 + } 44 + 45 + static void quicki2c_hid_close(struct hid_device *hid) 46 + { 47 + } 48 + 49 + static int quicki2c_hid_raw_request(struct hid_device *hid, 50 + unsigned char reportnum, 51 + __u8 *buf, size_t len, 52 + unsigned char rtype, int reqtype) 53 + { 54 + return 0; 55 + } 56 + 57 + static int quicki2c_hid_power(struct hid_device *hid, int lvl) 58 + { 59 + return 0; 60 + } 61 + 62 + static struct hid_ll_driver quicki2c_hid_ll_driver = { 63 + .parse = quicki2c_hid_parse, 64 + .start = quicki2c_hid_start, 65 + .stop = quicki2c_hid_stop, 66 + .open = quicki2c_hid_open, 67 + .close = quicki2c_hid_close, 68 + .power = quicki2c_hid_power, 69 + .raw_request = quicki2c_hid_raw_request, 70 + }; 71 + 72 + /** 73 + * quicki2c_hid_probe() - Register HID low level driver 74 + * 75 + * @qcdev: point to quicki2c device 76 + * 77 + * This function is used to allocate and add HID device. 78 + * 79 + * Return: 0 on success, non zero on error. 80 + */ 81 + int quicki2c_hid_probe(struct quicki2c_device *qcdev) 82 + { 83 + struct hid_device *hid; 84 + int ret; 85 + 86 + hid = hid_allocate_device(); 87 + if (IS_ERR(hid)) 88 + return PTR_ERR(hid); 89 + 90 + hid->ll_driver = &quicki2c_hid_ll_driver; 91 + hid->bus = BUS_PCI; 92 + hid->dev.parent = qcdev->dev; 93 + hid->driver_data = qcdev; 94 + hid->version = le16_to_cpu(qcdev->dev_desc.version_id); 95 + hid->vendor = le16_to_cpu(qcdev->dev_desc.vendor_id); 96 + hid->product = le16_to_cpu(qcdev->dev_desc.product_id); 97 + snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "quicki2c-hid", 98 + hid->vendor, hid->product); 99 + 100 + ret = hid_add_device(hid); 101 + if (ret) { 102 + hid_destroy_device(hid); 103 + return ret; 104 + } 105 + 106 + qcdev->hid_dev = hid; 107 + 108 + return 0; 109 + } 110 + 111 + /** 112 + * quicki2c_hid_remove() - Destroy HID device 113 + * 114 + * @qcdev: point to quicki2c device 115 + * 116 + * Return: 0 on success, non zero on error. 117 + */ 118 + void quicki2c_hid_remove(struct quicki2c_device *qcdev) 119 + { 120 + hid_destroy_device(qcdev->hid_dev); 121 + } 122 + 123 + /** 124 + * quicki2c_hid_send_report() - Send HID input report data to HID core 125 + * 126 + * @qcdev: point to quicki2c device 127 + * @data: point to input report data buffer 128 + * @data_len: the length of input report data 129 + * 130 + * Return: 0 on success, non zero on error. 131 + */ 132 + int quicki2c_hid_send_report(struct quicki2c_device *qcdev, 133 + void *data, size_t data_len) 134 + { 135 + int ret; 136 + 137 + ret = hid_input_report(qcdev->hid_dev, HID_INPUT_REPORT, data, data_len, 1); 138 + if (ret) 139 + dev_err(qcdev->dev, "Failed to send HID input report, ret = %d.\n", ret); 140 + 141 + return ret; 142 + }
+14
drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-hid.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2024 Intel Corporation */ 3 + 4 + #ifndef _QUICKI2C_HID_H_ 5 + #define _QUICKI2C_HID_H_ 6 + 7 + struct quicki2c_device; 8 + 9 + int quicki2c_hid_send_report(struct quicki2c_device *qcdev, 10 + void *data, size_t data_size); 11 + int quicki2c_hid_probe(struct quicki2c_device *qcdev); 12 + void quicki2c_hid_remove(struct quicki2c_device *qcdev); 13 + 14 + #endif /* _QUICKI2C_HID_H_ */
+44
include/linux/hid-over-i2c.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright 2024 Intel Corporation */ 3 + 4 + #ifndef _HID_OVER_I2C_H_ 5 + #define _HID_OVER_I2C_H_ 6 + 7 + /** 8 + * struct hidi2c_dev_descriptor - HIDI2C device descriptor definition 9 + * @dev_desc_len: The length of the complete device descriptor, fixed to 0x1E (30). 10 + * @bcd_ver: The version number of the HIDI2C protocol supported. 11 + * In binary coded decimal (BCD) format. 12 + * @report_desc_len: The length of the report descriptor 13 + * @report_desc_reg: The register address to retrieve report descriptor 14 + * @input_reg: the register address to retrieve input report 15 + * @max_input_len: The length of the largest possible HID input (or feature) report 16 + * @output_reg: the register address to send output report 17 + * @max_output_len: The length of the largest output (or feature) report 18 + * @cmd_reg: the register address to send command 19 + * @data_reg: the register address to send command data 20 + * @vendor_id: Device manufacturers vendor ID 21 + * @product_id: Device unique model/product ID 22 + * @version_id: Device’s unique version 23 + * @reserved0: Reserved and should be 0 24 + * @reserved1: Reserved and should be 0 25 + */ 26 + struct hidi2c_dev_descriptor { 27 + __le16 dev_desc_len; 28 + __le16 bcd_ver; 29 + __le16 report_desc_len; 30 + __le16 report_desc_reg; 31 + __le16 input_reg; 32 + __le16 max_input_len; 33 + __le16 output_reg; 34 + __le16 max_output_len; 35 + __le16 cmd_reg; 36 + __le16 data_reg; 37 + __le16 vendor_id; 38 + __le16 product_id; 39 + __le16 version_id; 40 + __le16 reserved0; 41 + __le16 reserved1; 42 + } __packed; 43 + 44 + #endif /* _HID_OVER_I2C_H_ */