4 * Copyright (C) 2004 Greg Kroah-Hartman (greg@kroah.com)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2.
12 #include <linux/kernel.h>
13 #include <linux/errno.h>
14 #include <linux/slab.h>
15 #include <linux/module.h>
16 #include <linux/usb.h>
19 #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com"
20 #define DRIVER_DESC "USB LED Driver"
23 DELCOM_VISUAL_SIGNAL_INDICATOR
,
24 DREAM_CHEEKY_WEBMAIL_NOTIFIER
,
28 /* the Webmail LED made by RISO KAGAKU CORP. decodes a color index
29 internally, we want to keep the red+green+blue sysfs api, so we decode
30 from 1-bit RGB to the riso kagaku color index according to this table... */
32 static unsigned const char riso_kagaku_tbl
[] = {
33 /* R+2G+4B -> riso kagaku color index */
39 [5] = 6, /* magenta */
44 #define RISO_KAGAKU_IX(r,g,b) riso_kagaku_tbl[((r)?1:0)+((g)?2:0)+((b)?4:0)]
46 /* table of devices that work with this driver */
47 static const struct usb_device_id id_table
[] = {
48 { USB_DEVICE(0x0fc5, 0x1223),
49 .driver_info
= DELCOM_VISUAL_SIGNAL_INDICATOR
},
50 { USB_DEVICE(0x1d34, 0x0004),
51 .driver_info
= DREAM_CHEEKY_WEBMAIL_NOTIFIER
},
52 { USB_DEVICE(0x1d34, 0x000a),
53 .driver_info
= DREAM_CHEEKY_WEBMAIL_NOTIFIER
},
54 { USB_DEVICE(0x1294, 0x1320),
55 .driver_info
= RISO_KAGAKU_LED
},
58 MODULE_DEVICE_TABLE(usb
, id_table
);
61 struct usb_device
*udev
;
68 static void change_color(struct usb_led
*led
)
71 unsigned char *buffer
;
74 buffer
= kmalloc(8, GFP_KERNEL
);
76 dev_err(&led
->udev
->dev
, "out of memory\n");
81 case DELCOM_VISUAL_SIGNAL_INDICATOR
: {
82 unsigned char color
= 0x07;
90 dev_dbg(&led
->udev
->dev
,
91 "blue = %d, red = %d, green = %d, color = %.2x\n",
92 led
->blue
, led
->red
, led
->green
, color
);
94 retval
= usb_control_msg(led
->udev
,
95 usb_sndctrlpipe(led
->udev
, 0),
98 (0x02 * 0x100) + 0x0a,
99 (0x00 * 0x100) + color
,
106 case DREAM_CHEEKY_WEBMAIL_NOTIFIER
:
107 dev_dbg(&led
->udev
->dev
,
108 "red = %d, green = %d, blue = %d\n",
109 led
->red
, led
->green
, led
->blue
);
111 buffer
[0] = led
->red
;
112 buffer
[1] = led
->green
;
113 buffer
[2] = led
->blue
;
114 buffer
[3] = buffer
[4] = buffer
[5] = 0;
118 retval
= usb_control_msg(led
->udev
,
119 usb_sndctrlpipe(led
->udev
, 0),
129 case RISO_KAGAKU_LED
:
130 buffer
[0] = RISO_KAGAKU_IX(led
->red
, led
->green
, led
->blue
);
136 retval
= usb_interrupt_msg(led
->udev
,
137 usb_sndctrlpipe(led
->udev
, 2),
138 buffer
, 5, &actlength
, 1000 /*ms timeout*/);
142 dev_err(&led
->udev
->dev
, "unknown device type %d\n", led
->type
);
146 dev_dbg(&led
->udev
->dev
, "retval = %d\n", retval
);
150 #define show_set(value) \
151 static ssize_t show_##value(struct device *dev, struct device_attribute *attr,\
154 struct usb_interface *intf = to_usb_interface(dev); \
155 struct usb_led *led = usb_get_intfdata(intf); \
157 return sprintf(buf, "%d\n", led->value); \
159 static ssize_t set_##value(struct device *dev, struct device_attribute *attr,\
160 const char *buf, size_t count) \
162 struct usb_interface *intf = to_usb_interface(dev); \
163 struct usb_led *led = usb_get_intfdata(intf); \
164 int temp = simple_strtoul(buf, NULL, 10); \
170 static DEVICE_ATTR(value, S_IRUGO | S_IWUSR, show_##value, set_##value);
175 static int led_probe(struct usb_interface
*interface
,
176 const struct usb_device_id
*id
)
178 struct usb_device
*udev
= interface_to_usbdev(interface
);
179 struct usb_led
*dev
= NULL
;
180 int retval
= -ENOMEM
;
182 dev
= kzalloc(sizeof(struct usb_led
), GFP_KERNEL
);
184 dev_err(&interface
->dev
, "out of memory\n");
188 dev
->udev
= usb_get_dev(udev
);
189 dev
->type
= id
->driver_info
;
191 usb_set_intfdata(interface
, dev
);
193 retval
= device_create_file(&interface
->dev
, &dev_attr_blue
);
196 retval
= device_create_file(&interface
->dev
, &dev_attr_red
);
199 retval
= device_create_file(&interface
->dev
, &dev_attr_green
);
203 if (dev
->type
== DREAM_CHEEKY_WEBMAIL_NOTIFIER
) {
204 unsigned char *enable
;
206 enable
= kmemdup("\x1f\x02\0\x5f\0\0\x1a\x03", 8, GFP_KERNEL
);
208 dev_err(&interface
->dev
, "out of memory\n");
213 retval
= usb_control_msg(udev
,
214 usb_sndctrlpipe(udev
, 0),
228 dev_info(&interface
->dev
, "USB LED device now attached\n");
232 device_remove_file(&interface
->dev
, &dev_attr_blue
);
233 device_remove_file(&interface
->dev
, &dev_attr_red
);
234 device_remove_file(&interface
->dev
, &dev_attr_green
);
235 usb_set_intfdata(interface
, NULL
);
236 usb_put_dev(dev
->udev
);
242 static void led_disconnect(struct usb_interface
*interface
)
246 dev
= usb_get_intfdata(interface
);
248 device_remove_file(&interface
->dev
, &dev_attr_blue
);
249 device_remove_file(&interface
->dev
, &dev_attr_red
);
250 device_remove_file(&interface
->dev
, &dev_attr_green
);
252 /* first remove the files, then set the pointer to NULL */
253 usb_set_intfdata(interface
, NULL
);
255 usb_put_dev(dev
->udev
);
259 dev_info(&interface
->dev
, "USB LED now disconnected\n");
262 static struct usb_driver led_driver
= {
265 .disconnect
= led_disconnect
,
266 .id_table
= id_table
,
269 module_usb_driver(led_driver
);
271 MODULE_AUTHOR(DRIVER_AUTHOR
);
272 MODULE_DESCRIPTION(DRIVER_DESC
);
273 MODULE_LICENSE("GPL");