aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-wiimote-ext.c
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@googlemail.com>2011-11-17 08:12:03 -0500
committerJiri Kosina <jkosina@suse.cz>2011-11-22 17:08:55 -0500
commit492ba955c1f7b8fdc3d87b6e4765c7a5db5f7657 (patch)
tree6b05bf3d6958eef58c59ab9e4f61ae624b34c3ec /drivers/hid/hid-wiimote-ext.c
parent82fb1b39581e7cdd71a6ce3cf12996711a583df2 (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.c81
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 {
37static void ext_disable(struct wiimote_ext *ext) 37static 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
47static bool motionp_read(struct wiimote_ext *ext) 54static 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
74error:
75 wiimote_cmd_release(ext->wdata);
76 return avail;
50} 77}
51 78
52static __u8 ext_read(struct wiimote_ext *ext) 79static __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
57static void ext_enable(struct wiimote_ext *ext, bool motionp, __u8 ext_type) 114static 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