1 // SPDX-License-Identifier: GPL-2.0-only 2 /*************************************************************************** 3 * Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org> * 4 * * 5 * Based on Logitech G13 driver (v0.4) * 6 * Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu> * 7 * * 8 ***************************************************************************/ 9 10 #include <linux/hid.h> 11 #include <linux/hid-debug.h> 12 #include <linux/input.h> 13 #include "hid-ids.h" 14 15 #include <linux/fb.h> 16 #include <linux/vmalloc.h> 17 18 #include <linux/completion.h> 19 #include <linux/uaccess.h> 20 #include <linux/module.h> 21 #include <linux/string.h> 22 23 #include "hid-picolcd.h" 24 25 26 /* Input device 27 * 28 * The PicoLCD has an IR receiver header, a built-in keypad with 5 keys 29 * and header for 4x4 key matrix. The built-in keys are part of the matrix. 30 */ 31 static const unsigned short def_keymap[PICOLCD_KEYS] = { 32 KEY_RESERVED, /* none */ 33 KEY_BACK, /* col 4 + row 1 */ 34 KEY_HOMEPAGE, /* col 3 + row 1 */ 35 KEY_RESERVED, /* col 2 + row 1 */ 36 KEY_RESERVED, /* col 1 + row 1 */ 37 KEY_SCROLLUP, /* col 4 + row 2 */ 38 KEY_OK, /* col 3 + row 2 */ 39 KEY_SCROLLDOWN, /* col 2 + row 2 */ 40 KEY_RESERVED, /* col 1 + row 2 */ 41 KEY_RESERVED, /* col 4 + row 3 */ 42 KEY_RESERVED, /* col 3 + row 3 */ 43 KEY_RESERVED, /* col 2 + row 3 */ 44 KEY_RESERVED, /* col 1 + row 3 */ 45 KEY_RESERVED, /* col 4 + row 4 */ 46 KEY_RESERVED, /* col 3 + row 4 */ 47 KEY_RESERVED, /* col 2 + row 4 */ 48 KEY_RESERVED, /* col 1 + row 4 */ 49 }; 50 51 52 /* Find a given report */ 53 struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir) 54 { 55 struct list_head *feature_report_list = &hdev->report_enum[dir].report_list; 56 struct hid_report *report = NULL; 57 58 list_for_each_entry(report, feature_report_list, list) { 59 if (report->id == id) 60 return report; 61 } 62 hid_warn(hdev, "No report with id 0x%x found\n", id); 63 return NULL; 64 } 65 66 /* Submit a report and wait for a reply from device - if device fades away 67 * or does not respond in time, return NULL */ 68 struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev, 69 int report_id, const u8 *raw_data, int size) 70 { 71 struct picolcd_data *data = hid_get_drvdata(hdev); 72 struct picolcd_pending *work; 73 struct hid_report *report = picolcd_out_report(report_id, hdev); 74 unsigned long flags; 75 int i, j; 76 unsigned int k; 77 78 if (!report || !data) 79 return NULL; 80 if (data->status & PICOLCD_FAILED) 81 return NULL; 82 work = kzalloc_obj(*work); 83 if (!work) 84 return NULL; 85 86 init_completion(&work->ready); 87 work->out_report = report; 88 work->in_report = NULL; 89 work->raw_size = 0; 90 91 mutex_lock(&data->mutex); 92 spin_lock_irqsave(&data->lock, flags); 93 for (i = k = 0; i < report->maxfield; i++) 94 for (j = 0; j < report->field[i]->report_count; j++) { 95 hid_set_field(report->field[i], j, k < size ? raw_data[k] : 0); 96 k++; 97 } 98 if (data->status & PICOLCD_FAILED) { 99 kfree(work); 100 work = NULL; 101 } else { 102 data->pending = work; 103 hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT); 104 spin_unlock_irqrestore(&data->lock, flags); 105 wait_for_completion_interruptible_timeout(&work->ready, HZ*2); 106 spin_lock_irqsave(&data->lock, flags); 107 data->pending = NULL; 108 } 109 spin_unlock_irqrestore(&data->lock, flags); 110 mutex_unlock(&data->mutex); 111 return work; 112 } 113 114 /* 115 * input class device 116 */ 117 static int picolcd_raw_keypad(struct picolcd_data *data, 118 struct hid_report *report, u8 *raw_data, int size) 119 { 120 /* 121 * Keypad event 122 * First and second data bytes list currently pressed keys, 123 * 0x00 means no key and at most 2 keys may be pressed at same time 124 */ 125 int i, j; 126 127 /* determine newly pressed keys */ 128 for (i = 0; i < size; i++) { 129 unsigned int key_code; 130 if (raw_data[i] == 0) 131 continue; 132 for (j = 0; j < sizeof(data->pressed_keys); j++) 133 if (data->pressed_keys[j] == raw_data[i]) 134 goto key_already_down; 135 for (j = 0; j < sizeof(data->pressed_keys); j++) 136 if (data->pressed_keys[j] == 0) { 137 data->pressed_keys[j] = raw_data[i]; 138 break; 139 } 140 input_event(data->input_keys, EV_MSC, MSC_SCAN, raw_data[i]); 141 if (raw_data[i] < PICOLCD_KEYS) 142 key_code = data->keycode[raw_data[i]]; 143 else 144 key_code = KEY_UNKNOWN; 145 if (key_code != KEY_UNKNOWN) { 146 dbg_hid(PICOLCD_NAME " got key press for %u:%d", 147 raw_data[i], key_code); 148 input_report_key(data->input_keys, key_code, 1); 149 } 150 input_sync(data->input_keys); 151 key_already_down: 152 continue; 153 } 154 155 /* determine newly released keys */ 156 for (j = 0; j < sizeof(data->pressed_keys); j++) { 157 unsigned int key_code; 158 if (data->pressed_keys[j] == 0) 159 continue; 160 for (i = 0; i < size; i++) 161 if (data->pressed_keys[j] == raw_data[i]) 162 goto key_still_down; 163 input_event(data->input_keys, EV_MSC, MSC_SCAN, data->pressed_keys[j]); 164 if (data->pressed_keys[j] < PICOLCD_KEYS) 165 key_code = data->keycode[data->pressed_keys[j]]; 166 else 167 key_code = KEY_UNKNOWN; 168 if (key_code != KEY_UNKNOWN) { 169 dbg_hid(PICOLCD_NAME " got key release for %u:%d", 170 data->pressed_keys[j], key_code); 171 input_report_key(data->input_keys, key_code, 0); 172 } 173 input_sync(data->input_keys); 174 data->pressed_keys[j] = 0; 175 key_still_down: 176 continue; 177 } 178 return 1; 179 } 180 181 static int picolcd_check_version(struct hid_device *hdev) 182 { 183 struct picolcd_data *data = hid_get_drvdata(hdev); 184 struct picolcd_pending *verinfo; 185 int ret = 0; 186 187 if (!data) 188 return -ENODEV; 189 190 verinfo = picolcd_send_and_wait(hdev, REPORT_VERSION, NULL, 0); 191 if (!verinfo) { 192 hid_err(hdev, "no version response from PicoLCD\n"); 193 return -ENODEV; 194 } 195 196 if (verinfo->raw_size == 2) { 197 data->version[0] = verinfo->raw_data[1]; 198 data->version[1] = verinfo->raw_data[0]; 199 if (data->status & PICOLCD_BOOTLOADER) { 200 hid_info(hdev, "PicoLCD, bootloader version %d.%d\n", 201 verinfo->raw_data[1], verinfo->raw_data[0]); 202 } else { 203 hid_info(hdev, "PicoLCD, firmware version %d.%d\n", 204 verinfo->raw_data[1], verinfo->raw_data[0]); 205 } 206 } else { 207 hid_err(hdev, "confused, got unexpected version response from PicoLCD\n"); 208 ret = -EINVAL; 209 } 210 kfree(verinfo); 211 return ret; 212 } 213 214 /* 215 * Reset our device and wait for answer to VERSION request 216 */ 217 int picolcd_reset(struct hid_device *hdev) 218 { 219 struct picolcd_data *data = hid_get_drvdata(hdev); 220 struct hid_report *report = picolcd_out_report(REPORT_RESET, hdev); 221 unsigned long flags; 222 int error; 223 224 if (!data || !report || report->maxfield != 1) 225 return -ENODEV; 226 227 spin_lock_irqsave(&data->lock, flags); 228 if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER) 229 data->status |= PICOLCD_BOOTLOADER; 230 231 /* perform the reset */ 232 hid_set_field(report->field[0], 0, 1); 233 if (data->status & PICOLCD_FAILED) { 234 spin_unlock_irqrestore(&data->lock, flags); 235 return -ENODEV; 236 } 237 hid_hw_request(hdev, report, HID_REQ_SET_REPORT); 238 spin_unlock_irqrestore(&data->lock, flags); 239 240 error = picolcd_check_version(hdev); 241 if (error) 242 return error; 243 244 picolcd_resume_lcd(data); 245 picolcd_resume_backlight(data); 246 picolcd_fb_refresh(data); 247 picolcd_leds_set(data); 248 return 0; 249 } 250 251 /* 252 * The "operation_mode" sysfs attribute 253 */ 254 static ssize_t picolcd_operation_mode_show(struct device *dev, 255 struct device_attribute *attr, char *buf) 256 { 257 struct picolcd_data *data = dev_get_drvdata(dev); 258 259 if (data->status & PICOLCD_BOOTLOADER) 260 return sysfs_emit(buf, "[bootloader] lcd\n"); 261 else 262 return sysfs_emit(buf, "bootloader [lcd]\n"); 263 } 264 265 static ssize_t picolcd_operation_mode_store(struct device *dev, 266 struct device_attribute *attr, const char *buf, size_t count) 267 { 268 struct picolcd_data *data = dev_get_drvdata(dev); 269 struct hid_report *report = NULL; 270 int timeout = data->opmode_delay; 271 unsigned long flags; 272 273 if (sysfs_streq(buf, "lcd")) { 274 if (data->status & PICOLCD_BOOTLOADER) 275 report = picolcd_out_report(REPORT_EXIT_FLASHER, data->hdev); 276 } else if (sysfs_streq(buf, "bootloader")) { 277 if (!(data->status & PICOLCD_BOOTLOADER)) 278 report = picolcd_out_report(REPORT_EXIT_KEYBOARD, data->hdev); 279 } else { 280 return -EINVAL; 281 } 282 283 if (!report || report->maxfield != 1) 284 return -EINVAL; 285 286 spin_lock_irqsave(&data->lock, flags); 287 hid_set_field(report->field[0], 0, timeout & 0xff); 288 hid_set_field(report->field[0], 1, (timeout >> 8) & 0xff); 289 hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT); 290 spin_unlock_irqrestore(&data->lock, flags); 291 return count; 292 } 293 294 static DEVICE_ATTR(operation_mode, 0644, picolcd_operation_mode_show, 295 picolcd_operation_mode_store); 296 297 /* 298 * The "operation_mode_delay" sysfs attribute 299 */ 300 static ssize_t picolcd_operation_mode_delay_show(struct device *dev, 301 struct device_attribute *attr, char *buf) 302 { 303 struct picolcd_data *data = dev_get_drvdata(dev); 304 305 return sysfs_emit(buf, "%hu\n", data->opmode_delay); 306 } 307 308 static ssize_t picolcd_operation_mode_delay_store(struct device *dev, 309 struct device_attribute *attr, const char *buf, size_t count) 310 { 311 struct picolcd_data *data = dev_get_drvdata(dev); 312 unsigned u; 313 if (sscanf(buf, "%u", &u) != 1) 314 return -EINVAL; 315 if (u > 30000) 316 return -EINVAL; 317 else 318 data->opmode_delay = u; 319 return count; 320 } 321 322 static DEVICE_ATTR(operation_mode_delay, 0644, picolcd_operation_mode_delay_show, 323 picolcd_operation_mode_delay_store); 324 325 /* 326 * Handle raw report as sent by device 327 */ 328 static int picolcd_raw_event(struct hid_device *hdev, 329 struct hid_report *report, u8 *raw_data, int size) 330 { 331 struct picolcd_data *data = hid_get_drvdata(hdev); 332 unsigned long flags; 333 334 if (!data) 335 return 1; 336 337 if (size > 64) { 338 hid_warn(hdev, "invalid size value (%d) for picolcd raw event (%d)\n", 339 size, report->id); 340 return 0; 341 } 342 343 if (report->id == REPORT_KEY_STATE) { 344 if (data->input_keys) 345 picolcd_raw_keypad(data, report, raw_data+1, size-1); 346 } else if (report->id == REPORT_IR_DATA) { 347 picolcd_raw_cir(data, report, raw_data+1, size-1); 348 } else { 349 spin_lock_irqsave(&data->lock, flags); 350 /* 351 * We let the caller of picolcd_send_and_wait() check if the 352 * report we got is one of the expected ones or not. 353 */ 354 if (data->pending) { 355 memcpy(data->pending->raw_data, raw_data+1, size-1); 356 data->pending->raw_size = size-1; 357 data->pending->in_report = report; 358 complete(&data->pending->ready); 359 } 360 spin_unlock_irqrestore(&data->lock, flags); 361 } 362 363 picolcd_debug_raw_event(data, hdev, report, raw_data, size); 364 return 1; 365 } 366 367 static int picolcd_suspend(struct hid_device *hdev, pm_message_t message) 368 { 369 if (PMSG_IS_AUTO(message)) 370 return 0; 371 372 picolcd_suspend_backlight(hid_get_drvdata(hdev)); 373 dbg_hid(PICOLCD_NAME " device ready for suspend\n"); 374 return 0; 375 } 376 377 static int picolcd_resume(struct hid_device *hdev) 378 { 379 int ret; 380 ret = picolcd_resume_backlight(hid_get_drvdata(hdev)); 381 if (ret) 382 dbg_hid(PICOLCD_NAME " restoring backlight failed: %d\n", ret); 383 return 0; 384 } 385 386 static int picolcd_reset_resume(struct hid_device *hdev) 387 { 388 int ret; 389 ret = picolcd_reset(hdev); 390 if (ret) 391 dbg_hid(PICOLCD_NAME " resetting our device failed: %d\n", ret); 392 ret = picolcd_fb_reset(hid_get_drvdata(hdev), 0); 393 if (ret) 394 dbg_hid(PICOLCD_NAME " restoring framebuffer content failed: %d\n", ret); 395 ret = picolcd_resume_lcd(hid_get_drvdata(hdev)); 396 if (ret) 397 dbg_hid(PICOLCD_NAME " restoring lcd failed: %d\n", ret); 398 ret = picolcd_resume_backlight(hid_get_drvdata(hdev)); 399 if (ret) 400 dbg_hid(PICOLCD_NAME " restoring backlight failed: %d\n", ret); 401 picolcd_leds_set(hid_get_drvdata(hdev)); 402 return 0; 403 } 404 405 /* initialize keypad input device */ 406 static int picolcd_init_keys(struct picolcd_data *data, 407 struct hid_report *report) 408 { 409 struct hid_device *hdev = data->hdev; 410 struct input_dev *idev; 411 int error, i; 412 413 if (!report) 414 return -ENODEV; 415 if (report->maxfield != 1 || report->field[0]->report_count != 2 || 416 report->field[0]->report_size != 8) { 417 hid_err(hdev, "unsupported KEY_STATE report\n"); 418 return -EINVAL; 419 } 420 421 idev = input_allocate_device(); 422 if (idev == NULL) { 423 hid_err(hdev, "failed to allocate input device\n"); 424 return -ENOMEM; 425 } 426 input_set_drvdata(idev, hdev); 427 memcpy(data->keycode, def_keymap, sizeof(def_keymap)); 428 idev->name = hdev->name; 429 idev->phys = hdev->phys; 430 idev->uniq = hdev->uniq; 431 idev->id.bustype = hdev->bus; 432 idev->id.vendor = hdev->vendor; 433 idev->id.product = hdev->product; 434 idev->id.version = hdev->version; 435 idev->dev.parent = &hdev->dev; 436 idev->keycode = &data->keycode; 437 idev->keycodemax = PICOLCD_KEYS; 438 idev->keycodesize = sizeof(data->keycode[0]); 439 input_set_capability(idev, EV_MSC, MSC_SCAN); 440 set_bit(EV_REP, idev->evbit); 441 for (i = 0; i < PICOLCD_KEYS; i++) 442 input_set_capability(idev, EV_KEY, data->keycode[i]); 443 error = input_register_device(idev); 444 if (error) { 445 hid_err(hdev, "error registering the input device\n"); 446 input_free_device(idev); 447 return error; 448 } 449 data->input_keys = idev; 450 return 0; 451 } 452 453 static void picolcd_exit_keys(struct picolcd_data *data) 454 { 455 struct input_dev *idev = data->input_keys; 456 457 data->input_keys = NULL; 458 if (idev) 459 input_unregister_device(idev); 460 } 461 462 static int picolcd_probe_lcd(struct hid_device *hdev, struct picolcd_data *data) 463 { 464 int error; 465 466 /* Setup keypad input device */ 467 error = picolcd_init_keys(data, picolcd_in_report(REPORT_KEY_STATE, hdev)); 468 if (error) 469 goto err; 470 471 /* Setup CIR input device */ 472 error = picolcd_init_cir(data, picolcd_in_report(REPORT_IR_DATA, hdev)); 473 if (error) 474 goto err; 475 476 /* Setup lcd class device */ 477 error = picolcd_init_lcd(data, picolcd_out_report(REPORT_CONTRAST, hdev)); 478 if (error) 479 goto err; 480 481 /* Setup backlight class device */ 482 error = picolcd_init_backlight(data, picolcd_out_report(REPORT_BRIGHTNESS, hdev)); 483 if (error) 484 goto err; 485 486 /* Set up the framebuffer device */ 487 error = picolcd_init_framebuffer(data); 488 if (error) 489 goto err; 490 491 /* Setup the LED class devices */ 492 error = picolcd_init_leds(data, picolcd_out_report(REPORT_LED_STATE, hdev)); 493 if (error) 494 goto err; 495 496 picolcd_init_devfs(data, picolcd_out_report(REPORT_EE_READ, hdev), 497 picolcd_out_report(REPORT_EE_WRITE, hdev), 498 picolcd_out_report(REPORT_READ_MEMORY, hdev), 499 picolcd_out_report(REPORT_WRITE_MEMORY, hdev), 500 picolcd_out_report(REPORT_RESET, hdev)); 501 return 0; 502 err: 503 picolcd_exit_leds(data); 504 picolcd_exit_framebuffer(data); 505 picolcd_exit_backlight(data); 506 picolcd_exit_lcd(data); 507 picolcd_exit_cir(data); 508 picolcd_exit_keys(data); 509 return error; 510 } 511 512 static int picolcd_probe_bootloader(struct hid_device *hdev, struct picolcd_data *data) 513 { 514 picolcd_init_devfs(data, NULL, NULL, 515 picolcd_out_report(REPORT_BL_READ_MEMORY, hdev), 516 picolcd_out_report(REPORT_BL_WRITE_MEMORY, hdev), NULL); 517 return 0; 518 } 519 520 static int picolcd_probe(struct hid_device *hdev, 521 const struct hid_device_id *id) 522 { 523 struct picolcd_data *data; 524 int error = -ENOMEM; 525 526 dbg_hid(PICOLCD_NAME " hardware probe...\n"); 527 528 /* 529 * Let's allocate the picolcd data structure, set some reasonable 530 * defaults, and associate it with the device 531 */ 532 data = kzalloc_obj(struct picolcd_data); 533 if (data == NULL) { 534 hid_err(hdev, "can't allocate space for Minibox PicoLCD device data\n"); 535 return -ENOMEM; 536 } 537 538 spin_lock_init(&data->lock); 539 mutex_init(&data->mutex); 540 data->hdev = hdev; 541 data->opmode_delay = 5000; 542 if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER) 543 data->status |= PICOLCD_BOOTLOADER; 544 hid_set_drvdata(hdev, data); 545 546 /* Parse the device reports and start it up */ 547 error = hid_parse(hdev); 548 if (error) { 549 hid_err(hdev, "device report parse failed\n"); 550 goto err_cleanup_data; 551 } 552 553 error = hid_hw_start(hdev, 0); 554 if (error) { 555 hid_err(hdev, "hardware start failed\n"); 556 goto err_cleanup_data; 557 } 558 559 error = hid_hw_open(hdev); 560 if (error) { 561 hid_err(hdev, "failed to open input interrupt pipe for key and IR events\n"); 562 goto err_cleanup_hid_hw; 563 } 564 565 error = device_create_file(&hdev->dev, &dev_attr_operation_mode_delay); 566 if (error) { 567 hid_err(hdev, "failed to create sysfs attributes\n"); 568 goto err_cleanup_hid_ll; 569 } 570 571 error = device_create_file(&hdev->dev, &dev_attr_operation_mode); 572 if (error) { 573 hid_err(hdev, "failed to create sysfs attributes\n"); 574 goto err_cleanup_sysfs1; 575 } 576 577 if (data->status & PICOLCD_BOOTLOADER) 578 error = picolcd_probe_bootloader(hdev, data); 579 else 580 error = picolcd_probe_lcd(hdev, data); 581 if (error) 582 goto err_cleanup_sysfs2; 583 584 dbg_hid(PICOLCD_NAME " activated and initialized\n"); 585 return 0; 586 587 err_cleanup_sysfs2: 588 device_remove_file(&hdev->dev, &dev_attr_operation_mode); 589 err_cleanup_sysfs1: 590 device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay); 591 err_cleanup_hid_ll: 592 hid_hw_close(hdev); 593 err_cleanup_hid_hw: 594 hid_hw_stop(hdev); 595 err_cleanup_data: 596 kfree(data); 597 return error; 598 } 599 600 static void picolcd_remove(struct hid_device *hdev) 601 { 602 struct picolcd_data *data = hid_get_drvdata(hdev); 603 unsigned long flags; 604 605 dbg_hid(PICOLCD_NAME " hardware remove...\n"); 606 spin_lock_irqsave(&data->lock, flags); 607 data->status |= PICOLCD_FAILED; 608 spin_unlock_irqrestore(&data->lock, flags); 609 610 picolcd_exit_devfs(data); 611 device_remove_file(&hdev->dev, &dev_attr_operation_mode); 612 device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay); 613 hid_hw_close(hdev); 614 hid_hw_stop(hdev); 615 616 /* Shortcut potential pending reply that will never arrive */ 617 spin_lock_irqsave(&data->lock, flags); 618 if (data->pending) 619 complete(&data->pending->ready); 620 spin_unlock_irqrestore(&data->lock, flags); 621 622 /* Cleanup LED */ 623 picolcd_exit_leds(data); 624 /* Clean up the framebuffer */ 625 picolcd_exit_framebuffer(data); 626 picolcd_exit_backlight(data); 627 picolcd_exit_lcd(data); 628 /* Cleanup input */ 629 picolcd_exit_cir(data); 630 picolcd_exit_keys(data); 631 632 mutex_destroy(&data->mutex); 633 /* Finally, clean up the picolcd data itself */ 634 kfree(data); 635 } 636 637 static const struct hid_device_id picolcd_devices[] = { 638 { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) }, 639 { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) }, 640 { } 641 }; 642 MODULE_DEVICE_TABLE(hid, picolcd_devices); 643 644 static struct hid_driver picolcd_driver = { 645 .name = "hid-picolcd", 646 .id_table = picolcd_devices, 647 .probe = picolcd_probe, 648 .remove = picolcd_remove, 649 .raw_event = picolcd_raw_event, 650 .suspend = pm_ptr(picolcd_suspend), 651 .resume = pm_ptr(picolcd_resume), 652 .reset_resume = pm_ptr(picolcd_reset_resume), 653 }; 654 module_hid_driver(picolcd_driver); 655 656 MODULE_DESCRIPTION("Minibox graphics PicoLCD Driver"); 657 MODULE_LICENSE("GPL v2"); 658