aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-wiimote-modules.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/hid-wiimote-modules.c')
-rw-r--r--drivers/hid/hid-wiimote-modules.c140
1 files changed, 140 insertions, 0 deletions
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
279static 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
301static 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
327static 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
363err_free:
364 wdata->leds[ops->arg] = NULL;
365 kfree(led);
366 return ret;
367}
368
369static 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
380static 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
273const struct wiimod_ops *wiimod_table[WIIMOD_NUM] = { 409const 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};