usb/misc/usbled: Add Riso Kagaku Webmail Notifier
authorChristian Vogel <vogelchr@vogel.cx>
Mon, 10 Feb 2014 17:49:43 +0000 (18:49 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 11 Feb 2014 22:00:16 +0000 (14:00 -0800)
Add support for the "Webmail Notifier" (USB powered LED for signaling
new emails) made by Riso Kagaku Corp. which displays 7 distinct colors.

USB Protocol initially reverse engineered by
https://code.google.com/p/usbmailnotifier/.

Signed-off-by: Christian Vogel <vogelchr@vogel.cx>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/misc/usbled.c

index 78eb4ff..bdef0d6 100644 (file)
 enum led_type {
        DELCOM_VISUAL_SIGNAL_INDICATOR,
        DREAM_CHEEKY_WEBMAIL_NOTIFIER,
+       RISO_KAGAKU_LED
 };
 
+/* the Webmail LED made by RISO KAGAKU CORP. decodes a color index
+   internally, we want to keep the red+green+blue sysfs api, so we decode
+   from 1-bit RGB to the riso kagaku color index according to this table... */
+
+static unsigned const char riso_kagaku_tbl[] = {
+/* R+2G+4B -> riso kagaku color index */
+       [0] = 0, /* black   */
+       [1] = 2, /* red     */
+       [2] = 1, /* green   */
+       [3] = 5, /* yellow  */
+       [4] = 3, /* blue    */
+       [5] = 6, /* magenta */
+       [6] = 4, /* cyan    */
+       [7] = 7  /* white   */
+};
+
+#define RISO_KAGAKU_IX(r,g,b) riso_kagaku_tbl[((r)?1:0)+((g)?2:0)+((b)?4:0)]
+
 /* table of devices that work with this driver */
 static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x0fc5, 0x1223),
@@ -32,6 +51,8 @@ static const struct usb_device_id id_table[] = {
                        .driver_info = DREAM_CHEEKY_WEBMAIL_NOTIFIER },
        { USB_DEVICE(0x1d34, 0x000a),
                        .driver_info = DREAM_CHEEKY_WEBMAIL_NOTIFIER },
+       { USB_DEVICE(0x1294, 0x1320),
+                       .driver_info = RISO_KAGAKU_LED },
        { },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
@@ -48,6 +69,7 @@ static void change_color(struct usb_led *led)
 {
        int retval = 0;
        unsigned char *buffer;
+       int actlength;
 
        buffer = kmalloc(8, GFP_KERNEL);
        if (!buffer) {
@@ -104,6 +126,18 @@ static void change_color(struct usb_led *led)
                                        2000);
                break;
 
+       case RISO_KAGAKU_LED:
+               buffer[0] = RISO_KAGAKU_IX(led->red, led->green, led->blue);
+               buffer[1] = 0;
+               buffer[2] = 0;
+               buffer[3] = 0;
+               buffer[4] = 0;
+
+               retval = usb_interrupt_msg(led->udev,
+                       usb_sndctrlpipe(led->udev, 2),
+                       buffer, 5, &actlength, 1000 /*ms timeout*/);
+               break;
+
        default:
                dev_err(&led->udev->dev, "unknown device type %d\n", led->type);
        }