0001
0002
0003
0004
0005
0006
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 #include <linux/backlight.h>
0018 #include <linux/lcd.h>
0019
0020 #include <linux/leds.h>
0021
0022 #include <linux/seq_file.h>
0023 #include <linux/debugfs.h>
0024
0025 #include <linux/completion.h>
0026 #include <linux/uaccess.h>
0027 #include <linux/module.h>
0028
0029 #include "hid-picolcd.h"
0030
0031
0032 void picolcd_leds_set(struct picolcd_data *data)
0033 {
0034 struct hid_report *report;
0035 unsigned long flags;
0036
0037 if (!data->led[0])
0038 return;
0039 report = picolcd_out_report(REPORT_LED_STATE, data->hdev);
0040 if (!report || report->maxfield != 1 || report->field[0]->report_count != 1)
0041 return;
0042
0043 spin_lock_irqsave(&data->lock, flags);
0044 hid_set_field(report->field[0], 0, data->led_state);
0045 if (!(data->status & PICOLCD_FAILED))
0046 hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
0047 spin_unlock_irqrestore(&data->lock, flags);
0048 }
0049
0050 static void picolcd_led_set_brightness(struct led_classdev *led_cdev,
0051 enum led_brightness value)
0052 {
0053 struct device *dev;
0054 struct hid_device *hdev;
0055 struct picolcd_data *data;
0056 int i, state = 0;
0057
0058 dev = led_cdev->dev->parent;
0059 hdev = to_hid_device(dev);
0060 data = hid_get_drvdata(hdev);
0061 if (!data)
0062 return;
0063 for (i = 0; i < 8; i++) {
0064 if (led_cdev != data->led[i])
0065 continue;
0066 state = (data->led_state >> i) & 1;
0067 if (value == LED_OFF && state) {
0068 data->led_state &= ~(1 << i);
0069 picolcd_leds_set(data);
0070 } else if (value != LED_OFF && !state) {
0071 data->led_state |= 1 << i;
0072 picolcd_leds_set(data);
0073 }
0074 break;
0075 }
0076 }
0077
0078 static enum led_brightness picolcd_led_get_brightness(struct led_classdev *led_cdev)
0079 {
0080 struct device *dev;
0081 struct hid_device *hdev;
0082 struct picolcd_data *data;
0083 int i, value = 0;
0084
0085 dev = led_cdev->dev->parent;
0086 hdev = to_hid_device(dev);
0087 data = hid_get_drvdata(hdev);
0088 for (i = 0; i < 8; i++)
0089 if (led_cdev == data->led[i]) {
0090 value = (data->led_state >> i) & 1;
0091 break;
0092 }
0093 return value ? LED_FULL : LED_OFF;
0094 }
0095
0096 int picolcd_init_leds(struct picolcd_data *data, struct hid_report *report)
0097 {
0098 struct device *dev = &data->hdev->dev;
0099 struct led_classdev *led;
0100 size_t name_sz = strlen(dev_name(dev)) + 8;
0101 char *name;
0102 int i, ret = 0;
0103
0104 if (!report)
0105 return -ENODEV;
0106 if (report->maxfield != 1 || report->field[0]->report_count != 1 ||
0107 report->field[0]->report_size != 8) {
0108 dev_err(dev, "unsupported LED_STATE report");
0109 return -EINVAL;
0110 }
0111
0112 for (i = 0; i < 8; i++) {
0113 led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL);
0114 if (!led) {
0115 dev_err(dev, "can't allocate memory for LED %d\n", i);
0116 ret = -ENOMEM;
0117 goto err;
0118 }
0119 name = (void *)(&led[1]);
0120 snprintf(name, name_sz, "%s::GPO%d", dev_name(dev), i);
0121 led->name = name;
0122 led->brightness = 0;
0123 led->max_brightness = 1;
0124 led->brightness_get = picolcd_led_get_brightness;
0125 led->brightness_set = picolcd_led_set_brightness;
0126
0127 data->led[i] = led;
0128 ret = led_classdev_register(dev, data->led[i]);
0129 if (ret) {
0130 data->led[i] = NULL;
0131 kfree(led);
0132 dev_err(dev, "can't register LED %d\n", i);
0133 goto err;
0134 }
0135 }
0136 return 0;
0137 err:
0138 for (i = 0; i < 8; i++)
0139 if (data->led[i]) {
0140 led = data->led[i];
0141 data->led[i] = NULL;
0142 led_classdev_unregister(led);
0143 kfree(led);
0144 }
0145 return ret;
0146 }
0147
0148 void picolcd_exit_leds(struct picolcd_data *data)
0149 {
0150 struct led_classdev *led;
0151 int i;
0152
0153 for (i = 0; i < 8; i++) {
0154 led = data->led[i];
0155 data->led[i] = NULL;
0156 if (!led)
0157 continue;
0158 led_classdev_unregister(led);
0159 kfree(led);
0160 }
0161 }
0162
0163