aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiner Kallweit <hkallweit1@gmail.com>2016-07-04 15:45:54 -0400
committerJiri Kosina <jkosina@suse.cz>2016-07-07 05:17:12 -0400
commitde9086509e716e9797f401dd260d5b4bdd2244c7 (patch)
treece91d0f0b88f92b174c5aeaa10d6c47293adfa95
parent34d9810b316b6de11a801a30339c070d1798a7b0 (diff)
HID: hid-led: add support for Delcom Visual Signal Indicator G2
Add support for the HID-compliant Delcom Visual Signal Indicator generation 2 devices. Successfully tested with part no 904000 from the family of these devices. Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/Kconfig1
-rw-r--r--drivers/hid/hid-core.c1
-rw-r--r--drivers/hid/hid-ids.h3
-rw-r--r--drivers/hid/hid-led.c98
4 files changed, 103 insertions, 0 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 8b1eb47930bc..e33ccefe3e54 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -397,6 +397,7 @@ config HID_LED
397 - Riso Kagaku Webmail Notifier 397 - Riso Kagaku Webmail Notifier
398 - Dream Cheeky Webmail Notifier and Friends Alert 398 - Dream Cheeky Webmail Notifier and Friends Alert
399 - ThingM blink(1) 399 - ThingM blink(1)
400 - Delcom Visual Signal Indicator Generation 2
400 401
401 To compile this driver as a module, choose M here: the 402 To compile this driver as a module, choose M here: the
402 module will be called hid-led. 403 module will be called hid-led.
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index eb674ce75fab..f808ae71f9a1 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1877,6 +1877,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1877 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) }, 1877 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) },
1878 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_4) }, 1878 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_4) },
1879 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, 1879 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) },
1880 { HID_USB_DEVICE(USB_VENDOR_ID_DELCOM, USB_DEVICE_ID_DELCOM_VISUAL_IND) },
1880 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, 1881 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
1881 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, 1882 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) },
1882 { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_WN) }, 1883 { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_WN) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index e104abae0dad..ffefbd09fb4c 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -296,6 +296,9 @@
296#define USB_VENDOR_ID_DEALEXTREAME 0x10c5 296#define USB_VENDOR_ID_DEALEXTREAME 0x10c5
297#define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a 297#define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a
298 298
299#define USB_VENDOR_ID_DELCOM 0x0fc5
300#define USB_DEVICE_ID_DELCOM_VISUAL_IND 0xb080
301
299#define USB_VENDOR_ID_DELORME 0x1163 302#define USB_VENDOR_ID_DELORME 0x1163
300#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 303#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
301#define USB_DEVICE_ID_DELORME_EM_LT20 0x0200 304#define USB_DEVICE_ID_DELORME_EM_LT20 0x0200
diff --git a/drivers/hid/hid-led.c b/drivers/hid/hid-led.c
index fce2a03cb647..d793ecefb8b6 100644
--- a/drivers/hid/hid-led.c
+++ b/drivers/hid/hid-led.c
@@ -27,6 +27,7 @@ enum hidled_type {
27 RISO_KAGAKU, 27 RISO_KAGAKU,
28 DREAM_CHEEKY, 28 DREAM_CHEEKY,
29 THINGM, 29 THINGM,
30 DELCOM,
30}; 31};
31 32
32static unsigned const char riso_kagaku_tbl[] = { 33static unsigned const char riso_kagaku_tbl[] = {
@@ -43,6 +44,28 @@ static unsigned const char riso_kagaku_tbl[] = {
43 44
44#define RISO_KAGAKU_IX(r, g, b) riso_kagaku_tbl[((r)?1:0)+((g)?2:0)+((b)?4:0)] 45#define RISO_KAGAKU_IX(r, g, b) riso_kagaku_tbl[((r)?1:0)+((g)?2:0)+((b)?4:0)]
45 46
47union delcom_packet {
48 __u8 data[8];
49 struct {
50 __u8 major_cmd;
51 __u8 minor_cmd;
52 __u8 data_lsb;
53 __u8 data_msb;
54 } tx;
55 struct {
56 __u8 cmd;
57 } rx;
58 struct {
59 __le16 family_code;
60 __le16 security_code;
61 __u8 fw_version;
62 } fw;
63};
64
65#define DELCOM_GREEN_LED 0
66#define DELCOM_RED_LED 1
67#define DELCOM_BLUE_LED 2
68
46struct hidled_device; 69struct hidled_device;
47struct hidled_rgb; 70struct hidled_rgb;
48 71
@@ -244,6 +267,68 @@ static int thingm_init(struct hidled_device *ldev)
244 return 0; 267 return 0;
245} 268}
246 269
270static inline int delcom_get_lednum(const struct hidled_led *led)
271{
272 if (led == &led->rgb->red)
273 return DELCOM_RED_LED;
274 else if (led == &led->rgb->green)
275 return DELCOM_GREEN_LED;
276 else
277 return DELCOM_BLUE_LED;
278}
279
280static int delcom_enable_led(struct hidled_led *led)
281{
282 union delcom_packet dp = { .tx.major_cmd = 101, .tx.minor_cmd = 12 };
283
284 dp.tx.data_lsb = 1 << delcom_get_lednum(led);
285 dp.tx.data_msb = 0;
286
287 return hidled_send(led->rgb->ldev, dp.data);
288}
289
290static int delcom_set_pwm(struct hidled_led *led)
291{
292 union delcom_packet dp = { .tx.major_cmd = 101, .tx.minor_cmd = 34 };
293
294 dp.tx.data_lsb = delcom_get_lednum(led);
295 dp.tx.data_msb = led->cdev.brightness;
296
297 return hidled_send(led->rgb->ldev, dp.data);
298}
299
300static int delcom_write(struct led_classdev *cdev, enum led_brightness br)
301{
302 struct hidled_led *led = to_hidled_led(cdev);
303 int ret;
304
305 /*
306 * enable LED
307 * We can't do this in the init function already because the device
308 * is internally reset later.
309 */
310 ret = delcom_enable_led(led);
311 if (ret)
312 return ret;
313
314 return delcom_set_pwm(led);
315}
316
317static int delcom_init(struct hidled_device *ldev)
318{
319 union delcom_packet dp = { .rx.cmd = 104 };
320 int ret;
321
322 ret = hidled_recv(ldev, dp.data);
323 if (ret)
324 return ret;
325 /*
326 * Several Delcom devices share the same USB VID/PID
327 * Check for family id 2 for Visual Signal Indicator
328 */
329 return dp.fw.family_code == 2 ? 0 : -ENODEV;
330}
331
247static const struct hidled_config hidled_configs[] = { 332static const struct hidled_config hidled_configs[] = {
248 { 333 {
249 .type = RISO_KAGAKU, 334 .type = RISO_KAGAKU,
@@ -277,6 +362,17 @@ static const struct hidled_config hidled_configs[] = {
277 .init = thingm_init, 362 .init = thingm_init,
278 .write = thingm_write, 363 .write = thingm_write,
279 }, 364 },
365 {
366 .type = DELCOM,
367 .name = "Delcom Visual Signal Indicator G2",
368 .short_name = "delcom",
369 .max_brightness = 100,
370 .num_leds = 1,
371 .report_size = 8,
372 .report_type = RAW_REQUEST,
373 .init = delcom_init,
374 .write = delcom_write,
375 },
280}; 376};
281 377
282static int hidled_init_led(struct hidled_led *led, const char *color_name, 378static int hidled_init_led(struct hidled_led *led, const char *color_name,
@@ -382,6 +478,8 @@ static const struct hid_device_id hidled_table[] = {
382 USB_DEVICE_ID_DREAM_CHEEKY_FA), .driver_data = DREAM_CHEEKY }, 478 USB_DEVICE_ID_DREAM_CHEEKY_FA), .driver_data = DREAM_CHEEKY },
383 { HID_USB_DEVICE(USB_VENDOR_ID_THINGM, 479 { HID_USB_DEVICE(USB_VENDOR_ID_THINGM,
384 USB_DEVICE_ID_BLINK1), .driver_data = THINGM }, 480 USB_DEVICE_ID_BLINK1), .driver_data = THINGM },
481 { HID_USB_DEVICE(USB_VENDOR_ID_DELCOM,
482 USB_DEVICE_ID_DELCOM_VISUAL_IND), .driver_data = DELCOM },
385 { } 483 { }
386}; 484};
387MODULE_DEVICE_TABLE(hid, hidled_table); 485MODULE_DEVICE_TABLE(hid, hidled_table);