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