diff options
author | David Herrmann <dh.herrmann@googlemail.com> | 2011-11-17 08:12:00 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2011-11-22 17:08:09 -0500 |
commit | fad8c0e34323eb7789f93750258a2cf02dc6cf69 (patch) | |
tree | bb2b0f3b89fa751702dec42681cdb1bf206d0259 | |
parent | 7e274400629fbf8eab294fef39c3efde463966a9 (diff) |
HID: wiimote: Add read-mem helpers
Add helper functions similar to the write-mem helpers but for reading wiimote
memory and eeprom.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | drivers/hid/hid-wiimote-core.c | 77 | ||||
-rw-r--r-- | drivers/hid/hid-wiimote.h | 4 |
2 files changed, 81 insertions, 0 deletions
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c index c955d500c81f..f7f8b7ff7dec 100644 --- a/drivers/hid/hid-wiimote-core.c +++ b/drivers/hid/hid-wiimote-core.c | |||
@@ -312,6 +312,37 @@ static void wiiproto_req_wmem(struct wiimote_data *wdata, bool eeprom, | |||
312 | wiimote_queue(wdata, cmd, sizeof(cmd)); | 312 | wiimote_queue(wdata, cmd, sizeof(cmd)); |
313 | } | 313 | } |
314 | 314 | ||
315 | #define wiiproto_req_rreg(wdata, os, sz) \ | ||
316 | wiiproto_req_rmem((wdata), false, (os), (sz)) | ||
317 | |||
318 | #define wiiproto_req_reeprom(wdata, os, sz) \ | ||
319 | wiiproto_req_rmem((wdata), true, (os), (sz)) | ||
320 | |||
321 | static void wiiproto_req_rmem(struct wiimote_data *wdata, bool eeprom, | ||
322 | __u32 offset, __u16 size) | ||
323 | { | ||
324 | __u8 cmd[7]; | ||
325 | |||
326 | if (size == 0) { | ||
327 | hid_warn(wdata->hdev, "Invalid length %d rmem request\n", size); | ||
328 | return; | ||
329 | } | ||
330 | |||
331 | cmd[0] = WIIPROTO_REQ_RMEM; | ||
332 | cmd[1] = 0; | ||
333 | cmd[2] = (offset >> 16) & 0xff; | ||
334 | cmd[3] = (offset >> 8) & 0xff; | ||
335 | cmd[4] = offset & 0xff; | ||
336 | cmd[5] = (size >> 8) & 0xff; | ||
337 | cmd[6] = size & 0xff; | ||
338 | |||
339 | if (!eeprom) | ||
340 | cmd[1] |= 0x04; | ||
341 | |||
342 | wiiproto_keep_rumble(wdata, &cmd[1]); | ||
343 | wiimote_queue(wdata, cmd, sizeof(cmd)); | ||
344 | } | ||
345 | |||
315 | /* requries the cmd-mutex to be held */ | 346 | /* requries the cmd-mutex to be held */ |
316 | int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, | 347 | int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, |
317 | const __u8 *wmem, __u8 size) | 348 | const __u8 *wmem, __u8 size) |
@@ -331,6 +362,36 @@ int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, | |||
331 | return ret; | 362 | return ret; |
332 | } | 363 | } |
333 | 364 | ||
365 | /* requries the cmd-mutex to be held */ | ||
366 | ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, __u8 *rmem, | ||
367 | __u8 size) | ||
368 | { | ||
369 | unsigned long flags; | ||
370 | ssize_t ret; | ||
371 | |||
372 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
373 | wdata->state.cmd_read_size = size; | ||
374 | wdata->state.cmd_read_buf = rmem; | ||
375 | wiimote_cmd_set(wdata, WIIPROTO_REQ_RMEM, offset & 0xffff); | ||
376 | wiiproto_req_rreg(wdata, offset, size); | ||
377 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
378 | |||
379 | ret = wiimote_cmd_wait(wdata); | ||
380 | |||
381 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
382 | wdata->state.cmd_read_buf = NULL; | ||
383 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
384 | |||
385 | if (!ret) { | ||
386 | if (wdata->state.cmd_read_size == 0) | ||
387 | ret = -EIO; | ||
388 | else | ||
389 | ret = wdata->state.cmd_read_size; | ||
390 | } | ||
391 | |||
392 | return ret; | ||
393 | } | ||
394 | |||
334 | static int wiimote_battery_get_property(struct power_supply *psy, | 395 | static int wiimote_battery_get_property(struct power_supply *psy, |
335 | enum power_supply_property psp, | 396 | enum power_supply_property psp, |
336 | union power_supply_propval *val) | 397 | union power_supply_propval *val) |
@@ -742,7 +803,23 @@ static void handler_status(struct wiimote_data *wdata, const __u8 *payload) | |||
742 | 803 | ||
743 | static void handler_data(struct wiimote_data *wdata, const __u8 *payload) | 804 | static void handler_data(struct wiimote_data *wdata, const __u8 *payload) |
744 | { | 805 | { |
806 | __u16 offset = payload[3] << 8 | payload[4]; | ||
807 | __u8 size = (payload[2] >> 4) + 1; | ||
808 | __u8 err = payload[2] & 0x0f; | ||
809 | |||
745 | handler_keys(wdata, payload); | 810 | handler_keys(wdata, payload); |
811 | |||
812 | if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_RMEM, offset)) { | ||
813 | if (err) | ||
814 | size = 0; | ||
815 | else if (size > wdata->state.cmd_read_size) | ||
816 | size = wdata->state.cmd_read_size; | ||
817 | |||
818 | wdata->state.cmd_read_size = size; | ||
819 | if (wdata->state.cmd_read_buf) | ||
820 | memcpy(wdata->state.cmd_read_buf, &payload[5], size); | ||
821 | wiimote_cmd_complete(wdata); | ||
822 | } | ||
746 | } | 823 | } |
747 | 824 | ||
748 | static void handler_return(struct wiimote_data *wdata, const __u8 *payload) | 825 | static void handler_return(struct wiimote_data *wdata, const __u8 *payload) |
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h index d78f79c08901..865740d3a3fe 100644 --- a/drivers/hid/hid-wiimote.h +++ b/drivers/hid/hid-wiimote.h | |||
@@ -62,6 +62,8 @@ struct wiimote_state { | |||
62 | /* results of synchronous requests */ | 62 | /* results of synchronous requests */ |
63 | __u8 cmd_battery; | 63 | __u8 cmd_battery; |
64 | __u8 cmd_err; | 64 | __u8 cmd_err; |
65 | __u8 *cmd_read_buf; | ||
66 | __u8 cmd_read_size; | ||
65 | }; | 67 | }; |
66 | 68 | ||
67 | struct wiimote_data { | 69 | struct wiimote_data { |
@@ -113,6 +115,8 @@ enum wiiproto_reqs { | |||
113 | extern void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm); | 115 | extern void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm); |
114 | extern int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, | 116 | extern int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, |
115 | const __u8 *wmem, __u8 size); | 117 | const __u8 *wmem, __u8 size); |
118 | extern ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, | ||
119 | __u8 *rmem, __u8 size); | ||
116 | 120 | ||
117 | /* requires the state.lock spinlock to be held */ | 121 | /* requires the state.lock spinlock to be held */ |
118 | static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd, | 122 | static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd, |