aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-05-05 17:12:48 -0400
committerJiri Kosina <jkosina@suse.cz>2013-06-03 05:06:59 -0400
commitc57ff761be8365599ff9ccdbb205ead4912b2067 (patch)
treeb9b8700089c89e50e097e43e3bac202cd3162310 /drivers/hid
parent5682b1a8690cfae5ad3bd40a123510fd4014066d (diff)
HID: wiimote: add device detection
Nintendo produced many different devices that are internally based on the Wii Remote protocol but provide different peripherals. To support these devices, we need to schedule a device detection during initialization. Device detection includes requesting a status report, reading extension information and then evaluating which device we may be dealing with. We currently detect gen1 and gen2 Wii Remote devices. All other devices are marked as generic devices. More detections will be added later. In followup patches we will be using these device IDs to control which peripherals to initialize. For instance if a device is known to have no IR camera, there is no need to provide the IR input device nor trying to access IR registers. In fact, there are 3rd party devices that break if we try things like this (hurray!). The init_worker will be scheduled whenever we get hotplug events. This isn't implemented, yet and will be added later. However, we need to make sure that this worker can be called multiple times. Signed-off-by: David Herrmann <dh.herrmann@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/hid-wiimote-core.c153
-rw-r--r--drivers/hid/hid-wiimote.h37
2 files changed, 188 insertions, 2 deletions
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 02656a8cc7d7..76d2c73eb696 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -399,6 +399,45 @@ ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, __u8 *rmem,
399 return ret; 399 return ret;
400} 400}
401 401
402/* requires the cmd-mutex to be held */
403static int wiimote_cmd_init_ext(struct wiimote_data *wdata)
404{
405 __u8 wmem;
406 int ret;
407
408 /* initialize extension */
409 wmem = 0x55;
410 ret = wiimote_cmd_write(wdata, 0xa400f0, &wmem, sizeof(wmem));
411 if (ret)
412 return ret;
413
414 /* disable default encryption */
415 wmem = 0x0;
416 ret = wiimote_cmd_write(wdata, 0xa400fb, &wmem, sizeof(wmem));
417 if (ret)
418 return ret;
419
420 return 0;
421}
422
423/* requires the cmd-mutex to be held */
424static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata)
425{
426 __u8 rmem[6];
427 int ret;
428
429 /* read extension ID */
430 ret = wiimote_cmd_read(wdata, 0xa400fa, rmem, 6);
431 if (ret != 6)
432 return WIIMOTE_EXT_NONE;
433
434 if (rmem[0] == 0xff && rmem[1] == 0xff && rmem[2] == 0xff &&
435 rmem[3] == 0xff && rmem[4] == 0xff && rmem[5] == 0xff)
436 return WIIMOTE_EXT_NONE;
437
438 return WIIMOTE_EXT_UNKNOWN;
439}
440
402static int wiimote_battery_get_property(struct power_supply *psy, 441static int wiimote_battery_get_property(struct power_supply *psy,
403 enum power_supply_property psp, 442 enum power_supply_property psp,
404 union power_supply_propval *val) 443 union power_supply_propval *val)
@@ -662,6 +701,105 @@ static void wiimote_ir_close(struct input_dev *dev)
662 wiimote_init_ir(wdata, 0); 701 wiimote_init_ir(wdata, 0);
663} 702}
664 703
704/* device (re-)initialization and detection */
705
706static const char *wiimote_devtype_names[WIIMOTE_DEV_NUM] = {
707 [WIIMOTE_DEV_PENDING] = "Pending",
708 [WIIMOTE_DEV_UNKNOWN] = "Unknown",
709 [WIIMOTE_DEV_GENERIC] = "Generic",
710 [WIIMOTE_DEV_GEN10] = "Nintendo Wii Remote (Gen 1)",
711 [WIIMOTE_DEV_GEN20] = "Nintendo Wii Remote Plus (Gen 2)",
712};
713
714/* Try to guess the device type based on all collected information. We
715 * first try to detect by static extension types, then VID/PID and the
716 * device name. If we cannot detect the device, we use
717 * WIIMOTE_DEV_GENERIC so all modules will get probed on the device. */
718static void wiimote_init_set_type(struct wiimote_data *wdata,
719 __u8 exttype)
720{
721 __u8 devtype = WIIMOTE_DEV_GENERIC;
722 __u16 vendor, product;
723 const char *name;
724
725 vendor = wdata->hdev->vendor;
726 product = wdata->hdev->product;
727 name = wdata->hdev->name;
728
729 if (!strcmp(name, "Nintendo RVL-CNT-01")) {
730 devtype = WIIMOTE_DEV_GEN10;
731 goto done;
732 } else if (!strcmp(name, "Nintendo RVL-CNT-01-TR")) {
733 devtype = WIIMOTE_DEV_GEN20;
734 goto done;
735 }
736
737 if (vendor == USB_VENDOR_ID_NINTENDO) {
738 if (product == USB_DEVICE_ID_NINTENDO_WIIMOTE) {
739 devtype = WIIMOTE_DEV_GEN10;
740 goto done;
741 } else if (product == USB_DEVICE_ID_NINTENDO_WIIMOTE2) {
742 devtype = WIIMOTE_DEV_GEN20;
743 goto done;
744 }
745 }
746
747done:
748 if (devtype == WIIMOTE_DEV_GENERIC)
749 hid_info(wdata->hdev, "cannot detect device; NAME: %s VID: %04x PID: %04x EXT: %04x\n",
750 name, vendor, product, exttype);
751 else
752 hid_info(wdata->hdev, "detected device: %s\n",
753 wiimote_devtype_names[devtype]);
754
755 spin_lock_irq(&wdata->state.lock);
756 wdata->state.devtype = devtype;
757 spin_unlock_irq(&wdata->state.lock);
758}
759
760static void wiimote_init_detect(struct wiimote_data *wdata)
761{
762 __u8 exttype = WIIMOTE_EXT_NONE;
763 bool ext;
764 int ret;
765
766 wiimote_cmd_acquire_noint(wdata);
767
768 spin_lock_irq(&wdata->state.lock);
769 wiimote_cmd_set(wdata, WIIPROTO_REQ_SREQ, 0);
770 wiiproto_req_status(wdata);
771 spin_unlock_irq(&wdata->state.lock);
772
773 ret = wiimote_cmd_wait_noint(wdata);
774 if (ret)
775 goto out_release;
776
777 spin_lock_irq(&wdata->state.lock);
778 ext = wdata->state.flags & WIIPROTO_FLAG_EXT_PLUGGED;
779 spin_unlock_irq(&wdata->state.lock);
780
781 if (!ext)
782 goto out_release;
783
784 wiimote_cmd_init_ext(wdata);
785 exttype = wiimote_cmd_read_ext(wdata);
786
787out_release:
788 wiimote_cmd_release(wdata);
789 wiimote_init_set_type(wdata, exttype);
790}
791
792static void wiimote_init_worker(struct work_struct *work)
793{
794 struct wiimote_data *wdata = container_of(work, struct wiimote_data,
795 init_worker);
796
797 if (wdata->state.devtype == WIIMOTE_DEV_PENDING)
798 wiimote_init_detect(wdata);
799}
800
801/* protocol handlers */
802
665static void handler_keys(struct wiimote_data *wdata, const __u8 *payload) 803static void handler_keys(struct wiimote_data *wdata, const __u8 *payload)
666{ 804{
667 input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_LEFT], 805 input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_LEFT],
@@ -776,7 +914,14 @@ static void handler_status(struct wiimote_data *wdata, const __u8 *payload)
776{ 914{
777 handler_status_K(wdata, payload); 915 handler_status_K(wdata, payload);
778 916
779 wiiext_event(wdata, payload[2] & 0x02); 917 /* update extension status */
918 if (payload[2] & 0x02) {
919 wdata->state.flags |= WIIPROTO_FLAG_EXT_PLUGGED;
920 wiiext_event(wdata, true);
921 } else {
922 wdata->state.flags &= ~WIIPROTO_FLAG_EXT_PLUGGED;
923 wiiext_event(wdata, false);
924 }
780 925
781 if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_SREQ, 0)) { 926 if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_SREQ, 0)) {
782 wdata->state.cmd_battery = payload[5]; 927 wdata->state.cmd_battery = payload[5];
@@ -1135,6 +1280,8 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev)
1135 mutex_init(&wdata->state.sync); 1280 mutex_init(&wdata->state.sync);
1136 wdata->state.drm = WIIPROTO_REQ_DRM_K; 1281 wdata->state.drm = WIIPROTO_REQ_DRM_K;
1137 1282
1283 INIT_WORK(&wdata->init_worker, wiimote_init_worker);
1284
1138 return wdata; 1285 return wdata;
1139 1286
1140err_ir: 1287err_ir:
@@ -1157,6 +1304,7 @@ static void wiimote_destroy(struct wiimote_data *wdata)
1157 input_unregister_device(wdata->accel); 1304 input_unregister_device(wdata->accel);
1158 input_unregister_device(wdata->ir); 1305 input_unregister_device(wdata->ir);
1159 input_unregister_device(wdata->input); 1306 input_unregister_device(wdata->input);
1307 cancel_work_sync(&wdata->init_worker);
1160 cancel_work_sync(&wdata->queue.worker); 1308 cancel_work_sync(&wdata->queue.worker);
1161 hid_hw_close(wdata->hdev); 1309 hid_hw_close(wdata->hdev);
1162 hid_hw_stop(wdata->hdev); 1310 hid_hw_stop(wdata->hdev);
@@ -1253,6 +1401,9 @@ static int wiimote_hid_probe(struct hid_device *hdev,
1253 wiiproto_req_leds(wdata, WIIPROTO_FLAG_LED1); 1401 wiiproto_req_leds(wdata, WIIPROTO_FLAG_LED1);
1254 spin_unlock_irq(&wdata->state.lock); 1402 spin_unlock_irq(&wdata->state.lock);
1255 1403
1404 /* schedule device detection */
1405 schedule_work(&wdata->init_worker);
1406
1256 return 0; 1407 return 0;
1257 1408
1258err_free: 1409err_free:
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index 2700d47dea3d..301607da7715 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -35,6 +35,8 @@
35#define WIIPROTO_FLAG_IR_BASIC 0x40 35#define WIIPROTO_FLAG_IR_BASIC 0x40
36#define WIIPROTO_FLAG_IR_EXT 0x80 36#define WIIPROTO_FLAG_IR_EXT 0x80
37#define WIIPROTO_FLAG_IR_FULL 0xc0 /* IR_BASIC | IR_EXT */ 37#define WIIPROTO_FLAG_IR_FULL 0xc0 /* IR_BASIC | IR_EXT */
38#define WIIPROTO_FLAG_EXT_PLUGGED 0x0100
39
38#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ 40#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \
39 WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) 41 WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4)
40#define WIIPROTO_FLAGS_IR (WIIPROTO_FLAG_IR_BASIC | WIIPROTO_FLAG_IR_EXT | \ 42#define WIIPROTO_FLAGS_IR (WIIPROTO_FLAG_IR_BASIC | WIIPROTO_FLAG_IR_EXT | \
@@ -43,6 +45,21 @@
43/* return flag for led \num */ 45/* return flag for led \num */
44#define WIIPROTO_FLAG_LED(num) (WIIPROTO_FLAG_LED1 << (num - 1)) 46#define WIIPROTO_FLAG_LED(num) (WIIPROTO_FLAG_LED1 << (num - 1))
45 47
48enum wiimote_devtype {
49 WIIMOTE_DEV_PENDING,
50 WIIMOTE_DEV_UNKNOWN,
51 WIIMOTE_DEV_GENERIC,
52 WIIMOTE_DEV_GEN10,
53 WIIMOTE_DEV_GEN20,
54 WIIMOTE_DEV_NUM,
55};
56
57enum wiimote_exttype {
58 WIIMOTE_EXT_NONE,
59 WIIMOTE_EXT_UNKNOWN,
60 WIIMOTE_EXT_NUM,
61};
62
46struct wiimote_buf { 63struct wiimote_buf {
47 __u8 data[HID_MAX_BUFFER_SIZE]; 64 __u8 data[HID_MAX_BUFFER_SIZE];
48 size_t size; 65 size_t size;
@@ -58,9 +75,10 @@ struct wiimote_queue {
58 75
59struct wiimote_state { 76struct wiimote_state {
60 spinlock_t lock; 77 spinlock_t lock;
61 __u8 flags; 78 __u32 flags;
62 __u8 accel_split[2]; 79 __u8 accel_split[2];
63 __u8 drm; 80 __u8 drm;
81 __u8 devtype;
64 82
65 /* synchronous cmd requests */ 83 /* synchronous cmd requests */
66 struct mutex sync; 84 struct mutex sync;
@@ -87,6 +105,7 @@ struct wiimote_data {
87 105
88 struct wiimote_queue queue; 106 struct wiimote_queue queue;
89 struct wiimote_state state; 107 struct wiimote_state state;
108 struct work_struct init_worker;
90}; 109};
91 110
92enum wiiproto_reqs { 111enum wiiproto_reqs {
@@ -181,6 +200,11 @@ static inline int wiimote_cmd_acquire(struct wiimote_data *wdata)
181 return mutex_lock_interruptible(&wdata->state.sync) ? -ERESTARTSYS : 0; 200 return mutex_lock_interruptible(&wdata->state.sync) ? -ERESTARTSYS : 0;
182} 201}
183 202
203static inline void wiimote_cmd_acquire_noint(struct wiimote_data *wdata)
204{
205 mutex_lock(&wdata->state.sync);
206}
207
184/* requires the state.lock spinlock to be held */ 208/* requires the state.lock spinlock to be held */
185static inline void wiimote_cmd_set(struct wiimote_data *wdata, int cmd, 209static inline void wiimote_cmd_set(struct wiimote_data *wdata, int cmd,
186 __u32 opt) 210 __u32 opt)
@@ -208,4 +232,15 @@ static inline int wiimote_cmd_wait(struct wiimote_data *wdata)
208 return 0; 232 return 0;
209} 233}
210 234
235static inline int wiimote_cmd_wait_noint(struct wiimote_data *wdata)
236{
237 unsigned long ret;
238
239 ret = wait_for_completion_timeout(&wdata->state.ready, HZ);
240 if (!ret)
241 return -EIO;
242 else
243 return 0;
244}
245
211#endif 246#endif