linux/drivers/hid/hid-sony.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  HID driver for Sony / PS2 / PS3 / PS4 BD devices.
 *
 *  Copyright (c) 1999 Andreas Gal
 *  Copyright (c) 2000-2005 Vojtech Pavlik <[email protected]>
 *  Copyright (c) 2005 Michael Haboustak <[email protected]> for Concept2, Inc
 *  Copyright (c) 2008 Jiri Slaby
 *  Copyright (c) 2012 David Dillow <[email protected]>
 *  Copyright (c) 2006-2013 Jiri Kosina
 *  Copyright (c) 2013 Colin Leitner <[email protected]>
 *  Copyright (c) 2014-2016 Frank Praznik <[email protected]>
 *  Copyright (c) 2018 Todd Kelner
 *  Copyright (c) 2020-2021 Pascal Giard <[email protected]>
 *  Copyright (c) 2020 Sanjay Govind <[email protected]>
 *  Copyright (c) 2021 Daniel Nguyen <[email protected]>
 */

/*
 */

/*
 * NOTE: in order for the Sony PS3 BD Remote Control to be found by
 * a Bluetooth host, the key combination Start+Enter has to be kept pressed
 * for about 7 seconds with the Bluetooth Host Controller in discovering mode.
 *
 * There will be no PIN request from the device.
 */

#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/leds.h>
#include <linux/power_supply.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/idr.h>
#include <linux/input/mt.h>
#include <linux/crc32.h>
#include <linux/usb.h>
#include <linux/timer.h>
#include <asm/unaligned.h>

#include "hid-ids.h"

#define VAIO_RDESC_CONSTANT
#define SIXAXIS_CONTROLLER_USB
#define SIXAXIS_CONTROLLER_BT
#define BUZZ_CONTROLLER
#define PS3REMOTE
#define MOTION_CONTROLLER_USB
#define MOTION_CONTROLLER_BT
#define NAVIGATION_CONTROLLER_USB
#define NAVIGATION_CONTROLLER_BT
#define SINO_LITE_CONTROLLER
#define FUTUREMAX_DANCE_MAT
#define NSG_MR5U_REMOTE_BT
#define NSG_MR7U_REMOTE_BT
#define SHANWAN_GAMEPAD
#define GH_GUITAR_CONTROLLER
#define GHL_GUITAR_PS3WIIU
#define GHL_GUITAR_PS4

#define SIXAXIS_CONTROLLER
#define MOTION_CONTROLLER
#define NAVIGATION_CONTROLLER
#define SONY_LED_SUPPORT
#define SONY_BATTERY_SUPPORT
#define SONY_FF_SUPPORT
#define SONY_BT_DEVICE
#define NSG_MRXU_REMOTE

#define MAX_LEDS
#define NSG_MRXU_MAX_X
#define NSG_MRXU_MAX_Y

/* The PS3/Wii U dongles require a poke every 10 seconds, but the PS4
 * requires one every 8 seconds. Using 8 seconds for all for simplicity.
 */
#define GHL_GUITAR_POKE_INTERVAL
#define GUITAR_TILT_USAGE

/* Magic data taken from GHLtarUtility:
 * https://github.com/ghlre/GHLtarUtility/blob/master/PS3Guitar.cs
 * Note: The Wii U and PS3 dongles happen to share the same!
 */
static const char ghl_ps3wiiu_magic_data[] =;

/* Magic data for the PS4 dongles sniffed with a USB protocol
 * analyzer.
 */
static const char ghl_ps4_magic_data[] =;

/* PS/3 Motion controller */
static u8 motion_rdesc[] =;

static u8 ps3remote_rdesc[] =;

static const unsigned int ps3remote_keymap_joypad_buttons[] =;
static const unsigned int ps3remote_keymap_remote_buttons[] =;

static const unsigned int buzz_keymap[] =;

/* The Navigation controller is a partial DS3 and uses the same HID report
 * and hence the same keymap indices, however not all axes/buttons
 * are physically present. We use the same axis and button mapping as
 * the DS3, which uses the Linux gamepad spec.
 */
static const unsigned int navigation_absmap[] =;

/* Buttons not physically available on the device, but still available
 * in the reports are explicitly set to 0 for documentation purposes.
 */
static const unsigned int navigation_keymap[] =;

static const unsigned int sixaxis_absmap[] =;

static const unsigned int sixaxis_keymap[] =;

static enum power_supply_property sony_battery_props[] =;

struct sixaxis_led {} __packed;

struct sixaxis_rumble {} __packed;

struct sixaxis_output_report {} __packed;

sixaxis_output_report_01;

struct motion_output_report_02 {};

#define SIXAXIS_REPORT_0xF2_SIZE
#define SIXAXIS_REPORT_0xF5_SIZE
#define MOTION_REPORT_0x02_SIZE

#define SENSOR_SUFFIX
#define TOUCHPAD_SUFFIX

#define SIXAXIS_INPUT_REPORT_ACC_X_OFFSET
#define SIXAXIS_ACC_RES_PER_G

static DEFINE_SPINLOCK(sony_dev_list_lock);
static LIST_HEAD(sony_device_list);
static DEFINE_IDA(sony_device_id_allocator);

enum sony_worker {};

struct sony_sc {};

static void sony_set_leds(struct sony_sc *sc);

static inline void sony_schedule_work(struct sony_sc *sc,
				      enum sony_worker which)
{}

static void ghl_magic_poke_cb(struct urb *urb)
{}

static void ghl_magic_poke(struct timer_list *t)
{}

static int ghl_init_urb(struct sony_sc *sc, struct usb_device *usbdev,
					   const char ghl_magic_data[], u16 poke_size)
{}

static int guitar_mapping(struct hid_device *hdev, struct hid_input *hi,
			  struct hid_field *field, struct hid_usage *usage,
			  unsigned long **bit, int *max)
{}

static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc,
			     unsigned int *rsize)
{}

static u8 *ps3remote_fixup(struct hid_device *hdev, u8 *rdesc,
			     unsigned int *rsize)
{}

static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
			     struct hid_field *field, struct hid_usage *usage,
			     unsigned long **bit, int *max)
{}

static int navigation_mapping(struct hid_device *hdev, struct hid_input *hi,
			  struct hid_field *field, struct hid_usage *usage,
			  unsigned long **bit, int *max)
{}


static int sixaxis_mapping(struct hid_device *hdev, struct hid_input *hi,
			  struct hid_field *field, struct hid_usage *usage,
			  unsigned long **bit, int *max)
{}

static u8 *sony_report_fixup(struct hid_device *hdev, u8 *rdesc,
		unsigned int *rsize)
{}

static void sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size)
{}

static void nsg_mrxu_parse_report(struct sony_sc *sc, u8 *rd, int size)
{}

static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
		u8 *rd, int size)
{}

static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
			struct hid_field *field, struct hid_usage *usage,
			unsigned long **bit, int *max)
{}

static int sony_register_touchpad(struct sony_sc *sc, int touch_count,
		int w, int h, int touch_major, int touch_minor, int orientation)
{}

static int sony_register_sensors(struct sony_sc *sc)
{}

/*
 * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
 * to "operational".  Without this, the ps3 controller will not report any
 * events.
 */
static int sixaxis_set_operational_usb(struct hid_device *hdev)
{}

static int sixaxis_set_operational_bt(struct hid_device *hdev)
{}

static void sixaxis_set_leds_from_id(struct sony_sc *sc)
{}

static void buzz_set_leds(struct sony_sc *sc)
{}

static void sony_set_leds(struct sony_sc *sc)
{}

static void sony_led_set_brightness(struct led_classdev *led,
				    enum led_brightness value)
{}

static enum led_brightness sony_led_get_brightness(struct led_classdev *led)
{}

static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on,
				unsigned long *delay_off)
{}

static int sony_leds_init(struct sony_sc *sc)
{}

static void sixaxis_send_output_report(struct sony_sc *sc)
{}

static void motion_send_output_report(struct sony_sc *sc)
{}

#ifdef CONFIG_SONY_FF
static inline void sony_send_output_report(struct sony_sc *sc)
{}
#endif

static void sony_state_worker(struct work_struct *work)
{}

static int sony_allocate_output_report(struct sony_sc *sc)
{}

#ifdef CONFIG_SONY_FF
static int sony_play_effect(struct input_dev *dev, void *data,
			    struct ff_effect *effect)
{}

static int sony_init_ff(struct sony_sc *sc)
{}

#else
static int sony_init_ff(struct sony_sc *sc)
{
	return 0;
}

#endif

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

static int sony_battery_probe(struct sony_sc *sc, int append_dev_id)
{}

/*
 * If a controller is plugged in via USB while already connected via Bluetooth
 * it will show up as two devices. A global list of connected controllers and
 * their MAC addresses is maintained to ensure that a device is only connected
 * once.
 *
 * Some USB-only devices masquerade as Sixaxis controllers and all have the
 * same dummy Bluetooth address, so a comparison of the connection type is
 * required.  Devices are only rejected in the case where two devices have
 * matching Bluetooth addresses on different bus types.
 */
static inline int sony_compare_connection_type(struct sony_sc *sc0,
						struct sony_sc *sc1)
{}

static int sony_check_add_dev_list(struct sony_sc *sc)
{}

static void sony_remove_dev_list(struct sony_sc *sc)
{}

static int sony_get_bt_devaddr(struct sony_sc *sc)
{}

static int sony_check_add(struct sony_sc *sc)
{}

static int sony_set_device_id(struct sony_sc *sc)
{}

static void sony_release_device_id(struct sony_sc *sc)
{}

static inline void sony_init_output_report(struct sony_sc *sc,
				void (*send_output_report)(struct sony_sc *))
{}

static inline void sony_cancel_work_sync(struct sony_sc *sc)
{}

static int sony_input_configured(struct hid_device *hdev,
					struct hid_input *hidinput)
{}

static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
{}

static void sony_remove(struct hid_device *hdev)
{}

#ifdef CONFIG_PM

static int sony_suspend(struct hid_device *hdev, pm_message_t message)
{}

static int sony_resume(struct hid_device *hdev)
{}

#endif

static const struct hid_device_id sony_devices[] =;
MODULE_DEVICE_TABLE(hid, sony_devices);

static struct hid_driver sony_driver =;

static int __init sony_init(void)
{}

static void __exit sony_exit(void)
{}
module_init();
module_exit(sony_exit);

MODULE_DESCRIPTION();
MODULE_LICENSE();