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 */
picolcd_report(int id,struct hid_device * hdev,int dir)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 */
picolcd_send_and_wait(struct hid_device * hdev,int report_id,const u8 * raw_data,int size)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 */
picolcd_raw_keypad(struct picolcd_data * data,struct hid_report * report,u8 * raw_data,int size)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
picolcd_check_version(struct hid_device * hdev)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 */
picolcd_reset(struct hid_device * hdev)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 */
picolcd_operation_mode_show(struct device * dev,struct device_attribute * attr,char * buf)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
picolcd_operation_mode_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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 */
picolcd_operation_mode_delay_show(struct device * dev,struct device_attribute * attr,char * buf)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
picolcd_operation_mode_delay_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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 */
picolcd_raw_event(struct hid_device * hdev,struct hid_report * report,u8 * raw_data,int size)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
picolcd_suspend(struct hid_device * hdev,pm_message_t message)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
picolcd_resume(struct hid_device * hdev)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
picolcd_reset_resume(struct hid_device * hdev)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 */
picolcd_init_keys(struct picolcd_data * data,struct hid_report * report)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
picolcd_exit_keys(struct picolcd_data * data)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
picolcd_probe_lcd(struct hid_device * hdev,struct picolcd_data * data)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
picolcd_probe_bootloader(struct hid_device * hdev,struct picolcd_data * data)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
picolcd_probe(struct hid_device * hdev,const struct hid_device_id * id)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
picolcd_remove(struct hid_device * hdev)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