diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2013-05-05 17:12:54 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2013-06-03 05:07:01 -0400 |
commit | 6c5ae01805e2cc1810328b538ccb2376b5f8bd9f (patch) | |
tree | 0870bb177a597bb36787d48b4112c587ab2614f9 | |
parent | dcf392313817efb4f318ebbf21f607dbdaf5ea56 (diff) |
HID: wiimote: convert LEDS to modules
Each of the 4 LEDs may be supported individually by devices. Therefore,
we need one module for each device. To avoid code-duplication, we simply
pass the LED ID as "arg" argument to the module loading code.
This just moves the code over to wiimote-module. The semantics stay the
same as before.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | drivers/hid/hid-wiimote-core.c | 125 | ||||
-rw-r--r-- | drivers/hid/hid-wiimote-modules.c | 140 | ||||
-rw-r--r-- | drivers/hid/hid-wiimote.h | 5 |
3 files changed, 158 insertions, 112 deletions
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c index bb1b3e3f4550..4f58c7827395 100644 --- a/drivers/hid/hid-wiimote-core.c +++ b/drivers/hid/hid-wiimote-core.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
15 | #include <linux/hid.h> | 15 | #include <linux/hid.h> |
16 | #include <linux/input.h> | 16 | #include <linux/input.h> |
17 | #include <linux/leds.h> | ||
18 | #include <linux/module.h> | 17 | #include <linux/module.h> |
19 | #include <linux/mutex.h> | 18 | #include <linux/mutex.h> |
20 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
@@ -151,7 +150,7 @@ void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble) | |||
151 | wiimote_queue(wdata, cmd, sizeof(cmd)); | 150 | wiimote_queue(wdata, cmd, sizeof(cmd)); |
152 | } | 151 | } |
153 | 152 | ||
154 | static void wiiproto_req_leds(struct wiimote_data *wdata, int leds) | 153 | void wiiproto_req_leds(struct wiimote_data *wdata, int leds) |
155 | { | 154 | { |
156 | __u8 cmd[2]; | 155 | __u8 cmd[2]; |
157 | 156 | ||
@@ -529,54 +528,6 @@ unlock: | |||
529 | return ret; | 528 | return ret; |
530 | } | 529 | } |
531 | 530 | ||
532 | static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev) | ||
533 | { | ||
534 | struct wiimote_data *wdata; | ||
535 | struct device *dev = led_dev->dev->parent; | ||
536 | int i; | ||
537 | unsigned long flags; | ||
538 | bool value = false; | ||
539 | |||
540 | wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); | ||
541 | |||
542 | for (i = 0; i < 4; ++i) { | ||
543 | if (wdata->leds[i] == led_dev) { | ||
544 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
545 | value = wdata->state.flags & WIIPROTO_FLAG_LED(i + 1); | ||
546 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
547 | break; | ||
548 | } | ||
549 | } | ||
550 | |||
551 | return value ? LED_FULL : LED_OFF; | ||
552 | } | ||
553 | |||
554 | static void wiimote_leds_set(struct led_classdev *led_dev, | ||
555 | enum led_brightness value) | ||
556 | { | ||
557 | struct wiimote_data *wdata; | ||
558 | struct device *dev = led_dev->dev->parent; | ||
559 | int i; | ||
560 | unsigned long flags; | ||
561 | __u8 state, flag; | ||
562 | |||
563 | wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); | ||
564 | |||
565 | for (i = 0; i < 4; ++i) { | ||
566 | if (wdata->leds[i] == led_dev) { | ||
567 | flag = WIIPROTO_FLAG_LED(i + 1); | ||
568 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
569 | state = wdata->state.flags; | ||
570 | if (value == LED_OFF) | ||
571 | wiiproto_req_leds(wdata, state & ~flag); | ||
572 | else | ||
573 | wiiproto_req_leds(wdata, state | flag); | ||
574 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
575 | break; | ||
576 | } | ||
577 | } | ||
578 | } | ||
579 | |||
580 | static int wiimote_accel_open(struct input_dev *dev) | 531 | static int wiimote_accel_open(struct input_dev *dev) |
581 | { | 532 | { |
582 | struct wiimote_data *wdata = input_get_drvdata(dev); | 533 | struct wiimote_data *wdata = input_get_drvdata(dev); |
@@ -626,18 +577,30 @@ static const __u8 * const wiimote_devtype_mods[WIIMOTE_DEV_NUM] = { | |||
626 | WIIMOD_KEYS, | 577 | WIIMOD_KEYS, |
627 | WIIMOD_RUMBLE, | 578 | WIIMOD_RUMBLE, |
628 | WIIMOD_BATTERY, | 579 | WIIMOD_BATTERY, |
580 | WIIMOD_LED1, | ||
581 | WIIMOD_LED2, | ||
582 | WIIMOD_LED3, | ||
583 | WIIMOD_LED4, | ||
629 | WIIMOD_NULL, | 584 | WIIMOD_NULL, |
630 | }, | 585 | }, |
631 | [WIIMOTE_DEV_GEN10] = (const __u8[]){ | 586 | [WIIMOTE_DEV_GEN10] = (const __u8[]){ |
632 | WIIMOD_KEYS, | 587 | WIIMOD_KEYS, |
633 | WIIMOD_RUMBLE, | 588 | WIIMOD_RUMBLE, |
634 | WIIMOD_BATTERY, | 589 | WIIMOD_BATTERY, |
590 | WIIMOD_LED1, | ||
591 | WIIMOD_LED2, | ||
592 | WIIMOD_LED3, | ||
593 | WIIMOD_LED4, | ||
635 | WIIMOD_NULL, | 594 | WIIMOD_NULL, |
636 | }, | 595 | }, |
637 | [WIIMOTE_DEV_GEN20] = (const __u8[]){ | 596 | [WIIMOTE_DEV_GEN20] = (const __u8[]){ |
638 | WIIMOD_KEYS, | 597 | WIIMOD_KEYS, |
639 | WIIMOD_RUMBLE, | 598 | WIIMOD_RUMBLE, |
640 | WIIMOD_BATTERY, | 599 | WIIMOD_BATTERY, |
600 | WIIMOD_LED1, | ||
601 | WIIMOD_LED2, | ||
602 | WIIMOD_LED3, | ||
603 | WIIMOD_LED4, | ||
641 | WIIMOD_NULL, | 604 | WIIMOD_NULL, |
642 | }, | 605 | }, |
643 | }; | 606 | }; |
@@ -1159,58 +1122,6 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, | |||
1159 | return 0; | 1122 | return 0; |
1160 | } | 1123 | } |
1161 | 1124 | ||
1162 | static void wiimote_leds_destroy(struct wiimote_data *wdata) | ||
1163 | { | ||
1164 | int i; | ||
1165 | struct led_classdev *led; | ||
1166 | |||
1167 | for (i = 0; i < 4; ++i) { | ||
1168 | if (wdata->leds[i]) { | ||
1169 | led = wdata->leds[i]; | ||
1170 | wdata->leds[i] = NULL; | ||
1171 | led_classdev_unregister(led); | ||
1172 | kfree(led); | ||
1173 | } | ||
1174 | } | ||
1175 | } | ||
1176 | |||
1177 | static int wiimote_leds_create(struct wiimote_data *wdata) | ||
1178 | { | ||
1179 | int i, ret; | ||
1180 | struct device *dev = &wdata->hdev->dev; | ||
1181 | size_t namesz = strlen(dev_name(dev)) + 9; | ||
1182 | struct led_classdev *led; | ||
1183 | char *name; | ||
1184 | |||
1185 | for (i = 0; i < 4; ++i) { | ||
1186 | led = kzalloc(sizeof(struct led_classdev) + namesz, GFP_KERNEL); | ||
1187 | if (!led) { | ||
1188 | ret = -ENOMEM; | ||
1189 | goto err; | ||
1190 | } | ||
1191 | name = (void*)&led[1]; | ||
1192 | snprintf(name, namesz, "%s:blue:p%d", dev_name(dev), i); | ||
1193 | led->name = name; | ||
1194 | led->brightness = 0; | ||
1195 | led->max_brightness = 1; | ||
1196 | led->brightness_get = wiimote_leds_get; | ||
1197 | led->brightness_set = wiimote_leds_set; | ||
1198 | |||
1199 | ret = led_classdev_register(dev, led); | ||
1200 | if (ret) { | ||
1201 | kfree(led); | ||
1202 | goto err; | ||
1203 | } | ||
1204 | wdata->leds[i] = led; | ||
1205 | } | ||
1206 | |||
1207 | return 0; | ||
1208 | |||
1209 | err: | ||
1210 | wiimote_leds_destroy(wdata); | ||
1211 | return ret; | ||
1212 | } | ||
1213 | |||
1214 | static struct wiimote_data *wiimote_create(struct hid_device *hdev) | 1125 | static struct wiimote_data *wiimote_create(struct hid_device *hdev) |
1215 | { | 1126 | { |
1216 | struct wiimote_data *wdata; | 1127 | struct wiimote_data *wdata; |
@@ -1300,7 +1211,6 @@ static void wiimote_destroy(struct wiimote_data *wdata) | |||
1300 | { | 1211 | { |
1301 | wiidebug_deinit(wdata); | 1212 | wiidebug_deinit(wdata); |
1302 | wiiext_deinit(wdata); | 1213 | wiiext_deinit(wdata); |
1303 | wiimote_leds_destroy(wdata); | ||
1304 | 1214 | ||
1305 | cancel_work_sync(&wdata->init_worker); | 1215 | cancel_work_sync(&wdata->init_worker); |
1306 | wiimote_modules_unload(wdata); | 1216 | wiimote_modules_unload(wdata); |
@@ -1357,10 +1267,6 @@ static int wiimote_hid_probe(struct hid_device *hdev, | |||
1357 | goto err_ir; | 1267 | goto err_ir; |
1358 | } | 1268 | } |
1359 | 1269 | ||
1360 | ret = wiimote_leds_create(wdata); | ||
1361 | if (ret) | ||
1362 | goto err_free; | ||
1363 | |||
1364 | ret = wiiext_init(wdata); | 1270 | ret = wiiext_init(wdata); |
1365 | if (ret) | 1271 | if (ret) |
1366 | goto err_free; | 1272 | goto err_free; |
@@ -1371,11 +1277,6 @@ static int wiimote_hid_probe(struct hid_device *hdev, | |||
1371 | 1277 | ||
1372 | hid_info(hdev, "New device registered\n"); | 1278 | hid_info(hdev, "New device registered\n"); |
1373 | 1279 | ||
1374 | /* by default set led1 after device initialization */ | ||
1375 | spin_lock_irq(&wdata->state.lock); | ||
1376 | wiiproto_req_leds(wdata, WIIPROTO_FLAG_LED1); | ||
1377 | spin_unlock_irq(&wdata->state.lock); | ||
1378 | |||
1379 | /* schedule device detection */ | 1280 | /* schedule device detection */ |
1380 | schedule_work(&wdata->init_worker); | 1281 | schedule_work(&wdata->init_worker); |
1381 | 1282 | ||
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c index 4cbbbe651ba5..f96de153971c 100644 --- a/drivers/hid/hid-wiimote-modules.c +++ b/drivers/hid/hid-wiimote-modules.c | |||
@@ -268,10 +268,150 @@ static const struct wiimod_ops wiimod_battery = { | |||
268 | .remove = wiimod_battery_remove, | 268 | .remove = wiimod_battery_remove, |
269 | }; | 269 | }; |
270 | 270 | ||
271 | /* | ||
272 | * LED | ||
273 | * 0 to 4 player LEDs are supported by devices. The "arg" field of the | ||
274 | * wiimod_ops structure specifies which LED this module controls. This allows | ||
275 | * to register a limited number of LEDs. | ||
276 | * State is managed by wiimote core. | ||
277 | */ | ||
278 | |||
279 | static enum led_brightness wiimod_led_get(struct led_classdev *led_dev) | ||
280 | { | ||
281 | struct wiimote_data *wdata; | ||
282 | struct device *dev = led_dev->dev->parent; | ||
283 | int i; | ||
284 | unsigned long flags; | ||
285 | bool value = false; | ||
286 | |||
287 | wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); | ||
288 | |||
289 | for (i = 0; i < 4; ++i) { | ||
290 | if (wdata->leds[i] == led_dev) { | ||
291 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
292 | value = wdata->state.flags & WIIPROTO_FLAG_LED(i + 1); | ||
293 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
294 | break; | ||
295 | } | ||
296 | } | ||
297 | |||
298 | return value ? LED_FULL : LED_OFF; | ||
299 | } | ||
300 | |||
301 | static void wiimod_led_set(struct led_classdev *led_dev, | ||
302 | enum led_brightness value) | ||
303 | { | ||
304 | struct wiimote_data *wdata; | ||
305 | struct device *dev = led_dev->dev->parent; | ||
306 | int i; | ||
307 | unsigned long flags; | ||
308 | __u8 state, flag; | ||
309 | |||
310 | wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); | ||
311 | |||
312 | for (i = 0; i < 4; ++i) { | ||
313 | if (wdata->leds[i] == led_dev) { | ||
314 | flag = WIIPROTO_FLAG_LED(i + 1); | ||
315 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
316 | state = wdata->state.flags; | ||
317 | if (value == LED_OFF) | ||
318 | wiiproto_req_leds(wdata, state & ~flag); | ||
319 | else | ||
320 | wiiproto_req_leds(wdata, state | flag); | ||
321 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
322 | break; | ||
323 | } | ||
324 | } | ||
325 | } | ||
326 | |||
327 | static int wiimod_led_probe(const struct wiimod_ops *ops, | ||
328 | struct wiimote_data *wdata) | ||
329 | { | ||
330 | struct device *dev = &wdata->hdev->dev; | ||
331 | size_t namesz = strlen(dev_name(dev)) + 9; | ||
332 | struct led_classdev *led; | ||
333 | unsigned long flags; | ||
334 | char *name; | ||
335 | int ret; | ||
336 | |||
337 | led = kzalloc(sizeof(struct led_classdev) + namesz, GFP_KERNEL); | ||
338 | if (!led) | ||
339 | return -ENOMEM; | ||
340 | |||
341 | name = (void*)&led[1]; | ||
342 | snprintf(name, namesz, "%s:blue:p%lu", dev_name(dev), ops->arg); | ||
343 | led->name = name; | ||
344 | led->brightness = 0; | ||
345 | led->max_brightness = 1; | ||
346 | led->brightness_get = wiimod_led_get; | ||
347 | led->brightness_set = wiimod_led_set; | ||
348 | |||
349 | wdata->leds[ops->arg] = led; | ||
350 | ret = led_classdev_register(dev, led); | ||
351 | if (ret) | ||
352 | goto err_free; | ||
353 | |||
354 | /* enable LED1 to stop initial LED-blinking */ | ||
355 | if (ops->arg == 0) { | ||
356 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
357 | wiiproto_req_leds(wdata, WIIPROTO_FLAG_LED1); | ||
358 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
359 | } | ||
360 | |||
361 | return 0; | ||
362 | |||
363 | err_free: | ||
364 | wdata->leds[ops->arg] = NULL; | ||
365 | kfree(led); | ||
366 | return ret; | ||
367 | } | ||
368 | |||
369 | static void wiimod_led_remove(const struct wiimod_ops *ops, | ||
370 | struct wiimote_data *wdata) | ||
371 | { | ||
372 | if (!wdata->leds[ops->arg]) | ||
373 | return; | ||
374 | |||
375 | led_classdev_unregister(wdata->leds[ops->arg]); | ||
376 | kfree(wdata->leds[ops->arg]); | ||
377 | wdata->leds[ops->arg] = NULL; | ||
378 | } | ||
379 | |||
380 | static const struct wiimod_ops wiimod_leds[4] = { | ||
381 | { | ||
382 | .flags = 0, | ||
383 | .arg = 0, | ||
384 | .probe = wiimod_led_probe, | ||
385 | .remove = wiimod_led_remove, | ||
386 | }, | ||
387 | { | ||
388 | .flags = 0, | ||
389 | .arg = 1, | ||
390 | .probe = wiimod_led_probe, | ||
391 | .remove = wiimod_led_remove, | ||
392 | }, | ||
393 | { | ||
394 | .flags = 0, | ||
395 | .arg = 2, | ||
396 | .probe = wiimod_led_probe, | ||
397 | .remove = wiimod_led_remove, | ||
398 | }, | ||
399 | { | ||
400 | .flags = 0, | ||
401 | .arg = 3, | ||
402 | .probe = wiimod_led_probe, | ||
403 | .remove = wiimod_led_remove, | ||
404 | }, | ||
405 | }; | ||
406 | |||
271 | /* module table */ | 407 | /* module table */ |
272 | 408 | ||
273 | const struct wiimod_ops *wiimod_table[WIIMOD_NUM] = { | 409 | const struct wiimod_ops *wiimod_table[WIIMOD_NUM] = { |
274 | [WIIMOD_KEYS] = &wiimod_keys, | 410 | [WIIMOD_KEYS] = &wiimod_keys, |
275 | [WIIMOD_RUMBLE] = &wiimod_rumble, | 411 | [WIIMOD_RUMBLE] = &wiimod_rumble, |
276 | [WIIMOD_BATTERY] = &wiimod_battery, | 412 | [WIIMOD_BATTERY] = &wiimod_battery, |
413 | [WIIMOD_LED1] = &wiimod_leds[0], | ||
414 | [WIIMOD_LED2] = &wiimod_leds[1], | ||
415 | [WIIMOD_LED3] = &wiimod_leds[2], | ||
416 | [WIIMOD_LED4] = &wiimod_leds[3], | ||
277 | }; | 417 | }; |
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h index 4151514fcd2e..66150a693324 100644 --- a/drivers/hid/hid-wiimote.h +++ b/drivers/hid/hid-wiimote.h | |||
@@ -129,6 +129,10 @@ enum wiimod_module { | |||
129 | WIIMOD_KEYS, | 129 | WIIMOD_KEYS, |
130 | WIIMOD_RUMBLE, | 130 | WIIMOD_RUMBLE, |
131 | WIIMOD_BATTERY, | 131 | WIIMOD_BATTERY, |
132 | WIIMOD_LED1, | ||
133 | WIIMOD_LED2, | ||
134 | WIIMOD_LED3, | ||
135 | WIIMOD_LED4, | ||
132 | WIIMOD_NUM, | 136 | WIIMOD_NUM, |
133 | WIIMOD_NULL = WIIMOD_NUM, | 137 | WIIMOD_NULL = WIIMOD_NUM, |
134 | }; | 138 | }; |
@@ -185,6 +189,7 @@ enum wiiproto_reqs { | |||
185 | 189 | ||
186 | extern void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm); | 190 | extern void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm); |
187 | extern void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble); | 191 | extern void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble); |
192 | extern void wiiproto_req_leds(struct wiimote_data *wdata, int leds); | ||
188 | extern void wiiproto_req_status(struct wiimote_data *wdata); | 193 | extern void wiiproto_req_status(struct wiimote_data *wdata); |
189 | extern int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, | 194 | extern int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, |
190 | const __u8 *wmem, __u8 size); | 195 | const __u8 *wmem, __u8 size); |