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