diff options
Diffstat (limited to 'drivers/hid/hid-wiimote-core.c')
| -rw-r--r-- | drivers/hid/hid-wiimote-core.c | 86 |
1 files changed, 51 insertions, 35 deletions
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c index 0c06054cab8f..5b5fc460a4c5 100644 --- a/drivers/hid/hid-wiimote-core.c +++ b/drivers/hid/hid-wiimote-core.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * HID driver for Nintendo Wii / Wii U peripherals * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@gmail.com> */ /* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. */ #include <linux/completion.h> @@ -28,14 +25,14 @@ static int wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, __u8 *buf; int ret; - if (!hdev->hid_output_raw_report) + if (!hdev->ll_driver->output_report) return -ENODEV; buf = kmemdup(buffer, count, GFP_KERNEL); if (!buf) return -ENOMEM; - ret = hdev->hid_output_raw_report(hdev, buf, count, HID_OUTPUT_REPORT); + ret = hid_hw_output_report(hdev, buf, count); kfree(buf); return ret; @@ -212,10 +209,12 @@ static __u8 select_drm(struct wiimote_data *wdata) if (ir == WIIPROTO_FLAG_IR_BASIC) { if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) { - if (ext) - return WIIPROTO_REQ_DRM_KAIE; - else - return WIIPROTO_REQ_DRM_KAI; + /* GEN10 and ealier devices bind IR formats to DRMs. + * Hence, we cannot use DRM_KAI here as it might be + * bound to IR_EXT. Use DRM_KAIE unconditionally so we + * work with all devices and our parsers can use the + * fixed formats, too. */ + return WIIPROTO_REQ_DRM_KAIE; } else { return WIIPROTO_REQ_DRM_KIE; } @@ -439,8 +438,7 @@ static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata, __u8 *rmem) if (ret != 6) return WIIMOTE_EXT_NONE; - hid_dbg(wdata->hdev, "extension ID: %02x:%02x %02x:%02x %02x:%02x\n", - rmem[0], rmem[1], rmem[2], rmem[3], rmem[4], rmem[5]); + hid_dbg(wdata->hdev, "extension ID: %6phC\n", rmem); if (rmem[0] == 0xff && rmem[1] == 0xff && rmem[2] == 0xff && rmem[3] == 0xff && rmem[4] == 0xff && rmem[5] == 0xff) @@ -454,6 +452,15 @@ static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata, __u8 *rmem) return WIIMOTE_EXT_BALANCE_BOARD; if (rmem[4] == 0x01 && rmem[5] == 0x20) return WIIMOTE_EXT_PRO_CONTROLLER; + if (rmem[0] == 0x01 && rmem[1] == 0x00 && + rmem[4] == 0x01 && rmem[5] == 0x03) + return WIIMOTE_EXT_DRUMS; + if (rmem[0] == 0x00 && rmem[1] == 0x00 && + rmem[4] == 0x01 && rmem[5] == 0x03) + return WIIMOTE_EXT_GUITAR; + if (rmem[0] == 0x03 && rmem[1] == 0x00 && + rmem[4] == 0x01 && rmem[5] == 0x03) + return WIIMOTE_EXT_TURNTABLE; return WIIMOTE_EXT_UNKNOWN; } @@ -487,8 +494,11 @@ static bool wiimote_cmd_map_mp(struct wiimote_data *wdata, __u8 exttype) /* map MP with correct pass-through mode */ switch (exttype) { case WIIMOTE_EXT_CLASSIC_CONTROLLER: + case WIIMOTE_EXT_DRUMS: + case WIIMOTE_EXT_GUITAR: wmem = 0x07; break; + case WIIMOTE_EXT_TURNTABLE: case WIIMOTE_EXT_NUNCHUK: wmem = 0x05; break; @@ -510,14 +520,12 @@ static bool wiimote_cmd_read_mp(struct wiimote_data *wdata, __u8 *rmem) if (ret != 6) return false; - hid_dbg(wdata->hdev, "motion plus ID: %02x:%02x %02x:%02x %02x:%02x\n", - rmem[0], rmem[1], rmem[2], rmem[3], rmem[4], rmem[5]); + hid_dbg(wdata->hdev, "motion plus ID: %6phC\n", rmem); if (rmem[5] == 0x05) return true; - hid_info(wdata->hdev, "unknown motion plus ID: %02x:%02x %02x:%02x %02x:%02x\n", - rmem[0], rmem[1], rmem[2], rmem[3], rmem[4], rmem[5]); + hid_info(wdata->hdev, "unknown motion plus ID: %6phC\n", rmem); return false; } @@ -533,8 +541,7 @@ static __u8 wiimote_cmd_read_mp_mapped(struct wiimote_data *wdata) if (ret != 6) return WIIMOTE_MP_NONE; - hid_dbg(wdata->hdev, "mapped motion plus ID: %02x:%02x %02x:%02x %02x:%02x\n", - rmem[0], rmem[1], rmem[2], rmem[3], rmem[4], rmem[5]); + hid_dbg(wdata->hdev, "mapped motion plus ID: %6phC\n", rmem); if (rmem[0] == 0xff && rmem[1] == 0xff && rmem[2] == 0xff && rmem[3] == 0xff && rmem[4] == 0xff && rmem[5] == 0xff) @@ -1077,6 +1084,9 @@ static const char *wiimote_exttype_names[WIIMOTE_EXT_NUM] = { [WIIMOTE_EXT_CLASSIC_CONTROLLER] = "Nintendo Wii Classic Controller", [WIIMOTE_EXT_BALANCE_BOARD] = "Nintendo Wii Balance Board", [WIIMOTE_EXT_PRO_CONTROLLER] = "Nintendo Wii U Pro Controller", + [WIIMOTE_EXT_DRUMS] = "Nintendo Wii Drums", + [WIIMOTE_EXT_GUITAR] = "Nintendo Wii Guitar", + [WIIMOTE_EXT_TURNTABLE] = "Nintendo Wii Turntable" }; /* @@ -1126,9 +1136,8 @@ static void wiimote_init_hotplug(struct wiimote_data *wdata) wiimote_ext_unload(wdata); if (exttype == WIIMOTE_EXT_UNKNOWN) { - hid_info(wdata->hdev, "cannot detect extension; %02x:%02x %02x:%02x %02x:%02x\n", - extdata[0], extdata[1], extdata[2], - extdata[3], extdata[4], extdata[5]); + hid_info(wdata->hdev, "cannot detect extension; %6phC\n", + extdata); } else if (exttype == WIIMOTE_EXT_NONE) { spin_lock_irq(&wdata->state.lock); wdata->state.exttype = WIIMOTE_EXT_NONE; @@ -1162,7 +1171,7 @@ static void wiimote_init_hotplug(struct wiimote_data *wdata) wiimote_cmd_release(wdata); /* delete MP hotplug timer */ - del_timer_sync(&wdata->timer); + timer_delete_sync(&wdata->timer); } else { /* reschedule MP hotplug timer */ if (!(flags & WIIPROTO_FLAG_BUILTIN_MP) && @@ -1229,9 +1238,9 @@ static void wiimote_schedule(struct wiimote_data *wdata) spin_unlock_irqrestore(&wdata->state.lock, flags); } -static void wiimote_init_timeout(unsigned long arg) +static void wiimote_init_timeout(struct timer_list *t) { - struct wiimote_data *wdata = (void*)arg; + struct wiimote_data *wdata = timer_container_of(wdata, t, timer); wiimote_schedule(wdata); } @@ -1478,7 +1487,7 @@ static void handler_return(struct wiimote_data *wdata, const __u8 *payload) wdata->state.cmd_err = err; wiimote_cmd_complete(wdata); } else if (err) { - hid_warn(wdata->hdev, "Remote error %hhu on req %hhu\n", err, + hid_warn(wdata->hdev, "Remote error %u on req %u\n", err, cmd); } } @@ -1582,7 +1591,7 @@ struct wiiproto_handler { void (*func)(struct wiimote_data *wdata, const __u8 *payload); }; -static struct wiiproto_handler handlers[] = { +static const struct wiiproto_handler handlers[] = { { .id = WIIPROTO_REQ_STATUS, .size = 6, .func = handler_status }, { .id = WIIPROTO_REQ_STATUS, .size = 2, .func = handler_status_K }, { .id = WIIPROTO_REQ_DATA, .size = 21, .func = handler_data }, @@ -1614,19 +1623,19 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, u8 *raw_data, int size) { struct wiimote_data *wdata = hid_get_drvdata(hdev); - struct wiiproto_handler *h; + const struct wiiproto_handler *h; int i; unsigned long flags; if (size < 1) return -EINVAL; - spin_lock_irqsave(&wdata->state.lock, flags); - for (i = 0; handlers[i].id; ++i) { h = &handlers[i]; if (h->id == raw_data[0] && h->size < size) { + spin_lock_irqsave(&wdata->state.lock, flags); h->func(wdata, &raw_data[1]); + spin_unlock_irqrestore(&wdata->state.lock, flags); break; } } @@ -1635,8 +1644,6 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, hid_warn(hdev, "Unhandled report %hhu size %d\n", raw_data[0], size); - spin_unlock_irqrestore(&wdata->state.lock, flags); - return 0; } @@ -1663,8 +1670,13 @@ static ssize_t wiimote_ext_show(struct device *dev, return sprintf(buf, "balanceboard\n"); case WIIMOTE_EXT_PRO_CONTROLLER: return sprintf(buf, "procontroller\n"); + case WIIMOTE_EXT_DRUMS: + return sprintf(buf, "drums\n"); + case WIIMOTE_EXT_GUITAR: + return sprintf(buf, "guitar\n"); + case WIIMOTE_EXT_TURNTABLE: + return sprintf(buf, "turntable\n"); case WIIMOTE_EXT_UNKNOWN: - /* fallthrough */ default: return sprintf(buf, "unknown\n"); } @@ -1714,7 +1726,6 @@ static ssize_t wiimote_dev_show(struct device *dev, case WIIMOTE_DEV_PENDING: return sprintf(buf, "pending\n"); case WIIMOTE_DEV_UNKNOWN: - /* fallthrough */ default: return sprintf(buf, "unknown\n"); } @@ -1743,7 +1754,7 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev) wdata->state.cmd_battery = 0xff; INIT_WORK(&wdata->init_worker, wiimote_init_worker); - setup_timer(&wdata->timer, wiimote_init_timeout, (long)wdata); + timer_setup(&wdata->timer, wiimote_init_timeout, 0); return wdata; } @@ -1760,7 +1771,7 @@ static void wiimote_destroy(struct wiimote_data *wdata) spin_unlock_irqrestore(&wdata->state.lock, flags); cancel_work_sync(&wdata->init_worker); - del_timer_sync(&wdata->timer); + timer_shutdown_sync(&wdata->timer); device_remove_file(&wdata->hdev->dev, &dev_attr_devtype); device_remove_file(&wdata->hdev->dev, &dev_attr_extension); @@ -1862,6 +1873,11 @@ static const struct hid_device_id wiimote_hid_devices[] = { USB_DEVICE_ID_NINTENDO_WIIMOTE2) }, { } }; + +bool wiimote_dpad_as_analog = false; +module_param_named(dpad_as_analog, wiimote_dpad_as_analog, bool, 0644); +MODULE_PARM_DESC(dpad_as_analog, "Use D-Pad as main analog input"); + MODULE_DEVICE_TABLE(hid, wiimote_hid_devices); static struct hid_driver wiimote_hid_driver = { |
