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 #include <linux/string.h> 32 33 #include "hid-picolcd.h" 34 35 36 /* Input device 37 * 38 * The PicoLCD has an IR receiver header, a built-in keypad with 5 keys 39 * and header for 4x4 key matrix. The built-in keys are part of the matrix. 40 */ 41 static const unsigned short def_keymap[PICOLCD_KEYS] = { 42 KEY_RESERVED, /* none */ 43 KEY_BACK, /* col 4 + row 1 */ 44 KEY_HOMEPAGE, /* col 3 + row 1 */ 45 KEY_RESERVED, /* col 2 + row 1 */ 46 KEY_RESERVED, /* col 1 + row 1 */ 47 KEY_SCROLLUP, /* col 4 + row 2 */ 48 KEY_OK, /* col 3 + row 2 */ 49 KEY_SCROLLDOWN, /* col 2 + row 2 */ 50 KEY_RESERVED, /* col 1 + row 2 */ 51 KEY_RESERVED, /* col 4 + row 3 */ 52 KEY_RESERVED, /* col 3 + row 3 */ 53 KEY_RESERVED, /* col 2 + row 3 */ 54 KEY_RESERVED, /* col 1 + row 3 */ 55 KEY_RESERVED, /* col 4 + row 4 */ 56 KEY_RESERVED, /* col 3 + row 4 */ 57 KEY_RESERVED, /* col 2 + row 4 */ 58 KEY_RESERVED, /* col 1 + row 4 */ 59 }; 60 61 62 /* Find a given report */ 63 struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir) 64 { 65 struct list_head *feature_report_list = &hdev->report_enum[dir].report_list; 66 struct hid_report *report = NULL; 67 68 list_for_each_entry(report, feature_report_list, list) { 69 if (report->id == id) 70 return report; 71 } 72 hid_warn(hdev, "No report with id 0x%x found\n", id); 73 return NULL; 74 } 75 76 /* Submit a report and wait for a reply from device - if device fades away 77 * or does not respond in time, return NULL */ 78 struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev, 79 int report_id, const u8 *raw_data, int size) 80 { 81 struct picolcd_data *data = hid_get_drvdata(hdev); 82 struct picolcd_pending *work; 83 struct hid_report *report = picolcd_out_report(report_id, hdev); 84 unsigned long flags; 85 int i, j, k; 86 87 if (!report || !data) 88 return NULL; 89 if (data->status & PICOLCD_FAILED) 90 return NULL; 91 work = kzalloc(sizeof(*work), GFP_KERNEL); 92 if (!work) 93 return NULL; 94 95 init_completion(&work->ready); 96 work->out_report = report; 97 work->in_report = NULL; 98 work->raw_size = 0; 99 100 mutex_lock(&data->mutex); 101 spin_lock_irqsave(&data->lock, flags); 102 for (i = k = 0; i < report->maxfield; i++) 103 for (j = 0; j < report->field[i]->report_count; j++) { 104 hid_set_field(report->field[i], j, k < size ? raw_data[k] : 0); 105 k++; 106 } 107 if (data->status & PICOLCD_FAILED) { 108 kfree(work); 109 work = NULL; 110 } else { 111 data->pending = work; 112 hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT); 113 spin_unlock_irqrestore(&data->lock, flags); 114 wait_for_completion_interruptible_timeout(&work->ready, HZ*2); 115 spin_lock_irqsave(&data->lock, flags); 116 data->pending = NULL; 117 } 118 spin_unlock_irqrestore(&data->lock, flags); 119 mutex_unlock(&data->mutex); 120 return work; 121 } 122 123 /* 124 * input class device 125 */ 126 static int picolcd_raw_keypad(struct picolcd_data *data, 127 struct hid_report *report, u8 *raw_data, int size) 128 { 129 /* 130 * Keypad event 131 * First and second data bytes list currently pressed keys, 132 * 0x00 means no key and at most 2 keys may be pressed at same time 133 */ 134 int i, j; 135 136 /* determine newly pressed keys */ 137 for (i = 0; i < size; i++) { 138 unsigned int key_code; 139 if (raw_data[i] == 0) 140 continue; 141 for (j = 0; j < sizeof(data->pressed_keys); j++) 142 if (data->pressed_keys[j] == raw_data[i]) 143 goto key_already_down; 144 for (j = 0; j < sizeof(data->pressed_keys); j++) 145 if (data->pressed_keys[j] == 0) { 146 data->pressed_keys[j] = raw_data[i]; 147 break; 148 } 149 input_event(data->input_keys, EV_MSC, MSC_SCAN, raw_data[i]); 150 if (raw_data[i] < PICOLCD_KEYS) 151 key_code = data->keycode[raw_data[i]]; 152 else 153 key_code = KEY_UNKNOWN; 154 if (key_code != KEY_UNKNOWN) { 155 dbg_hid(PICOLCD_NAME " got key press for %u:%d", 156 raw_data[i], key_code); 157 input_report_key(data->input_keys, key_code, 1); 158 } 159 input_sync(data->input_keys); 160 key_already_down: 161 continue; 162 } 163 164 /* determine newly released keys */ 165 for (j = 0; j < sizeof(data->pressed_keys); j++) { 166 unsigned int key_code; 167 if (data->pressed_keys[j] == 0) 168 continue; 169 for (i = 0; i < size; i++) 170 if (data->pressed_keys[j] == raw_data[i]) 171 goto key_still_down; 172 input_event(data->input_keys, EV_MSC, MSC_SCAN, data->pressed_keys[j]); 173 if (data->pressed_keys[j] < PICOLCD_KEYS) 174 key_code = data->keycode[data->pressed_keys[j]]; 175 else 176 key_code = KEY_UNKNOWN; 177 if (key_code != KEY_UNKNOWN) { 178 dbg_hid(PICOLCD_NAME " got key release for %u:%d", 179 data->pressed_keys[j], key_code); 180 input_report_key(data->input_keys, key_code, 0); 181 } 182 input_sync(data->input_keys); 183 data->pressed_keys[j] = 0; 184 key_still_down: 185 continue; 186 } 187 return 1; 188 } 189 190 static int picolcd_check_version(struct hid_device *hdev) 191 { 192 struct picolcd_data *data = hid_get_drvdata(hdev); 193 struct picolcd_pending *verinfo; 194 int ret = 0; 195 196 if (!data) 197 return -ENODEV; 198 199 verinfo = picolcd_send_and_wait(hdev, REPORT_VERSION, NULL, 0); 200 if (!verinfo) { 201 hid_err(hdev, "no version response from PicoLCD\n"); 202 return -ENODEV; 203 } 204 205 if (verinfo->raw_size == 2) { 206 data->version[0] = verinfo->raw_data[1]; 207 data->version[1] = verinfo->raw_data[0]; 208 if (data->status & PICOLCD_BOOTLOADER) { 209 hid_info(hdev, "PicoLCD, bootloader version %d.%d\n", 210 verinfo->raw_data[1], verinfo->raw_data[0]); 211 } else { 212 hid_info(hdev, "PicoLCD, firmware version %d.%d\n", 213 verinfo->raw_data[1], verinfo->raw_data[0]); 214 } 215 } else { 216 hid_err(hdev, "confused, got unexpected version response from PicoLCD\n"); 217 ret = -EINVAL; 218 } 219 kfree(verinfo); 220 return ret; 221 } 222 223 /* 224 * Reset our device and wait for answer to VERSION request 225 */ 226 int picolcd_reset(struct hid_device *hdev) 227 { 228 struct picolcd_data *data = hid_get_drvdata(hdev); 229 struct hid_report *report = picolcd_out_report(REPORT_RESET, hdev); 230 unsigned long flags; 231 int error; 232 233 if (!data || !report || report->maxfield != 1) 234 return -ENODEV; 235 236 spin_lock_irqsave(&data->lock, flags); 237 if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER) 238 data->status |= PICOLCD_BOOTLOADER; 239 240 /* perform the reset */ 241 hid_set_field(report->field[0], 0, 1); 242 if (data->status & PICOLCD_FAILED) { 243 spin_unlock_irqrestore(&data->lock, flags); 244 return -ENODEV; 245 } 246 hid_hw_request(hdev, report, HID_REQ_SET_REPORT); 247 spin_unlock_irqrestore(&data->lock, flags); 248 249 error = picolcd_check_version(hdev); 250 if (error) 251 return error; 252 253 picolcd_resume_lcd(data); 254 picolcd_resume_backlight(data); 255 picolcd_fb_refresh(data); 256 picolcd_leds_set(data); 257 return 0; 258 } 259 260 /* 261 * The "operation_mode" sysfs attribute 262 */ 263 static ssize_t picolcd_operation_mode_show(struct device *dev, 264 struct device_attribute *attr, char *buf) 265 { 266 struct picolcd_data *data = dev_get_drvdata(dev); 267 268 if (data->status & PICOLCD_BOOTLOADER) 269 return snprintf(buf, PAGE_SIZE, "[bootloader] lcd\n"); 270 else 271 return snprintf(buf, PAGE_SIZE, "bootloader [lcd]\n"); 272 } 273 274 static ssize_t picolcd_operation_mode_store(struct device *dev, 275 struct device_attribute *attr, const char *buf, size_t count) 276 { 277 struct picolcd_data *data = dev_get_drvdata(dev); 278 struct hid_report *report = NULL; 279 int timeout = data->opmode_delay; 280 unsigned long flags; 281 282 if (sysfs_streq(buf, "lcd")) { 283 if (data->status & PICOLCD_BOOTLOADER) 284 report = picolcd_out_report(REPORT_EXIT_FLASHER, data->hdev); 285 } else if (sysfs_streq(buf, "bootloader")) { 286 if (!(data->status & PICOLCD_BOOTLOADER)) 287 report = picolcd_out_report(REPORT_EXIT_KEYBOARD, data->hdev); 288 } else { 289 return -EINVAL; 290 } 291 292 if (!report || report->maxfield != 1) 293 return -EINVAL; 294 295 spin_lock_irqsave(&data->lock, flags); 296 hid_set_field(report->field[0], 0, timeout & 0xff); 297 hid_set_field(report->field[0], 1, (timeout >> 8) & 0xff); 298 hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT); 299 spin_unlock_irqrestore(&data->lock, flags); 300 return count; 301 } 302 303 static DEVICE_ATTR(operation_mode, 0644, picolcd_operation_mode_show, 304 picolcd_operation_mode_store); 305 306 /* 307 * The "operation_mode_delay" sysfs attribute 308 */ 309 static ssize_t picolcd_operation_mode_delay_show(struct device *dev, 310 struct device_attribute *attr, char *buf) 311 { 312 struct picolcd_data *data = dev_get_drvdata(dev); 313 314 return snprintf(buf, PAGE_SIZE, "%hu\n", data->opmode_delay); 315 } 316 317 static ssize_t picolcd_operation_mode_delay_store(struct device *dev, 318 struct device_attribute *attr, const char *buf, size_t count) 319 { 320 struct picolcd_data *data = dev_get_drvdata(dev); 321 unsigned u; 322 if (sscanf(buf, "%u", &u) != 1) 323 return -EINVAL; 324 if (u > 30000) 325 return -EINVAL; 326 else 327 data->opmode_delay = u; 328 return count; 329 } 330 331 static DEVICE_ATTR(operation_mode_delay, 0644, picolcd_operation_mode_delay_show, 332 picolcd_operation_mode_delay_store); 333 334 /* 335 * Handle raw report as sent by device 336 */ 337 static int picolcd_raw_event(struct hid_device *hdev, 338 struct hid_report *report, u8 *raw_data, int size) 339 { 340 struct picolcd_data *data = hid_get_drvdata(hdev); 341 unsigned long flags; 342 int ret = 0; 343 344 if (!data) 345 return 1; 346 347 if (size > 64) { 348 hid_warn(hdev, "invalid size value (%d) for picolcd raw event (%d)\n", 349 size, report->id); 350 return 0; 351 } 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