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 #include <linux/pm_runtime.h> 7 8 #include "quicki2c-dev.h" 9 #include "quicki2c-hid.h" 10 #include "quicki2c-protocol.h" 11 12 /** 13 * quicki2c_hid_parse() - HID core parse() callback 14 * 15 * @hid: HID device instance 16 * 17 * This function gets called during call to hid_add_device 18 * 19 * Return: 0 on success and non zero on error. 20 */ 21 static int quicki2c_hid_parse(struct hid_device *hid) 22 { 23 struct quicki2c_device *qcdev = hid->driver_data; 24 25 if (qcdev->report_descriptor) 26 return hid_parse_report(hid, qcdev->report_descriptor, 27 le16_to_cpu(qcdev->dev_desc.report_desc_len)); 28 29 dev_err_once(qcdev->dev, "invalid report descriptor\n"); 30 return -EINVAL; 31 } 32 33 static int quicki2c_hid_start(struct hid_device *hid) 34 { 35 return 0; 36 } 37 38 static void quicki2c_hid_stop(struct hid_device *hid) 39 { 40 } 41 42 static int quicki2c_hid_open(struct hid_device *hid) 43 { 44 return 0; 45 } 46 47 static void quicki2c_hid_close(struct hid_device *hid) 48 { 49 } 50 51 static int quicki2c_hid_raw_request(struct hid_device *hid, 52 unsigned char reportnum, 53 __u8 *buf, size_t len, 54 unsigned char rtype, int reqtype) 55 { 56 struct quicki2c_device *qcdev = hid->driver_data; 57 int ret = 0; 58 59 ret = pm_runtime_resume_and_get(qcdev->dev); 60 if (ret) 61 return ret; 62 63 switch (reqtype) { 64 case HID_REQ_GET_REPORT: 65 ret = quicki2c_get_report(qcdev, rtype, reportnum, buf, len); 66 break; 67 case HID_REQ_SET_REPORT: 68 ret = quicki2c_set_report(qcdev, rtype, reportnum, buf, len); 69 break; 70 default: 71 dev_err(qcdev->dev, "Not supported request type %d\n", reqtype); 72 break; 73 } 74 75 pm_runtime_put_autosuspend(qcdev->dev); 76 77 return ret; 78 } 79 80 static int quicki2c_hid_power(struct hid_device *hid, int lvl) 81 { 82 return 0; 83 } 84 85 static int quicki2c_hid_output_report(struct hid_device *hid, u8 *buf, size_t count) 86 { 87 struct quicki2c_device *qcdev = hid->driver_data; 88 89 return quicki2c_output_report(qcdev, buf, count); 90 } 91 92 static struct hid_ll_driver quicki2c_hid_ll_driver = { 93 .parse = quicki2c_hid_parse, 94 .start = quicki2c_hid_start, 95 .stop = quicki2c_hid_stop, 96 .open = quicki2c_hid_open, 97 .close = quicki2c_hid_close, 98 .power = quicki2c_hid_power, 99 .raw_request = quicki2c_hid_raw_request, 100 .output_report = quicki2c_hid_output_report, 101 }; 102 103 /** 104 * quicki2c_hid_probe() - Register HID low level driver 105 * 106 * @qcdev: point to quicki2c device 107 * 108 * This function is used to allocate and add HID device. 109 * 110 * Return: 0 on success, non zero on error. 111 */ 112 int quicki2c_hid_probe(struct quicki2c_device *qcdev) 113 { 114 struct hid_device *hid; 115 int ret; 116 117 hid = hid_allocate_device(); 118 if (IS_ERR(hid)) 119 return PTR_ERR(hid); 120 121 hid->ll_driver = &quicki2c_hid_ll_driver; 122 hid->bus = BUS_PCI; 123 hid->dev.parent = qcdev->dev; 124 hid->driver_data = qcdev; 125 hid->version = le16_to_cpu(qcdev->dev_desc.version_id); 126 hid->vendor = le16_to_cpu(qcdev->dev_desc.vendor_id); 127 hid->product = le16_to_cpu(qcdev->dev_desc.product_id); 128 snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "quicki2c-hid", 129 hid->vendor, hid->product); 130 strscpy(hid->phys, dev_name(qcdev->dev), sizeof(hid->phys)); 131 132 ret = hid_add_device(hid); 133 if (ret) { 134 hid_destroy_device(hid); 135 return ret; 136 } 137 138 qcdev->hid_dev = hid; 139 140 return 0; 141 } 142 143 /** 144 * quicki2c_hid_remove() - Destroy HID device 145 * 146 * @qcdev: point to quicki2c device 147 * 148 * Return: 0 on success, non zero on error. 149 */ 150 void quicki2c_hid_remove(struct quicki2c_device *qcdev) 151 { 152 hid_destroy_device(qcdev->hid_dev); 153 } 154 155 /** 156 * quicki2c_hid_send_report() - Send HID input report data to HID core 157 * 158 * @qcdev: point to quicki2c device 159 * @data: point to input report data buffer 160 * @data_len: the length of input report data 161 * 162 * Return: 0 on success, non zero on error. 163 */ 164 int quicki2c_hid_send_report(struct quicki2c_device *qcdev, 165 void *data, size_t data_len) 166 { 167 int ret; 168 169 ret = hid_input_report(qcdev->hid_dev, HID_INPUT_REPORT, data, data_len, 1); 170 if (ret) 171 dev_err(qcdev->dev, "Failed to send HID input report, ret = %d.\n", ret); 172 173 return ret; 174 } 175