diff options
| author | David Herrmann <dh.herrmann@googlemail.com> | 2011-09-06 07:50:39 -0400 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2011-09-07 07:25:18 -0400 |
| commit | 6591d758d54291fcc5fd560653edef73d50bd978 (patch) | |
| tree | 1b5df45a7d4b175e2a5706c08aee1efed2e78db3 | |
| parent | e3979a9189d744ffecae1bcd36ae0a8b6d22f65f (diff) | |
HID: wiimote: Read wiimote battery charge level
This registers a power_supply device for every remote to retrieve the current
battery charge level. Since this information is not sent by the wiimote
continously, we need to explicitely request it.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
| -rw-r--r-- | drivers/hid/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/hid/hid-wiimote.c | 60 |
2 files changed, 61 insertions, 0 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 1130a8987125..9907dc9cfb12 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
| @@ -590,6 +590,7 @@ config HID_WIIMOTE | |||
| 590 | tristate "Nintendo Wii Remote support" | 590 | tristate "Nintendo Wii Remote support" |
| 591 | depends on BT_HIDP | 591 | depends on BT_HIDP |
| 592 | depends on LEDS_CLASS | 592 | depends on LEDS_CLASS |
| 593 | select POWER_SUPPLY | ||
| 593 | ---help--- | 594 | ---help--- |
| 594 | Support for the Nintendo Wii Remote bluetooth device. | 595 | Support for the Nintendo Wii Remote bluetooth device. |
| 595 | 596 | ||
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index 48198cb0fed2..c83cafaa46a3 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/leds.h> | 17 | #include <linux/leds.h> |
| 18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 19 | #include <linux/mutex.h> | 19 | #include <linux/mutex.h> |
| 20 | #include <linux/power_supply.h> | ||
| 20 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
| 21 | #include "hid-ids.h" | 22 | #include "hid-ids.h" |
| 22 | 23 | ||
| @@ -51,6 +52,7 @@ struct wiimote_data { | |||
| 51 | struct led_classdev *leds[4]; | 52 | struct led_classdev *leds[4]; |
| 52 | struct input_dev *accel; | 53 | struct input_dev *accel; |
| 53 | struct input_dev *ir; | 54 | struct input_dev *ir; |
| 55 | struct power_supply battery; | ||
| 54 | 56 | ||
| 55 | spinlock_t qlock; | 57 | spinlock_t qlock; |
| 56 | __u8 head; | 58 | __u8 head; |
| @@ -133,6 +135,10 @@ static __u16 wiiproto_keymap[] = { | |||
| 133 | BTN_MODE, /* WIIPROTO_KEY_HOME */ | 135 | BTN_MODE, /* WIIPROTO_KEY_HOME */ |
| 134 | }; | 136 | }; |
| 135 | 137 | ||
| 138 | static enum power_supply_property wiimote_battery_props[] = { | ||
| 139 | POWER_SUPPLY_PROP_CAPACITY | ||
| 140 | }; | ||
| 141 | |||
| 136 | /* requires the state.lock spinlock to be held */ | 142 | /* requires the state.lock spinlock to be held */ |
| 137 | static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd, | 143 | static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd, |
| 138 | __u32 opt) | 144 | __u32 opt) |
| @@ -453,6 +459,43 @@ static int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, | |||
| 453 | return ret; | 459 | return ret; |
| 454 | } | 460 | } |
| 455 | 461 | ||
| 462 | static int wiimote_battery_get_property(struct power_supply *psy, | ||
| 463 | enum power_supply_property psp, | ||
| 464 | union power_supply_propval *val) | ||
| 465 | { | ||
| 466 | struct wiimote_data *wdata = container_of(psy, | ||
| 467 | struct wiimote_data, battery); | ||
| 468 | int ret = 0, state; | ||
| 469 | unsigned long flags; | ||
| 470 | |||
| 471 | ret = wiimote_cmd_acquire(wdata); | ||
| 472 | if (ret) | ||
| 473 | return ret; | ||
| 474 | |||
| 475 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
| 476 | wiimote_cmd_set(wdata, WIIPROTO_REQ_SREQ, 0); | ||
| 477 | wiiproto_req_status(wdata); | ||
| 478 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 479 | |||
| 480 | ret = wiimote_cmd_wait(wdata); | ||
| 481 | state = wdata->state.cmd_battery; | ||
| 482 | wiimote_cmd_release(wdata); | ||
| 483 | |||
| 484 | if (ret) | ||
| 485 | return ret; | ||
| 486 | |||
| 487 | switch (psp) { | ||
| 488 | case POWER_SUPPLY_PROP_CAPACITY: | ||
| 489 | val->intval = state * 100 / 255; | ||
| 490 | break; | ||
| 491 | default: | ||
| 492 | ret = -EINVAL; | ||
| 493 | break; | ||
| 494 | } | ||
| 495 | |||
| 496 | return ret; | ||
| 497 | } | ||
| 498 | |||
| 456 | static int wiimote_init_ir(struct wiimote_data *wdata, __u16 mode) | 499 | static int wiimote_init_ir(struct wiimote_data *wdata, __u16 mode) |
| 457 | { | 500 | { |
| 458 | int ret; | 501 | int ret; |
| @@ -1155,6 +1198,7 @@ static void wiimote_destroy(struct wiimote_data *wdata) | |||
| 1155 | { | 1198 | { |
| 1156 | wiimote_leds_destroy(wdata); | 1199 | wiimote_leds_destroy(wdata); |
| 1157 | 1200 | ||
| 1201 | power_supply_unregister(&wdata->battery); | ||
| 1158 | input_unregister_device(wdata->accel); | 1202 | input_unregister_device(wdata->accel); |
| 1159 | input_unregister_device(wdata->ir); | 1203 | input_unregister_device(wdata->ir); |
| 1160 | input_unregister_device(wdata->input); | 1204 | input_unregister_device(wdata->input); |
| @@ -1206,6 +1250,19 @@ static int wiimote_hid_probe(struct hid_device *hdev, | |||
| 1206 | goto err_input; | 1250 | goto err_input; |
| 1207 | } | 1251 | } |
| 1208 | 1252 | ||
| 1253 | wdata->battery.properties = wiimote_battery_props; | ||
| 1254 | wdata->battery.num_properties = ARRAY_SIZE(wiimote_battery_props); | ||
| 1255 | wdata->battery.get_property = wiimote_battery_get_property; | ||
| 1256 | wdata->battery.name = "wiimote_battery"; | ||
| 1257 | wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY; | ||
| 1258 | wdata->battery.use_for_apm = 0; | ||
| 1259 | |||
| 1260 | ret = power_supply_register(&wdata->hdev->dev, &wdata->battery); | ||
| 1261 | if (ret) { | ||
| 1262 | hid_err(hdev, "Cannot register battery device\n"); | ||
| 1263 | goto err_battery; | ||
| 1264 | } | ||
| 1265 | |||
| 1209 | ret = wiimote_leds_create(wdata); | 1266 | ret = wiimote_leds_create(wdata); |
| 1210 | if (ret) | 1267 | if (ret) |
| 1211 | goto err_free; | 1268 | goto err_free; |
| @@ -1223,6 +1280,9 @@ err_free: | |||
| 1223 | wiimote_destroy(wdata); | 1280 | wiimote_destroy(wdata); |
| 1224 | return ret; | 1281 | return ret; |
| 1225 | 1282 | ||
| 1283 | err_battery: | ||
| 1284 | input_unregister_device(wdata->input); | ||
| 1285 | wdata->input = NULL; | ||
| 1226 | err_input: | 1286 | err_input: |
| 1227 | input_unregister_device(wdata->ir); | 1287 | input_unregister_device(wdata->ir); |
| 1228 | wdata->ir = NULL; | 1288 | wdata->ir = NULL; |
