Pull HID updates from Jiri Kosina: - HID battery handling cleanup by David Herrmann - ELO 4000/4500 driver, which has been finally ported to be proper HID driver by Jiri Slaby - ps3remote driver functionality is now provided by generic sony driver, by Jiri Kosina - PS2/3 Buzz controllers support, by Colin Leitner - rework of wiimote driver including full extensions hotpluggin support, sub-device modularization and speaker support by David Herrmann * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (55 commits) HID: wacom: Intuos4 battery charging changes HID: i2c-hid: support sending HID output reports using the output register HID: kye: Add report fixup for Genius Gila Gaming mouse HID: wiimote: support Nintendo Wii U Pro Controller Input: make gamepad API keycodes more clear input: document gamepad API and add extra keycodes HID: explain out-of-range check better HID: fix false positive out of range values HID: wiimote: fix coccinelle warnings HID: roccat: check cdev_add return value HID: fold ps3remote driver into generic Sony driver HID: hyperv: convert alloc+memcpy to memdup HID: core: fix reporting of raw events HID: wiimote: discard invalid EXT data reports HID: wiimote: fix classic controller parsing HID: wiimote: init EXT/MP during device detection HID: wiimote: fix DRM debug-attr to correctly parse input HID: wiimote: add MP quirks HID: wiimote: remove old static extension support HID: wiimote: add "bboard_calib" attribute ...
Unified · Split
| @@ -12,7 +12,7 @@ Description: Make it possible to set/get current led state. Reading from it · 11 unmodified lines | ||
| 12 | 12 | What: /sys/bus/hid/drivers/wiimote/<dev>/extension |
| 13 | 13 | Date: August 2011 |
| 14 | 14 | KernelVersion: 3.2 |
| 15 | −Contact: David Herrmann <dh.herrmann@googlemail.com> | |
| 15 | +Contact: David Herrmann <dh.herrmann@gmail.com> | |
| 16 | 16 | Description: This file contains the currently connected and initialized |
| 17 | 17 | extensions. It can be one of: none, motionp, nunchuck, classic, |
| 18 | 18 | motionp+nunchuck, motionp+classic |
| @@ -20,3 +20,40 @@ Description: This file contains the currently connected and initialized · 1 unmodified line | ||
| 20 | 20 | the official Nintendo Nunchuck extension and classic is the |
| 21 | 21 | Nintendo Classic Controller extension. The motionp extension can |
| 22 | 22 | be combined with the other two. |
| 23 | + Starting with kernel-version 3.11 Motion Plus hotplugging is | |
| 24 | + supported and if detected, it's no longer reported as static | |
| 25 | + extension. You will get uevent notifications for the motion-plus | |
| 26 | + device then. | |
| 27 | + | |
| 28 | +What: /sys/bus/hid/drivers/wiimote/<dev>/devtype | |
| 29 | +Date: May 2013 | |
| 30 | +KernelVersion: 3.11 | |
| 31 | +Contact: David Herrmann <dh.herrmann@gmail.com> | |
| 32 | +Description: While a device is initialized by the wiimote driver, we perform | |
| 33 | + a device detection and signal a "change" uevent after it is | |
| 34 | + done. This file shows the detected device type. "pending" means | |
| 35 | + that the detection is still ongoing, "unknown" means, that the | |
| 36 | + device couldn't be detected or loaded. "generic" means, that the | |
| 37 | + device couldn't be detected but supports basic Wii Remote | |
| 38 | + features and can be used. | |
| 39 | + Other strings for each device-type are available and may be | |
| 40 | + added if new device-specific detections are added. | |
| 41 | + Currently supported are: | |
| 42 | + gen10: First Wii Remote generation | |
| 43 | + gen20: Second Wii Remote Plus generation (builtin MP) | |
| 44 | + balanceboard: Wii Balance Board | |
| 45 | + | |
| 46 | +What: /sys/bus/hid/drivers/wiimote/<dev>/bboard_calib | |
| 47 | +Date: May 2013 | |
| 48 | +KernelVersion: 3.11 | |
| 49 | +Contact: David Herrmann <dh.herrmann@gmail.com> | |
| 50 | +Description: This attribute is only provided if the device was detected as a | |
| 51 | + balance board. It provides a single line with 3 calibration | |
| 52 | + values for all 4 sensors. The values are separated by colons and | |
| 53 | + are each 2 bytes long (encoded as 4 digit hexadecimal value). | |
| 54 | + First, 0kg values for all 4 sensors are written, followed by the | |
| 55 | + 17kg values for all 4 sensors and last the 34kg values for all 4 | |
| 56 | + sensors. | |
| 57 | + Calibration data is already applied by the kernel to all input | |
| 58 | + values but may be used by user-space to perform other | |
| 59 | + transformations. | |
| @@ -217,6 +217,13 @@ config HID_ELECOM · 216 unmodified lines | ||
| 217 | 217 | ---help--- |
| 218 | 218 | Support for the ELECOM BM084 (bluetooth mouse). |
| 219 | 219 | |
| 220 | +config HID_ELO | |
| 221 | + tristate "ELO USB 4000/4500 touchscreen" | |
| 222 | + depends on USB_HID | |
| 223 | + ---help--- | |
| 224 | + Support for the ELO USB 4000/4500 touchscreens. Note that this is for | |
| 225 | + different devices than those handled by CONFIG_TOUCHSCREEN_USB_ELO. | |
| 226 | + | |
| 220 | 227 | config HID_EZKEY |
| 221 | 228 | tristate "Ezkey BTC 8193 keyboard" if EXPERT |
| 222 | 229 | depends on HID |
| @@ -231,6 +238,9 @@ config HID_HOLTEK · 8 unmodified lines | ||
| 231 | 238 | Support for Holtek based devices: |
| 232 | 239 | - Holtek On Line Grip based game controller |
| 233 | 240 | - Trust GXT 18 Gaming Keyboard |
| 241 | + - Sharkoon Drakonia / Perixx MX-2000 gaming mice | |
| 242 | + - Tracer Sniper TRM-503 / NOVA Gaming Slider X200 / | |
| 243 | + Zalman ZM-GM1 | |
| 234 | 244 | |
| 235 | 245 | config HOLTEK_FF |
| 236 | 246 | bool "Holtek On Line Grip force feedback support" |
| @@ -240,6 +250,12 @@ config HOLTEK_FF · 3 unmodified lines | ||
| 240 | 250 | Say Y here if you have a Holtek On Line Grip based game controller |
| 241 | 251 | and want to have force feedback support for it. |
| 242 | 252 | |
| 253 | +config HID_HUION | |
| 254 | + tristate "Huion tablets" | |
| 255 | + depends on USB_HID | |
| 256 | + ---help--- | |
| 257 | + Support for Huion 580 tablet. | |
| 258 | + | |
| 243 | 259 | config HID_KEYTOUCH |
| 244 | 260 | tristate "Keytouch HID devices" |
| 245 | 261 | depends on HID |
| @@ -561,15 +577,6 @@ config HID_PRIMAX · 315 unmodified lines | ||
| 561 | 577 | Support for Primax devices that are not fully compliant with the |
| 562 | 578 | HID standard. |
| 563 | 579 | |
| 564 | −config HID_PS3REMOTE | |
| 565 | − tristate "Sony PS3 BD Remote Control" | |
| 566 | − depends on HID | |
| 567 | − ---help--- | |
| 568 | − Support for the Sony PS3 Blue-ray Disk Remote Control and Logitech | |
| 569 | − Harmony Adapter for PS3, which connect over Bluetooth. | |
| 570 | − | |
| 571 | − Support for the 6-axis controllers is provided by HID_SONY. | |
| 572 | − | |
| 573 | 580 | config HID_ROCCAT |
| 574 | 581 | tristate "Roccat device support" |
| 575 | 582 | depends on USB_HID |
| @@ -594,12 +601,17 @@ config HID_SAMSUNG · 18 unmodified lines | ||
| 594 | 601 | Support for Samsung InfraRed remote control or keyboards. |
| 595 | 602 | |
| 596 | 603 | config HID_SONY |
| 597 | − tristate "Sony PS3 controller" | |
| 604 | + tristate "Sony PS2/3 accessories" | |
| 598 | 605 | depends on USB_HID |
| 606 | + depends on NEW_LEDS | |
| 607 | + depends on LEDS_CLASS | |
| 599 | 608 | ---help--- |
| 600 | − Support for Sony PS3 6-axis controllers. | |
| 609 | + Support for | |
| 601 | 610 | |
| 602 | − Support for the Sony PS3 BD Remote is provided by HID_PS3REMOTE. | |
| 611 | + * Sony PS3 6-axis controllers | |
| 612 | + * Buzz controllers | |
| 613 | + * Sony PS3 Blue-ray Disk Remote Control (Bluetooth) | |
| 614 | + * Logitech Harmony adapter for Sony Playstation 3 (Bluetooth) | |
| 603 | 615 | |
| 604 | 616 | config HID_SPEEDLINK |
| 605 | 617 | tristate "Speedlink VAD Cezanne mouse support" |
| @@ -707,22 +719,29 @@ config HID_WACOM · 101 unmodified lines | ||
| 707 | 719 | Support for Wacom Graphire Bluetooth and Intuos4 WL tablets. |
| 708 | 720 | |
| 709 | 721 | config HID_WIIMOTE |
| 710 | − tristate "Nintendo Wii Remote support" | |
| 722 | + tristate "Nintendo Wii / Wii U peripherals" | |
| 711 | 723 | depends on HID |
| 712 | 724 | depends on LEDS_CLASS |
| 713 | 725 | select POWER_SUPPLY |
| 714 | 726 | select INPUT_FF_MEMLESS |
| 715 | 727 | ---help--- |
| 716 | − Support for the Nintendo Wii Remote bluetooth device. | |
| 728 | + Support for Nintendo Wii and Wii U Bluetooth peripherals. Supported | |
| 729 | + devices are the Wii Remote and its extension devices, but also devices | |
| 730 | + based on the Wii Remote like the Wii U Pro Controller or the | |
| 731 | + Wii Balance Board. | |
| 717 | 732 | |
| 718 | −config HID_WIIMOTE_EXT | |
| 719 | − bool "Nintendo Wii Remote Extension support" | |
| 720 | − depends on HID_WIIMOTE | |
| 721 | − default HID_WIIMOTE | |
| 722 | − ---help--- | |
| 723 | − Support for extension controllers of the Nintendo Wii Remote. Say yes | |
| 724 | − here if you want to use the Nintendo Motion+, Nunchuck or Classic | |
| 725 | − extension controllers with your Wii Remote. | |
| 733 | + Support for all official Nintendo extensions is available, however, 3rd | |
| 734 | + party extensions might not be supported. Please report these devices to: | |
| 735 | + http://github.com/dvdhrm/xwiimote/issues | |
| 736 | + | |
| 737 | + Other Nintendo Wii U peripherals that are IEEE 802.11 based (including | |
| 738 | + the Wii U Gamepad) might be supported in the future. But currently | |
| 739 | + support is limited to Bluetooth based devices. | |
| 740 | + | |
| 741 | + If unsure, say N. | |
| 742 | + | |
| 743 | + To compile this driver as a module, choose M here: the | |
| 744 | + module will be called hid-wiimote. | |
| 726 | 745 | |
| 727 | 746 | config HID_ZEROPLUS |
| 728 | 747 | tristate "Zeroplus based game controller support" |
| @@ -28,10 +28,7 @@ ifdef CONFIG_LOGIWHEELS_FF · 27 unmodified lines | ||
| 28 | 28 | hid-logitech-y += hid-lg4ff.o |
| 29 | 29 | endif |
| 30 | 30 | |
| 31 | −hid-wiimote-y := hid-wiimote-core.o | |
| 32 | −ifdef CONFIG_HID_WIIMOTE_EXT | |
| 33 | − hid-wiimote-y += hid-wiimote-ext.o | |
| 34 | −endif | |
| 31 | +hid-wiimote-y := hid-wiimote-core.o hid-wiimote-modules.o | |
| 35 | 32 | ifdef CONFIG_DEBUG_FS |
| 36 | 33 | hid-wiimote-y += hid-wiimote-debug.o |
| 37 | 34 | endif |
| @@ -48,10 +45,13 @@ obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o · 10 unmodified lines | ||
| 48 | 45 | obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o |
| 49 | 46 | obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o |
| 50 | 47 | obj-$(CONFIG_HID_ELECOM) += hid-elecom.o |
| 48 | +obj-$(CONFIG_HID_ELO) += hid-elo.o | |
| 51 | 49 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o |
| 52 | 50 | obj-$(CONFIG_HID_GYRATION) += hid-gyration.o |
| 53 | 51 | obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o |
| 52 | +obj-$(CONFIG_HID_HOLTEK) += hid-holtek-mouse.o | |
| 54 | 53 | obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o |
| 54 | +obj-$(CONFIG_HID_HUION) += hid-huion.o | |
| 55 | 55 | obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o |
| 56 | 56 | obj-$(CONFIG_HID_ICADE) += hid-icade.o |
| 57 | 57 | obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o |
| @@ -92,7 +92,6 @@ hid-picolcd-y += hid-picolcd_debugfs.o · 34 unmodified lines | ||
| 92 | 92 | endif |
| 93 | 93 | |
| 94 | 94 | obj-$(CONFIG_HID_PRIMAX) += hid-primax.o |
| 95 | −obj-$(CONFIG_HID_PS3REMOTE) += hid-ps3remote.o | |
| 96 | 95 | obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ |
| 97 | 96 | hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ |
| 98 | 97 | hid-roccat-koneplus.o hid-roccat-konepure.o hid-roccat-kovaplus.o \ |
| @@ -1293,7 +1293,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i · 1292 unmodified lines | ||
| 1293 | 1293 | |
| 1294 | 1294 | if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) { |
| 1295 | 1295 | ret = hdrv->raw_event(hid, report, data, size); |
| 1296 | − if (ret != 0) { | |
| 1296 | + if (ret < 0) { | |
| 1297 | 1297 | ret = ret < 0 ? ret : 0; |
| 1298 | 1298 | goto unlock; |
| 1299 | 1299 | } |
| @@ -1573,6 +1573,8 @@ static const struct hid_device_id hid_have_special_driver[] = { · 273 unmodified lines | ||
| 1573 | 1573 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, |
| 1574 | 1574 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, |
| 1575 | 1575 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, |
| 1576 | + { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) }, | |
| 1577 | + { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0030) }, | |
| 1576 | 1578 | { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) }, |
| 1577 | 1579 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, |
| 1578 | 1580 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, |
| @@ -1584,10 +1586,14 @@ static const struct hid_device_id hid_have_special_driver[] = { · 5 unmodified lines | ||
| 1584 | 1586 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, |
| 1585 | 1587 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, |
| 1586 | 1588 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) }, |
| 1589 | + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) }, | |
| 1590 | + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) }, | |
| 1591 | + { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) }, | |
| 1587 | 1592 | { HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) }, |
| 1588 | 1593 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) }, |
| 1589 | 1594 | { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, |
| 1590 | 1595 | { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, |
| 1596 | + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) }, | |
| 1591 | 1597 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, |
| 1592 | 1598 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) }, |
| 1593 | 1599 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, |
| @@ -1680,6 +1686,8 @@ static const struct hid_device_id hid_have_special_driver[] = { · 86 unmodified lines | ||
| 1680 | 1686 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, |
| 1681 | 1687 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, |
| 1682 | 1688 | { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, |
| 1689 | + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) }, | |
| 1690 | + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) }, | |
| 1683 | 1691 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, |
| 1684 | 1692 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, |
| 1685 | 1693 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, |
| @@ -2042,6 +2050,8 @@ static const struct hid_device_id hid_ignore_list[] = { · 356 unmodified lines | ||
| 2042 | 2050 | { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) }, |
| 2043 | 2051 | { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) }, |
| 2044 | 2052 | { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) }, |
| 2053 | + { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_SPEAK_410) }, | |
| 2054 | + { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_SPEAK_510) }, | |
| 2045 | 2055 | { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) }, |
| 2046 | 2056 | { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) }, |
| 2047 | 2057 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) }, |
| @@ -0,0 +1,273 @@ | ||
| 1 | +/* | |
| 2 | + * HID driver for ELO usb touchscreen 4000/4500 | |
| 3 | + * | |
| 4 | + * Copyright (c) 2013 Jiri Slaby | |
| 5 | + * | |
| 6 | + * Data parsing taken from elousb driver by Vojtech Pavlik. | |
| 7 | + * | |
| 8 | + * This driver is licensed under the terms of GPLv2. | |
| 9 | + */ | |
| 10 | + | |
| 11 | +#include <linux/hid.h> | |
| 12 | +#include <linux/input.h> | |
| 13 | +#include <linux/module.h> | |
| 14 | +#include <linux/usb.h> | |
| 15 | +#include <linux/workqueue.h> | |
| 16 | + | |
| 17 | +#include "hid-ids.h" | |
| 18 | + | |
| 19 | +#define ELO_PERIODIC_READ_INTERVAL HZ | |
| 20 | +#define ELO_SMARTSET_CMD_TIMEOUT 2000 /* msec */ | |
| 21 | + | |
| 22 | +/* Elo SmartSet commands */ | |
| 23 | +#define ELO_FLUSH_SMARTSET_RESPONSES 0x02 /* Flush all pending smartset responses */ | |
| 24 | +#define ELO_SEND_SMARTSET_COMMAND 0x05 /* Send a smartset command */ | |
| 25 | +#define ELO_GET_SMARTSET_RESPONSE 0x06 /* Get a smartset response */ | |
| 26 | +#define ELO_DIAG 0x64 /* Diagnostics command */ | |
| 27 | +#define ELO_SMARTSET_PACKET_SIZE 8 | |
| 28 | + | |
| 29 | +struct elo_priv { | |
| 30 | + struct usb_device *usbdev; | |
| 31 | + struct delayed_work work; | |
| 32 | + unsigned char buffer[ELO_SMARTSET_PACKET_SIZE]; | |
| 33 | +}; | |
| 34 | + | |
| 35 | +static struct workqueue_struct *wq; | |
| 36 | +static bool use_fw_quirk = true; | |
| 37 | +module_param(use_fw_quirk, bool, S_IRUGO); | |
| 38 | +MODULE_PARM_DESC(use_fw_quirk, "Do periodic pokes for broken M firmwares (default = true)"); | |
| 39 | + | |
| 40 | +static void elo_input_configured(struct hid_device *hdev, | |
| 41 | + struct hid_input *hidinput) | |
| 42 | +{ | |
| 43 | + struct input_dev *input = hidinput->input; | |
| 44 | + | |
| 45 | + set_bit(BTN_TOUCH, input->keybit); | |
| 46 | + set_bit(ABS_PRESSURE, input->absbit); | |
| 47 | + input_set_abs_params(input, ABS_PRESSURE, 0, 256, 0, 0); | |
| 48 | +} | |
| 49 | + | |
| 50 | +static void elo_process_data(struct input_dev *input, const u8 *data, int size) | |
| 51 | +{ | |
| 52 | + int press; | |
| 53 | + | |
| 54 | + input_report_abs(input, ABS_X, (data[3] << 8) | data[2]); | |
| 55 | + input_report_abs(input, ABS_Y, (data[5] << 8) | data[4]); | |
| 56 | + | |
| 57 | + press = 0; | |
| 58 | + if (data[1] & 0x80) | |
| 59 | + press = (data[7] << 8) | data[6]; | |
| 60 | + input_report_abs(input, ABS_PRESSURE, press); | |
| 61 | + | |
| 62 | + if (data[1] & 0x03) { | |
| 63 | + input_report_key(input, BTN_TOUCH, 1); | |
| 64 | + input_sync(input); | |
| 65 | + } | |
| 66 | + | |
| 67 | + if (data[1] & 0x04) | |
| 68 | + input_report_key(input, BTN_TOUCH, 0); | |
| 69 | + | |
| 70 | + input_sync(input); | |
| 71 | +} | |
| 72 | + | |
| 73 | +static int elo_raw_event(struct hid_device *hdev, struct hid_report *report, | |
| 74 | + u8 *data, int size) | |
| 75 | +{ | |
| 76 | + struct hid_input *hidinput; | |
| 77 | + | |
| 78 | + if (!(hdev->claimed & HID_CLAIMED_INPUT) || list_empty(&hdev->inputs)) | |
| 79 | + return 0; | |
| 80 | + | |
| 81 | + hidinput = list_first_entry(&hdev->inputs, struct hid_input, list); | |
| 82 | + | |
| 83 | + switch (report->id) { | |
| 84 | + case 0: | |
| 85 | + if (data[0] == 'T') { /* Mandatory ELO packet marker */ | |
| 86 | + elo_process_data(hidinput->input, data, size); | |
| 87 | + return 1; | |
| 88 | + } | |
| 89 | + break; | |
| 90 | + default: /* unknown report */ | |
| 91 | + /* Unknown report type; pass upstream */ | |
| 92 | + hid_info(hdev, "unknown report type %d\n", report->id); | |
| 93 | + break; | |
| 94 | + } | |
| 95 | + | |
| 96 | + return 0; | |
| 97 | +} | |
| 98 | + | |
| 99 | +static int elo_smartset_send_get(struct usb_device *dev, u8 command, | |
| 100 | + void *data) | |
| 101 | +{ | |
| 102 | + unsigned int pipe; | |
| 103 | + u8 dir; | |
| 104 | + | |
| 105 | + if (command == ELO_SEND_SMARTSET_COMMAND) { | |
| 106 | + pipe = usb_sndctrlpipe(dev, 0); | |
| 107 | + dir = USB_DIR_OUT; | |
| 108 | + } else if (command == ELO_GET_SMARTSET_RESPONSE) { | |
| 109 | + pipe = usb_rcvctrlpipe(dev, 0); | |
| 110 | + dir = USB_DIR_IN; | |
| 111 | + } else | |
| 112 | + return -EINVAL; | |
| 113 | + | |
| 114 | + return usb_control_msg(dev, pipe, command, | |
| 115 | + dir | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
| 116 | + 0, 0, data, ELO_SMARTSET_PACKET_SIZE, | |
| 117 | + ELO_SMARTSET_CMD_TIMEOUT); | |
| 118 | +} | |
| 119 | + | |
| 120 | +static int elo_flush_smartset_responses(struct usb_device *dev) | |
| 121 | +{ | |
| 122 | + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | |
| 123 | + ELO_FLUSH_SMARTSET_RESPONSES, | |
| 124 | + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
| 125 | + 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); | |
| 126 | +} | |
| 127 | + | |
| 128 | +static void elo_work(struct work_struct *work) | |
| 129 | +{ | |
| 130 | + struct elo_priv *priv = container_of(work, struct elo_priv, work.work); | |
| 131 | + struct usb_device *dev = priv->usbdev; | |
| 132 | + unsigned char *buffer = priv->buffer; | |
| 133 | + int ret; | |
| 134 | + | |
| 135 | + ret = elo_flush_smartset_responses(dev); | |
| 136 | + if (ret < 0) { | |
| 137 | + dev_err(&dev->dev, "initial FLUSH_SMARTSET_RESPONSES failed, error %d\n", | |
| 138 | + ret); | |
| 139 | + goto fail; | |
| 140 | + } | |
| 141 | + | |
| 142 | + /* send Diagnostics command */ | |
| 143 | + *buffer = ELO_DIAG; | |
| 144 | + ret = elo_smartset_send_get(dev, ELO_SEND_SMARTSET_COMMAND, buffer); | |
| 145 | + if (ret < 0) { | |
| 146 | + dev_err(&dev->dev, "send Diagnostics Command failed, error %d\n", | |
| 147 | + ret); | |
| 148 | + goto fail; | |
| 149 | + } | |
| 150 | + | |
| 151 | + /* get the result */ | |
| 152 | + ret = elo_smartset_send_get(dev, ELO_GET_SMARTSET_RESPONSE, buffer); | |
| 153 | + if (ret < 0) { | |
| 154 | + dev_err(&dev->dev, "get Diagnostics Command response failed, error %d\n", | |
| 155 | + ret); | |
| 156 | + goto fail; | |
| 157 | + } | |
| 158 | + | |
| 159 | + /* read the ack */ | |
| 160 | + if (*buffer != 'A') { | |
| 161 | + ret = elo_smartset_send_get(dev, ELO_GET_SMARTSET_RESPONSE, | |
| 162 | + buffer); | |
| 163 | + if (ret < 0) { | |
| 164 | + dev_err(&dev->dev, "get acknowledge response failed, error %d\n", | |
| 165 | + ret); | |
| 166 | + goto fail; | |
| 167 | + } | |
| 168 | + } | |
| 169 | + | |
| 170 | +fail: | |
| 171 | + ret = elo_flush_smartset_responses(dev); | |
| 172 | + if (ret < 0) | |
| 173 | + dev_err(&dev->dev, "final FLUSH_SMARTSET_RESPONSES failed, error %d\n", | |
| 174 | + ret); | |
| 175 | + queue_delayed_work(wq, &priv->work, ELO_PERIODIC_READ_INTERVAL); | |
| 176 | +} | |
| 177 | + | |
| 178 | +/* | |
| 179 | + * Not all Elo devices need the periodic HID descriptor reads. | |
| 180 | + * Only firmware version M needs this. | |
| 181 | + */ | |
| 182 | +static bool elo_broken_firmware(struct usb_device *dev) | |
| 183 | +{ | |
| 184 | + return use_fw_quirk && le16_to_cpu(dev->descriptor.bcdDevice) == 0x10d; | |
| 185 | +} | |
| 186 | + | |
| 187 | +static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id) | |
| 188 | +{ | |
| 189 | + struct elo_priv *priv; | |
| 190 | + int ret; | |
| 191 | + | |
| 192 | + priv = kzalloc(sizeof(*priv), GFP_KERNEL); | |
| 193 | + if (!priv) | |
| 194 | + return -ENOMEM; | |
| 195 | + | |
| 196 | + INIT_DELAYED_WORK(&priv->work, elo_work); | |
| 197 | + priv->usbdev = interface_to_usbdev(to_usb_interface(hdev->dev.parent)); | |
| 198 | + | |
| 199 | + hid_set_drvdata(hdev, priv); | |
| 200 | + | |
| 201 | + ret = hid_parse(hdev); | |
| 202 | + if (ret) { | |
| 203 | + hid_err(hdev, "parse failed\n"); | |
| 204 | + goto err_free; | |
| 205 | + } | |
| 206 | + | |
| 207 | + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | |
| 208 | + if (ret) { | |
| 209 | + hid_err(hdev, "hw start failed\n"); | |
| 210 | + goto err_free; | |
| 211 | + } | |
| 212 | + | |
| 213 | + if (elo_broken_firmware(priv->usbdev)) { | |
| 214 | + hid_info(hdev, "broken firmware found, installing workaround\n"); | |
| 215 | + queue_delayed_work(wq, &priv->work, ELO_PERIODIC_READ_INTERVAL); | |
| 216 | + } | |
| 217 | + | |
| 218 | + return 0; | |
| 219 | +err_free: | |
| 220 | + kfree(priv); | |
| 221 | + return ret; | |
| 222 | +} | |
| 223 | + | |
| 224 | +static void elo_remove(struct hid_device *hdev) | |
| 225 | +{ | |
| 226 | + struct elo_priv *priv = hid_get_drvdata(hdev); | |
| 227 | + | |
| 228 | + hid_hw_stop(hdev); | |
| 229 | + flush_workqueue(wq); | |
| 230 | + kfree(priv); | |
| 231 | +} | |
| 232 | + | |
| 233 | +static const struct hid_device_id elo_devices[] = { | |
| 234 | + { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009), }, | |
| 235 | + { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0030), }, | |
| 236 | + { } | |
| 237 | +}; | |
| 238 | +MODULE_DEVICE_TABLE(hid, elo_devices); | |
| 239 | + | |
| 240 | +static struct hid_driver elo_driver = { | |
| 241 | + .name = "elo", | |
| 242 | + .id_table = elo_devices, | |
| 243 | + .probe = elo_probe, | |
| 244 | + .remove = elo_remove, | |
| 245 | + .raw_event = elo_raw_event, | |
| 246 | + .input_configured = elo_input_configured, | |
| 247 | +}; | |
| 248 | + | |
| 249 | +static int __init elo_driver_init(void) | |
| 250 | +{ | |
| 251 | + int ret; | |
| 252 | + | |
| 253 | + wq = create_singlethread_workqueue("elousb"); | |
| 254 | + if (!wq) | |
| 255 | + return -ENOMEM; | |
| 256 | + | |
| 257 | + ret = hid_register_driver(&elo_driver); | |
| 258 | + if (ret) | |
| 259 | + destroy_workqueue(wq); | |
| 260 | + | |
| 261 | + return ret; | |
| 262 | +} | |
| 263 | +module_init(elo_driver_init); | |
| 264 | + | |
| 265 | +static void __exit elo_driver_exit(void) | |
| 266 | +{ | |
| 267 | + hid_unregister_driver(&elo_driver); | |
| 268 | + destroy_workqueue(wq); | |
| 269 | +} | |
| 270 | +module_exit(elo_driver_exit); | |
| 271 | + | |
| 272 | +MODULE_AUTHOR("Jiri Slaby <jslaby@suse.cz>"); | |
| 273 | +MODULE_LICENSE("GPL"); | |
| @@ -0,0 +1,77 @@ | ||
| 1 | +/* | |
| 2 | + * HID driver for Holtek gaming mice | |
| 3 | + * Copyright (c) 2013 Christian Ohm | |
| 4 | + * Heavily inspired by various other HID drivers that adjust the report | |
| 5 | + * descriptor. | |
| 6 | +*/ | |
| 7 | + | |
| 8 | +/* | |
| 9 | + * This program is free software; you can redistribute it and/or modify it | |
| 10 | + * under the terms of the GNU General Public License as published by the Free | |
| 11 | + * Software Foundation; either version 2 of the License, or (at your option) | |
| 12 | + * any later version. | |
| 13 | + */ | |
| 14 | + | |
| 15 | +#include <linux/hid.h> | |
| 16 | +#include <linux/module.h> | |
| 17 | +#include <linux/usb.h> | |
| 18 | + | |
| 19 | +#include "hid-ids.h" | |
| 20 | + | |
| 21 | +/* | |
| 22 | + * The report descriptor of some Holtek based gaming mice specifies an | |
| 23 | + * excessively large number of consumer usages (2^15), which is more than | |
| 24 | + * HID_MAX_USAGES. This prevents proper parsing of the report descriptor. | |
| 25 | + * | |
| 26 | + * This driver fixes the report descriptor for: | |
| 27 | + * - USB ID 04d9:a067, sold as Sharkoon Drakonia and Perixx MX-2000 | |
| 28 | + * - USB ID 04d9:a04a, sold as Tracer Sniper TRM-503, NOVA Gaming Slider X200 | |
| 29 | + * and Zalman ZM-GM1 | |
| 30 | + */ | |
| 31 | + | |
| 32 | +static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |
| 33 | + unsigned int *rsize) | |
| 34 | +{ | |
| 35 | + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | |
| 36 | + | |
| 37 | + if (intf->cur_altsetting->desc.bInterfaceNumber == 1) { | |
| 38 | + /* Change usage maximum and logical maximum from 0x7fff to | |
| 39 | + * 0x2fff, so they don't exceed HID_MAX_USAGES */ | |
| 40 | + switch (hdev->product) { | |
| 41 | + case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067: | |
| 42 | + if (*rsize >= 122 && rdesc[115] == 0xff && rdesc[116] == 0x7f | |
| 43 | + && rdesc[120] == 0xff && rdesc[121] == 0x7f) { | |
| 44 | + hid_info(hdev, "Fixing up report descriptor\n"); | |
| 45 | + rdesc[116] = rdesc[121] = 0x2f; | |
| 46 | + } | |
| 47 | + break; | |
| 48 | + case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A: | |
| 49 | + if (*rsize >= 113 && rdesc[106] == 0xff && rdesc[107] == 0x7f | |
| 50 | + && rdesc[111] == 0xff && rdesc[112] == 0x7f) { | |
| 51 | + hid_info(hdev, "Fixing up report descriptor\n"); | |
| 52 | + rdesc[107] = rdesc[112] = 0x2f; | |
| 53 | + } | |
| 54 | + break; | |
| 55 | + } | |
| 56 | + | |
| 57 | + } | |
| 58 | + return rdesc; | |
| 59 | +} | |
| 60 | + | |
| 61 | +static const struct hid_device_id holtek_mouse_devices[] = { | |
| 62 | + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, | |
| 63 | + USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) }, | |
| 64 | + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, | |
| 65 | + USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) }, | |
| 66 | + { } | |
| 67 | +}; | |
| 68 | +MODULE_DEVICE_TABLE(hid, holtek_mouse_devices); | |
| 69 | + | |
| 70 | +static struct hid_driver holtek_mouse_driver = { | |
| 71 | + .name = "holtek_mouse", | |
| 72 | + .id_table = holtek_mouse_devices, | |
| 73 | + .report_fixup = holtek_mouse_report_fixup, | |
| 74 | +}; | |
| 75 | + | |
| 76 | +module_hid_driver(holtek_mouse_driver); | |
| 77 | +MODULE_LICENSE("GPL"); | |
| @@ -0,0 +1,177 @@ | ||
| 1 | +/* | |
| 2 | + * HID driver for Huion devices not fully compliant with HID standard | |
| 3 | + * | |
| 4 | + * Copyright (c) 2013 Martin Rusko | |
| 5 | + */ | |
| 6 | + | |
| 7 | +/* | |
| 8 | + * This program is free software; you can redistribute it and/or modify it | |
| 9 | + * under the terms of the GNU General Public License as published by the Free | |
| 10 | + * Software Foundation; either version 2 of the License, or (at your option) | |
| 11 | + * any later version. | |
| 12 | + */ | |
| 13 | + | |
| 14 | +#include <linux/device.h> | |
| 15 | +#include <linux/hid.h> | |
| 16 | +#include <linux/module.h> | |
| 17 | +#include <linux/usb.h> | |
| 18 | +#include "usbhid/usbhid.h" | |
| 19 | + | |
| 20 | +#include "hid-ids.h" | |
| 21 | + | |
| 22 | +/* Original Huion 580 report descriptor size */ | |
| 23 | +#define HUION_580_RDESC_ORIG_SIZE 177 | |
| 24 | + | |
| 25 | +/* Fixed Huion 580 report descriptor */ | |
| 26 | +static __u8 huion_580_rdesc_fixed[] = { | |
| 27 | + 0x05, 0x0D, /* Usage Page (Digitizer), */ | |
| 28 | + 0x09, 0x02, /* Usage (Pen), */ | |
| 29 | + 0xA1, 0x01, /* Collection (Application), */ | |
| 30 | + 0x85, 0x07, /* Report ID (7), */ | |
| 31 | + 0x09, 0x20, /* Usage (Stylus), */ | |
| 32 | + 0xA0, /* Collection (Physical), */ | |
| 33 | + 0x14, /* Logical Minimum (0), */ | |
| 34 | + 0x25, 0x01, /* Logical Maximum (1), */ | |
| 35 | + 0x75, 0x01, /* Report Size (1), */ | |
| 36 | + 0x09, 0x42, /* Usage (Tip Switch), */ | |
| 37 | + 0x09, 0x44, /* Usage (Barrel Switch), */ | |
| 38 | + 0x09, 0x46, /* Usage (Tablet Pick), */ | |
| 39 | + 0x95, 0x03, /* Report Count (3), */ | |
| 40 | + 0x81, 0x02, /* Input (Variable), */ | |
| 41 | + 0x95, 0x03, /* Report Count (3), */ | |
| 42 | + 0x81, 0x03, /* Input (Constant, Variable), */ | |
| 43 | + 0x09, 0x32, /* Usage (In Range), */ | |
| 44 | + 0x95, 0x01, /* Report Count (1), */ | |
| 45 | + 0x81, 0x02, /* Input (Variable), */ | |
| 46 | + 0x95, 0x01, /* Report Count (1), */ | |
| 47 | + 0x81, 0x03, /* Input (Constant, Variable), */ | |
| 48 | + 0x75, 0x10, /* Report Size (16), */ | |
| 49 | + 0x95, 0x01, /* Report Count (1), */ | |
| 50 | + 0xA4, /* Push, */ | |
| 51 | + 0x05, 0x01, /* Usage Page (Desktop), */ | |
| 52 | + 0x65, 0x13, /* Unit (Inch), */ | |
| 53 | + 0x55, 0xFD, /* Unit Exponent (-3), */ | |
| 54 | + 0x34, /* Physical Minimum (0), */ | |
| 55 | + 0x09, 0x30, /* Usage (X), */ | |
| 56 | + 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */ | |
| 57 | + 0x26, 0x00, 0x7D, /* Logical Maximum (32000), */ | |
| 58 | + 0x81, 0x02, /* Input (Variable), */ | |
| 59 | + 0x09, 0x31, /* Usage (Y), */ | |
| 60 | + 0x46, 0x88, 0x13, /* Physical Maximum (5000), */ | |
| 61 | + 0x26, 0x20, 0x4E, /* Logical Maximum (20000), */ | |
| 62 | + 0x81, 0x02, /* Input (Variable), */ | |
| 63 | + 0xB4, /* Pop, */ | |
| 64 | + 0x09, 0x30, /* Usage (Tip Pressure), */ | |
| 65 | + 0x26, 0xFF, 0x07, /* Logical Maximum (2047), */ | |
| 66 | + 0x81, 0x02, /* Input (Variable), */ | |
| 67 | + 0xC0, /* End Collection, */ | |
| 68 | + 0xC0 /* End Collection */ | |
| 69 | +}; | |
| 70 | + | |
| 71 | +static __u8 *huion_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |
| 72 | + unsigned int *rsize) | |
| 73 | +{ | |
| 74 | + switch (hdev->product) { | |
| 75 | + case USB_DEVICE_ID_HUION_580: | |
| 76 | + if (*rsize == HUION_580_RDESC_ORIG_SIZE) { | |
| 77 | + rdesc = huion_580_rdesc_fixed; | |
| 78 | + *rsize = sizeof(huion_580_rdesc_fixed); | |
| 79 | + } | |
| 80 | + break; | |
| 81 | + } | |
| 82 | + return rdesc; | |
| 83 | +} | |
| 84 | + | |
| 85 | +/** | |
| 86 | + * Enable fully-functional tablet mode by reading special string | |
| 87 | + * descriptor. | |
| 88 | + * | |
| 89 | + * @hdev: HID device | |
| 90 | + * | |
| 91 | + * The specific string descriptor and data were discovered by sniffing | |
| 92 | + * the Windows driver traffic. | |
| 93 | + */ | |
| 94 | +static int huion_tablet_enable(struct hid_device *hdev) | |
| 95 | +{ | |
| 96 | + int rc; | |
| 97 | + char buf[22]; | |
| 98 | + | |
| 99 | + rc = usb_string(hid_to_usb_dev(hdev), 0x64, buf, sizeof(buf)); | |
| 100 | + if (rc < 0) | |
| 101 | + return rc; | |
| 102 | + | |
| 103 | + return 0; | |
| 104 | +} | |
| 105 | + | |
| 106 | +static int huion_probe(struct hid_device *hdev, const struct hid_device_id *id) | |
| 107 | +{ | |
| 108 | + int ret; | |
| 109 | + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | |
| 110 | + | |
| 111 | + /* Ignore interfaces 1 (mouse) and 2 (keyboard) for Huion 580 tablet, | |
| 112 | + * as they are not used | |
| 113 | + */ | |
| 114 | + switch (id->product) { | |
| 115 | + case USB_DEVICE_ID_HUION_580: | |
| 116 | + if (intf->cur_altsetting->desc.bInterfaceNumber != 0x00) | |
| 117 | + return -ENODEV; | |
| 118 | + break; | |
| 119 | + } | |
| 120 | + | |
| 121 | + ret = hid_parse(hdev); | |
| 122 | + if (ret) { | |
| 123 | + hid_err(hdev, "parse failed\n"); | |
| 124 | + goto err; | |
| 125 | + } | |
| 126 | + | |
| 127 | + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | |
| 128 | + if (ret) { | |
| 129 | + hid_err(hdev, "hw start failed\n"); | |
| 130 | + goto err; | |
| 131 | + } | |
| 132 | + | |
| 133 | + switch (id->product) { | |
| 134 | + case USB_DEVICE_ID_HUION_580: | |
| 135 | + ret = huion_tablet_enable(hdev); | |
| 136 | + if (ret) { | |
| 137 | + hid_err(hdev, "tablet enabling failed\n"); | |
| 138 | + goto enabling_err; | |
| 139 | + } | |
| 140 | + break; | |
| 141 | + } | |
| 142 | + | |
| 143 | + return 0; | |
| 144 | +enabling_err: | |
| 145 | + hid_hw_stop(hdev); | |
| 146 | +err: | |
| 147 | + return ret; | |
| 148 | +} | |
| 149 | + | |
| 150 | +static int huion_raw_event(struct hid_device *hdev, struct hid_report *report, | |
| 151 | + u8 *data, int size) | |
| 152 | +{ | |
| 153 | + /* If this is a pen input report then invert the in-range bit */ | |
| 154 | + if (report->type == HID_INPUT_REPORT && report->id == 0x07 && size >= 2) | |
| 155 | + data[1] ^= 0x40; | |
| 156 | + | |
| 157 | + return 0; | |
| 158 | +} | |
| 159 | + | |
| 160 | +static const struct hid_device_id huion_devices[] = { | |
| 161 | + { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) }, | |
| 162 | + { } | |
| 163 | +}; | |
| 164 | +MODULE_DEVICE_TABLE(hid, huion_devices); | |
| 165 | + | |
| 166 | +static struct hid_driver huion_driver = { | |
| 167 | + .name = "huion", | |
| 168 | + .id_table = huion_devices, | |
| 169 | + .probe = huion_probe, | |
| 170 | + .report_fixup = huion_report_fixup, | |
| 171 | + .raw_event = huion_raw_event, | |
| 172 | +}; | |
| 173 | +module_hid_driver(huion_driver); | |
| 174 | + | |
| 175 | +MODULE_AUTHOR("Martin Rusko"); | |
| 176 | +MODULE_DESCRIPTION("Huion HID driver"); | |
| 177 | +MODULE_LICENSE("GPL"); | |
| @@ -199,13 +199,11 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, · 198 unmodified lines | ||
| 199 | 199 | if (desc->bLength == 0) |
| 200 | 200 | goto cleanup; |
| 201 | 201 | |
| 202 | − input_device->hid_desc = kzalloc(desc->bLength, GFP_ATOMIC); | |
| 202 | + input_device->hid_desc = kmemdup(desc, desc->bLength, GFP_ATOMIC); | |
| 203 | 203 | |
| 204 | 204 | if (!input_device->hid_desc) |
| 205 | 205 | goto cleanup; |
| 206 | 206 | |
| 207 | − memcpy(input_device->hid_desc, desc, desc->bLength); | |
| 208 | − | |
| 209 | 207 | input_device->report_desc_size = desc->desc[0].wDescriptorLength; |
| 210 | 208 | if (input_device->report_desc_size == 0) { |
| 211 | 209 | input_device->dev_info_status = -EINVAL; |
| @@ -248,6 +248,9 @@ · 247 unmodified lines | ||
| 248 | 248 | #define USB_DEVICE_ID_CYPRESS_BARCODE_4 0xed81 |
| 249 | 249 | #define USB_DEVICE_ID_CYPRESS_TRUETOUCH 0xc001 |
| 250 | 250 | |
| 251 | +#define USB_VENDOR_ID_DATA_MODUL 0x7374 | |
| 252 | +#define USB_VENDOR_ID_DATA_MODUL_EASYMAXTOUCH 0x1201 | |
| 253 | + | |
| 251 | 254 | #define USB_VENDOR_ID_DEALEXTREAME 0x10c5 |
| 252 | 255 | #define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a |
| 253 | 256 | |
| @@ -272,16 +275,15 @@ · 18 unmodified lines | ||
| 272 | 275 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_725E 0x725e |
| 273 | 276 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7262 0x7262 |
| 274 | 277 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B 0x726b |
| 275 | −#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72AA 0x72aa | |
| 276 | 278 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1 0x72a1 |
| 279 | +#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72AA 0x72aa | |
| 280 | +#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4 0x72c4 | |
| 281 | +#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72D0 0x72d0 | |
| 277 | 282 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA 0x72fa |
| 278 | 283 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302 0x7302 |
| 279 | 284 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349 0x7349 |
| 280 | 285 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7 0x73f7 |
| 281 | 286 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001 |
| 282 | −#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224 0x7224 | |
| 283 | −#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72D0 0x72d0 | |
| 284 | −#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4 0x72c4 | |
| 285 | 287 | |
| 286 | 288 | #define USB_VENDOR_ID_ELECOM 0x056e |
| 287 | 289 | #define USB_DEVICE_ID_ELECOM_BM084 0x0061 |
| @@ -425,6 +427,9 @@ · 137 unmodified lines | ||
| 425 | 427 | #define USB_DEVICE_ID_UGCI_FLYING 0x0020 |
| 426 | 428 | #define USB_DEVICE_ID_UGCI_FIGHTING 0x0030 |
| 427 | 429 | |
| 430 | +#define USB_VENDOR_ID_HUION 0x256c | |
| 431 | +#define USB_DEVICE_ID_HUION_580 0x006e | |
| 432 | + | |
| 428 | 433 | #define USB_VENDOR_ID_IDEACOM 0x1cb6 |
| 429 | 434 | #define USB_DEVICE_ID_IDEACOM_IDC6650 0x6650 |
| 430 | 435 | #define USB_DEVICE_ID_IDEACOM_IDC6651 0x6651 |
| @@ -440,6 +445,8 @@ · 9 unmodified lines | ||
| 440 | 445 | |
| 441 | 446 | #define USB_VENDOR_ID_HOLTEK_ALT 0x04d9 |
| 442 | 447 | #define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD 0xa055 |
| 448 | +#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067 0xa067 | |
| 449 | +#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A 0xa04a | |
| 443 | 450 | |
| 444 | 451 | #define USB_VENDOR_ID_IMATION 0x0718 |
| 445 | 452 | #define USB_DEVICE_ID_DISC_STAKKA 0xd000 |
| @@ -447,6 +454,10 @@ · 1 unmodified line | ||
| 447 | 454 | #define USB_VENDOR_ID_IRTOUCHSYSTEMS 0x6615 |
| 448 | 455 | #define USB_DEVICE_ID_IRTOUCH_INFRARED_USB 0x0070 |
| 449 | 456 | |
| 457 | +#define USB_VENDOR_ID_JABRA 0x0b0e | |
| 458 | +#define USB_DEVICE_ID_JABRA_SPEAK_410 0x0412 | |
| 459 | +#define USB_DEVICE_ID_JABRA_SPEAK_510 0x0420 | |
| 460 | + | |
| 450 | 461 | #define USB_VENDOR_ID_JESS 0x0c45 |
| 451 | 462 | #define USB_DEVICE_ID_JESS_YUREX 0x1010 |
| 452 | 463 | |
| @@ -467,6 +478,7 @@ · 14 unmodified lines | ||
| 467 | 478 | |
| 468 | 479 | #define USB_VENDOR_ID_KYE 0x0458 |
| 469 | 480 | #define USB_DEVICE_ID_KYE_ERGO_525V 0x0087 |
| 481 | +#define USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE 0x0138 | |
| 470 | 482 | #define USB_DEVICE_ID_KYE_GPEN_560 0x5003 |
| 471 | 483 | #define USB_DEVICE_ID_KYE_EASYPEN_I405X 0x5010 |
| 472 | 484 | #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X 0x5011 |
| @@ -734,6 +746,8 @@ · 261 unmodified lines | ||
| 734 | 746 | #define USB_DEVICE_ID_SONY_PS3_BDREMOTE 0x0306 |
| 735 | 747 | #define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 |
| 736 | 748 | #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f |
| 749 | +#define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002 | |
| 750 | +#define USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER 0x1000 | |
| 737 | 751 | |
| 738 | 752 | #define USB_VENDOR_ID_SOUNDGRAPH 0x15c2 |
| 739 | 753 | #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034 |
| @@ -354,10 +354,10 @@ static int hidinput_get_battery_property(struct power_supply *psy, · 353 unmodified lines | ||
| 354 | 354 | dev->battery_report_type); |
| 355 | 355 | |
| 356 | 356 | if (ret != 2) { |
| 357 | − if (ret >= 0) | |
| 358 | − ret = -EINVAL; | |
| 357 | + ret = -ENODATA; | |
| 359 | 358 | break; |
| 360 | 359 | } |
| 360 | + ret = 0; | |
| 361 | 361 | |
| 362 | 362 | if (dev->battery_min < dev->battery_max && |
| 363 | 363 | buf[1] >= dev->battery_min && |
| @@ -1042,9 +1042,14 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct · 678 unmodified lines | ||
| 1042 | 1042 | |
| 1043 | 1043 | /* |
| 1044 | 1044 | * Ignore out-of-range values as per HID specification, |
| 1045 | − * section 5.10 and 6.2.25 | |
| 1045 | + * section 5.10 and 6.2.25. | |
| 1046 | + * | |
| 1047 | + * The logical_minimum < logical_maximum check is done so that we | |
| 1048 | + * don't unintentionally discard values sent by devices which | |
| 1049 | + * don't specify logical min and max. | |
| 1046 | 1050 | */ |
| 1047 | 1051 | if ((field->flags & HID_MAIN_ITEM_VARIABLE) && |
| 1052 | + (field->logical_minimum < field->logical_maximum) && | |
| 1048 | 1053 | (value < field->logical_minimum || |
| 1049 | 1054 | value > field->logical_maximum)) { |
| 1050 | 1055 | dbg_hid("Ignoring out-of-range value %x\n", value); |
| @@ -314,6 +314,25 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, · 313 unmodified lines | ||
| 314 | 314 | *rsize = sizeof(easypen_m610x_rdesc_fixed); |
| 315 | 315 | } |
| 316 | 316 | break; |
| 317 | + case USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE: | |
| 318 | + /* | |
| 319 | + * the fixup that need to be done: | |
| 320 | + * - change Usage Maximum in the Comsumer Control | |
| 321 | + * (report ID 3) to a reasonable value | |
| 322 | + */ | |
| 323 | + if (*rsize >= 135 && | |
| 324 | + /* Usage Page (Consumer Devices) */ | |
| 325 | + rdesc[104] == 0x05 && rdesc[105] == 0x0c && | |
| 326 | + /* Usage (Consumer Control) */ | |
| 327 | + rdesc[106] == 0x09 && rdesc[107] == 0x01 && | |
| 328 | + /* Usage Maximum > 12287 */ | |
| 329 | + rdesc[114] == 0x2a && rdesc[116] > 0x2f) { | |
| 330 | + hid_info(hdev, | |
| 331 | + "fixing up Genius Gila Gaming Mouse " | |
| 332 | + "report descriptor\n"); | |
| 333 | + rdesc[116] = 0x2f; | |
| 334 | + } | |
| 335 | + break; | |
| 317 | 336 | } |
| 318 | 337 | return rdesc; |
| 319 | 338 | } |
| @@ -407,6 +426,8 @@ static const struct hid_device_id kye_devices[] = { · 87 unmodified lines | ||
| 407 | 426 | USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, |
| 408 | 427 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, |
| 409 | 428 | USB_DEVICE_ID_KYE_EASYPEN_M610X) }, |
| 429 | + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, | |
| 430 | + USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) }, | |
| 410 | 431 | { } |
| 411 | 432 | }; |
| 412 | 433 | MODULE_DEVICE_TABLE(hid, kye_devices); |
| @@ -1111,6 +1111,11 @@ static const struct hid_device_id mt_devices[] = { · 1110 unmodified lines | ||
| 1111 | 1111 | HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, |
| 1112 | 1112 | USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, |
| 1113 | 1113 | |
| 1114 | + /* Data Modul easyMaxTouch */ | |
| 1115 | + { .driver_data = MT_CLS_DEFAULT, | |
| 1116 | + MT_USB_DEVICE(USB_VENDOR_ID_DATA_MODUL, | |
| 1117 | + USB_VENDOR_ID_DATA_MODUL_EASYMAXTOUCH) }, | |
| 1118 | + | |
| 1114 | 1119 | /* eGalax devices (resistive) */ |
| 1115 | 1120 | { .driver_data = MT_CLS_EGALAX, |
| 1116 | 1121 | MT_USB_DEVICE(USB_VENDOR_ID_DWAV, |
| @@ -1120,33 +1125,39 @@ static const struct hid_device_id mt_devices[] = { · 3 unmodified lines | ||
| 1120 | 1125 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) }, |
| 1121 | 1126 | |
| 1122 | 1127 | /* eGalax devices (capacitive) */ |
| 1123 | − { .driver_data = MT_CLS_EGALAX, | |
| 1124 | − MT_USB_DEVICE(USB_VENDOR_ID_DWAV, | |
| 1125 | − USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) }, | |
| 1126 | 1128 | { .driver_data = MT_CLS_EGALAX_SERIAL, |
| 1127 | 1129 | MT_USB_DEVICE(USB_VENDOR_ID_DWAV, |
| 1128 | 1130 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7207) }, |
| 1129 | − { .driver_data = MT_CLS_EGALAX_SERIAL, | |
| 1131 | + { .driver_data = MT_CLS_EGALAX, | |
| 1130 | 1132 | MT_USB_DEVICE(USB_VENDOR_ID_DWAV, |
| 1131 | − USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_725E) }, | |
| 1133 | + USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) }, | |
| 1132 | 1134 | { .driver_data = MT_CLS_EGALAX_SERIAL, |
| 1133 | 1135 | MT_USB_DEVICE(USB_VENDOR_ID_DWAV, |
| 1134 | 1136 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224) }, |
| 1135 | 1137 | { .driver_data = MT_CLS_EGALAX_SERIAL, |
| 1136 | 1138 | MT_USB_DEVICE(USB_VENDOR_ID_DWAV, |
| 1137 | 1139 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_722A) }, |
| 1138 | − { .driver_data = MT_CLS_EGALAX, | |
| 1140 | + { .driver_data = MT_CLS_EGALAX_SERIAL, | |
| 1139 | 1141 | MT_USB_DEVICE(USB_VENDOR_ID_DWAV, |
| 1140 | − USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) }, | |
| 1142 | + USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_725E) }, | |
| 1141 | 1143 | { .driver_data = MT_CLS_EGALAX_SERIAL, |
| 1142 | 1144 | MT_USB_DEVICE(USB_VENDOR_ID_DWAV, |
| 1143 | 1145 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7262) }, |
| 1146 | + { .driver_data = MT_CLS_EGALAX, | |
| 1147 | + MT_USB_DEVICE(USB_VENDOR_ID_DWAV, | |
| 1148 | + USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) }, | |
| 1144 | 1149 | { .driver_data = MT_CLS_EGALAX, |
| 1145 | 1150 | MT_USB_DEVICE(USB_VENDOR_ID_DWAV, |
| 1146 | 1151 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) }, |
| 1147 | 1152 | { .driver_data = MT_CLS_EGALAX_SERIAL, |
| 1148 | 1153 | MT_USB_DEVICE(USB_VENDOR_ID_DWAV, |
| 1149 | 1154 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72AA) }, |
| 1155 | + { .driver_data = MT_CLS_EGALAX, | |
| 1156 | + HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | |
| 1157 | + USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4) }, | |
| 1158 | + { .driver_data = MT_CLS_EGALAX, | |
| 1159 | + HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | |
| 1160 | + USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72D0) }, | |
| 1150 | 1161 | { .driver_data = MT_CLS_EGALAX, |
| 1151 | 1162 | MT_USB_DEVICE(USB_VENDOR_ID_DWAV, |
| 1152 | 1163 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA) }, |
| @@ -1162,15 +1173,6 @@ static const struct hid_device_id mt_devices[] = { · 9 unmodified lines | ||
| 1162 | 1173 | { .driver_data = MT_CLS_EGALAX_SERIAL, |
| 1163 | 1174 | MT_USB_DEVICE(USB_VENDOR_ID_DWAV, |
| 1164 | 1175 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) }, |
| 1165 | − { .driver_data = MT_CLS_EGALAX, | |
| 1166 | − HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | |
| 1167 | − USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224) }, | |
| 1168 | − { .driver_data = MT_CLS_EGALAX, | |
| 1169 | − HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | |
| 1170 | − USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72D0) }, | |
| 1171 | − { .driver_data = MT_CLS_EGALAX, | |
| 1172 | − HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | |
| 1173 | − USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4) }, | |
| 1174 | 1176 | |
| 1175 | 1177 | /* Elo TouchSystems IntelliTouch Plus panel */ |
| 1176 | 1178 | { .driver_data = MT_CLS_DUAL_CONTACT_ID, |
| @@ -1,204 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * HID driver for Sony PS3 BD Remote Control | |
| 3 | − * | |
| 4 | − * Copyright (c) 2012 David Dillow <dave@thedillows.org> | |
| 5 | − * Based on a blend of the bluez fakehid user-space code by Marcel Holtmann | |
| 6 | − * and other kernel HID drivers. | |
| 7 | − */ | |
| 8 | − | |
| 9 | −/* | |
| 10 | − * This program is free software; you can redistribute it and/or modify it | |
| 11 | − * under the terms of the GNU General Public License as published by the Free | |
| 12 | − * Software Foundation; either version 2 of the License, or (at your option) | |
| 13 | − * any later version. | |
| 14 | − */ | |
| 15 | − | |
| 16 | −/* NOTE: in order for the Sony PS3 BD Remote Control to be found by | |
| 17 | − * a Bluetooth host, the key combination Start+Enter has to be kept pressed | |
| 18 | − * for about 7 seconds with the Bluetooth Host Controller in discovering mode. | |
| 19 | − * | |
| 20 | − * There will be no PIN request from the device. | |
| 21 | − */ | |
| 22 | − | |
| 23 | −#include <linux/device.h> | |
| 24 | −#include <linux/hid.h> | |
| 25 | −#include <linux/module.h> | |
| 26 | − | |
| 27 | −#include "hid-ids.h" | |
| 28 | − | |
| 29 | −static __u8 ps3remote_rdesc[] = { | |
| 30 | − 0x05, 0x01, /* GUsagePage Generic Desktop */ | |
| 31 | − 0x09, 0x05, /* LUsage 0x05 [Game Pad] */ | |
| 32 | − 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */ | |
| 33 | − | |
| 34 | − /* Use collection 1 for joypad buttons */ | |
| 35 | − 0xA1, 0x02, /* MCollection Logical (interrelated data) */ | |
| 36 | − | |
| 37 | − /* Ignore the 1st byte, maybe it is used for a controller | |
| 38 | − * number but it's not needed for correct operation */ | |
| 39 | − 0x75, 0x08, /* GReportSize 0x08 [8] */ | |
| 40 | − 0x95, 0x01, /* GReportCount 0x01 [1] */ | |
| 41 | − 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ | |
| 42 | − | |
| 43 | − /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these | |
| 44 | − * buttons multiple keypresses are allowed */ | |
| 45 | − 0x05, 0x09, /* GUsagePage Button */ | |
| 46 | − 0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */ | |
| 47 | − 0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */ | |
| 48 | − 0x14, /* GLogicalMinimum [0] */ | |
| 49 | − 0x25, 0x01, /* GLogicalMaximum 0x01 [1] */ | |
| 50 | − 0x75, 0x01, /* GReportSize 0x01 [1] */ | |
| 51 | − 0x95, 0x18, /* GReportCount 0x18 [24] */ | |
| 52 | − 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ | |
| 53 | − | |
| 54 | − 0xC0, /* MEndCollection */ | |
| 55 | − | |
| 56 | − /* Use collection 2 for remote control buttons */ | |
| 57 | − 0xA1, 0x02, /* MCollection Logical (interrelated data) */ | |
| 58 | − | |
| 59 | − /* 5th byte is used for remote control buttons */ | |
| 60 | − 0x05, 0x09, /* GUsagePage Button */ | |
| 61 | − 0x18, /* LUsageMinimum [No button pressed] */ | |
| 62 | − 0x29, 0xFE, /* LUsageMaximum 0xFE [Button 254] */ | |
| 63 | − 0x14, /* GLogicalMinimum [0] */ | |
| 64 | − 0x26, 0xFE, 0x00, /* GLogicalMaximum 0x00FE [254] */ | |
| 65 | − 0x75, 0x08, /* GReportSize 0x08 [8] */ | |
| 66 | − 0x95, 0x01, /* GReportCount 0x01 [1] */ | |
| 67 | − 0x80, /* MInput */ | |
| 68 | − | |
| 69 | − /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at | |
| 70 | − * 0xff and 11th is for press indication */ | |
| 71 | − 0x75, 0x08, /* GReportSize 0x08 [8] */ | |
| 72 | − 0x95, 0x06, /* GReportCount 0x06 [6] */ | |
| 73 | − 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ | |
| 74 | − | |
| 75 | − /* 12th byte is for battery strength */ | |
| 76 | − 0x05, 0x06, /* GUsagePage Generic Device Controls */ | |
| 77 | − 0x09, 0x20, /* LUsage 0x20 [Battery Strength] */ | |
| 78 | − 0x14, /* GLogicalMinimum [0] */ | |
| 79 | − 0x25, 0x05, /* GLogicalMaximum 0x05 [5] */ | |
| 80 | − 0x75, 0x08, /* GReportSize 0x08 [8] */ | |
| 81 | − 0x95, 0x01, /* GReportCount 0x01 [1] */ | |
| 82 | − 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ | |
| 83 | − | |
| 84 | − 0xC0, /* MEndCollection */ | |
| 85 | − | |
| 86 | − 0xC0 /* MEndCollection [Game Pad] */ | |
| 87 | −}; | |
| 88 | − | |
| 89 | −static const unsigned int ps3remote_keymap_joypad_buttons[] = { | |
| 90 | − [0x01] = KEY_SELECT, | |
| 91 | − [0x02] = BTN_THUMBL, /* L3 */ | |
| 92 | − [0x03] = BTN_THUMBR, /* R3 */ | |
| 93 | − [0x04] = BTN_START, | |
| 94 | − [0x05] = KEY_UP, | |
| 95 | − [0x06] = KEY_RIGHT, | |
| 96 | − [0x07] = KEY_DOWN, | |
| 97 | − [0x08] = KEY_LEFT, | |
| 98 | − [0x09] = BTN_TL2, /* L2 */ | |
| 99 | − [0x0a] = BTN_TR2, /* R2 */ | |
| 100 | − [0x0b] = BTN_TL, /* L1 */ | |
| 101 | − [0x0c] = BTN_TR, /* R1 */ | |
| 102 | − [0x0d] = KEY_OPTION, /* options/triangle */ | |
| 103 | − [0x0e] = KEY_BACK, /* back/circle */ | |
| 104 | − [0x0f] = BTN_0, /* cross */ | |
| 105 | − [0x10] = KEY_SCREEN, /* view/square */ | |
| 106 | − [0x11] = KEY_HOMEPAGE, /* PS button */ | |
| 107 | − [0x14] = KEY_ENTER, | |
| 108 | −}; | |
| 109 | −static const unsigned int ps3remote_keymap_remote_buttons[] = { | |
| 110 | − [0x00] = KEY_1, | |
| 111 | − [0x01] = KEY_2, | |
| 112 | − [0x02] = KEY_3, | |
| 113 | − [0x03] = KEY_4, | |
| 114 | − [0x04] = KEY_5, | |
| 115 | − [0x05] = KEY_6, | |
| 116 | − [0x06] = KEY_7, | |
| 117 | − [0x07] = KEY_8, | |
| 118 | − [0x08] = KEY_9, | |
| 119 | − [0x09] = KEY_0, | |
| 120 | − [0x0e] = KEY_ESC, /* return */ | |
| 121 | − [0x0f] = KEY_CLEAR, | |
| 122 | − [0x16] = KEY_EJECTCD, | |
| 123 | − [0x1a] = KEY_MENU, /* top menu */ | |
| 124 | − [0x28] = KEY_TIME, | |
| 125 | − [0x30] = KEY_PREVIOUS, | |
| 126 | − [0x31] = KEY_NEXT, | |
| 127 | − [0x32] = KEY_PLAY, | |
| 128 | − [0x33] = KEY_REWIND, /* scan back */ | |
| 129 | − [0x34] = KEY_FORWARD, /* scan forward */ | |
| 130 | − [0x38] = KEY_STOP, | |
| 131 | − [0x39] = KEY_PAUSE, | |
| 132 | − [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */ | |
| 133 | − [0x60] = KEY_FRAMEBACK, /* slow/step back */ | |
| 134 | − [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */ | |
| 135 | − [0x63] = KEY_SUBTITLE, | |
| 136 | − [0x64] = KEY_AUDIO, | |
| 137 | − [0x65] = KEY_ANGLE, | |
| 138 | − [0x70] = KEY_INFO, /* display */ | |
| 139 | − [0x80] = KEY_BLUE, | |
| 140 | − [0x81] = KEY_RED, | |
| 141 | − [0x82] = KEY_GREEN, | |
| 142 | − [0x83] = KEY_YELLOW, | |
| 143 | −}; | |
| 144 | − | |
| 145 | −static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, | |
| 146 | − unsigned int *rsize) | |
| 147 | −{ | |
| 148 | − *rsize = sizeof(ps3remote_rdesc); | |
| 149 | − return ps3remote_rdesc; | |
| 150 | −} | |
| 151 | − | |
| 152 | −static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, | |
| 153 | − struct hid_field *field, struct hid_usage *usage, | |
| 154 | − unsigned long **bit, int *max) | |
| 155 | −{ | |
| 156 | − unsigned int key = usage->hid & HID_USAGE; | |
| 157 | − | |
| 158 | − if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) | |
| 159 | − return -1; | |
| 160 | − | |
| 161 | − switch (usage->collection_index) { | |
| 162 | − case 1: | |
| 163 | − if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons)) | |
| 164 | − return -1; | |
| 165 | − | |
| 166 | − key = ps3remote_keymap_joypad_buttons[key]; | |
| 167 | − if (!key) | |
| 168 | − return -1; | |
| 169 | − break; | |
| 170 | − case 2: | |
| 171 | − if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons)) | |
| 172 | − return -1; | |
| 173 | − | |
| 174 | − key = ps3remote_keymap_remote_buttons[key]; | |
| 175 | − if (!key) | |
| 176 | − return -1; | |
| 177 | − break; | |
| 178 | − default: | |
| 179 | − return -1; | |
| 180 | − } | |
| 181 | − | |
| 182 | − hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); | |
| 183 | − return 1; | |
| 184 | −} | |
| 185 | − | |
| 186 | −static const struct hid_device_id ps3remote_devices[] = { | |
| 187 | − /* PS3 BD Remote Control */ | |
| 188 | − { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, | |
| 189 | − /* Logitech Harmony Adapter for PS3 */ | |
| 190 | − { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) }, | |
| 191 | − { } | |
| 192 | −}; | |
| 193 | −MODULE_DEVICE_TABLE(hid, ps3remote_devices); | |
| 194 | − | |
| 195 | −static struct hid_driver ps3remote_driver = { | |
| 196 | − .name = "ps3_remote", | |
| 197 | − .id_table = ps3remote_devices, | |
| 198 | − .report_fixup = ps3remote_fixup, | |
| 199 | − .input_mapping = ps3remote_mapping, | |
| 200 | −}; | |
| 201 | −module_hid_driver(ps3remote_driver); | |
| 202 | − | |
| 203 | −MODULE_LICENSE("GPL"); | |
| 204 | −MODULE_AUTHOR("David Dillow <dave@thedillows.org>, Antonio Ospite <ospite@studenti.unina.it>"); | |
| @@ -366,7 +366,7 @@ void roccat_disconnect(int minor) · 365 unmodified lines | ||
| 366 | 366 | mutex_lock(&devices_lock); |
| 367 | 367 | devices[minor] = NULL; |
| 368 | 368 | mutex_unlock(&devices_lock); |
| 369 | − | |
| 369 | + | |
| 370 | 370 | if (device->open) { |
| 371 | 371 | hid_hw_close(device->hid); |
| 372 | 372 | wake_up_interruptible(&device->wait); |
| @@ -426,13 +426,23 @@ static int __init roccat_init(void) · 53 unmodified lines | ||
| 426 | 426 | |
| 427 | 427 | if (retval < 0) { |
| 428 | 428 | pr_warn("can't get major number\n"); |
| 429 | − return retval; | |
| 429 | + goto error; | |
| 430 | 430 | } |
| 431 | 431 | |
| 432 | 432 | cdev_init(&roccat_cdev, &roccat_ops); |
| 433 | − cdev_add(&roccat_cdev, dev_id, ROCCAT_MAX_DEVICES); | |
| 433 | + retval = cdev_add(&roccat_cdev, dev_id, ROCCAT_MAX_DEVICES); | |
| 434 | 434 | |
| 435 | + if (retval < 0) { | |
| 436 | + pr_warn("cannot add cdev\n"); | |
| 437 | + goto cleanup_alloc_chrdev_region; | |
| 438 | + } | |
| 435 | 439 | return 0; |
| 440 | + | |
| 441 | + | |
| 442 | + cleanup_alloc_chrdev_region: | |
| 443 | + unregister_chrdev_region(dev_id, ROCCAT_MAX_DEVICES); | |
| 444 | + error: | |
| 445 | + return retval; | |
| 436 | 446 | } |
| 437 | 447 | |
| 438 | 448 | static void __exit roccat_exit(void) |
| @@ -1,11 +1,13 @@ | ||
| 1 | 1 | /* |
| 2 | − * HID driver for some sony "special" devices | |
| 2 | + * HID driver for Sony / PS2 / PS3 BD devices. | |
| 3 | 3 | * |
| 4 | 4 | * Copyright (c) 1999 Andreas Gal |
| 5 | 5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> |
| 6 | 6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc |
| 7 | 7 | * Copyright (c) 2008 Jiri Slaby |
| 8 | − * Copyright (c) 2006-2008 Jiri Kosina | |
| 8 | + * Copyright (c) 2012 David Dillow <dave@thedillows.org> | |
| 9 | + * Copyright (c) 2006-2013 Jiri Kosina | |
| 10 | + * Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com> | |
| 9 | 11 | */ |
| 10 | 12 | |
| 11 | 13 | /* |
| @@ -15,17 +17,27 @@ · 3 unmodified lines | ||
| 15 | 17 | * any later version. |
| 16 | 18 | */ |
| 17 | 19 | |
| 20 | +/* NOTE: in order for the Sony PS3 BD Remote Control to be found by | |
| 21 | + * a Bluetooth host, the key combination Start+Enter has to be kept pressed | |
| 22 | + * for about 7 seconds with the Bluetooth Host Controller in discovering mode. | |
| 23 | + * | |
| 24 | + * There will be no PIN request from the device. | |
| 25 | + */ | |
| 26 | + | |
| 18 | 27 | #include <linux/device.h> |
| 19 | 28 | #include <linux/hid.h> |
| 20 | 29 | #include <linux/module.h> |
| 21 | 30 | #include <linux/slab.h> |
| 22 | 31 | #include <linux/usb.h> |
| 32 | +#include <linux/leds.h> | |
| 23 | 33 | |
| 24 | 34 | #include "hid-ids.h" |
| 25 | 35 | |
| 26 | 36 | #define VAIO_RDESC_CONSTANT (1 << 0) |
| 27 | 37 | #define SIXAXIS_CONTROLLER_USB (1 << 1) |
| 28 | 38 | #define SIXAXIS_CONTROLLER_BT (1 << 2) |
| 39 | +#define BUZZ_CONTROLLER (1 << 3) | |
| 40 | +#define PS3REMOTE (1 << 4) | |
| 29 | 41 | |
| 30 | 42 | static const u8 sixaxis_rdesc_fixup[] = { |
| 31 | 43 | 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C, |
| @@ -55,10 +67,214 @@ static const u8 sixaxis_rdesc_fixup2[] = { · 23 unmodified lines | ||
| 55 | 67 | 0xb1, 0x02, 0xc0, 0xc0, |
| 56 | 68 | }; |
| 57 | 69 | |
| 70 | +static __u8 ps3remote_rdesc[] = { | |
| 71 | + 0x05, 0x01, /* GUsagePage Generic Desktop */ | |
| 72 | + 0x09, 0x05, /* LUsage 0x05 [Game Pad] */ | |
| 73 | + 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */ | |
| 74 | + | |
| 75 | + /* Use collection 1 for joypad buttons */ | |
| 76 | + 0xA1, 0x02, /* MCollection Logical (interrelated data) */ | |
| 77 | + | |
| 78 | + /* Ignore the 1st byte, maybe it is used for a controller | |
| 79 | + * number but it's not needed for correct operation */ | |
| 80 | + 0x75, 0x08, /* GReportSize 0x08 [8] */ | |
| 81 | + 0x95, 0x01, /* GReportCount 0x01 [1] */ | |
| 82 | + 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ | |
| 83 | + | |
| 84 | + /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these | |
| 85 | + * buttons multiple keypresses are allowed */ | |
| 86 | + 0x05, 0x09, /* GUsagePage Button */ | |
| 87 | + 0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */ | |
| 88 | + 0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */ | |
| 89 | + 0x14, /* GLogicalMinimum [0] */ | |
| 90 | + 0x25, 0x01, /* GLogicalMaximum 0x01 [1] */ | |
| 91 | + 0x75, 0x01, /* GReportSize 0x01 [1] */ | |
| 92 | + 0x95, 0x18, /* GReportCount 0x18 [24] */ | |
| 93 | + 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ | |
| 94 | + | |
| 95 | + 0xC0, /* MEndCollection */ | |
| 96 | + | |
| 97 | + /* Use collection 2 for remote control buttons */ | |
| 98 | + 0xA1, 0x02, /* MCollection Logical (interrelated data) */ | |
| 99 | + | |
| 100 | + /* 5th byte is used for remote control buttons */ | |
| 101 | + 0x05, 0x09, /* GUsagePage Button */ | |
| 102 | + 0x18, /* LUsageMinimum [No button pressed] */ | |
| 103 | + 0x29, 0xFE, /* LUsageMaximum 0xFE [Button 254] */ | |
| 104 | + 0x14, /* GLogicalMinimum [0] */ | |
| 105 | + 0x26, 0xFE, 0x00, /* GLogicalMaximum 0x00FE [254] */ | |
| 106 | + 0x75, 0x08, /* GReportSize 0x08 [8] */ | |
| 107 | + 0x95, 0x01, /* GReportCount 0x01 [1] */ | |
| 108 | + 0x80, /* MInput */ | |
| 109 | + | |
| 110 | + /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at | |
| 111 | + * 0xff and 11th is for press indication */ | |
| 112 | + 0x75, 0x08, /* GReportSize 0x08 [8] */ | |
| 113 | + 0x95, 0x06, /* GReportCount 0x06 [6] */ | |
| 114 | + 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ | |
| 115 | + | |
| 116 | + /* 12th byte is for battery strength */ | |
| 117 | + 0x05, 0x06, /* GUsagePage Generic Device Controls */ | |
| 118 | + 0x09, 0x20, /* LUsage 0x20 [Battery Strength] */ | |
| 119 | + 0x14, /* GLogicalMinimum [0] */ | |
| 120 | + 0x25, 0x05, /* GLogicalMaximum 0x05 [5] */ | |
| 121 | + 0x75, 0x08, /* GReportSize 0x08 [8] */ | |
| 122 | + 0x95, 0x01, /* GReportCount 0x01 [1] */ | |
| 123 | + 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ | |
| 124 | + | |
| 125 | + 0xC0, /* MEndCollection */ | |
| 126 | + | |
| 127 | + 0xC0 /* MEndCollection [Game Pad] */ | |
| 128 | +}; | |
| 129 | + | |
| 130 | +static const unsigned int ps3remote_keymap_joypad_buttons[] = { | |
| 131 | + [0x01] = KEY_SELECT, | |
| 132 | + [0x02] = BTN_THUMBL, /* L3 */ | |
| 133 | + [0x03] = BTN_THUMBR, /* R3 */ | |
| 134 | + [0x04] = BTN_START, | |
| 135 | + [0x05] = KEY_UP, | |
| 136 | + [0x06] = KEY_RIGHT, | |
| 137 | + [0x07] = KEY_DOWN, | |
| 138 | + [0x08] = KEY_LEFT, | |
| 139 | + [0x09] = BTN_TL2, /* L2 */ | |
| 140 | + [0x0a] = BTN_TR2, /* R2 */ | |
| 141 | + [0x0b] = BTN_TL, /* L1 */ | |
| 142 | + [0x0c] = BTN_TR, /* R1 */ | |
| 143 | + [0x0d] = KEY_OPTION, /* options/triangle */ | |
| 144 | + [0x0e] = KEY_BACK, /* back/circle */ | |
| 145 | + [0x0f] = BTN_0, /* cross */ | |
| 146 | + [0x10] = KEY_SCREEN, /* view/square */ | |
| 147 | + [0x11] = KEY_HOMEPAGE, /* PS button */ | |
| 148 | + [0x14] = KEY_ENTER, | |
| 149 | +}; | |
| 150 | +static const unsigned int ps3remote_keymap_remote_buttons[] = { | |
| 151 | + [0x00] = KEY_1, | |
| 152 | + [0x01] = KEY_2, | |
| 153 | + [0x02] = KEY_3, | |
| 154 | + [0x03] = KEY_4, | |
| 155 | + [0x04] = KEY_5, | |
| 156 | + [0x05] = KEY_6, | |
| 157 | + [0x06] = KEY_7, | |
| 158 | + [0x07] = KEY_8, | |
| 159 | + [0x08] = KEY_9, | |
| 160 | + [0x09] = KEY_0, | |
| 161 | + [0x0e] = KEY_ESC, /* return */ | |
| 162 | + [0x0f] = KEY_CLEAR, | |
| 163 | + [0x16] = KEY_EJECTCD, | |
| 164 | + [0x1a] = KEY_MENU, /* top menu */ | |
| 165 | + [0x28] = KEY_TIME, | |
| 166 | + [0x30] = KEY_PREVIOUS, | |
| 167 | + [0x31] = KEY_NEXT, | |
| 168 | + [0x32] = KEY_PLAY, | |
| 169 | + [0x33] = KEY_REWIND, /* scan back */ | |
| 170 | + [0x34] = KEY_FORWARD, /* scan forward */ | |
| 171 | + [0x38] = KEY_STOP, | |
| 172 | + [0x39] = KEY_PAUSE, | |
| 173 | + [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */ | |
| 174 | + [0x60] = KEY_FRAMEBACK, /* slow/step back */ | |
| 175 | + [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */ | |
| 176 | + [0x63] = KEY_SUBTITLE, | |
| 177 | + [0x64] = KEY_AUDIO, | |
| 178 | + [0x65] = KEY_ANGLE, | |
| 179 | + [0x70] = KEY_INFO, /* display */ | |
| 180 | + [0x80] = KEY_BLUE, | |
| 181 | + [0x81] = KEY_RED, | |
| 182 | + [0x82] = KEY_GREEN, | |
| 183 | + [0x83] = KEY_YELLOW, | |
| 184 | +}; | |
| 185 | + | |
| 186 | +static const unsigned int buzz_keymap[] = { | |
| 187 | + /* The controller has 4 remote buzzers, each with one LED and 5 | |
| 188 | + * buttons. | |
| 189 | + * | |
| 190 | + * We use the mapping chosen by the controller, which is: | |
| 191 | + * | |
| 192 | + * Key Offset | |
| 193 | + * ------------------- | |
| 194 | + * Buzz 1 | |
| 195 | + * Blue 5 | |
| 196 | + * Orange 4 | |
| 197 | + * Green 3 | |
| 198 | + * Yellow 2 | |
| 199 | + * | |
| 200 | + * So, for example, the orange button on the third buzzer is mapped to | |
| 201 | + * BTN_TRIGGER_HAPPY14 | |
| 202 | + */ | |
| 203 | + [ 1] = BTN_TRIGGER_HAPPY1, | |
| 204 | + [ 2] = BTN_TRIGGER_HAPPY2, | |
| 205 | + [ 3] = BTN_TRIGGER_HAPPY3, | |
| 206 | + [ 4] = BTN_TRIGGER_HAPPY4, | |
| 207 | + [ 5] = BTN_TRIGGER_HAPPY5, | |
| 208 | + [ 6] = BTN_TRIGGER_HAPPY6, | |
| 209 | + [ 7] = BTN_TRIGGER_HAPPY7, | |
| 210 | + [ 8] = BTN_TRIGGER_HAPPY8, | |
| 211 | + [ 9] = BTN_TRIGGER_HAPPY9, | |
| 212 | + [10] = BTN_TRIGGER_HAPPY10, | |
| 213 | + [11] = BTN_TRIGGER_HAPPY11, | |
| 214 | + [12] = BTN_TRIGGER_HAPPY12, | |
| 215 | + [13] = BTN_TRIGGER_HAPPY13, | |
| 216 | + [14] = BTN_TRIGGER_HAPPY14, | |
| 217 | + [15] = BTN_TRIGGER_HAPPY15, | |
| 218 | + [16] = BTN_TRIGGER_HAPPY16, | |
| 219 | + [17] = BTN_TRIGGER_HAPPY17, | |
| 220 | + [18] = BTN_TRIGGER_HAPPY18, | |
| 221 | + [19] = BTN_TRIGGER_HAPPY19, | |
| 222 | + [20] = BTN_TRIGGER_HAPPY20, | |
| 223 | +}; | |
| 224 | + | |
| 58 | 225 | struct sony_sc { |
| 59 | 226 | unsigned long quirks; |
| 227 | + | |
| 228 | + void *extra; | |
| 60 | 229 | }; |
| 61 | 230 | |
| 231 | +struct buzz_extra { | |
| 232 | + int led_state; | |
| 233 | + struct led_classdev *leds[4]; | |
| 234 | +}; | |
| 235 | + | |
| 236 | +static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, | |
| 237 | + unsigned int *rsize) | |
| 238 | +{ | |
| 239 | + *rsize = sizeof(ps3remote_rdesc); | |
| 240 | + return ps3remote_rdesc; | |
| 241 | +} | |
| 242 | + | |
| 243 | +static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, | |
| 244 | + struct hid_field *field, struct hid_usage *usage, | |
| 245 | + unsigned long **bit, int *max) | |
| 246 | +{ | |
| 247 | + unsigned int key = usage->hid & HID_USAGE; | |
| 248 | + | |
| 249 | + if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) | |
| 250 | + return -1; | |
| 251 | + | |
| 252 | + switch (usage->collection_index) { | |
| 253 | + case 1: | |
| 254 | + if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons)) | |
| 255 | + return -1; | |
| 256 | + | |
| 257 | + key = ps3remote_keymap_joypad_buttons[key]; | |
| 258 | + if (!key) | |
| 259 | + return -1; | |
| 260 | + break; | |
| 261 | + case 2: | |
| 262 | + if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons)) | |
| 263 | + return -1; | |
| 264 | + | |
| 265 | + key = ps3remote_keymap_remote_buttons[key]; | |
| 266 | + if (!key) | |
| 267 | + return -1; | |
| 268 | + break; | |
| 269 | + default: | |
| 270 | + return -1; | |
| 271 | + } | |
| 272 | + | |
| 273 | + hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); | |
| 274 | + return 1; | |
| 275 | +} | |
| 276 | + | |
| 277 | + | |
| 62 | 278 | /* Sony Vaio VGX has wrongly mouse pointer declared as constant */ |
| 63 | 279 | static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 64 | 280 | unsigned int *rsize) |
| @@ -95,6 +311,10 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, · 30 unmodified lines | ||
| 95 | 311 | *rsize = sizeof(sixaxis_rdesc_fixup2); |
| 96 | 312 | memcpy(rdesc, &sixaxis_rdesc_fixup2, *rsize); |
| 97 | 313 | } |
| 314 | + | |
| 315 | + if (sc->quirks & PS3REMOTE) | |
| 316 | + return ps3remote_fixup(hdev, rdesc, rsize); | |
| 317 | + | |
| 98 | 318 | return rdesc; |
| 99 | 319 | } |
| 100 | 320 | |
| @@ -117,6 +337,41 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, · 16 unmodified lines | ||
| 117 | 337 | return 0; |
| 118 | 338 | } |
| 119 | 339 | |
| 340 | +static int sony_mapping(struct hid_device *hdev, struct hid_input *hi, | |
| 341 | + struct hid_field *field, struct hid_usage *usage, | |
| 342 | + unsigned long **bit, int *max) | |
| 343 | +{ | |
| 344 | + struct sony_sc *sc = hid_get_drvdata(hdev); | |
| 345 | + | |
| 346 | + if (sc->quirks & BUZZ_CONTROLLER) { | |
| 347 | + unsigned int key = usage->hid & HID_USAGE; | |
| 348 | + | |
| 349 | + if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) | |
| 350 | + return -1; | |
| 351 | + | |
| 352 | + switch (usage->collection_index) { | |
| 353 | + case 1: | |
| 354 | + if (key >= ARRAY_SIZE(buzz_keymap)) | |
| 355 | + return -1; | |
| 356 | + | |
| 357 | + key = buzz_keymap[key]; | |
| 358 | + if (!key) | |
| 359 | + return -1; | |
| 360 | + break; | |
| 361 | + default: | |
| 362 | + return -1; | |
| 363 | + } | |
| 364 | + | |
| 365 | + hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); | |
| 366 | + return 1; | |
| 367 | + } | |
| 368 | + | |
| 369 | + if (sc->quirks & PS3REMOTE) | |
| 370 | + return ps3remote_mapping(hdev, hi, field, usage, bit, max); | |
| 371 | + | |
| 372 | + return -1; | |
| 373 | +} | |
| 374 | + | |
| 120 | 375 | /* |
| 121 | 376 | * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP |
| 122 | 377 | * like it should according to usbhid/hid-core.c::usbhid_output_raw_report() |
| @@ -192,11 +447,181 @@ static int sixaxis_set_operational_bt(struct hid_device *hdev) · 69 unmodified lines | ||
| 192 | 447 | return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); |
| 193 | 448 | } |
| 194 | 449 | |
| 450 | +static void buzz_set_leds(struct hid_device *hdev, int leds) | |
| 451 | +{ | |
| 452 | + struct list_head *report_list = | |
| 453 | + &hdev->report_enum[HID_OUTPUT_REPORT].report_list; | |
| 454 | + struct hid_report *report = list_entry(report_list->next, | |
| 455 | + struct hid_report, list); | |
| 456 | + __s32 *value = report->field[0]->value; | |
| 457 | + | |
| 458 | + value[0] = 0x00; | |
| 459 | + value[1] = (leds & 1) ? 0xff : 0x00; | |
| 460 | + value[2] = (leds & 2) ? 0xff : 0x00; | |
| 461 | + value[3] = (leds & 4) ? 0xff : 0x00; | |
| 462 | + value[4] = (leds & 8) ? 0xff : 0x00; | |
| 463 | + value[5] = 0x00; | |
| 464 | + value[6] = 0x00; | |
| 465 | + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); | |
| 466 | +} | |
| 467 | + | |
| 468 | +static void buzz_led_set_brightness(struct led_classdev *led, | |
| 469 | + enum led_brightness value) | |
| 470 | +{ | |
| 471 | + struct device *dev = led->dev->parent; | |
| 472 | + struct hid_device *hdev = container_of(dev, struct hid_device, dev); | |
| 473 | + struct sony_sc *drv_data; | |
| 474 | + struct buzz_extra *buzz; | |
| 475 | + | |
| 476 | + int n; | |
| 477 | + | |
| 478 | + drv_data = hid_get_drvdata(hdev); | |
| 479 | + if (!drv_data || !drv_data->extra) { | |
| 480 | + hid_err(hdev, "No device data\n"); | |
| 481 | + return; | |
| 482 | + } | |
| 483 | + buzz = drv_data->extra; | |
| 484 | + | |
| 485 | + for (n = 0; n < 4; n++) { | |
| 486 | + if (led == buzz->leds[n]) { | |
| 487 | + int on = !! (buzz->led_state & (1 << n)); | |
| 488 | + if (value == LED_OFF && on) { | |
| 489 | + buzz->led_state &= ~(1 << n); | |
| 490 | + buzz_set_leds(hdev, buzz->led_state); | |
| 491 | + } else if (value != LED_OFF && !on) { | |
| 492 | + buzz->led_state |= (1 << n); | |
| 493 | + buzz_set_leds(hdev, buzz->led_state); | |
| 494 | + } | |
| 495 | + break; | |
| 496 | + } | |
| 497 | + } | |
| 498 | +} | |
| 499 | + | |
| 500 | +static enum led_brightness buzz_led_get_brightness(struct led_classdev *led) | |
| 501 | +{ | |
| 502 | + struct device *dev = led->dev->parent; | |
| 503 | + struct hid_device *hdev = container_of(dev, struct hid_device, dev); | |
| 504 | + struct sony_sc *drv_data; | |
| 505 | + struct buzz_extra *buzz; | |
| 506 | + | |
| 507 | + int n; | |
| 508 | + int on = 0; | |
| 509 | + | |
| 510 | + drv_data = hid_get_drvdata(hdev); | |
| 511 | + if (!drv_data || !drv_data->extra) { | |
| 512 | + hid_err(hdev, "No device data\n"); | |
| 513 | + return LED_OFF; | |
| 514 | + } | |
| 515 | + buzz = drv_data->extra; | |
| 516 | + | |
| 517 | + for (n = 0; n < 4; n++) { | |
| 518 | + if (led == buzz->leds[n]) { | |
| 519 | + on = !! (buzz->led_state & (1 << n)); | |
| 520 | + break; | |
| 521 | + } | |
| 522 | + } | |
| 523 | + | |
| 524 | + return on ? LED_FULL : LED_OFF; | |
| 525 | +} | |
| 526 | + | |
| 527 | +static int buzz_init(struct hid_device *hdev) | |
| 528 | +{ | |
| 529 | + struct sony_sc *drv_data; | |
| 530 | + struct buzz_extra *buzz; | |
| 531 | + int n, ret = 0; | |
| 532 | + struct led_classdev *led; | |
| 533 | + size_t name_sz; | |
| 534 | + char *name; | |
| 535 | + | |
| 536 | + drv_data = hid_get_drvdata(hdev); | |
| 537 | + BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER)); | |
| 538 | + | |
| 539 | + buzz = kzalloc(sizeof(*buzz), GFP_KERNEL); | |
| 540 | + if (!buzz) { | |
| 541 | + hid_err(hdev, "Insufficient memory, cannot allocate driver data\n"); | |
| 542 | + return -ENOMEM; | |
| 543 | + } | |
| 544 | + drv_data->extra = buzz; | |
| 545 | + | |
| 546 | + /* Clear LEDs as we have no way of reading their initial state. This is | |
| 547 | + * only relevant if the driver is loaded after somebody actively set the | |
| 548 | + * LEDs to on */ | |
| 549 | + buzz_set_leds(hdev, 0x00); | |
| 550 | + | |
| 551 | + name_sz = strlen(dev_name(&hdev->dev)) + strlen("::buzz#") + 1; | |
| 552 | + | |
| 553 | + for (n = 0; n < 4; n++) { | |
| 554 | + led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL); | |
| 555 | + if (!led) { | |
| 556 | + hid_err(hdev, "Couldn't allocate memory for LED %d\n", n); | |
| 557 | + goto error_leds; | |
| 558 | + } | |
| 559 | + | |
| 560 | + name = (void *)(&led[1]); | |
| 561 | + snprintf(name, name_sz, "%s::buzz%d", dev_name(&hdev->dev), n + 1); | |
| 562 | + led->name = name; | |
| 563 | + led->brightness = 0; | |
| 564 | + led->max_brightness = 1; | |
| 565 | + led->brightness_get = buzz_led_get_brightness; | |
| 566 | + led->brightness_set = buzz_led_set_brightness; | |
| 567 | + | |
| 568 | + if (led_classdev_register(&hdev->dev, led)) { | |
| 569 | + hid_err(hdev, "Failed to register LED %d\n", n); | |
| 570 | + kfree(led); | |
| 571 | + goto error_leds; | |
| 572 | + } | |
| 573 | + | |
| 574 | + buzz->leds[n] = led; | |
| 575 | + } | |
| 576 | + | |
| 577 | + return ret; | |
| 578 | + | |
| 579 | +error_leds: | |
| 580 | + for (n = 0; n < 4; n++) { | |
| 581 | + led = buzz->leds[n]; | |
| 582 | + buzz->leds[n] = NULL; | |
| 583 | + if (!led) | |
| 584 | + continue; | |
| 585 | + led_classdev_unregister(led); | |
| 586 | + kfree(led); | |
| 587 | + } | |
| 588 | + | |
| 589 | + kfree(drv_data->extra); | |
| 590 | + drv_data->extra = NULL; | |
| 591 | + return ret; | |
| 592 | +} | |
| 593 | + | |
| 594 | +static void buzz_remove(struct hid_device *hdev) | |
| 595 | +{ | |
| 596 | + struct sony_sc *drv_data; | |
| 597 | + struct buzz_extra *buzz; | |
| 598 | + struct led_classdev *led; | |
| 599 | + int n; | |
| 600 | + | |
| 601 | + drv_data = hid_get_drvdata(hdev); | |
| 602 | + BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER)); | |
| 603 | + | |
| 604 | + buzz = drv_data->extra; | |
| 605 | + | |
| 606 | + for (n = 0; n < 4; n++) { | |
| 607 | + led = buzz->leds[n]; | |
| 608 | + buzz->leds[n] = NULL; | |
| 609 | + if (!led) | |
| 610 | + continue; | |
| 611 | + led_classdev_unregister(led); | |
| 612 | + kfree(led); | |
| 613 | + } | |
| 614 | + | |
| 615 | + kfree(drv_data->extra); | |
| 616 | + drv_data->extra = NULL; | |
| 617 | +} | |
| 618 | + | |
| 195 | 619 | static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) |
| 196 | 620 | { |
| 197 | 621 | int ret; |
| 198 | 622 | unsigned long quirks = id->driver_data; |
| 199 | 623 | struct sony_sc *sc; |
| 624 | + unsigned int connect_mask = HID_CONNECT_DEFAULT; | |
| 200 | 625 | |
| 201 | 626 | sc = kzalloc(sizeof(*sc), GFP_KERNEL); |
| 202 | 627 | if (sc == NULL) { |
| @@ -213,8 +638,14 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) · 10 unmodified lines | ||
| 213 | 638 | goto err_free; |
| 214 | 639 | } |
| 215 | 640 | |
| 216 | − ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | | |
| 217 | − HID_CONNECT_HIDDEV_FORCE); | |
| 641 | + if (sc->quirks & VAIO_RDESC_CONSTANT) | |
| 642 | + connect_mask |= HID_CONNECT_HIDDEV_FORCE; | |
| 643 | + else if (sc->quirks & SIXAXIS_CONTROLLER_USB) | |
| 644 | + connect_mask |= HID_CONNECT_HIDDEV_FORCE; | |
| 645 | + else if (sc->quirks & SIXAXIS_CONTROLLER_BT) | |
| 646 | + connect_mask |= HID_CONNECT_HIDDEV_FORCE; | |
| 647 | + | |
| 648 | + ret = hid_hw_start(hdev, connect_mask); | |
| 218 | 649 | if (ret) { |
| 219 | 650 | hid_err(hdev, "hw start failed\n"); |
| 220 | 651 | goto err_free; |
| @@ -226,6 +657,8 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) · 5 unmodified lines | ||
| 226 | 657 | } |
| 227 | 658 | else if (sc->quirks & SIXAXIS_CONTROLLER_BT) |
| 228 | 659 | ret = sixaxis_set_operational_bt(hdev); |
| 660 | + else if (sc->quirks & BUZZ_CONTROLLER) | |
| 661 | + ret = buzz_init(hdev); | |
| 229 | 662 | else |
| 230 | 663 | ret = 0; |
| 231 | 664 | |
| @@ -242,8 +675,13 @@ err_free: · 10 unmodified lines | ||
| 242 | 675 | |
| 243 | 676 | static void sony_remove(struct hid_device *hdev) |
| 244 | 677 | { |
| 678 | + struct sony_sc *sc = hid_get_drvdata(hdev); | |
| 679 | + | |
| 680 | + if (sc->quirks & BUZZ_CONTROLLER) | |
| 681 | + buzz_remove(hdev); | |
| 682 | + | |
| 245 | 683 | hid_hw_stop(hdev); |
| 246 | − kfree(hid_get_drvdata(hdev)); | |
| 684 | + kfree(sc); | |
| 247 | 685 | } |
| 248 | 686 | |
| 249 | 687 | static const struct hid_device_id sony_devices[] = { |
| @@ -257,17 +695,30 @@ static const struct hid_device_id sony_devices[] = { · 7 unmodified lines | ||
| 257 | 695 | .driver_data = VAIO_RDESC_CONSTANT }, |
| 258 | 696 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE), |
| 259 | 697 | .driver_data = VAIO_RDESC_CONSTANT }, |
| 698 | + /* Wired Buzz Controller. Reported as Sony Hub from its USB ID and as | |
| 699 | + * Logitech joystick from the device descriptor. */ | |
| 700 | + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER), | |
| 701 | + .driver_data = BUZZ_CONTROLLER }, | |
| 702 | + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER), | |
| 703 | + .driver_data = BUZZ_CONTROLLER }, | |
| 704 | + /* PS3 BD Remote Control */ | |
| 705 | + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE), | |
| 706 | + .driver_data = PS3REMOTE }, | |
| 707 | + /* Logitech Harmony Adapter for PS3 */ | |
| 708 | + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3), | |
| 709 | + .driver_data = PS3REMOTE }, | |
| 260 | 710 | { } |
| 261 | 711 | }; |
| 262 | 712 | MODULE_DEVICE_TABLE(hid, sony_devices); |
| 263 | 713 | |
| 264 | 714 | static struct hid_driver sony_driver = { |
| 265 | − .name = "sony", | |
| 266 | − .id_table = sony_devices, | |
| 267 | − .probe = sony_probe, | |
| 268 | − .remove = sony_remove, | |
| 269 | − .report_fixup = sony_report_fixup, | |
| 270 | − .raw_event = sony_raw_event | |
| 715 | + .name = "sony", | |
| 716 | + .id_table = sony_devices, | |
| 717 | + .input_mapping = sony_mapping, | |
| 718 | + .probe = sony_probe, | |
| 719 | + .remove = sony_remove, | |
| 720 | + .report_fixup = sony_report_fixup, | |
| 721 | + .raw_event = sony_raw_event | |
| 271 | 722 | }; |
| 272 | 723 | module_hid_driver(sony_driver); |
| 273 | 724 | |
| @@ -46,6 +46,7 @@ struct wacom_data { · 45 unmodified lines | ||
| 46 | 46 | __u8 battery_capacity; |
| 47 | 47 | __u8 power_raw; |
| 48 | 48 | __u8 ps_connected; |
| 49 | + __u8 bat_charging; | |
| 49 | 50 | struct power_supply battery; |
| 50 | 51 | struct power_supply ac; |
| 51 | 52 | __u8 led_selector; |
| @@ -62,6 +63,7 @@ static enum power_supply_property wacom_battery_props[] = { · 10 unmodified lines | ||
| 62 | 63 | POWER_SUPPLY_PROP_PRESENT, |
| 63 | 64 | POWER_SUPPLY_PROP_CAPACITY, |
| 64 | 65 | POWER_SUPPLY_PROP_SCOPE, |
| 66 | + POWER_SUPPLY_PROP_STATUS, | |
| 65 | 67 | }; |
| 66 | 68 | |
| 67 | 69 | static enum power_supply_property wacom_ac_props[] = { |
| @@ -287,6 +289,15 @@ static int wacom_battery_get_property(struct power_supply *psy, · 219 unmodified lines | ||
| 287 | 289 | case POWER_SUPPLY_PROP_CAPACITY: |
| 288 | 290 | val->intval = wdata->battery_capacity; |
| 289 | 291 | break; |
| 292 | + case POWER_SUPPLY_PROP_STATUS: | |
| 293 | + if (wdata->bat_charging) | |
| 294 | + val->intval = POWER_SUPPLY_STATUS_CHARGING; | |
| 295 | + else | |
| 296 | + if (wdata->battery_capacity == 100 && wdata->ps_connected) | |
| 297 | + val->intval = POWER_SUPPLY_STATUS_FULL; | |
| 298 | + else | |
| 299 | + val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | |
| 300 | + break; | |
| 290 | 301 | default: |
| 291 | 302 | ret = -EINVAL; |
| 292 | 303 | break; |
| @@ -727,7 +738,8 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, · 434 unmodified lines | ||
| 727 | 738 | if (power_raw != wdata->power_raw) { |
| 728 | 739 | wdata->power_raw = power_raw; |
| 729 | 740 | wdata->battery_capacity = batcap_i4[power_raw & 0x07]; |
| 730 | − wdata->ps_connected = power_raw & 0x08; | |
| 741 | + wdata->bat_charging = (power_raw & 0x08) ? 1 : 0; | |
| 742 | + wdata->ps_connected = (power_raw & 0x10) ? 1 : 0; | |
| 731 | 743 | } |
| 732 | 744 | |
| 733 | 745 | break; |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | /* |
| 2 | − * HID driver for Nintendo Wiimote devices | |
| 3 | − * Copyright (c) 2011 David Herrmann | |
| 2 | + * HID driver for Nintendo Wii / Wii U peripherals | |
| 3 | + * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@gmail.com> | |
| 4 | 4 | */ |
| 5 | 5 | |
| 6 | 6 | /* |
| @@ -14,53 +14,19 @@ · 7 unmodified lines | ||
| 14 | 14 | #include <linux/device.h> |
| 15 | 15 | #include <linux/hid.h> |
| 16 | 16 | #include <linux/input.h> |
| 17 | −#include <linux/leds.h> | |
| 18 | 17 | #include <linux/module.h> |
| 19 | 18 | #include <linux/mutex.h> |
| 20 | −#include <linux/power_supply.h> | |
| 21 | 19 | #include <linux/spinlock.h> |
| 22 | 20 | #include "hid-ids.h" |
| 23 | 21 | #include "hid-wiimote.h" |
| 24 | 22 | |
| 25 | −enum wiiproto_keys { | |
| 26 | − WIIPROTO_KEY_LEFT, | |
| 27 | − WIIPROTO_KEY_RIGHT, | |
| 28 | − WIIPROTO_KEY_UP, | |
| 29 | − WIIPROTO_KEY_DOWN, | |
| 30 | − WIIPROTO_KEY_PLUS, | |
| 31 | − WIIPROTO_KEY_MINUS, | |
| 32 | − WIIPROTO_KEY_ONE, | |
| 33 | − WIIPROTO_KEY_TWO, | |
| 34 | − WIIPROTO_KEY_A, | |
| 35 | − WIIPROTO_KEY_B, | |
| 36 | − WIIPROTO_KEY_HOME, | |
| 37 | − WIIPROTO_KEY_COUNT | |
| 38 | −}; | |
| 39 | − | |
| 40 | −static __u16 wiiproto_keymap[] = { | |
| 41 | − KEY_LEFT, /* WIIPROTO_KEY_LEFT */ | |
| 42 | − KEY_RIGHT, /* WIIPROTO_KEY_RIGHT */ | |
| 43 | − KEY_UP, /* WIIPROTO_KEY_UP */ | |
| 44 | − KEY_DOWN, /* WIIPROTO_KEY_DOWN */ | |
| 45 | − KEY_NEXT, /* WIIPROTO_KEY_PLUS */ | |
| 46 | − KEY_PREVIOUS, /* WIIPROTO_KEY_MINUS */ | |
| 47 | − BTN_1, /* WIIPROTO_KEY_ONE */ | |
| 48 | − BTN_2, /* WIIPROTO_KEY_TWO */ | |
| 49 | − BTN_A, /* WIIPROTO_KEY_A */ | |
| 50 | − BTN_B, /* WIIPROTO_KEY_B */ | |
| 51 | − BTN_MODE, /* WIIPROTO_KEY_HOME */ | |
| 52 | −}; | |
| 23 | +/* output queue handling */ | |
| 53 | 24 | |
| 54 | −static enum power_supply_property wiimote_battery_props[] = { | |
| 55 | − POWER_SUPPLY_PROP_CAPACITY, | |
| 56 | − POWER_SUPPLY_PROP_SCOPE, | |
| 57 | −}; | |
| 58 | − | |
| 59 | −static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, | |
| 60 | − size_t count) | |
| 25 | +static int wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, | |
| 26 | + size_t count) | |
| 61 | 27 | { |
| 62 | 28 | __u8 *buf; |
| 63 | − ssize_t ret; | |
| 29 | + int ret; | |
| 64 | 30 | |
| 65 | 31 | if (!hdev->hid_output_raw_report) |
| 66 | 32 | return -ENODEV; |
| @@ -75,24 +41,33 @@ static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, · 8 unmodified lines | ||
| 75 | 41 | return ret; |
| 76 | 42 | } |
| 77 | 43 | |
| 78 | −static void wiimote_worker(struct work_struct *work) | |
| 44 | +static void wiimote_queue_worker(struct work_struct *work) | |
| 79 | 45 | { |
| 80 | − struct wiimote_data *wdata = container_of(work, struct wiimote_data, | |
| 81 | − worker); | |
| 46 | + struct wiimote_queue *queue = container_of(work, struct wiimote_queue, | |
| 47 | + worker); | |
| 48 | + struct wiimote_data *wdata = container_of(queue, struct wiimote_data, | |
| 49 | + queue); | |
| 82 | 50 | unsigned long flags; |
| 51 | + int ret; | |
| 83 | 52 | |
| 84 | − spin_lock_irqsave(&wdata->qlock, flags); | |
| 53 | + spin_lock_irqsave(&wdata->queue.lock, flags); | |
| 85 | 54 | |
| 86 | − while (wdata->head != wdata->tail) { | |
| 87 | − spin_unlock_irqrestore(&wdata->qlock, flags); | |
| 88 | − wiimote_hid_send(wdata->hdev, wdata->outq[wdata->tail].data, | |
| 89 | − wdata->outq[wdata->tail].size); | |
| 90 | − spin_lock_irqsave(&wdata->qlock, flags); | |
| 55 | + while (wdata->queue.head != wdata->queue.tail) { | |
| 56 | + spin_unlock_irqrestore(&wdata->queue.lock, flags); | |
| 57 | + ret = wiimote_hid_send(wdata->hdev, | |
| 58 | + wdata->queue.outq[wdata->queue.tail].data, | |
| 59 | + wdata->queue.outq[wdata->queue.tail].size); | |
| 60 | + if (ret < 0) { | |
| 61 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 62 | + wiimote_cmd_abort(wdata); | |
| 63 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 64 | + } | |
| 65 | + spin_lock_irqsave(&wdata->queue.lock, flags); | |
| 91 | 66 | |
| 92 | − wdata->tail = (wdata->tail + 1) % WIIMOTE_BUFSIZE; | |
| 67 | + wdata->queue.tail = (wdata->queue.tail + 1) % WIIMOTE_BUFSIZE; | |
| 93 | 68 | } |
| 94 | 69 | |
| 95 | − spin_unlock_irqrestore(&wdata->qlock, flags); | |
| 70 | + spin_unlock_irqrestore(&wdata->queue.lock, flags); | |
| 96 | 71 | } |
| 97 | 72 | |
| 98 | 73 | static void wiimote_queue(struct wiimote_data *wdata, const __u8 *buffer, |
| @@ -103,7 +78,9 @@ static void wiimote_queue(struct wiimote_data *wdata, const __u8 *buffer, · 4 unmodified lines | ||
| 103 | 78 | |
| 104 | 79 | if (count > HID_MAX_BUFFER_SIZE) { |
| 105 | 80 | hid_warn(wdata->hdev, "Sending too large output report\n"); |
| 106 | − return; | |
| 81 | + | |
| 82 | + spin_lock_irqsave(&wdata->queue.lock, flags); | |
| 83 | + goto out_error; | |
| 107 | 84 | } |
| 108 | 85 | |
| 109 | 86 | /* |
| @@ -116,22 +93,28 @@ static void wiimote_queue(struct wiimote_data *wdata, const __u8 *buffer, · 6 unmodified lines | ||
| 116 | 93 | * will reschedule itself until the queue is empty. |
| 117 | 94 | */ |
| 118 | 95 | |
| 119 | − spin_lock_irqsave(&wdata->qlock, flags); | |
| 96 | + spin_lock_irqsave(&wdata->queue.lock, flags); | |
| 120 | 97 | |
| 121 | − memcpy(wdata->outq[wdata->head].data, buffer, count); | |
| 122 | − wdata->outq[wdata->head].size = count; | |
| 123 | − newhead = (wdata->head + 1) % WIIMOTE_BUFSIZE; | |
| 98 | + memcpy(wdata->queue.outq[wdata->queue.head].data, buffer, count); | |
| 99 | + wdata->queue.outq[wdata->queue.head].size = count; | |
| 100 | + newhead = (wdata->queue.head + 1) % WIIMOTE_BUFSIZE; | |
| 124 | 101 | |
| 125 | − if (wdata->head == wdata->tail) { | |
| 126 | − wdata->head = newhead; | |
| 127 | − schedule_work(&wdata->worker); | |
| 128 | − } else if (newhead != wdata->tail) { | |
| 129 | − wdata->head = newhead; | |
| 102 | + if (wdata->queue.head == wdata->queue.tail) { | |
| 103 | + wdata->queue.head = newhead; | |
| 104 | + schedule_work(&wdata->queue.worker); | |
| 105 | + } else if (newhead != wdata->queue.tail) { | |
| 106 | + wdata->queue.head = newhead; | |
| 130 | 107 | } else { |
| 131 | 108 | hid_warn(wdata->hdev, "Output queue is full"); |
| 109 | + goto out_error; | |
| 132 | 110 | } |
| 133 | 111 | |
| 134 | − spin_unlock_irqrestore(&wdata->qlock, flags); | |
| 112 | + goto out_unlock; | |
| 113 | + | |
| 114 | +out_error: | |
| 115 | + wiimote_cmd_abort(wdata); | |
| 116 | +out_unlock: | |
| 117 | + spin_unlock_irqrestore(&wdata->queue.lock, flags); | |
| 135 | 118 | } |
| 136 | 119 | |
| 137 | 120 | /* |
| @@ -147,7 +130,7 @@ static inline void wiiproto_keep_rumble(struct wiimote_data *wdata, __u8 *cmd1) · 9 unmodified lines | ||
| 147 | 130 | *cmd1 |= 0x01; |
| 148 | 131 | } |
| 149 | 132 | |
| 150 | −static void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble) | |
| 133 | +void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble) | |
| 151 | 134 | { |
| 152 | 135 | __u8 cmd[2]; |
| 153 | 136 | |
| @@ -167,7 +150,7 @@ static void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble) · 13 unmodified lines | ||
| 167 | 150 | wiimote_queue(wdata, cmd, sizeof(cmd)); |
| 168 | 151 | } |
| 169 | 152 | |
| 170 | −static void wiiproto_req_leds(struct wiimote_data *wdata, int leds) | |
| 153 | +void wiiproto_req_leds(struct wiimote_data *wdata, int leds) | |
| 171 | 154 | { |
| 172 | 155 | __u8 cmd[2]; |
| 173 | 156 | |
| @@ -196,17 +179,46 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds) · 22 unmodified lines | ||
| 196 | 179 | * Check what peripherals of the wiimote are currently |
| 197 | 180 | * active and select a proper DRM that supports all of |
| 198 | 181 | * the requested data inputs. |
| 182 | + * | |
| 183 | + * Not all combinations are actually supported. The following | |
| 184 | + * combinations work only with limitations: | |
| 185 | + * - IR cam in extended or full mode disables any data transmission | |
| 186 | + * of extension controllers. There is no DRM mode that supports | |
| 187 | + * extension bytes plus extended/full IR. | |
| 188 | + * - IR cam with accelerometer and extension *_EXT8 is not supported. | |
| 189 | + * However, all extensions that need *_EXT8 are devices that don't | |
| 190 | + * support IR cameras. Hence, this shouldn't happen under normal | |
| 191 | + * operation. | |
| 192 | + * - *_EXT16 is only supported in combination with buttons and | |
| 193 | + * accelerometer. No IR or similar can be active simultaneously. As | |
| 194 | + * above, all modules that require it are mutually exclusive with | |
| 195 | + * IR/etc. so this doesn't matter. | |
| 199 | 196 | */ |
| 200 | 197 | static __u8 select_drm(struct wiimote_data *wdata) |
| 201 | 198 | { |
| 202 | 199 | __u8 ir = wdata->state.flags & WIIPROTO_FLAGS_IR; |
| 203 | − bool ext = wiiext_active(wdata); | |
| 200 | + bool ext; | |
| 204 | 201 | |
| 205 | − if (ir == WIIPROTO_FLAG_IR_BASIC) { | |
| 206 | − if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) | |
| 207 | − return WIIPROTO_REQ_DRM_KAIE; | |
| 202 | + ext = (wdata->state.flags & WIIPROTO_FLAG_EXT_USED) || | |
| 203 | + (wdata->state.flags & WIIPROTO_FLAG_MP_USED); | |
| 204 | + | |
| 205 | + /* some 3rd-party balance-boards are hard-coded to KEE, *sigh* */ | |
| 206 | + if (wdata->state.devtype == WIIMOTE_DEV_BALANCE_BOARD) { | |
| 207 | + if (ext) | |
| 208 | + return WIIPROTO_REQ_DRM_KEE; | |
| 208 | 209 | else |
| 210 | + return WIIPROTO_REQ_DRM_K; | |
| 211 | + } | |
| 212 | + | |
| 213 | + if (ir == WIIPROTO_FLAG_IR_BASIC) { | |
| 214 | + if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) { | |
| 215 | + if (ext) | |
| 216 | + return WIIPROTO_REQ_DRM_KAIE; | |
| 217 | + else | |
| 218 | + return WIIPROTO_REQ_DRM_KAI; | |
| 219 | + } else { | |
| 209 | 220 | return WIIPROTO_REQ_DRM_KIE; |
| 221 | + } | |
| 210 | 222 | } else if (ir == WIIPROTO_FLAG_IR_EXT) { |
| 211 | 223 | return WIIPROTO_REQ_DRM_KAI; |
| 212 | 224 | } else if (ir == WIIPROTO_FLAG_IR_FULL) { |
| @@ -219,7 +231,7 @@ static __u8 select_drm(struct wiimote_data *wdata) · 6 unmodified lines | ||
| 219 | 231 | return WIIPROTO_REQ_DRM_KA; |
| 220 | 232 | } else { |
| 221 | 233 | if (ext) |
| 222 | − return WIIPROTO_REQ_DRM_KE; | |
| 234 | + return WIIPROTO_REQ_DRM_KEE; | |
| 223 | 235 | else |
| 224 | 236 | return WIIPROTO_REQ_DRM_K; |
| 225 | 237 | } |
| @@ -230,7 +242,9 @@ void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm) · 4 unmodified lines | ||
| 230 | 242 | { |
| 231 | 243 | __u8 cmd[3]; |
| 232 | 244 | |
| 233 | − if (drm == WIIPROTO_REQ_NULL) | |
| 245 | + if (wdata->state.flags & WIIPROTO_FLAG_DRM_LOCKED) | |
| 246 | + drm = wdata->state.drm; | |
| 247 | + else if (drm == WIIPROTO_REQ_NULL) | |
| 234 | 248 | drm = select_drm(wdata); |
| 235 | 249 | |
| 236 | 250 | cmd[0] = WIIPROTO_REQ_DRM; |
| @@ -242,7 +256,7 @@ void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm) · 5 unmodified lines | ||
| 242 | 256 | wiimote_queue(wdata, cmd, sizeof(cmd)); |
| 243 | 257 | } |
| 244 | 258 | |
| 245 | −static void wiiproto_req_status(struct wiimote_data *wdata) | |
| 259 | +void wiiproto_req_status(struct wiimote_data *wdata) | |
| 246 | 260 | { |
| 247 | 261 | __u8 cmd[2]; |
| 248 | 262 | |
| @@ -253,7 +267,7 @@ static void wiiproto_req_status(struct wiimote_data *wdata) · 4 unmodified lines | ||
| 253 | 267 | wiimote_queue(wdata, cmd, sizeof(cmd)); |
| 254 | 268 | } |
| 255 | 269 | |
| 256 | −static void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel) | |
| 270 | +void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel) | |
| 257 | 271 | { |
| 258 | 272 | accel = !!accel; |
| 259 | 273 | if (accel == !!(wdata->state.flags & WIIPROTO_FLAG_ACCEL)) |
| @@ -267,7 +281,7 @@ static void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel) · 7 unmodified lines | ||
| 267 | 281 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); |
| 268 | 282 | } |
| 269 | 283 | |
| 270 | −static void wiiproto_req_ir1(struct wiimote_data *wdata, __u8 flags) | |
| 284 | +void wiiproto_req_ir1(struct wiimote_data *wdata, __u8 flags) | |
| 271 | 285 | { |
| 272 | 286 | __u8 cmd[2]; |
| 273 | 287 | |
| @@ -278,7 +292,7 @@ static void wiiproto_req_ir1(struct wiimote_data *wdata, __u8 flags) · 4 unmodified lines | ||
| 278 | 292 | wiimote_queue(wdata, cmd, sizeof(cmd)); |
| 279 | 293 | } |
| 280 | 294 | |
| 281 | −static void wiiproto_req_ir2(struct wiimote_data *wdata, __u8 flags) | |
| 295 | +void wiiproto_req_ir2(struct wiimote_data *wdata, __u8 flags) | |
| 282 | 296 | { |
| 283 | 297 | __u8 cmd[2]; |
| 284 | 298 | |
| @@ -394,399 +408,998 @@ ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, __u8 *rmem, · 109 unmodified lines | ||
| 394 | 408 | return ret; |
| 395 | 409 | } |
| 396 | 410 | |
| 397 | −static int wiimote_battery_get_property(struct power_supply *psy, | |
| 398 | − enum power_supply_property psp, | |
| 399 | − union power_supply_propval *val) | |
| 411 | +/* requires the cmd-mutex to be held */ | |
| 412 | +static int wiimote_cmd_init_ext(struct wiimote_data *wdata) | |
| 400 | 413 | { |
| 401 | − struct wiimote_data *wdata = container_of(psy, | |
| 402 | − struct wiimote_data, battery); | |
| 403 | − int ret = 0, state; | |
| 404 | − unsigned long flags; | |
| 414 | + __u8 wmem; | |
| 415 | + int ret; | |
| 405 | 416 | |
| 406 | − if (psp == POWER_SUPPLY_PROP_SCOPE) { | |
| 407 | − val->intval = POWER_SUPPLY_SCOPE_DEVICE; | |
| 408 | − return 0; | |
| 409 | − } | |
| 417 | + /* initialize extension */ | |
| 418 | + wmem = 0x55; | |
| 419 | + ret = wiimote_cmd_write(wdata, 0xa400f0, &wmem, sizeof(wmem)); | |
| 420 | + if (ret) | |
| 421 | + return ret; | |
| 410 | 422 | |
| 411 | − ret = wiimote_cmd_acquire(wdata); | |
| 423 | + /* disable default encryption */ | |
| 424 | + wmem = 0x0; | |
| 425 | + ret = wiimote_cmd_write(wdata, 0xa400fb, &wmem, sizeof(wmem)); | |
| 412 | 426 | if (ret) |
| 413 | 427 | return ret; |
| 414 | 428 | |
| 415 | − spin_lock_irqsave(&wdata->state.lock, flags); | |
| 416 | − wiimote_cmd_set(wdata, WIIPROTO_REQ_SREQ, 0); | |
| 417 | − wiiproto_req_status(wdata); | |
| 418 | − spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 429 | + return 0; | |
| 430 | +} | |
| 419 | 431 | |
| 420 | − ret = wiimote_cmd_wait(wdata); | |
| 421 | − state = wdata->state.cmd_battery; | |
| 422 | − wiimote_cmd_release(wdata); | |
| 432 | +/* requires the cmd-mutex to be held */ | |
| 433 | +static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata, __u8 *rmem) | |
| 434 | +{ | |
| 435 | + int ret; | |
| 436 | + | |
| 437 | + /* read extension ID */ | |
| 438 | + ret = wiimote_cmd_read(wdata, 0xa400fa, rmem, 6); | |
| 439 | + if (ret != 6) | |
| 440 | + return WIIMOTE_EXT_NONE; | |
| 441 | + | |
| 442 | + hid_dbg(wdata->hdev, "extension ID: %02x:%02x %02x:%02x %02x:%02x\n", | |
| 443 | + rmem[0], rmem[1], rmem[2], rmem[3], rmem[4], rmem[5]); | |
| 423 | 444 | |
| 445 | + if (rmem[0] == 0xff && rmem[1] == 0xff && rmem[2] == 0xff && | |
| 446 | + rmem[3] == 0xff && rmem[4] == 0xff && rmem[5] == 0xff) | |
| 447 | + return WIIMOTE_EXT_NONE; | |
| 448 | + | |
| 449 | + if (rmem[4] == 0x00 && rmem[5] == 0x00) | |
| 450 | + return WIIMOTE_EXT_NUNCHUK; | |
| 451 | + if (rmem[4] == 0x01 && rmem[5] == 0x01) | |
| 452 | + return WIIMOTE_EXT_CLASSIC_CONTROLLER; | |
| 453 | + if (rmem[4] == 0x04 && rmem[5] == 0x02) | |
| 454 | + return WIIMOTE_EXT_BALANCE_BOARD; | |
| 455 | + if (rmem[4] == 0x01 && rmem[5] == 0x20) | |
| 456 | + return WIIMOTE_EXT_PRO_CONTROLLER; | |
| 457 | + | |
| 458 | + return WIIMOTE_EXT_UNKNOWN; | |
| 459 | +} | |
| 460 | + | |
| 461 | +/* requires the cmd-mutex to be held */ | |
| 462 | +static int wiimote_cmd_init_mp(struct wiimote_data *wdata) | |
| 463 | +{ | |
| 464 | + __u8 wmem; | |
| 465 | + int ret; | |
| 466 | + | |
| 467 | + /* initialize MP */ | |
| 468 | + wmem = 0x55; | |
| 469 | + ret = wiimote_cmd_write(wdata, 0xa600f0, &wmem, sizeof(wmem)); | |
| 424 | 470 | if (ret) |
| 425 | 471 | return ret; |
| 426 | 472 | |
| 427 | − switch (psp) { | |
| 428 | − case POWER_SUPPLY_PROP_CAPACITY: | |
| 429 | − val->intval = state * 100 / 255; | |
| 430 | − break; | |
| 431 | − default: | |
| 432 | − ret = -EINVAL; | |
| 433 | − break; | |
| 473 | + /* disable default encryption */ | |
| 474 | + wmem = 0x0; | |
| 475 | + ret = wiimote_cmd_write(wdata, 0xa600fb, &wmem, sizeof(wmem)); | |
| 476 | + if (ret) | |
| 477 | + return ret; | |
| 478 | + | |
| 479 | + return 0; | |
| 480 | +} | |
| 481 | + | |
| 482 | +/* requires the cmd-mutex to be held */ | |
| 483 | +static bool wiimote_cmd_map_mp(struct wiimote_data *wdata, __u8 exttype) | |
| 484 | +{ | |
| 485 | + __u8 wmem; | |
| 486 | + | |
| 487 | + /* map MP with correct pass-through mode */ | |
| 488 | + switch (exttype) { | |
| 489 | + case WIIMOTE_EXT_CLASSIC_CONTROLLER: | |
| 490 | + wmem = 0x07; | |
| 491 | + break; | |
| 492 | + case WIIMOTE_EXT_NUNCHUK: | |
| 493 | + wmem = 0x05; | |
| 494 | + break; | |
| 495 | + default: | |
| 496 | + wmem = 0x04; | |
| 497 | + break; | |
| 434 | 498 | } |
| 435 | 499 | |
| 436 | − return ret; | |
| 500 | + return wiimote_cmd_write(wdata, 0xa600fe, &wmem, sizeof(wmem)); | |
| 437 | 501 | } |
| 438 | 502 | |
| 439 | −static int wiimote_init_ir(struct wiimote_data *wdata, __u16 mode) | |
| 503 | +/* requires the cmd-mutex to be held */ | |
| 504 | +static bool wiimote_cmd_read_mp(struct wiimote_data *wdata, __u8 *rmem) | |
| 440 | 505 | { |
| 441 | 506 | int ret; |
| 442 | − unsigned long flags; | |
| 443 | − __u8 format = 0; | |
| 444 | − static const __u8 data_enable[] = { 0x01 }; | |
| 445 | − static const __u8 data_sens1[] = { 0x02, 0x00, 0x00, 0x71, 0x01, | |
| 446 | − 0x00, 0xaa, 0x00, 0x64 }; | |
| 447 | − static const __u8 data_sens2[] = { 0x63, 0x03 }; | |
| 448 | − static const __u8 data_fin[] = { 0x08 }; | |
| 449 | 507 | |
| 450 | − spin_lock_irqsave(&wdata->state.lock, flags); | |
| 508 | + /* read motion plus ID */ | |
| 509 | + ret = wiimote_cmd_read(wdata, 0xa600fa, rmem, 6); | |
| 510 | + if (ret != 6) | |
| 511 | + return false; | |
| 451 | 512 | |
| 452 | − if (mode == (wdata->state.flags & WIIPROTO_FLAGS_IR)) { | |
| 453 | − spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 454 | − return 0; | |
| 455 | − } | |
| 513 | + hid_dbg(wdata->hdev, "motion plus ID: %02x:%02x %02x:%02x %02x:%02x\n", | |
| 514 | + rmem[0], rmem[1], rmem[2], rmem[3], rmem[4], rmem[5]); | |
| 456 | 515 | |
| 457 | − if (mode == 0) { | |
| 458 | − wdata->state.flags &= ~WIIPROTO_FLAGS_IR; | |
| 459 | − wiiproto_req_ir1(wdata, 0); | |
| 460 | − wiiproto_req_ir2(wdata, 0); | |
| 461 | − wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | |
| 462 | − spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 463 | − return 0; | |
| 464 | − } | |
| 516 | + if (rmem[5] == 0x05) | |
| 517 | + return true; | |
| 465 | 518 | |
| 466 | − spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 519 | + hid_info(wdata->hdev, "unknown motion plus ID: %02x:%02x %02x:%02x %02x:%02x\n", | |
| 520 | + rmem[0], rmem[1], rmem[2], rmem[3], rmem[4], rmem[5]); | |
| 467 | 521 | |
| 468 | − ret = wiimote_cmd_acquire(wdata); | |
| 469 | − if (ret) | |
| 470 | − return ret; | |
| 522 | + return false; | |
| 523 | +} | |
| 471 | 524 | |
| 472 | − /* send PIXEL CLOCK ENABLE cmd first */ | |
| 473 | − spin_lock_irqsave(&wdata->state.lock, flags); | |
| 474 | − wiimote_cmd_set(wdata, WIIPROTO_REQ_IR1, 0); | |
| 475 | − wiiproto_req_ir1(wdata, 0x06); | |
| 476 | − spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 525 | +/* requires the cmd-mutex to be held */ | |
| 526 | +static __u8 wiimote_cmd_read_mp_mapped(struct wiimote_data *wdata) | |
| 527 | +{ | |
| 528 | + int ret; | |
| 529 | + __u8 rmem[6]; | |
| 477 | 530 | |
| 478 | − ret = wiimote_cmd_wait(wdata); | |
| 479 | − if (ret) | |
| 480 | − goto unlock; | |
| 481 | − if (wdata->state.cmd_err) { | |
| 482 | − ret = -EIO; | |
| 483 | − goto unlock; | |
| 531 | + /* read motion plus ID */ | |
| 532 | + ret = wiimote_cmd_read(wdata, 0xa400fa, rmem, 6); | |
| 533 | + if (ret != 6) | |
| 534 | + return WIIMOTE_MP_NONE; | |
| 535 | + | |
| 536 | + hid_dbg(wdata->hdev, "mapped motion plus ID: %02x:%02x %02x:%02x %02x:%02x\n", | |
| 537 | + rmem[0], rmem[1], rmem[2], rmem[3], rmem[4], rmem[5]); | |
| 538 | + | |
| 539 | + if (rmem[0] == 0xff && rmem[1] == 0xff && rmem[2] == 0xff && | |
| 540 | + rmem[3] == 0xff && rmem[4] == 0xff && rmem[5] == 0xff) | |
| 541 | + return WIIMOTE_MP_NONE; | |
| 542 | + | |
| 543 | + if (rmem[4] == 0x04 && rmem[5] == 0x05) | |
| 544 | + return WIIMOTE_MP_SINGLE; | |
| 545 | + else if (rmem[4] == 0x05 && rmem[5] == 0x05) | |
| 546 | + return WIIMOTE_MP_PASSTHROUGH_NUNCHUK; | |
| 547 | + else if (rmem[4] == 0x07 && rmem[5] == 0x05) | |
| 548 | + return WIIMOTE_MP_PASSTHROUGH_CLASSIC; | |
| 549 | + | |
| 550 | + return WIIMOTE_MP_UNKNOWN; | |
| 551 | +} | |
| 552 | + | |
| 553 | +/* device module handling */ | |
| 554 | + | |
| 555 | +static const __u8 * const wiimote_devtype_mods[WIIMOTE_DEV_NUM] = { | |
| 556 | + [WIIMOTE_DEV_PENDING] = (const __u8[]){ | |
| 557 | + WIIMOD_NULL, | |
| 558 | + }, | |
| 559 | + [WIIMOTE_DEV_UNKNOWN] = (const __u8[]){ | |
| 560 | + WIIMOD_NO_MP, | |
| 561 | + WIIMOD_NULL, | |
| 562 | + }, | |
| 563 | + [WIIMOTE_DEV_GENERIC] = (const __u8[]){ | |
| 564 | + WIIMOD_KEYS, | |
| 565 | + WIIMOD_RUMBLE, | |
| 566 | + WIIMOD_BATTERY, | |
| 567 | + WIIMOD_LED1, | |
| 568 | + WIIMOD_LED2, | |
| 569 | + WIIMOD_LED3, | |
| 570 | + WIIMOD_LED4, | |
| 571 | + WIIMOD_ACCEL, | |
| 572 | + WIIMOD_IR, | |
| 573 | + WIIMOD_NULL, | |
| 574 | + }, | |
| 575 | + [WIIMOTE_DEV_GEN10] = (const __u8[]){ | |
| 576 | + WIIMOD_KEYS, | |
| 577 | + WIIMOD_RUMBLE, | |
| 578 | + WIIMOD_BATTERY, | |
| 579 | + WIIMOD_LED1, | |
| 580 | + WIIMOD_LED2, | |
| 581 | + WIIMOD_LED3, | |
| 582 | + WIIMOD_LED4, | |
| 583 | + WIIMOD_ACCEL, | |
| 584 | + WIIMOD_IR, | |
| 585 | + WIIMOD_NULL, | |
| 586 | + }, | |
| 587 | + [WIIMOTE_DEV_GEN20] = (const __u8[]){ | |
| 588 | + WIIMOD_KEYS, | |
| 589 | + WIIMOD_RUMBLE, | |
| 590 | + WIIMOD_BATTERY, | |
| 591 | + WIIMOD_LED1, | |
| 592 | + WIIMOD_LED2, | |
| 593 | + WIIMOD_LED3, | |
| 594 | + WIIMOD_LED4, | |
| 595 | + WIIMOD_ACCEL, | |
| 596 | + WIIMOD_IR, | |
| 597 | + WIIMOD_BUILTIN_MP, | |
| 598 | + WIIMOD_NULL, | |
| 599 | + }, | |
| 600 | + [WIIMOTE_DEV_BALANCE_BOARD] = (const __u8[]) { | |
| 601 | + WIIMOD_BATTERY, | |
| 602 | + WIIMOD_LED1, | |
| 603 | + WIIMOD_NO_MP, | |
| 604 | + WIIMOD_NULL, | |
| 605 | + }, | |
| 606 | + [WIIMOTE_DEV_PRO_CONTROLLER] = (const __u8[]) { | |
| 607 | + WIIMOD_BATTERY, | |
| 608 | + WIIMOD_LED1, | |
| 609 | + WIIMOD_LED2, | |
| 610 | + WIIMOD_LED3, | |
| 611 | + WIIMOD_LED4, | |
| 612 | + WIIMOD_NO_MP, | |
| 613 | + WIIMOD_NULL, | |
| 614 | + }, | |
| 615 | +}; | |
| 616 | + | |
| 617 | +static void wiimote_modules_load(struct wiimote_data *wdata, | |
| 618 | + unsigned int devtype) | |
| 619 | +{ | |
| 620 | + bool need_input = false; | |
| 621 | + const __u8 *mods, *iter; | |
| 622 | + const struct wiimod_ops *ops; | |
| 623 | + int ret; | |
| 624 | + | |
| 625 | + mods = wiimote_devtype_mods[devtype]; | |
| 626 | + | |
| 627 | + for (iter = mods; *iter != WIIMOD_NULL; ++iter) { | |
| 628 | + if (wiimod_table[*iter]->flags & WIIMOD_FLAG_INPUT) { | |
| 629 | + need_input = true; | |
| 630 | + break; | |
| 631 | + } | |
| 484 | 632 | } |
| 485 | 633 | |
| 486 | − /* enable IR LOGIC */ | |
| 487 | − spin_lock_irqsave(&wdata->state.lock, flags); | |
| 488 | − wiimote_cmd_set(wdata, WIIPROTO_REQ_IR2, 0); | |
| 489 | − wiiproto_req_ir2(wdata, 0x06); | |
| 490 | − spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 634 | + if (need_input) { | |
| 635 | + wdata->input = input_allocate_device(); | |
| 636 | + if (!wdata->input) | |
| 637 | + return; | |
| 638 | + | |
| 639 | + input_set_drvdata(wdata->input, wdata); | |
| 640 | + wdata->input->dev.parent = &wdata->hdev->dev; | |
| 641 | + wdata->input->id.bustype = wdata->hdev->bus; | |
| 642 | + wdata->input->id.vendor = wdata->hdev->vendor; | |
| 643 | + wdata->input->id.product = wdata->hdev->product; | |
| 644 | + wdata->input->id.version = wdata->hdev->version; | |
| 645 | + wdata->input->name = WIIMOTE_NAME; | |
| 646 | + } | |
| 491 | 647 | |
| 492 | − ret = wiimote_cmd_wait(wdata); | |
| 493 | − if (ret) | |
| 494 | − goto unlock; | |
| 495 | − if (wdata->state.cmd_err) { | |
| 496 | − ret = -EIO; | |
| 497 | − goto unlock; | |
| 648 | + for (iter = mods; *iter != WIIMOD_NULL; ++iter) { | |
| 649 | + ops = wiimod_table[*iter]; | |
| 650 | + if (!ops->probe) | |
| 651 | + continue; | |
| 652 | + | |
| 653 | + ret = ops->probe(ops, wdata); | |
| 654 | + if (ret) | |
| 655 | + goto error; | |
| 498 | 656 | } |
| 499 | 657 | |
| 500 | − /* enable IR cam but do not make it send data, yet */ | |
| 501 | − ret = wiimote_cmd_write(wdata, 0xb00030, data_enable, | |
| 502 | − sizeof(data_enable)); | |
| 503 | − if (ret) | |
| 504 | − goto unlock; | |
| 658 | + if (wdata->input) { | |
| 659 | + ret = input_register_device(wdata->input); | |
| 660 | + if (ret) | |
| 661 | + goto error; | |
| 662 | + } | |
| 505 | 663 | |
| 506 | − /* write first sensitivity block */ | |
| 507 | − ret = wiimote_cmd_write(wdata, 0xb00000, data_sens1, | |
| 508 | − sizeof(data_sens1)); | |
| 509 | − if (ret) | |
| 510 | − goto unlock; | |
| 664 | + spin_lock_irq(&wdata->state.lock); | |
| 665 | + wdata->state.devtype = devtype; | |
| 666 | + spin_unlock_irq(&wdata->state.lock); | |
| 667 | + return; | |
| 511 | 668 | |
| 512 | − /* write second sensitivity block */ | |
| 513 | − ret = wiimote_cmd_write(wdata, 0xb0001a, data_sens2, | |
| 514 | − sizeof(data_sens2)); | |
| 515 | − if (ret) | |
| 516 | − goto unlock; | |
| 669 | +error: | |
| 670 | + for ( ; iter-- != mods; ) { | |
| 671 | + ops = wiimod_table[*iter]; | |
| 672 | + if (ops->remove) | |
| 673 | + ops->remove(ops, wdata); | |
| 674 | + } | |
| 517 | 675 | |
| 518 | − /* put IR cam into desired state */ | |
| 519 | − switch (mode) { | |
| 520 | − case WIIPROTO_FLAG_IR_FULL: | |
| 521 | − format = 5; | |
| 522 | − break; | |
| 523 | − case WIIPROTO_FLAG_IR_EXT: | |
| 524 | − format = 3; | |
| 525 | − break; | |
| 526 | − case WIIPROTO_FLAG_IR_BASIC: | |
| 527 | − format = 1; | |
| 528 | − break; | |
| 676 | + if (wdata->input) { | |
| 677 | + input_free_device(wdata->input); | |
| 678 | + wdata->input = NULL; | |
| 529 | 679 | } |
| 530 | − ret = wiimote_cmd_write(wdata, 0xb00033, &format, sizeof(format)); | |
| 531 | − if (ret) | |
| 532 | − goto unlock; | |
| 680 | +} | |
| 533 | 681 | |
| 534 | − /* make IR cam send data */ | |
| 535 | − ret = wiimote_cmd_write(wdata, 0xb00030, data_fin, sizeof(data_fin)); | |
| 536 | − if (ret) | |
| 537 | − goto unlock; | |
| 682 | +static void wiimote_modules_unload(struct wiimote_data *wdata) | |
| 683 | +{ | |
| 684 | + const __u8 *mods, *iter; | |
| 685 | + const struct wiimod_ops *ops; | |
| 686 | + unsigned long flags; | |
| 687 | + | |
| 688 | + mods = wiimote_devtype_mods[wdata->state.devtype]; | |
| 538 | 689 | |
| 539 | − /* request new DRM mode compatible to IR mode */ | |
| 540 | 690 | spin_lock_irqsave(&wdata->state.lock, flags); |
| 541 | − wdata->state.flags &= ~WIIPROTO_FLAGS_IR; | |
| 542 | − wdata->state.flags |= mode & WIIPROTO_FLAGS_IR; | |
| 543 | − wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | |
| 691 | + wdata->state.devtype = WIIMOTE_DEV_UNKNOWN; | |
| 544 | 692 | spin_unlock_irqrestore(&wdata->state.lock, flags); |
| 545 | 693 | |
| 546 | −unlock: | |
| 547 | − wiimote_cmd_release(wdata); | |
| 548 | − return ret; | |
| 694 | + /* find end of list */ | |
| 695 | + for (iter = mods; *iter != WIIMOD_NULL; ++iter) | |
| 696 | + /* empty */ ; | |
| 697 | + | |
| 698 | + if (wdata->input) { | |
| 699 | + input_get_device(wdata->input); | |
| 700 | + input_unregister_device(wdata->input); | |
| 701 | + } | |
| 702 | + | |
| 703 | + for ( ; iter-- != mods; ) { | |
| 704 | + ops = wiimod_table[*iter]; | |
| 705 | + if (ops->remove) | |
| 706 | + ops->remove(ops, wdata); | |
| 707 | + } | |
| 708 | + | |
| 709 | + if (wdata->input) { | |
| 710 | + input_put_device(wdata->input); | |
| 711 | + wdata->input = NULL; | |
| 712 | + } | |
| 549 | 713 | } |
| 550 | 714 | |
| 551 | −static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev) | |
| 715 | +/* device extension handling */ | |
| 716 | + | |
| 717 | +static void wiimote_ext_load(struct wiimote_data *wdata, unsigned int ext) | |
| 552 | 718 | { |
| 553 | − struct wiimote_data *wdata; | |
| 554 | − struct device *dev = led_dev->dev->parent; | |
| 555 | − int i; | |
| 556 | 719 | unsigned long flags; |
| 557 | − bool value = false; | |
| 720 | + const struct wiimod_ops *ops; | |
| 721 | + int ret; | |
| 558 | 722 | |
| 559 | − wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); | |
| 723 | + ops = wiimod_ext_table[ext]; | |
| 560 | 724 | |
| 561 | − for (i = 0; i < 4; ++i) { | |
| 562 | − if (wdata->leds[i] == led_dev) { | |
| 563 | − spin_lock_irqsave(&wdata->state.lock, flags); | |
| 564 | − value = wdata->state.flags & WIIPROTO_FLAG_LED(i + 1); | |
| 565 | − spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 566 | − break; | |
| 567 | − } | |
| 725 | + if (ops->probe) { | |
| 726 | + ret = ops->probe(ops, wdata); | |
| 727 | + if (ret) | |
| 728 | + ext = WIIMOTE_EXT_UNKNOWN; | |
| 568 | 729 | } |
| 569 | 730 | |
| 570 | − return value ? LED_FULL : LED_OFF; | |
| 731 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 732 | + wdata->state.exttype = ext; | |
| 733 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 571 | 734 | } |
| 572 | 735 | |
| 573 | −static void wiimote_leds_set(struct led_classdev *led_dev, | |
| 574 | − enum led_brightness value) | |
| 736 | +static void wiimote_ext_unload(struct wiimote_data *wdata) | |
| 575 | 737 | { |
| 576 | − struct wiimote_data *wdata; | |
| 577 | − struct device *dev = led_dev->dev->parent; | |
| 578 | − int i; | |
| 579 | 738 | unsigned long flags; |
| 580 | − __u8 state, flag; | |
| 739 | + const struct wiimod_ops *ops; | |
| 581 | 740 | |
| 582 | − wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); | |
| 741 | + ops = wiimod_ext_table[wdata->state.exttype]; | |
| 583 | 742 | |
| 584 | − for (i = 0; i < 4; ++i) { | |
| 585 | − if (wdata->leds[i] == led_dev) { | |
| 586 | − flag = WIIPROTO_FLAG_LED(i + 1); | |
| 587 | − spin_lock_irqsave(&wdata->state.lock, flags); | |
| 588 | − state = wdata->state.flags; | |
| 589 | − if (value == LED_OFF) | |
| 590 | − wiiproto_req_leds(wdata, state & ~flag); | |
| 591 | − else | |
| 592 | − wiiproto_req_leds(wdata, state | flag); | |
| 593 | − spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 594 | − break; | |
| 595 | − } | |
| 743 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 744 | + wdata->state.exttype = WIIMOTE_EXT_UNKNOWN; | |
| 745 | + wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED; | |
| 746 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 747 | + | |
| 748 | + if (ops->remove) | |
| 749 | + ops->remove(ops, wdata); | |
| 750 | +} | |
| 751 | + | |
| 752 | +static void wiimote_mp_load(struct wiimote_data *wdata) | |
| 753 | +{ | |
| 754 | + unsigned long flags; | |
| 755 | + const struct wiimod_ops *ops; | |
| 756 | + int ret; | |
| 757 | + __u8 mode = 2; | |
| 758 | + | |
| 759 | + ops = &wiimod_mp; | |
| 760 | + if (ops->probe) { | |
| 761 | + ret = ops->probe(ops, wdata); | |
| 762 | + if (ret) | |
| 763 | + mode = 1; | |
| 596 | 764 | } |
| 765 | + | |
| 766 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 767 | + wdata->state.mp = mode; | |
| 768 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 597 | 769 | } |
| 598 | 770 | |
| 599 | −static int wiimote_ff_play(struct input_dev *dev, void *data, | |
| 600 | − struct ff_effect *eff) | |
| 771 | +static void wiimote_mp_unload(struct wiimote_data *wdata) | |
| 601 | 772 | { |
| 602 | − struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 603 | − __u8 value; | |
| 604 | 773 | unsigned long flags; |
| 774 | + const struct wiimod_ops *ops; | |
| 605 | 775 | |
| 606 | − /* | |
| 607 | − * The wiimote supports only a single rumble motor so if any magnitude | |
| 608 | − * is set to non-zero then we start the rumble motor. If both are set to | |
| 609 | − * zero, we stop the rumble motor. | |
| 610 | − */ | |
| 776 | + if (wdata->state.mp < 2) | |
| 777 | + return; | |
| 611 | 778 | |
| 612 | − if (eff->u.rumble.strong_magnitude || eff->u.rumble.weak_magnitude) | |
| 613 | − value = 1; | |
| 614 | − else | |
| 615 | − value = 0; | |
| 779 | + ops = &wiimod_mp; | |
| 616 | 780 | |
| 617 | 781 | spin_lock_irqsave(&wdata->state.lock, flags); |
| 618 | − wiiproto_req_rumble(wdata, value); | |
| 782 | + wdata->state.mp = 0; | |
| 783 | + wdata->state.flags &= ~WIIPROTO_FLAG_MP_USED; | |
| 619 | 784 | spin_unlock_irqrestore(&wdata->state.lock, flags); |
| 620 | 785 | |
| 621 | − return 0; | |
| 786 | + if (ops->remove) | |
| 787 | + ops->remove(ops, wdata); | |
| 622 | 788 | } |
| 623 | 789 | |
| 624 | −static int wiimote_input_open(struct input_dev *dev) | |
| 625 | −{ | |
| 626 | − struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 790 | +/* device (re-)initialization and detection */ | |
| 627 | 791 | |
| 628 | − return hid_hw_open(wdata->hdev); | |
| 629 | −} | |
| 792 | +static const char *wiimote_devtype_names[WIIMOTE_DEV_NUM] = { | |
| 793 | + [WIIMOTE_DEV_PENDING] = "Pending", | |
| 794 | + [WIIMOTE_DEV_UNKNOWN] = "Unknown", | |
| 795 | + [WIIMOTE_DEV_GENERIC] = "Generic", | |
| 796 | + [WIIMOTE_DEV_GEN10] = "Nintendo Wii Remote (Gen 1)", | |
| 797 | + [WIIMOTE_DEV_GEN20] = "Nintendo Wii Remote Plus (Gen 2)", | |
| 798 | + [WIIMOTE_DEV_BALANCE_BOARD] = "Nintendo Wii Balance Board", | |
| 799 | + [WIIMOTE_DEV_PRO_CONTROLLER] = "Nintendo Wii U Pro Controller", | |
| 800 | +}; | |
| 630 | 801 | |
| 631 | −static void wiimote_input_close(struct input_dev *dev) | |
| 802 | +/* Try to guess the device type based on all collected information. We | |
| 803 | + * first try to detect by static extension types, then VID/PID and the | |
| 804 | + * device name. If we cannot detect the device, we use | |
| 805 | + * WIIMOTE_DEV_GENERIC so all modules will get probed on the device. */ | |
| 806 | +static void wiimote_init_set_type(struct wiimote_data *wdata, | |
| 807 | + __u8 exttype) | |
| 632 | 808 | { |
| 633 | − struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 809 | + __u8 devtype = WIIMOTE_DEV_GENERIC; | |
| 810 | + __u16 vendor, product; | |
| 811 | + const char *name; | |
| 812 | + | |
| 813 | + vendor = wdata->hdev->vendor; | |
| 814 | + product = wdata->hdev->product; | |
| 815 | + name = wdata->hdev->name; | |
| 816 | + | |
| 817 | + if (exttype == WIIMOTE_EXT_BALANCE_BOARD) { | |
| 818 | + devtype = WIIMOTE_DEV_BALANCE_BOARD; | |
| 819 | + goto done; | |
| 820 | + } else if (exttype == WIIMOTE_EXT_PRO_CONTROLLER) { | |
| 821 | + devtype = WIIMOTE_DEV_PRO_CONTROLLER; | |
| 822 | + goto done; | |
| 823 | + } | |
| 634 | 824 | |
| 635 | − hid_hw_close(wdata->hdev); | |
| 825 | + if (!strcmp(name, "Nintendo RVL-CNT-01")) { | |
| 826 | + devtype = WIIMOTE_DEV_GEN10; | |
| 827 | + goto done; | |
| 828 | + } else if (!strcmp(name, "Nintendo RVL-CNT-01-TR")) { | |
| 829 | + devtype = WIIMOTE_DEV_GEN20; | |
| 830 | + goto done; | |
| 831 | + } else if (!strcmp(name, "Nintendo RVL-WBC-01")) { | |
| 832 | + devtype = WIIMOTE_DEV_BALANCE_BOARD; | |
| 833 | + goto done; | |
| 834 | + } else if (!strcmp(name, "Nintendo RVL-CNT-01-UC")) { | |
| 835 | + devtype = WIIMOTE_DEV_PRO_CONTROLLER; | |
| 836 | + goto done; | |
| 837 | + } | |
| 838 | + | |
| 839 | + if (vendor == USB_VENDOR_ID_NINTENDO) { | |
| 840 | + if (product == USB_DEVICE_ID_NINTENDO_WIIMOTE) { | |
| 841 | + devtype = WIIMOTE_DEV_GEN10; | |
| 842 | + goto done; | |
| 843 | + } else if (product == USB_DEVICE_ID_NINTENDO_WIIMOTE2) { | |
| 844 | + devtype = WIIMOTE_DEV_GEN20; | |
| 845 | + goto done; | |
| 846 | + } | |
| 847 | + } | |
| 848 | + | |
| 849 | +done: | |
| 850 | + if (devtype == WIIMOTE_DEV_GENERIC) | |
| 851 | + hid_info(wdata->hdev, "cannot detect device; NAME: %s VID: %04x PID: %04x EXT: %04x\n", | |
| 852 | + name, vendor, product, exttype); | |
| 853 | + else | |
| 854 | + hid_info(wdata->hdev, "detected device: %s\n", | |
| 855 | + wiimote_devtype_names[devtype]); | |
| 856 | + | |
| 857 | + wiimote_modules_load(wdata, devtype); | |
| 636 | 858 | } |
| 637 | 859 | |
| 638 | −static int wiimote_accel_open(struct input_dev *dev) | |
| 860 | +static void wiimote_init_detect(struct wiimote_data *wdata) | |
| 639 | 861 | { |
| 640 | − struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 862 | + __u8 exttype = WIIMOTE_EXT_NONE, extdata[6]; | |
| 863 | + bool ext; | |
| 641 | 864 | int ret; |
| 642 | − unsigned long flags; | |
| 643 | 865 | |
| 644 | − ret = hid_hw_open(wdata->hdev); | |
| 866 | + wiimote_cmd_acquire_noint(wdata); | |
| 867 | + | |
| 868 | + spin_lock_irq(&wdata->state.lock); | |
| 869 | + wdata->state.devtype = WIIMOTE_DEV_UNKNOWN; | |
| 870 | + wiimote_cmd_set(wdata, WIIPROTO_REQ_SREQ, 0); | |
| 871 | + wiiproto_req_status(wdata); | |
| 872 | + spin_unlock_irq(&wdata->state.lock); | |
| 873 | + | |
| 874 | + ret = wiimote_cmd_wait_noint(wdata); | |
| 645 | 875 | if (ret) |
| 646 | − return ret; | |
| 876 | + goto out_release; | |
| 647 | 877 | |
| 648 | − spin_lock_irqsave(&wdata->state.lock, flags); | |
| 649 | − wiiproto_req_accel(wdata, true); | |
| 650 | − spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 878 | + spin_lock_irq(&wdata->state.lock); | |
| 879 | + ext = wdata->state.flags & WIIPROTO_FLAG_EXT_PLUGGED; | |
| 880 | + spin_unlock_irq(&wdata->state.lock); | |
| 651 | 881 | |
| 652 | − return 0; | |
| 882 | + if (!ext) | |
| 883 | + goto out_release; | |
| 884 | + | |
| 885 | + wiimote_cmd_init_ext(wdata); | |
| 886 | + exttype = wiimote_cmd_read_ext(wdata, extdata); | |
| 887 | + | |
| 888 | +out_release: | |
| 889 | + wiimote_cmd_release(wdata); | |
| 890 | + wiimote_init_set_type(wdata, exttype); | |
| 891 | + | |
| 892 | + /* schedule MP timer */ | |
| 893 | + spin_lock_irq(&wdata->state.lock); | |
| 894 | + if (!(wdata->state.flags & WIIPROTO_FLAG_BUILTIN_MP) && | |
| 895 | + !(wdata->state.flags & WIIPROTO_FLAG_NO_MP)) | |
| 896 | + mod_timer(&wdata->timer, jiffies + HZ * 4); | |
| 897 | + spin_unlock_irq(&wdata->state.lock); | |
| 653 | 898 | } |
| 654 | 899 | |
| 655 | −static void wiimote_accel_close(struct input_dev *dev) | |
| 900 | +/* | |
| 901 | + * MP hotplug events are not generated by the wiimote. Therefore, we need | |
| 902 | + * polling to detect it. We use a 4s interval for polling MP registers. This | |
| 903 | + * seems reasonable considering applications can trigger it manually via | |
| 904 | + * sysfs requests. | |
| 905 | + */ | |
| 906 | +static void wiimote_init_poll_mp(struct wiimote_data *wdata) | |
| 656 | 907 | { |
| 657 | − struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 658 | − unsigned long flags; | |
| 908 | + bool mp; | |
| 909 | + __u8 mpdata[6]; | |
| 659 | 910 | |
| 660 | − spin_lock_irqsave(&wdata->state.lock, flags); | |
| 661 | − wiiproto_req_accel(wdata, false); | |
| 662 | − spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 911 | + wiimote_cmd_acquire_noint(wdata); | |
| 912 | + wiimote_cmd_init_mp(wdata); | |
| 913 | + mp = wiimote_cmd_read_mp(wdata, mpdata); | |
| 914 | + wiimote_cmd_release(wdata); | |
| 663 | 915 | |
| 664 | − hid_hw_close(wdata->hdev); | |
| 916 | + /* load/unload MP module if it changed */ | |
| 917 | + if (mp) { | |
| 918 | + if (!wdata->state.mp) { | |
| 919 | + hid_info(wdata->hdev, "detected extension: Nintendo Wii Motion Plus\n"); | |
| 920 | + wiimote_mp_load(wdata); | |
| 921 | + } | |
| 922 | + } else if (wdata->state.mp) { | |
| 923 | + wiimote_mp_unload(wdata); | |
| 924 | + } | |
| 925 | + | |
| 926 | + mod_timer(&wdata->timer, jiffies + HZ * 4); | |
| 665 | 927 | } |
| 666 | 928 | |
| 667 | −static int wiimote_ir_open(struct input_dev *dev) | |
| 929 | +/* | |
| 930 | + * Check whether the wiimote is in the expected state. The extension registers | |
| 931 | + * may change during hotplug and initialization so we might get hotplug events | |
| 932 | + * that we caused by remapping some memory. | |
| 933 | + * We use some heuristics here to check known states. If the wiimote is in the | |
| 934 | + * expected state, we can ignore the hotplug event. | |
| 935 | + * | |
| 936 | + * Returns "true" if the device is in expected state, "false" if we should | |
| 937 | + * redo hotplug handling and extension initialization. | |
| 938 | + */ | |
| 939 | +static bool wiimote_init_check(struct wiimote_data *wdata) | |
| 668 | 940 | { |
| 669 | − struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 670 | − int ret; | |
| 941 | + __u32 flags; | |
| 942 | + __u8 type, data[6]; | |
| 943 | + bool ret, poll_mp; | |
| 671 | 944 | |
| 672 | − ret = hid_hw_open(wdata->hdev); | |
| 673 | − if (ret) | |
| 674 | − return ret; | |
| 945 | + spin_lock_irq(&wdata->state.lock); | |
| 946 | + flags = wdata->state.flags; | |
| 947 | + spin_unlock_irq(&wdata->state.lock); | |
| 675 | 948 | |
| 676 | − ret = wiimote_init_ir(wdata, WIIPROTO_FLAG_IR_BASIC); | |
| 677 | − if (ret) { | |
| 678 | − hid_hw_close(wdata->hdev); | |
| 679 | − return ret; | |
| 949 | + wiimote_cmd_acquire_noint(wdata); | |
| 950 | + | |
| 951 | + /* If MP is used and active, but the extension is not, we expect: | |
| 952 | + * read_mp_mapped() == WIIMOTE_MP_SINGLE | |
| 953 | + * state.flags == !EXT_ACTIVE && !MP_PLUGGED && MP_ACTIVE | |
| 954 | + * We do not check EXT_PLUGGED because it might change during | |
| 955 | + * initialization of MP without extensions. | |
| 956 | + * - If MP is unplugged/replugged, read_mp_mapped() fails | |
| 957 | + * - If EXT is plugged, MP_PLUGGED will get set */ | |
| 958 | + if (wdata->state.exttype == WIIMOTE_EXT_NONE && | |
| 959 | + wdata->state.mp > 0 && (flags & WIIPROTO_FLAG_MP_USED)) { | |
| 960 | + type = wiimote_cmd_read_mp_mapped(wdata); | |
| 961 | + ret = type == WIIMOTE_MP_SINGLE; | |
| 962 | + | |
| 963 | + spin_lock_irq(&wdata->state.lock); | |
| 964 | + ret = ret && !(wdata->state.flags & WIIPROTO_FLAG_EXT_ACTIVE); | |
| 965 | + ret = ret && !(wdata->state.flags & WIIPROTO_FLAG_MP_PLUGGED); | |
| 966 | + ret = ret && (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE); | |
| 967 | + spin_unlock_irq(&wdata->state.lock); | |
| 968 | + | |
| 969 | + if (!ret) | |
| 970 | + hid_dbg(wdata->hdev, "state left: !EXT && MP\n"); | |
| 971 | + | |
| 972 | + /* while MP is mapped, we get EXT_PLUGGED events */ | |
| 973 | + poll_mp = false; | |
| 974 | + | |
| 975 | + goto out_release; | |
| 680 | 976 | } |
| 681 | 977 | |
| 682 | − return 0; | |
| 978 | + /* If MP is unused, but the extension port is used, we expect: | |
| 979 | + * read_ext == state.exttype | |
| 980 | + * state.flags == !MP_ACTIVE && EXT_ACTIVE | |
| 981 | + * - If MP is plugged/unplugged, our timer detects it | |
| 982 | + * - If EXT is unplugged/replugged, EXT_ACTIVE will become unset */ | |
| 983 | + if (!(flags & WIIPROTO_FLAG_MP_USED) && | |
| 984 | + wdata->state.exttype != WIIMOTE_EXT_NONE) { | |
| 985 | + type = wiimote_cmd_read_ext(wdata, data); | |
| 986 | + ret = type == wdata->state.exttype; | |
| 987 | + | |
| 988 | + spin_lock_irq(&wdata->state.lock); | |
| 989 | + ret = ret && !(wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE); | |
| 990 | + ret = ret && (wdata->state.flags & WIIPROTO_FLAG_EXT_ACTIVE); | |
| 991 | + spin_unlock_irq(&wdata->state.lock); | |
| 992 | + | |
| 993 | + if (!ret) | |
| 994 | + hid_dbg(wdata->hdev, "state left: EXT && !MP\n"); | |
| 995 | + | |
| 996 | + /* poll MP for hotplug events */ | |
| 997 | + poll_mp = true; | |
| 998 | + | |
| 999 | + goto out_release; | |
| 1000 | + } | |
| 1001 | + | |
| 1002 | + /* If neither MP nor an extension are used, we expect: | |
| 1003 | + * read_ext() == WIIMOTE_EXT_NONE | |
| 1004 | + * state.flags == !MP_ACTIVE && !EXT_ACTIVE && !EXT_PLUGGED | |
| 1005 | + * No need to perform any action in this case as everything is | |
| 1006 | + * disabled already. | |
| 1007 | + * - If MP is plugged/unplugged, our timer detects it | |
| 1008 | + * - If EXT is plugged, EXT_PLUGGED will be set */ | |
| 1009 | + if (!(flags & WIIPROTO_FLAG_MP_USED) && | |
| 1010 | + wdata->state.exttype == WIIMOTE_EXT_NONE) { | |
| 1011 | + type = wiimote_cmd_read_ext(wdata, data); | |
| 1012 | + ret = type == wdata->state.exttype; | |
| 1013 | + | |
| 1014 | + spin_lock_irq(&wdata->state.lock); | |
| 1015 | + ret = ret && !(wdata->state.flags & WIIPROTO_FLAG_EXT_ACTIVE); | |
| 1016 | + ret = ret && !(wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE); | |
| 1017 | + ret = ret && !(wdata->state.flags & WIIPROTO_FLAG_EXT_PLUGGED); | |
| 1018 | + spin_unlock_irq(&wdata->state.lock); | |
| 1019 | + | |
| 1020 | + if (!ret) | |
| 1021 | + hid_dbg(wdata->hdev, "state left: !EXT && !MP\n"); | |
| 1022 | + | |
| 1023 | + /* poll MP for hotplug events */ | |
| 1024 | + poll_mp = true; | |
| 1025 | + | |
| 1026 | + goto out_release; | |
| 1027 | + } | |
| 1028 | + | |
| 1029 | + /* The trickiest part is if both EXT and MP are active. We cannot read | |
| 1030 | + * the EXT ID, anymore, because MP is mapped over it. However, we use | |
| 1031 | + * a handy trick here: | |
| 1032 | + * - EXT_ACTIVE is unset whenever !MP_PLUGGED is sent | |
| 1033 | + * MP_PLUGGED might be re-sent again before we are scheduled, but | |
| 1034 | + * EXT_ACTIVE will stay unset. | |
| 1035 | + * So it is enough to check for mp_mapped() and MP_ACTIVE and | |
| 1036 | + * EXT_ACTIVE. EXT_PLUGGED is a sanity check. */ | |
| 1037 | + if (wdata->state.exttype != WIIMOTE_EXT_NONE && | |
| 1038 | + wdata->state.mp > 0 && (flags & WIIPROTO_FLAG_MP_USED)) { | |
| 1039 | + type = wiimote_cmd_read_mp_mapped(wdata); | |
| 1040 | + ret = type != WIIMOTE_MP_NONE; | |
| 1041 | + ret = ret && type != WIIMOTE_MP_UNKNOWN; | |
| 1042 | + ret = ret && type != WIIMOTE_MP_SINGLE; | |
| 1043 | + | |
| 1044 | + spin_lock_irq(&wdata->state.lock); | |
| 1045 | + ret = ret && (wdata->state.flags & WIIPROTO_FLAG_EXT_PLUGGED); | |
| 1046 | + ret = ret && (wdata->state.flags & WIIPROTO_FLAG_EXT_ACTIVE); | |
| 1047 | + ret = ret && (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE); | |
| 1048 | + spin_unlock_irq(&wdata->state.lock); | |
| 1049 | + | |
| 1050 | + if (!ret) | |
| 1051 | + hid_dbg(wdata->hdev, "state left: EXT && MP\n"); | |
| 1052 | + | |
| 1053 | + /* while MP is mapped, we get EXT_PLUGGED events */ | |
| 1054 | + poll_mp = false; | |
| 1055 | + | |
| 1056 | + goto out_release; | |
| 1057 | + } | |
| 1058 | + | |
| 1059 | + /* unknown state */ | |
| 1060 | + ret = false; | |
| 1061 | + | |
| 1062 | +out_release: | |
| 1063 | + wiimote_cmd_release(wdata); | |
| 1064 | + | |
| 1065 | + /* only poll for MP if requested and if state didn't change */ | |
| 1066 | + if (ret && poll_mp && !(flags & WIIPROTO_FLAG_BUILTIN_MP) && | |
| 1067 | + !(flags & WIIPROTO_FLAG_NO_MP)) | |
| 1068 | + wiimote_init_poll_mp(wdata); | |
| 1069 | + | |
| 1070 | + return ret; | |
| 683 | 1071 | } |
| 684 | 1072 | |
| 685 | −static void wiimote_ir_close(struct input_dev *dev) | |
| 1073 | +static const char *wiimote_exttype_names[WIIMOTE_EXT_NUM] = { | |
| 1074 | + [WIIMOTE_EXT_NONE] = "None", | |
| 1075 | + [WIIMOTE_EXT_UNKNOWN] = "Unknown", | |
| 1076 | + [WIIMOTE_EXT_NUNCHUK] = "Nintendo Wii Nunchuk", | |
| 1077 | + [WIIMOTE_EXT_CLASSIC_CONTROLLER] = "Nintendo Wii Classic Controller", | |
| 1078 | + [WIIMOTE_EXT_BALANCE_BOARD] = "Nintendo Wii Balance Board", | |
| 1079 | + [WIIMOTE_EXT_PRO_CONTROLLER] = "Nintendo Wii U Pro Controller", | |
| 1080 | +}; | |
| 1081 | + | |
| 1082 | +/* | |
| 1083 | + * Handle hotplug events | |
| 1084 | + * If we receive an hotplug event and the device-check failed, we deinitialize | |
| 1085 | + * the extension ports, re-read all extension IDs and set the device into | |
| 1086 | + * the desired state. This involves mapping MP into the main extension | |
| 1087 | + * registers, setting up extension passthrough modes and initializing the | |
| 1088 | + * requested extensions. | |
| 1089 | + */ | |
| 1090 | +static void wiimote_init_hotplug(struct wiimote_data *wdata) | |
| 686 | 1091 | { |
| 687 | − struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 1092 | + __u8 exttype, extdata[6], mpdata[6]; | |
| 1093 | + __u32 flags; | |
| 1094 | + bool mp; | |
| 688 | 1095 | |
| 689 | − wiimote_init_ir(wdata, 0); | |
| 690 | − hid_hw_close(wdata->hdev); | |
| 1096 | + hid_dbg(wdata->hdev, "detect extensions..\n"); | |
| 1097 | + | |
| 1098 | + wiimote_cmd_acquire_noint(wdata); | |
| 1099 | + | |
| 1100 | + spin_lock_irq(&wdata->state.lock); | |
| 1101 | + | |
| 1102 | + /* get state snapshot that we will then work on */ | |
| 1103 | + flags = wdata->state.flags; | |
| 1104 | + | |
| 1105 | + /* disable event forwarding temporarily */ | |
| 1106 | + wdata->state.flags &= ~WIIPROTO_FLAG_EXT_ACTIVE; | |
| 1107 | + wdata->state.flags &= ~WIIPROTO_FLAG_MP_ACTIVE; | |
| 1108 | + | |
| 1109 | + spin_unlock_irq(&wdata->state.lock); | |
| 1110 | + | |
| 1111 | + /* init extension and MP (deactivates current extension or MP) */ | |
| 1112 | + wiimote_cmd_init_ext(wdata); | |
| 1113 | + if (flags & WIIPROTO_FLAG_NO_MP) { | |
| 1114 | + mp = false; | |
| 1115 | + } else { | |
| 1116 | + wiimote_cmd_init_mp(wdata); | |
| 1117 | + mp = wiimote_cmd_read_mp(wdata, mpdata); | |
| 1118 | + } | |
| 1119 | + exttype = wiimote_cmd_read_ext(wdata, extdata); | |
| 1120 | + | |
| 1121 | + wiimote_cmd_release(wdata); | |
| 1122 | + | |
| 1123 | + /* load/unload extension module if it changed */ | |
| 1124 | + if (exttype != wdata->state.exttype) { | |
| 1125 | + /* unload previous extension */ | |
| 1126 | + wiimote_ext_unload(wdata); | |
| 1127 | + | |
| 1128 | + if (exttype == WIIMOTE_EXT_UNKNOWN) { | |
| 1129 | + hid_info(wdata->hdev, "cannot detect extension; %02x:%02x %02x:%02x %02x:%02x\n", | |
| 1130 | + extdata[0], extdata[1], extdata[2], | |
| 1131 | + extdata[3], extdata[4], extdata[5]); | |
| 1132 | + } else if (exttype == WIIMOTE_EXT_NONE) { | |
| 1133 | + spin_lock_irq(&wdata->state.lock); | |
| 1134 | + wdata->state.exttype = WIIMOTE_EXT_NONE; | |
| 1135 | + spin_unlock_irq(&wdata->state.lock); | |
| 1136 | + } else { | |
| 1137 | + hid_info(wdata->hdev, "detected extension: %s\n", | |
| 1138 | + wiimote_exttype_names[exttype]); | |
| 1139 | + /* try loading new extension */ | |
| 1140 | + wiimote_ext_load(wdata, exttype); | |
| 1141 | + } | |
| 1142 | + } | |
| 1143 | + | |
| 1144 | + /* load/unload MP module if it changed */ | |
| 1145 | + if (mp) { | |
| 1146 | + if (!wdata->state.mp) { | |
| 1147 | + hid_info(wdata->hdev, "detected extension: Nintendo Wii Motion Plus\n"); | |
| 1148 | + wiimote_mp_load(wdata); | |
| 1149 | + } | |
| 1150 | + } else if (wdata->state.mp) { | |
| 1151 | + wiimote_mp_unload(wdata); | |
| 1152 | + } | |
| 1153 | + | |
| 1154 | + /* if MP is not used, do not map or activate it */ | |
| 1155 | + if (!(flags & WIIPROTO_FLAG_MP_USED)) | |
| 1156 | + mp = false; | |
| 1157 | + | |
| 1158 | + /* map MP into main extension registers if used */ | |
| 1159 | + if (mp) { | |
| 1160 | + wiimote_cmd_acquire_noint(wdata); | |
| 1161 | + wiimote_cmd_map_mp(wdata, exttype); | |
| 1162 | + wiimote_cmd_release(wdata); | |
| 1163 | + | |
| 1164 | + /* delete MP hotplug timer */ | |
| 1165 | + del_timer_sync(&wdata->timer); | |
| 1166 | + } else { | |
| 1167 | + /* reschedule MP hotplug timer */ | |
| 1168 | + if (!(flags & WIIPROTO_FLAG_BUILTIN_MP) && | |
| 1169 | + !(flags & WIIPROTO_FLAG_NO_MP)) | |
| 1170 | + mod_timer(&wdata->timer, jiffies + HZ * 4); | |
| 1171 | + } | |
| 1172 | + | |
| 1173 | + spin_lock_irq(&wdata->state.lock); | |
| 1174 | + | |
| 1175 | + /* enable data forwarding again and set expected hotplug state */ | |
| 1176 | + if (mp) { | |
| 1177 | + wdata->state.flags |= WIIPROTO_FLAG_MP_ACTIVE; | |
| 1178 | + if (wdata->state.exttype == WIIMOTE_EXT_NONE) { | |
| 1179 | + wdata->state.flags &= ~WIIPROTO_FLAG_EXT_PLUGGED; | |
| 1180 | + wdata->state.flags &= ~WIIPROTO_FLAG_MP_PLUGGED; | |
| 1181 | + } else { | |
| 1182 | + wdata->state.flags &= ~WIIPROTO_FLAG_EXT_PLUGGED; | |
| 1183 | + wdata->state.flags |= WIIPROTO_FLAG_MP_PLUGGED; | |
| 1184 | + wdata->state.flags |= WIIPROTO_FLAG_EXT_ACTIVE; | |
| 1185 | + } | |
| 1186 | + } else if (wdata->state.exttype != WIIMOTE_EXT_NONE) { | |
| 1187 | + wdata->state.flags |= WIIPROTO_FLAG_EXT_ACTIVE; | |
| 1188 | + } | |
| 1189 | + | |
| 1190 | + /* request status report for hotplug state updates */ | |
| 1191 | + wiiproto_req_status(wdata); | |
| 1192 | + | |
| 1193 | + spin_unlock_irq(&wdata->state.lock); | |
| 1194 | + | |
| 1195 | + hid_dbg(wdata->hdev, "detected extensions: MP: %d EXT: %d\n", | |
| 1196 | + wdata->state.mp, wdata->state.exttype); | |
| 691 | 1197 | } |
| 692 | 1198 | |
| 693 | −static void handler_keys(struct wiimote_data *wdata, const __u8 *payload) | |
| 1199 | +static void wiimote_init_worker(struct work_struct *work) | |
| 1200 | +{ | |
| 1201 | + struct wiimote_data *wdata = container_of(work, struct wiimote_data, | |
| 1202 | + init_worker); | |
| 1203 | + bool changed = false; | |
| 1204 | + | |
| 1205 | + if (wdata->state.devtype == WIIMOTE_DEV_PENDING) { | |
| 1206 | + wiimote_init_detect(wdata); | |
| 1207 | + changed = true; | |
| 1208 | + } | |
| 1209 | + | |
| 1210 | + if (changed || !wiimote_init_check(wdata)) | |
| 1211 | + wiimote_init_hotplug(wdata); | |
| 1212 | + | |
| 1213 | + if (changed) | |
| 1214 | + kobject_uevent(&wdata->hdev->dev.kobj, KOBJ_CHANGE); | |
| 1215 | +} | |
| 1216 | + | |
| 1217 | +void __wiimote_schedule(struct wiimote_data *wdata) | |
| 694 | 1218 | { |
| 695 | − input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_LEFT], | |
| 696 | − !!(payload[0] & 0x01)); | |
| 697 | − input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_RIGHT], | |
| 698 | − !!(payload[0] & 0x02)); | |
| 699 | − input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_DOWN], | |
| 700 | − !!(payload[0] & 0x04)); | |
| 701 | − input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_UP], | |
| 702 | − !!(payload[0] & 0x08)); | |
| 703 | − input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_PLUS], | |
| 704 | − !!(payload[0] & 0x10)); | |
| 705 | − input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_TWO], | |
| 706 | − !!(payload[1] & 0x01)); | |
| 707 | − input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_ONE], | |
| 708 | − !!(payload[1] & 0x02)); | |
| 709 | − input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_B], | |
| 710 | − !!(payload[1] & 0x04)); | |
| 711 | − input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_A], | |
| 712 | − !!(payload[1] & 0x08)); | |
| 713 | − input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_MINUS], | |
| 714 | − !!(payload[1] & 0x10)); | |
| 715 | − input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_HOME], | |
| 716 | − !!(payload[1] & 0x80)); | |
| 717 | − input_sync(wdata->input); | |
| 1219 | + if (!(wdata->state.flags & WIIPROTO_FLAG_EXITING)) | |
| 1220 | + schedule_work(&wdata->init_worker); | |
| 718 | 1221 | } |
| 719 | 1222 | |
| 720 | −static void handler_accel(struct wiimote_data *wdata, const __u8 *payload) | |
| 1223 | +static void wiimote_schedule(struct wiimote_data *wdata) | |
| 721 | 1224 | { |
| 722 | − __u16 x, y, z; | |
| 1225 | + unsigned long flags; | |
| 723 | 1226 | |
| 724 | − if (!(wdata->state.flags & WIIPROTO_FLAG_ACCEL)) | |
| 725 | − return; | |
| 1227 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 1228 | + __wiimote_schedule(wdata); | |
| 1229 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 1230 | +} | |
| 726 | 1231 | |
| 727 | − /* | |
| 728 | − * payload is: BB BB XX YY ZZ | |
| 729 | − * Accelerometer data is encoded into 3 10bit values. XX, YY and ZZ | |
| 730 | − * contain the upper 8 bits of each value. The lower 2 bits are | |
| 731 | − * contained in the buttons data BB BB. | |
| 732 | − * Bits 6 and 7 of the first buttons byte BB is the lower 2 bits of the | |
| 733 | − * X accel value. Bit 5 of the second buttons byte is the 2nd bit of Y | |
| 734 | − * accel value and bit 6 is the second bit of the Z value. | |
| 735 | − * The first bit of Y and Z values is not available and always set to 0. | |
| 736 | − * 0x200 is returned on no movement. | |
| 737 | − */ | |
| 1232 | +static void wiimote_init_timeout(unsigned long arg) | |
| 1233 | +{ | |
| 1234 | + struct wiimote_data *wdata = (void*)arg; | |
| 738 | 1235 | |
| 739 | − x = payload[2] << 2; | |
| 740 | − y = payload[3] << 2; | |
| 741 | − z = payload[4] << 2; | |
| 1236 | + wiimote_schedule(wdata); | |
| 1237 | +} | |
| 1238 | + | |
| 1239 | +/* protocol handlers */ | |
| 1240 | + | |
| 1241 | +static void handler_keys(struct wiimote_data *wdata, const __u8 *payload) | |
| 1242 | +{ | |
| 1243 | + const __u8 *iter, *mods; | |
| 1244 | + const struct wiimod_ops *ops; | |
| 742 | 1245 | |
| 743 | − x |= (payload[0] >> 5) & 0x3; | |
| 744 | − y |= (payload[1] >> 4) & 0x2; | |
| 745 | − z |= (payload[1] >> 5) & 0x2; | |
| 1246 | + ops = wiimod_ext_table[wdata->state.exttype]; | |
| 1247 | + if (ops->in_keys) { | |
| 1248 | + ops->in_keys(wdata, payload); | |
| 1249 | + return; | |
| 1250 | + } | |
| 746 | 1251 | |
| 747 | − input_report_abs(wdata->accel, ABS_RX, x - 0x200); | |
| 748 | − input_report_abs(wdata->accel, ABS_RY, y - 0x200); | |
| 749 | − input_report_abs(wdata->accel, ABS_RZ, z - 0x200); | |
| 750 | − input_sync(wdata->accel); | |
| 1252 | + mods = wiimote_devtype_mods[wdata->state.devtype]; | |
| 1253 | + for (iter = mods; *iter != WIIMOD_NULL; ++iter) { | |
| 1254 | + ops = wiimod_table[*iter]; | |
| 1255 | + if (ops->in_keys) { | |
| 1256 | + ops->in_keys(wdata, payload); | |
| 1257 | + break; | |
| 1258 | + } | |
| 1259 | + } | |
| 751 | 1260 | } |
| 752 | 1261 | |
| 753 | −#define ir_to_input0(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \ | |
| 754 | − ABS_HAT0X, ABS_HAT0Y) | |
| 755 | −#define ir_to_input1(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \ | |
| 756 | − ABS_HAT1X, ABS_HAT1Y) | |
| 757 | −#define ir_to_input2(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \ | |
| 758 | − ABS_HAT2X, ABS_HAT2Y) | |
| 759 | −#define ir_to_input3(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \ | |
| 760 | − ABS_HAT3X, ABS_HAT3Y) | |
| 1262 | +static void handler_accel(struct wiimote_data *wdata, const __u8 *payload) | |
| 1263 | +{ | |
| 1264 | + const __u8 *iter, *mods; | |
| 1265 | + const struct wiimod_ops *ops; | |
| 1266 | + | |
| 1267 | + ops = wiimod_ext_table[wdata->state.exttype]; | |
| 1268 | + if (ops->in_accel) { | |
| 1269 | + ops->in_accel(wdata, payload); | |
| 1270 | + return; | |
| 1271 | + } | |
| 761 | 1272 | |
| 762 | −static void __ir_to_input(struct wiimote_data *wdata, const __u8 *ir, | |
| 763 | − bool packed, __u8 xid, __u8 yid) | |
| 1273 | + mods = wiimote_devtype_mods[wdata->state.devtype]; | |
| 1274 | + for (iter = mods; *iter != WIIMOD_NULL; ++iter) { | |
| 1275 | + ops = wiimod_table[*iter]; | |
| 1276 | + if (ops->in_accel) { | |
| 1277 | + ops->in_accel(wdata, payload); | |
| 1278 | + break; | |
| 1279 | + } | |
| 1280 | + } | |
| 1281 | +} | |
| 1282 | + | |
| 1283 | +static bool valid_ext_handler(const struct wiimod_ops *ops, size_t len) | |
| 764 | 1284 | { |
| 765 | − __u16 x, y; | |
| 1285 | + if (!ops->in_ext) | |
| 1286 | + return false; | |
| 1287 | + if ((ops->flags & WIIMOD_FLAG_EXT8) && len < 8) | |
| 1288 | + return false; | |
| 1289 | + if ((ops->flags & WIIMOD_FLAG_EXT16) && len < 16) | |
| 1290 | + return false; | |
| 1291 | + | |
| 1292 | + return true; | |
| 1293 | +} | |
| 766 | 1294 | |
| 767 | − if (!(wdata->state.flags & WIIPROTO_FLAGS_IR)) | |
| 1295 | +static void handler_ext(struct wiimote_data *wdata, const __u8 *payload, | |
| 1296 | + size_t len) | |
| 1297 | +{ | |
| 1298 | + static const __u8 invalid[21] = { 0xff, 0xff, 0xff, 0xff, | |
| 1299 | + 0xff, 0xff, 0xff, 0xff, | |
| 1300 | + 0xff, 0xff, 0xff, 0xff, | |
| 1301 | + 0xff, 0xff, 0xff, 0xff, | |
| 1302 | + 0xff, 0xff, 0xff, 0xff, | |
| 1303 | + 0xff }; | |
| 1304 | + const __u8 *iter, *mods; | |
| 1305 | + const struct wiimod_ops *ops; | |
| 1306 | + bool is_mp; | |
| 1307 | + | |
| 1308 | + if (len > 21) | |
| 1309 | + len = 21; | |
| 1310 | + if (len < 6 || !memcmp(payload, invalid, len)) | |
| 768 | 1311 | return; |
| 769 | 1312 | |
| 770 | − /* | |
| 771 | − * Basic IR data is encoded into 3 bytes. The first two bytes are the | |
| 772 | − * lower 8 bit of the X/Y data, the 3rd byte contains the upper 2 bits | |
| 773 | − * of both. | |
| 774 | − * If data is packed, then the 3rd byte is put first and slightly | |
| 775 | − * reordered. This allows to interleave packed and non-packed data to | |
| 776 | − * have two IR sets in 5 bytes instead of 6. | |
| 777 | − * The resulting 10bit X/Y values are passed to the ABS_HATXY input dev. | |
| 778 | − */ | |
| 1313 | + /* if MP is active, track MP slot hotplugging */ | |
| 1314 | + if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) { | |
| 1315 | + /* this bit is set for invalid events (eg. during hotplug) */ | |
| 1316 | + if (payload[5] & 0x01) | |
| 1317 | + return; | |
| 1318 | + | |
| 1319 | + if (payload[4] & 0x01) { | |
| 1320 | + if (!(wdata->state.flags & WIIPROTO_FLAG_MP_PLUGGED)) { | |
| 1321 | + hid_dbg(wdata->hdev, "MP hotplug: 1\n"); | |
| 1322 | + wdata->state.flags |= WIIPROTO_FLAG_MP_PLUGGED; | |
| 1323 | + __wiimote_schedule(wdata); | |
| 1324 | + } | |
| 1325 | + } else { | |
| 1326 | + if (wdata->state.flags & WIIPROTO_FLAG_MP_PLUGGED) { | |
| 1327 | + hid_dbg(wdata->hdev, "MP hotplug: 0\n"); | |
| 1328 | + wdata->state.flags &= ~WIIPROTO_FLAG_MP_PLUGGED; | |
| 1329 | + wdata->state.flags &= ~WIIPROTO_FLAG_EXT_ACTIVE; | |
| 1330 | + __wiimote_schedule(wdata); | |
| 1331 | + } | |
| 1332 | + } | |
| 779 | 1333 | |
| 780 | − if (packed) { | |
| 781 | − x = ir[1] | ((ir[0] & 0x03) << 8); | |
| 782 | − y = ir[2] | ((ir[0] & 0x0c) << 6); | |
| 1334 | + /* detect MP data that is sent interleaved with EXT data */ | |
| 1335 | + is_mp = payload[5] & 0x02; | |
| 783 | 1336 | } else { |
| 784 | − x = ir[0] | ((ir[2] & 0x30) << 4); | |
| 785 | − y = ir[1] | ((ir[2] & 0xc0) << 2); | |
| 1337 | + is_mp = false; | |
| 1338 | + } | |
| 1339 | + | |
| 1340 | + /* ignore EXT events if no extension is active */ | |
| 1341 | + if (!(wdata->state.flags & WIIPROTO_FLAG_EXT_ACTIVE) && !is_mp) | |
| 1342 | + return; | |
| 1343 | + | |
| 1344 | + /* try forwarding to extension handler, first */ | |
| 1345 | + ops = wiimod_ext_table[wdata->state.exttype]; | |
| 1346 | + if (is_mp && ops->in_mp) { | |
| 1347 | + ops->in_mp(wdata, payload); | |
| 1348 | + return; | |
| 1349 | + } else if (!is_mp && valid_ext_handler(ops, len)) { | |
| 1350 | + ops->in_ext(wdata, payload); | |
| 1351 | + return; | |
| 1352 | + } | |
| 1353 | + | |
| 1354 | + /* try forwarding to MP handler */ | |
| 1355 | + ops = &wiimod_mp; | |
| 1356 | + if (is_mp && ops->in_mp) { | |
| 1357 | + ops->in_mp(wdata, payload); | |
| 1358 | + return; | |
| 1359 | + } else if (!is_mp && valid_ext_handler(ops, len)) { | |
| 1360 | + ops->in_ext(wdata, payload); | |
| 1361 | + return; | |
| 786 | 1362 | } |
| 787 | 1363 | |
| 788 | − input_report_abs(wdata->ir, xid, x); | |
| 789 | − input_report_abs(wdata->ir, yid, y); | |
| 1364 | + /* try forwarding to loaded modules */ | |
| 1365 | + mods = wiimote_devtype_mods[wdata->state.devtype]; | |
| 1366 | + for (iter = mods; *iter != WIIMOD_NULL; ++iter) { | |
| 1367 | + ops = wiimod_table[*iter]; | |
| 1368 | + if (is_mp && ops->in_mp) { | |
| 1369 | + ops->in_mp(wdata, payload); | |
| 1370 | + return; | |
| 1371 | + } else if (!is_mp && valid_ext_handler(ops, len)) { | |
| 1372 | + ops->in_ext(wdata, payload); | |
| 1373 | + return; | |
| 1374 | + } | |
| 1375 | + } | |
| 1376 | +} | |
| 1377 | + | |
| 1378 | +#define ir_to_input0(wdata, ir, packed) handler_ir((wdata), (ir), (packed), 0) | |
| 1379 | +#define ir_to_input1(wdata, ir, packed) handler_ir((wdata), (ir), (packed), 1) | |
| 1380 | +#define ir_to_input2(wdata, ir, packed) handler_ir((wdata), (ir), (packed), 2) | |
| 1381 | +#define ir_to_input3(wdata, ir, packed) handler_ir((wdata), (ir), (packed), 3) | |
| 1382 | + | |
| 1383 | +static void handler_ir(struct wiimote_data *wdata, const __u8 *payload, | |
| 1384 | + bool packed, unsigned int id) | |
| 1385 | +{ | |
| 1386 | + const __u8 *iter, *mods; | |
| 1387 | + const struct wiimod_ops *ops; | |
| 1388 | + | |
| 1389 | + ops = wiimod_ext_table[wdata->state.exttype]; | |
| 1390 | + if (ops->in_ir) { | |
| 1391 | + ops->in_ir(wdata, payload, packed, id); | |
| 1392 | + return; | |
| 1393 | + } | |
| 1394 | + | |
| 1395 | + mods = wiimote_devtype_mods[wdata->state.devtype]; | |
| 1396 | + for (iter = mods; *iter != WIIMOD_NULL; ++iter) { | |
| 1397 | + ops = wiimod_table[*iter]; | |
| 1398 | + if (ops->in_ir) { | |
| 1399 | + ops->in_ir(wdata, payload, packed, id); | |
| 1400 | + break; | |
| 1401 | + } | |
| 1402 | + } | |
| 790 | 1403 | } |
| 791 | 1404 | |
| 792 | 1405 | /* reduced status report with "BB BB" key data only */ |
| @@ -804,12 +1417,27 @@ static void handler_status(struct wiimote_data *wdata, const __u8 *payload) · 11 unmodified lines | ||
| 804 | 1417 | { |
| 805 | 1418 | handler_status_K(wdata, payload); |
| 806 | 1419 | |
| 807 | − wiiext_event(wdata, payload[2] & 0x02); | |
| 1420 | + /* update extension status */ | |
| 1421 | + if (payload[2] & 0x02) { | |
| 1422 | + if (!(wdata->state.flags & WIIPROTO_FLAG_EXT_PLUGGED)) { | |
| 1423 | + hid_dbg(wdata->hdev, "EXT hotplug: 1\n"); | |
| 1424 | + wdata->state.flags |= WIIPROTO_FLAG_EXT_PLUGGED; | |
| 1425 | + __wiimote_schedule(wdata); | |
| 1426 | + } | |
| 1427 | + } else { | |
| 1428 | + if (wdata->state.flags & WIIPROTO_FLAG_EXT_PLUGGED) { | |
| 1429 | + hid_dbg(wdata->hdev, "EXT hotplug: 0\n"); | |
| 1430 | + wdata->state.flags &= ~WIIPROTO_FLAG_EXT_PLUGGED; | |
| 1431 | + wdata->state.flags &= ~WIIPROTO_FLAG_MP_PLUGGED; | |
| 1432 | + wdata->state.flags &= ~WIIPROTO_FLAG_EXT_ACTIVE; | |
| 1433 | + wdata->state.flags &= ~WIIPROTO_FLAG_MP_ACTIVE; | |
| 1434 | + __wiimote_schedule(wdata); | |
| 1435 | + } | |
| 1436 | + } | |
| 808 | 1437 | |
| 809 | − if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_SREQ, 0)) { | |
| 810 | − wdata->state.cmd_battery = payload[5]; | |
| 1438 | + wdata->state.cmd_battery = payload[5]; | |
| 1439 | + if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_SREQ, 0)) | |
| 811 | 1440 | wiimote_cmd_complete(wdata); |
| 812 | − } | |
| 813 | 1441 | } |
| 814 | 1442 | |
| 815 | 1443 | /* reduced generic report with "BB BB" key data only */ |
| @@ -864,7 +1492,7 @@ static void handler_drm_KA(struct wiimote_data *wdata, const __u8 *payload) · 48 unmodified lines | ||
| 864 | 1492 | static void handler_drm_KE(struct wiimote_data *wdata, const __u8 *payload) |
| 865 | 1493 | { |
| 866 | 1494 | handler_keys(wdata, payload); |
| 867 | − wiiext_handle(wdata, &payload[2]); | |
| 1495 | + handler_ext(wdata, &payload[2], 8); | |
| 868 | 1496 | } |
| 869 | 1497 | |
| 870 | 1498 | static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload) |
| @@ -875,13 +1503,12 @@ static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload) · 4 unmodified lines | ||
| 875 | 1503 | ir_to_input1(wdata, &payload[8], false); |
| 876 | 1504 | ir_to_input2(wdata, &payload[11], false); |
| 877 | 1505 | ir_to_input3(wdata, &payload[14], false); |
| 878 | − input_sync(wdata->ir); | |
| 879 | 1506 | } |
| 880 | 1507 | |
| 881 | 1508 | static void handler_drm_KEE(struct wiimote_data *wdata, const __u8 *payload) |
| 882 | 1509 | { |
| 883 | 1510 | handler_keys(wdata, payload); |
| 884 | − wiiext_handle(wdata, &payload[2]); | |
| 1511 | + handler_ext(wdata, &payload[2], 19); | |
| 885 | 1512 | } |
| 886 | 1513 | |
| 887 | 1514 | static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload) |
| @@ -891,15 +1518,14 @@ static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload) · 3 unmodified lines | ||
| 891 | 1518 | ir_to_input1(wdata, &payload[4], true); |
| 892 | 1519 | ir_to_input2(wdata, &payload[7], false); |
| 893 | 1520 | ir_to_input3(wdata, &payload[9], true); |
| 894 | − input_sync(wdata->ir); | |
| 895 | − wiiext_handle(wdata, &payload[12]); | |
| 1521 | + handler_ext(wdata, &payload[12], 9); | |
| 896 | 1522 | } |
| 897 | 1523 | |
| 898 | 1524 | static void handler_drm_KAE(struct wiimote_data *wdata, const __u8 *payload) |
| 899 | 1525 | { |
| 900 | 1526 | handler_keys(wdata, payload); |
| 901 | 1527 | handler_accel(wdata, payload); |
| 902 | − wiiext_handle(wdata, &payload[5]); | |
| 1528 | + handler_ext(wdata, &payload[5], 16); | |
| 903 | 1529 | } |
| 904 | 1530 | |
| 905 | 1531 | static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload) |
| @@ -910,13 +1536,12 @@ static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload) · 4 unmodified lines | ||
| 910 | 1536 | ir_to_input1(wdata, &payload[7], true); |
| 911 | 1537 | ir_to_input2(wdata, &payload[10], false); |
| 912 | 1538 | ir_to_input3(wdata, &payload[12], true); |
| 913 | − input_sync(wdata->ir); | |
| 914 | − wiiext_handle(wdata, &payload[15]); | |
| 1539 | + handler_ext(wdata, &payload[15], 6); | |
| 915 | 1540 | } |
| 916 | 1541 | |
| 917 | 1542 | static void handler_drm_E(struct wiimote_data *wdata, const __u8 *payload) |
| 918 | 1543 | { |
| 919 | − wiiext_handle(wdata, payload); | |
| 1544 | + handler_ext(wdata, payload, 21); | |
| 920 | 1545 | } |
| 921 | 1546 | |
| 922 | 1547 | static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload) |
| @@ -929,7 +1554,6 @@ static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload) · 6 unmodified lines | ||
| 929 | 1554 | |
| 930 | 1555 | ir_to_input0(wdata, &payload[3], false); |
| 931 | 1556 | ir_to_input1(wdata, &payload[12], false); |
| 932 | − input_sync(wdata->ir); | |
| 933 | 1557 | } |
| 934 | 1558 | |
| 935 | 1559 | static void handler_drm_SKAI2(struct wiimote_data *wdata, const __u8 *payload) |
| @@ -950,7 +1574,6 @@ static void handler_drm_SKAI2(struct wiimote_data *wdata, const __u8 *payload) · 14 unmodified lines | ||
| 950 | 1574 | |
| 951 | 1575 | ir_to_input2(wdata, &payload[3], false); |
| 952 | 1576 | ir_to_input3(wdata, &payload[12], false); |
| 953 | − input_sync(wdata->ir); | |
| 954 | 1577 | } |
| 955 | 1578 | |
| 956 | 1579 | struct wiiproto_handler { |
| @@ -1017,177 +1640,136 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, · 60 unmodified lines | ||
| 1017 | 1640 | return 0; |
| 1018 | 1641 | } |
| 1019 | 1642 | |
| 1020 | −static void wiimote_leds_destroy(struct wiimote_data *wdata) | |
| 1643 | +static ssize_t wiimote_ext_show(struct device *dev, | |
| 1644 | + struct device_attribute *attr, | |
| 1645 | + char *buf) | |
| 1021 | 1646 | { |
| 1022 | − int i; | |
| 1023 | − struct led_classdev *led; | |
| 1024 | − | |
| 1025 | − for (i = 0; i < 4; ++i) { | |
| 1026 | − if (wdata->leds[i]) { | |
| 1027 | − led = wdata->leds[i]; | |
| 1028 | − wdata->leds[i] = NULL; | |
| 1029 | − led_classdev_unregister(led); | |
| 1030 | − kfree(led); | |
| 1031 | − } | |
| 1647 | + struct wiimote_data *wdata = dev_to_wii(dev); | |
| 1648 | + __u8 type; | |
| 1649 | + unsigned long flags; | |
| 1650 | + | |
| 1651 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 1652 | + type = wdata->state.exttype; | |
| 1653 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 1654 | + | |
| 1655 | + switch (type) { | |
| 1656 | + case WIIMOTE_EXT_NONE: | |
| 1657 | + return sprintf(buf, "none\n"); | |
| 1658 | + case WIIMOTE_EXT_NUNCHUK: | |
| 1659 | + return sprintf(buf, "nunchuk\n"); | |
| 1660 | + case WIIMOTE_EXT_CLASSIC_CONTROLLER: | |
| 1661 | + return sprintf(buf, "classic\n"); | |
| 1662 | + case WIIMOTE_EXT_BALANCE_BOARD: | |
| 1663 | + return sprintf(buf, "balanceboard\n"); | |
| 1664 | + case WIIMOTE_EXT_PRO_CONTROLLER: | |
| 1665 | + return sprintf(buf, "procontroller\n"); | |
| 1666 | + case WIIMOTE_EXT_UNKNOWN: | |
| 1667 | + /* fallthrough */ | |
| 1668 | + default: | |
| 1669 | + return sprintf(buf, "unknown\n"); | |
| 1032 | 1670 | } |
| 1033 | 1671 | } |
| 1034 | 1672 | |
| 1035 | −static int wiimote_leds_create(struct wiimote_data *wdata) | |
| 1673 | +static ssize_t wiimote_ext_store(struct device *dev, | |
| 1674 | + struct device_attribute *attr, | |
| 1675 | + const char *buf, size_t count) | |
| 1036 | 1676 | { |
| 1037 | − int i, ret; | |
| 1038 | − struct device *dev = &wdata->hdev->dev; | |
| 1039 | − size_t namesz = strlen(dev_name(dev)) + 9; | |
| 1040 | − struct led_classdev *led; | |
| 1041 | − char *name; | |
| 1677 | + struct wiimote_data *wdata = dev_to_wii(dev); | |
| 1042 | 1678 | |
| 1043 | − for (i = 0; i < 4; ++i) { | |
| 1044 | − led = kzalloc(sizeof(struct led_classdev) + namesz, GFP_KERNEL); | |
| 1045 | − if (!led) { | |
| 1046 | − ret = -ENOMEM; | |
| 1047 | − goto err; | |
| 1048 | − } | |
| 1049 | − name = (void*)&led[1]; | |
| 1050 | − snprintf(name, namesz, "%s:blue:p%d", dev_name(dev), i); | |
| 1051 | − led->name = name; | |
| 1052 | − led->brightness = 0; | |
| 1053 | − led->max_brightness = 1; | |
| 1054 | − led->brightness_get = wiimote_leds_get; | |
| 1055 | − led->brightness_set = wiimote_leds_set; | |
| 1056 | − | |
| 1057 | − ret = led_classdev_register(dev, led); | |
| 1058 | − if (ret) { | |
| 1059 | − kfree(led); | |
| 1060 | − goto err; | |
| 1061 | − } | |
| 1062 | − wdata->leds[i] = led; | |
| 1679 | + if (!strcmp(buf, "scan")) { | |
| 1680 | + wiimote_schedule(wdata); | |
| 1681 | + } else { | |
| 1682 | + return -EINVAL; | |
| 1063 | 1683 | } |
| 1064 | 1684 | |
| 1065 | − return 0; | |
| 1685 | + return strnlen(buf, PAGE_SIZE); | |
| 1686 | +} | |
| 1066 | 1687 | |
| 1067 | −err: | |
| 1068 | − wiimote_leds_destroy(wdata); | |
| 1069 | − return ret; | |
| 1688 | +static DEVICE_ATTR(extension, S_IRUGO | S_IWUSR | S_IWGRP, wiimote_ext_show, | |
| 1689 | + wiimote_ext_store); | |
| 1690 | + | |
| 1691 | +static ssize_t wiimote_dev_show(struct device *dev, | |
| 1692 | + struct device_attribute *attr, | |
| 1693 | + char *buf) | |
| 1694 | +{ | |
| 1695 | + struct wiimote_data *wdata = dev_to_wii(dev); | |
| 1696 | + __u8 type; | |
| 1697 | + unsigned long flags; | |
| 1698 | + | |
| 1699 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 1700 | + type = wdata->state.devtype; | |
| 1701 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 1702 | + | |
| 1703 | + switch (type) { | |
| 1704 | + case WIIMOTE_DEV_GENERIC: | |
| 1705 | + return sprintf(buf, "generic\n"); | |
| 1706 | + case WIIMOTE_DEV_GEN10: | |
| 1707 | + return sprintf(buf, "gen10\n"); | |
| 1708 | + case WIIMOTE_DEV_GEN20: | |
| 1709 | + return sprintf(buf, "gen20\n"); | |
| 1710 | + case WIIMOTE_DEV_BALANCE_BOARD: | |
| 1711 | + return sprintf(buf, "balanceboard\n"); | |
| 1712 | + case WIIMOTE_DEV_PRO_CONTROLLER: | |
| 1713 | + return sprintf(buf, "procontroller\n"); | |
| 1714 | + case WIIMOTE_DEV_PENDING: | |
| 1715 | + return sprintf(buf, "pending\n"); | |
| 1716 | + case WIIMOTE_DEV_UNKNOWN: | |
| 1717 | + /* fallthrough */ | |
| 1718 | + default: | |
| 1719 | + return sprintf(buf, "unknown\n"); | |
| 1720 | + } | |
| 1070 | 1721 | } |
| 1071 | 1722 | |
| 1723 | +static DEVICE_ATTR(devtype, S_IRUGO, wiimote_dev_show, NULL); | |
| 1724 | + | |
| 1072 | 1725 | static struct wiimote_data *wiimote_create(struct hid_device *hdev) |
| 1073 | 1726 | { |
| 1074 | 1727 | struct wiimote_data *wdata; |
| 1075 | − int i; | |
| 1076 | 1728 | |
| 1077 | 1729 | wdata = kzalloc(sizeof(*wdata), GFP_KERNEL); |
| 1078 | 1730 | if (!wdata) |
| 1079 | 1731 | return NULL; |
| 1080 | 1732 | |
| 1081 | − wdata->input = input_allocate_device(); | |
| 1082 | − if (!wdata->input) | |
| 1083 | − goto err; | |
| 1084 | − | |
| 1085 | 1733 | wdata->hdev = hdev; |
| 1086 | 1734 | hid_set_drvdata(hdev, wdata); |
| 1087 | 1735 | |
| 1088 | − input_set_drvdata(wdata->input, wdata); | |
| 1089 | − wdata->input->open = wiimote_input_open; | |
| 1090 | − wdata->input->close = wiimote_input_close; | |
| 1091 | − wdata->input->dev.parent = &wdata->hdev->dev; | |
| 1092 | − wdata->input->id.bustype = wdata->hdev->bus; | |
| 1093 | − wdata->input->id.vendor = wdata->hdev->vendor; | |
| 1094 | − wdata->input->id.product = wdata->hdev->product; | |
| 1095 | − wdata->input->id.version = wdata->hdev->version; | |
| 1096 | − wdata->input->name = WIIMOTE_NAME; | |
| 1097 | − | |
| 1098 | − set_bit(EV_KEY, wdata->input->evbit); | |
| 1099 | − for (i = 0; i < WIIPROTO_KEY_COUNT; ++i) | |
| 1100 | − set_bit(wiiproto_keymap[i], wdata->input->keybit); | |
| 1101 | − | |
| 1102 | − set_bit(FF_RUMBLE, wdata->input->ffbit); | |
| 1103 | − if (input_ff_create_memless(wdata->input, NULL, wiimote_ff_play)) | |
| 1104 | − goto err_input; | |
| 1105 | − | |
| 1106 | − wdata->accel = input_allocate_device(); | |
| 1107 | − if (!wdata->accel) | |
| 1108 | − goto err_input; | |
| 1109 | − | |
| 1110 | − input_set_drvdata(wdata->accel, wdata); | |
| 1111 | − wdata->accel->open = wiimote_accel_open; | |
| 1112 | − wdata->accel->close = wiimote_accel_close; | |
| 1113 | − wdata->accel->dev.parent = &wdata->hdev->dev; | |
| 1114 | − wdata->accel->id.bustype = wdata->hdev->bus; | |
| 1115 | − wdata->accel->id.vendor = wdata->hdev->vendor; | |
| 1116 | − wdata->accel->id.product = wdata->hdev->product; | |
| 1117 | − wdata->accel->id.version = wdata->hdev->version; | |
| 1118 | − wdata->accel->name = WIIMOTE_NAME " Accelerometer"; | |
| 1119 | − | |
| 1120 | − set_bit(EV_ABS, wdata->accel->evbit); | |
| 1121 | − set_bit(ABS_RX, wdata->accel->absbit); | |
| 1122 | − set_bit(ABS_RY, wdata->accel->absbit); | |
| 1123 | − set_bit(ABS_RZ, wdata->accel->absbit); | |
| 1124 | − input_set_abs_params(wdata->accel, ABS_RX, -500, 500, 2, 4); | |
| 1125 | − input_set_abs_params(wdata->accel, ABS_RY, -500, 500, 2, 4); | |
| 1126 | − input_set_abs_params(wdata->accel, ABS_RZ, -500, 500, 2, 4); | |
| 1127 | − | |
| 1128 | − wdata->ir = input_allocate_device(); | |
| 1129 | − if (!wdata->ir) | |
| 1130 | − goto err_ir; | |
| 1131 | − | |
| 1132 | − input_set_drvdata(wdata->ir, wdata); | |
| 1133 | − wdata->ir->open = wiimote_ir_open; | |
| 1134 | − wdata->ir->close = wiimote_ir_close; | |
| 1135 | − wdata->ir->dev.parent = &wdata->hdev->dev; | |
| 1136 | − wdata->ir->id.bustype = wdata->hdev->bus; | |
| 1137 | − wdata->ir->id.vendor = wdata->hdev->vendor; | |
| 1138 | − wdata->ir->id.product = wdata->hdev->product; | |
| 1139 | − wdata->ir->id.version = wdata->hdev->version; | |
| 1140 | − wdata->ir->name = WIIMOTE_NAME " IR"; | |
| 1141 | − | |
| 1142 | − set_bit(EV_ABS, wdata->ir->evbit); | |
| 1143 | − set_bit(ABS_HAT0X, wdata->ir->absbit); | |
| 1144 | − set_bit(ABS_HAT0Y, wdata->ir->absbit); | |
| 1145 | − set_bit(ABS_HAT1X, wdata->ir->absbit); | |
| 1146 | − set_bit(ABS_HAT1Y, wdata->ir->absbit); | |
| 1147 | − set_bit(ABS_HAT2X, wdata->ir->absbit); | |
| 1148 | − set_bit(ABS_HAT2Y, wdata->ir->absbit); | |
| 1149 | − set_bit(ABS_HAT3X, wdata->ir->absbit); | |
| 1150 | − set_bit(ABS_HAT3Y, wdata->ir->absbit); | |
| 1151 | − input_set_abs_params(wdata->ir, ABS_HAT0X, 0, 1023, 2, 4); | |
| 1152 | − input_set_abs_params(wdata->ir, ABS_HAT0Y, 0, 767, 2, 4); | |
| 1153 | − input_set_abs_params(wdata->ir, ABS_HAT1X, 0, 1023, 2, 4); | |
| 1154 | − input_set_abs_params(wdata->ir, ABS_HAT1Y, 0, 767, 2, 4); | |
| 1155 | − input_set_abs_params(wdata->ir, ABS_HAT2X, 0, 1023, 2, 4); | |
| 1156 | − input_set_abs_params(wdata->ir, ABS_HAT2Y, 0, 767, 2, 4); | |
| 1157 | − input_set_abs_params(wdata->ir, ABS_HAT3X, 0, 1023, 2, 4); | |
| 1158 | − input_set_abs_params(wdata->ir, ABS_HAT3Y, 0, 767, 2, 4); | |
| 1159 | − | |
| 1160 | − spin_lock_init(&wdata->qlock); | |
| 1161 | − INIT_WORK(&wdata->worker, wiimote_worker); | |
| 1736 | + spin_lock_init(&wdata->queue.lock); | |
| 1737 | + INIT_WORK(&wdata->queue.worker, wiimote_queue_worker); | |
| 1162 | 1738 | |
| 1163 | 1739 | spin_lock_init(&wdata->state.lock); |
| 1164 | 1740 | init_completion(&wdata->state.ready); |
| 1165 | 1741 | mutex_init(&wdata->state.sync); |
| 1166 | 1742 | wdata->state.drm = WIIPROTO_REQ_DRM_K; |
| 1743 | + wdata->state.cmd_battery = 0xff; | |
| 1167 | 1744 | |
| 1168 | − return wdata; | |
| 1745 | + INIT_WORK(&wdata->init_worker, wiimote_init_worker); | |
| 1746 | + setup_timer(&wdata->timer, wiimote_init_timeout, (long)wdata); | |
| 1169 | 1747 | |
| 1170 | −err_ir: | |
| 1171 | − input_free_device(wdata->accel); | |
| 1172 | −err_input: | |
| 1173 | − input_free_device(wdata->input); | |
| 1174 | −err: | |
| 1175 | − kfree(wdata); | |
| 1176 | − return NULL; | |
| 1748 | + return wdata; | |
| 1177 | 1749 | } |
| 1178 | 1750 | |
| 1179 | 1751 | static void wiimote_destroy(struct wiimote_data *wdata) |
| 1180 | 1752 | { |
| 1753 | + unsigned long flags; | |
| 1754 | + | |
| 1181 | 1755 | wiidebug_deinit(wdata); |
| 1182 | − wiiext_deinit(wdata); | |
| 1183 | − wiimote_leds_destroy(wdata); | |
| 1184 | − | |
| 1185 | − power_supply_unregister(&wdata->battery); | |
| 1186 | − kfree(wdata->battery.name); | |
| 1187 | − input_unregister_device(wdata->accel); | |
| 1188 | − input_unregister_device(wdata->ir); | |
| 1189 | − input_unregister_device(wdata->input); | |
| 1190 | − cancel_work_sync(&wdata->worker); | |
| 1756 | + | |
| 1757 | + /* prevent init_worker from being scheduled again */ | |
| 1758 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 1759 | + wdata->state.flags |= WIIPROTO_FLAG_EXITING; | |
| 1760 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 1761 | + | |
| 1762 | + cancel_work_sync(&wdata->init_worker); | |
| 1763 | + del_timer_sync(&wdata->timer); | |
| 1764 | + | |
| 1765 | + device_remove_file(&wdata->hdev->dev, &dev_attr_devtype); | |
| 1766 | + device_remove_file(&wdata->hdev->dev, &dev_attr_extension); | |
| 1767 | + | |
| 1768 | + wiimote_mp_unload(wdata); | |
| 1769 | + wiimote_ext_unload(wdata); | |
| 1770 | + wiimote_modules_unload(wdata); | |
| 1771 | + cancel_work_sync(&wdata->queue.worker); | |
| 1772 | + hid_hw_close(wdata->hdev); | |
| 1191 | 1773 | hid_hw_stop(wdata->hdev); |
| 1192 | 1774 | |
| 1193 | 1775 | kfree(wdata); |
| @@ -1219,62 +1801,32 @@ static int wiimote_hid_probe(struct hid_device *hdev, · 25 unmodified lines | ||
| 1219 | 1801 | goto err; |
| 1220 | 1802 | } |
| 1221 | 1803 | |
| 1222 | − ret = input_register_device(wdata->accel); | |
| 1804 | + ret = hid_hw_open(hdev); | |
| 1223 | 1805 | if (ret) { |
| 1224 | − hid_err(hdev, "Cannot register input device\n"); | |
| 1806 | + hid_err(hdev, "cannot start hardware I/O\n"); | |
| 1225 | 1807 | goto err_stop; |
| 1226 | 1808 | } |
| 1227 | 1809 | |
| 1228 | − ret = input_register_device(wdata->ir); | |
| 1229 | − if (ret) { | |
| 1230 | − hid_err(hdev, "Cannot register input device\n"); | |
| 1231 | − goto err_ir; | |
| 1232 | − } | |
| 1233 | − | |
| 1234 | − ret = input_register_device(wdata->input); | |
| 1810 | + ret = device_create_file(&hdev->dev, &dev_attr_extension); | |
| 1235 | 1811 | if (ret) { |
| 1236 | − hid_err(hdev, "Cannot register input device\n"); | |
| 1237 | − goto err_input; | |
| 1238 | − } | |
| 1239 | − | |
| 1240 | − wdata->battery.properties = wiimote_battery_props; | |
| 1241 | − wdata->battery.num_properties = ARRAY_SIZE(wiimote_battery_props); | |
| 1242 | − wdata->battery.get_property = wiimote_battery_get_property; | |
| 1243 | − wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY; | |
| 1244 | − wdata->battery.use_for_apm = 0; | |
| 1245 | − wdata->battery.name = kasprintf(GFP_KERNEL, "wiimote_battery_%s", | |
| 1246 | − wdata->hdev->uniq); | |
| 1247 | − if (!wdata->battery.name) { | |
| 1248 | − ret = -ENOMEM; | |
| 1249 | − goto err_battery_name; | |
| 1812 | + hid_err(hdev, "cannot create sysfs attribute\n"); | |
| 1813 | + goto err_close; | |
| 1250 | 1814 | } |
| 1251 | 1815 | |
| 1252 | − ret = power_supply_register(&wdata->hdev->dev, &wdata->battery); | |
| 1816 | + ret = device_create_file(&hdev->dev, &dev_attr_devtype); | |
| 1253 | 1817 | if (ret) { |
| 1254 | − hid_err(hdev, "Cannot register battery device\n"); | |
| 1255 | − goto err_battery; | |
| 1818 | + hid_err(hdev, "cannot create sysfs attribute\n"); | |
| 1819 | + goto err_ext; | |
| 1256 | 1820 | } |
| 1257 | 1821 | |
| 1258 | − power_supply_powers(&wdata->battery, &hdev->dev); | |
| 1259 | − | |
| 1260 | − ret = wiimote_leds_create(wdata); | |
| 1261 | − if (ret) | |
| 1262 | − goto err_free; | |
| 1263 | − | |
| 1264 | − ret = wiiext_init(wdata); | |
| 1265 | − if (ret) | |
| 1266 | − goto err_free; | |
| 1267 | − | |
| 1268 | 1822 | ret = wiidebug_init(wdata); |
| 1269 | 1823 | if (ret) |
| 1270 | 1824 | goto err_free; |
| 1271 | 1825 | |
| 1272 | 1826 | hid_info(hdev, "New device registered\n"); |
| 1273 | 1827 | |
| 1274 | − /* by default set led1 after device initialization */ | |
| 1275 | − spin_lock_irq(&wdata->state.lock); | |
| 1276 | − wiiproto_req_leds(wdata, WIIPROTO_FLAG_LED1); | |
| 1277 | − spin_unlock_irq(&wdata->state.lock); | |
| 1828 | + /* schedule device detection */ | |
| 1829 | + wiimote_schedule(wdata); | |
| 1278 | 1830 | |
| 1279 | 1831 | return 0; |
| 1280 | 1832 | |
| @@ -1282,23 +1834,15 @@ err_free: · 1 unmodified line | ||
| 1282 | 1834 | wiimote_destroy(wdata); |
| 1283 | 1835 | return ret; |
| 1284 | 1836 | |
| 1285 | −err_battery: | |
| 1286 | − kfree(wdata->battery.name); | |
| 1287 | −err_battery_name: | |
| 1288 | − input_unregister_device(wdata->input); | |
| 1289 | − wdata->input = NULL; | |
| 1290 | −err_input: | |
| 1291 | − input_unregister_device(wdata->ir); | |
| 1292 | − wdata->ir = NULL; | |
| 1293 | −err_ir: | |
| 1294 | − input_unregister_device(wdata->accel); | |
| 1295 | − wdata->accel = NULL; | |
| 1837 | +err_ext: | |
| 1838 | + device_remove_file(&wdata->hdev->dev, &dev_attr_extension); | |
| 1839 | +err_close: | |
| 1840 | + hid_hw_close(hdev); | |
| 1296 | 1841 | err_stop: |
| 1297 | 1842 | hid_hw_stop(hdev); |
| 1298 | 1843 | err: |
| 1299 | 1844 | input_free_device(wdata->ir); |
| 1300 | 1845 | input_free_device(wdata->accel); |
| 1301 | − input_free_device(wdata->input); | |
| 1302 | 1846 | kfree(wdata); |
| 1303 | 1847 | return ret; |
| 1304 | 1848 | } |
| @@ -1331,4 +1875,4 @@ module_hid_driver(wiimote_hid_driver); · 26 unmodified lines | ||
| 1331 | 1875 | |
| 1332 | 1876 | MODULE_LICENSE("GPL"); |
| 1333 | 1877 | MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>"); |
| 1334 | −MODULE_DESCRIPTION(WIIMOTE_NAME " Device Driver"); | |
| 1878 | +MODULE_DESCRIPTION("Driver for Nintendo Wii / Wii U peripherals"); | |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | /* |
| 2 | − * Debug support for HID Nintendo Wiimote devices | |
| 3 | − * Copyright (c) 2011 David Herrmann | |
| 2 | + * Debug support for HID Nintendo Wii / Wii U peripherals | |
| 3 | + * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@gmail.com> | |
| 4 | 4 | */ |
| 5 | 5 | |
| 6 | 6 | /* |
| @@ -127,7 +127,8 @@ static int wiidebug_drm_open(struct inode *i, struct file *f) · 120 unmodified lines | ||
| 127 | 127 | static ssize_t wiidebug_drm_write(struct file *f, const char __user *u, |
| 128 | 128 | size_t s, loff_t *off) |
| 129 | 129 | { |
| 130 | − struct wiimote_debug *dbg = f->private_data; | |
| 130 | + struct seq_file *sf = f->private_data; | |
| 131 | + struct wiimote_debug *dbg = sf->private; | |
| 131 | 132 | unsigned long flags; |
| 132 | 133 | char buf[16]; |
| 133 | 134 | ssize_t len; |
| @@ -140,7 +141,7 @@ static ssize_t wiidebug_drm_write(struct file *f, const char __user *u, · 6 unmodified lines | ||
| 140 | 141 | if (copy_from_user(buf, u, len)) |
| 141 | 142 | return -EFAULT; |
| 142 | 143 | |
| 143 | − buf[15] = 0; | |
| 144 | + buf[len] = 0; | |
| 144 | 145 | |
| 145 | 146 | for (i = 0; i < WIIPROTO_REQ_MAX; ++i) { |
| 146 | 147 | if (!wiidebug_drmmap[i]) |
| @@ -150,10 +151,13 @@ static ssize_t wiidebug_drm_write(struct file *f, const char __user *u, · 3 unmodified lines | ||
| 150 | 151 | } |
| 151 | 152 | |
| 152 | 153 | if (i == WIIPROTO_REQ_MAX) |
| 153 | − i = simple_strtoul(buf, NULL, 10); | |
| 154 | + i = simple_strtoul(buf, NULL, 16); | |
| 154 | 155 | |
| 155 | 156 | spin_lock_irqsave(&dbg->wdata->state.lock, flags); |
| 157 | + dbg->wdata->state.flags &= ~WIIPROTO_FLAG_DRM_LOCKED; | |
| 156 | 158 | wiiproto_req_drm(dbg->wdata, (__u8) i); |
| 159 | + if (i != WIIPROTO_REQ_NULL) | |
| 160 | + dbg->wdata->state.flags |= WIIPROTO_FLAG_DRM_LOCKED; | |
| 157 | 161 | spin_unlock_irqrestore(&dbg->wdata->state.lock, flags); |
| 158 | 162 | |
| 159 | 163 | return len; |
| @@ -1,849 +0,0 @@ | ||
| 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 | − | |
| 19 | −struct wiimote_ext { | |
| 20 | − struct wiimote_data *wdata; | |
| 21 | − struct work_struct worker; | |
| 22 | − struct input_dev *input; | |
| 23 | − struct input_dev *mp_input; | |
| 24 | − | |
| 25 | − atomic_t opened; | |
| 26 | − atomic_t mp_opened; | |
| 27 | − bool plugged; | |
| 28 | − bool mp_plugged; | |
| 29 | − bool motionp; | |
| 30 | − __u8 ext_type; | |
| 31 | − __u16 calib[4][3]; | |
| 32 | −}; | |
| 33 | − | |
| 34 | −enum wiiext_type { | |
| 35 | − WIIEXT_NONE, /* placeholder */ | |
| 36 | − WIIEXT_CLASSIC, /* Nintendo classic controller */ | |
| 37 | − WIIEXT_NUNCHUCK, /* Nintendo nunchuck controller */ | |
| 38 | − WIIEXT_BALANCE_BOARD, /* Nintendo balance board controller */ | |
| 39 | −}; | |
| 40 | − | |
| 41 | −enum wiiext_keys { | |
| 42 | − WIIEXT_KEY_C, | |
| 43 | − WIIEXT_KEY_Z, | |
| 44 | − WIIEXT_KEY_A, | |
| 45 | − WIIEXT_KEY_B, | |
| 46 | − WIIEXT_KEY_X, | |
| 47 | − WIIEXT_KEY_Y, | |
| 48 | − WIIEXT_KEY_ZL, | |
| 49 | − WIIEXT_KEY_ZR, | |
| 50 | − WIIEXT_KEY_PLUS, | |
| 51 | − WIIEXT_KEY_MINUS, | |
| 52 | − WIIEXT_KEY_HOME, | |
| 53 | − WIIEXT_KEY_LEFT, | |
| 54 | − WIIEXT_KEY_RIGHT, | |
| 55 | − WIIEXT_KEY_UP, | |
| 56 | − WIIEXT_KEY_DOWN, | |
| 57 | − WIIEXT_KEY_LT, | |
| 58 | − WIIEXT_KEY_RT, | |
| 59 | − WIIEXT_KEY_COUNT | |
| 60 | −}; | |
| 61 | − | |
| 62 | −static __u16 wiiext_keymap[] = { | |
| 63 | − BTN_C, /* WIIEXT_KEY_C */ | |
| 64 | − BTN_Z, /* WIIEXT_KEY_Z */ | |
| 65 | − BTN_A, /* WIIEXT_KEY_A */ | |
| 66 | − BTN_B, /* WIIEXT_KEY_B */ | |
| 67 | − BTN_X, /* WIIEXT_KEY_X */ | |
| 68 | − BTN_Y, /* WIIEXT_KEY_Y */ | |
| 69 | − BTN_TL2, /* WIIEXT_KEY_ZL */ | |
| 70 | − BTN_TR2, /* WIIEXT_KEY_ZR */ | |
| 71 | − KEY_NEXT, /* WIIEXT_KEY_PLUS */ | |
| 72 | − KEY_PREVIOUS, /* WIIEXT_KEY_MINUS */ | |
| 73 | − BTN_MODE, /* WIIEXT_KEY_HOME */ | |
| 74 | − KEY_LEFT, /* WIIEXT_KEY_LEFT */ | |
| 75 | − KEY_RIGHT, /* WIIEXT_KEY_RIGHT */ | |
| 76 | − KEY_UP, /* WIIEXT_KEY_UP */ | |
| 77 | − KEY_DOWN, /* WIIEXT_KEY_DOWN */ | |
| 78 | − BTN_TL, /* WIIEXT_KEY_LT */ | |
| 79 | − BTN_TR, /* WIIEXT_KEY_RT */ | |
| 80 | −}; | |
| 81 | − | |
| 82 | −/* disable all extensions */ | |
| 83 | −static void ext_disable(struct wiimote_ext *ext) | |
| 84 | −{ | |
| 85 | − unsigned long flags; | |
| 86 | − __u8 wmem = 0x55; | |
| 87 | − | |
| 88 | − if (!wiimote_cmd_acquire(ext->wdata)) { | |
| 89 | − wiimote_cmd_write(ext->wdata, 0xa400f0, &wmem, sizeof(wmem)); | |
| 90 | − wiimote_cmd_release(ext->wdata); | |
| 91 | − } | |
| 92 | − | |
| 93 | − spin_lock_irqsave(&ext->wdata->state.lock, flags); | |
| 94 | − ext->motionp = false; | |
| 95 | − ext->ext_type = WIIEXT_NONE; | |
| 96 | − wiiproto_req_drm(ext->wdata, WIIPROTO_REQ_NULL); | |
| 97 | − spin_unlock_irqrestore(&ext->wdata->state.lock, flags); | |
| 98 | −} | |
| 99 | − | |
| 100 | −static bool motionp_read(struct wiimote_ext *ext) | |
| 101 | −{ | |
| 102 | − __u8 rmem[2], wmem; | |
| 103 | − ssize_t ret; | |
| 104 | − bool avail = false; | |
| 105 | − | |
| 106 | − if (!atomic_read(&ext->mp_opened)) | |
| 107 | − return false; | |
| 108 | − | |
| 109 | − if (wiimote_cmd_acquire(ext->wdata)) | |
| 110 | − return false; | |
| 111 | − | |
| 112 | − /* initialize motion plus */ | |
| 113 | − wmem = 0x55; | |
| 114 | − ret = wiimote_cmd_write(ext->wdata, 0xa600f0, &wmem, sizeof(wmem)); | |
| 115 | − if (ret) | |
| 116 | − goto error; | |
| 117 | − | |
| 118 | − /* read motion plus ID */ | |
| 119 | − ret = wiimote_cmd_read(ext->wdata, 0xa600fe, rmem, 2); | |
| 120 | − if (ret == 2 || rmem[1] == 0x5) | |
| 121 | − avail = true; | |
| 122 | − | |
| 123 | −error: | |
| 124 | − wiimote_cmd_release(ext->wdata); | |
| 125 | − return avail; | |
| 126 | −} | |
| 127 | − | |
| 128 | −static __u8 ext_read(struct wiimote_ext *ext) | |
| 129 | −{ | |
| 130 | − ssize_t ret; | |
| 131 | − __u8 buf[24], i, j, offs = 0; | |
| 132 | − __u8 rmem[2], wmem; | |
| 133 | − __u8 type = WIIEXT_NONE; | |
| 134 | − | |
| 135 | − if (!ext->plugged || !atomic_read(&ext->opened)) | |
| 136 | − return WIIEXT_NONE; | |
| 137 | − | |
| 138 | − if (wiimote_cmd_acquire(ext->wdata)) | |
| 139 | − return WIIEXT_NONE; | |
| 140 | − | |
| 141 | − /* initialize extension */ | |
| 142 | − wmem = 0x55; | |
| 143 | − ret = wiimote_cmd_write(ext->wdata, 0xa400f0, &wmem, sizeof(wmem)); | |
| 144 | − if (!ret) { | |
| 145 | − /* disable encryption */ | |
| 146 | − wmem = 0x0; | |
| 147 | − wiimote_cmd_write(ext->wdata, 0xa400fb, &wmem, sizeof(wmem)); | |
| 148 | − } | |
| 149 | − | |
| 150 | − /* read extension ID */ | |
| 151 | − ret = wiimote_cmd_read(ext->wdata, 0xa400fe, rmem, 2); | |
| 152 | − if (ret == 2) { | |
| 153 | − if (rmem[0] == 0 && rmem[1] == 0) | |
| 154 | − type = WIIEXT_NUNCHUCK; | |
| 155 | − else if (rmem[0] == 0x01 && rmem[1] == 0x01) | |
| 156 | − type = WIIEXT_CLASSIC; | |
| 157 | − else if (rmem[0] == 0x04 && rmem[1] == 0x02) | |
| 158 | − type = WIIEXT_BALANCE_BOARD; | |
| 159 | − } | |
| 160 | − | |
| 161 | − /* get balance board calibration data */ | |
| 162 | − if (type == WIIEXT_BALANCE_BOARD) { | |
| 163 | − ret = wiimote_cmd_read(ext->wdata, 0xa40024, buf, 12); | |
| 164 | − ret += wiimote_cmd_read(ext->wdata, 0xa40024 + 12, | |
| 165 | − buf + 12, 12); | |
| 166 | − | |
| 167 | − if (ret != 24) { | |
| 168 | − type = WIIEXT_NONE; | |
| 169 | − } else { | |
| 170 | − for (i = 0; i < 3; i++) { | |
| 171 | − for (j = 0; j < 4; j++) { | |
| 172 | − ext->calib[j][i] = buf[offs]; | |
| 173 | − ext->calib[j][i] <<= 8; | |
| 174 | − ext->calib[j][i] |= buf[offs + 1]; | |
| 175 | − offs += 2; | |
| 176 | − } | |
| 177 | − } | |
| 178 | − } | |
| 179 | − } | |
| 180 | − | |
| 181 | − wiimote_cmd_release(ext->wdata); | |
| 182 | − | |
| 183 | − return type; | |
| 184 | −} | |
| 185 | − | |
| 186 | −static void ext_enable(struct wiimote_ext *ext, bool motionp, __u8 ext_type) | |
| 187 | −{ | |
| 188 | − unsigned long flags; | |
| 189 | − __u8 wmem; | |
| 190 | − int ret; | |
| 191 | − | |
| 192 | − if (motionp) { | |
| 193 | − if (wiimote_cmd_acquire(ext->wdata)) | |
| 194 | − return; | |
| 195 | − | |
| 196 | − if (ext_type == WIIEXT_CLASSIC) | |
| 197 | − wmem = 0x07; | |
| 198 | − else if (ext_type == WIIEXT_NUNCHUCK) | |
| 199 | − wmem = 0x05; | |
| 200 | − else | |
| 201 | − wmem = 0x04; | |
| 202 | − | |
| 203 | − ret = wiimote_cmd_write(ext->wdata, 0xa600fe, &wmem, sizeof(wmem)); | |
| 204 | − wiimote_cmd_release(ext->wdata); | |
| 205 | − if (ret) | |
| 206 | − return; | |
| 207 | − } | |
| 208 | − | |
| 209 | − spin_lock_irqsave(&ext->wdata->state.lock, flags); | |
| 210 | − ext->motionp = motionp; | |
| 211 | − ext->ext_type = ext_type; | |
| 212 | − wiiproto_req_drm(ext->wdata, WIIPROTO_REQ_NULL); | |
| 213 | − spin_unlock_irqrestore(&ext->wdata->state.lock, flags); | |
| 214 | −} | |
| 215 | − | |
| 216 | −static void wiiext_worker(struct work_struct *work) | |
| 217 | −{ | |
| 218 | − struct wiimote_ext *ext = container_of(work, struct wiimote_ext, | |
| 219 | − worker); | |
| 220 | − bool motionp; | |
| 221 | − __u8 ext_type; | |
| 222 | − | |
| 223 | − ext_disable(ext); | |
| 224 | − motionp = motionp_read(ext); | |
| 225 | − ext_type = ext_read(ext); | |
| 226 | − ext_enable(ext, motionp, ext_type); | |
| 227 | −} | |
| 228 | − | |
| 229 | −/* schedule work only once, otherwise mark for reschedule */ | |
| 230 | −static void wiiext_schedule(struct wiimote_ext *ext) | |
| 231 | −{ | |
| 232 | − schedule_work(&ext->worker); | |
| 233 | −} | |
| 234 | − | |
| 235 | −/* | |
| 236 | − * Reacts on extension port events | |
| 237 | − * Whenever the driver gets an event from the wiimote that an extension has been | |
| 238 | − * plugged or unplugged, this funtion shall be called. It checks what extensions | |
| 239 | − * are connected and initializes and activates them. | |
| 240 | − * This can be called in atomic context. The initialization is done in a | |
| 241 | − * separate worker thread. The state.lock spinlock must be held by the caller. | |
| 242 | − */ | |
| 243 | −void wiiext_event(struct wiimote_data *wdata, bool plugged) | |
| 244 | −{ | |
| 245 | − if (!wdata->ext) | |
| 246 | − return; | |
| 247 | − | |
| 248 | − if (wdata->ext->plugged == plugged) | |
| 249 | − return; | |
| 250 | − | |
| 251 | − wdata->ext->plugged = plugged; | |
| 252 | − | |
| 253 | − if (!plugged) | |
| 254 | − wdata->ext->mp_plugged = false; | |
| 255 | − | |
| 256 | − /* | |
| 257 | − * We need to call wiiext_schedule(wdata->ext) here, however, the | |
| 258 | − * extension initialization logic is not fully understood and so | |
| 259 | − * automatic initialization is not supported, yet. | |
| 260 | − */ | |
| 261 | −} | |
| 262 | − | |
| 263 | −/* | |
| 264 | − * Returns true if the current DRM mode should contain extension data and false | |
| 265 | − * if there is no interest in extension data. | |
| 266 | − * All supported extensions send 6 byte extension data so any DRM that contains | |
| 267 | − * extension bytes is fine. | |
| 268 | − * The caller must hold the state.lock spinlock. | |
| 269 | − */ | |
| 270 | −bool wiiext_active(struct wiimote_data *wdata) | |
| 271 | −{ | |
| 272 | − if (!wdata->ext) | |
| 273 | − return false; | |
| 274 | − | |
| 275 | − return wdata->ext->motionp || wdata->ext->ext_type; | |
| 276 | −} | |
| 277 | − | |
| 278 | −static void handler_motionp(struct wiimote_ext *ext, const __u8 *payload) | |
| 279 | −{ | |
| 280 | − __s32 x, y, z; | |
| 281 | − bool plugged; | |
| 282 | − | |
| 283 | − /* | 8 7 6 5 4 3 | 2 | 1 | | |
| 284 | − * -----+------------------------------+-----+-----+ | |
| 285 | − * 1 | Yaw Speed <7:0> | | |
| 286 | − * 2 | Roll Speed <7:0> | | |
| 287 | − * 3 | Pitch Speed <7:0> | | |
| 288 | − * -----+------------------------------+-----+-----+ | |
| 289 | − * 4 | Yaw Speed <13:8> | Yaw |Pitch| | |
| 290 | − * -----+------------------------------+-----+-----+ | |
| 291 | − * 5 | Roll Speed <13:8> |Roll | Ext | | |
| 292 | − * -----+------------------------------+-----+-----+ | |
| 293 | − * 6 | Pitch Speed <13:8> | 1 | 0 | | |
| 294 | − * -----+------------------------------+-----+-----+ | |
| 295 | − * The single bits Yaw, Roll, Pitch in the lower right corner specify | |
| 296 | − * whether the wiimote is rotating fast (0) or slow (1). Speed for slow | |
| 297 | − * roation is 440 deg/s and for fast rotation 2000 deg/s. To get a | |
| 298 | − * linear scale we multiply by 2000/440 = ~4.5454 which is 18 for fast | |
| 299 | − * and 9 for slow. | |
| 300 | − * If the wiimote is not rotating the sensor reports 2^13 = 8192. | |
| 301 | − * Ext specifies whether an extension is connected to the motionp. | |
| 302 | − */ | |
| 303 | − | |
| 304 | − x = payload[0]; | |
| 305 | − y = payload[1]; | |
| 306 | − z = payload[2]; | |
| 307 | − | |
| 308 | − x |= (((__u16)payload[3]) << 6) & 0xff00; | |
| 309 | − y |= (((__u16)payload[4]) << 6) & 0xff00; | |
| 310 | − z |= (((__u16)payload[5]) << 6) & 0xff00; | |
| 311 | − | |
| 312 | − x -= 8192; | |
| 313 | − y -= 8192; | |
| 314 | − z -= 8192; | |
| 315 | − | |
| 316 | − if (!(payload[3] & 0x02)) | |
| 317 | − x *= 18; | |
| 318 | − else | |
| 319 | − x *= 9; | |
| 320 | − if (!(payload[4] & 0x02)) | |
| 321 | − y *= 18; | |
| 322 | − else | |
| 323 | − y *= 9; | |
| 324 | − if (!(payload[3] & 0x01)) | |
| 325 | − z *= 18; | |
| 326 | − else | |
| 327 | − z *= 9; | |
| 328 | − | |
| 329 | − input_report_abs(ext->mp_input, ABS_RX, x); | |
| 330 | − input_report_abs(ext->mp_input, ABS_RY, y); | |
| 331 | − input_report_abs(ext->mp_input, ABS_RZ, z); | |
| 332 | − input_sync(ext->mp_input); | |
| 333 | − | |
| 334 | − plugged = payload[5] & 0x01; | |
| 335 | − if (plugged != ext->mp_plugged) | |
| 336 | − ext->mp_plugged = plugged; | |
| 337 | −} | |
| 338 | − | |
| 339 | −static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload) | |
| 340 | −{ | |
| 341 | − __s16 x, y, z, bx, by; | |
| 342 | − | |
| 343 | − /* Byte | 8 7 | 6 5 | 4 3 | 2 | 1 | | |
| 344 | − * -----+----------+---------+---------+----+-----+ | |
| 345 | − * 1 | Button X <7:0> | | |
| 346 | − * 2 | Button Y <7:0> | | |
| 347 | − * -----+----------+---------+---------+----+-----+ | |
| 348 | − * 3 | Speed X <9:2> | | |
| 349 | − * 4 | Speed Y <9:2> | | |
| 350 | − * 5 | Speed Z <9:2> | | |
| 351 | − * -----+----------+---------+---------+----+-----+ | |
| 352 | − * 6 | Z <1:0> | Y <1:0> | X <1:0> | BC | BZ | | |
| 353 | − * -----+----------+---------+---------+----+-----+ | |
| 354 | − * Button X/Y is the analog stick. Speed X, Y and Z are the | |
| 355 | − * accelerometer data in the same format as the wiimote's accelerometer. | |
| 356 | − * The 6th byte contains the LSBs of the accelerometer data. | |
| 357 | − * BC and BZ are the C and Z buttons: 0 means pressed | |
| 358 | − * | |
| 359 | − * If reported interleaved with motionp, then the layout changes. The | |
| 360 | − * 5th and 6th byte changes to: | |
| 361 | − * -----+-----------------------------------+-----+ | |
| 362 | − * 5 | Speed Z <9:3> | EXT | | |
| 363 | − * -----+--------+-----+-----+----+----+----+-----+ | |
| 364 | − * 6 |Z <2:1> |Y <1>|X <1>| BC | BZ | 0 | 0 | | |
| 365 | − * -----+--------+-----+-----+----+----+----+-----+ | |
| 366 | − * All three accelerometer values lose their LSB. The other data is | |
| 367 | − * still available but slightly moved. | |
| 368 | − * | |
| 369 | − * Center data for button values is 128. Center value for accelerometer | |
| 370 | − * values it 512 / 0x200 | |
| 371 | − */ | |
| 372 | − | |
| 373 | − bx = payload[0]; | |
| 374 | − by = payload[1]; | |
| 375 | − bx -= 128; | |
| 376 | − by -= 128; | |
| 377 | − | |
| 378 | − x = payload[2] << 2; | |
| 379 | − y = payload[3] << 2; | |
| 380 | − z = payload[4] << 2; | |
| 381 | − | |
| 382 | − if (ext->motionp) { | |
| 383 | − x |= (payload[5] >> 3) & 0x02; | |
| 384 | − y |= (payload[5] >> 4) & 0x02; | |
| 385 | − z &= ~0x4; | |
| 386 | − z |= (payload[5] >> 5) & 0x06; | |
| 387 | − } else { | |
| 388 | − x |= (payload[5] >> 2) & 0x03; | |
| 389 | − y |= (payload[5] >> 4) & 0x03; | |
| 390 | − z |= (payload[5] >> 6) & 0x03; | |
| 391 | − } | |
| 392 | − | |
| 393 | − x -= 0x200; | |
| 394 | − y -= 0x200; | |
| 395 | − z -= 0x200; | |
| 396 | − | |
| 397 | − input_report_abs(ext->input, ABS_HAT0X, bx); | |
| 398 | − input_report_abs(ext->input, ABS_HAT0Y, by); | |
| 399 | − | |
| 400 | − input_report_abs(ext->input, ABS_RX, x); | |
| 401 | − input_report_abs(ext->input, ABS_RY, y); | |
| 402 | − input_report_abs(ext->input, ABS_RZ, z); | |
| 403 | − | |
| 404 | − if (ext->motionp) { | |
| 405 | − input_report_key(ext->input, | |
| 406 | − wiiext_keymap[WIIEXT_KEY_Z], !(payload[5] & 0x04)); | |
| 407 | − input_report_key(ext->input, | |
| 408 | − wiiext_keymap[WIIEXT_KEY_C], !(payload[5] & 0x08)); | |
| 409 | − } else { | |
| 410 | − input_report_key(ext->input, | |
| 411 | − wiiext_keymap[WIIEXT_KEY_Z], !(payload[5] & 0x01)); | |
| 412 | − input_report_key(ext->input, | |
| 413 | − wiiext_keymap[WIIEXT_KEY_C], !(payload[5] & 0x02)); | |
| 414 | − } | |
| 415 | − | |
| 416 | − input_sync(ext->input); | |
| 417 | −} | |
| 418 | − | |
| 419 | −static void handler_classic(struct wiimote_ext *ext, const __u8 *payload) | |
| 420 | −{ | |
| 421 | − __s8 rx, ry, lx, ly, lt, rt; | |
| 422 | − | |
| 423 | − /* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | | |
| 424 | − * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 425 | − * 1 | RX <5:4> | LX <5:0> | | |
| 426 | − * 2 | RX <3:2> | LY <5:0> | | |
| 427 | − * -----+-----+-----+-----+-----------------------------+ | |
| 428 | − * 3 |RX<1>| LT <5:4> | RY <5:1> | | |
| 429 | − * -----+-----+-----------+-----------------------------+ | |
| 430 | − * 4 | LT <3:1> | RT <5:1> | | |
| 431 | − * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 432 | − * 5 | BDR | BDD | BLT | B- | BH | B+ | BRT | 1 | | |
| 433 | − * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 434 | − * 6 | BZL | BB | BY | BA | BX | BZR | BDL | BDU | | |
| 435 | − * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 436 | − * All buttons are 0 if pressed | |
| 437 | − * RX and RY are right analog stick | |
| 438 | − * LX and LY are left analog stick | |
| 439 | − * LT is left trigger, RT is right trigger | |
| 440 | − * BLT is 0 if left trigger is fully pressed | |
| 441 | − * BRT is 0 if right trigger is fully pressed | |
| 442 | − * BDR, BDD, BDL, BDU form the D-Pad with right, down, left, up buttons | |
| 443 | − * BZL is left Z button and BZR is right Z button | |
| 444 | − * B-, BH, B+ are +, HOME and - buttons | |
| 445 | − * BB, BY, BA, BX are A, B, X, Y buttons | |
| 446 | − * LSB of RX, RY, LT, and RT are not transmitted and always 0. | |
| 447 | − * | |
| 448 | − * With motionp enabled it changes slightly to this: | |
| 449 | − * Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | | |
| 450 | − * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 451 | − * 1 | RX <4:3> | LX <5:1> | BDU | | |
| 452 | − * 2 | RX <2:1> | LY <5:1> | BDL | | |
| 453 | − * -----+-----+-----+-----+-----------------------+-----+ | |
| 454 | − * 3 |RX<0>| LT <4:3> | RY <4:0> | | |
| 455 | − * -----+-----+-----------+-----------------------------+ | |
| 456 | − * 4 | LT <2:0> | RT <4:0> | | |
| 457 | − * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 458 | − * 5 | BDR | BDD | BLT | B- | BH | B+ | BRT | EXT | | |
| 459 | − * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 460 | − * 6 | BZL | BB | BY | BA | BX | BZR | 0 | 0 | | |
| 461 | − * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 462 | − * Only the LSBs of LX and LY are lost. BDU and BDL are moved, the rest | |
| 463 | − * is the same as before. | |
| 464 | − */ | |
| 465 | − | |
| 466 | − if (ext->motionp) { | |
| 467 | − lx = payload[0] & 0x3e; | |
| 468 | − ly = payload[0] & 0x3e; | |
| 469 | − } else { | |
| 470 | − lx = payload[0] & 0x3f; | |
| 471 | − ly = payload[0] & 0x3f; | |
| 472 | − } | |
| 473 | − | |
| 474 | − rx = (payload[0] >> 3) & 0x14; | |
| 475 | − rx |= (payload[1] >> 5) & 0x06; | |
| 476 | − rx |= (payload[2] >> 7) & 0x01; | |
| 477 | − ry = payload[2] & 0x1f; | |
| 478 | − | |
| 479 | − rt = payload[3] & 0x1f; | |
| 480 | − lt = (payload[2] >> 2) & 0x18; | |
| 481 | − lt |= (payload[3] >> 5) & 0x07; | |
| 482 | − | |
| 483 | − rx <<= 1; | |
| 484 | − ry <<= 1; | |
| 485 | − rt <<= 1; | |
| 486 | − lt <<= 1; | |
| 487 | − | |
| 488 | − input_report_abs(ext->input, ABS_HAT1X, lx - 0x20); | |
| 489 | − input_report_abs(ext->input, ABS_HAT1Y, ly - 0x20); | |
| 490 | − input_report_abs(ext->input, ABS_HAT2X, rx - 0x20); | |
| 491 | − input_report_abs(ext->input, ABS_HAT2Y, ry - 0x20); | |
| 492 | − input_report_abs(ext->input, ABS_HAT3X, rt - 0x20); | |
| 493 | − input_report_abs(ext->input, ABS_HAT3Y, lt - 0x20); | |
| 494 | − | |
| 495 | − input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_RIGHT], | |
| 496 | − !!(payload[4] & 0x80)); | |
| 497 | − input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_DOWN], | |
| 498 | − !!(payload[4] & 0x40)); | |
| 499 | − input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LT], | |
| 500 | − !!(payload[4] & 0x20)); | |
| 501 | − input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_MINUS], | |
| 502 | − !!(payload[4] & 0x10)); | |
| 503 | − input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_HOME], | |
| 504 | − !!(payload[4] & 0x08)); | |
| 505 | − input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_PLUS], | |
| 506 | − !!(payload[4] & 0x04)); | |
| 507 | − input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_RT], | |
| 508 | − !!(payload[4] & 0x02)); | |
| 509 | − input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_ZL], | |
| 510 | − !!(payload[5] & 0x80)); | |
| 511 | − input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_B], | |
| 512 | − !!(payload[5] & 0x40)); | |
| 513 | − input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_Y], | |
| 514 | − !!(payload[5] & 0x20)); | |
| 515 | − input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_A], | |
| 516 | − !!(payload[5] & 0x10)); | |
| 517 | − input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_X], | |
| 518 | − !!(payload[5] & 0x08)); | |
| 519 | − input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_ZR], | |
| 520 | − !!(payload[5] & 0x04)); | |
| 521 | − | |
| 522 | − if (ext->motionp) { | |
| 523 | − input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_UP], | |
| 524 | − !!(payload[0] & 0x01)); | |
| 525 | − input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LEFT], | |
| 526 | − !!(payload[1] & 0x01)); | |
| 527 | − } else { | |
| 528 | − input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_UP], | |
| 529 | − !!(payload[5] & 0x01)); | |
| 530 | − input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LEFT], | |
| 531 | − !!(payload[5] & 0x02)); | |
| 532 | − } | |
| 533 | − | |
| 534 | − input_sync(ext->input); | |
| 535 | −} | |
| 536 | − | |
| 537 | −static void handler_balance_board(struct wiimote_ext *ext, const __u8 *payload) | |
| 538 | −{ | |
| 539 | − __s32 val[4], tmp; | |
| 540 | − unsigned int i; | |
| 541 | − | |
| 542 | − /* Byte | 8 7 6 5 4 3 2 1 | | |
| 543 | − * -----+--------------------------+ | |
| 544 | − * 1 | Top Right <15:8> | | |
| 545 | − * 2 | Top Right <7:0> | | |
| 546 | − * -----+--------------------------+ | |
| 547 | − * 3 | Bottom Right <15:8> | | |
| 548 | − * 4 | Bottom Right <7:0> | | |
| 549 | − * -----+--------------------------+ | |
| 550 | − * 5 | Top Left <15:8> | | |
| 551 | − * 6 | Top Left <7:0> | | |
| 552 | − * -----+--------------------------+ | |
| 553 | − * 7 | Bottom Left <15:8> | | |
| 554 | − * 8 | Bottom Left <7:0> | | |
| 555 | − * -----+--------------------------+ | |
| 556 | − * | |
| 557 | − * These values represent the weight-measurements of the Wii-balance | |
| 558 | − * board with 16bit precision. | |
| 559 | − * | |
| 560 | − * The balance-board is never reported interleaved with motionp. | |
| 561 | − */ | |
| 562 | − | |
| 563 | − val[0] = payload[0]; | |
| 564 | − val[0] <<= 8; | |
| 565 | − val[0] |= payload[1]; | |
| 566 | − | |
| 567 | − val[1] = payload[2]; | |
| 568 | − val[1] <<= 8; | |
| 569 | − val[1] |= payload[3]; | |
| 570 | − | |
| 571 | − val[2] = payload[4]; | |
| 572 | − val[2] <<= 8; | |
| 573 | − val[2] |= payload[5]; | |
| 574 | − | |
| 575 | − val[3] = payload[6]; | |
| 576 | − val[3] <<= 8; | |
| 577 | − val[3] |= payload[7]; | |
| 578 | − | |
| 579 | − /* apply calibration data */ | |
| 580 | − for (i = 0; i < 4; i++) { | |
| 581 | − if (val[i] < ext->calib[i][1]) { | |
| 582 | − tmp = val[i] - ext->calib[i][0]; | |
| 583 | − tmp *= 1700; | |
| 584 | − tmp /= ext->calib[i][1] - ext->calib[i][0]; | |
| 585 | − } else { | |
| 586 | − tmp = val[i] - ext->calib[i][1]; | |
| 587 | − tmp *= 1700; | |
| 588 | − tmp /= ext->calib[i][2] - ext->calib[i][1]; | |
| 589 | − tmp += 1700; | |
| 590 | − } | |
| 591 | − val[i] = tmp; | |
| 592 | − } | |
| 593 | − | |
| 594 | − input_report_abs(ext->input, ABS_HAT0X, val[0]); | |
| 595 | − input_report_abs(ext->input, ABS_HAT0Y, val[1]); | |
| 596 | − input_report_abs(ext->input, ABS_HAT1X, val[2]); | |
| 597 | − input_report_abs(ext->input, ABS_HAT1Y, val[3]); | |
| 598 | − | |
| 599 | − input_sync(ext->input); | |
| 600 | −} | |
| 601 | − | |
| 602 | −/* call this with state.lock spinlock held */ | |
| 603 | −void wiiext_handle(struct wiimote_data *wdata, const __u8 *payload) | |
| 604 | −{ | |
| 605 | − struct wiimote_ext *ext = wdata->ext; | |
| 606 | − | |
| 607 | − if (!ext) | |
| 608 | − return; | |
| 609 | − | |
| 610 | − if (ext->motionp && (payload[5] & 0x02)) { | |
| 611 | − handler_motionp(ext, payload); | |
| 612 | − } else if (ext->ext_type == WIIEXT_NUNCHUCK) { | |
| 613 | − handler_nunchuck(ext, payload); | |
| 614 | − } else if (ext->ext_type == WIIEXT_CLASSIC) { | |
| 615 | − handler_classic(ext, payload); | |
| 616 | − } else if (ext->ext_type == WIIEXT_BALANCE_BOARD) { | |
| 617 | − handler_balance_board(ext, payload); | |
| 618 | − } | |
| 619 | −} | |
| 620 | − | |
| 621 | −static ssize_t wiiext_show(struct device *dev, struct device_attribute *attr, | |
| 622 | − char *buf) | |
| 623 | −{ | |
| 624 | − struct wiimote_data *wdata = dev_to_wii(dev); | |
| 625 | − __u8 type = WIIEXT_NONE; | |
| 626 | − bool motionp = false; | |
| 627 | − unsigned long flags; | |
| 628 | − | |
| 629 | − spin_lock_irqsave(&wdata->state.lock, flags); | |
| 630 | − if (wdata->ext) { | |
| 631 | − motionp = wdata->ext->motionp; | |
| 632 | − type = wdata->ext->ext_type; | |
| 633 | − } | |
| 634 | − spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 635 | − | |
| 636 | − if (type == WIIEXT_NUNCHUCK) { | |
| 637 | − if (motionp) | |
| 638 | − return sprintf(buf, "motionp+nunchuck\n"); | |
| 639 | − else | |
| 640 | − return sprintf(buf, "nunchuck\n"); | |
| 641 | − } else if (type == WIIEXT_CLASSIC) { | |
| 642 | − if (motionp) | |
| 643 | − return sprintf(buf, "motionp+classic\n"); | |
| 644 | − else | |
| 645 | − return sprintf(buf, "classic\n"); | |
| 646 | − } else if (type == WIIEXT_BALANCE_BOARD) { | |
| 647 | − if (motionp) | |
| 648 | − return sprintf(buf, "motionp+balanceboard\n"); | |
| 649 | − else | |
| 650 | − return sprintf(buf, "balanceboard\n"); | |
| 651 | − } else { | |
| 652 | − if (motionp) | |
| 653 | − return sprintf(buf, "motionp\n"); | |
| 654 | − else | |
| 655 | − return sprintf(buf, "none\n"); | |
| 656 | − } | |
| 657 | −} | |
| 658 | − | |
| 659 | −static DEVICE_ATTR(extension, S_IRUGO, wiiext_show, NULL); | |
| 660 | − | |
| 661 | −static int wiiext_input_open(struct input_dev *dev) | |
| 662 | −{ | |
| 663 | − struct wiimote_ext *ext = input_get_drvdata(dev); | |
| 664 | − int ret; | |
| 665 | − | |
| 666 | − ret = hid_hw_open(ext->wdata->hdev); | |
| 667 | − if (ret) | |
| 668 | − return ret; | |
| 669 | − | |
| 670 | − atomic_inc(&ext->opened); | |
| 671 | − wiiext_schedule(ext); | |
| 672 | − | |
| 673 | − return 0; | |
| 674 | −} | |
| 675 | − | |
| 676 | −static void wiiext_input_close(struct input_dev *dev) | |
| 677 | −{ | |
| 678 | − struct wiimote_ext *ext = input_get_drvdata(dev); | |
| 679 | − | |
| 680 | − atomic_dec(&ext->opened); | |
| 681 | − wiiext_schedule(ext); | |
| 682 | − hid_hw_close(ext->wdata->hdev); | |
| 683 | −} | |
| 684 | − | |
| 685 | −static int wiiext_mp_open(struct input_dev *dev) | |
| 686 | −{ | |
| 687 | − struct wiimote_ext *ext = input_get_drvdata(dev); | |
| 688 | − int ret; | |
| 689 | − | |
| 690 | − ret = hid_hw_open(ext->wdata->hdev); | |
| 691 | − if (ret) | |
| 692 | − return ret; | |
| 693 | − | |
| 694 | − atomic_inc(&ext->mp_opened); | |
| 695 | − wiiext_schedule(ext); | |
| 696 | − | |
| 697 | − return 0; | |
| 698 | −} | |
| 699 | − | |
| 700 | −static void wiiext_mp_close(struct input_dev *dev) | |
| 701 | −{ | |
| 702 | − struct wiimote_ext *ext = input_get_drvdata(dev); | |
| 703 | − | |
| 704 | − atomic_dec(&ext->mp_opened); | |
| 705 | − wiiext_schedule(ext); | |
| 706 | − hid_hw_close(ext->wdata->hdev); | |
| 707 | −} | |
| 708 | − | |
| 709 | −/* Initializes the extension driver of a wiimote */ | |
| 710 | −int wiiext_init(struct wiimote_data *wdata) | |
| 711 | −{ | |
| 712 | − struct wiimote_ext *ext; | |
| 713 | − unsigned long flags; | |
| 714 | − int ret, i; | |
| 715 | − | |
| 716 | − ext = kzalloc(sizeof(*ext), GFP_KERNEL); | |
| 717 | − if (!ext) | |
| 718 | − return -ENOMEM; | |
| 719 | − | |
| 720 | − ext->wdata = wdata; | |
| 721 | − INIT_WORK(&ext->worker, wiiext_worker); | |
| 722 | − | |
| 723 | − ext->input = input_allocate_device(); | |
| 724 | − if (!ext->input) { | |
| 725 | − ret = -ENOMEM; | |
| 726 | − goto err_input; | |
| 727 | − } | |
| 728 | − | |
| 729 | − input_set_drvdata(ext->input, ext); | |
| 730 | − ext->input->open = wiiext_input_open; | |
| 731 | − ext->input->close = wiiext_input_close; | |
| 732 | − ext->input->dev.parent = &wdata->hdev->dev; | |
| 733 | − ext->input->id.bustype = wdata->hdev->bus; | |
| 734 | − ext->input->id.vendor = wdata->hdev->vendor; | |
| 735 | − ext->input->id.product = wdata->hdev->product; | |
| 736 | − ext->input->id.version = wdata->hdev->version; | |
| 737 | − ext->input->name = WIIMOTE_NAME " Extension"; | |
| 738 | − | |
| 739 | − set_bit(EV_KEY, ext->input->evbit); | |
| 740 | − for (i = 0; i < WIIEXT_KEY_COUNT; ++i) | |
| 741 | − set_bit(wiiext_keymap[i], ext->input->keybit); | |
| 742 | − | |
| 743 | − set_bit(EV_ABS, ext->input->evbit); | |
| 744 | − set_bit(ABS_HAT0X, ext->input->absbit); | |
| 745 | − set_bit(ABS_HAT0Y, ext->input->absbit); | |
| 746 | − set_bit(ABS_HAT1X, ext->input->absbit); | |
| 747 | − set_bit(ABS_HAT1Y, ext->input->absbit); | |
| 748 | − set_bit(ABS_HAT2X, ext->input->absbit); | |
| 749 | − set_bit(ABS_HAT2Y, ext->input->absbit); | |
| 750 | − set_bit(ABS_HAT3X, ext->input->absbit); | |
| 751 | − set_bit(ABS_HAT3Y, ext->input->absbit); | |
| 752 | − input_set_abs_params(ext->input, ABS_HAT0X, -120, 120, 2, 4); | |
| 753 | − input_set_abs_params(ext->input, ABS_HAT0Y, -120, 120, 2, 4); | |
| 754 | − input_set_abs_params(ext->input, ABS_HAT1X, -30, 30, 1, 1); | |
| 755 | − input_set_abs_params(ext->input, ABS_HAT1Y, -30, 30, 1, 1); | |
| 756 | − input_set_abs_params(ext->input, ABS_HAT2X, -30, 30, 1, 1); | |
| 757 | − input_set_abs_params(ext->input, ABS_HAT2Y, -30, 30, 1, 1); | |
| 758 | − input_set_abs_params(ext->input, ABS_HAT3X, -30, 30, 1, 1); | |
| 759 | − input_set_abs_params(ext->input, ABS_HAT3Y, -30, 30, 1, 1); | |
| 760 | − set_bit(ABS_RX, ext->input->absbit); | |
| 761 | − set_bit(ABS_RY, ext->input->absbit); | |
| 762 | − set_bit(ABS_RZ, ext->input->absbit); | |
| 763 | − input_set_abs_params(ext->input, ABS_RX, -500, 500, 2, 4); | |
| 764 | − input_set_abs_params(ext->input, ABS_RY, -500, 500, 2, 4); | |
| 765 | − input_set_abs_params(ext->input, ABS_RZ, -500, 500, 2, 4); | |
| 766 | − | |
| 767 | − ret = input_register_device(ext->input); | |
| 768 | − if (ret) { | |
| 769 | − input_free_device(ext->input); | |
| 770 | − goto err_input; | |
| 771 | − } | |
| 772 | − | |
| 773 | − ext->mp_input = input_allocate_device(); | |
| 774 | − if (!ext->mp_input) { | |
| 775 | − ret = -ENOMEM; | |
| 776 | − goto err_mp; | |
| 777 | − } | |
| 778 | − | |
| 779 | − input_set_drvdata(ext->mp_input, ext); | |
| 780 | − ext->mp_input->open = wiiext_mp_open; | |
| 781 | − ext->mp_input->close = wiiext_mp_close; | |
| 782 | − ext->mp_input->dev.parent = &wdata->hdev->dev; | |
| 783 | − ext->mp_input->id.bustype = wdata->hdev->bus; | |
| 784 | − ext->mp_input->id.vendor = wdata->hdev->vendor; | |
| 785 | − ext->mp_input->id.product = wdata->hdev->product; | |
| 786 | − ext->mp_input->id.version = wdata->hdev->version; | |
| 787 | − ext->mp_input->name = WIIMOTE_NAME " Motion+"; | |
| 788 | − | |
| 789 | − set_bit(EV_ABS, ext->mp_input->evbit); | |
| 790 | − set_bit(ABS_RX, ext->mp_input->absbit); | |
| 791 | − set_bit(ABS_RY, ext->mp_input->absbit); | |
| 792 | − set_bit(ABS_RZ, ext->mp_input->absbit); | |
| 793 | − input_set_abs_params(ext->mp_input, ABS_RX, -160000, 160000, 4, 8); | |
| 794 | − input_set_abs_params(ext->mp_input, ABS_RY, -160000, 160000, 4, 8); | |
| 795 | − input_set_abs_params(ext->mp_input, ABS_RZ, -160000, 160000, 4, 8); | |
| 796 | − | |
| 797 | − ret = input_register_device(ext->mp_input); | |
| 798 | − if (ret) { | |
| 799 | − input_free_device(ext->mp_input); | |
| 800 | − goto err_mp; | |
| 801 | − } | |
| 802 | − | |
| 803 | − ret = device_create_file(&wdata->hdev->dev, &dev_attr_extension); | |
| 804 | − if (ret) | |
| 805 | − goto err_dev; | |
| 806 | − | |
| 807 | − spin_lock_irqsave(&wdata->state.lock, flags); | |
| 808 | − wdata->ext = ext; | |
| 809 | − spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 810 | − | |
| 811 | − return 0; | |
| 812 | − | |
| 813 | −err_dev: | |
| 814 | − input_unregister_device(ext->mp_input); | |
| 815 | −err_mp: | |
| 816 | − input_unregister_device(ext->input); | |
| 817 | −err_input: | |
| 818 | − kfree(ext); | |
| 819 | − return ret; | |
| 820 | −} | |
| 821 | − | |
| 822 | −/* Deinitializes the extension driver of a wiimote */ | |
| 823 | −void wiiext_deinit(struct wiimote_data *wdata) | |
| 824 | −{ | |
| 825 | − struct wiimote_ext *ext = wdata->ext; | |
| 826 | − unsigned long flags; | |
| 827 | − | |
| 828 | − if (!ext) | |
| 829 | − return; | |
| 830 | − | |
| 831 | − /* | |
| 832 | − * We first unset wdata->ext to avoid further input from the wiimote | |
| 833 | − * core. The worker thread does not access this pointer so it is not | |
| 834 | − * affected by this. | |
| 835 | − * We kill the worker after this so it does not get respawned during | |
| 836 | − * deinitialization. | |
| 837 | − */ | |
| 838 | − | |
| 839 | − spin_lock_irqsave(&wdata->state.lock, flags); | |
| 840 | − wdata->ext = NULL; | |
| 841 | − spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 842 | − | |
| 843 | − device_remove_file(&wdata->hdev->dev, &dev_attr_extension); | |
| 844 | − input_unregister_device(ext->mp_input); | |
| 845 | − input_unregister_device(ext->input); | |
| 846 | − | |
| 847 | − cancel_work_sync(&ext->worker); | |
| 848 | − kfree(ext); | |
| 849 | −} | |
| @@ -0,0 +1,2086 @@ | ||
| 1 | +/* | |
| 2 | + * Device Modules for Nintendo Wii / Wii U HID Driver | |
| 3 | + * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@gmail.com> | |
| 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 | +/* | |
| 14 | + * Wiimote Modules | |
| 15 | + * Nintendo devices provide different peripherals and many new devices lack | |
| 16 | + * initial features like the IR camera. Therefore, each peripheral device is | |
| 17 | + * implemented as an independent module and we probe on each device only the | |
| 18 | + * modules for the hardware that really is available. | |
| 19 | + * | |
| 20 | + * Module registration is sequential. Unregistration is done in reverse order. | |
| 21 | + * After device detection, the needed modules are loaded. Users can trigger | |
| 22 | + * re-detection which causes all modules to be unloaded and then reload the | |
| 23 | + * modules for the new detected device. | |
| 24 | + * | |
| 25 | + * wdata->input is a shared input device. It is always initialized prior to | |
| 26 | + * module registration. If at least one registered module is marked as | |
| 27 | + * WIIMOD_FLAG_INPUT, then the input device will get registered after all | |
| 28 | + * modules were registered. | |
| 29 | + * Please note that it is unregistered _before_ the "remove" callbacks are | |
| 30 | + * called. This guarantees that no input interaction is done, anymore. However, | |
| 31 | + * the wiimote core keeps a reference to the input device so it is freed only | |
| 32 | + * after all modules were removed. It is safe to send events to unregistered | |
| 33 | + * input devices. | |
| 34 | + */ | |
| 35 | + | |
| 36 | +#include <linux/device.h> | |
| 37 | +#include <linux/hid.h> | |
| 38 | +#include <linux/input.h> | |
| 39 | +#include <linux/spinlock.h> | |
| 40 | +#include "hid-wiimote.h" | |
| 41 | + | |
| 42 | +/* | |
| 43 | + * Keys | |
| 44 | + * The initial Wii Remote provided a bunch of buttons that are reported as | |
| 45 | + * part of the core protocol. Many later devices dropped these and report | |
| 46 | + * invalid data in the core button reports. Load this only on devices which | |
| 47 | + * correctly send button reports. | |
| 48 | + * It uses the shared input device. | |
| 49 | + */ | |
| 50 | + | |
| 51 | +static const __u16 wiimod_keys_map[] = { | |
| 52 | + KEY_LEFT, /* WIIPROTO_KEY_LEFT */ | |
| 53 | + KEY_RIGHT, /* WIIPROTO_KEY_RIGHT */ | |
| 54 | + KEY_UP, /* WIIPROTO_KEY_UP */ | |
| 55 | + KEY_DOWN, /* WIIPROTO_KEY_DOWN */ | |
| 56 | + KEY_NEXT, /* WIIPROTO_KEY_PLUS */ | |
| 57 | + KEY_PREVIOUS, /* WIIPROTO_KEY_MINUS */ | |
| 58 | + BTN_1, /* WIIPROTO_KEY_ONE */ | |
| 59 | + BTN_2, /* WIIPROTO_KEY_TWO */ | |
| 60 | + BTN_A, /* WIIPROTO_KEY_A */ | |
| 61 | + BTN_B, /* WIIPROTO_KEY_B */ | |
| 62 | + BTN_MODE, /* WIIPROTO_KEY_HOME */ | |
| 63 | +}; | |
| 64 | + | |
| 65 | +static void wiimod_keys_in_keys(struct wiimote_data *wdata, const __u8 *keys) | |
| 66 | +{ | |
| 67 | + input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_LEFT], | |
| 68 | + !!(keys[0] & 0x01)); | |
| 69 | + input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_RIGHT], | |
| 70 | + !!(keys[0] & 0x02)); | |
| 71 | + input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_DOWN], | |
| 72 | + !!(keys[0] & 0x04)); | |
| 73 | + input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_UP], | |
| 74 | + !!(keys[0] & 0x08)); | |
| 75 | + input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_PLUS], | |
| 76 | + !!(keys[0] & 0x10)); | |
| 77 | + input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_TWO], | |
| 78 | + !!(keys[1] & 0x01)); | |
| 79 | + input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_ONE], | |
| 80 | + !!(keys[1] & 0x02)); | |
| 81 | + input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_B], | |
| 82 | + !!(keys[1] & 0x04)); | |
| 83 | + input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_A], | |
| 84 | + !!(keys[1] & 0x08)); | |
| 85 | + input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_MINUS], | |
| 86 | + !!(keys[1] & 0x10)); | |
| 87 | + input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_HOME], | |
| 88 | + !!(keys[1] & 0x80)); | |
| 89 | + input_sync(wdata->input); | |
| 90 | +} | |
| 91 | + | |
| 92 | +static int wiimod_keys_probe(const struct wiimod_ops *ops, | |
| 93 | + struct wiimote_data *wdata) | |
| 94 | +{ | |
| 95 | + unsigned int i; | |
| 96 | + | |
| 97 | + set_bit(EV_KEY, wdata->input->evbit); | |
| 98 | + for (i = 0; i < WIIPROTO_KEY_COUNT; ++i) | |
| 99 | + set_bit(wiimod_keys_map[i], wdata->input->keybit); | |
| 100 | + | |
| 101 | + return 0; | |
| 102 | +} | |
| 103 | + | |
| 104 | +static const struct wiimod_ops wiimod_keys = { | |
| 105 | + .flags = WIIMOD_FLAG_INPUT, | |
| 106 | + .arg = 0, | |
| 107 | + .probe = wiimod_keys_probe, | |
| 108 | + .remove = NULL, | |
| 109 | + .in_keys = wiimod_keys_in_keys, | |
| 110 | +}; | |
| 111 | + | |
| 112 | +/* | |
| 113 | + * Rumble | |
| 114 | + * Nearly all devices provide a rumble feature. A small motor for | |
| 115 | + * force-feedback effects. We provide an FF_RUMBLE memless ff device on the | |
| 116 | + * shared input device if this module is loaded. | |
| 117 | + * The rumble motor is controlled via a flag on almost every output report so | |
| 118 | + * the wiimote core handles the rumble flag. But if a device doesn't provide | |
| 119 | + * the rumble motor, this flag shouldn't be set. | |
| 120 | + */ | |
| 121 | + | |
| 122 | +static int wiimod_rumble_play(struct input_dev *dev, void *data, | |
| 123 | + struct ff_effect *eff) | |
| 124 | +{ | |
| 125 | + struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 126 | + __u8 value; | |
| 127 | + unsigned long flags; | |
| 128 | + | |
| 129 | + /* | |
| 130 | + * The wiimote supports only a single rumble motor so if any magnitude | |
| 131 | + * is set to non-zero then we start the rumble motor. If both are set to | |
| 132 | + * zero, we stop the rumble motor. | |
| 133 | + */ | |
| 134 | + | |
| 135 | + if (eff->u.rumble.strong_magnitude || eff->u.rumble.weak_magnitude) | |
| 136 | + value = 1; | |
| 137 | + else | |
| 138 | + value = 0; | |
| 139 | + | |
| 140 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 141 | + wiiproto_req_rumble(wdata, value); | |
| 142 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 143 | + | |
| 144 | + return 0; | |
| 145 | +} | |
| 146 | + | |
| 147 | +static int wiimod_rumble_probe(const struct wiimod_ops *ops, | |
| 148 | + struct wiimote_data *wdata) | |
| 149 | +{ | |
| 150 | + set_bit(FF_RUMBLE, wdata->input->ffbit); | |
| 151 | + if (input_ff_create_memless(wdata->input, NULL, wiimod_rumble_play)) | |
| 152 | + return -ENOMEM; | |
| 153 | + | |
| 154 | + return 0; | |
| 155 | +} | |
| 156 | + | |
| 157 | +static void wiimod_rumble_remove(const struct wiimod_ops *ops, | |
| 158 | + struct wiimote_data *wdata) | |
| 159 | +{ | |
| 160 | + unsigned long flags; | |
| 161 | + | |
| 162 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 163 | + wiiproto_req_rumble(wdata, 0); | |
| 164 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 165 | +} | |
| 166 | + | |
| 167 | +static const struct wiimod_ops wiimod_rumble = { | |
| 168 | + .flags = WIIMOD_FLAG_INPUT, | |
| 169 | + .arg = 0, | |
| 170 | + .probe = wiimod_rumble_probe, | |
| 171 | + .remove = wiimod_rumble_remove, | |
| 172 | +}; | |
| 173 | + | |
| 174 | +/* | |
| 175 | + * Battery | |
| 176 | + * 1 byte of battery capacity information is sent along every protocol status | |
| 177 | + * report. The wiimote core caches it but we try to update it on every | |
| 178 | + * user-space request. | |
| 179 | + * This is supported by nearly every device so it's almost always enabled. | |
| 180 | + */ | |
| 181 | + | |
| 182 | +static enum power_supply_property wiimod_battery_props[] = { | |
| 183 | + POWER_SUPPLY_PROP_CAPACITY, | |
| 184 | + POWER_SUPPLY_PROP_SCOPE, | |
| 185 | +}; | |
| 186 | + | |
| 187 | +static int wiimod_battery_get_property(struct power_supply *psy, | |
| 188 | + enum power_supply_property psp, | |
| 189 | + union power_supply_propval *val) | |
| 190 | +{ | |
| 191 | + struct wiimote_data *wdata = container_of(psy, struct wiimote_data, | |
| 192 | + battery); | |
| 193 | + int ret = 0, state; | |
| 194 | + unsigned long flags; | |
| 195 | + | |
| 196 | + if (psp == POWER_SUPPLY_PROP_SCOPE) { | |
| 197 | + val->intval = POWER_SUPPLY_SCOPE_DEVICE; | |
| 198 | + return 0; | |
| 199 | + } else if (psp != POWER_SUPPLY_PROP_CAPACITY) { | |
| 200 | + return -EINVAL; | |
| 201 | + } | |
| 202 | + | |
| 203 | + ret = wiimote_cmd_acquire(wdata); | |
| 204 | + if (ret) | |
| 205 | + return ret; | |
| 206 | + | |
| 207 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 208 | + wiimote_cmd_set(wdata, WIIPROTO_REQ_SREQ, 0); | |
| 209 | + wiiproto_req_status(wdata); | |
| 210 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 211 | + | |
| 212 | + wiimote_cmd_wait(wdata); | |
| 213 | + wiimote_cmd_release(wdata); | |
| 214 | + | |
| 215 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 216 | + state = wdata->state.cmd_battery; | |
| 217 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 218 | + | |
| 219 | + val->intval = state * 100 / 255; | |
| 220 | + return ret; | |
| 221 | +} | |
| 222 | + | |
| 223 | +static int wiimod_battery_probe(const struct wiimod_ops *ops, | |
| 224 | + struct wiimote_data *wdata) | |
| 225 | +{ | |
| 226 | + int ret; | |
| 227 | + | |
| 228 | + wdata->battery.properties = wiimod_battery_props; | |
| 229 | + wdata->battery.num_properties = ARRAY_SIZE(wiimod_battery_props); | |
| 230 | + wdata->battery.get_property = wiimod_battery_get_property; | |
| 231 | + wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY; | |
| 232 | + wdata->battery.use_for_apm = 0; | |
| 233 | + wdata->battery.name = kasprintf(GFP_KERNEL, "wiimote_battery_%s", | |
| 234 | + wdata->hdev->uniq); | |
| 235 | + if (!wdata->battery.name) | |
| 236 | + return -ENOMEM; | |
| 237 | + | |
| 238 | + ret = power_supply_register(&wdata->hdev->dev, &wdata->battery); | |
| 239 | + if (ret) { | |
| 240 | + hid_err(wdata->hdev, "cannot register battery device\n"); | |
| 241 | + goto err_free; | |
| 242 | + } | |
| 243 | + | |
| 244 | + power_supply_powers(&wdata->battery, &wdata->hdev->dev); | |
| 245 | + return 0; | |
| 246 | + | |
| 247 | +err_free: | |
| 248 | + kfree(wdata->battery.name); | |
| 249 | + wdata->battery.name = NULL; | |
| 250 | + return ret; | |
| 251 | +} | |
| 252 | + | |
| 253 | +static void wiimod_battery_remove(const struct wiimod_ops *ops, | |
| 254 | + struct wiimote_data *wdata) | |
| 255 | +{ | |
| 256 | + if (!wdata->battery.name) | |
| 257 | + return; | |
| 258 | + | |
| 259 | + power_supply_unregister(&wdata->battery); | |
| 260 | + kfree(wdata->battery.name); | |
| 261 | + wdata->battery.name = NULL; | |
| 262 | +} | |
| 263 | + | |
| 264 | +static const struct wiimod_ops wiimod_battery = { | |
| 265 | + .flags = 0, | |
| 266 | + .arg = 0, | |
| 267 | + .probe = wiimod_battery_probe, | |
| 268 | + .remove = wiimod_battery_remove, | |
| 269 | +}; | |
| 270 | + | |
| 271 | +/* | |
| 272 | + * LED | |
| 273 | + * 0 to 4 player LEDs are supported by devices. The "arg" field of the | |
| 274 | + * wiimod_ops structure specifies which LED this module controls. This allows | |
| 275 | + * to register a limited number of LEDs. | |
| 276 | + * State is managed by wiimote core. | |
| 277 | + */ | |
| 278 | + | |
| 279 | +static enum led_brightness wiimod_led_get(struct led_classdev *led_dev) | |
| 280 | +{ | |
| 281 | + struct wiimote_data *wdata; | |
| 282 | + struct device *dev = led_dev->dev->parent; | |
| 283 | + int i; | |
| 284 | + unsigned long flags; | |
| 285 | + bool value = false; | |
| 286 | + | |
| 287 | + wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); | |
| 288 | + | |
| 289 | + for (i = 0; i < 4; ++i) { | |
| 290 | + if (wdata->leds[i] == led_dev) { | |
| 291 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 292 | + value = wdata->state.flags & WIIPROTO_FLAG_LED(i + 1); | |
| 293 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 294 | + break; | |
| 295 | + } | |
| 296 | + } | |
| 297 | + | |
| 298 | + return value ? LED_FULL : LED_OFF; | |
| 299 | +} | |
| 300 | + | |
| 301 | +static void wiimod_led_set(struct led_classdev *led_dev, | |
| 302 | + enum led_brightness value) | |
| 303 | +{ | |
| 304 | + struct wiimote_data *wdata; | |
| 305 | + struct device *dev = led_dev->dev->parent; | |
| 306 | + int i; | |
| 307 | + unsigned long flags; | |
| 308 | + __u8 state, flag; | |
| 309 | + | |
| 310 | + wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); | |
| 311 | + | |
| 312 | + for (i = 0; i < 4; ++i) { | |
| 313 | + if (wdata->leds[i] == led_dev) { | |
| 314 | + flag = WIIPROTO_FLAG_LED(i + 1); | |
| 315 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 316 | + state = wdata->state.flags; | |
| 317 | + if (value == LED_OFF) | |
| 318 | + wiiproto_req_leds(wdata, state & ~flag); | |
| 319 | + else | |
| 320 | + wiiproto_req_leds(wdata, state | flag); | |
| 321 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 322 | + break; | |
| 323 | + } | |
| 324 | + } | |
| 325 | +} | |
| 326 | + | |
| 327 | +static int wiimod_led_probe(const struct wiimod_ops *ops, | |
| 328 | + struct wiimote_data *wdata) | |
| 329 | +{ | |
| 330 | + struct device *dev = &wdata->hdev->dev; | |
| 331 | + size_t namesz = strlen(dev_name(dev)) + 9; | |
| 332 | + struct led_classdev *led; | |
| 333 | + unsigned long flags; | |
| 334 | + char *name; | |
| 335 | + int ret; | |
| 336 | + | |
| 337 | + led = kzalloc(sizeof(struct led_classdev) + namesz, GFP_KERNEL); | |
| 338 | + if (!led) | |
| 339 | + return -ENOMEM; | |
| 340 | + | |
| 341 | + name = (void*)&led[1]; | |
| 342 | + snprintf(name, namesz, "%s:blue:p%lu", dev_name(dev), ops->arg); | |
| 343 | + led->name = name; | |
| 344 | + led->brightness = 0; | |
| 345 | + led->max_brightness = 1; | |
| 346 | + led->brightness_get = wiimod_led_get; | |
| 347 | + led->brightness_set = wiimod_led_set; | |
| 348 | + | |
| 349 | + wdata->leds[ops->arg] = led; | |
| 350 | + ret = led_classdev_register(dev, led); | |
| 351 | + if (ret) | |
| 352 | + goto err_free; | |
| 353 | + | |
| 354 | + /* enable LED1 to stop initial LED-blinking */ | |
| 355 | + if (ops->arg == 0) { | |
| 356 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 357 | + wiiproto_req_leds(wdata, WIIPROTO_FLAG_LED1); | |
| 358 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 359 | + } | |
| 360 | + | |
| 361 | + return 0; | |
| 362 | + | |
| 363 | +err_free: | |
| 364 | + wdata->leds[ops->arg] = NULL; | |
| 365 | + kfree(led); | |
| 366 | + return ret; | |
| 367 | +} | |
| 368 | + | |
| 369 | +static void wiimod_led_remove(const struct wiimod_ops *ops, | |
| 370 | + struct wiimote_data *wdata) | |
| 371 | +{ | |
| 372 | + if (!wdata->leds[ops->arg]) | |
| 373 | + return; | |
| 374 | + | |
| 375 | + led_classdev_unregister(wdata->leds[ops->arg]); | |
| 376 | + kfree(wdata->leds[ops->arg]); | |
| 377 | + wdata->leds[ops->arg] = NULL; | |
| 378 | +} | |
| 379 | + | |
| 380 | +static const struct wiimod_ops wiimod_leds[4] = { | |
| 381 | + { | |
| 382 | + .flags = 0, | |
| 383 | + .arg = 0, | |
| 384 | + .probe = wiimod_led_probe, | |
| 385 | + .remove = wiimod_led_remove, | |
| 386 | + }, | |
| 387 | + { | |
| 388 | + .flags = 0, | |
| 389 | + .arg = 1, | |
| 390 | + .probe = wiimod_led_probe, | |
| 391 | + .remove = wiimod_led_remove, | |
| 392 | + }, | |
| 393 | + { | |
| 394 | + .flags = 0, | |
| 395 | + .arg = 2, | |
| 396 | + .probe = wiimod_led_probe, | |
| 397 | + .remove = wiimod_led_remove, | |
| 398 | + }, | |
| 399 | + { | |
| 400 | + .flags = 0, | |
| 401 | + .arg = 3, | |
| 402 | + .probe = wiimod_led_probe, | |
| 403 | + .remove = wiimod_led_remove, | |
| 404 | + }, | |
| 405 | +}; | |
| 406 | + | |
| 407 | +/* | |
| 408 | + * Accelerometer | |
| 409 | + * 3 axis accelerometer data is part of nearly all DRMs. If not supported by a | |
| 410 | + * device, it's mostly cleared to 0. This module parses this data and provides | |
| 411 | + * it via a separate input device. | |
| 412 | + */ | |
| 413 | + | |
| 414 | +static void wiimod_accel_in_accel(struct wiimote_data *wdata, | |
| 415 | + const __u8 *accel) | |
| 416 | +{ | |
| 417 | + __u16 x, y, z; | |
| 418 | + | |
| 419 | + if (!(wdata->state.flags & WIIPROTO_FLAG_ACCEL)) | |
| 420 | + return; | |
| 421 | + | |
| 422 | + /* | |
| 423 | + * payload is: BB BB XX YY ZZ | |
| 424 | + * Accelerometer data is encoded into 3 10bit values. XX, YY and ZZ | |
| 425 | + * contain the upper 8 bits of each value. The lower 2 bits are | |
| 426 | + * contained in the buttons data BB BB. | |
| 427 | + * Bits 6 and 7 of the first buttons byte BB is the lower 2 bits of the | |
| 428 | + * X accel value. Bit 5 of the second buttons byte is the 2nd bit of Y | |
| 429 | + * accel value and bit 6 is the second bit of the Z value. | |
| 430 | + * The first bit of Y and Z values is not available and always set to 0. | |
| 431 | + * 0x200 is returned on no movement. | |
| 432 | + */ | |
| 433 | + | |
| 434 | + x = accel[2] << 2; | |
| 435 | + y = accel[3] << 2; | |
| 436 | + z = accel[4] << 2; | |
| 437 | + | |
| 438 | + x |= (accel[0] >> 5) & 0x3; | |
| 439 | + y |= (accel[1] >> 4) & 0x2; | |
| 440 | + z |= (accel[1] >> 5) & 0x2; | |
| 441 | + | |
| 442 | + input_report_abs(wdata->accel, ABS_RX, x - 0x200); | |
| 443 | + input_report_abs(wdata->accel, ABS_RY, y - 0x200); | |
| 444 | + input_report_abs(wdata->accel, ABS_RZ, z - 0x200); | |
| 445 | + input_sync(wdata->accel); | |
| 446 | +} | |
| 447 | + | |
| 448 | +static int wiimod_accel_open(struct input_dev *dev) | |
| 449 | +{ | |
| 450 | + struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 451 | + unsigned long flags; | |
| 452 | + | |
| 453 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 454 | + wiiproto_req_accel(wdata, true); | |
| 455 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 456 | + | |
| 457 | + return 0; | |
| 458 | +} | |
| 459 | + | |
| 460 | +static void wiimod_accel_close(struct input_dev *dev) | |
| 461 | +{ | |
| 462 | + struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 463 | + unsigned long flags; | |
| 464 | + | |
| 465 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 466 | + wiiproto_req_accel(wdata, false); | |
| 467 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 468 | +} | |
| 469 | + | |
| 470 | +static int wiimod_accel_probe(const struct wiimod_ops *ops, | |
| 471 | + struct wiimote_data *wdata) | |
| 472 | +{ | |
| 473 | + int ret; | |
| 474 | + | |
| 475 | + wdata->accel = input_allocate_device(); | |
| 476 | + if (!wdata->accel) | |
| 477 | + return -ENOMEM; | |
| 478 | + | |
| 479 | + input_set_drvdata(wdata->accel, wdata); | |
| 480 | + wdata->accel->open = wiimod_accel_open; | |
| 481 | + wdata->accel->close = wiimod_accel_close; | |
| 482 | + wdata->accel->dev.parent = &wdata->hdev->dev; | |
| 483 | + wdata->accel->id.bustype = wdata->hdev->bus; | |
| 484 | + wdata->accel->id.vendor = wdata->hdev->vendor; | |
| 485 | + wdata->accel->id.product = wdata->hdev->product; | |
| 486 | + wdata->accel->id.version = wdata->hdev->version; | |
| 487 | + wdata->accel->name = WIIMOTE_NAME " Accelerometer"; | |
| 488 | + | |
| 489 | + set_bit(EV_ABS, wdata->accel->evbit); | |
| 490 | + set_bit(ABS_RX, wdata->accel->absbit); | |
| 491 | + set_bit(ABS_RY, wdata->accel->absbit); | |
| 492 | + set_bit(ABS_RZ, wdata->accel->absbit); | |
| 493 | + input_set_abs_params(wdata->accel, ABS_RX, -500, 500, 2, 4); | |
| 494 | + input_set_abs_params(wdata->accel, ABS_RY, -500, 500, 2, 4); | |
| 495 | + input_set_abs_params(wdata->accel, ABS_RZ, -500, 500, 2, 4); | |
| 496 | + | |
| 497 | + ret = input_register_device(wdata->accel); | |
| 498 | + if (ret) { | |
| 499 | + hid_err(wdata->hdev, "cannot register input device\n"); | |
| 500 | + goto err_free; | |
| 501 | + } | |
| 502 | + | |
| 503 | + return 0; | |
| 504 | + | |
| 505 | +err_free: | |
| 506 | + input_free_device(wdata->accel); | |
| 507 | + wdata->accel = NULL; | |
| 508 | + return ret; | |
| 509 | +} | |
| 510 | + | |
| 511 | +static void wiimod_accel_remove(const struct wiimod_ops *ops, | |
| 512 | + struct wiimote_data *wdata) | |
| 513 | +{ | |
| 514 | + if (!wdata->accel) | |
| 515 | + return; | |
| 516 | + | |
| 517 | + input_unregister_device(wdata->accel); | |
| 518 | + wdata->accel = NULL; | |
| 519 | +} | |
| 520 | + | |
| 521 | +static const struct wiimod_ops wiimod_accel = { | |
| 522 | + .flags = 0, | |
| 523 | + .arg = 0, | |
| 524 | + .probe = wiimod_accel_probe, | |
| 525 | + .remove = wiimod_accel_remove, | |
| 526 | + .in_accel = wiimod_accel_in_accel, | |
| 527 | +}; | |
| 528 | + | |
| 529 | +/* | |
| 530 | + * IR Cam | |
| 531 | + * Up to 4 IR sources can be tracked by a normal Wii Remote. The IR cam needs | |
| 532 | + * to be initialized with a fairly complex procedure and consumes a lot of | |
| 533 | + * power. Therefore, as long as no application uses the IR input device, it is | |
| 534 | + * kept offline. | |
| 535 | + * Nearly no other device than the normal Wii Remotes supports the IR cam so | |
| 536 | + * you can disable this module for these devices. | |
| 537 | + */ | |
| 538 | + | |
| 539 | +static void wiimod_ir_in_ir(struct wiimote_data *wdata, const __u8 *ir, | |
| 540 | + bool packed, unsigned int id) | |
| 541 | +{ | |
| 542 | + __u16 x, y; | |
| 543 | + __u8 xid, yid; | |
| 544 | + bool sync = false; | |
| 545 | + | |
| 546 | + if (!(wdata->state.flags & WIIPROTO_FLAGS_IR)) | |
| 547 | + return; | |
| 548 | + | |
| 549 | + switch (id) { | |
| 550 | + case 0: | |
| 551 | + xid = ABS_HAT0X; | |
| 552 | + yid = ABS_HAT0Y; | |
| 553 | + break; | |
| 554 | + case 1: | |
| 555 | + xid = ABS_HAT1X; | |
| 556 | + yid = ABS_HAT1Y; | |
| 557 | + break; | |
| 558 | + case 2: | |
| 559 | + xid = ABS_HAT2X; | |
| 560 | + yid = ABS_HAT2Y; | |
| 561 | + break; | |
| 562 | + case 3: | |
| 563 | + xid = ABS_HAT3X; | |
| 564 | + yid = ABS_HAT3Y; | |
| 565 | + sync = true; | |
| 566 | + break; | |
| 567 | + default: | |
| 568 | + return; | |
| 569 | + } | |
| 570 | + | |
| 571 | + /* | |
| 572 | + * Basic IR data is encoded into 3 bytes. The first two bytes are the | |
| 573 | + * lower 8 bit of the X/Y data, the 3rd byte contains the upper 2 bits | |
| 574 | + * of both. | |
| 575 | + * If data is packed, then the 3rd byte is put first and slightly | |
| 576 | + * reordered. This allows to interleave packed and non-packed data to | |
| 577 | + * have two IR sets in 5 bytes instead of 6. | |
| 578 | + * The resulting 10bit X/Y values are passed to the ABS_HAT? input dev. | |
| 579 | + */ | |
| 580 | + | |
| 581 | + if (packed) { | |
| 582 | + x = ir[1] | ((ir[0] & 0x03) << 8); | |
| 583 | + y = ir[2] | ((ir[0] & 0x0c) << 6); | |
| 584 | + } else { | |
| 585 | + x = ir[0] | ((ir[2] & 0x30) << 4); | |
| 586 | + y = ir[1] | ((ir[2] & 0xc0) << 2); | |
| 587 | + } | |
| 588 | + | |
| 589 | + input_report_abs(wdata->ir, xid, x); | |
| 590 | + input_report_abs(wdata->ir, yid, y); | |
| 591 | + | |
| 592 | + if (sync) | |
| 593 | + input_sync(wdata->ir); | |
| 594 | +} | |
| 595 | + | |
| 596 | +static int wiimod_ir_change(struct wiimote_data *wdata, __u16 mode) | |
| 597 | +{ | |
| 598 | + int ret; | |
| 599 | + unsigned long flags; | |
| 600 | + __u8 format = 0; | |
| 601 | + static const __u8 data_enable[] = { 0x01 }; | |
| 602 | + static const __u8 data_sens1[] = { 0x02, 0x00, 0x00, 0x71, 0x01, | |
| 603 | + 0x00, 0xaa, 0x00, 0x64 }; | |
| 604 | + static const __u8 data_sens2[] = { 0x63, 0x03 }; | |
| 605 | + static const __u8 data_fin[] = { 0x08 }; | |
| 606 | + | |
| 607 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 608 | + | |
| 609 | + if (mode == (wdata->state.flags & WIIPROTO_FLAGS_IR)) { | |
| 610 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 611 | + return 0; | |
| 612 | + } | |
| 613 | + | |
| 614 | + if (mode == 0) { | |
| 615 | + wdata->state.flags &= ~WIIPROTO_FLAGS_IR; | |
| 616 | + wiiproto_req_ir1(wdata, 0); | |
| 617 | + wiiproto_req_ir2(wdata, 0); | |
| 618 | + wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | |
| 619 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 620 | + return 0; | |
| 621 | + } | |
| 622 | + | |
| 623 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 624 | + | |
| 625 | + ret = wiimote_cmd_acquire(wdata); | |
| 626 | + if (ret) | |
| 627 | + return ret; | |
| 628 | + | |
| 629 | + /* send PIXEL CLOCK ENABLE cmd first */ | |
| 630 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 631 | + wiimote_cmd_set(wdata, WIIPROTO_REQ_IR1, 0); | |
| 632 | + wiiproto_req_ir1(wdata, 0x06); | |
| 633 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 634 | + | |
| 635 | + ret = wiimote_cmd_wait(wdata); | |
| 636 | + if (ret) | |
| 637 | + goto unlock; | |
| 638 | + if (wdata->state.cmd_err) { | |
| 639 | + ret = -EIO; | |
| 640 | + goto unlock; | |
| 641 | + } | |
| 642 | + | |
| 643 | + /* enable IR LOGIC */ | |
| 644 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 645 | + wiimote_cmd_set(wdata, WIIPROTO_REQ_IR2, 0); | |
| 646 | + wiiproto_req_ir2(wdata, 0x06); | |
| 647 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 648 | + | |
| 649 | + ret = wiimote_cmd_wait(wdata); | |
| 650 | + if (ret) | |
| 651 | + goto unlock; | |
| 652 | + if (wdata->state.cmd_err) { | |
| 653 | + ret = -EIO; | |
| 654 | + goto unlock; | |
| 655 | + } | |
| 656 | + | |
| 657 | + /* enable IR cam but do not make it send data, yet */ | |
| 658 | + ret = wiimote_cmd_write(wdata, 0xb00030, data_enable, | |
| 659 | + sizeof(data_enable)); | |
| 660 | + if (ret) | |
| 661 | + goto unlock; | |
| 662 | + | |
| 663 | + /* write first sensitivity block */ | |
| 664 | + ret = wiimote_cmd_write(wdata, 0xb00000, data_sens1, | |
| 665 | + sizeof(data_sens1)); | |
| 666 | + if (ret) | |
| 667 | + goto unlock; | |
| 668 | + | |
| 669 | + /* write second sensitivity block */ | |
| 670 | + ret = wiimote_cmd_write(wdata, 0xb0001a, data_sens2, | |
| 671 | + sizeof(data_sens2)); | |
| 672 | + if (ret) | |
| 673 | + goto unlock; | |
| 674 | + | |
| 675 | + /* put IR cam into desired state */ | |
| 676 | + switch (mode) { | |
| 677 | + case WIIPROTO_FLAG_IR_FULL: | |
| 678 | + format = 5; | |
| 679 | + break; | |
| 680 | + case WIIPROTO_FLAG_IR_EXT: | |
| 681 | + format = 3; | |
| 682 | + break; | |
| 683 | + case WIIPROTO_FLAG_IR_BASIC: | |
| 684 | + format = 1; | |
| 685 | + break; | |
| 686 | + } | |
| 687 | + ret = wiimote_cmd_write(wdata, 0xb00033, &format, sizeof(format)); | |
| 688 | + if (ret) | |
| 689 | + goto unlock; | |
| 690 | + | |
| 691 | + /* make IR cam send data */ | |
| 692 | + ret = wiimote_cmd_write(wdata, 0xb00030, data_fin, sizeof(data_fin)); | |
| 693 | + if (ret) | |
| 694 | + goto unlock; | |
| 695 | + | |
| 696 | + /* request new DRM mode compatible to IR mode */ | |
| 697 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 698 | + wdata->state.flags &= ~WIIPROTO_FLAGS_IR; | |
| 699 | + wdata->state.flags |= mode & WIIPROTO_FLAGS_IR; | |
| 700 | + wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | |
| 701 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 702 | + | |
| 703 | +unlock: | |
| 704 | + wiimote_cmd_release(wdata); | |
| 705 | + return ret; | |
| 706 | +} | |
| 707 | + | |
| 708 | +static int wiimod_ir_open(struct input_dev *dev) | |
| 709 | +{ | |
| 710 | + struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 711 | + | |
| 712 | + return wiimod_ir_change(wdata, WIIPROTO_FLAG_IR_BASIC); | |
| 713 | +} | |
| 714 | + | |
| 715 | +static void wiimod_ir_close(struct input_dev *dev) | |
| 716 | +{ | |
| 717 | + struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 718 | + | |
| 719 | + wiimod_ir_change(wdata, 0); | |
| 720 | +} | |
| 721 | + | |
| 722 | +static int wiimod_ir_probe(const struct wiimod_ops *ops, | |
| 723 | + struct wiimote_data *wdata) | |
| 724 | +{ | |
| 725 | + int ret; | |
| 726 | + | |
| 727 | + wdata->ir = input_allocate_device(); | |
| 728 | + if (!wdata->ir) | |
| 729 | + return -ENOMEM; | |
| 730 | + | |
| 731 | + input_set_drvdata(wdata->ir, wdata); | |
| 732 | + wdata->ir->open = wiimod_ir_open; | |
| 733 | + wdata->ir->close = wiimod_ir_close; | |
| 734 | + wdata->ir->dev.parent = &wdata->hdev->dev; | |
| 735 | + wdata->ir->id.bustype = wdata->hdev->bus; | |
| 736 | + wdata->ir->id.vendor = wdata->hdev->vendor; | |
| 737 | + wdata->ir->id.product = wdata->hdev->product; | |
| 738 | + wdata->ir->id.version = wdata->hdev->version; | |
| 739 | + wdata->ir->name = WIIMOTE_NAME " IR"; | |
| 740 | + | |
| 741 | + set_bit(EV_ABS, wdata->ir->evbit); | |
| 742 | + set_bit(ABS_HAT0X, wdata->ir->absbit); | |
| 743 | + set_bit(ABS_HAT0Y, wdata->ir->absbit); | |
| 744 | + set_bit(ABS_HAT1X, wdata->ir->absbit); | |
| 745 | + set_bit(ABS_HAT1Y, wdata->ir->absbit); | |
| 746 | + set_bit(ABS_HAT2X, wdata->ir->absbit); | |
| 747 | + set_bit(ABS_HAT2Y, wdata->ir->absbit); | |
| 748 | + set_bit(ABS_HAT3X, wdata->ir->absbit); | |
| 749 | + set_bit(ABS_HAT3Y, wdata->ir->absbit); | |
| 750 | + input_set_abs_params(wdata->ir, ABS_HAT0X, 0, 1023, 2, 4); | |
| 751 | + input_set_abs_params(wdata->ir, ABS_HAT0Y, 0, 767, 2, 4); | |
| 752 | + input_set_abs_params(wdata->ir, ABS_HAT1X, 0, 1023, 2, 4); | |
| 753 | + input_set_abs_params(wdata->ir, ABS_HAT1Y, 0, 767, 2, 4); | |
| 754 | + input_set_abs_params(wdata->ir, ABS_HAT2X, 0, 1023, 2, 4); | |
| 755 | + input_set_abs_params(wdata->ir, ABS_HAT2Y, 0, 767, 2, 4); | |
| 756 | + input_set_abs_params(wdata->ir, ABS_HAT3X, 0, 1023, 2, 4); | |
| 757 | + input_set_abs_params(wdata->ir, ABS_HAT3Y, 0, 767, 2, 4); | |
| 758 | + | |
| 759 | + ret = input_register_device(wdata->ir); | |
| 760 | + if (ret) { | |
| 761 | + hid_err(wdata->hdev, "cannot register input device\n"); | |
| 762 | + goto err_free; | |
| 763 | + } | |
| 764 | + | |
| 765 | + return 0; | |
| 766 | + | |
| 767 | +err_free: | |
| 768 | + input_free_device(wdata->ir); | |
| 769 | + wdata->ir = NULL; | |
| 770 | + return ret; | |
| 771 | +} | |
| 772 | + | |
| 773 | +static void wiimod_ir_remove(const struct wiimod_ops *ops, | |
| 774 | + struct wiimote_data *wdata) | |
| 775 | +{ | |
| 776 | + if (!wdata->ir) | |
| 777 | + return; | |
| 778 | + | |
| 779 | + input_unregister_device(wdata->ir); | |
| 780 | + wdata->ir = NULL; | |
| 781 | +} | |
| 782 | + | |
| 783 | +static const struct wiimod_ops wiimod_ir = { | |
| 784 | + .flags = 0, | |
| 785 | + .arg = 0, | |
| 786 | + .probe = wiimod_ir_probe, | |
| 787 | + .remove = wiimod_ir_remove, | |
| 788 | + .in_ir = wiimod_ir_in_ir, | |
| 789 | +}; | |
| 790 | + | |
| 791 | +/* | |
| 792 | + * Nunchuk Extension | |
| 793 | + * The Nintendo Wii Nunchuk was the first official extension published by | |
| 794 | + * Nintendo. It provides two additional keys and a separate accelerometer. It | |
| 795 | + * can be hotplugged to standard Wii Remotes. | |
| 796 | + */ | |
| 797 | + | |
| 798 | +enum wiimod_nunchuk_keys { | |
| 799 | + WIIMOD_NUNCHUK_KEY_C, | |
| 800 | + WIIMOD_NUNCHUK_KEY_Z, | |
| 801 | + WIIMOD_NUNCHUK_KEY_NUM, | |
| 802 | +}; | |
| 803 | + | |
| 804 | +static const __u16 wiimod_nunchuk_map[] = { | |
| 805 | + BTN_C, /* WIIMOD_NUNCHUK_KEY_C */ | |
| 806 | + BTN_Z, /* WIIMOD_NUNCHUK_KEY_Z */ | |
| 807 | +}; | |
| 808 | + | |
| 809 | +static void wiimod_nunchuk_in_ext(struct wiimote_data *wdata, const __u8 *ext) | |
| 810 | +{ | |
| 811 | + __s16 x, y, z, bx, by; | |
| 812 | + | |
| 813 | + /* Byte | 8 7 | 6 5 | 4 3 | 2 | 1 | | |
| 814 | + * -----+----------+---------+---------+----+-----+ | |
| 815 | + * 1 | Button X <7:0> | | |
| 816 | + * 2 | Button Y <7:0> | | |
| 817 | + * -----+----------+---------+---------+----+-----+ | |
| 818 | + * 3 | Speed X <9:2> | | |
| 819 | + * 4 | Speed Y <9:2> | | |
| 820 | + * 5 | Speed Z <9:2> | | |
| 821 | + * -----+----------+---------+---------+----+-----+ | |
| 822 | + * 6 | Z <1:0> | Y <1:0> | X <1:0> | BC | BZ | | |
| 823 | + * -----+----------+---------+---------+----+-----+ | |
| 824 | + * Button X/Y is the analog stick. Speed X, Y and Z are the | |
| 825 | + * accelerometer data in the same format as the wiimote's accelerometer. | |
| 826 | + * The 6th byte contains the LSBs of the accelerometer data. | |
| 827 | + * BC and BZ are the C and Z buttons: 0 means pressed | |
| 828 | + * | |
| 829 | + * If reported interleaved with motionp, then the layout changes. The | |
| 830 | + * 5th and 6th byte changes to: | |
| 831 | + * -----+-----------------------------------+-----+ | |
| 832 | + * 5 | Speed Z <9:3> | EXT | | |
| 833 | + * -----+--------+-----+-----+----+----+----+-----+ | |
| 834 | + * 6 |Z <2:1> |Y <1>|X <1>| BC | BZ | 0 | 0 | | |
| 835 | + * -----+--------+-----+-----+----+----+----+-----+ | |
| 836 | + * All three accelerometer values lose their LSB. The other data is | |
| 837 | + * still available but slightly moved. | |
| 838 | + * | |
| 839 | + * Center data for button values is 128. Center value for accelerometer | |
| 840 | + * values it 512 / 0x200 | |
| 841 | + */ | |
| 842 | + | |
| 843 | + bx = ext[0]; | |
| 844 | + by = ext[1]; | |
| 845 | + bx -= 128; | |
| 846 | + by -= 128; | |
| 847 | + | |
| 848 | + x = ext[2] << 2; | |
| 849 | + y = ext[3] << 2; | |
| 850 | + z = ext[4] << 2; | |
| 851 | + | |
| 852 | + if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) { | |
| 853 | + x |= (ext[5] >> 3) & 0x02; | |
| 854 | + y |= (ext[5] >> 4) & 0x02; | |
| 855 | + z &= ~0x4; | |
| 856 | + z |= (ext[5] >> 5) & 0x06; | |
| 857 | + } else { | |
| 858 | + x |= (ext[5] >> 2) & 0x03; | |
| 859 | + y |= (ext[5] >> 4) & 0x03; | |
| 860 | + z |= (ext[5] >> 6) & 0x03; | |
| 861 | + } | |
| 862 | + | |
| 863 | + x -= 0x200; | |
| 864 | + y -= 0x200; | |
| 865 | + z -= 0x200; | |
| 866 | + | |
| 867 | + input_report_abs(wdata->extension.input, ABS_HAT0X, bx); | |
| 868 | + input_report_abs(wdata->extension.input, ABS_HAT0Y, by); | |
| 869 | + | |
| 870 | + input_report_abs(wdata->extension.input, ABS_RX, x); | |
| 871 | + input_report_abs(wdata->extension.input, ABS_RY, y); | |
| 872 | + input_report_abs(wdata->extension.input, ABS_RZ, z); | |
| 873 | + | |
| 874 | + if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) { | |
| 875 | + input_report_key(wdata->extension.input, | |
| 876 | + wiimod_nunchuk_map[WIIMOD_NUNCHUK_KEY_Z], | |
| 877 | + !(ext[5] & 0x04)); | |
| 878 | + input_report_key(wdata->extension.input, | |
| 879 | + wiimod_nunchuk_map[WIIMOD_NUNCHUK_KEY_C], | |
| 880 | + !(ext[5] & 0x08)); | |
| 881 | + } else { | |
| 882 | + input_report_key(wdata->extension.input, | |
| 883 | + wiimod_nunchuk_map[WIIMOD_NUNCHUK_KEY_Z], | |
| 884 | + !(ext[5] & 0x01)); | |
| 885 | + input_report_key(wdata->extension.input, | |
| 886 | + wiimod_nunchuk_map[WIIMOD_NUNCHUK_KEY_C], | |
| 887 | + !(ext[5] & 0x02)); | |
| 888 | + } | |
| 889 | + | |
| 890 | + input_sync(wdata->extension.input); | |
| 891 | +} | |
| 892 | + | |
| 893 | +static int wiimod_nunchuk_open(struct input_dev *dev) | |
| 894 | +{ | |
| 895 | + struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 896 | + unsigned long flags; | |
| 897 | + | |
| 898 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 899 | + wdata->state.flags |= WIIPROTO_FLAG_EXT_USED; | |
| 900 | + wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | |
| 901 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 902 | + | |
| 903 | + return 0; | |
| 904 | +} | |
| 905 | + | |
| 906 | +static void wiimod_nunchuk_close(struct input_dev *dev) | |
| 907 | +{ | |
| 908 | + struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 909 | + unsigned long flags; | |
| 910 | + | |
| 911 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 912 | + wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED; | |
| 913 | + wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | |
| 914 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 915 | +} | |
| 916 | + | |
| 917 | +static int wiimod_nunchuk_probe(const struct wiimod_ops *ops, | |
| 918 | + struct wiimote_data *wdata) | |
| 919 | +{ | |
| 920 | + int ret, i; | |
| 921 | + | |
| 922 | + wdata->extension.input = input_allocate_device(); | |
| 923 | + if (!wdata->extension.input) | |
| 924 | + return -ENOMEM; | |
| 925 | + | |
| 926 | + input_set_drvdata(wdata->extension.input, wdata); | |
| 927 | + wdata->extension.input->open = wiimod_nunchuk_open; | |
| 928 | + wdata->extension.input->close = wiimod_nunchuk_close; | |
| 929 | + wdata->extension.input->dev.parent = &wdata->hdev->dev; | |
| 930 | + wdata->extension.input->id.bustype = wdata->hdev->bus; | |
| 931 | + wdata->extension.input->id.vendor = wdata->hdev->vendor; | |
| 932 | + wdata->extension.input->id.product = wdata->hdev->product; | |
| 933 | + wdata->extension.input->id.version = wdata->hdev->version; | |
| 934 | + wdata->extension.input->name = WIIMOTE_NAME " Nunchuk"; | |
| 935 | + | |
| 936 | + set_bit(EV_KEY, wdata->extension.input->evbit); | |
| 937 | + for (i = 0; i < WIIMOD_NUNCHUK_KEY_NUM; ++i) | |
| 938 | + set_bit(wiimod_nunchuk_map[i], | |
| 939 | + wdata->extension.input->keybit); | |
| 940 | + | |
| 941 | + set_bit(EV_ABS, wdata->extension.input->evbit); | |
| 942 | + set_bit(ABS_HAT0X, wdata->extension.input->absbit); | |
| 943 | + set_bit(ABS_HAT0Y, wdata->extension.input->absbit); | |
| 944 | + input_set_abs_params(wdata->extension.input, | |
| 945 | + ABS_HAT0X, -120, 120, 2, 4); | |
| 946 | + input_set_abs_params(wdata->extension.input, | |
| 947 | + ABS_HAT0Y, -120, 120, 2, 4); | |
| 948 | + set_bit(ABS_RX, wdata->extension.input->absbit); | |
| 949 | + set_bit(ABS_RY, wdata->extension.input->absbit); | |
| 950 | + set_bit(ABS_RZ, wdata->extension.input->absbit); | |
| 951 | + input_set_abs_params(wdata->extension.input, | |
| 952 | + ABS_RX, -500, 500, 2, 4); | |
| 953 | + input_set_abs_params(wdata->extension.input, | |
| 954 | + ABS_RY, -500, 500, 2, 4); | |
| 955 | + input_set_abs_params(wdata->extension.input, | |
| 956 | + ABS_RZ, -500, 500, 2, 4); | |
| 957 | + | |
| 958 | + ret = input_register_device(wdata->extension.input); | |
| 959 | + if (ret) | |
| 960 | + goto err_free; | |
| 961 | + | |
| 962 | + return 0; | |
| 963 | + | |
| 964 | +err_free: | |
| 965 | + input_free_device(wdata->extension.input); | |
| 966 | + wdata->extension.input = NULL; | |
| 967 | + return ret; | |
| 968 | +} | |
| 969 | + | |
| 970 | +static void wiimod_nunchuk_remove(const struct wiimod_ops *ops, | |
| 971 | + struct wiimote_data *wdata) | |
| 972 | +{ | |
| 973 | + if (!wdata->extension.input) | |
| 974 | + return; | |
| 975 | + | |
| 976 | + input_unregister_device(wdata->extension.input); | |
| 977 | + wdata->extension.input = NULL; | |
| 978 | +} | |
| 979 | + | |
| 980 | +static const struct wiimod_ops wiimod_nunchuk = { | |
| 981 | + .flags = 0, | |
| 982 | + .arg = 0, | |
| 983 | + .probe = wiimod_nunchuk_probe, | |
| 984 | + .remove = wiimod_nunchuk_remove, | |
| 985 | + .in_ext = wiimod_nunchuk_in_ext, | |
| 986 | +}; | |
| 987 | + | |
| 988 | +/* | |
| 989 | + * Classic Controller | |
| 990 | + * Another official extension from Nintendo. It provides a classic | |
| 991 | + * gamecube-like controller that can be hotplugged on the Wii Remote. | |
| 992 | + * It has several hardware buttons and switches that are all reported via | |
| 993 | + * a normal extension device. | |
| 994 | + */ | |
| 995 | + | |
| 996 | +enum wiimod_classic_keys { | |
| 997 | + WIIMOD_CLASSIC_KEY_A, | |
| 998 | + WIIMOD_CLASSIC_KEY_B, | |
| 999 | + WIIMOD_CLASSIC_KEY_X, | |
| 1000 | + WIIMOD_CLASSIC_KEY_Y, | |
| 1001 | + WIIMOD_CLASSIC_KEY_ZL, | |
| 1002 | + WIIMOD_CLASSIC_KEY_ZR, | |
| 1003 | + WIIMOD_CLASSIC_KEY_PLUS, | |
| 1004 | + WIIMOD_CLASSIC_KEY_MINUS, | |
| 1005 | + WIIMOD_CLASSIC_KEY_HOME, | |
| 1006 | + WIIMOD_CLASSIC_KEY_LEFT, | |
| 1007 | + WIIMOD_CLASSIC_KEY_RIGHT, | |
| 1008 | + WIIMOD_CLASSIC_KEY_UP, | |
| 1009 | + WIIMOD_CLASSIC_KEY_DOWN, | |
| 1010 | + WIIMOD_CLASSIC_KEY_LT, | |
| 1011 | + WIIMOD_CLASSIC_KEY_RT, | |
| 1012 | + WIIMOD_CLASSIC_KEY_NUM, | |
| 1013 | +}; | |
| 1014 | + | |
| 1015 | +static const __u16 wiimod_classic_map[] = { | |
| 1016 | + BTN_A, /* WIIMOD_CLASSIC_KEY_A */ | |
| 1017 | + BTN_B, /* WIIMOD_CLASSIC_KEY_B */ | |
| 1018 | + BTN_X, /* WIIMOD_CLASSIC_KEY_X */ | |
| 1019 | + BTN_Y, /* WIIMOD_CLASSIC_KEY_Y */ | |
| 1020 | + BTN_TL2, /* WIIMOD_CLASSIC_KEY_ZL */ | |
| 1021 | + BTN_TR2, /* WIIMOD_CLASSIC_KEY_ZR */ | |
| 1022 | + KEY_NEXT, /* WIIMOD_CLASSIC_KEY_PLUS */ | |
| 1023 | + KEY_PREVIOUS, /* WIIMOD_CLASSIC_KEY_MINUS */ | |
| 1024 | + BTN_MODE, /* WIIMOD_CLASSIC_KEY_HOME */ | |
| 1025 | + KEY_LEFT, /* WIIMOD_CLASSIC_KEY_LEFT */ | |
| 1026 | + KEY_RIGHT, /* WIIMOD_CLASSIC_KEY_RIGHT */ | |
| 1027 | + KEY_UP, /* WIIMOD_CLASSIC_KEY_UP */ | |
| 1028 | + KEY_DOWN, /* WIIMOD_CLASSIC_KEY_DOWN */ | |
| 1029 | + BTN_TL, /* WIIMOD_CLASSIC_KEY_LT */ | |
| 1030 | + BTN_TR, /* WIIMOD_CLASSIC_KEY_RT */ | |
| 1031 | +}; | |
| 1032 | + | |
| 1033 | +static void wiimod_classic_in_ext(struct wiimote_data *wdata, const __u8 *ext) | |
| 1034 | +{ | |
| 1035 | + __s8 rx, ry, lx, ly, lt, rt; | |
| 1036 | + | |
| 1037 | + /* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | | |
| 1038 | + * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 1039 | + * 1 | RX <5:4> | LX <5:0> | | |
| 1040 | + * 2 | RX <3:2> | LY <5:0> | | |
| 1041 | + * -----+-----+-----+-----+-----------------------------+ | |
| 1042 | + * 3 |RX<1>| LT <5:4> | RY <5:1> | | |
| 1043 | + * -----+-----+-----------+-----------------------------+ | |
| 1044 | + * 4 | LT <3:1> | RT <5:1> | | |
| 1045 | + * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 1046 | + * 5 | BDR | BDD | BLT | B- | BH | B+ | BRT | 1 | | |
| 1047 | + * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 1048 | + * 6 | BZL | BB | BY | BA | BX | BZR | BDL | BDU | | |
| 1049 | + * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 1050 | + * All buttons are 0 if pressed | |
| 1051 | + * RX and RY are right analog stick | |
| 1052 | + * LX and LY are left analog stick | |
| 1053 | + * LT is left trigger, RT is right trigger | |
| 1054 | + * BLT is 0 if left trigger is fully pressed | |
| 1055 | + * BRT is 0 if right trigger is fully pressed | |
| 1056 | + * BDR, BDD, BDL, BDU form the D-Pad with right, down, left, up buttons | |
| 1057 | + * BZL is left Z button and BZR is right Z button | |
| 1058 | + * B-, BH, B+ are +, HOME and - buttons | |
| 1059 | + * BB, BY, BA, BX are A, B, X, Y buttons | |
| 1060 | + * LSB of RX, RY, LT, and RT are not transmitted and always 0. | |
| 1061 | + * | |
| 1062 | + * With motionp enabled it changes slightly to this: | |
| 1063 | + * Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | | |
| 1064 | + * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 1065 | + * 1 | RX <5:4> | LX <5:1> | BDU | | |
| 1066 | + * 2 | RX <3:2> | LY <5:1> | BDL | | |
| 1067 | + * -----+-----+-----+-----+-----------------------+-----+ | |
| 1068 | + * 3 |RX<1>| LT <5:4> | RY <5:1> | | |
| 1069 | + * -----+-----+-----------+-----------------------------+ | |
| 1070 | + * 4 | LT <3:1> | RT <5:1> | | |
| 1071 | + * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 1072 | + * 5 | BDR | BDD | BLT | B- | BH | B+ | BRT | EXT | | |
| 1073 | + * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 1074 | + * 6 | BZL | BB | BY | BA | BX | BZR | 0 | 0 | | |
| 1075 | + * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 1076 | + * Only the LSBs of LX and LY are lost. BDU and BDL are moved, the rest | |
| 1077 | + * is the same as before. | |
| 1078 | + */ | |
| 1079 | + | |
| 1080 | + if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) { | |
| 1081 | + lx = ext[0] & 0x3e; | |
| 1082 | + ly = ext[1] & 0x3e; | |
| 1083 | + } else { | |
| 1084 | + lx = ext[0] & 0x3f; | |
| 1085 | + ly = ext[1] & 0x3f; | |
| 1086 | + } | |
| 1087 | + | |
| 1088 | + rx = (ext[0] >> 3) & 0x18; | |
| 1089 | + rx |= (ext[1] >> 5) & 0x06; | |
| 1090 | + rx |= (ext[2] >> 7) & 0x01; | |
| 1091 | + ry = ext[2] & 0x1f; | |
| 1092 | + | |
| 1093 | + rt = ext[3] & 0x1f; | |
| 1094 | + lt = (ext[2] >> 2) & 0x18; | |
| 1095 | + lt |= (ext[3] >> 5) & 0x07; | |
| 1096 | + | |
| 1097 | + rx <<= 1; | |
| 1098 | + ry <<= 1; | |
| 1099 | + rt <<= 1; | |
| 1100 | + lt <<= 1; | |
| 1101 | + | |
| 1102 | + input_report_abs(wdata->extension.input, ABS_HAT1X, lx - 0x20); | |
| 1103 | + input_report_abs(wdata->extension.input, ABS_HAT1Y, ly - 0x20); | |
| 1104 | + input_report_abs(wdata->extension.input, ABS_HAT2X, rx - 0x20); | |
| 1105 | + input_report_abs(wdata->extension.input, ABS_HAT2Y, ry - 0x20); | |
| 1106 | + input_report_abs(wdata->extension.input, ABS_HAT3X, rt); | |
| 1107 | + input_report_abs(wdata->extension.input, ABS_HAT3Y, lt); | |
| 1108 | + | |
| 1109 | + input_report_key(wdata->extension.input, | |
| 1110 | + wiimod_classic_map[WIIMOD_CLASSIC_KEY_RIGHT], | |
| 1111 | + !(ext[4] & 0x80)); | |
| 1112 | + input_report_key(wdata->extension.input, | |
| 1113 | + wiimod_classic_map[WIIMOD_CLASSIC_KEY_DOWN], | |
| 1114 | + !(ext[4] & 0x40)); | |
| 1115 | + input_report_key(wdata->extension.input, | |
| 1116 | + wiimod_classic_map[WIIMOD_CLASSIC_KEY_LT], | |
| 1117 | + !(ext[4] & 0x20)); | |
| 1118 | + input_report_key(wdata->extension.input, | |
| 1119 | + wiimod_classic_map[WIIMOD_CLASSIC_KEY_MINUS], | |
| 1120 | + !(ext[4] & 0x10)); | |
| 1121 | + input_report_key(wdata->extension.input, | |
| 1122 | + wiimod_classic_map[WIIMOD_CLASSIC_KEY_HOME], | |
| 1123 | + !(ext[4] & 0x08)); | |
| 1124 | + input_report_key(wdata->extension.input, | |
| 1125 | + wiimod_classic_map[WIIMOD_CLASSIC_KEY_PLUS], | |
| 1126 | + !(ext[4] & 0x04)); | |
| 1127 | + input_report_key(wdata->extension.input, | |
| 1128 | + wiimod_classic_map[WIIMOD_CLASSIC_KEY_RT], | |
| 1129 | + !(ext[4] & 0x02)); | |
| 1130 | + input_report_key(wdata->extension.input, | |
| 1131 | + wiimod_classic_map[WIIMOD_CLASSIC_KEY_ZL], | |
| 1132 | + !(ext[5] & 0x80)); | |
| 1133 | + input_report_key(wdata->extension.input, | |
| 1134 | + wiimod_classic_map[WIIMOD_CLASSIC_KEY_B], | |
| 1135 | + !(ext[5] & 0x40)); | |
| 1136 | + input_report_key(wdata->extension.input, | |
| 1137 | + wiimod_classic_map[WIIMOD_CLASSIC_KEY_Y], | |
| 1138 | + !(ext[5] & 0x20)); | |
| 1139 | + input_report_key(wdata->extension.input, | |
| 1140 | + wiimod_classic_map[WIIMOD_CLASSIC_KEY_A], | |
| 1141 | + !(ext[5] & 0x10)); | |
| 1142 | + input_report_key(wdata->extension.input, | |
| 1143 | + wiimod_classic_map[WIIMOD_CLASSIC_KEY_X], | |
| 1144 | + !(ext[5] & 0x08)); | |
| 1145 | + input_report_key(wdata->extension.input, | |
| 1146 | + wiimod_classic_map[WIIMOD_CLASSIC_KEY_ZR], | |
| 1147 | + !(ext[5] & 0x04)); | |
| 1148 | + | |
| 1149 | + if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) { | |
| 1150 | + input_report_key(wdata->extension.input, | |
| 1151 | + wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT], | |
| 1152 | + !(ext[1] & 0x01)); | |
| 1153 | + input_report_key(wdata->extension.input, | |
| 1154 | + wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP], | |
| 1155 | + !(ext[0] & 0x01)); | |
| 1156 | + } else { | |
| 1157 | + input_report_key(wdata->extension.input, | |
| 1158 | + wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT], | |
| 1159 | + !(ext[5] & 0x02)); | |
| 1160 | + input_report_key(wdata->extension.input, | |
| 1161 | + wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP], | |
| 1162 | + !(ext[5] & 0x01)); | |
| 1163 | + } | |
| 1164 | + | |
| 1165 | + input_sync(wdata->extension.input); | |
| 1166 | +} | |
| 1167 | + | |
| 1168 | +static int wiimod_classic_open(struct input_dev *dev) | |
| 1169 | +{ | |
| 1170 | + struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 1171 | + unsigned long flags; | |
| 1172 | + | |
| 1173 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 1174 | + wdata->state.flags |= WIIPROTO_FLAG_EXT_USED; | |
| 1175 | + wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | |
| 1176 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 1177 | + | |
| 1178 | + return 0; | |
| 1179 | +} | |
| 1180 | + | |
| 1181 | +static void wiimod_classic_close(struct input_dev *dev) | |
| 1182 | +{ | |
| 1183 | + struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 1184 | + unsigned long flags; | |
| 1185 | + | |
| 1186 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 1187 | + wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED; | |
| 1188 | + wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | |
| 1189 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 1190 | +} | |
| 1191 | + | |
| 1192 | +static int wiimod_classic_probe(const struct wiimod_ops *ops, | |
| 1193 | + struct wiimote_data *wdata) | |
| 1194 | +{ | |
| 1195 | + int ret, i; | |
| 1196 | + | |
| 1197 | + wdata->extension.input = input_allocate_device(); | |
| 1198 | + if (!wdata->extension.input) | |
| 1199 | + return -ENOMEM; | |
| 1200 | + | |
| 1201 | + input_set_drvdata(wdata->extension.input, wdata); | |
| 1202 | + wdata->extension.input->open = wiimod_classic_open; | |
| 1203 | + wdata->extension.input->close = wiimod_classic_close; | |
| 1204 | + wdata->extension.input->dev.parent = &wdata->hdev->dev; | |
| 1205 | + wdata->extension.input->id.bustype = wdata->hdev->bus; | |
| 1206 | + wdata->extension.input->id.vendor = wdata->hdev->vendor; | |
| 1207 | + wdata->extension.input->id.product = wdata->hdev->product; | |
| 1208 | + wdata->extension.input->id.version = wdata->hdev->version; | |
| 1209 | + wdata->extension.input->name = WIIMOTE_NAME " Classic Controller"; | |
| 1210 | + | |
| 1211 | + set_bit(EV_KEY, wdata->extension.input->evbit); | |
| 1212 | + for (i = 0; i < WIIMOD_CLASSIC_KEY_NUM; ++i) | |
| 1213 | + set_bit(wiimod_classic_map[i], | |
| 1214 | + wdata->extension.input->keybit); | |
| 1215 | + | |
| 1216 | + set_bit(EV_ABS, wdata->extension.input->evbit); | |
| 1217 | + set_bit(ABS_HAT1X, wdata->extension.input->absbit); | |
| 1218 | + set_bit(ABS_HAT1Y, wdata->extension.input->absbit); | |
| 1219 | + set_bit(ABS_HAT2X, wdata->extension.input->absbit); | |
| 1220 | + set_bit(ABS_HAT2Y, wdata->extension.input->absbit); | |
| 1221 | + set_bit(ABS_HAT3X, wdata->extension.input->absbit); | |
| 1222 | + set_bit(ABS_HAT3Y, wdata->extension.input->absbit); | |
| 1223 | + input_set_abs_params(wdata->extension.input, | |
| 1224 | + ABS_HAT1X, -30, 30, 1, 1); | |
| 1225 | + input_set_abs_params(wdata->extension.input, | |
| 1226 | + ABS_HAT1Y, -30, 30, 1, 1); | |
| 1227 | + input_set_abs_params(wdata->extension.input, | |
| 1228 | + ABS_HAT2X, -30, 30, 1, 1); | |
| 1229 | + input_set_abs_params(wdata->extension.input, | |
| 1230 | + ABS_HAT2Y, -30, 30, 1, 1); | |
| 1231 | + input_set_abs_params(wdata->extension.input, | |
| 1232 | + ABS_HAT3X, -30, 30, 1, 1); | |
| 1233 | + input_set_abs_params(wdata->extension.input, | |
| 1234 | + ABS_HAT3Y, -30, 30, 1, 1); | |
| 1235 | + | |
| 1236 | + ret = input_register_device(wdata->extension.input); | |
| 1237 | + if (ret) | |
| 1238 | + goto err_free; | |
| 1239 | + | |
| 1240 | + return 0; | |
| 1241 | + | |
| 1242 | +err_free: | |
| 1243 | + input_free_device(wdata->extension.input); | |
| 1244 | + wdata->extension.input = NULL; | |
| 1245 | + return ret; | |
| 1246 | +} | |
| 1247 | + | |
| 1248 | +static void wiimod_classic_remove(const struct wiimod_ops *ops, | |
| 1249 | + struct wiimote_data *wdata) | |
| 1250 | +{ | |
| 1251 | + if (!wdata->extension.input) | |
| 1252 | + return; | |
| 1253 | + | |
| 1254 | + input_unregister_device(wdata->extension.input); | |
| 1255 | + wdata->extension.input = NULL; | |
| 1256 | +} | |
| 1257 | + | |
| 1258 | +static const struct wiimod_ops wiimod_classic = { | |
| 1259 | + .flags = 0, | |
| 1260 | + .arg = 0, | |
| 1261 | + .probe = wiimod_classic_probe, | |
| 1262 | + .remove = wiimod_classic_remove, | |
| 1263 | + .in_ext = wiimod_classic_in_ext, | |
| 1264 | +}; | |
| 1265 | + | |
| 1266 | +/* | |
| 1267 | + * Balance Board Extension | |
| 1268 | + * The Nintendo Wii Balance Board provides four hardware weight sensor plus a | |
| 1269 | + * single push button. No other peripherals are available. However, the | |
| 1270 | + * balance-board data is sent via a standard Wii Remote extension. All other | |
| 1271 | + * data for non-present hardware is zeroed out. | |
| 1272 | + * Some 3rd party devices react allergic if we try to access normal Wii Remote | |
| 1273 | + * hardware, so this extension module should be the only module that is loaded | |
| 1274 | + * on balance boards. | |
| 1275 | + * The balance board needs 8 bytes extension data instead of basic 6 bytes so | |
| 1276 | + * it needs the WIIMOD_FLAG_EXT8 flag. | |
| 1277 | + */ | |
| 1278 | + | |
| 1279 | +static void wiimod_bboard_in_keys(struct wiimote_data *wdata, const __u8 *keys) | |
| 1280 | +{ | |
| 1281 | + input_report_key(wdata->extension.input, BTN_A, | |
| 1282 | + !!(keys[1] & 0x08)); | |
| 1283 | + input_sync(wdata->extension.input); | |
| 1284 | +} | |
| 1285 | + | |
| 1286 | +static void wiimod_bboard_in_ext(struct wiimote_data *wdata, | |
| 1287 | + const __u8 *ext) | |
| 1288 | +{ | |
| 1289 | + __s32 val[4], tmp, div; | |
| 1290 | + unsigned int i; | |
| 1291 | + struct wiimote_state *s = &wdata->state; | |
| 1292 | + | |
| 1293 | + /* | |
| 1294 | + * Balance board data layout: | |
| 1295 | + * | |
| 1296 | + * Byte | 8 7 6 5 4 3 2 1 | | |
| 1297 | + * -----+--------------------------+ | |
| 1298 | + * 1 | Top Right <15:8> | | |
| 1299 | + * 2 | Top Right <7:0> | | |
| 1300 | + * -----+--------------------------+ | |
| 1301 | + * 3 | Bottom Right <15:8> | | |
| 1302 | + * 4 | Bottom Right <7:0> | | |
| 1303 | + * -----+--------------------------+ | |
| 1304 | + * 5 | Top Left <15:8> | | |
| 1305 | + * 6 | Top Left <7:0> | | |
| 1306 | + * -----+--------------------------+ | |
| 1307 | + * 7 | Bottom Left <15:8> | | |
| 1308 | + * 8 | Bottom Left <7:0> | | |
| 1309 | + * -----+--------------------------+ | |
| 1310 | + * | |
| 1311 | + * These values represent the weight-measurements of the Wii-balance | |
| 1312 | + * board with 16bit precision. | |
| 1313 | + * | |
| 1314 | + * The balance-board is never reported interleaved with motionp. | |
| 1315 | + */ | |
| 1316 | + | |
| 1317 | + val[0] = ext[0]; | |
| 1318 | + val[0] <<= 8; | |
| 1319 | + val[0] |= ext[1]; | |
| 1320 | + | |
| 1321 | + val[1] = ext[2]; | |
| 1322 | + val[1] <<= 8; | |
| 1323 | + val[1] |= ext[3]; | |
| 1324 | + | |
| 1325 | + val[2] = ext[4]; | |
| 1326 | + val[2] <<= 8; | |
| 1327 | + val[2] |= ext[5]; | |
| 1328 | + | |
| 1329 | + val[3] = ext[6]; | |
| 1330 | + val[3] <<= 8; | |
| 1331 | + val[3] |= ext[7]; | |
| 1332 | + | |
| 1333 | + /* apply calibration data */ | |
| 1334 | + for (i = 0; i < 4; i++) { | |
| 1335 | + if (val[i] <= s->calib_bboard[i][0]) { | |
| 1336 | + tmp = 0; | |
| 1337 | + } else if (val[i] < s->calib_bboard[i][1]) { | |
| 1338 | + tmp = val[i] - s->calib_bboard[i][0]; | |
| 1339 | + tmp *= 1700; | |
| 1340 | + div = s->calib_bboard[i][1] - s->calib_bboard[i][0]; | |
| 1341 | + tmp /= div ? div : 1; | |
| 1342 | + } else { | |
| 1343 | + tmp = val[i] - s->calib_bboard[i][1]; | |
| 1344 | + tmp *= 1700; | |
| 1345 | + div = s->calib_bboard[i][2] - s->calib_bboard[i][1]; | |
| 1346 | + tmp /= div ? div : 1; | |
| 1347 | + tmp += 1700; | |
| 1348 | + } | |
| 1349 | + val[i] = tmp; | |
| 1350 | + } | |
| 1351 | + | |
| 1352 | + input_report_abs(wdata->extension.input, ABS_HAT0X, val[0]); | |
| 1353 | + input_report_abs(wdata->extension.input, ABS_HAT0Y, val[1]); | |
| 1354 | + input_report_abs(wdata->extension.input, ABS_HAT1X, val[2]); | |
| 1355 | + input_report_abs(wdata->extension.input, ABS_HAT1Y, val[3]); | |
| 1356 | + input_sync(wdata->extension.input); | |
| 1357 | +} | |
| 1358 | + | |
| 1359 | +static int wiimod_bboard_open(struct input_dev *dev) | |
| 1360 | +{ | |
| 1361 | + struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 1362 | + unsigned long flags; | |
| 1363 | + | |
| 1364 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 1365 | + wdata->state.flags |= WIIPROTO_FLAG_EXT_USED; | |
| 1366 | + wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | |
| 1367 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 1368 | + | |
| 1369 | + return 0; | |
| 1370 | +} | |
| 1371 | + | |
| 1372 | +static void wiimod_bboard_close(struct input_dev *dev) | |
| 1373 | +{ | |
| 1374 | + struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 1375 | + unsigned long flags; | |
| 1376 | + | |
| 1377 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 1378 | + wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED; | |
| 1379 | + wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | |
| 1380 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 1381 | +} | |
| 1382 | + | |
| 1383 | +static ssize_t wiimod_bboard_calib_show(struct device *dev, | |
| 1384 | + struct device_attribute *attr, | |
| 1385 | + char *out) | |
| 1386 | +{ | |
| 1387 | + struct wiimote_data *wdata = dev_to_wii(dev); | |
| 1388 | + int i, j, ret; | |
| 1389 | + __u16 val; | |
| 1390 | + __u8 buf[24], offs; | |
| 1391 | + | |
| 1392 | + ret = wiimote_cmd_acquire(wdata); | |
| 1393 | + if (ret) | |
| 1394 | + return ret; | |
| 1395 | + | |
| 1396 | + ret = wiimote_cmd_read(wdata, 0xa40024, buf, 12); | |
| 1397 | + if (ret != 12) { | |
| 1398 | + wiimote_cmd_release(wdata); | |
| 1399 | + return ret < 0 ? ret : -EIO; | |
| 1400 | + } | |
| 1401 | + ret = wiimote_cmd_read(wdata, 0xa40024 + 12, buf + 12, 12); | |
| 1402 | + if (ret != 12) { | |
| 1403 | + wiimote_cmd_release(wdata); | |
| 1404 | + return ret < 0 ? ret : -EIO; | |
| 1405 | + } | |
| 1406 | + | |
| 1407 | + wiimote_cmd_release(wdata); | |
| 1408 | + | |
| 1409 | + spin_lock_irq(&wdata->state.lock); | |
| 1410 | + offs = 0; | |
| 1411 | + for (i = 0; i < 3; ++i) { | |
| 1412 | + for (j = 0; j < 4; ++j) { | |
| 1413 | + wdata->state.calib_bboard[j][i] = buf[offs]; | |
| 1414 | + wdata->state.calib_bboard[j][i] <<= 8; | |
| 1415 | + wdata->state.calib_bboard[j][i] |= buf[offs + 1]; | |
| 1416 | + offs += 2; | |
| 1417 | + } | |
| 1418 | + } | |
| 1419 | + spin_unlock_irq(&wdata->state.lock); | |
| 1420 | + | |
| 1421 | + ret = 0; | |
| 1422 | + for (i = 0; i < 3; ++i) { | |
| 1423 | + for (j = 0; j < 4; ++j) { | |
| 1424 | + val = wdata->state.calib_bboard[j][i]; | |
| 1425 | + if (i == 2 && j == 3) | |
| 1426 | + ret += sprintf(&out[ret], "%04x\n", val); | |
| 1427 | + else | |
| 1428 | + ret += sprintf(&out[ret], "%04x:", val); | |
| 1429 | + } | |
| 1430 | + } | |
| 1431 | + | |
| 1432 | + return ret; | |
| 1433 | +} | |
| 1434 | + | |
| 1435 | +static DEVICE_ATTR(bboard_calib, S_IRUGO, wiimod_bboard_calib_show, NULL); | |
| 1436 | + | |
| 1437 | +static int wiimod_bboard_probe(const struct wiimod_ops *ops, | |
| 1438 | + struct wiimote_data *wdata) | |
| 1439 | +{ | |
| 1440 | + int ret, i, j; | |
| 1441 | + __u8 buf[24], offs; | |
| 1442 | + | |
| 1443 | + wiimote_cmd_acquire_noint(wdata); | |
| 1444 | + | |
| 1445 | + ret = wiimote_cmd_read(wdata, 0xa40024, buf, 12); | |
| 1446 | + if (ret != 12) { | |
| 1447 | + wiimote_cmd_release(wdata); | |
| 1448 | + return ret < 0 ? ret : -EIO; | |
| 1449 | + } | |
| 1450 | + ret = wiimote_cmd_read(wdata, 0xa40024 + 12, buf + 12, 12); | |
| 1451 | + if (ret != 12) { | |
| 1452 | + wiimote_cmd_release(wdata); | |
| 1453 | + return ret < 0 ? ret : -EIO; | |
| 1454 | + } | |
| 1455 | + | |
| 1456 | + wiimote_cmd_release(wdata); | |
| 1457 | + | |
| 1458 | + offs = 0; | |
| 1459 | + for (i = 0; i < 3; ++i) { | |
| 1460 | + for (j = 0; j < 4; ++j) { | |
| 1461 | + wdata->state.calib_bboard[j][i] = buf[offs]; | |
| 1462 | + wdata->state.calib_bboard[j][i] <<= 8; | |
| 1463 | + wdata->state.calib_bboard[j][i] |= buf[offs + 1]; | |
| 1464 | + offs += 2; | |
| 1465 | + } | |
| 1466 | + } | |
| 1467 | + | |
| 1468 | + wdata->extension.input = input_allocate_device(); | |
| 1469 | + if (!wdata->extension.input) | |
| 1470 | + return -ENOMEM; | |
| 1471 | + | |
| 1472 | + ret = device_create_file(&wdata->hdev->dev, | |
| 1473 | + &dev_attr_bboard_calib); | |
| 1474 | + if (ret) { | |
| 1475 | + hid_err(wdata->hdev, "cannot create sysfs attribute\n"); | |
| 1476 | + goto err_free; | |
| 1477 | + } | |
| 1478 | + | |
| 1479 | + input_set_drvdata(wdata->extension.input, wdata); | |
| 1480 | + wdata->extension.input->open = wiimod_bboard_open; | |
| 1481 | + wdata->extension.input->close = wiimod_bboard_close; | |
| 1482 | + wdata->extension.input->dev.parent = &wdata->hdev->dev; | |
| 1483 | + wdata->extension.input->id.bustype = wdata->hdev->bus; | |
| 1484 | + wdata->extension.input->id.vendor = wdata->hdev->vendor; | |
| 1485 | + wdata->extension.input->id.product = wdata->hdev->product; | |
| 1486 | + wdata->extension.input->id.version = wdata->hdev->version; | |
| 1487 | + wdata->extension.input->name = WIIMOTE_NAME " Balance Board"; | |
| 1488 | + | |
| 1489 | + set_bit(EV_KEY, wdata->extension.input->evbit); | |
| 1490 | + set_bit(BTN_A, wdata->extension.input->keybit); | |
| 1491 | + | |
| 1492 | + set_bit(EV_ABS, wdata->extension.input->evbit); | |
| 1493 | + set_bit(ABS_HAT0X, wdata->extension.input->absbit); | |
| 1494 | + set_bit(ABS_HAT0Y, wdata->extension.input->absbit); | |
| 1495 | + set_bit(ABS_HAT1X, wdata->extension.input->absbit); | |
| 1496 | + set_bit(ABS_HAT1Y, wdata->extension.input->absbit); | |
| 1497 | + input_set_abs_params(wdata->extension.input, | |
| 1498 | + ABS_HAT0X, 0, 65535, 2, 4); | |
| 1499 | + input_set_abs_params(wdata->extension.input, | |
| 1500 | + ABS_HAT0Y, 0, 65535, 2, 4); | |
| 1501 | + input_set_abs_params(wdata->extension.input, | |
| 1502 | + ABS_HAT1X, 0, 65535, 2, 4); | |
| 1503 | + input_set_abs_params(wdata->extension.input, | |
| 1504 | + ABS_HAT1Y, 0, 65535, 2, 4); | |
| 1505 | + | |
| 1506 | + ret = input_register_device(wdata->extension.input); | |
| 1507 | + if (ret) | |
| 1508 | + goto err_file; | |
| 1509 | + | |
| 1510 | + return 0; | |
| 1511 | + | |
| 1512 | +err_file: | |
| 1513 | + device_remove_file(&wdata->hdev->dev, | |
| 1514 | + &dev_attr_bboard_calib); | |
| 1515 | +err_free: | |
| 1516 | + input_free_device(wdata->extension.input); | |
| 1517 | + wdata->extension.input = NULL; | |
| 1518 | + return ret; | |
| 1519 | +} | |
| 1520 | + | |
| 1521 | +static void wiimod_bboard_remove(const struct wiimod_ops *ops, | |
| 1522 | + struct wiimote_data *wdata) | |
| 1523 | +{ | |
| 1524 | + if (!wdata->extension.input) | |
| 1525 | + return; | |
| 1526 | + | |
| 1527 | + input_unregister_device(wdata->extension.input); | |
| 1528 | + wdata->extension.input = NULL; | |
| 1529 | + device_remove_file(&wdata->hdev->dev, | |
| 1530 | + &dev_attr_bboard_calib); | |
| 1531 | +} | |
| 1532 | + | |
| 1533 | +static const struct wiimod_ops wiimod_bboard = { | |
| 1534 | + .flags = WIIMOD_FLAG_EXT8, | |
| 1535 | + .arg = 0, | |
| 1536 | + .probe = wiimod_bboard_probe, | |
| 1537 | + .remove = wiimod_bboard_remove, | |
| 1538 | + .in_keys = wiimod_bboard_in_keys, | |
| 1539 | + .in_ext = wiimod_bboard_in_ext, | |
| 1540 | +}; | |
| 1541 | + | |
| 1542 | +/* | |
| 1543 | + * Pro Controller | |
| 1544 | + * Released with the Wii U was the Nintendo Wii U Pro Controller. It does not | |
| 1545 | + * work together with the classic Wii, but only with the new Wii U. However, it | |
| 1546 | + * uses the same protocol and provides a builtin "classic controller pro" | |
| 1547 | + * extension, few standard buttons, a rumble motor, 4 LEDs and a battery. | |
| 1548 | + * We provide all these via a standard extension device as the device doesn't | |
| 1549 | + * feature an extension port. | |
| 1550 | + */ | |
| 1551 | + | |
| 1552 | +enum wiimod_pro_keys { | |
| 1553 | + WIIMOD_PRO_KEY_A, | |
| 1554 | + WIIMOD_PRO_KEY_B, | |
| 1555 | + WIIMOD_PRO_KEY_X, | |
| 1556 | + WIIMOD_PRO_KEY_Y, | |
| 1557 | + WIIMOD_PRO_KEY_PLUS, | |
| 1558 | + WIIMOD_PRO_KEY_MINUS, | |
| 1559 | + WIIMOD_PRO_KEY_HOME, | |
| 1560 | + WIIMOD_PRO_KEY_LEFT, | |
| 1561 | + WIIMOD_PRO_KEY_RIGHT, | |
| 1562 | + WIIMOD_PRO_KEY_UP, | |
| 1563 | + WIIMOD_PRO_KEY_DOWN, | |
| 1564 | + WIIMOD_PRO_KEY_TL, | |
| 1565 | + WIIMOD_PRO_KEY_TR, | |
| 1566 | + WIIMOD_PRO_KEY_ZL, | |
| 1567 | + WIIMOD_PRO_KEY_ZR, | |
| 1568 | + WIIMOD_PRO_KEY_THUMBL, | |
| 1569 | + WIIMOD_PRO_KEY_THUMBR, | |
| 1570 | + WIIMOD_PRO_KEY_NUM, | |
| 1571 | +}; | |
| 1572 | + | |
| 1573 | +static const __u16 wiimod_pro_map[] = { | |
| 1574 | + BTN_EAST, /* WIIMOD_PRO_KEY_A */ | |
| 1575 | + BTN_SOUTH, /* WIIMOD_PRO_KEY_B */ | |
| 1576 | + BTN_NORTH, /* WIIMOD_PRO_KEY_X */ | |
| 1577 | + BTN_WEST, /* WIIMOD_PRO_KEY_Y */ | |
| 1578 | + BTN_START, /* WIIMOD_PRO_KEY_PLUS */ | |
| 1579 | + BTN_SELECT, /* WIIMOD_PRO_KEY_MINUS */ | |
| 1580 | + BTN_MODE, /* WIIMOD_PRO_KEY_HOME */ | |
| 1581 | + BTN_DPAD_LEFT, /* WIIMOD_PRO_KEY_LEFT */ | |
| 1582 | + BTN_DPAD_RIGHT, /* WIIMOD_PRO_KEY_RIGHT */ | |
| 1583 | + BTN_DPAD_UP, /* WIIMOD_PRO_KEY_UP */ | |
| 1584 | + BTN_DPAD_DOWN, /* WIIMOD_PRO_KEY_DOWN */ | |
| 1585 | + BTN_TL, /* WIIMOD_PRO_KEY_TL */ | |
| 1586 | + BTN_TR, /* WIIMOD_PRO_KEY_TR */ | |
| 1587 | + BTN_TL2, /* WIIMOD_PRO_KEY_ZL */ | |
| 1588 | + BTN_TR2, /* WIIMOD_PRO_KEY_ZR */ | |
| 1589 | + BTN_THUMBL, /* WIIMOD_PRO_KEY_THUMBL */ | |
| 1590 | + BTN_THUMBR, /* WIIMOD_PRO_KEY_THUMBR */ | |
| 1591 | +}; | |
| 1592 | + | |
| 1593 | +static void wiimod_pro_in_ext(struct wiimote_data *wdata, const __u8 *ext) | |
| 1594 | +{ | |
| 1595 | + __s16 rx, ry, lx, ly; | |
| 1596 | + | |
| 1597 | + /* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | | |
| 1598 | + * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 1599 | + * 1 | LX <7:0> | | |
| 1600 | + * -----+-----------------------+-----------------------+ | |
| 1601 | + * 2 | 0 0 0 0 | LX <11:8> | | |
| 1602 | + * -----+-----------------------+-----------------------+ | |
| 1603 | + * 3 | RX <7:0> | | |
| 1604 | + * -----+-----------------------+-----------------------+ | |
| 1605 | + * 4 | 0 0 0 0 | RX <11:8> | | |
| 1606 | + * -----+-----------------------+-----------------------+ | |
| 1607 | + * 5 | LY <7:0> | | |
| 1608 | + * -----+-----------------------+-----------------------+ | |
| 1609 | + * 6 | 0 0 0 0 | LY <11:8> | | |
| 1610 | + * -----+-----------------------+-----------------------+ | |
| 1611 | + * 7 | RY <7:0> | | |
| 1612 | + * -----+-----------------------+-----------------------+ | |
| 1613 | + * 8 | 0 0 0 0 | RY <11:8> | | |
| 1614 | + * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 1615 | + * 9 | BDR | BDD | BLT | B- | BH | B+ | BRT | 1 | | |
| 1616 | + * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 1617 | + * 10 | BZL | BB | BY | BA | BX | BZR | BDL | BDU | | |
| 1618 | + * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | |
| 1619 | + * 11 | 1 | BATTERY | USB |CHARG|LTHUM|RTHUM| | |
| 1620 | + * -----+-----+-----------------+-----------+-----+-----+ | |
| 1621 | + * All buttons are low-active (0 if pressed) | |
| 1622 | + * RX and RY are right analog stick | |
| 1623 | + * LX and LY are left analog stick | |
| 1624 | + * BLT is left trigger, BRT is right trigger. | |
| 1625 | + * BDR, BDD, BDL, BDU form the D-Pad with right, down, left, up buttons | |
| 1626 | + * BZL is left Z button and BZR is right Z button | |
| 1627 | + * B-, BH, B+ are +, HOME and - buttons | |
| 1628 | + * BB, BY, BA, BX are A, B, X, Y buttons | |
| 1629 | + * | |
| 1630 | + * Bits marked as 0/1 are unknown and never changed during tests. | |
| 1631 | + * | |
| 1632 | + * Not entirely verified: | |
| 1633 | + * CHARG: 1 if uncharging, 0 if charging | |
| 1634 | + * USB: 1 if not connected, 0 if connected | |
| 1635 | + * BATTERY: battery capacity from 000 (empty) to 100 (full) | |
| 1636 | + */ | |
| 1637 | + | |
| 1638 | + lx = (ext[0] & 0xff) | ((ext[1] & 0x0f) << 8); | |
| 1639 | + rx = (ext[2] & 0xff) | ((ext[3] & 0x0f) << 8); | |
| 1640 | + ly = (ext[4] & 0xff) | ((ext[5] & 0x0f) << 8); | |
| 1641 | + ry = (ext[6] & 0xff) | ((ext[7] & 0x0f) << 8); | |
| 1642 | + | |
| 1643 | + input_report_abs(wdata->extension.input, ABS_X, lx - 0x800); | |
| 1644 | + input_report_abs(wdata->extension.input, ABS_Y, ly - 0x800); | |
| 1645 | + input_report_abs(wdata->extension.input, ABS_RX, rx - 0x800); | |
| 1646 | + input_report_abs(wdata->extension.input, ABS_RY, ry - 0x800); | |
| 1647 | + | |
| 1648 | + input_report_key(wdata->extension.input, | |
| 1649 | + wiimod_pro_map[WIIMOD_PRO_KEY_RIGHT], | |
| 1650 | + !(ext[8] & 0x80)); | |
| 1651 | + input_report_key(wdata->extension.input, | |
| 1652 | + wiimod_pro_map[WIIMOD_PRO_KEY_DOWN], | |
| 1653 | + !(ext[8] & 0x40)); | |
| 1654 | + input_report_key(wdata->extension.input, | |
| 1655 | + wiimod_pro_map[WIIMOD_PRO_KEY_TL], | |
| 1656 | + !(ext[8] & 0x20)); | |
| 1657 | + input_report_key(wdata->extension.input, | |
| 1658 | + wiimod_pro_map[WIIMOD_PRO_KEY_MINUS], | |
| 1659 | + !(ext[8] & 0x10)); | |
| 1660 | + input_report_key(wdata->extension.input, | |
| 1661 | + wiimod_pro_map[WIIMOD_PRO_KEY_HOME], | |
| 1662 | + !(ext[8] & 0x08)); | |
| 1663 | + input_report_key(wdata->extension.input, | |
| 1664 | + wiimod_pro_map[WIIMOD_PRO_KEY_PLUS], | |
| 1665 | + !(ext[8] & 0x04)); | |
| 1666 | + input_report_key(wdata->extension.input, | |
| 1667 | + wiimod_pro_map[WIIMOD_PRO_KEY_TR], | |
| 1668 | + !(ext[8] & 0x02)); | |
| 1669 | + | |
| 1670 | + input_report_key(wdata->extension.input, | |
| 1671 | + wiimod_pro_map[WIIMOD_PRO_KEY_ZL], | |
| 1672 | + !(ext[9] & 0x80)); | |
| 1673 | + input_report_key(wdata->extension.input, | |
| 1674 | + wiimod_pro_map[WIIMOD_PRO_KEY_B], | |
| 1675 | + !(ext[9] & 0x40)); | |
| 1676 | + input_report_key(wdata->extension.input, | |
| 1677 | + wiimod_pro_map[WIIMOD_PRO_KEY_Y], | |
| 1678 | + !(ext[9] & 0x20)); | |
| 1679 | + input_report_key(wdata->extension.input, | |
| 1680 | + wiimod_pro_map[WIIMOD_PRO_KEY_A], | |
| 1681 | + !(ext[9] & 0x10)); | |
| 1682 | + input_report_key(wdata->extension.input, | |
| 1683 | + wiimod_pro_map[WIIMOD_PRO_KEY_X], | |
| 1684 | + !(ext[9] & 0x08)); | |
| 1685 | + input_report_key(wdata->extension.input, | |
| 1686 | + wiimod_pro_map[WIIMOD_PRO_KEY_ZR], | |
| 1687 | + !(ext[9] & 0x04)); | |
| 1688 | + input_report_key(wdata->extension.input, | |
| 1689 | + wiimod_pro_map[WIIMOD_PRO_KEY_LEFT], | |
| 1690 | + !(ext[9] & 0x02)); | |
| 1691 | + input_report_key(wdata->extension.input, | |
| 1692 | + wiimod_pro_map[WIIMOD_PRO_KEY_UP], | |
| 1693 | + !(ext[9] & 0x01)); | |
| 1694 | + | |
| 1695 | + input_report_key(wdata->extension.input, | |
| 1696 | + wiimod_pro_map[WIIMOD_PRO_KEY_THUMBL], | |
| 1697 | + !(ext[10] & 0x02)); | |
| 1698 | + input_report_key(wdata->extension.input, | |
| 1699 | + wiimod_pro_map[WIIMOD_PRO_KEY_THUMBR], | |
| 1700 | + !(ext[10] & 0x01)); | |
| 1701 | + | |
| 1702 | + input_sync(wdata->extension.input); | |
| 1703 | +} | |
| 1704 | + | |
| 1705 | +static int wiimod_pro_open(struct input_dev *dev) | |
| 1706 | +{ | |
| 1707 | + struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 1708 | + unsigned long flags; | |
| 1709 | + | |
| 1710 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 1711 | + wdata->state.flags |= WIIPROTO_FLAG_EXT_USED; | |
| 1712 | + wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | |
| 1713 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 1714 | + | |
| 1715 | + return 0; | |
| 1716 | +} | |
| 1717 | + | |
| 1718 | +static void wiimod_pro_close(struct input_dev *dev) | |
| 1719 | +{ | |
| 1720 | + struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 1721 | + unsigned long flags; | |
| 1722 | + | |
| 1723 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 1724 | + wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED; | |
| 1725 | + wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | |
| 1726 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 1727 | +} | |
| 1728 | + | |
| 1729 | +static int wiimod_pro_play(struct input_dev *dev, void *data, | |
| 1730 | + struct ff_effect *eff) | |
| 1731 | +{ | |
| 1732 | + struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 1733 | + __u8 value; | |
| 1734 | + unsigned long flags; | |
| 1735 | + | |
| 1736 | + /* | |
| 1737 | + * The wiimote supports only a single rumble motor so if any magnitude | |
| 1738 | + * is set to non-zero then we start the rumble motor. If both are set to | |
| 1739 | + * zero, we stop the rumble motor. | |
| 1740 | + */ | |
| 1741 | + | |
| 1742 | + if (eff->u.rumble.strong_magnitude || eff->u.rumble.weak_magnitude) | |
| 1743 | + value = 1; | |
| 1744 | + else | |
| 1745 | + value = 0; | |
| 1746 | + | |
| 1747 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 1748 | + wiiproto_req_rumble(wdata, value); | |
| 1749 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 1750 | + | |
| 1751 | + return 0; | |
| 1752 | +} | |
| 1753 | + | |
| 1754 | +static int wiimod_pro_probe(const struct wiimod_ops *ops, | |
| 1755 | + struct wiimote_data *wdata) | |
| 1756 | +{ | |
| 1757 | + int ret, i; | |
| 1758 | + | |
| 1759 | + wdata->extension.input = input_allocate_device(); | |
| 1760 | + if (!wdata->extension.input) | |
| 1761 | + return -ENOMEM; | |
| 1762 | + | |
| 1763 | + set_bit(FF_RUMBLE, wdata->extension.input->ffbit); | |
| 1764 | + input_set_drvdata(wdata->extension.input, wdata); | |
| 1765 | + | |
| 1766 | + if (input_ff_create_memless(wdata->extension.input, NULL, | |
| 1767 | + wiimod_pro_play)) { | |
| 1768 | + ret = -ENOMEM; | |
| 1769 | + goto err_free; | |
| 1770 | + } | |
| 1771 | + | |
| 1772 | + wdata->extension.input->open = wiimod_pro_open; | |
| 1773 | + wdata->extension.input->close = wiimod_pro_close; | |
| 1774 | + wdata->extension.input->dev.parent = &wdata->hdev->dev; | |
| 1775 | + wdata->extension.input->id.bustype = wdata->hdev->bus; | |
| 1776 | + wdata->extension.input->id.vendor = wdata->hdev->vendor; | |
| 1777 | + wdata->extension.input->id.product = wdata->hdev->product; | |
| 1778 | + wdata->extension.input->id.version = wdata->hdev->version; | |
| 1779 | + wdata->extension.input->name = WIIMOTE_NAME " Pro Controller"; | |
| 1780 | + | |
| 1781 | + set_bit(EV_KEY, wdata->extension.input->evbit); | |
| 1782 | + for (i = 0; i < WIIMOD_PRO_KEY_NUM; ++i) | |
| 1783 | + set_bit(wiimod_pro_map[i], | |
| 1784 | + wdata->extension.input->keybit); | |
| 1785 | + | |
| 1786 | + set_bit(EV_ABS, wdata->extension.input->evbit); | |
| 1787 | + set_bit(ABS_X, wdata->extension.input->absbit); | |
| 1788 | + set_bit(ABS_Y, wdata->extension.input->absbit); | |
| 1789 | + set_bit(ABS_RX, wdata->extension.input->absbit); | |
| 1790 | + set_bit(ABS_RY, wdata->extension.input->absbit); | |
| 1791 | + input_set_abs_params(wdata->extension.input, | |
| 1792 | + ABS_X, -0x800, 0x800, 2, 4); | |
| 1793 | + input_set_abs_params(wdata->extension.input, | |
| 1794 | + ABS_Y, -0x800, 0x800, 2, 4); | |
| 1795 | + input_set_abs_params(wdata->extension.input, | |
| 1796 | + ABS_RX, -0x800, 0x800, 2, 4); | |
| 1797 | + input_set_abs_params(wdata->extension.input, | |
| 1798 | + ABS_RY, -0x800, 0x800, 2, 4); | |
| 1799 | + | |
| 1800 | + ret = input_register_device(wdata->extension.input); | |
| 1801 | + if (ret) | |
| 1802 | + goto err_free; | |
| 1803 | + | |
| 1804 | + return 0; | |
| 1805 | + | |
| 1806 | +err_free: | |
| 1807 | + input_free_device(wdata->extension.input); | |
| 1808 | + wdata->extension.input = NULL; | |
| 1809 | + return ret; | |
| 1810 | +} | |
| 1811 | + | |
| 1812 | +static void wiimod_pro_remove(const struct wiimod_ops *ops, | |
| 1813 | + struct wiimote_data *wdata) | |
| 1814 | +{ | |
| 1815 | + unsigned long flags; | |
| 1816 | + | |
| 1817 | + if (!wdata->extension.input) | |
| 1818 | + return; | |
| 1819 | + | |
| 1820 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 1821 | + wiiproto_req_rumble(wdata, 0); | |
| 1822 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 1823 | + | |
| 1824 | + input_unregister_device(wdata->extension.input); | |
| 1825 | + wdata->extension.input = NULL; | |
| 1826 | +} | |
| 1827 | + | |
| 1828 | +static const struct wiimod_ops wiimod_pro = { | |
| 1829 | + .flags = WIIMOD_FLAG_EXT16, | |
| 1830 | + .arg = 0, | |
| 1831 | + .probe = wiimod_pro_probe, | |
| 1832 | + .remove = wiimod_pro_remove, | |
| 1833 | + .in_ext = wiimod_pro_in_ext, | |
| 1834 | +}; | |
| 1835 | + | |
| 1836 | +/* | |
| 1837 | + * Builtin Motion Plus | |
| 1838 | + * This module simply sets the WIIPROTO_FLAG_BUILTIN_MP protocol flag which | |
| 1839 | + * disables polling for Motion-Plus. This should be set only for devices which | |
| 1840 | + * don't allow MP hotplugging. | |
| 1841 | + */ | |
| 1842 | + | |
| 1843 | +static int wiimod_builtin_mp_probe(const struct wiimod_ops *ops, | |
| 1844 | + struct wiimote_data *wdata) | |
| 1845 | +{ | |
| 1846 | + unsigned long flags; | |
| 1847 | + | |
| 1848 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 1849 | + wdata->state.flags |= WIIPROTO_FLAG_BUILTIN_MP; | |
| 1850 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 1851 | + | |
| 1852 | + return 0; | |
| 1853 | +} | |
| 1854 | + | |
| 1855 | +static void wiimod_builtin_mp_remove(const struct wiimod_ops *ops, | |
| 1856 | + struct wiimote_data *wdata) | |
| 1857 | +{ | |
| 1858 | + unsigned long flags; | |
| 1859 | + | |
| 1860 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 1861 | + wdata->state.flags |= WIIPROTO_FLAG_BUILTIN_MP; | |
| 1862 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 1863 | +} | |
| 1864 | + | |
| 1865 | +static const struct wiimod_ops wiimod_builtin_mp = { | |
| 1866 | + .flags = 0, | |
| 1867 | + .arg = 0, | |
| 1868 | + .probe = wiimod_builtin_mp_probe, | |
| 1869 | + .remove = wiimod_builtin_mp_remove, | |
| 1870 | +}; | |
| 1871 | + | |
| 1872 | +/* | |
| 1873 | + * No Motion Plus | |
| 1874 | + * This module simply sets the WIIPROTO_FLAG_NO_MP protocol flag which | |
| 1875 | + * disables motion-plus. This is needed for devices that advertise this but we | |
| 1876 | + * don't know how to use it (or whether it is actually present). | |
| 1877 | + */ | |
| 1878 | + | |
| 1879 | +static int wiimod_no_mp_probe(const struct wiimod_ops *ops, | |
| 1880 | + struct wiimote_data *wdata) | |
| 1881 | +{ | |
| 1882 | + unsigned long flags; | |
| 1883 | + | |
| 1884 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 1885 | + wdata->state.flags |= WIIPROTO_FLAG_NO_MP; | |
| 1886 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 1887 | + | |
| 1888 | + return 0; | |
| 1889 | +} | |
| 1890 | + | |
| 1891 | +static void wiimod_no_mp_remove(const struct wiimod_ops *ops, | |
| 1892 | + struct wiimote_data *wdata) | |
| 1893 | +{ | |
| 1894 | + unsigned long flags; | |
| 1895 | + | |
| 1896 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 1897 | + wdata->state.flags |= WIIPROTO_FLAG_NO_MP; | |
| 1898 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 1899 | +} | |
| 1900 | + | |
| 1901 | +static const struct wiimod_ops wiimod_no_mp = { | |
| 1902 | + .flags = 0, | |
| 1903 | + .arg = 0, | |
| 1904 | + .probe = wiimod_no_mp_probe, | |
| 1905 | + .remove = wiimod_no_mp_remove, | |
| 1906 | +}; | |
| 1907 | + | |
| 1908 | +/* | |
| 1909 | + * Motion Plus | |
| 1910 | + * The Motion Plus extension provides rotation sensors (gyro) as a small | |
| 1911 | + * extension device for Wii Remotes. Many devices have them built-in so | |
| 1912 | + * you cannot see them from the outside. | |
| 1913 | + * Motion Plus extensions are special because they are on a separate extension | |
| 1914 | + * port and allow other extensions to be used simultaneously. This is all | |
| 1915 | + * handled by the Wiimote Core so we don't have to deal with it. | |
| 1916 | + */ | |
| 1917 | + | |
| 1918 | +static void wiimod_mp_in_mp(struct wiimote_data *wdata, const __u8 *ext) | |
| 1919 | +{ | |
| 1920 | + __s32 x, y, z; | |
| 1921 | + | |
| 1922 | + /* | 8 7 6 5 4 3 | 2 | 1 | | |
| 1923 | + * -----+------------------------------+-----+-----+ | |
| 1924 | + * 1 | Yaw Speed <7:0> | | |
| 1925 | + * 2 | Roll Speed <7:0> | | |
| 1926 | + * 3 | Pitch Speed <7:0> | | |
| 1927 | + * -----+------------------------------+-----+-----+ | |
| 1928 | + * 4 | Yaw Speed <13:8> | Yaw |Pitch| | |
| 1929 | + * -----+------------------------------+-----+-----+ | |
| 1930 | + * 5 | Roll Speed <13:8> |Roll | Ext | | |
| 1931 | + * -----+------------------------------+-----+-----+ | |
| 1932 | + * 6 | Pitch Speed <13:8> | 1 | 0 | | |
| 1933 | + * -----+------------------------------+-----+-----+ | |
| 1934 | + * The single bits Yaw, Roll, Pitch in the lower right corner specify | |
| 1935 | + * whether the wiimote is rotating fast (0) or slow (1). Speed for slow | |
| 1936 | + * roation is 440 deg/s and for fast rotation 2000 deg/s. To get a | |
| 1937 | + * linear scale we multiply by 2000/440 = ~4.5454 which is 18 for fast | |
| 1938 | + * and 9 for slow. | |
| 1939 | + * If the wiimote is not rotating the sensor reports 2^13 = 8192. | |
| 1940 | + * Ext specifies whether an extension is connected to the motionp. | |
| 1941 | + * which is parsed by wiimote-core. | |
| 1942 | + */ | |
| 1943 | + | |
| 1944 | + x = ext[0]; | |
| 1945 | + y = ext[1]; | |
| 1946 | + z = ext[2]; | |
| 1947 | + | |
| 1948 | + x |= (((__u16)ext[3]) << 6) & 0xff00; | |
| 1949 | + y |= (((__u16)ext[4]) << 6) & 0xff00; | |
| 1950 | + z |= (((__u16)ext[5]) << 6) & 0xff00; | |
| 1951 | + | |
| 1952 | + x -= 8192; | |
| 1953 | + y -= 8192; | |
| 1954 | + z -= 8192; | |
| 1955 | + | |
| 1956 | + if (!(ext[3] & 0x02)) | |
| 1957 | + x *= 18; | |
| 1958 | + else | |
| 1959 | + x *= 9; | |
| 1960 | + if (!(ext[4] & 0x02)) | |
| 1961 | + y *= 18; | |
| 1962 | + else | |
| 1963 | + y *= 9; | |
| 1964 | + if (!(ext[3] & 0x01)) | |
| 1965 | + z *= 18; | |
| 1966 | + else | |
| 1967 | + z *= 9; | |
| 1968 | + | |
| 1969 | + input_report_abs(wdata->mp, ABS_RX, x); | |
| 1970 | + input_report_abs(wdata->mp, ABS_RY, y); | |
| 1971 | + input_report_abs(wdata->mp, ABS_RZ, z); | |
| 1972 | + input_sync(wdata->mp); | |
| 1973 | +} | |
| 1974 | + | |
| 1975 | +static int wiimod_mp_open(struct input_dev *dev) | |
| 1976 | +{ | |
| 1977 | + struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 1978 | + unsigned long flags; | |
| 1979 | + | |
| 1980 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 1981 | + wdata->state.flags |= WIIPROTO_FLAG_MP_USED; | |
| 1982 | + wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | |
| 1983 | + __wiimote_schedule(wdata); | |
| 1984 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 1985 | + | |
| 1986 | + return 0; | |
| 1987 | +} | |
| 1988 | + | |
| 1989 | +static void wiimod_mp_close(struct input_dev *dev) | |
| 1990 | +{ | |
| 1991 | + struct wiimote_data *wdata = input_get_drvdata(dev); | |
| 1992 | + unsigned long flags; | |
| 1993 | + | |
| 1994 | + spin_lock_irqsave(&wdata->state.lock, flags); | |
| 1995 | + wdata->state.flags &= ~WIIPROTO_FLAG_MP_USED; | |
| 1996 | + wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | |
| 1997 | + __wiimote_schedule(wdata); | |
| 1998 | + spin_unlock_irqrestore(&wdata->state.lock, flags); | |
| 1999 | +} | |
| 2000 | + | |
| 2001 | +static int wiimod_mp_probe(const struct wiimod_ops *ops, | |
| 2002 | + struct wiimote_data *wdata) | |
| 2003 | +{ | |
| 2004 | + int ret; | |
| 2005 | + | |
| 2006 | + wdata->mp = input_allocate_device(); | |
| 2007 | + if (!wdata->mp) | |
| 2008 | + return -ENOMEM; | |
| 2009 | + | |
| 2010 | + input_set_drvdata(wdata->mp, wdata); | |
| 2011 | + wdata->mp->open = wiimod_mp_open; | |
| 2012 | + wdata->mp->close = wiimod_mp_close; | |
| 2013 | + wdata->mp->dev.parent = &wdata->hdev->dev; | |
| 2014 | + wdata->mp->id.bustype = wdata->hdev->bus; | |
| 2015 | + wdata->mp->id.vendor = wdata->hdev->vendor; | |
| 2016 | + wdata->mp->id.product = wdata->hdev->product; | |
| 2017 | + wdata->mp->id.version = wdata->hdev->version; | |
| 2018 | + wdata->mp->name = WIIMOTE_NAME " Motion Plus"; | |
| 2019 | + | |
| 2020 | + set_bit(EV_ABS, wdata->mp->evbit); | |
| 2021 | + set_bit(ABS_RX, wdata->mp->absbit); | |
| 2022 | + set_bit(ABS_RY, wdata->mp->absbit); | |
| 2023 | + set_bit(ABS_RZ, wdata->mp->absbit); | |
| 2024 | + input_set_abs_params(wdata->mp, | |
| 2025 | + ABS_RX, -16000, 16000, 4, 8); | |
| 2026 | + input_set_abs_params(wdata->mp, | |
| 2027 | + ABS_RY, -16000, 16000, 4, 8); | |
| 2028 | + input_set_abs_params(wdata->mp, | |
| 2029 | + ABS_RZ, -16000, 16000, 4, 8); | |
| 2030 | + | |
| 2031 | + ret = input_register_device(wdata->mp); | |
| 2032 | + if (ret) | |
| 2033 | + goto err_free; | |
| 2034 | + | |
| 2035 | + return 0; | |
| 2036 | + | |
| 2037 | +err_free: | |
| 2038 | + input_free_device(wdata->mp); | |
| 2039 | + wdata->mp = NULL; | |
| 2040 | + return ret; | |
| 2041 | +} | |
| 2042 | + | |
| 2043 | +static void wiimod_mp_remove(const struct wiimod_ops *ops, | |
| 2044 | + struct wiimote_data *wdata) | |
| 2045 | +{ | |
| 2046 | + if (!wdata->mp) | |
| 2047 | + return; | |
| 2048 | + | |
| 2049 | + input_unregister_device(wdata->mp); | |
| 2050 | + wdata->mp = NULL; | |
| 2051 | +} | |
| 2052 | + | |
| 2053 | +const struct wiimod_ops wiimod_mp = { | |
| 2054 | + .flags = 0, | |
| 2055 | + .arg = 0, | |
| 2056 | + .probe = wiimod_mp_probe, | |
| 2057 | + .remove = wiimod_mp_remove, | |
| 2058 | + .in_mp = wiimod_mp_in_mp, | |
| 2059 | +}; | |
| 2060 | + | |
| 2061 | +/* module table */ | |
| 2062 | + | |
| 2063 | +static const struct wiimod_ops wiimod_dummy; | |
| 2064 | + | |
| 2065 | +const struct wiimod_ops *wiimod_table[WIIMOD_NUM] = { | |
| 2066 | + [WIIMOD_KEYS] = &wiimod_keys, | |
| 2067 | + [WIIMOD_RUMBLE] = &wiimod_rumble, | |
| 2068 | + [WIIMOD_BATTERY] = &wiimod_battery, | |
| 2069 | + [WIIMOD_LED1] = &wiimod_leds[0], | |
| 2070 | + [WIIMOD_LED2] = &wiimod_leds[1], | |
| 2071 | + [WIIMOD_LED3] = &wiimod_leds[2], | |
| 2072 | + [WIIMOD_LED4] = &wiimod_leds[3], | |
| 2073 | + [WIIMOD_ACCEL] = &wiimod_accel, | |
| 2074 | + [WIIMOD_IR] = &wiimod_ir, | |
| 2075 | + [WIIMOD_BUILTIN_MP] = &wiimod_builtin_mp, | |
| 2076 | + [WIIMOD_NO_MP] = &wiimod_no_mp, | |
| 2077 | +}; | |
| 2078 | + | |
| 2079 | +const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM] = { | |
| 2080 | + [WIIMOTE_EXT_NONE] = &wiimod_dummy, | |
| 2081 | + [WIIMOTE_EXT_UNKNOWN] = &wiimod_dummy, | |
| 2082 | + [WIIMOTE_EXT_NUNCHUK] = &wiimod_nunchuk, | |
| 2083 | + [WIIMOTE_EXT_CLASSIC_CONTROLLER] = &wiimod_classic, | |
| 2084 | + [WIIMOTE_EXT_BALANCE_BOARD] = &wiimod_bboard, | |
| 2085 | + [WIIMOTE_EXT_PRO_CONTROLLER] = &wiimod_pro, | |
| 2086 | +}; | |
| @@ -2,8 +2,8 @@ · 1 unmodified line | ||
| 2 | 2 | #define __HID_WIIMOTE_H |
| 3 | 3 | |
| 4 | 4 | /* |
| 5 | − * HID driver for Nintendo Wiimote devices | |
| 6 | − * Copyright (c) 2011 David Herrmann | |
| 5 | + * HID driver for Nintendo Wii / Wii U peripherals | |
| 6 | + * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@gmail.com> | |
| 7 | 7 | */ |
| 8 | 8 | |
| 9 | 9 | /* |
| @@ -22,6 +22,7 @@ · 12 unmodified lines | ||
| 22 | 22 | #include <linux/mutex.h> |
| 23 | 23 | #include <linux/power_supply.h> |
| 24 | 24 | #include <linux/spinlock.h> |
| 25 | +#include <linux/timer.h> | |
| 25 | 26 | |
| 26 | 27 | #define WIIMOTE_NAME "Nintendo Wii Remote" |
| 27 | 28 | #define WIIMOTE_BUFSIZE 32 |
| @@ -35,6 +36,17 @@ · 7 unmodified lines | ||
| 35 | 36 | #define WIIPROTO_FLAG_IR_BASIC 0x40 |
| 36 | 37 | #define WIIPROTO_FLAG_IR_EXT 0x80 |
| 37 | 38 | #define WIIPROTO_FLAG_IR_FULL 0xc0 /* IR_BASIC | IR_EXT */ |
| 39 | +#define WIIPROTO_FLAG_EXT_PLUGGED 0x0100 | |
| 40 | +#define WIIPROTO_FLAG_EXT_USED 0x0200 | |
| 41 | +#define WIIPROTO_FLAG_EXT_ACTIVE 0x0400 | |
| 42 | +#define WIIPROTO_FLAG_MP_PLUGGED 0x0800 | |
| 43 | +#define WIIPROTO_FLAG_MP_USED 0x1000 | |
| 44 | +#define WIIPROTO_FLAG_MP_ACTIVE 0x2000 | |
| 45 | +#define WIIPROTO_FLAG_EXITING 0x4000 | |
| 46 | +#define WIIPROTO_FLAG_DRM_LOCKED 0x8000 | |
| 47 | +#define WIIPROTO_FLAG_BUILTIN_MP 0x010000 | |
| 48 | +#define WIIPROTO_FLAG_NO_MP 0x020000 | |
| 49 | + | |
| 38 | 50 | #define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ |
| 39 | 51 | WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) |
| 40 | 52 | #define WIIPROTO_FLAGS_IR (WIIPROTO_FLAG_IR_BASIC | WIIPROTO_FLAG_IR_EXT | \ |
| @@ -43,16 +55,71 @@ · 2 unmodified lines | ||
| 43 | 55 | /* return flag for led \num */ |
| 44 | 56 | #define WIIPROTO_FLAG_LED(num) (WIIPROTO_FLAG_LED1 << (num - 1)) |
| 45 | 57 | |
| 58 | +enum wiiproto_keys { | |
| 59 | + WIIPROTO_KEY_LEFT, | |
| 60 | + WIIPROTO_KEY_RIGHT, | |
| 61 | + WIIPROTO_KEY_UP, | |
| 62 | + WIIPROTO_KEY_DOWN, | |
| 63 | + WIIPROTO_KEY_PLUS, | |
| 64 | + WIIPROTO_KEY_MINUS, | |
| 65 | + WIIPROTO_KEY_ONE, | |
| 66 | + WIIPROTO_KEY_TWO, | |
| 67 | + WIIPROTO_KEY_A, | |
| 68 | + WIIPROTO_KEY_B, | |
| 69 | + WIIPROTO_KEY_HOME, | |
| 70 | + WIIPROTO_KEY_COUNT | |
| 71 | +}; | |
| 72 | + | |
| 73 | +enum wiimote_devtype { | |
| 74 | + WIIMOTE_DEV_PENDING, | |
| 75 | + WIIMOTE_DEV_UNKNOWN, | |
| 76 | + WIIMOTE_DEV_GENERIC, | |
| 77 | + WIIMOTE_DEV_GEN10, | |
| 78 | + WIIMOTE_DEV_GEN20, | |
| 79 | + WIIMOTE_DEV_BALANCE_BOARD, | |
| 80 | + WIIMOTE_DEV_PRO_CONTROLLER, | |
| 81 | + WIIMOTE_DEV_NUM, | |
| 82 | +}; | |
| 83 | + | |
| 84 | +enum wiimote_exttype { | |
| 85 | + WIIMOTE_EXT_NONE, | |
| 86 | + WIIMOTE_EXT_UNKNOWN, | |
| 87 | + WIIMOTE_EXT_NUNCHUK, | |
| 88 | + WIIMOTE_EXT_CLASSIC_CONTROLLER, | |
| 89 | + WIIMOTE_EXT_BALANCE_BOARD, | |
| 90 | + WIIMOTE_EXT_PRO_CONTROLLER, | |
| 91 | + WIIMOTE_EXT_NUM, | |
| 92 | +}; | |
| 93 | + | |
| 94 | +enum wiimote_mptype { | |
| 95 | + WIIMOTE_MP_NONE, | |
| 96 | + WIIMOTE_MP_UNKNOWN, | |
| 97 | + WIIMOTE_MP_SINGLE, | |
| 98 | + WIIMOTE_MP_PASSTHROUGH_NUNCHUK, | |
| 99 | + WIIMOTE_MP_PASSTHROUGH_CLASSIC, | |
| 100 | +}; | |
| 101 | + | |
| 46 | 102 | struct wiimote_buf { |
| 47 | 103 | __u8 data[HID_MAX_BUFFER_SIZE]; |
| 48 | 104 | size_t size; |
| 49 | 105 | }; |
| 50 | 106 | |
| 107 | +struct wiimote_queue { | |
| 108 | + spinlock_t lock; | |
| 109 | + struct work_struct worker; | |
| 110 | + __u8 head; | |
| 111 | + __u8 tail; | |
| 112 | + struct wiimote_buf outq[WIIMOTE_BUFSIZE]; | |
| 113 | +}; | |
| 114 | + | |
| 51 | 115 | struct wiimote_state { |
| 52 | 116 | spinlock_t lock; |
| 53 | − __u8 flags; | |
| 117 | + __u32 flags; | |
| 54 | 118 | __u8 accel_split[2]; |
| 55 | 119 | __u8 drm; |
| 120 | + __u8 devtype; | |
| 121 | + __u8 exttype; | |
| 122 | + __u8 mp; | |
| 56 | 123 | |
| 57 | 124 | /* synchronous cmd requests */ |
| 58 | 125 | struct mutex sync; |
| @@ -65,6 +132,9 @@ struct wiimote_state { · 6 unmodified lines | ||
| 65 | 132 | __u8 cmd_err; |
| 66 | 133 | __u8 *cmd_read_buf; |
| 67 | 134 | __u8 cmd_read_size; |
| 135 | + | |
| 136 | + /* calibration data */ | |
| 137 | + __u16 calib_bboard[4][3]; | |
| 68 | 138 | }; |
| 69 | 139 | |
| 70 | 140 | struct wiimote_data { |
| @@ -74,18 +144,63 @@ struct wiimote_data { · 3 unmodified lines | ||
| 74 | 144 | struct input_dev *accel; |
| 75 | 145 | struct input_dev *ir; |
| 76 | 146 | struct power_supply battery; |
| 77 | − struct wiimote_ext *ext; | |
| 147 | + struct input_dev *mp; | |
| 148 | + struct timer_list timer; | |
| 78 | 149 | struct wiimote_debug *debug; |
| 79 | 150 | |
| 80 | − spinlock_t qlock; | |
| 81 | − __u8 head; | |
| 82 | − __u8 tail; | |
| 83 | − struct wiimote_buf outq[WIIMOTE_BUFSIZE]; | |
| 84 | − struct work_struct worker; | |
| 151 | + union { | |
| 152 | + struct input_dev *input; | |
| 153 | + } extension; | |
| 85 | 154 | |
| 155 | + struct wiimote_queue queue; | |
| 86 | 156 | struct wiimote_state state; |
| 157 | + struct work_struct init_worker; | |
| 158 | +}; | |
| 159 | + | |
| 160 | +/* wiimote modules */ | |
| 161 | + | |
| 162 | +enum wiimod_module { | |
| 163 | + WIIMOD_KEYS, | |
| 164 | + WIIMOD_RUMBLE, | |
| 165 | + WIIMOD_BATTERY, | |
| 166 | + WIIMOD_LED1, | |
| 167 | + WIIMOD_LED2, | |
| 168 | + WIIMOD_LED3, | |
| 169 | + WIIMOD_LED4, | |
| 170 | + WIIMOD_ACCEL, | |
| 171 | + WIIMOD_IR, | |
| 172 | + WIIMOD_BUILTIN_MP, | |
| 173 | + WIIMOD_NO_MP, | |
| 174 | + WIIMOD_NUM, | |
| 175 | + WIIMOD_NULL = WIIMOD_NUM, | |
| 176 | +}; | |
| 177 | + | |
| 178 | +#define WIIMOD_FLAG_INPUT 0x0001 | |
| 179 | +#define WIIMOD_FLAG_EXT8 0x0002 | |
| 180 | +#define WIIMOD_FLAG_EXT16 0x0004 | |
| 181 | + | |
| 182 | +struct wiimod_ops { | |
| 183 | + __u16 flags; | |
| 184 | + unsigned long arg; | |
| 185 | + int (*probe) (const struct wiimod_ops *ops, | |
| 186 | + struct wiimote_data *wdata); | |
| 187 | + void (*remove) (const struct wiimod_ops *ops, | |
| 188 | + struct wiimote_data *wdata); | |
| 189 | + | |
| 190 | + void (*in_keys) (struct wiimote_data *wdata, const __u8 *keys); | |
| 191 | + void (*in_accel) (struct wiimote_data *wdata, const __u8 *accel); | |
| 192 | + void (*in_ir) (struct wiimote_data *wdata, const __u8 *ir, bool packed, | |
| 193 | + unsigned int id); | |
| 194 | + void (*in_mp) (struct wiimote_data *wdata, const __u8 *mp); | |
| 195 | + void (*in_ext) (struct wiimote_data *wdata, const __u8 *ext); | |
| 87 | 196 | }; |
| 88 | 197 | |
| 198 | +extern const struct wiimod_ops *wiimod_table[WIIMOD_NUM]; | |
| 199 | +extern const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM]; | |
| 200 | +extern const struct wiimod_ops wiimod_mp; | |
| 201 | + | |
| 202 | +/* wiimote requests */ | |
| 203 | + | |
| 89 | 204 | enum wiiproto_reqs { |
| 90 | 205 | WIIPROTO_REQ_NULL = 0x0, |
| 91 | 206 | WIIPROTO_REQ_RUMBLE = 0x10, |
| @@ -99,24 +214,55 @@ enum wiiproto_reqs { · 7 unmodified lines | ||
| 99 | 214 | WIIPROTO_REQ_STATUS = 0x20, |
| 100 | 215 | WIIPROTO_REQ_DATA = 0x21, |
| 101 | 216 | WIIPROTO_REQ_RETURN = 0x22, |
| 217 | + | |
| 218 | + /* DRM_K: BB*2 */ | |
| 102 | 219 | WIIPROTO_REQ_DRM_K = 0x30, |
| 220 | + | |
| 221 | + /* DRM_KA: BB*2 AA*3 */ | |
| 103 | 222 | WIIPROTO_REQ_DRM_KA = 0x31, |
| 223 | + | |
| 224 | + /* DRM_KE: BB*2 EE*8 */ | |
| 104 | 225 | WIIPROTO_REQ_DRM_KE = 0x32, |
| 226 | + | |
| 227 | + /* DRM_KAI: BB*2 AA*3 II*12 */ | |
| 105 | 228 | WIIPROTO_REQ_DRM_KAI = 0x33, |
| 229 | + | |
| 230 | + /* DRM_KEE: BB*2 EE*19 */ | |
| 106 | 231 | WIIPROTO_REQ_DRM_KEE = 0x34, |
| 232 | + | |
| 233 | + /* DRM_KAE: BB*2 AA*3 EE*16 */ | |
| 107 | 234 | WIIPROTO_REQ_DRM_KAE = 0x35, |
| 235 | + | |
| 236 | + /* DRM_KIE: BB*2 II*10 EE*9 */ | |
| 108 | 237 | WIIPROTO_REQ_DRM_KIE = 0x36, |
| 238 | + | |
| 239 | + /* DRM_KAIE: BB*2 AA*3 II*10 EE*6 */ | |
| 109 | 240 | WIIPROTO_REQ_DRM_KAIE = 0x37, |
| 241 | + | |
| 242 | + /* DRM_E: EE*21 */ | |
| 110 | 243 | WIIPROTO_REQ_DRM_E = 0x3d, |
| 244 | + | |
| 245 | + /* DRM_SKAI1: BB*2 AA*1 II*18 */ | |
| 111 | 246 | WIIPROTO_REQ_DRM_SKAI1 = 0x3e, |
| 247 | + | |
| 248 | + /* DRM_SKAI2: BB*2 AA*1 II*18 */ | |
| 112 | 249 | WIIPROTO_REQ_DRM_SKAI2 = 0x3f, |
| 250 | + | |
| 113 | 251 | WIIPROTO_REQ_MAX |
| 114 | 252 | }; |
| 115 | 253 | |
| 116 | 254 | #define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \ |
| 117 | 255 | dev)) |
| 118 | 256 | |
| 257 | +void __wiimote_schedule(struct wiimote_data *wdata); | |
| 258 | + | |
| 119 | 259 | extern void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm); |
| 260 | +extern void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble); | |
| 261 | +extern void wiiproto_req_leds(struct wiimote_data *wdata, int leds); | |
| 262 | +extern void wiiproto_req_status(struct wiimote_data *wdata); | |
| 263 | +extern void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel); | |
| 264 | +extern void wiiproto_req_ir1(struct wiimote_data *wdata, __u8 flags); | |
| 265 | +extern void wiiproto_req_ir2(struct wiimote_data *wdata, __u8 flags); | |
| 120 | 266 | extern int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, |
| 121 | 267 | const __u8 *wmem, __u8 size); |
| 122 | 268 | extern ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, |
| @@ -129,24 +275,6 @@ extern ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, · 6 unmodified lines | ||
| 129 | 275 | extern void wiiproto_req_rmem(struct wiimote_data *wdata, bool eeprom, |
| 130 | 276 | __u32 offset, __u16 size); |
| 131 | 277 | |
| 132 | −#ifdef CONFIG_HID_WIIMOTE_EXT | |
| 133 | − | |
| 134 | −extern int wiiext_init(struct wiimote_data *wdata); | |
| 135 | −extern void wiiext_deinit(struct wiimote_data *wdata); | |
| 136 | −extern void wiiext_event(struct wiimote_data *wdata, bool plugged); | |
| 137 | −extern bool wiiext_active(struct wiimote_data *wdata); | |
| 138 | −extern void wiiext_handle(struct wiimote_data *wdata, const __u8 *payload); | |
| 139 | − | |
| 140 | −#else | |
| 141 | − | |
| 142 | −static inline int wiiext_init(void *u) { return 0; } | |
| 143 | −static inline void wiiext_deinit(void *u) { } | |
| 144 | −static inline void wiiext_event(void *u, bool p) { } | |
| 145 | −static inline bool wiiext_active(void *u) { return false; } | |
| 146 | −static inline void wiiext_handle(void *u, const __u8 *p) { } | |
| 147 | − | |
| 148 | −#endif | |
| 149 | − | |
| 150 | 278 | #ifdef CONFIG_DEBUG_FS |
| 151 | 279 | |
| 152 | 280 | extern int wiidebug_init(struct wiimote_data *wdata); |
| @@ -173,11 +301,26 @@ static inline void wiimote_cmd_complete(struct wiimote_data *wdata) · 20 unmodified lines | ||
| 173 | 301 | complete(&wdata->state.ready); |
| 174 | 302 | } |
| 175 | 303 | |
| 304 | +/* requires the state.lock spinlock to be held */ | |
| 305 | +static inline void wiimote_cmd_abort(struct wiimote_data *wdata) | |
| 306 | +{ | |
| 307 | + /* Abort synchronous request by waking up the sleeping caller. But | |
| 308 | + * reset the state.cmd field to an invalid value so no further event | |
| 309 | + * handlers will work with it. */ | |
| 310 | + wdata->state.cmd = WIIPROTO_REQ_MAX; | |
| 311 | + complete(&wdata->state.ready); | |
| 312 | +} | |
| 313 | + | |
| 176 | 314 | static inline int wiimote_cmd_acquire(struct wiimote_data *wdata) |
| 177 | 315 | { |
| 178 | 316 | return mutex_lock_interruptible(&wdata->state.sync) ? -ERESTARTSYS : 0; |
| 179 | 317 | } |
| 180 | 318 | |
| 319 | +static inline void wiimote_cmd_acquire_noint(struct wiimote_data *wdata) | |
| 320 | +{ | |
| 321 | + mutex_lock(&wdata->state.sync); | |
| 322 | +} | |
| 323 | + | |
| 181 | 324 | /* requires the state.lock spinlock to be held */ |
| 182 | 325 | static inline void wiimote_cmd_set(struct wiimote_data *wdata, int cmd, |
| 183 | 326 | __u32 opt) |
| @@ -196,11 +339,31 @@ static inline int wiimote_cmd_wait(struct wiimote_data *wdata) · 12 unmodified lines | ||
| 196 | 339 | { |
| 197 | 340 | int ret; |
| 198 | 341 | |
| 342 | + /* The completion acts as implicit memory barrier so we can safely | |
| 343 | + * assume that state.cmd is set on success/failure and isn't accessed | |
| 344 | + * by any other thread, anymore. */ | |
| 345 | + | |
| 199 | 346 | ret = wait_for_completion_interruptible_timeout(&wdata->state.ready, HZ); |
| 200 | 347 | if (ret < 0) |
| 201 | 348 | return -ERESTARTSYS; |
| 202 | 349 | else if (ret == 0) |
| 203 | 350 | return -EIO; |
| 351 | + else if (wdata->state.cmd != WIIPROTO_REQ_NULL) | |
| 352 | + return -EIO; | |
| 353 | + else | |
| 354 | + return 0; | |
| 355 | +} | |
| 356 | + | |
| 357 | +static inline int wiimote_cmd_wait_noint(struct wiimote_data *wdata) | |
| 358 | +{ | |
| 359 | + unsigned long ret; | |
| 360 | + | |
| 361 | + /* no locking needed; see wiimote_cmd_wait() */ | |
| 362 | + ret = wait_for_completion_timeout(&wdata->state.ready, HZ); | |
| 363 | + if (!ret) | |
| 364 | + return -EIO; | |
| 365 | + else if (wdata->state.cmd != WIIPROTO_REQ_NULL) | |
| 366 | + return -EIO; | |
| 204 | 367 | else |
| 205 | 368 | return 0; |
| 206 | 369 | } |
| @@ -108,6 +108,7 @@ static const struct i2c_hid_cmd hid_reset_cmd = { I2C_HID_CMD(0x01), · 107 unmodified lines | ||
| 108 | 108 | static const struct i2c_hid_cmd hid_get_report_cmd = { I2C_HID_CMD(0x02) }; |
| 109 | 109 | static const struct i2c_hid_cmd hid_set_report_cmd = { I2C_HID_CMD(0x03) }; |
| 110 | 110 | static const struct i2c_hid_cmd hid_set_power_cmd = { I2C_HID_CMD(0x08) }; |
| 111 | +static const struct i2c_hid_cmd hid_no_cmd = { .length = 0 }; | |
| 111 | 112 | |
| 112 | 113 | /* |
| 113 | 114 | * These definitions are not used here, but are defined by the spec. |
| @@ -259,8 +260,11 @@ static int i2c_hid_set_report(struct i2c_client *client, u8 reportType, · 145 unmodified lines | ||
| 259 | 260 | { |
| 260 | 261 | struct i2c_hid *ihid = i2c_get_clientdata(client); |
| 261 | 262 | u8 *args = ihid->argsbuf; |
| 263 | + const struct i2c_hid_cmd * hidcmd = &hid_set_report_cmd; | |
| 262 | 264 | int ret; |
| 263 | 265 | u16 dataRegister = le16_to_cpu(ihid->hdesc.wDataRegister); |
| 266 | + u16 outputRegister = le16_to_cpu(ihid->hdesc.wOutputRegister); | |
| 267 | + u16 maxOutputLength = le16_to_cpu(ihid->hdesc.wMaxOutputLength); | |
| 264 | 268 | |
| 265 | 269 | /* hidraw already checked that data_len < HID_MAX_BUFFER_SIZE */ |
| 266 | 270 | u16 size = 2 /* size */ + |
| @@ -278,8 +282,18 @@ static int i2c_hid_set_report(struct i2c_client *client, u8 reportType, · 11 unmodified lines | ||
| 278 | 282 | reportID = 0x0F; |
| 279 | 283 | } |
| 280 | 284 | |
| 281 | − args[index++] = dataRegister & 0xFF; | |
| 282 | − args[index++] = dataRegister >> 8; | |
| 285 | + /* | |
| 286 | + * use the data register for feature reports or if the device does not | |
| 287 | + * support the output register | |
| 288 | + */ | |
| 289 | + if (reportType == 0x03 || maxOutputLength == 0) { | |
| 290 | + args[index++] = dataRegister & 0xFF; | |
| 291 | + args[index++] = dataRegister >> 8; | |
| 292 | + } else { | |
| 293 | + args[index++] = outputRegister & 0xFF; | |
| 294 | + args[index++] = outputRegister >> 8; | |
| 295 | + hidcmd = &hid_no_cmd; | |
| 296 | + } | |
| 283 | 297 | |
| 284 | 298 | args[index++] = size & 0xFF; |
| 285 | 299 | args[index++] = size >> 8; |
| @@ -289,7 +303,7 @@ static int i2c_hid_set_report(struct i2c_client *client, u8 reportType, · 3 unmodified lines | ||
| 289 | 303 | |
| 290 | 304 | memcpy(&args[index], buf, data_len); |
| 291 | 305 | |
| 292 | − ret = __i2c_hid_command(client, &hid_set_report_cmd, reportID, | |
| 306 | + ret = __i2c_hid_command(client, hidcmd, reportID, | |
| 293 | 307 | reportType, args, args_len, NULL, 0); |
| 294 | 308 | if (ret) { |
| 295 | 309 | dev_err(&client->dev, "failed to set a report to device.\n"); |
| @@ -506,11 +506,15 @@ struct input_keymap_entry { · 505 unmodified lines | ||
| 506 | 506 | #define BTN_DEAD 0x12f |
| 507 | 507 | |
| 508 | 508 | #define BTN_GAMEPAD 0x130 |
| 509 | −#define BTN_A 0x130 | |
| 510 | −#define BTN_B 0x131 | |
| 509 | +#define BTN_SOUTH 0x130 | |
| 510 | +#define BTN_A BTN_SOUTH | |
| 511 | +#define BTN_EAST 0x131 | |
| 512 | +#define BTN_B BTN_EAST | |
| 511 | 513 | #define BTN_C 0x132 |
| 512 | −#define BTN_X 0x133 | |
| 513 | −#define BTN_Y 0x134 | |
| 514 | +#define BTN_NORTH 0x133 | |
| 515 | +#define BTN_X BTN_NORTH | |
| 516 | +#define BTN_WEST 0x134 | |
| 517 | +#define BTN_Y BTN_WEST | |
| 514 | 518 | #define BTN_Z 0x135 |
| 515 | 519 | #define BTN_TL 0x136 |
| 516 | 520 | #define BTN_TR 0x137 |
| @@ -707,6 +711,11 @@ struct input_keymap_entry { · 190 unmodified lines | ||
| 707 | 711 | #define KEY_ATTENDANT_TOGGLE 0x21d /* Attendant call on or off */ |
| 708 | 712 | #define KEY_LIGHTS_TOGGLE 0x21e /* Reading light on or off */ |
| 709 | 713 | |
| 714 | +#define BTN_DPAD_UP 0x220 | |
| 715 | +#define BTN_DPAD_DOWN 0x221 | |
| 716 | +#define BTN_DPAD_LEFT 0x222 | |
| 717 | +#define BTN_DPAD_RIGHT 0x223 | |
| 718 | + | |
| 710 | 719 | #define BTN_TRIGGER_HAPPY 0x2c0 |
| 711 | 720 | #define BTN_TRIGGER_HAPPY1 0x2c0 |
| 712 | 721 | #define BTN_TRIGGER_HAPPY2 0x2c1 |
| @@ -850,6 +850,29 @@ static void hidp_session_dev_del(struct hidp_session *session) · 849 unmodified lines | ||
| 850 | 850 | input_unregister_device(session->input); |
| 851 | 851 | } |
| 852 | 852 | |
| 853 | +/* | |
| 854 | + * Asynchronous device registration | |
| 855 | + * HID device drivers might want to perform I/O during initialization to | |
| 856 | + * detect device types. Therefore, call device registration in a separate | |
| 857 | + * worker so the HIDP thread can schedule I/O operations. | |
| 858 | + * Note that this must be called after the worker thread was initialized | |
| 859 | + * successfully. This will then add the devices and increase session state | |
| 860 | + * on success, otherwise it will terminate the session thread. | |
| 861 | + */ | |
| 862 | +static void hidp_session_dev_work(struct work_struct *work) | |
| 863 | +{ | |
| 864 | + struct hidp_session *session = container_of(work, | |
| 865 | + struct hidp_session, | |
| 866 | + dev_init); | |
| 867 | + int ret; | |
| 868 | + | |
| 869 | + ret = hidp_session_dev_add(session); | |
| 870 | + if (!ret) | |
| 871 | + atomic_inc(&session->state); | |
| 872 | + else | |
| 873 | + hidp_session_terminate(session); | |
| 874 | +} | |
| 875 | + | |
| 853 | 876 | /* |
| 854 | 877 | * Create new session object |
| 855 | 878 | * Allocate session object, initialize static fields, copy input data into the |
| @@ -897,6 +920,7 @@ static int hidp_session_new(struct hidp_session **out, const bdaddr_t *bdaddr, · 41 unmodified lines | ||
| 897 | 920 | session->idle_to = req->idle_to; |
| 898 | 921 | |
| 899 | 922 | /* device management */ |
| 923 | + INIT_WORK(&session->dev_init, hidp_session_dev_work); | |
| 900 | 924 | setup_timer(&session->timer, hidp_idle_timeout, |
| 901 | 925 | (unsigned long)session); |
| 902 | 926 | |
| @@ -1035,8 +1059,8 @@ static void hidp_session_terminate(struct hidp_session *session) · 132 unmodified lines | ||
| 1035 | 1059 | * Probe HIDP session |
| 1036 | 1060 | * This is called from the l2cap_conn core when our l2cap_user object is bound |
| 1037 | 1061 | * to the hci-connection. We get the session via the \user object and can now |
| 1038 | − * start the session thread, register the HID/input devices and link it into | |
| 1039 | − * the global session list. | |
| 1062 | + * start the session thread, link it into the global session list and | |
| 1063 | + * schedule HID/input device registration. | |
| 1040 | 1064 | * The global session-list owns its own reference to the session object so you |
| 1041 | 1065 | * can drop your own reference after registering the l2cap_user object. |
| 1042 | 1066 | */ |
| @@ -1058,21 +1082,30 @@ static int hidp_session_probe(struct l2cap_conn *conn, · 15 unmodified lines | ||
| 1058 | 1082 | goto out_unlock; |
| 1059 | 1083 | } |
| 1060 | 1084 | |
| 1085 | + if (session->input) { | |
| 1086 | + ret = hidp_session_dev_add(session); | |
| 1087 | + if (ret) | |
| 1088 | + goto out_unlock; | |
| 1089 | + } | |
| 1090 | + | |
| 1061 | 1091 | ret = hidp_session_start_sync(session); |
| 1062 | 1092 | if (ret) |
| 1063 | − goto out_unlock; | |
| 1093 | + goto out_del; | |
| 1064 | 1094 | |
| 1065 | − ret = hidp_session_dev_add(session); | |
| 1066 | − if (ret) | |
| 1067 | − goto out_stop; | |
| 1095 | + /* HID device registration is async to allow I/O during probe */ | |
| 1096 | + if (session->input) | |
| 1097 | + atomic_inc(&session->state); | |
| 1098 | + else | |
| 1099 | + schedule_work(&session->dev_init); | |
| 1068 | 1100 | |
| 1069 | 1101 | hidp_session_get(session); |
| 1070 | 1102 | list_add(&session->list, &hidp_session_list); |
| 1071 | 1103 | ret = 0; |
| 1072 | 1104 | goto out_unlock; |
| 1073 | 1105 | |
| 1074 | −out_stop: | |
| 1075 | − hidp_session_terminate(session); | |
| 1106 | +out_del: | |
| 1107 | + if (session->input) | |
| 1108 | + hidp_session_dev_del(session); | |
| 1076 | 1109 | out_unlock: |
| 1077 | 1110 | up_write(&hidp_session_sem); |
| 1078 | 1111 | return ret; |
| @@ -1102,7 +1135,12 @@ static void hidp_session_remove(struct l2cap_conn *conn, · 23 unmodified lines | ||
| 1102 | 1135 | down_write(&hidp_session_sem); |
| 1103 | 1136 | |
| 1104 | 1137 | hidp_session_terminate(session); |
| 1105 | − hidp_session_dev_del(session); | |
| 1138 | + | |
| 1139 | + cancel_work_sync(&session->dev_init); | |
| 1140 | + if (session->input || | |
| 1141 | + atomic_read(&session->state) > HIDP_SESSION_PREPARING) | |
| 1142 | + hidp_session_dev_del(session); | |
| 1143 | + | |
| 1106 | 1144 | list_del(&session->list); |
| 1107 | 1145 | |
| 1108 | 1146 | up_write(&hidp_session_sem); |
| @@ -128,6 +128,7 @@ int hidp_get_conninfo(struct hidp_conninfo *ci); · 127 unmodified lines | ||
| 128 | 128 | |
| 129 | 129 | enum hidp_session_state { |
| 130 | 130 | HIDP_SESSION_IDLING, |
| 131 | + HIDP_SESSION_PREPARING, | |
| 131 | 132 | HIDP_SESSION_RUNNING, |
| 132 | 133 | }; |
| 133 | 134 | |
| @@ -156,6 +157,7 @@ struct hidp_session { · 22 unmodified lines | ||
| 156 | 157 | unsigned long idle_to; |
| 157 | 158 | |
| 158 | 159 | /* device management */ |
| 160 | + struct work_struct dev_init; | |
| 159 | 161 | struct input_dev *input; |
| 160 | 162 | struct hid_device *hid; |
| 161 | 163 | struct timer_list timer; |