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