linux/drivers/hid/hid-wiimote-modules.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Device Modules for Nintendo Wii / Wii U HID Driver
 * Copyright (c) 2011-2013 David Herrmann <[email protected]>
 */

/*
 */

/*
 * Wiimote Modules
 * Nintendo devices provide different peripherals and many new devices lack
 * initial features like the IR camera. Therefore, each peripheral device is
 * implemented as an independent module and we probe on each device only the
 * modules for the hardware that really is available.
 *
 * Module registration is sequential. Unregistration is done in reverse order.
 * After device detection, the needed modules are loaded. Users can trigger
 * re-detection which causes all modules to be unloaded and then reload the
 * modules for the new detected device.
 *
 * wdata->input is a shared input device. It is always initialized prior to
 * module registration. If at least one registered module is marked as
 * WIIMOD_FLAG_INPUT, then the input device will get registered after all
 * modules were registered.
 * Please note that it is unregistered _before_ the "remove" callbacks are
 * called. This guarantees that no input interaction is done, anymore. However,
 * the wiimote core keeps a reference to the input device so it is freed only
 * after all modules were removed. It is safe to send events to unregistered
 * input devices.
 */

#include <linux/device.h>
#include <linux/hid.h>
#include <linux/input.h>
#include <linux/spinlock.h>
#include "hid-wiimote.h"

/*
 * Keys
 * The initial Wii Remote provided a bunch of buttons that are reported as
 * part of the core protocol. Many later devices dropped these and report
 * invalid data in the core button reports. Load this only on devices which
 * correctly send button reports.
 * It uses the shared input device.
 */

static const __u16 wiimod_keys_map[] =;

static void wiimod_keys_in_keys(struct wiimote_data *wdata, const __u8 *keys)
{}

static int wiimod_keys_probe(const struct wiimod_ops *ops,
			     struct wiimote_data *wdata)
{}

static const struct wiimod_ops wiimod_keys =;

/*
 * Rumble
 * Nearly all devices provide a rumble feature. A small motor for
 * force-feedback effects. We provide an FF_RUMBLE memless ff device on the
 * shared input device if this module is loaded.
 * The rumble motor is controlled via a flag on almost every output report so
 * the wiimote core handles the rumble flag. But if a device doesn't provide
 * the rumble motor, this flag shouldn't be set.
 */

/* used by wiimod_rumble and wiipro_rumble */
static void wiimod_rumble_worker(struct work_struct *work)
{}

static int wiimod_rumble_play(struct input_dev *dev, void *data,
			      struct ff_effect *eff)
{}

static int wiimod_rumble_probe(const struct wiimod_ops *ops,
			       struct wiimote_data *wdata)
{}

static void wiimod_rumble_remove(const struct wiimod_ops *ops,
				 struct wiimote_data *wdata)
{}

static const struct wiimod_ops wiimod_rumble =;

/*
 * Battery
 * 1 byte of battery capacity information is sent along every protocol status
 * report. The wiimote core caches it but we try to update it on every
 * user-space request.
 * This is supported by nearly every device so it's almost always enabled.
 */

static enum power_supply_property wiimod_battery_props[] =;

static int wiimod_battery_get_property(struct power_supply *psy,
				       enum power_supply_property psp,
				       union power_supply_propval *val)
{}

static int wiimod_battery_probe(const struct wiimod_ops *ops,
				struct wiimote_data *wdata)
{}

static void wiimod_battery_remove(const struct wiimod_ops *ops,
				  struct wiimote_data *wdata)
{}

static const struct wiimod_ops wiimod_battery =;

/*
 * LED
 * 0 to 4 player LEDs are supported by devices. The "arg" field of the
 * wiimod_ops structure specifies which LED this module controls. This allows
 * to register a limited number of LEDs.
 * State is managed by wiimote core.
 */

static enum led_brightness wiimod_led_get(struct led_classdev *led_dev)
{}

static void wiimod_led_set(struct led_classdev *led_dev,
			   enum led_brightness value)
{}

static int wiimod_led_probe(const struct wiimod_ops *ops,
			    struct wiimote_data *wdata)
{}

static void wiimod_led_remove(const struct wiimod_ops *ops,
			      struct wiimote_data *wdata)
{}

static const struct wiimod_ops wiimod_leds[4] =;

/*
 * Accelerometer
 * 3 axis accelerometer data is part of nearly all DRMs. If not supported by a
 * device, it's mostly cleared to 0. This module parses this data and provides
 * it via a separate input device.
 */

static void wiimod_accel_in_accel(struct wiimote_data *wdata,
				  const __u8 *accel)
{}

static int wiimod_accel_open(struct input_dev *dev)
{}

static void wiimod_accel_close(struct input_dev *dev)
{}

static int wiimod_accel_probe(const struct wiimod_ops *ops,
			      struct wiimote_data *wdata)
{}

static void wiimod_accel_remove(const struct wiimod_ops *ops,
				struct wiimote_data *wdata)
{}

static const struct wiimod_ops wiimod_accel =;

/*
 * IR Cam
 * Up to 4 IR sources can be tracked by a normal Wii Remote. The IR cam needs
 * to be initialized with a fairly complex procedure and consumes a lot of
 * power. Therefore, as long as no application uses the IR input device, it is
 * kept offline.
 * Nearly no other device than the normal Wii Remotes supports the IR cam so
 * you can disable this module for these devices.
 */

static void wiimod_ir_in_ir(struct wiimote_data *wdata, const __u8 *ir,
			    bool packed, unsigned int id)
{}

static int wiimod_ir_change(struct wiimote_data *wdata, __u16 mode)
{}

static int wiimod_ir_open(struct input_dev *dev)
{}

static void wiimod_ir_close(struct input_dev *dev)
{}

static int wiimod_ir_probe(const struct wiimod_ops *ops,
			   struct wiimote_data *wdata)
{}

static void wiimod_ir_remove(const struct wiimod_ops *ops,
			     struct wiimote_data *wdata)
{}

static const struct wiimod_ops wiimod_ir =;

/*
 * Nunchuk Extension
 * The Nintendo Wii Nunchuk was the first official extension published by
 * Nintendo. It provides two additional keys and a separate accelerometer. It
 * can be hotplugged to standard Wii Remotes.
 */

enum wiimod_nunchuk_keys {};

static const __u16 wiimod_nunchuk_map[] =;

static void wiimod_nunchuk_in_ext(struct wiimote_data *wdata, const __u8 *ext)
{}

static int wiimod_nunchuk_open(struct input_dev *dev)
{}

static void wiimod_nunchuk_close(struct input_dev *dev)
{}

static int wiimod_nunchuk_probe(const struct wiimod_ops *ops,
				struct wiimote_data *wdata)
{}

static void wiimod_nunchuk_remove(const struct wiimod_ops *ops,
				  struct wiimote_data *wdata)
{}

static const struct wiimod_ops wiimod_nunchuk =;

/*
 * Classic Controller
 * Another official extension from Nintendo. It provides a classic
 * gamecube-like controller that can be hotplugged on the Wii Remote.
 * It has several hardware buttons and switches that are all reported via
 * a normal extension device.
 */

enum wiimod_classic_keys {};

static const __u16 wiimod_classic_map[] =;

static void wiimod_classic_in_ext(struct wiimote_data *wdata, const __u8 *ext)
{}

static int wiimod_classic_open(struct input_dev *dev)
{}

static void wiimod_classic_close(struct input_dev *dev)
{}

static int wiimod_classic_probe(const struct wiimod_ops *ops,
				struct wiimote_data *wdata)
{}

static void wiimod_classic_remove(const struct wiimod_ops *ops,
				  struct wiimote_data *wdata)
{}

static const struct wiimod_ops wiimod_classic =;

/*
 * Balance Board Extension
 * The Nintendo Wii Balance Board provides four hardware weight sensor plus a
 * single push button. No other peripherals are available. However, the
 * balance-board data is sent via a standard Wii Remote extension. All other
 * data for non-present hardware is zeroed out.
 * Some 3rd party devices react allergic if we try to access normal Wii Remote
 * hardware, so this extension module should be the only module that is loaded
 * on balance boards.
 * The balance board needs 8 bytes extension data instead of basic 6 bytes so
 * it needs the WIIMOD_FLAG_EXT8 flag.
 */

static void wiimod_bboard_in_keys(struct wiimote_data *wdata, const __u8 *keys)
{}

static void wiimod_bboard_in_ext(struct wiimote_data *wdata,
				 const __u8 *ext)
{}

static int wiimod_bboard_open(struct input_dev *dev)
{}

static void wiimod_bboard_close(struct input_dev *dev)
{}

static ssize_t wiimod_bboard_calib_show(struct device *dev,
					struct device_attribute *attr,
					char *out)
{}

static DEVICE_ATTR(bboard_calib, S_IRUGO, wiimod_bboard_calib_show, NULL);

static int wiimod_bboard_probe(const struct wiimod_ops *ops,
			       struct wiimote_data *wdata)
{}

static void wiimod_bboard_remove(const struct wiimod_ops *ops,
				 struct wiimote_data *wdata)
{}

static const struct wiimod_ops wiimod_bboard =;

/*
 * Pro Controller
 * Released with the Wii U was the Nintendo Wii U Pro Controller. It does not
 * work together with the classic Wii, but only with the new Wii U. However, it
 * uses the same protocol and provides a builtin "classic controller pro"
 * extension, few standard buttons, a rumble motor, 4 LEDs and a battery.
 * We provide all these via a standard extension device as the device doesn't
 * feature an extension port.
 */

enum wiimod_pro_keys {};

static const __u16 wiimod_pro_map[] =;

static void wiimod_pro_in_ext(struct wiimote_data *wdata, const __u8 *ext)
{}

static int wiimod_pro_open(struct input_dev *dev)
{}

static void wiimod_pro_close(struct input_dev *dev)
{}

static int wiimod_pro_play(struct input_dev *dev, void *data,
			   struct ff_effect *eff)
{}

static ssize_t wiimod_pro_calib_show(struct device *dev,
				     struct device_attribute *attr,
				     char *out)
{}

static ssize_t wiimod_pro_calib_store(struct device *dev,
				      struct device_attribute *attr,
				      const char *buf, size_t count)
{}

static DEVICE_ATTR(pro_calib, S_IRUGO|S_IWUSR|S_IWGRP, wiimod_pro_calib_show,
		   wiimod_pro_calib_store);

static int wiimod_pro_probe(const struct wiimod_ops *ops,
			    struct wiimote_data *wdata)
{}

static void wiimod_pro_remove(const struct wiimod_ops *ops,
			      struct wiimote_data *wdata)
{}

static const struct wiimod_ops wiimod_pro =;

/*
 * Drums
 * Guitar-Hero, Rock-Band and other games came bundled with drums which can
 * be plugged as extension to a Wiimote. Drum-reports are still not entirely
 * figured out, but the most important information is known.
 * We create a separate device for drums and report all information via this
 * input device.
 */

static inline void wiimod_drums_report_pressure(struct wiimote_data *wdata,
						__u8 none, __u8 which,
						__u8 pressure, __u8 onoff,
						__u8 *store, __u16 code,
						__u8 which_code)
{}

static void wiimod_drums_in_ext(struct wiimote_data *wdata, const __u8 *ext)
{}

static int wiimod_drums_open(struct input_dev *dev)
{}

static void wiimod_drums_close(struct input_dev *dev)
{}

static int wiimod_drums_probe(const struct wiimod_ops *ops,
			      struct wiimote_data *wdata)
{}

static void wiimod_drums_remove(const struct wiimod_ops *ops,
				struct wiimote_data *wdata)
{}

static const struct wiimod_ops wiimod_drums =;

/*
 * Guitar
 * Guitar-Hero, Rock-Band and other games came bundled with guitars which can
 * be plugged as extension to a Wiimote.
 * We create a separate device for guitars and report all information via this
 * input device.
 */

enum wiimod_guitar_keys {};

static const __u16 wiimod_guitar_map[] =;

static void wiimod_guitar_in_ext(struct wiimote_data *wdata, const __u8 *ext)
{}

static int wiimod_guitar_open(struct input_dev *dev)
{}

static void wiimod_guitar_close(struct input_dev *dev)
{}

static int wiimod_guitar_probe(const struct wiimod_ops *ops,
			       struct wiimote_data *wdata)
{}

static void wiimod_guitar_remove(const struct wiimod_ops *ops,
				 struct wiimote_data *wdata)
{}

static const struct wiimod_ops wiimod_guitar =;

/* 
 * Turntable
 * DJ Hero came with a Turntable Controller that was plugged in
 * as an extension.
 * We create a separate device for turntables and report all information via this
 * input device.
*/

enum wiimod_turntable_keys {};

static const __u16 wiimod_turntable_map[] =;

static void wiimod_turntable_in_ext(struct wiimote_data *wdata, const __u8 *ext)
{}

static int wiimod_turntable_open(struct input_dev *dev)
{}

static void wiimod_turntable_close(struct input_dev *dev)
{}

static int wiimod_turntable_probe(const struct wiimod_ops *ops,
			       struct wiimote_data *wdata)
{}

static void wiimod_turntable_remove(const struct wiimod_ops *ops,
				 struct wiimote_data *wdata)
{}

static const struct wiimod_ops wiimod_turntable =;

/*
 * Builtin Motion Plus
 * This module simply sets the WIIPROTO_FLAG_BUILTIN_MP protocol flag which
 * disables polling for Motion-Plus. This should be set only for devices which
 * don't allow MP hotplugging.
 */

static int wiimod_builtin_mp_probe(const struct wiimod_ops *ops,
				   struct wiimote_data *wdata)
{}

static void wiimod_builtin_mp_remove(const struct wiimod_ops *ops,
				     struct wiimote_data *wdata)
{}

static const struct wiimod_ops wiimod_builtin_mp =;

/*
 * No Motion Plus
 * This module simply sets the WIIPROTO_FLAG_NO_MP protocol flag which
 * disables motion-plus. This is needed for devices that advertise this but we
 * don't know how to use it (or whether it is actually present).
 */

static int wiimod_no_mp_probe(const struct wiimod_ops *ops,
			      struct wiimote_data *wdata)
{}

static void wiimod_no_mp_remove(const struct wiimod_ops *ops,
				struct wiimote_data *wdata)
{}

static const struct wiimod_ops wiimod_no_mp =;

/*
 * Motion Plus
 * The Motion Plus extension provides rotation sensors (gyro) as a small
 * extension device for Wii Remotes. Many devices have them built-in so
 * you cannot see them from the outside.
 * Motion Plus extensions are special because they are on a separate extension
 * port and allow other extensions to be used simultaneously. This is all
 * handled by the Wiimote Core so we don't have to deal with it.
 */

static void wiimod_mp_in_mp(struct wiimote_data *wdata, const __u8 *ext)
{}

static int wiimod_mp_open(struct input_dev *dev)
{}

static void wiimod_mp_close(struct input_dev *dev)
{}

static int wiimod_mp_probe(const struct wiimod_ops *ops,
			   struct wiimote_data *wdata)
{}

static void wiimod_mp_remove(const struct wiimod_ops *ops,
			     struct wiimote_data *wdata)
{}

const struct wiimod_ops wiimod_mp =;

/* module table */

static const struct wiimod_ops wiimod_dummy;

const struct wiimod_ops *wiimod_table[WIIMOD_NUM] =;

const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM] =;