blob: b9254015c58f7b5c04625ec27ecc3d4d4c7d24f4 [file] [log] [blame]
David Herrmanncb992212011-11-17 14:12:01 +01001/*
2 * HID driver for Nintendo Wiimote extension devices
3 * Copyright (c) 2011 David Herrmann
4 */
5
6/*
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 */
12
13#include <linux/atomic.h>
14#include <linux/module.h>
15#include <linux/spinlock.h>
16#include <linux/workqueue.h>
17#include "hid-wiimote.h"
18
19struct wiimote_ext {
20 struct wiimote_data *wdata;
21 struct work_struct worker;
David Herrmann479901b2011-11-17 14:12:05 +010022 struct input_dev *input;
23 struct input_dev *mp_input;
David Herrmanncb992212011-11-17 14:12:01 +010024
25 atomic_t opened;
26 atomic_t mp_opened;
27 bool plugged;
28 bool motionp;
29 __u8 ext_type;
30};
31
32enum wiiext_type {
33 WIIEXT_NONE, /* placeholder */
34 WIIEXT_CLASSIC, /* Nintendo classic controller */
35 WIIEXT_NUNCHUCK, /* Nintendo nunchuck controller */
36};
37
David Herrmann82fb1b32011-11-17 14:12:02 +010038/* diable all extensions */
39static void ext_disable(struct wiimote_ext *ext)
40{
41 unsigned long flags;
David Herrmann492ba952011-11-17 14:12:03 +010042 __u8 wmem = 0x55;
43
44 if (!wiimote_cmd_acquire(ext->wdata)) {
45 wiimote_cmd_write(ext->wdata, 0xa400f0, &wmem, sizeof(wmem));
46 wiimote_cmd_release(ext->wdata);
47 }
David Herrmann82fb1b32011-11-17 14:12:02 +010048
49 spin_lock_irqsave(&ext->wdata->state.lock, flags);
50 ext->motionp = false;
51 ext->ext_type = WIIEXT_NONE;
David Herrmann492ba952011-11-17 14:12:03 +010052 wiiproto_req_drm(ext->wdata, WIIPROTO_REQ_NULL);
David Herrmann82fb1b32011-11-17 14:12:02 +010053 spin_unlock_irqrestore(&ext->wdata->state.lock, flags);
54}
55
56static bool motionp_read(struct wiimote_ext *ext)
57{
David Herrmann492ba952011-11-17 14:12:03 +010058 __u8 rmem[2], wmem;
59 ssize_t ret;
60 bool avail = false;
61
David Herrmann479901b2011-11-17 14:12:05 +010062 if (!atomic_read(&ext->mp_opened))
63 return false;
64
David Herrmann492ba952011-11-17 14:12:03 +010065 if (wiimote_cmd_acquire(ext->wdata))
66 return false;
67
68 /* initialize motion plus */
69 wmem = 0x55;
70 ret = wiimote_cmd_write(ext->wdata, 0xa600f0, &wmem, sizeof(wmem));
71 if (ret)
72 goto error;
73
74 /* read motion plus ID */
75 ret = wiimote_cmd_read(ext->wdata, 0xa600fe, rmem, 2);
76 if (ret == 2 || rmem[1] == 0x5)
77 avail = true;
78
79error:
80 wiimote_cmd_release(ext->wdata);
81 return avail;
David Herrmann82fb1b32011-11-17 14:12:02 +010082}
83
84static __u8 ext_read(struct wiimote_ext *ext)
85{
David Herrmann492ba952011-11-17 14:12:03 +010086 ssize_t ret;
87 __u8 rmem[2], wmem;
88 __u8 type = WIIEXT_NONE;
89
David Herrmann479901b2011-11-17 14:12:05 +010090 if (!ext->plugged || !atomic_read(&ext->opened))
David Herrmann492ba952011-11-17 14:12:03 +010091 return WIIEXT_NONE;
92
93 if (wiimote_cmd_acquire(ext->wdata))
94 return WIIEXT_NONE;
95
96 /* initialize extension */
97 wmem = 0x55;
98 ret = wiimote_cmd_write(ext->wdata, 0xa400f0, &wmem, sizeof(wmem));
99 if (!ret) {
100 /* disable encryption */
101 wmem = 0x0;
102 wiimote_cmd_write(ext->wdata, 0xa400fb, &wmem, sizeof(wmem));
103 }
104
105 /* read extension ID */
106 ret = wiimote_cmd_read(ext->wdata, 0xa400fe, rmem, 2);
107 if (ret == 2) {
108 if (rmem[0] == 0 && rmem[1] == 0)
109 type = WIIEXT_NUNCHUCK;
110 else if (rmem[0] == 0x01 && rmem[1] == 0x01)
111 type = WIIEXT_CLASSIC;
112 }
113
114 wiimote_cmd_release(ext->wdata);
115
116 return type;
David Herrmann82fb1b32011-11-17 14:12:02 +0100117}
118
119static void ext_enable(struct wiimote_ext *ext, bool motionp, __u8 ext_type)
120{
121 unsigned long flags;
David Herrmann492ba952011-11-17 14:12:03 +0100122 __u8 wmem;
123 int ret;
124
125 if (motionp) {
126 if (wiimote_cmd_acquire(ext->wdata))
127 return;
128
129 if (ext_type == WIIEXT_CLASSIC)
130 wmem = 0x07;
131 else if (ext_type == WIIEXT_NUNCHUCK)
132 wmem = 0x05;
133 else
134 wmem = 0x04;
135
136 ret = wiimote_cmd_write(ext->wdata, 0xa600fe, &wmem, sizeof(wmem));
137 wiimote_cmd_release(ext->wdata);
138 if (ret)
139 return;
140 }
David Herrmann82fb1b32011-11-17 14:12:02 +0100141
142 spin_lock_irqsave(&ext->wdata->state.lock, flags);
143 ext->motionp = motionp;
144 ext->ext_type = ext_type;
David Herrmann492ba952011-11-17 14:12:03 +0100145 wiiproto_req_drm(ext->wdata, WIIPROTO_REQ_NULL);
David Herrmann82fb1b32011-11-17 14:12:02 +0100146 spin_unlock_irqrestore(&ext->wdata->state.lock, flags);
147}
148
David Herrmanncb992212011-11-17 14:12:01 +0100149static void wiiext_worker(struct work_struct *work)
150{
151 struct wiimote_ext *ext = container_of(work, struct wiimote_ext,
152 worker);
David Herrmann82fb1b32011-11-17 14:12:02 +0100153 bool motionp;
154 __u8 ext_type;
155
156 ext_disable(ext);
157 motionp = motionp_read(ext);
158 ext_type = ext_read(ext);
159 ext_enable(ext, motionp, ext_type);
David Herrmanncb992212011-11-17 14:12:01 +0100160}
161
162/* schedule work only once, otherwise mark for reschedule */
163static void wiiext_schedule(struct wiimote_ext *ext)
164{
165 queue_work(system_nrt_wq, &ext->worker);
166}
167
168/*
169 * Reacts on extension port events
170 * Whenever the driver gets an event from the wiimote that an extension has been
171 * plugged or unplugged, this funtion shall be called. It checks what extensions
172 * are connected and initializes and activates them.
173 * This can be called in atomic context. The initialization is done in a
174 * separate worker thread. The state.lock spinlock must be held by the caller.
175 */
176void wiiext_event(struct wiimote_data *wdata, bool plugged)
177{
178 if (!wdata->ext)
179 return;
180
181 if (wdata->ext->plugged == plugged)
182 return;
183
184 wdata->ext->plugged = plugged;
185 /*
186 * We need to call wiiext_schedule(wdata->ext) here, however, the
187 * extension initialization logic is not fully understood and so
188 * automatic initialization is not supported, yet.
189 */
190}
191
192/*
193 * Returns true if the current DRM mode should contain extension data and false
194 * if there is no interest in extension data.
195 * All supported extensions send 6 byte extension data so any DRM that contains
196 * extension bytes is fine.
197 * The caller must hold the state.lock spinlock.
198 */
199bool wiiext_active(struct wiimote_data *wdata)
200{
201 if (!wdata->ext)
202 return false;
203
204 return wdata->ext->motionp || wdata->ext->ext_type;
205}
206
David Herrmannc1e51392011-11-17 14:12:04 +0100207static ssize_t wiiext_show(struct device *dev, struct device_attribute *attr,
208 char *buf)
209{
210 struct wiimote_data *wdata = dev_to_wii(dev);
211 __u8 type = WIIEXT_NONE;
212 bool motionp = false;
213 unsigned long flags;
214
215 spin_lock_irqsave(&wdata->state.lock, flags);
216 if (wdata->ext) {
217 motionp = wdata->ext->motionp;
218 type = wdata->ext->ext_type;
219 }
220 spin_unlock_irqrestore(&wdata->state.lock, flags);
221
222 if (type == WIIEXT_NUNCHUCK) {
223 if (motionp)
224 return sprintf(buf, "motionp+nunchuck\n");
225 else
226 return sprintf(buf, "nunchuck\n");
227 } else if (type == WIIEXT_CLASSIC) {
228 if (motionp)
229 return sprintf(buf, "motionp+classic\n");
230 else
231 return sprintf(buf, "classic\n");
232 } else {
233 if (motionp)
234 return sprintf(buf, "motionp\n");
235 else
236 return sprintf(buf, "none\n");
237 }
238}
239
240static DEVICE_ATTR(extension, S_IRUGO, wiiext_show, NULL);
241
David Herrmann479901b2011-11-17 14:12:05 +0100242static int wiiext_input_open(struct input_dev *dev)
243{
244 struct wiimote_ext *ext = input_get_drvdata(dev);
245 int ret;
246
247 ret = hid_hw_open(ext->wdata->hdev);
248 if (ret)
249 return ret;
250
251 atomic_inc(&ext->opened);
252 wiiext_schedule(ext);
253
254 return 0;
255}
256
257static void wiiext_input_close(struct input_dev *dev)
258{
259 struct wiimote_ext *ext = input_get_drvdata(dev);
260
261 atomic_dec(&ext->opened);
262 wiiext_schedule(ext);
263 hid_hw_close(ext->wdata->hdev);
264}
265
266static int wiiext_mp_open(struct input_dev *dev)
267{
268 struct wiimote_ext *ext = input_get_drvdata(dev);
269 int ret;
270
271 ret = hid_hw_open(ext->wdata->hdev);
272 if (ret)
273 return ret;
274
275 atomic_inc(&ext->mp_opened);
276 wiiext_schedule(ext);
277
278 return 0;
279}
280
281static void wiiext_mp_close(struct input_dev *dev)
282{
283 struct wiimote_ext *ext = input_get_drvdata(dev);
284
285 atomic_dec(&ext->mp_opened);
286 wiiext_schedule(ext);
287 hid_hw_close(ext->wdata->hdev);
288}
289
David Herrmanncb992212011-11-17 14:12:01 +0100290/* Initializes the extension driver of a wiimote */
291int wiiext_init(struct wiimote_data *wdata)
292{
293 struct wiimote_ext *ext;
294 unsigned long flags;
David Herrmannc1e51392011-11-17 14:12:04 +0100295 int ret;
David Herrmanncb992212011-11-17 14:12:01 +0100296
297 ext = kzalloc(sizeof(*ext), GFP_KERNEL);
298 if (!ext)
299 return -ENOMEM;
300
301 ext->wdata = wdata;
302 INIT_WORK(&ext->worker, wiiext_worker);
303
David Herrmann479901b2011-11-17 14:12:05 +0100304 ext->input = input_allocate_device();
305 if (!ext->input) {
306 ret = -ENOMEM;
307 goto err_input;
308 }
309
310 input_set_drvdata(ext->input, ext);
311 ext->input->open = wiiext_input_open;
312 ext->input->close = wiiext_input_close;
313 ext->input->dev.parent = &wdata->hdev->dev;
314 ext->input->id.bustype = wdata->hdev->bus;
315 ext->input->id.vendor = wdata->hdev->vendor;
316 ext->input->id.product = wdata->hdev->product;
317 ext->input->id.version = wdata->hdev->version;
318 ext->input->name = WIIMOTE_NAME " Extension";
319
320 ret = input_register_device(ext->input);
321 if (ret) {
322 input_free_device(ext->input);
323 goto err_input;
324 }
325
326 ext->mp_input = input_allocate_device();
327 if (!ext->mp_input) {
328 ret = -ENOMEM;
329 goto err_mp;
330 }
331
332 input_set_drvdata(ext->mp_input, ext);
333 ext->mp_input->open = wiiext_mp_open;
334 ext->mp_input->close = wiiext_mp_close;
335 ext->mp_input->dev.parent = &wdata->hdev->dev;
336 ext->mp_input->id.bustype = wdata->hdev->bus;
337 ext->mp_input->id.vendor = wdata->hdev->vendor;
338 ext->mp_input->id.product = wdata->hdev->product;
339 ext->mp_input->id.version = wdata->hdev->version;
340 ext->mp_input->name = WIIMOTE_NAME " Motion+";
341
342 ret = input_register_device(ext->mp_input);
343 if (ret) {
344 input_free_device(ext->mp_input);
345 goto err_mp;
346 }
347
David Herrmannc1e51392011-11-17 14:12:04 +0100348 ret = device_create_file(&wdata->hdev->dev, &dev_attr_extension);
349 if (ret)
David Herrmann479901b2011-11-17 14:12:05 +0100350 goto err_dev;
David Herrmannc1e51392011-11-17 14:12:04 +0100351
David Herrmanncb992212011-11-17 14:12:01 +0100352 spin_lock_irqsave(&wdata->state.lock, flags);
353 wdata->ext = ext;
354 spin_unlock_irqrestore(&wdata->state.lock, flags);
355
356 return 0;
David Herrmannc1e51392011-11-17 14:12:04 +0100357
David Herrmann479901b2011-11-17 14:12:05 +0100358err_dev:
359 input_unregister_device(ext->mp_input);
360err_mp:
361 input_unregister_device(ext->input);
362err_input:
David Herrmannc1e51392011-11-17 14:12:04 +0100363 kfree(ext);
364 return ret;
David Herrmanncb992212011-11-17 14:12:01 +0100365}
366
367/* Deinitializes the extension driver of a wiimote */
368void wiiext_deinit(struct wiimote_data *wdata)
369{
370 struct wiimote_ext *ext = wdata->ext;
371 unsigned long flags;
372
373 if (!ext)
374 return;
375
376 /*
377 * We first unset wdata->ext to avoid further input from the wiimote
378 * core. The worker thread does not access this pointer so it is not
379 * affected by this.
380 * We kill the worker after this so it does not get respawned during
381 * deinitialization.
382 */
383
384 spin_lock_irqsave(&wdata->state.lock, flags);
385 wdata->ext = NULL;
386 spin_unlock_irqrestore(&wdata->state.lock, flags);
387
David Herrmannc1e51392011-11-17 14:12:04 +0100388 device_remove_file(&wdata->hdev->dev, &dev_attr_extension);
David Herrmann479901b2011-11-17 14:12:05 +0100389 input_unregister_device(ext->mp_input);
390 input_unregister_device(ext->input);
David Herrmannc1e51392011-11-17 14:12:04 +0100391
David Herrmanncb992212011-11-17 14:12:01 +0100392 cancel_work_sync(&ext->worker);
393 kfree(ext);
394}