1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * ISHTP-HID glue driver. 4 * 5 * Copyright (c) 2012-2016, Intel Corporation. 6 */ 7 8 #include <linux/hid.h> 9 #include <linux/intel-ish-client-if.h> 10 #include <uapi/linux/input.h> 11 #include "ishtp-hid.h" 12 13 /** 14 * ishtp_hid_parse() - hid-core .parse() callback 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 ishtp_hid_parse(struct hid_device *hid) 22 { 23 struct ishtp_hid_data *hid_data = hid->driver_data; 24 struct ishtp_cl_data *client_data = hid_data->client_data; 25 int rv; 26 27 rv = hid_parse_report(hid, client_data->report_descr[hid_data->index], 28 client_data->report_descr_size[hid_data->index]); 29 if (rv) 30 return rv; 31 32 return 0; 33 } 34 35 /* Empty callbacks with success return code */ 36 static int ishtp_hid_start(struct hid_device *hid) 37 { 38 return 0; 39 } 40 41 static void ishtp_hid_stop(struct hid_device *hid) 42 { 43 } 44 45 static int ishtp_hid_open(struct hid_device *hid) 46 { 47 return 0; 48 } 49 50 static void ishtp_hid_close(struct hid_device *hid) 51 { 52 } 53 54 static int ishtp_raw_request(struct hid_device *hid, unsigned char reportnum, 55 __u8 *buf, size_t len, unsigned char rtype, 56 int reqtype) 57 { 58 struct ishtp_hid_data *hid_data = hid->driver_data; 59 char *ishtp_buf = NULL; 60 size_t ishtp_buf_len; 61 unsigned int header_size = sizeof(struct hostif_msg); 62 63 if (rtype == HID_OUTPUT_REPORT) 64 return -EINVAL; 65 66 hid_data->request_done = false; 67 switch (reqtype) { 68 case HID_REQ_GET_REPORT: 69 hid_data->raw_buf = buf; 70 hid_data->raw_buf_size = len; 71 hid_data->raw_get_req = true; 72 73 hid_ishtp_get_report(hid, reportnum, rtype); 74 break; 75 case HID_REQ_SET_REPORT: 76 /* 77 * Spare 7 bytes for 64b accesses through 78 * get/put_unaligned_le64() 79 */ 80 ishtp_buf_len = len + header_size; 81 ishtp_buf = kzalloc(ishtp_buf_len + 7, GFP_KERNEL); 82 if (!ishtp_buf) 83 return -ENOMEM; 84 85 memcpy(ishtp_buf + header_size, buf, len); 86 hid_ishtp_set_feature(hid, ishtp_buf, ishtp_buf_len, reportnum); 87 kfree(ishtp_buf); 88 break; 89 } 90 91 hid_hw_wait(hid); 92 93 return len; 94 } 95 96 /** 97 * ishtp_hid_request() - hid-core .request() callback 98 * @hid: hid device instance 99 * @rep: pointer to hid_report 100 * @reqtype: type of req. [GET|SET]_REPORT 101 * 102 * This function is used to set/get feaure/input report. 103 */ 104 static void ishtp_hid_request(struct hid_device *hid, struct hid_report *rep, 105 int reqtype) 106 { 107 struct ishtp_hid_data *hid_data = hid->driver_data; 108 /* the specific report length, just HID part of it */ 109 unsigned int len = ((rep->size - 1) >> 3) + 1 + (rep->id > 0); 110 char *buf; 111 unsigned int header_size = sizeof(struct hostif_msg); 112 113 len += header_size; 114 115 hid_data->request_done = false; 116 switch (reqtype) { 117 case HID_REQ_GET_REPORT: 118 hid_data->raw_get_req = false; 119 hid_ishtp_get_report(hid, rep->id, rep->type); 120 break; 121 case HID_REQ_SET_REPORT: 122 /* 123 * Spare 7 bytes for 64b accesses through 124 * get/put_unaligned_le64() 125 */ 126 buf = kzalloc(len + 7, GFP_KERNEL); 127 if (!buf) 128 return; 129 130 hid_output_report(rep, buf + header_size); 131 hid_ishtp_set_feature(hid, buf, len, rep->id); 132 kfree(buf); 133 break; 134 } 135 } 136 137 /** 138 * ishtp_wait_for_response() - hid-core .wait() callback 139 * @hid: hid device instance 140 * 141 * This function is used to wait after get feaure/input report. 142 * 143 * Return: 0 on success and non zero on error 144 */ 145 static int ishtp_wait_for_response(struct hid_device *hid) 146 { 147 struct ishtp_hid_data *hid_data = hid->driver_data; 148 int rv; 149 150 hid_ishtp_trace(client_data, "%s hid %p\n", __func__, hid); 151 152 rv = ishtp_hid_link_ready_wait(hid_data->client_data); 153 if (rv) 154 return rv; 155 156 if (!hid_data->request_done) 157 wait_event_interruptible_timeout(hid_data->hid_wait, 158 hid_data->request_done, 3 * HZ); 159 160 if (!hid_data->request_done) { 161 hid_err(hid, 162 "timeout waiting for response from ISHTP device\n"); 163 return -ETIMEDOUT; 164 } 165 hid_ishtp_trace(client_data, "%s hid %p done\n", __func__, hid); 166 167 hid_data->request_done = false; 168 169 return 0; 170 } 171 172 /** 173 * ishtp_hid_wakeup() - Wakeup caller 174 * @hid: hid device instance 175 * 176 * This function will wakeup caller waiting for Get/Set feature report 177 */ 178 void ishtp_hid_wakeup(struct hid_device *hid) 179 { 180 struct ishtp_hid_data *hid_data = hid->driver_data; 181 182 hid_data->request_done = true; 183 wake_up_interruptible(&hid_data->hid_wait); 184 } 185 186 static struct hid_ll_driver ishtp_hid_ll_driver = { 187 .parse = ishtp_hid_parse, 188 .start = ishtp_hid_start, 189 .stop = ishtp_hid_stop, 190 .open = ishtp_hid_open, 191 .close = ishtp_hid_close, 192 .request = ishtp_hid_request, 193 .wait = ishtp_wait_for_response, 194 .raw_request = ishtp_raw_request 195 }; 196 197 /** 198 * ishtp_hid_probe() - hid register ll driver 199 * @cur_hid_dev: Index of hid device calling to register 200 * @client_data: Client data pointer 201 * 202 * This function is used to allocate and add HID device. 203 * 204 * Return: 0 on success, non zero on error 205 */ 206 int ishtp_hid_probe(unsigned int cur_hid_dev, 207 struct ishtp_cl_data *client_data) 208 { 209 int rv; 210 struct hid_device *hid; 211 struct ishtp_hid_data *hid_data; 212 213 hid = hid_allocate_device(); 214 if (IS_ERR(hid)) 215 return PTR_ERR(hid); 216 217 hid_data = kzalloc(sizeof(*hid_data), GFP_KERNEL); 218 if (!hid_data) { 219 rv = -ENOMEM; 220 goto err_hid_data; 221 } 222 223 hid_data->index = cur_hid_dev; 224 hid_data->client_data = client_data; 225 init_waitqueue_head(&hid_data->hid_wait); 226 227 hid->driver_data = hid_data; 228 229 client_data->hid_sensor_hubs[cur_hid_dev] = hid; 230 231 hid->ll_driver = &ishtp_hid_ll_driver; 232 hid->bus = BUS_INTEL_ISHTP; 233 hid->dev.parent = ishtp_device(client_data->cl_device); 234 235 hid->version = le16_to_cpu(ISH_HID_VERSION); 236 hid->vendor = le16_to_cpu(client_data->hid_devices[cur_hid_dev].vid); 237 hid->product = le16_to_cpu(client_data->hid_devices[cur_hid_dev].pid); 238 snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "hid-ishtp", 239 hid->vendor, hid->product); 240 241 rv = hid_add_device(hid); 242 if (rv) 243 goto err_hid_device; 244 245 hid_ishtp_trace(client_data, "%s allocated hid %p\n", __func__, hid); 246 247 return 0; 248 249 err_hid_device: 250 kfree(hid_data); 251 err_hid_data: 252 hid_destroy_device(hid); 253 return rv; 254 } 255 256 /** 257 * ishtp_hid_probe() - Remove registered hid device 258 * @client_data: client data pointer 259 * 260 * This function is used to destroy allocatd HID device. 261 */ 262 void ishtp_hid_remove(struct ishtp_cl_data *client_data) 263 { 264 int i; 265 266 for (i = 0; i < client_data->num_hid_devices; ++i) { 267 if (client_data->hid_sensor_hubs[i]) { 268 kfree(client_data->hid_sensor_hubs[i]->driver_data); 269 hid_destroy_device(client_data->hid_sensor_hubs[i]); 270 client_data->hid_sensor_hubs[i] = NULL; 271 } 272 } 273 } 274