Blame view

drivers/hid/hid-led.c 12.1 KB
a10e763b8   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
2
3
4
5
6
7
  /*
   * Simple USB RGB LED driver
   *
   * Copyright 2016 Heiner Kallweit <hkallweit1@gmail.com>
   * Based on drivers/hid/hid-thingm.c and
   * drivers/usb/misc/usbled.c
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
   */
  
  #include <linux/hid.h>
  #include <linux/hidraw.h>
  #include <linux/leds.h>
  #include <linux/module.h>
  #include <linux/mutex.h>
  
  #include "hid-ids.h"
  
  enum hidled_report_type {
  	RAW_REQUEST,
  	OUTPUT_REPORT
  };
  
  enum hidled_type {
  	RISO_KAGAKU,
  	DREAM_CHEEKY,
007414e8f   Heiner Kallweit   HID: hid-led: add...
26
  	THINGM,
de9086509   Heiner Kallweit   HID: hid-led: add...
27
  	DELCOM,
9d1e048cc   Heiner Kallweit   HID: hid-led: add...
28
  	LUXAFOR,
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  };
  
  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)]
de9086509   Heiner Kallweit   HID: hid-led: add...
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  union delcom_packet {
  	__u8 data[8];
  	struct {
  		__u8 major_cmd;
  		__u8 minor_cmd;
  		__u8 data_lsb;
  		__u8 data_msb;
  	} tx;
  	struct {
  		__u8 cmd;
  	} rx;
  	struct {
  		__le16 family_code;
  		__le16 security_code;
  		__u8 fw_version;
  	} fw;
  };
  
  #define DELCOM_GREEN_LED	0
  #define DELCOM_RED_LED		1
  #define DELCOM_BLUE_LED		2
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
65
  struct hidled_device;
5bc839367   Heiner Kallweit   HID: hid-led: add...
66
  struct hidled_rgb;
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
67
68
69
70
71
72
  
  struct hidled_config {
  	enum hidled_type	type;
  	const char		*name;
  	const char		*short_name;
  	enum led_brightness	max_brightness;
5bc839367   Heiner Kallweit   HID: hid-led: add...
73
  	int			num_leds;
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
74
75
  	size_t			report_size;
  	enum hidled_report_type	report_type;
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
76
77
78
79
80
81
  	int (*init)(struct hidled_device *ldev);
  	int (*write)(struct led_classdev *cdev, enum led_brightness br);
  };
  
  struct hidled_led {
  	struct led_classdev	cdev;
5bc839367   Heiner Kallweit   HID: hid-led: add...
82
  	struct hidled_rgb	*rgb;
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
83
84
  	char			name[32];
  };
5bc839367   Heiner Kallweit   HID: hid-led: add...
85
86
  struct hidled_rgb {
  	struct hidled_device	*ldev;
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
87
88
89
  	struct hidled_led	red;
  	struct hidled_led	green;
  	struct hidled_led	blue;
5bc839367   Heiner Kallweit   HID: hid-led: add...
90
91
92
93
94
  	u8			num;
  };
  
  struct hidled_device {
  	const struct hidled_config *config;
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
95
  	struct hid_device       *hdev;
5bc839367   Heiner Kallweit   HID: hid-led: add...
96
  	struct hidled_rgb	*rgb;
3d1355b3c   Heiner Kallweit   HID: hid-led: fix...
97
  	u8			*buf;
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
  	struct mutex		lock;
  };
  
  #define MAX_REPORT_SIZE		16
  
  #define to_hidled_led(arg) container_of(arg, struct hidled_led, cdev)
  
  static bool riso_kagaku_switch_green_blue;
  module_param(riso_kagaku_switch_green_blue, bool, S_IRUGO | S_IWUSR);
  MODULE_PARM_DESC(riso_kagaku_switch_green_blue,
  	"switch green and blue RGB component for Riso Kagaku devices");
  
  static int hidled_send(struct hidled_device *ldev, __u8 *buf)
  {
  	int ret;
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
113
  	mutex_lock(&ldev->lock);
3d1355b3c   Heiner Kallweit   HID: hid-led: fix...
114
115
116
117
118
  	/*
  	 * buffer provided to hid_hw_raw_request must not be on the stack
  	 * and must not be part of a data structure
  	 */
  	memcpy(ldev->buf, buf, ldev->config->report_size);
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
119
  	if (ldev->config->report_type == RAW_REQUEST)
3d1355b3c   Heiner Kallweit   HID: hid-led: fix...
120
  		ret = hid_hw_raw_request(ldev->hdev, buf[0], ldev->buf,
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
121
122
123
124
  					 ldev->config->report_size,
  					 HID_FEATURE_REPORT,
  					 HID_REQ_SET_REPORT);
  	else if (ldev->config->report_type == OUTPUT_REPORT)
3d1355b3c   Heiner Kallweit   HID: hid-led: fix...
125
  		ret = hid_hw_output_report(ldev->hdev, ldev->buf,
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
126
127
128
129
130
131
132
133
134
135
136
  					   ldev->config->report_size);
  	else
  		ret = -EINVAL;
  
  	mutex_unlock(&ldev->lock);
  
  	if (ret < 0)
  		return ret;
  
  	return ret == ldev->config->report_size ? 0 : -EMSGSIZE;
  }
437457300   Heiner Kallweit   HID: hid-led: add...
137
138
139
140
141
142
143
  /* reading data is supported for report type RAW_REQUEST only */
  static int hidled_recv(struct hidled_device *ldev, __u8 *buf)
  {
  	int ret;
  
  	if (ldev->config->report_type != RAW_REQUEST)
  		return -EINVAL;
437457300   Heiner Kallweit   HID: hid-led: add...
144
  	mutex_lock(&ldev->lock);
3d1355b3c   Heiner Kallweit   HID: hid-led: fix...
145
146
147
  	memcpy(ldev->buf, buf, ldev->config->report_size);
  
  	ret = hid_hw_raw_request(ldev->hdev, buf[0], ldev->buf,
437457300   Heiner Kallweit   HID: hid-led: add...
148
149
150
151
152
  				 ldev->config->report_size,
  				 HID_FEATURE_REPORT,
  				 HID_REQ_SET_REPORT);
  	if (ret < 0)
  		goto err;
3d1355b3c   Heiner Kallweit   HID: hid-led: fix...
153
  	ret = hid_hw_raw_request(ldev->hdev, buf[0], ldev->buf,
437457300   Heiner Kallweit   HID: hid-led: add...
154
155
156
  				 ldev->config->report_size,
  				 HID_FEATURE_REPORT,
  				 HID_REQ_GET_REPORT);
3d1355b3c   Heiner Kallweit   HID: hid-led: fix...
157
158
  
  	memcpy(buf, ldev->buf, ldev->config->report_size);
437457300   Heiner Kallweit   HID: hid-led: add...
159
160
161
162
163
  err:
  	mutex_unlock(&ldev->lock);
  
  	return ret < 0 ? ret : 0;
  }
5bc839367   Heiner Kallweit   HID: hid-led: add...
164
  static u8 riso_kagaku_index(struct hidled_rgb *rgb)
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
165
166
  {
  	enum led_brightness r, g, b;
5bc839367   Heiner Kallweit   HID: hid-led: add...
167
168
169
  	r = rgb->red.cdev.brightness;
  	g = rgb->green.cdev.brightness;
  	b = rgb->blue.cdev.brightness;
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
170
171
172
173
174
175
176
177
178
179
  
  	if (riso_kagaku_switch_green_blue)
  		return RISO_KAGAKU_IX(r, b, g);
  	else
  		return RISO_KAGAKU_IX(r, g, b);
  }
  
  static int riso_kagaku_write(struct led_classdev *cdev, enum led_brightness br)
  {
  	struct hidled_led *led = to_hidled_led(cdev);
5bc839367   Heiner Kallweit   HID: hid-led: add...
180
  	struct hidled_rgb *rgb = led->rgb;
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
181
  	__u8 buf[MAX_REPORT_SIZE] = {};
5bc839367   Heiner Kallweit   HID: hid-led: add...
182
  	buf[1] = riso_kagaku_index(rgb);
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
183

5bc839367   Heiner Kallweit   HID: hid-led: add...
184
  	return hidled_send(rgb->ldev, buf);
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
185
186
187
188
189
  }
  
  static int dream_cheeky_write(struct led_classdev *cdev, enum led_brightness br)
  {
  	struct hidled_led *led = to_hidled_led(cdev);
5bc839367   Heiner Kallweit   HID: hid-led: add...
190
  	struct hidled_rgb *rgb = led->rgb;
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
191
  	__u8 buf[MAX_REPORT_SIZE] = {};
5bc839367   Heiner Kallweit   HID: hid-led: add...
192
193
194
  	buf[1] = rgb->red.cdev.brightness;
  	buf[2] = rgb->green.cdev.brightness;
  	buf[3] = rgb->blue.cdev.brightness;
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
195
196
  	buf[7] = 0x1a;
  	buf[8] = 0x05;
5bc839367   Heiner Kallweit   HID: hid-led: add...
197
  	return hidled_send(rgb->ldev, buf);
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
  }
  
  static int dream_cheeky_init(struct hidled_device *ldev)
  {
  	__u8 buf[MAX_REPORT_SIZE] = {};
  
  	/* Dream Cheeky magic */
  	buf[1] = 0x1f;
  	buf[2] = 0x02;
  	buf[4] = 0x5f;
  	buf[7] = 0x1a;
  	buf[8] = 0x03;
  
  	return hidled_send(ldev, buf);
  }
007414e8f   Heiner Kallweit   HID: hid-led: add...
213
214
215
216
  static int _thingm_write(struct led_classdev *cdev, enum led_brightness br,
  			 u8 offset)
  {
  	struct hidled_led *led = to_hidled_led(cdev);
34d9810b3   Heiner Kallweit   HID: hid-led: rem...
217
  	__u8 buf[MAX_REPORT_SIZE] = { 1, 'c' };
007414e8f   Heiner Kallweit   HID: hid-led: add...
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
  
  	buf[2] = led->rgb->red.cdev.brightness;
  	buf[3] = led->rgb->green.cdev.brightness;
  	buf[4] = led->rgb->blue.cdev.brightness;
  	buf[7] = led->rgb->num + offset;
  
  	return hidled_send(led->rgb->ldev, buf);
  }
  
  static int thingm_write_v1(struct led_classdev *cdev, enum led_brightness br)
  {
  	return _thingm_write(cdev, br, 0);
  }
  
  static int thingm_write(struct led_classdev *cdev, enum led_brightness br)
  {
  	return _thingm_write(cdev, br, 1);
  }
  
  static const struct hidled_config hidled_config_thingm_v1 = {
  	.name = "ThingM blink(1) v1",
  	.short_name = "thingm",
  	.max_brightness = 255,
  	.num_leds = 1,
  	.report_size = 9,
  	.report_type = RAW_REQUEST,
007414e8f   Heiner Kallweit   HID: hid-led: add...
244
245
246
247
248
  	.write = thingm_write_v1,
  };
  
  static int thingm_init(struct hidled_device *ldev)
  {
34d9810b3   Heiner Kallweit   HID: hid-led: rem...
249
  	__u8 buf[MAX_REPORT_SIZE] = { 1, 'v' };
007414e8f   Heiner Kallweit   HID: hid-led: add...
250
251
252
253
254
255
256
257
258
259
260
261
  	int ret;
  
  	ret = hidled_recv(ldev, buf);
  	if (ret)
  		return ret;
  
  	/* Check for firmware major version 1 */
  	if (buf[3] == '1')
  		ldev->config = &hidled_config_thingm_v1;
  
  	return 0;
  }
de9086509   Heiner Kallweit   HID: hid-led: add...
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
  static inline int delcom_get_lednum(const struct hidled_led *led)
  {
  	if (led == &led->rgb->red)
  		return DELCOM_RED_LED;
  	else if (led == &led->rgb->green)
  		return DELCOM_GREEN_LED;
  	else
  		return DELCOM_BLUE_LED;
  }
  
  static int delcom_enable_led(struct hidled_led *led)
  {
  	union delcom_packet dp = { .tx.major_cmd = 101, .tx.minor_cmd = 12 };
  
  	dp.tx.data_lsb = 1 << delcom_get_lednum(led);
  	dp.tx.data_msb = 0;
  
  	return hidled_send(led->rgb->ldev, dp.data);
  }
  
  static int delcom_set_pwm(struct hidled_led *led)
  {
  	union delcom_packet dp = { .tx.major_cmd = 101, .tx.minor_cmd = 34 };
  
  	dp.tx.data_lsb = delcom_get_lednum(led);
  	dp.tx.data_msb = led->cdev.brightness;
  
  	return hidled_send(led->rgb->ldev, dp.data);
  }
  
  static int delcom_write(struct led_classdev *cdev, enum led_brightness br)
  {
  	struct hidled_led *led = to_hidled_led(cdev);
  	int ret;
  
  	/*
  	 * enable LED
  	 * We can't do this in the init function already because the device
  	 * is internally reset later.
  	 */
  	ret = delcom_enable_led(led);
  	if (ret)
  		return ret;
  
  	return delcom_set_pwm(led);
  }
  
  static int delcom_init(struct hidled_device *ldev)
  {
  	union delcom_packet dp = { .rx.cmd = 104 };
  	int ret;
  
  	ret = hidled_recv(ldev, dp.data);
  	if (ret)
  		return ret;
  	/*
  	 * Several Delcom devices share the same USB VID/PID
  	 * Check for family id 2 for Visual Signal Indicator
  	 */
f4c109b66   Heiner Kallweit   HID: hid-led: fix...
321
  	return le16_to_cpu(dp.fw.family_code) == 2 ? 0 : -ENODEV;
de9086509   Heiner Kallweit   HID: hid-led: add...
322
  }
9d1e048cc   Heiner Kallweit   HID: hid-led: add...
323
324
325
326
327
328
329
330
331
332
333
334
  static int luxafor_write(struct led_classdev *cdev, enum led_brightness br)
  {
  	struct hidled_led *led = to_hidled_led(cdev);
  	__u8 buf[MAX_REPORT_SIZE] = { [1] = 1 };
  
  	buf[2] = led->rgb->num + 1;
  	buf[3] = led->rgb->red.cdev.brightness;
  	buf[4] = led->rgb->green.cdev.brightness;
  	buf[5] = led->rgb->blue.cdev.brightness;
  
  	return hidled_send(led->rgb->ldev, buf);
  }
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
335
336
337
338
339
340
  static const struct hidled_config hidled_configs[] = {
  	{
  		.type = RISO_KAGAKU,
  		.name = "Riso Kagaku Webmail Notifier",
  		.short_name = "riso_kagaku",
  		.max_brightness = 1,
5bc839367   Heiner Kallweit   HID: hid-led: add...
341
  		.num_leds = 1,
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
342
343
  		.report_size = 6,
  		.report_type = OUTPUT_REPORT,
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
344
345
346
347
348
349
350
  		.write = riso_kagaku_write,
  	},
  	{
  		.type = DREAM_CHEEKY,
  		.name = "Dream Cheeky Webmail Notifier",
  		.short_name = "dream_cheeky",
  		.max_brightness = 31,
5bc839367   Heiner Kallweit   HID: hid-led: add...
351
  		.num_leds = 1,
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
352
353
  		.report_size = 9,
  		.report_type = RAW_REQUEST,
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
354
355
356
  		.init = dream_cheeky_init,
  		.write = dream_cheeky_write,
  	},
007414e8f   Heiner Kallweit   HID: hid-led: add...
357
358
359
360
361
362
363
364
  	{
  		.type = THINGM,
  		.name = "ThingM blink(1)",
  		.short_name = "thingm",
  		.max_brightness = 255,
  		.num_leds = 2,
  		.report_size = 9,
  		.report_type = RAW_REQUEST,
007414e8f   Heiner Kallweit   HID: hid-led: add...
365
366
367
  		.init = thingm_init,
  		.write = thingm_write,
  	},
de9086509   Heiner Kallweit   HID: hid-led: add...
368
369
370
371
372
373
374
375
376
377
378
  	{
  		.type = DELCOM,
  		.name = "Delcom Visual Signal Indicator G2",
  		.short_name = "delcom",
  		.max_brightness = 100,
  		.num_leds = 1,
  		.report_size = 8,
  		.report_type = RAW_REQUEST,
  		.init = delcom_init,
  		.write = delcom_write,
  	},
9d1e048cc   Heiner Kallweit   HID: hid-led: add...
379
380
381
382
383
384
385
386
387
388
  	{
  		.type = LUXAFOR,
  		.name = "Greynut Luxafor",
  		.short_name = "luxafor",
  		.max_brightness = 255,
  		.num_leds = 6,
  		.report_size = 9,
  		.report_type = OUTPUT_REPORT,
  		.write = luxafor_write,
  	},
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
389
390
391
  };
  
  static int hidled_init_led(struct hidled_led *led, const char *color_name,
5bc839367   Heiner Kallweit   HID: hid-led: add...
392
  			   struct hidled_rgb *rgb, unsigned int minor)
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
393
  {
5bc839367   Heiner Kallweit   HID: hid-led: add...
394
395
396
397
398
399
400
401
  	const struct hidled_config *config = rgb->ldev->config;
  
  	if (config->num_leds > 1)
  		snprintf(led->name, sizeof(led->name), "%s%u:%s:led%u",
  			 config->short_name, minor, color_name, rgb->num);
  	else
  		snprintf(led->name, sizeof(led->name), "%s%u:%s",
  			 config->short_name, minor, color_name);
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
402
  	led->cdev.name = led->name;
5bc839367   Heiner Kallweit   HID: hid-led: add...
403
404
  	led->cdev.max_brightness = config->max_brightness;
  	led->cdev.brightness_set_blocking = config->write;
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
405
  	led->cdev.flags = LED_HW_PLUGGABLE;
5bc839367   Heiner Kallweit   HID: hid-led: add...
406
  	led->rgb = rgb;
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
407

5bc839367   Heiner Kallweit   HID: hid-led: add...
408
  	return devm_led_classdev_register(&rgb->ldev->hdev->dev, &led->cdev);
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
409
  }
5bc839367   Heiner Kallweit   HID: hid-led: add...
410
  static int hidled_init_rgb(struct hidled_rgb *rgb, unsigned int minor)
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
411
412
413
414
  {
  	int ret;
  
  	/* Register the red diode */
5bc839367   Heiner Kallweit   HID: hid-led: add...
415
  	ret = hidled_init_led(&rgb->red, "red", rgb, minor);
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
416
417
418
419
  	if (ret)
  		return ret;
  
  	/* Register the green diode */
5bc839367   Heiner Kallweit   HID: hid-led: add...
420
  	ret = hidled_init_led(&rgb->green, "green", rgb, minor);
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
421
422
423
424
  	if (ret)
  		return ret;
  
  	/* Register the blue diode */
5bc839367   Heiner Kallweit   HID: hid-led: add...
425
  	return hidled_init_led(&rgb->blue, "blue", rgb, minor);
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
426
427
428
429
430
431
432
433
434
435
436
  }
  
  static int hidled_probe(struct hid_device *hdev, const struct hid_device_id *id)
  {
  	struct hidled_device *ldev;
  	unsigned int minor;
  	int ret, i;
  
  	ldev = devm_kzalloc(&hdev->dev, sizeof(*ldev), GFP_KERNEL);
  	if (!ldev)
  		return -ENOMEM;
3d1355b3c   Heiner Kallweit   HID: hid-led: fix...
437
438
439
  	ldev->buf = devm_kmalloc(&hdev->dev, MAX_REPORT_SIZE, GFP_KERNEL);
  	if (!ldev->buf)
  		return -ENOMEM;
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
  	ret = hid_parse(hdev);
  	if (ret)
  		return ret;
  
  	ldev->hdev = hdev;
  	mutex_init(&ldev->lock);
  
  	for (i = 0; !ldev->config && i < ARRAY_SIZE(hidled_configs); i++)
  		if (hidled_configs[i].type == id->driver_data)
  			ldev->config = &hidled_configs[i];
  
  	if (!ldev->config)
  		return -EINVAL;
  
  	if (ldev->config->init) {
  		ret = ldev->config->init(ldev);
  		if (ret)
  			return ret;
  	}
5bc839367   Heiner Kallweit   HID: hid-led: add...
459
460
461
462
  	ldev->rgb = devm_kcalloc(&hdev->dev, ldev->config->num_leds,
  				 sizeof(struct hidled_rgb), GFP_KERNEL);
  	if (!ldev->rgb)
  		return -ENOMEM;
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
463
464
465
466
467
  	ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
  	if (ret)
  		return ret;
  
  	minor = ((struct hidraw *) hdev->hidraw)->minor;
5bc839367   Heiner Kallweit   HID: hid-led: add...
468
469
470
471
472
473
474
475
  	for (i = 0; i < ldev->config->num_leds; i++) {
  		ldev->rgb[i].ldev = ldev;
  		ldev->rgb[i].num = i;
  		ret = hidled_init_rgb(&ldev->rgb[i], minor);
  		if (ret) {
  			hid_hw_stop(hdev);
  			return ret;
  		}
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
  	}
  
  	hid_info(hdev, "%s initialized
  ", ldev->config->name);
  
  	return 0;
  }
  
  static const struct hid_device_id hidled_table[] = {
  	{ HID_USB_DEVICE(USB_VENDOR_ID_RISO_KAGAKU,
  	  USB_DEVICE_ID_RI_KA_WEBMAIL), .driver_data = RISO_KAGAKU },
  	{ HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY,
  	  USB_DEVICE_ID_DREAM_CHEEKY_WN), .driver_data = DREAM_CHEEKY },
  	{ HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY,
  	  USB_DEVICE_ID_DREAM_CHEEKY_FA), .driver_data = DREAM_CHEEKY },
007414e8f   Heiner Kallweit   HID: hid-led: add...
491
492
  	{ HID_USB_DEVICE(USB_VENDOR_ID_THINGM,
  	  USB_DEVICE_ID_BLINK1), .driver_data = THINGM },
de9086509   Heiner Kallweit   HID: hid-led: add...
493
494
  	{ HID_USB_DEVICE(USB_VENDOR_ID_DELCOM,
  	  USB_DEVICE_ID_DELCOM_VISUAL_IND), .driver_data = DELCOM },
9d1e048cc   Heiner Kallweit   HID: hid-led: add...
495
496
  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP,
  	  USB_DEVICE_ID_LUXAFOR), .driver_data = LUXAFOR },
6c7ad07e9   Heiner Kallweit   HID: migrate USB ...
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
  	{ }
  };
  MODULE_DEVICE_TABLE(hid, hidled_table);
  
  static struct hid_driver hidled_driver = {
  	.name = "hid-led",
  	.probe = hidled_probe,
  	.id_table = hidled_table,
  };
  
  module_hid_driver(hidled_driver);
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Heiner Kallweit <hkallweit1@gmail.com>");
  MODULE_DESCRIPTION("Simple USB RGB LED driver");