aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/Kconfig9
-rw-r--r--drivers/hid/Makefile3
-rw-r--r--drivers/hid/hid-wiimote-core.c23
-rw-r--r--drivers/hid/hid-wiimote-ext.c130
-rw-r--r--drivers/hid/hid-wiimote.h17
5 files changed, 178 insertions, 4 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 22a4a051f221..7a0c6f956d3e 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -623,6 +623,15 @@ config HID_WIIMOTE
623 ---help--- 623 ---help---
624 Support for the Nintendo Wii Remote bluetooth device. 624 Support for the Nintendo Wii Remote bluetooth device.
625 625
626config HID_WIIMOTE_EXT
627 bool "Nintendo Wii Remote Extension support"
628 depends on HID_WIIMOTE
629 default HID_WIIMOTE
630 ---help---
631 Support for extension controllers of the Nintendo Wii Remote. Say yes
632 here if you want to use the Nintendo Motion+, Nunchuck or Classic
633 extension controllers with your Wii Remote.
634
626config HID_ZEROPLUS 635config HID_ZEROPLUS
627 tristate "Zeroplus based game controller support" 636 tristate "Zeroplus based game controller support"
628 depends on USB_HID 637 depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 96d33adb258a..5fab4e632eab 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -26,6 +26,9 @@ ifdef CONFIG_LOGIWHEELS_FF
26endif 26endif
27 27
28hid-wiimote-y := hid-wiimote-core.o 28hid-wiimote-y := hid-wiimote-core.o
29ifdef CONFIG_HID_WIIMOTE_EXT
30 hid-wiimote-y += hid-wiimote-ext.o
31endif
29 32
30obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o 33obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o
31obj-$(CONFIG_HID_ACRUX) += hid-axff.o 34obj-$(CONFIG_HID_ACRUX) += hid-axff.o
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index f7f8b7ff7dec..2ca8bfd350ad 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -201,6 +201,7 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds)
201static __u8 select_drm(struct wiimote_data *wdata) 201static __u8 select_drm(struct wiimote_data *wdata)
202{ 202{
203 __u8 ir = wdata->state.flags & WIIPROTO_FLAGS_IR; 203 __u8 ir = wdata->state.flags & WIIPROTO_FLAGS_IR;
204 bool ext = wiiext_active(wdata);
204 205
205 if (ir == WIIPROTO_FLAG_IR_BASIC) { 206 if (ir == WIIPROTO_FLAG_IR_BASIC) {
206 if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) 207 if (wdata->state.flags & WIIPROTO_FLAG_ACCEL)
@@ -212,10 +213,17 @@ static __u8 select_drm(struct wiimote_data *wdata)
212 } else if (ir == WIIPROTO_FLAG_IR_FULL) { 213 } else if (ir == WIIPROTO_FLAG_IR_FULL) {
213 return WIIPROTO_REQ_DRM_SKAI1; 214 return WIIPROTO_REQ_DRM_SKAI1;
214 } else { 215 } else {
215 if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) 216 if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) {
216 return WIIPROTO_REQ_DRM_KA; 217 if (ext)
217 else 218 return WIIPROTO_REQ_DRM_KAE;
218 return WIIPROTO_REQ_DRM_K; 219 else
220 return WIIPROTO_REQ_DRM_KA;
221 } else {
222 if (ext)
223 return WIIPROTO_REQ_DRM_KE;
224 else
225 return WIIPROTO_REQ_DRM_K;
226 }
219 } 227 }
220} 228}
221 229
@@ -795,6 +803,8 @@ static void handler_status(struct wiimote_data *wdata, const __u8 *payload)
795 /* on status reports the drm is reset so we need to resend the drm */ 803 /* on status reports the drm is reset so we need to resend the drm */
796 wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); 804 wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
797 805
806 wiiext_event(wdata, payload[2] & 0x02);
807
798 if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_SREQ, 0)) { 808 if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_SREQ, 0)) {
799 wdata->state.cmd_battery = payload[5]; 809 wdata->state.cmd_battery = payload[5];
800 wiimote_cmd_complete(wdata); 810 wiimote_cmd_complete(wdata);
@@ -1145,6 +1155,7 @@ err:
1145 1155
1146static void wiimote_destroy(struct wiimote_data *wdata) 1156static void wiimote_destroy(struct wiimote_data *wdata)
1147{ 1157{
1158 wiiext_deinit(wdata);
1148 wiimote_leds_destroy(wdata); 1159 wiimote_leds_destroy(wdata);
1149 1160
1150 power_supply_unregister(&wdata->battery); 1161 power_supply_unregister(&wdata->battery);
@@ -1216,6 +1227,10 @@ static int wiimote_hid_probe(struct hid_device *hdev,
1216 if (ret) 1227 if (ret)
1217 goto err_free; 1228 goto err_free;
1218 1229
1230 ret = wiiext_init(wdata);
1231 if (ret)
1232 goto err_free;
1233
1219 hid_info(hdev, "New device registered\n"); 1234 hid_info(hdev, "New device registered\n");
1220 1235
1221 /* by default set led1 after device initialization */ 1236 /* by default set led1 after device initialization */
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c
new file mode 100644
index 000000000000..fa9c67722aca
--- /dev/null
+++ b/drivers/hid/hid-wiimote-ext.c
@@ -0,0 +1,130 @@
1/*
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;
22
23 atomic_t opened;
24 atomic_t mp_opened;
25 bool plugged;
26 bool motionp;
27 __u8 ext_type;
28};
29
30enum wiiext_type {
31 WIIEXT_NONE, /* placeholder */
32 WIIEXT_CLASSIC, /* Nintendo classic controller */
33 WIIEXT_NUNCHUCK, /* Nintendo nunchuck controller */
34};
35
36static void wiiext_worker(struct work_struct *work)
37{
38 struct wiimote_ext *ext = container_of(work, struct wiimote_ext,
39 worker);
40}
41
42/* schedule work only once, otherwise mark for reschedule */
43static void wiiext_schedule(struct wiimote_ext *ext)
44{
45 queue_work(system_nrt_wq, &ext->worker);
46}
47
48/*
49 * Reacts on extension port events
50 * Whenever the driver gets an event from the wiimote that an extension has been
51 * plugged or unplugged, this funtion shall be called. It checks what extensions
52 * are connected and initializes and activates them.
53 * This can be called in atomic context. The initialization is done in a
54 * separate worker thread. The state.lock spinlock must be held by the caller.
55 */
56void wiiext_event(struct wiimote_data *wdata, bool plugged)
57{
58 if (!wdata->ext)
59 return;
60
61 if (wdata->ext->plugged == plugged)
62 return;
63
64 wdata->ext->plugged = plugged;
65 /*
66 * We need to call wiiext_schedule(wdata->ext) here, however, the
67 * extension initialization logic is not fully understood and so
68 * automatic initialization is not supported, yet.
69 */
70}
71
72/*
73 * Returns true if the current DRM mode should contain extension data and false
74 * if there is no interest in extension data.
75 * All supported extensions send 6 byte extension data so any DRM that contains
76 * extension bytes is fine.
77 * The caller must hold the state.lock spinlock.
78 */
79bool wiiext_active(struct wiimote_data *wdata)
80{
81 if (!wdata->ext)
82 return false;
83
84 return wdata->ext->motionp || wdata->ext->ext_type;
85}
86
87/* Initializes the extension driver of a wiimote */
88int wiiext_init(struct wiimote_data *wdata)
89{
90 struct wiimote_ext *ext;
91 unsigned long flags;
92
93 ext = kzalloc(sizeof(*ext), GFP_KERNEL);
94 if (!ext)
95 return -ENOMEM;
96
97 ext->wdata = wdata;
98 INIT_WORK(&ext->worker, wiiext_worker);
99
100 spin_lock_irqsave(&wdata->state.lock, flags);
101 wdata->ext = ext;
102 spin_unlock_irqrestore(&wdata->state.lock, flags);
103
104 return 0;
105}
106
107/* Deinitializes the extension driver of a wiimote */
108void wiiext_deinit(struct wiimote_data *wdata)
109{
110 struct wiimote_ext *ext = wdata->ext;
111 unsigned long flags;
112
113 if (!ext)
114 return;
115
116 /*
117 * We first unset wdata->ext to avoid further input from the wiimote
118 * core. The worker thread does not access this pointer so it is not
119 * affected by this.
120 * We kill the worker after this so it does not get respawned during
121 * deinitialization.
122 */
123
124 spin_lock_irqsave(&wdata->state.lock, flags);
125 wdata->ext = NULL;
126 spin_unlock_irqrestore(&wdata->state.lock, flags);
127
128 cancel_work_sync(&ext->worker);
129 kfree(ext);
130}
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index 865740d3a3fe..abbfab8f60b7 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -73,6 +73,7 @@ struct wiimote_data {
73 struct input_dev *accel; 73 struct input_dev *accel;
74 struct input_dev *ir; 74 struct input_dev *ir;
75 struct power_supply battery; 75 struct power_supply battery;
76 struct wiimote_ext *ext;
76 77
77 spinlock_t qlock; 78 spinlock_t qlock;
78 __u8 head; 79 __u8 head;
@@ -118,6 +119,22 @@ extern int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset,
118extern ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, 119extern ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset,
119 __u8 *rmem, __u8 size); 120 __u8 *rmem, __u8 size);
120 121
122#ifdef CONFIG_HID_WIIMOTE_EXT
123
124extern int wiiext_init(struct wiimote_data *wdata);
125extern void wiiext_deinit(struct wiimote_data *wdata);
126extern void wiiext_event(struct wiimote_data *wdata, bool plugged);
127extern bool wiiext_active(struct wiimote_data *wdata);
128
129#else
130
131static inline int wiiext_init(void *u) { return 0; }
132static inline void wiiext_deinit(void *u) { }
133static inline void wiiext_event(void *u, bool p) { }
134static inline bool wiiext_active(void *u) { return false; }
135
136#endif
137
121/* requires the state.lock spinlock to be held */ 138/* requires the state.lock spinlock to be held */
122static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd, 139static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd,
123 __u32 opt) 140 __u32 opt)