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 || report->maxfield != 1) 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 (size > 64) { 354 hid_warn(hdev, "invalid size value (%d) for picolcd raw event (%d)\n", 355 size, report->id); 356 return 0; 357 } 358 359 if (report->id == REPORT_KEY_STATE) { 360 if (data->input_keys) 361 ret = picolcd_raw_keypad(data, report, raw_data+1, size-1); 362 } else if (report->id == REPORT_IR_DATA) { 363 ret = picolcd_raw_cir(data, report, raw_data+1, size-1); 364 } else { 365 spin_lock_irqsave(&data->lock, flags); 366 /* 367 * We let the caller of picolcd_send_and_wait() check if the 368 * report we got is one of the expected ones or not. 369 */ 370 if (data->pending) { 371 memcpy(data->pending->raw_data, raw_data+1, size-1); 372 data->pending->raw_size = size-1; 373 data->pending->in_report = report; 374 complete(&data->pending->ready); 375 } 376 spin_unlock_irqrestore(&data->lock, flags); 377 } 378 379 picolcd_debug_raw_event(data, hdev, report, raw_data, size); 380 return 1; 381 } 382 383 #ifdef CONFIG_PM 384 static int picolcd_suspend(struct hid_device *hdev, pm_message_t message) 385 { 386 if (PMSG_IS_AUTO(message)) 387 return 0; 388 389 picolcd_suspend_backlight(hid_get_drvdata(hdev)); 390 dbg_hid(PICOLCD_NAME " device ready for suspend\n"); 391 return 0; 392 } 393 394 static int picolcd_resume(struct hid_device *hdev) 395 { 396 int ret; 397 ret = picolcd_resume_backlight(hid_get_drvdata(hdev)); 398 if (ret) 399 dbg_hid(PICOLCD_NAME " restoring backlight failed: %d\n", ret); 400 return 0; 401 } 402 403 static int picolcd_reset_resume(struct hid_device *hdev) 404 { 405 int ret; 406 ret = picolcd_reset(hdev); 407 if (ret) 408 dbg_hid(PICOLCD_NAME " resetting our device failed: %d\n", ret); 409 ret = picolcd_fb_reset(hid_get_drvdata(hdev), 0); 410 if (ret) 411 dbg_hid(PICOLCD_NAME " restoring framebuffer content failed: %d\n", ret); 412 ret = picolcd_resume_lcd(hid_get_drvdata(hdev)); 413 if (ret) 414 dbg_hid(PICOLCD_NAME " restoring lcd failed: %d\n", ret); 415 ret = picolcd_resume_backlight(hid_get_drvdata(hdev)); 416 if (ret) 417 dbg_hid(PICOLCD_NAME " restoring backlight failed: %d\n", ret); 418 picolcd_leds_set(hid_get_drvdata(hdev)); 419 return 0; 420 } 421 #endif 422 423 /* initialize keypad input device */ 424 static int picolcd_init_keys(struct picolcd_data *data, 425 struct hid_report *report) 426 { 427 struct hid_device *hdev = data->hdev; 428 struct input_dev *idev; 429 int error, i; 430 431 if (!report) 432 return -ENODEV; 433 if (report->maxfield != 1 || report->field[0]->report_count != 2 || 434 report->field[0]->report_size != 8) { 435 hid_err(hdev, "unsupported KEY_STATE report\n"); 436 return -EINVAL; 437 } 438 439 idev = input_allocate_device(); 440 if (idev == NULL) { 441 hid_err(hdev, "failed to allocate input device\n"); 442 return -ENOMEM; 443 } 444 input_set_drvdata(idev, hdev); 445 memcpy(data->keycode, def_keymap, sizeof(def_keymap)); 446 idev->name = hdev->name; 447 idev->phys = hdev->phys; 448 idev->uniq = hdev->uniq; 449 idev->id.bustype = hdev->bus; 450 idev->id.vendor = hdev->vendor; 451 idev->id.product = hdev->product; 452 idev->id.version = hdev->version; 453 idev->dev.parent = &hdev->dev; 454 idev->keycode = &data->keycode; 455 idev->keycodemax = PICOLCD_KEYS; 456 idev->keycodesize = sizeof(data->keycode[0]); 457 input_set_capability(idev, EV_MSC, MSC_SCAN); 458 set_bit(EV_REP, idev->evbit); 459 for (i = 0; i < PICOLCD_KEYS; i++) 460 input_set_capability(idev, EV_KEY, data->keycode[i]); 461 error = input_register_device(idev); 462 if (error) { 463 hid_err(hdev, "error registering the input device\n"); 464 input_free_device(idev); 465 return error; 466 } 467 data->input_keys = idev; 468 return 0; 469 } 470 471 static void picolcd_exit_keys(struct picolcd_data *data) 472 { 473 struct input_dev *idev = data->input_keys; 474 475 data->input_keys = NULL; 476 if (idev) 477 input_unregister_device(idev); 478 } 479 480 static int picolcd_probe_lcd(struct hid_device *hdev, struct picolcd_data *data) 481 { 482 int error; 483 484 /* Setup keypad input device */ 485 error = picolcd_init_keys(data, picolcd_in_report(REPORT_KEY_STATE, hdev)); 486 if (error) 487 goto err; 488 489 /* Setup CIR input device */ 490 error = picolcd_init_cir(data, picolcd_in_report(REPORT_IR_DATA, hdev)); 491 if (error) 492 goto err; 493 494 /* Set up the framebuffer device */ 495 error = picolcd_init_framebuffer(data); 496 if (error) 497 goto err; 498 499 /* Setup lcd class device */ 500 error = picolcd_init_lcd(data, picolcd_out_report(REPORT_CONTRAST, hdev)); 501 if (error) 502 goto err; 503 504 /* Setup backlight class device */ 505 error = picolcd_init_backlight(data, picolcd_out_report(REPORT_BRIGHTNESS, hdev)); 506 if (error) 507 goto err; 508 509 /* Setup the LED class devices */ 510 error = picolcd_init_leds(data, picolcd_out_report(REPORT_LED_STATE, hdev)); 511 if (error) 512 goto err; 513 514 picolcd_init_devfs(data, picolcd_out_report(REPORT_EE_READ, hdev), 515 picolcd_out_report(REPORT_EE_WRITE, hdev), 516 picolcd_out_report(REPORT_READ_MEMORY, hdev), 517 picolcd_out_report(REPORT_WRITE_MEMORY, hdev), 518 picolcd_out_report(REPORT_RESET, hdev)); 519 return 0; 520 err: 521 picolcd_exit_leds(data); 522 picolcd_exit_backlight(data); 523 picolcd_exit_lcd(data); 524 picolcd_exit_framebuffer(data); 525 picolcd_exit_cir(data); 526 picolcd_exit_keys(data); 527 return error; 528 } 529 530 static int picolcd_probe_bootloader(struct hid_device *hdev, struct picolcd_data *data) 531 { 532 picolcd_init_devfs(data, NULL, NULL, 533 picolcd_out_report(REPORT_BL_READ_MEMORY, hdev), 534 picolcd_out_report(REPORT_BL_WRITE_MEMORY, hdev), NULL); 535 return 0; 536 } 537 538 static int picolcd_probe(struct hid_device *hdev, 539 const struct hid_device_id *id) 540 { 541 struct picolcd_data *data; 542 int error = -ENOMEM; 543 544 dbg_hid(PICOLCD_NAME " hardware probe...\n"); 545 546 /* 547 * Let's allocate the picolcd data structure, set some reasonable 548 * defaults, and associate it with the device 549 */ 550 data = kzalloc(sizeof(struct picolcd_data), GFP_KERNEL); 551 if (data == NULL) { 552 hid_err(hdev, "can't allocate space for Minibox PicoLCD device data\n"); 553 error = -ENOMEM; 554 goto err_no_cleanup; 555 } 556 557 spin_lock_init(&data->lock); 558 mutex_init(&data->mutex); 559 data->hdev = hdev; 560 data->opmode_delay = 5000; 561 if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER) 562 data->status |= PICOLCD_BOOTLOADER; 563 hid_set_drvdata(hdev, data); 564 565 /* Parse the device reports and start it up */ 566 error = hid_parse(hdev); 567 if (error) { 568 hid_err(hdev, "device report parse failed\n"); 569 goto err_cleanup_data; 570 } 571 572 error = hid_hw_start(hdev, 0); 573 if (error) { 574 hid_err(hdev, "hardware start failed\n"); 575 goto err_cleanup_data; 576 } 577 578 error = hid_hw_open(hdev); 579 if (error) { 580 hid_err(hdev, "failed to open input interrupt pipe for key and IR events\n"); 581 goto err_cleanup_hid_hw; 582 } 583 584 error = device_create_file(&hdev->dev, &dev_attr_operation_mode_delay); 585 if (error) { 586 hid_err(hdev, "failed to create sysfs attributes\n"); 587 goto err_cleanup_hid_ll; 588 } 589 590 error = device_create_file(&hdev->dev, &dev_attr_operation_mode); 591 if (error) { 592 hid_err(hdev, "failed to create sysfs attributes\n"); 593 goto err_cleanup_sysfs1; 594 } 595 596 if (data->status & PICOLCD_BOOTLOADER) 597 error = picolcd_probe_bootloader(hdev, data); 598 else 599 error = picolcd_probe_lcd(hdev, data); 600 if (error) 601 goto err_cleanup_sysfs2; 602 603 dbg_hid(PICOLCD_NAME " activated and initialized\n"); 604 return 0; 605 606 err_cleanup_sysfs2: 607 device_remove_file(&hdev->dev, &dev_attr_operation_mode); 608 err_cleanup_sysfs1: 609 device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay); 610 err_cleanup_hid_ll: 611 hid_hw_close(hdev); 612 err_cleanup_hid_hw: 613 hid_hw_stop(hdev); 614 err_cleanup_data: 615 kfree(data); 616 err_no_cleanup: 617 hid_set_drvdata(hdev, NULL); 618 619 return error; 620 } 621 622 static void picolcd_remove(struct hid_device *hdev) 623 { 624 struct picolcd_data *data = hid_get_drvdata(hdev); 625 unsigned long flags; 626 627 dbg_hid(PICOLCD_NAME " hardware remove...\n"); 628 spin_lock_irqsave(&data->lock, flags); 629 data->status |= PICOLCD_FAILED; 630 spin_unlock_irqrestore(&data->lock, flags); 631 632 picolcd_exit_devfs(data); 633 device_remove_file(&hdev->dev, &dev_attr_operation_mode); 634 device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay); 635 hid_hw_close(hdev); 636 hid_hw_stop(hdev); 637 638 /* Shortcut potential pending reply that will never arrive */ 639 spin_lock_irqsave(&data->lock, flags); 640 if (data->pending) 641 complete(&data->pending->ready); 642 spin_unlock_irqrestore(&data->lock, flags); 643 644 /* Cleanup LED */ 645 picolcd_exit_leds(data); 646 /* Clean up the framebuffer */ 647 picolcd_exit_backlight(data); 648 picolcd_exit_lcd(data); 649 picolcd_exit_framebuffer(data); 650 /* Cleanup input */ 651 picolcd_exit_cir(data); 652 picolcd_exit_keys(data); 653 654 hid_set_drvdata(hdev, NULL); 655 mutex_destroy(&data->mutex); 656 /* Finally, clean up the picolcd data itself */ 657 kfree(data); 658 } 659 660 static const struct hid_device_id picolcd_devices[] = { 661 { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) }, 662 { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) }, 663 { } 664 }; 665 MODULE_DEVICE_TABLE(hid, picolcd_devices); 666 667 static struct hid_driver picolcd_driver = { 668 .name = "hid-picolcd", 669 .id_table = picolcd_devices, 670 .probe = picolcd_probe, 671 .remove = picolcd_remove, 672 .raw_event = picolcd_raw_event, 673 #ifdef CONFIG_PM 674 .suspend = picolcd_suspend, 675 .resume = picolcd_resume, 676 .reset_resume = picolcd_reset_resume, 677 #endif 678 }; 679 module_hid_driver(picolcd_driver); 680 681 MODULE_DESCRIPTION("Minibox graphics PicoLCD Driver"); 682 MODULE_LICENSE("GPL v2"); 683