diff options
author | David Herrmann <dh.herrmann@googlemail.com> | 2011-11-17 08:12:03 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2011-11-22 17:08:55 -0500 |
commit | 492ba955c1f7b8fdc3d87b6e4765c7a5db5f7657 (patch) | |
tree | 6b05bf3d6958eef58c59ab9e4f61ae624b34c3ec /drivers/hid/hid-wiimote-ext.c | |
parent | 82fb1b39581e7cdd71a6ce3cf12996711a583df2 (diff) |
HID: wiimote: Add extension initializers
The wiimote extension registers are not fully understood, so we always disable
all extensions on extension-port events. Then we reinitialize and reidentify
them and activate all requested extensions.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-wiimote-ext.c')
-rw-r--r-- | drivers/hid/hid-wiimote-ext.c | 81 |
1 files changed, 79 insertions, 2 deletions
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c index 3e3e1fc8d838..233bdfe3205b 100644 --- a/drivers/hid/hid-wiimote-ext.c +++ b/drivers/hid/hid-wiimote-ext.c | |||
@@ -37,30 +37,107 @@ enum wiiext_type { | |||
37 | static void ext_disable(struct wiimote_ext *ext) | 37 | static void ext_disable(struct wiimote_ext *ext) |
38 | { | 38 | { |
39 | unsigned long flags; | 39 | unsigned long flags; |
40 | __u8 wmem = 0x55; | ||
41 | |||
42 | if (!wiimote_cmd_acquire(ext->wdata)) { | ||
43 | wiimote_cmd_write(ext->wdata, 0xa400f0, &wmem, sizeof(wmem)); | ||
44 | wiimote_cmd_release(ext->wdata); | ||
45 | } | ||
40 | 46 | ||
41 | spin_lock_irqsave(&ext->wdata->state.lock, flags); | 47 | spin_lock_irqsave(&ext->wdata->state.lock, flags); |
42 | ext->motionp = false; | 48 | ext->motionp = false; |
43 | ext->ext_type = WIIEXT_NONE; | 49 | ext->ext_type = WIIEXT_NONE; |
50 | wiiproto_req_drm(ext->wdata, WIIPROTO_REQ_NULL); | ||
44 | spin_unlock_irqrestore(&ext->wdata->state.lock, flags); | 51 | spin_unlock_irqrestore(&ext->wdata->state.lock, flags); |
45 | } | 52 | } |
46 | 53 | ||
47 | static bool motionp_read(struct wiimote_ext *ext) | 54 | static bool motionp_read(struct wiimote_ext *ext) |
48 | { | 55 | { |
49 | return false; | 56 | __u8 rmem[2], wmem; |
57 | ssize_t ret; | ||
58 | bool avail = false; | ||
59 | |||
60 | if (wiimote_cmd_acquire(ext->wdata)) | ||
61 | return false; | ||
62 | |||
63 | /* initialize motion plus */ | ||
64 | wmem = 0x55; | ||
65 | ret = wiimote_cmd_write(ext->wdata, 0xa600f0, &wmem, sizeof(wmem)); | ||
66 | if (ret) | ||
67 | goto error; | ||
68 | |||
69 | /* read motion plus ID */ | ||
70 | ret = wiimote_cmd_read(ext->wdata, 0xa600fe, rmem, 2); | ||
71 | if (ret == 2 || rmem[1] == 0x5) | ||
72 | avail = true; | ||
73 | |||
74 | error: | ||
75 | wiimote_cmd_release(ext->wdata); | ||
76 | return avail; | ||
50 | } | 77 | } |
51 | 78 | ||
52 | static __u8 ext_read(struct wiimote_ext *ext) | 79 | static __u8 ext_read(struct wiimote_ext *ext) |
53 | { | 80 | { |
54 | return WIIEXT_NONE; | 81 | ssize_t ret; |
82 | __u8 rmem[2], wmem; | ||
83 | __u8 type = WIIEXT_NONE; | ||
84 | |||
85 | if (!ext->plugged) | ||
86 | return WIIEXT_NONE; | ||
87 | |||
88 | if (wiimote_cmd_acquire(ext->wdata)) | ||
89 | return WIIEXT_NONE; | ||
90 | |||
91 | /* initialize extension */ | ||
92 | wmem = 0x55; | ||
93 | ret = wiimote_cmd_write(ext->wdata, 0xa400f0, &wmem, sizeof(wmem)); | ||
94 | if (!ret) { | ||
95 | /* disable encryption */ | ||
96 | wmem = 0x0; | ||
97 | wiimote_cmd_write(ext->wdata, 0xa400fb, &wmem, sizeof(wmem)); | ||
98 | } | ||
99 | |||
100 | /* read extension ID */ | ||
101 | ret = wiimote_cmd_read(ext->wdata, 0xa400fe, rmem, 2); | ||
102 | if (ret == 2) { | ||
103 | if (rmem[0] == 0 && rmem[1] == 0) | ||
104 | type = WIIEXT_NUNCHUCK; | ||
105 | else if (rmem[0] == 0x01 && rmem[1] == 0x01) | ||
106 | type = WIIEXT_CLASSIC; | ||
107 | } | ||
108 | |||
109 | wiimote_cmd_release(ext->wdata); | ||
110 | |||
111 | return type; | ||
55 | } | 112 | } |
56 | 113 | ||
57 | static void ext_enable(struct wiimote_ext *ext, bool motionp, __u8 ext_type) | 114 | static void ext_enable(struct wiimote_ext *ext, bool motionp, __u8 ext_type) |
58 | { | 115 | { |
59 | unsigned long flags; | 116 | unsigned long flags; |
117 | __u8 wmem; | ||
118 | int ret; | ||
119 | |||
120 | if (motionp) { | ||
121 | if (wiimote_cmd_acquire(ext->wdata)) | ||
122 | return; | ||
123 | |||
124 | if (ext_type == WIIEXT_CLASSIC) | ||
125 | wmem = 0x07; | ||
126 | else if (ext_type == WIIEXT_NUNCHUCK) | ||
127 | wmem = 0x05; | ||
128 | else | ||
129 | wmem = 0x04; | ||
130 | |||
131 | ret = wiimote_cmd_write(ext->wdata, 0xa600fe, &wmem, sizeof(wmem)); | ||
132 | wiimote_cmd_release(ext->wdata); | ||
133 | if (ret) | ||
134 | return; | ||
135 | } | ||
60 | 136 | ||
61 | spin_lock_irqsave(&ext->wdata->state.lock, flags); | 137 | spin_lock_irqsave(&ext->wdata->state.lock, flags); |
62 | ext->motionp = motionp; | 138 | ext->motionp = motionp; |
63 | ext->ext_type = ext_type; | 139 | ext->ext_type = ext_type; |
140 | wiiproto_req_drm(ext->wdata, WIIPROTO_REQ_NULL); | ||
64 | spin_unlock_irqrestore(&ext->wdata->state.lock, flags); | 141 | spin_unlock_irqrestore(&ext->wdata->state.lock, flags); |
65 | } | 142 | } |
66 | 143 | ||