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 /drivers/hid/hid-wiimote.c | |
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>
Diffstat (limited to 'drivers/hid/hid-wiimote.c')
-rw-r--r-- | drivers/hid/hid-wiimote.c | 60 |
1 files changed, 60 insertions, 0 deletions
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; |