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