diff options
author | Melchior FRANZ <mfranz@aon.at> | 2010-12-21 20:04:33 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-12-21 23:48:21 -0500 |
commit | 73bc7d315f56e260071bdb5f15e25b53bddc1402 (patch) | |
tree | 20e676a2eb44f2b5eba6bee581a74ccca6a60cde /drivers/usb/misc/usbled.c | |
parent | c466cd2bb9cee2e576fc9663b828f51e322d7b4b (diff) |
USB: add support for Dream Cheeky DL100B Webmail Notifier (1d34:0004)
So far the USBLED driver only supports Delcom's "USB Visual Signal
Indicator" (http://www.delcomproducts.com/products_USBLMP.asp). The
driver generates virtual files "red", "green", and "blue" under the
device's /sys/ directory, where color values can be read from and
written to.
This patch adds support for Dream Cheeky's "DL100B Webmail Notifier"
(http://www.dreamcheeky.com/webmail-notifier -- available from several
shops, such as http://www.conrad.at/ce/de/product/777048/USB-WEBMAIL).
This device isn't as pretty as Delcom's, but it's *far* cheaper, and
its 3 LEDs can be set in 32 brightness steps each. The grey envelope
contour can easily be removed, leaving a rather neutral white box (with
a few small holes), which is useful for generic signalling purposes.
Of course, the small circuit board can easily be put into a prettier
case.
The DL100B device pretends to be a HID, but the HID descriptor shows
that it's not overly useful as such (see below). The patch therefore
removes the "HID-ness" (hid-core.c, hid-ids.h), and adds the necessary
commands to usbled.c. The protocol info comes from the developer's
manual that Dream Cheeky kindly provided (815DeveloperManual.pdf).
HID descriptor:
0: 05 01 Usage Page 'Generic Desktop Controls'
2: 09 10 Usage 'Reserved'
4: a1 01 Collection 'Application (mouse, keyboard)'
6: 05 00 Usage Page 'Undefined'
8: 19 10 Usage Minimum = 16
10: 29 11 Usage Maximum = 17
12: 15 00 Logical Minimum = 0
14: 25 0f Logical Maximum = 15
16: 75 08 Report Size = 8
18: 95 08 Report Count = 8
20: 91 02 Output data *var abs lin pref-state null-pos non-vol bit-field
22: 19 10 Usage Minimum = 16
24: 29 11 Usage Maximum = 17
26: 15 00 Logical Minimum = 0
28: 25 0f Logical Maximum = 15
30: 75 08 Report Size = 8
32: 95 08 Report Count = 8
34: 81 00 Input data array abs lin pref-state null-pos non-vol bit-field
36: c0 End Collection
Signed-off-by: Melchior FRANZ <mfranz@aon.at>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/misc/usbled.c')
-rw-r--r-- | drivers/usb/misc/usbled.c | 118 |
1 files changed, 90 insertions, 28 deletions
diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c index c96f51de1696..1732d9bc097e 100644 --- a/drivers/usb/misc/usbled.c +++ b/drivers/usb/misc/usbled.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * USB LED driver - 1.1 | 2 | * USB LED driver |
3 | * | 3 | * |
4 | * Copyright (C) 2004 Greg Kroah-Hartman (greg@kroah.com) | 4 | * Copyright (C) 2004 Greg Kroah-Hartman (greg@kroah.com) |
5 | * | 5 | * |
@@ -20,12 +20,17 @@ | |||
20 | #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com" | 20 | #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com" |
21 | #define DRIVER_DESC "USB LED Driver" | 21 | #define DRIVER_DESC "USB LED Driver" |
22 | 22 | ||
23 | #define VENDOR_ID 0x0fc5 | 23 | enum led_type { |
24 | #define PRODUCT_ID 0x1223 | 24 | DELCOM_VISUAL_SIGNAL_INDICATOR, |
25 | DREAM_CHEEKY_WEBMAIL_NOTIFIER, | ||
26 | }; | ||
25 | 27 | ||
26 | /* table of devices that work with this driver */ | 28 | /* table of devices that work with this driver */ |
27 | static const struct usb_device_id id_table[] = { | 29 | static const struct usb_device_id id_table[] = { |
28 | { USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, | 30 | { USB_DEVICE(0x0fc5, 0x1223), |
31 | .driver_info = DELCOM_VISUAL_SIGNAL_INDICATOR }, | ||
32 | { USB_DEVICE(0x1d34, 0x0004), | ||
33 | .driver_info = DREAM_CHEEKY_WEBMAIL_NOTIFIER }, | ||
29 | { }, | 34 | { }, |
30 | }; | 35 | }; |
31 | MODULE_DEVICE_TABLE (usb, id_table); | 36 | MODULE_DEVICE_TABLE (usb, id_table); |
@@ -35,15 +40,12 @@ struct usb_led { | |||
35 | unsigned char blue; | 40 | unsigned char blue; |
36 | unsigned char red; | 41 | unsigned char red; |
37 | unsigned char green; | 42 | unsigned char green; |
43 | enum led_type type; | ||
38 | }; | 44 | }; |
39 | 45 | ||
40 | #define BLUE 0x04 | ||
41 | #define RED 0x02 | ||
42 | #define GREEN 0x01 | ||
43 | static void change_color(struct usb_led *led) | 46 | static void change_color(struct usb_led *led) |
44 | { | 47 | { |
45 | int retval; | 48 | int retval; |
46 | unsigned char color = 0x07; | ||
47 | unsigned char *buffer; | 49 | unsigned char *buffer; |
48 | 50 | ||
49 | buffer = kmalloc(8, GFP_KERNEL); | 51 | buffer = kmalloc(8, GFP_KERNEL); |
@@ -52,25 +54,59 @@ static void change_color(struct usb_led *led) | |||
52 | return; | 54 | return; |
53 | } | 55 | } |
54 | 56 | ||
55 | if (led->blue) | 57 | switch (led->type) { |
56 | color &= ~(BLUE); | 58 | case DELCOM_VISUAL_SIGNAL_INDICATOR: { |
57 | if (led->red) | 59 | unsigned char color = 0x07; |
58 | color &= ~(RED); | 60 | |
59 | if (led->green) | 61 | if (led->blue) |
60 | color &= ~(GREEN); | 62 | color &= ~0x04; |
61 | dev_dbg(&led->udev->dev, | 63 | if (led->red) |
62 | "blue = %d, red = %d, green = %d, color = %.2x\n", | 64 | color &= ~0x02; |
63 | led->blue, led->red, led->green, color); | 65 | if (led->green) |
64 | 66 | color &= ~0x01; | |
65 | retval = usb_control_msg(led->udev, | 67 | dev_dbg(&led->udev->dev, |
66 | usb_sndctrlpipe(led->udev, 0), | 68 | "blue = %d, red = %d, green = %d, color = %.2x\n", |
67 | 0x12, | 69 | led->blue, led->red, led->green, color); |
68 | 0xc8, | 70 | |
69 | (0x02 * 0x100) + 0x0a, | 71 | retval = usb_control_msg(led->udev, |
70 | (0x00 * 0x100) + color, | 72 | usb_sndctrlpipe(led->udev, 0), |
71 | buffer, | 73 | 0x12, |
72 | 8, | 74 | 0xc8, |
73 | 2000); | 75 | (0x02 * 0x100) + 0x0a, |
76 | (0x00 * 0x100) + color, | ||
77 | buffer, | ||
78 | 8, | ||
79 | 2000); | ||
80 | break; | ||
81 | } | ||
82 | |||
83 | case DREAM_CHEEKY_WEBMAIL_NOTIFIER: | ||
84 | dev_dbg(&led->udev->dev, | ||
85 | "red = %d, green = %d, blue = %d\n", | ||
86 | led->red, led->green, led->blue); | ||
87 | |||
88 | buffer[0] = led->red; | ||
89 | buffer[1] = led->green; | ||
90 | buffer[2] = led->blue; | ||
91 | buffer[3] = buffer[4] = buffer[5] = 0; | ||
92 | buffer[6] = 0x1a; | ||
93 | buffer[7] = 0x05; | ||
94 | |||
95 | retval = usb_control_msg(led->udev, | ||
96 | usb_sndctrlpipe(led->udev, 0), | ||
97 | 0x09, | ||
98 | 0x21, | ||
99 | 0x200, | ||
100 | 0, | ||
101 | buffer, | ||
102 | 8, | ||
103 | 2000); | ||
104 | break; | ||
105 | |||
106 | default: | ||
107 | dev_err(&led->udev->dev, "unknown device type %d\n", led->type); | ||
108 | } | ||
109 | |||
74 | if (retval) | 110 | if (retval) |
75 | dev_dbg(&led->udev->dev, "retval = %d\n", retval); | 111 | dev_dbg(&led->udev->dev, "retval = %d\n", retval); |
76 | kfree(buffer); | 112 | kfree(buffer); |
@@ -107,11 +143,12 @@ static int led_probe(struct usb_interface *interface, const struct usb_device_id | |||
107 | 143 | ||
108 | dev = kzalloc(sizeof(struct usb_led), GFP_KERNEL); | 144 | dev = kzalloc(sizeof(struct usb_led), GFP_KERNEL); |
109 | if (dev == NULL) { | 145 | if (dev == NULL) { |
110 | dev_err(&interface->dev, "Out of memory\n"); | 146 | dev_err(&interface->dev, "out of memory\n"); |
111 | goto error_mem; | 147 | goto error_mem; |
112 | } | 148 | } |
113 | 149 | ||
114 | dev->udev = usb_get_dev(udev); | 150 | dev->udev = usb_get_dev(udev); |
151 | dev->type = id->driver_info; | ||
115 | 152 | ||
116 | usb_set_intfdata (interface, dev); | 153 | usb_set_intfdata (interface, dev); |
117 | 154 | ||
@@ -125,6 +162,31 @@ static int led_probe(struct usb_interface *interface, const struct usb_device_id | |||
125 | if (retval) | 162 | if (retval) |
126 | goto error; | 163 | goto error; |
127 | 164 | ||
165 | if (dev->type == DREAM_CHEEKY_WEBMAIL_NOTIFIER) { | ||
166 | unsigned char *enable; | ||
167 | |||
168 | enable = kmemdup("\x1f\x02\0\x5f\0\0\x1a\x03", 8, GFP_KERNEL); | ||
169 | if (!enable) { | ||
170 | dev_err(&interface->dev, "out of memory\n"); | ||
171 | retval = -ENOMEM; | ||
172 | goto error; | ||
173 | } | ||
174 | |||
175 | retval = usb_control_msg(udev, | ||
176 | usb_sndctrlpipe(udev, 0), | ||
177 | 0x09, | ||
178 | 0x21, | ||
179 | 0x200, | ||
180 | 0, | ||
181 | enable, | ||
182 | 8, | ||
183 | 2000); | ||
184 | |||
185 | kfree(enable); | ||
186 | if (retval != 8) | ||
187 | goto error; | ||
188 | } | ||
189 | |||
128 | dev_info(&interface->dev, "USB LED device now attached\n"); | 190 | dev_info(&interface->dev, "USB LED device now attached\n"); |
129 | return 0; | 191 | return 0; |
130 | 192 | ||