Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /***************************************************************************
0003  *   Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org>  *
0004  *                                                                         *
0005  *   Based on Logitech G13 driver (v0.4)                                   *
0006  *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
0007  *                                                                         *
0008  ***************************************************************************/
0009 
0010 #include <linux/hid.h>
0011 #include <linux/hid-debug.h>
0012 #include <linux/input.h>
0013 #include "hid-ids.h"
0014 
0015 #include <linux/fb.h>
0016 #include <linux/vmalloc.h>
0017 
0018 #include <linux/completion.h>
0019 #include <linux/uaccess.h>
0020 #include <linux/module.h>
0021 #include <linux/string.h>
0022 
0023 #include "hid-picolcd.h"
0024 
0025 
0026 /* Input device
0027  *
0028  * The PicoLCD has an IR receiver header, a built-in keypad with 5 keys
0029  * and header for 4x4 key matrix. The built-in keys are part of the matrix.
0030  */
0031 static const unsigned short def_keymap[PICOLCD_KEYS] = {
0032     KEY_RESERVED,   /* none */
0033     KEY_BACK,   /* col 4 + row 1 */
0034     KEY_HOMEPAGE,   /* col 3 + row 1 */
0035     KEY_RESERVED,   /* col 2 + row 1 */
0036     KEY_RESERVED,   /* col 1 + row 1 */
0037     KEY_SCROLLUP,   /* col 4 + row 2 */
0038     KEY_OK,     /* col 3 + row 2 */
0039     KEY_SCROLLDOWN, /* col 2 + row 2 */
0040     KEY_RESERVED,   /* col 1 + row 2 */
0041     KEY_RESERVED,   /* col 4 + row 3 */
0042     KEY_RESERVED,   /* col 3 + row 3 */
0043     KEY_RESERVED,   /* col 2 + row 3 */
0044     KEY_RESERVED,   /* col 1 + row 3 */
0045     KEY_RESERVED,   /* col 4 + row 4 */
0046     KEY_RESERVED,   /* col 3 + row 4 */
0047     KEY_RESERVED,   /* col 2 + row 4 */
0048     KEY_RESERVED,   /* col 1 + row 4 */
0049 };
0050 
0051 
0052 /* Find a given report */
0053 struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir)
0054 {
0055     struct list_head *feature_report_list = &hdev->report_enum[dir].report_list;
0056     struct hid_report *report = NULL;
0057 
0058     list_for_each_entry(report, feature_report_list, list) {
0059         if (report->id == id)
0060             return report;
0061     }
0062     hid_warn(hdev, "No report with id 0x%x found\n", id);
0063     return NULL;
0064 }
0065 
0066 /* Submit a report and wait for a reply from device - if device fades away
0067  * or does not respond in time, return NULL */
0068 struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev,
0069         int report_id, const u8 *raw_data, int size)
0070 {
0071     struct picolcd_data *data = hid_get_drvdata(hdev);
0072     struct picolcd_pending *work;
0073     struct hid_report *report = picolcd_out_report(report_id, hdev);
0074     unsigned long flags;
0075     int i, j, k;
0076 
0077     if (!report || !data)
0078         return NULL;
0079     if (data->status & PICOLCD_FAILED)
0080         return NULL;
0081     work = kzalloc(sizeof(*work), GFP_KERNEL);
0082     if (!work)
0083         return NULL;
0084 
0085     init_completion(&work->ready);
0086     work->out_report = report;
0087     work->in_report  = NULL;
0088     work->raw_size   = 0;
0089 
0090     mutex_lock(&data->mutex);
0091     spin_lock_irqsave(&data->lock, flags);
0092     for (i = k = 0; i < report->maxfield; i++)
0093         for (j = 0; j < report->field[i]->report_count; j++) {
0094             hid_set_field(report->field[i], j, k < size ? raw_data[k] : 0);
0095             k++;
0096         }
0097     if (data->status & PICOLCD_FAILED) {
0098         kfree(work);
0099         work = NULL;
0100     } else {
0101         data->pending = work;
0102         hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
0103         spin_unlock_irqrestore(&data->lock, flags);
0104         wait_for_completion_interruptible_timeout(&work->ready, HZ*2);
0105         spin_lock_irqsave(&data->lock, flags);
0106         data->pending = NULL;
0107     }
0108     spin_unlock_irqrestore(&data->lock, flags);
0109     mutex_unlock(&data->mutex);
0110     return work;
0111 }
0112 
0113 /*
0114  * input class device
0115  */
0116 static int picolcd_raw_keypad(struct picolcd_data *data,
0117         struct hid_report *report, u8 *raw_data, int size)
0118 {
0119     /*
0120      * Keypad event
0121      * First and second data bytes list currently pressed keys,
0122      * 0x00 means no key and at most 2 keys may be pressed at same time
0123      */
0124     int i, j;
0125 
0126     /* determine newly pressed keys */
0127     for (i = 0; i < size; i++) {
0128         unsigned int key_code;
0129         if (raw_data[i] == 0)
0130             continue;
0131         for (j = 0; j < sizeof(data->pressed_keys); j++)
0132             if (data->pressed_keys[j] == raw_data[i])
0133                 goto key_already_down;
0134         for (j = 0; j < sizeof(data->pressed_keys); j++)
0135             if (data->pressed_keys[j] == 0) {
0136                 data->pressed_keys[j] = raw_data[i];
0137                 break;
0138             }
0139         input_event(data->input_keys, EV_MSC, MSC_SCAN, raw_data[i]);
0140         if (raw_data[i] < PICOLCD_KEYS)
0141             key_code = data->keycode[raw_data[i]];
0142         else
0143             key_code = KEY_UNKNOWN;
0144         if (key_code != KEY_UNKNOWN) {
0145             dbg_hid(PICOLCD_NAME " got key press for %u:%d",
0146                     raw_data[i], key_code);
0147             input_report_key(data->input_keys, key_code, 1);
0148         }
0149         input_sync(data->input_keys);
0150 key_already_down:
0151         continue;
0152     }
0153 
0154     /* determine newly released keys */
0155     for (j = 0; j < sizeof(data->pressed_keys); j++) {
0156         unsigned int key_code;
0157         if (data->pressed_keys[j] == 0)
0158             continue;
0159         for (i = 0; i < size; i++)
0160             if (data->pressed_keys[j] == raw_data[i])
0161                 goto key_still_down;
0162         input_event(data->input_keys, EV_MSC, MSC_SCAN, data->pressed_keys[j]);
0163         if (data->pressed_keys[j] < PICOLCD_KEYS)
0164             key_code = data->keycode[data->pressed_keys[j]];
0165         else
0166             key_code = KEY_UNKNOWN;
0167         if (key_code != KEY_UNKNOWN) {
0168             dbg_hid(PICOLCD_NAME " got key release for %u:%d",
0169                     data->pressed_keys[j], key_code);
0170             input_report_key(data->input_keys, key_code, 0);
0171         }
0172         input_sync(data->input_keys);
0173         data->pressed_keys[j] = 0;
0174 key_still_down:
0175         continue;
0176     }
0177     return 1;
0178 }
0179 
0180 static int picolcd_check_version(struct hid_device *hdev)
0181 {
0182     struct picolcd_data *data = hid_get_drvdata(hdev);
0183     struct picolcd_pending *verinfo;
0184     int ret = 0;
0185 
0186     if (!data)
0187         return -ENODEV;
0188 
0189     verinfo = picolcd_send_and_wait(hdev, REPORT_VERSION, NULL, 0);
0190     if (!verinfo) {
0191         hid_err(hdev, "no version response from PicoLCD\n");
0192         return -ENODEV;
0193     }
0194 
0195     if (verinfo->raw_size == 2) {
0196         data->version[0] = verinfo->raw_data[1];
0197         data->version[1] = verinfo->raw_data[0];
0198         if (data->status & PICOLCD_BOOTLOADER) {
0199             hid_info(hdev, "PicoLCD, bootloader version %d.%d\n",
0200                  verinfo->raw_data[1], verinfo->raw_data[0]);
0201         } else {
0202             hid_info(hdev, "PicoLCD, firmware version %d.%d\n",
0203                  verinfo->raw_data[1], verinfo->raw_data[0]);
0204         }
0205     } else {
0206         hid_err(hdev, "confused, got unexpected version response from PicoLCD\n");
0207         ret = -EINVAL;
0208     }
0209     kfree(verinfo);
0210     return ret;
0211 }
0212 
0213 /*
0214  * Reset our device and wait for answer to VERSION request
0215  */
0216 int picolcd_reset(struct hid_device *hdev)
0217 {
0218     struct picolcd_data *data = hid_get_drvdata(hdev);
0219     struct hid_report *report = picolcd_out_report(REPORT_RESET, hdev);
0220     unsigned long flags;
0221     int error;
0222 
0223     if (!data || !report || report->maxfield != 1)
0224         return -ENODEV;
0225 
0226     spin_lock_irqsave(&data->lock, flags);
0227     if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER)
0228         data->status |= PICOLCD_BOOTLOADER;
0229 
0230     /* perform the reset */
0231     hid_set_field(report->field[0], 0, 1);
0232     if (data->status & PICOLCD_FAILED) {
0233         spin_unlock_irqrestore(&data->lock, flags);
0234         return -ENODEV;
0235     }
0236     hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
0237     spin_unlock_irqrestore(&data->lock, flags);
0238 
0239     error = picolcd_check_version(hdev);
0240     if (error)
0241         return error;
0242 
0243     picolcd_resume_lcd(data);
0244     picolcd_resume_backlight(data);
0245     picolcd_fb_refresh(data);
0246     picolcd_leds_set(data);
0247     return 0;
0248 }
0249 
0250 /*
0251  * The "operation_mode" sysfs attribute
0252  */
0253 static ssize_t picolcd_operation_mode_show(struct device *dev,
0254         struct device_attribute *attr, char *buf)
0255 {
0256     struct picolcd_data *data = dev_get_drvdata(dev);
0257 
0258     if (data->status & PICOLCD_BOOTLOADER)
0259         return snprintf(buf, PAGE_SIZE, "[bootloader] lcd\n");
0260     else
0261         return snprintf(buf, PAGE_SIZE, "bootloader [lcd]\n");
0262 }
0263 
0264 static ssize_t picolcd_operation_mode_store(struct device *dev,
0265         struct device_attribute *attr, const char *buf, size_t count)
0266 {
0267     struct picolcd_data *data = dev_get_drvdata(dev);
0268     struct hid_report *report = NULL;
0269     int timeout = data->opmode_delay;
0270     unsigned long flags;
0271 
0272     if (sysfs_streq(buf, "lcd")) {
0273         if (data->status & PICOLCD_BOOTLOADER)
0274             report = picolcd_out_report(REPORT_EXIT_FLASHER, data->hdev);
0275     } else if (sysfs_streq(buf, "bootloader")) {
0276         if (!(data->status & PICOLCD_BOOTLOADER))
0277             report = picolcd_out_report(REPORT_EXIT_KEYBOARD, data->hdev);
0278     } else {
0279         return -EINVAL;
0280     }
0281 
0282     if (!report || report->maxfield != 1)
0283         return -EINVAL;
0284 
0285     spin_lock_irqsave(&data->lock, flags);
0286     hid_set_field(report->field[0], 0, timeout & 0xff);
0287     hid_set_field(report->field[0], 1, (timeout >> 8) & 0xff);
0288     hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
0289     spin_unlock_irqrestore(&data->lock, flags);
0290     return count;
0291 }
0292 
0293 static DEVICE_ATTR(operation_mode, 0644, picolcd_operation_mode_show,
0294         picolcd_operation_mode_store);
0295 
0296 /*
0297  * The "operation_mode_delay" sysfs attribute
0298  */
0299 static ssize_t picolcd_operation_mode_delay_show(struct device *dev,
0300         struct device_attribute *attr, char *buf)
0301 {
0302     struct picolcd_data *data = dev_get_drvdata(dev);
0303 
0304     return snprintf(buf, PAGE_SIZE, "%hu\n", data->opmode_delay);
0305 }
0306 
0307 static ssize_t picolcd_operation_mode_delay_store(struct device *dev,
0308         struct device_attribute *attr, const char *buf, size_t count)
0309 {
0310     struct picolcd_data *data = dev_get_drvdata(dev);
0311     unsigned u;
0312     if (sscanf(buf, "%u", &u) != 1)
0313         return -EINVAL;
0314     if (u > 30000)
0315         return -EINVAL;
0316     else
0317         data->opmode_delay = u;
0318     return count;
0319 }
0320 
0321 static DEVICE_ATTR(operation_mode_delay, 0644, picolcd_operation_mode_delay_show,
0322         picolcd_operation_mode_delay_store);
0323 
0324 /*
0325  * Handle raw report as sent by device
0326  */
0327 static int picolcd_raw_event(struct hid_device *hdev,
0328         struct hid_report *report, u8 *raw_data, int size)
0329 {
0330     struct picolcd_data *data = hid_get_drvdata(hdev);
0331     unsigned long flags;
0332 
0333     if (!data)
0334         return 1;
0335 
0336     if (size > 64) {
0337         hid_warn(hdev, "invalid size value (%d) for picolcd raw event (%d)\n",
0338                 size, report->id);
0339         return 0;
0340     }
0341 
0342     if (report->id == REPORT_KEY_STATE) {
0343         if (data->input_keys)
0344             picolcd_raw_keypad(data, report, raw_data+1, size-1);
0345     } else if (report->id == REPORT_IR_DATA) {
0346         picolcd_raw_cir(data, report, raw_data+1, size-1);
0347     } else {
0348         spin_lock_irqsave(&data->lock, flags);
0349         /*
0350          * We let the caller of picolcd_send_and_wait() check if the
0351          * report we got is one of the expected ones or not.
0352          */
0353         if (data->pending) {
0354             memcpy(data->pending->raw_data, raw_data+1, size-1);
0355             data->pending->raw_size  = size-1;
0356             data->pending->in_report = report;
0357             complete(&data->pending->ready);
0358         }
0359         spin_unlock_irqrestore(&data->lock, flags);
0360     }
0361 
0362     picolcd_debug_raw_event(data, hdev, report, raw_data, size);
0363     return 1;
0364 }
0365 
0366 #ifdef CONFIG_PM
0367 static int picolcd_suspend(struct hid_device *hdev, pm_message_t message)
0368 {
0369     if (PMSG_IS_AUTO(message))
0370         return 0;
0371 
0372     picolcd_suspend_backlight(hid_get_drvdata(hdev));
0373     dbg_hid(PICOLCD_NAME " device ready for suspend\n");
0374     return 0;
0375 }
0376 
0377 static int picolcd_resume(struct hid_device *hdev)
0378 {
0379     int ret;
0380     ret = picolcd_resume_backlight(hid_get_drvdata(hdev));
0381     if (ret)
0382         dbg_hid(PICOLCD_NAME " restoring backlight failed: %d\n", ret);
0383     return 0;
0384 }
0385 
0386 static int picolcd_reset_resume(struct hid_device *hdev)
0387 {
0388     int ret;
0389     ret = picolcd_reset(hdev);
0390     if (ret)
0391         dbg_hid(PICOLCD_NAME " resetting our device failed: %d\n", ret);
0392     ret = picolcd_fb_reset(hid_get_drvdata(hdev), 0);
0393     if (ret)
0394         dbg_hid(PICOLCD_NAME " restoring framebuffer content failed: %d\n", ret);
0395     ret = picolcd_resume_lcd(hid_get_drvdata(hdev));
0396     if (ret)
0397         dbg_hid(PICOLCD_NAME " restoring lcd failed: %d\n", ret);
0398     ret = picolcd_resume_backlight(hid_get_drvdata(hdev));
0399     if (ret)
0400         dbg_hid(PICOLCD_NAME " restoring backlight failed: %d\n", ret);
0401     picolcd_leds_set(hid_get_drvdata(hdev));
0402     return 0;
0403 }
0404 #endif
0405 
0406 /* initialize keypad input device */
0407 static int picolcd_init_keys(struct picolcd_data *data,
0408         struct hid_report *report)
0409 {
0410     struct hid_device *hdev = data->hdev;
0411     struct input_dev *idev;
0412     int error, i;
0413 
0414     if (!report)
0415         return -ENODEV;
0416     if (report->maxfield != 1 || report->field[0]->report_count != 2 ||
0417             report->field[0]->report_size != 8) {
0418         hid_err(hdev, "unsupported KEY_STATE report\n");
0419         return -EINVAL;
0420     }
0421 
0422     idev = input_allocate_device();
0423     if (idev == NULL) {
0424         hid_err(hdev, "failed to allocate input device\n");
0425         return -ENOMEM;
0426     }
0427     input_set_drvdata(idev, hdev);
0428     memcpy(data->keycode, def_keymap, sizeof(def_keymap));
0429     idev->name = hdev->name;
0430     idev->phys = hdev->phys;
0431     idev->uniq = hdev->uniq;
0432     idev->id.bustype = hdev->bus;
0433     idev->id.vendor  = hdev->vendor;
0434     idev->id.product = hdev->product;
0435     idev->id.version = hdev->version;
0436     idev->dev.parent = &hdev->dev;
0437     idev->keycode     = &data->keycode;
0438     idev->keycodemax  = PICOLCD_KEYS;
0439     idev->keycodesize = sizeof(data->keycode[0]);
0440     input_set_capability(idev, EV_MSC, MSC_SCAN);
0441     set_bit(EV_REP, idev->evbit);
0442     for (i = 0; i < PICOLCD_KEYS; i++)
0443         input_set_capability(idev, EV_KEY, data->keycode[i]);
0444     error = input_register_device(idev);
0445     if (error) {
0446         hid_err(hdev, "error registering the input device\n");
0447         input_free_device(idev);
0448         return error;
0449     }
0450     data->input_keys = idev;
0451     return 0;
0452 }
0453 
0454 static void picolcd_exit_keys(struct picolcd_data *data)
0455 {
0456     struct input_dev *idev = data->input_keys;
0457 
0458     data->input_keys = NULL;
0459     if (idev)
0460         input_unregister_device(idev);
0461 }
0462 
0463 static int picolcd_probe_lcd(struct hid_device *hdev, struct picolcd_data *data)
0464 {
0465     int error;
0466 
0467     /* Setup keypad input device */
0468     error = picolcd_init_keys(data, picolcd_in_report(REPORT_KEY_STATE, hdev));
0469     if (error)
0470         goto err;
0471 
0472     /* Setup CIR input device */
0473     error = picolcd_init_cir(data, picolcd_in_report(REPORT_IR_DATA, hdev));
0474     if (error)
0475         goto err;
0476 
0477     /* Set up the framebuffer device */
0478     error = picolcd_init_framebuffer(data);
0479     if (error)
0480         goto err;
0481 
0482     /* Setup lcd class device */
0483     error = picolcd_init_lcd(data, picolcd_out_report(REPORT_CONTRAST, hdev));
0484     if (error)
0485         goto err;
0486 
0487     /* Setup backlight class device */
0488     error = picolcd_init_backlight(data, picolcd_out_report(REPORT_BRIGHTNESS, hdev));
0489     if (error)
0490         goto err;
0491 
0492     /* Setup the LED class devices */
0493     error = picolcd_init_leds(data, picolcd_out_report(REPORT_LED_STATE, hdev));
0494     if (error)
0495         goto err;
0496 
0497     picolcd_init_devfs(data, picolcd_out_report(REPORT_EE_READ, hdev),
0498             picolcd_out_report(REPORT_EE_WRITE, hdev),
0499             picolcd_out_report(REPORT_READ_MEMORY, hdev),
0500             picolcd_out_report(REPORT_WRITE_MEMORY, hdev),
0501             picolcd_out_report(REPORT_RESET, hdev));
0502     return 0;
0503 err:
0504     picolcd_exit_leds(data);
0505     picolcd_exit_backlight(data);
0506     picolcd_exit_lcd(data);
0507     picolcd_exit_framebuffer(data);
0508     picolcd_exit_cir(data);
0509     picolcd_exit_keys(data);
0510     return error;
0511 }
0512 
0513 static int picolcd_probe_bootloader(struct hid_device *hdev, struct picolcd_data *data)
0514 {
0515     picolcd_init_devfs(data, NULL, NULL,
0516             picolcd_out_report(REPORT_BL_READ_MEMORY, hdev),
0517             picolcd_out_report(REPORT_BL_WRITE_MEMORY, hdev), NULL);
0518     return 0;
0519 }
0520 
0521 static int picolcd_probe(struct hid_device *hdev,
0522              const struct hid_device_id *id)
0523 {
0524     struct picolcd_data *data;
0525     int error = -ENOMEM;
0526 
0527     dbg_hid(PICOLCD_NAME " hardware probe...\n");
0528 
0529     /*
0530      * Let's allocate the picolcd data structure, set some reasonable
0531      * defaults, and associate it with the device
0532      */
0533     data = kzalloc(sizeof(struct picolcd_data), GFP_KERNEL);
0534     if (data == NULL) {
0535         hid_err(hdev, "can't allocate space for Minibox PicoLCD device data\n");
0536         return -ENOMEM;
0537     }
0538 
0539     spin_lock_init(&data->lock);
0540     mutex_init(&data->mutex);
0541     data->hdev = hdev;
0542     data->opmode_delay = 5000;
0543     if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER)
0544         data->status |= PICOLCD_BOOTLOADER;
0545     hid_set_drvdata(hdev, data);
0546 
0547     /* Parse the device reports and start it up */
0548     error = hid_parse(hdev);
0549     if (error) {
0550         hid_err(hdev, "device report parse failed\n");
0551         goto err_cleanup_data;
0552     }
0553 
0554     error = hid_hw_start(hdev, 0);
0555     if (error) {
0556         hid_err(hdev, "hardware start failed\n");
0557         goto err_cleanup_data;
0558     }
0559 
0560     error = hid_hw_open(hdev);
0561     if (error) {
0562         hid_err(hdev, "failed to open input interrupt pipe for key and IR events\n");
0563         goto err_cleanup_hid_hw;
0564     }
0565 
0566     error = device_create_file(&hdev->dev, &dev_attr_operation_mode_delay);
0567     if (error) {
0568         hid_err(hdev, "failed to create sysfs attributes\n");
0569         goto err_cleanup_hid_ll;
0570     }
0571 
0572     error = device_create_file(&hdev->dev, &dev_attr_operation_mode);
0573     if (error) {
0574         hid_err(hdev, "failed to create sysfs attributes\n");
0575         goto err_cleanup_sysfs1;
0576     }
0577 
0578     if (data->status & PICOLCD_BOOTLOADER)
0579         error = picolcd_probe_bootloader(hdev, data);
0580     else
0581         error = picolcd_probe_lcd(hdev, data);
0582     if (error)
0583         goto err_cleanup_sysfs2;
0584 
0585     dbg_hid(PICOLCD_NAME " activated and initialized\n");
0586     return 0;
0587 
0588 err_cleanup_sysfs2:
0589     device_remove_file(&hdev->dev, &dev_attr_operation_mode);
0590 err_cleanup_sysfs1:
0591     device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay);
0592 err_cleanup_hid_ll:
0593     hid_hw_close(hdev);
0594 err_cleanup_hid_hw:
0595     hid_hw_stop(hdev);
0596 err_cleanup_data:
0597     kfree(data);
0598     return error;
0599 }
0600 
0601 static void picolcd_remove(struct hid_device *hdev)
0602 {
0603     struct picolcd_data *data = hid_get_drvdata(hdev);
0604     unsigned long flags;
0605 
0606     dbg_hid(PICOLCD_NAME " hardware remove...\n");
0607     spin_lock_irqsave(&data->lock, flags);
0608     data->status |= PICOLCD_FAILED;
0609     spin_unlock_irqrestore(&data->lock, flags);
0610 
0611     picolcd_exit_devfs(data);
0612     device_remove_file(&hdev->dev, &dev_attr_operation_mode);
0613     device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay);
0614     hid_hw_close(hdev);
0615     hid_hw_stop(hdev);
0616 
0617     /* Shortcut potential pending reply that will never arrive */
0618     spin_lock_irqsave(&data->lock, flags);
0619     if (data->pending)
0620         complete(&data->pending->ready);
0621     spin_unlock_irqrestore(&data->lock, flags);
0622 
0623     /* Cleanup LED */
0624     picolcd_exit_leds(data);
0625     /* Clean up the framebuffer */
0626     picolcd_exit_backlight(data);
0627     picolcd_exit_lcd(data);
0628     picolcd_exit_framebuffer(data);
0629     /* Cleanup input */
0630     picolcd_exit_cir(data);
0631     picolcd_exit_keys(data);
0632 
0633     mutex_destroy(&data->mutex);
0634     /* Finally, clean up the picolcd data itself */
0635     kfree(data);
0636 }
0637 
0638 static const struct hid_device_id picolcd_devices[] = {
0639     { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) },
0640     { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) },
0641     { }
0642 };
0643 MODULE_DEVICE_TABLE(hid, picolcd_devices);
0644 
0645 static struct hid_driver picolcd_driver = {
0646     .name =          "hid-picolcd",
0647     .id_table =      picolcd_devices,
0648     .probe =         picolcd_probe,
0649     .remove =        picolcd_remove,
0650     .raw_event =     picolcd_raw_event,
0651 #ifdef CONFIG_PM
0652     .suspend =       picolcd_suspend,
0653     .resume =        picolcd_resume,
0654     .reset_resume =  picolcd_reset_resume,
0655 #endif
0656 };
0657 module_hid_driver(picolcd_driver);
0658 
0659 MODULE_DESCRIPTION("Minibox graphics PicoLCD Driver");
0660 MODULE_LICENSE("GPL v2");