hid.c (11774B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * HID class driver for the Greybus. 4 * 5 * Copyright 2014 Google Inc. 6 * Copyright 2014 Linaro Ltd. 7 */ 8 9#include <linux/bitops.h> 10#include <linux/hid.h> 11#include <linux/kernel.h> 12#include <linux/module.h> 13#include <linux/mutex.h> 14#include <linux/slab.h> 15#include <linux/greybus.h> 16 17/* Greybus HID device's structure */ 18struct gb_hid { 19 struct gb_bundle *bundle; 20 struct gb_connection *connection; 21 22 struct hid_device *hid; 23 struct gb_hid_desc_response hdesc; 24 25 unsigned long flags; 26#define GB_HID_STARTED 0x01 27#define GB_HID_READ_PENDING 0x04 28 29 unsigned int bufsize; 30 char *inbuf; 31}; 32 33/* Routines to get controller's information over greybus */ 34 35/* Operations performed on greybus */ 36static int gb_hid_get_desc(struct gb_hid *ghid) 37{ 38 return gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_DESC, NULL, 39 0, &ghid->hdesc, sizeof(ghid->hdesc)); 40} 41 42static int gb_hid_get_report_desc(struct gb_hid *ghid, char *rdesc) 43{ 44 int ret; 45 46 ret = gb_pm_runtime_get_sync(ghid->bundle); 47 if (ret) 48 return ret; 49 50 ret = gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT_DESC, 51 NULL, 0, rdesc, 52 le16_to_cpu(ghid->hdesc.wReportDescLength)); 53 54 gb_pm_runtime_put_autosuspend(ghid->bundle); 55 56 return ret; 57} 58 59static int gb_hid_set_power(struct gb_hid *ghid, int type) 60{ 61 int ret; 62 63 ret = gb_pm_runtime_get_sync(ghid->bundle); 64 if (ret) 65 return ret; 66 67 ret = gb_operation_sync(ghid->connection, type, NULL, 0, NULL, 0); 68 69 gb_pm_runtime_put_autosuspend(ghid->bundle); 70 71 return ret; 72} 73 74static int gb_hid_get_report(struct gb_hid *ghid, u8 report_type, u8 report_id, 75 unsigned char *buf, int len) 76{ 77 struct gb_hid_get_report_request request; 78 int ret; 79 80 ret = gb_pm_runtime_get_sync(ghid->bundle); 81 if (ret) 82 return ret; 83 84 request.report_type = report_type; 85 request.report_id = report_id; 86 87 ret = gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT, 88 &request, sizeof(request), buf, len); 89 90 gb_pm_runtime_put_autosuspend(ghid->bundle); 91 92 return ret; 93} 94 95static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, 96 unsigned char *buf, int len) 97{ 98 struct gb_hid_set_report_request *request; 99 struct gb_operation *operation; 100 int ret, size = sizeof(*request) + len - 1; 101 102 ret = gb_pm_runtime_get_sync(ghid->bundle); 103 if (ret) 104 return ret; 105 106 operation = gb_operation_create(ghid->connection, 107 GB_HID_TYPE_SET_REPORT, size, 0, 108 GFP_KERNEL); 109 if (!operation) { 110 gb_pm_runtime_put_autosuspend(ghid->bundle); 111 return -ENOMEM; 112 } 113 114 request = operation->request->payload; 115 request->report_type = report_type; 116 request->report_id = report_id; 117 memcpy(request->report, buf, len); 118 119 ret = gb_operation_request_send_sync(operation); 120 if (ret) { 121 dev_err(&operation->connection->bundle->dev, 122 "failed to set report: %d\n", ret); 123 } else { 124 ret = len; 125 } 126 127 gb_operation_put(operation); 128 gb_pm_runtime_put_autosuspend(ghid->bundle); 129 130 return ret; 131} 132 133static int gb_hid_request_handler(struct gb_operation *op) 134{ 135 struct gb_connection *connection = op->connection; 136 struct gb_hid *ghid = gb_connection_get_data(connection); 137 struct gb_hid_input_report_request *request = op->request->payload; 138 139 if (op->type != GB_HID_TYPE_IRQ_EVENT) { 140 dev_err(&connection->bundle->dev, 141 "unsupported unsolicited request\n"); 142 return -EINVAL; 143 } 144 145 if (test_bit(GB_HID_STARTED, &ghid->flags)) 146 hid_input_report(ghid->hid, HID_INPUT_REPORT, 147 request->report, op->request->payload_size, 1); 148 149 return 0; 150} 151 152static int gb_hid_report_len(struct hid_report *report) 153{ 154 return ((report->size - 1) >> 3) + 1 + 155 report->device->report_enum[report->type].numbered; 156} 157 158static void gb_hid_find_max_report(struct hid_device *hid, unsigned int type, 159 unsigned int *max) 160{ 161 struct hid_report *report; 162 unsigned int size; 163 164 list_for_each_entry(report, &hid->report_enum[type].report_list, list) { 165 size = gb_hid_report_len(report); 166 if (*max < size) 167 *max = size; 168 } 169} 170 171static void gb_hid_free_buffers(struct gb_hid *ghid) 172{ 173 kfree(ghid->inbuf); 174 ghid->inbuf = NULL; 175 ghid->bufsize = 0; 176} 177 178static int gb_hid_alloc_buffers(struct gb_hid *ghid, size_t bufsize) 179{ 180 ghid->inbuf = kzalloc(bufsize, GFP_KERNEL); 181 if (!ghid->inbuf) 182 return -ENOMEM; 183 184 ghid->bufsize = bufsize; 185 186 return 0; 187} 188 189/* Routines dealing with reports */ 190static void gb_hid_init_report(struct gb_hid *ghid, struct hid_report *report) 191{ 192 unsigned int size; 193 194 size = gb_hid_report_len(report); 195 if (gb_hid_get_report(ghid, report->type, report->id, ghid->inbuf, 196 size)) 197 return; 198 199 /* 200 * hid->driver_lock is held as we are in probe function, 201 * we just need to setup the input fields, so using 202 * hid_report_raw_event is safe. 203 */ 204 hid_report_raw_event(ghid->hid, report->type, ghid->inbuf, size, 1); 205} 206 207static void gb_hid_init_reports(struct gb_hid *ghid) 208{ 209 struct hid_device *hid = ghid->hid; 210 struct hid_report *report; 211 212 list_for_each_entry(report, 213 &hid->report_enum[HID_INPUT_REPORT].report_list, 214 list) 215 gb_hid_init_report(ghid, report); 216 217 list_for_each_entry(report, 218 &hid->report_enum[HID_FEATURE_REPORT].report_list, 219 list) 220 gb_hid_init_report(ghid, report); 221} 222 223static int __gb_hid_get_raw_report(struct hid_device *hid, 224 unsigned char report_number, __u8 *buf, size_t count, 225 unsigned char report_type) 226{ 227 struct gb_hid *ghid = hid->driver_data; 228 int ret; 229 230 if (report_type == HID_OUTPUT_REPORT) 231 return -EINVAL; 232 233 ret = gb_hid_get_report(ghid, report_type, report_number, buf, count); 234 if (!ret) 235 ret = count; 236 237 return ret; 238} 239 240static int __gb_hid_output_raw_report(struct hid_device *hid, __u8 *buf, 241 size_t len, unsigned char report_type) 242{ 243 struct gb_hid *ghid = hid->driver_data; 244 int report_id = buf[0]; 245 int ret; 246 247 if (report_type == HID_INPUT_REPORT) 248 return -EINVAL; 249 250 if (report_id) { 251 buf++; 252 len--; 253 } 254 255 ret = gb_hid_set_report(ghid, report_type, report_id, buf, len); 256 if (report_id && ret >= 0) 257 ret++; /* add report_id to the number of transferred bytes */ 258 259 return 0; 260} 261 262static int gb_hid_raw_request(struct hid_device *hid, unsigned char reportnum, 263 __u8 *buf, size_t len, unsigned char rtype, 264 int reqtype) 265{ 266 switch (reqtype) { 267 case HID_REQ_GET_REPORT: 268 return __gb_hid_get_raw_report(hid, reportnum, buf, len, rtype); 269 case HID_REQ_SET_REPORT: 270 if (buf[0] != reportnum) 271 return -EINVAL; 272 return __gb_hid_output_raw_report(hid, buf, len, rtype); 273 default: 274 return -EIO; 275 } 276} 277 278/* HID Callbacks */ 279static int gb_hid_parse(struct hid_device *hid) 280{ 281 struct gb_hid *ghid = hid->driver_data; 282 unsigned int rsize; 283 char *rdesc; 284 int ret; 285 286 rsize = le16_to_cpu(ghid->hdesc.wReportDescLength); 287 if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) { 288 dbg_hid("weird size of report descriptor (%u)\n", rsize); 289 return -EINVAL; 290 } 291 292 rdesc = kzalloc(rsize, GFP_KERNEL); 293 if (!rdesc) 294 return -ENOMEM; 295 296 ret = gb_hid_get_report_desc(ghid, rdesc); 297 if (ret) { 298 hid_err(hid, "reading report descriptor failed\n"); 299 goto free_rdesc; 300 } 301 302 ret = hid_parse_report(hid, rdesc, rsize); 303 if (ret) 304 dbg_hid("parsing report descriptor failed\n"); 305 306free_rdesc: 307 kfree(rdesc); 308 309 return ret; 310} 311 312static int gb_hid_start(struct hid_device *hid) 313{ 314 struct gb_hid *ghid = hid->driver_data; 315 unsigned int bufsize = HID_MIN_BUFFER_SIZE; 316 int ret; 317 318 gb_hid_find_max_report(hid, HID_INPUT_REPORT, &bufsize); 319 gb_hid_find_max_report(hid, HID_OUTPUT_REPORT, &bufsize); 320 gb_hid_find_max_report(hid, HID_FEATURE_REPORT, &bufsize); 321 322 if (bufsize > HID_MAX_BUFFER_SIZE) 323 bufsize = HID_MAX_BUFFER_SIZE; 324 325 ret = gb_hid_alloc_buffers(ghid, bufsize); 326 if (ret) 327 return ret; 328 329 if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS)) 330 gb_hid_init_reports(ghid); 331 332 return 0; 333} 334 335static void gb_hid_stop(struct hid_device *hid) 336{ 337 struct gb_hid *ghid = hid->driver_data; 338 339 gb_hid_free_buffers(ghid); 340} 341 342static int gb_hid_open(struct hid_device *hid) 343{ 344 struct gb_hid *ghid = hid->driver_data; 345 int ret; 346 347 ret = gb_hid_set_power(ghid, GB_HID_TYPE_PWR_ON); 348 if (ret < 0) 349 return ret; 350 351 set_bit(GB_HID_STARTED, &ghid->flags); 352 return 0; 353} 354 355static void gb_hid_close(struct hid_device *hid) 356{ 357 struct gb_hid *ghid = hid->driver_data; 358 int ret; 359 360 clear_bit(GB_HID_STARTED, &ghid->flags); 361 362 /* Save some power */ 363 ret = gb_hid_set_power(ghid, GB_HID_TYPE_PWR_OFF); 364 if (ret) 365 dev_err(&ghid->connection->bundle->dev, 366 "failed to power off (%d)\n", ret); 367} 368 369static int gb_hid_power(struct hid_device *hid, int lvl) 370{ 371 struct gb_hid *ghid = hid->driver_data; 372 373 switch (lvl) { 374 case PM_HINT_FULLON: 375 return gb_hid_set_power(ghid, GB_HID_TYPE_PWR_ON); 376 case PM_HINT_NORMAL: 377 return gb_hid_set_power(ghid, GB_HID_TYPE_PWR_OFF); 378 } 379 380 return 0; 381} 382 383/* HID structure to pass callbacks */ 384static struct hid_ll_driver gb_hid_ll_driver = { 385 .parse = gb_hid_parse, 386 .start = gb_hid_start, 387 .stop = gb_hid_stop, 388 .open = gb_hid_open, 389 .close = gb_hid_close, 390 .power = gb_hid_power, 391 .raw_request = gb_hid_raw_request, 392}; 393 394static int gb_hid_init(struct gb_hid *ghid) 395{ 396 struct hid_device *hid = ghid->hid; 397 int ret; 398 399 ret = gb_hid_get_desc(ghid); 400 if (ret) 401 return ret; 402 403 hid->version = le16_to_cpu(ghid->hdesc.bcdHID); 404 hid->vendor = le16_to_cpu(ghid->hdesc.wVendorID); 405 hid->product = le16_to_cpu(ghid->hdesc.wProductID); 406 hid->country = ghid->hdesc.bCountryCode; 407 408 hid->driver_data = ghid; 409 hid->ll_driver = &gb_hid_ll_driver; 410 hid->dev.parent = &ghid->connection->bundle->dev; 411// hid->bus = BUS_GREYBUS; /* Need a bustype for GREYBUS in <linux/input.h> */ 412 413 /* Set HID device's name */ 414 snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", 415 dev_name(&ghid->connection->bundle->dev), 416 hid->vendor, hid->product); 417 418 return 0; 419} 420 421static int gb_hid_probe(struct gb_bundle *bundle, 422 const struct greybus_bundle_id *id) 423{ 424 struct greybus_descriptor_cport *cport_desc; 425 struct gb_connection *connection; 426 struct hid_device *hid; 427 struct gb_hid *ghid; 428 int ret; 429 430 if (bundle->num_cports != 1) 431 return -ENODEV; 432 433 cport_desc = &bundle->cport_desc[0]; 434 if (cport_desc->protocol_id != GREYBUS_PROTOCOL_HID) 435 return -ENODEV; 436 437 ghid = kzalloc(sizeof(*ghid), GFP_KERNEL); 438 if (!ghid) 439 return -ENOMEM; 440 441 connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), 442 gb_hid_request_handler); 443 if (IS_ERR(connection)) { 444 ret = PTR_ERR(connection); 445 goto err_free_ghid; 446 } 447 448 gb_connection_set_data(connection, ghid); 449 ghid->connection = connection; 450 451 hid = hid_allocate_device(); 452 if (IS_ERR(hid)) { 453 ret = PTR_ERR(hid); 454 goto err_connection_destroy; 455 } 456 457 ghid->hid = hid; 458 ghid->bundle = bundle; 459 460 greybus_set_drvdata(bundle, ghid); 461 462 ret = gb_connection_enable(connection); 463 if (ret) 464 goto err_destroy_hid; 465 466 ret = gb_hid_init(ghid); 467 if (ret) 468 goto err_connection_disable; 469 470 ret = hid_add_device(hid); 471 if (ret) { 472 hid_err(hid, "can't add hid device: %d\n", ret); 473 goto err_connection_disable; 474 } 475 476 gb_pm_runtime_put_autosuspend(bundle); 477 478 return 0; 479 480err_connection_disable: 481 gb_connection_disable(connection); 482err_destroy_hid: 483 hid_destroy_device(hid); 484err_connection_destroy: 485 gb_connection_destroy(connection); 486err_free_ghid: 487 kfree(ghid); 488 489 return ret; 490} 491 492static void gb_hid_disconnect(struct gb_bundle *bundle) 493{ 494 struct gb_hid *ghid = greybus_get_drvdata(bundle); 495 496 if (gb_pm_runtime_get_sync(bundle)) 497 gb_pm_runtime_get_noresume(bundle); 498 499 hid_destroy_device(ghid->hid); 500 gb_connection_disable(ghid->connection); 501 gb_connection_destroy(ghid->connection); 502 kfree(ghid); 503} 504 505static const struct greybus_bundle_id gb_hid_id_table[] = { 506 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_HID) }, 507 { } 508}; 509MODULE_DEVICE_TABLE(greybus, gb_hid_id_table); 510 511static struct greybus_driver gb_hid_driver = { 512 .name = "hid", 513 .probe = gb_hid_probe, 514 .disconnect = gb_hid_disconnect, 515 .id_table = gb_hid_id_table, 516}; 517module_greybus_driver(gb_hid_driver); 518 519MODULE_LICENSE("GPL v2");