linux/drivers/hid/hid-logitech-hidpp.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 *  HIDPP protocol for Logitech receivers
 *
 *  Copyright (c) 2011 Logitech (c)
 *  Copyright (c) 2012-2013 Google (c)
 *  Copyright (c) 2013-2014 Red Hat Inc.
 */


#define pr_fmt(fmt)

#include <linux/device.h>
#include <linux/input.h>
#include <linux/usb.h>
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/sched/clock.h>
#include <linux/kfifo.h>
#include <linux/input/mt.h>
#include <linux/workqueue.h>
#include <linux/atomic.h>
#include <linux/fixp-arith.h>
#include <asm/unaligned.h>
#include "usbhid/usbhid.h"
#include "hid-ids.h"

MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_AUTHOR();

static bool disable_tap_to_click;
module_param(disable_tap_to_click, bool, 0644);
MODULE_PARM_DESC();

/* Define a non-zero software ID to identify our own requests */
#define LINUX_KERNEL_SW_ID

#define REPORT_ID_HIDPP_SHORT
#define REPORT_ID_HIDPP_LONG
#define REPORT_ID_HIDPP_VERY_LONG

#define HIDPP_REPORT_SHORT_LENGTH
#define HIDPP_REPORT_LONG_LENGTH
#define HIDPP_REPORT_VERY_LONG_MAX_LENGTH

#define HIDPP_REPORT_SHORT_SUPPORTED
#define HIDPP_REPORT_LONG_SUPPORTED
#define HIDPP_REPORT_VERY_LONG_SUPPORTED

#define HIDPP_SUB_ID_CONSUMER_VENDOR_KEYS
#define HIDPP_SUB_ID_ROLLER
#define HIDPP_SUB_ID_MOUSE_EXTRA_BTNS
#define HIDPP_SUB_ID_USER_IFACE_EVENT
#define HIDPP_USER_IFACE_EVENT_ENCRYPTION_KEY_LOST

#define HIDPP_QUIRK_CLASS_WTP
#define HIDPP_QUIRK_CLASS_M560
#define HIDPP_QUIRK_CLASS_K400
#define HIDPP_QUIRK_CLASS_G920
#define HIDPP_QUIRK_CLASS_K750

/* bits 2..20 are reserved for classes */
/* #define HIDPP_QUIRK_CONNECT_EVENTS		BIT(21) disabled */
#define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS
#define HIDPP_QUIRK_DELAYED_INIT
#define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS
#define HIDPP_QUIRK_HIDPP_WHEELS
#define HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS
#define HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS
#define HIDPP_QUIRK_HI_RES_SCROLL_1P0
#define HIDPP_QUIRK_WIRELESS_STATUS

/* These are just aliases for now */
#define HIDPP_QUIRK_KBD_SCROLL_WHEEL
#define HIDPP_QUIRK_KBD_ZOOM_WHEEL

/* Convenience constant to check for any high-res support. */
#define HIDPP_CAPABILITY_HI_RES_SCROLL

#define HIDPP_CAPABILITY_HIDPP10_BATTERY
#define HIDPP_CAPABILITY_HIDPP20_BATTERY
#define HIDPP_CAPABILITY_BATTERY_MILEAGE
#define HIDPP_CAPABILITY_BATTERY_LEVEL_STATUS
#define HIDPP_CAPABILITY_BATTERY_VOLTAGE
#define HIDPP_CAPABILITY_BATTERY_PERCENTAGE
#define HIDPP_CAPABILITY_UNIFIED_BATTERY
#define HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL
#define HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL
#define HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL
#define HIDPP_CAPABILITY_ADC_MEASUREMENT

#define lg_map_key_clear(c)

/*
 * There are two hidpp protocols in use, the first version hidpp10 is known
 * as register access protocol or RAP, the second version hidpp20 is known as
 * feature access protocol or FAP
 *
 * Most older devices (including the Unifying usb receiver) use the RAP protocol
 * where as most newer devices use the FAP protocol. Both protocols are
 * compatible with the underlying transport, which could be usb, Unifiying, or
 * bluetooth. The message lengths are defined by the hid vendor specific report
 * descriptor for the HIDPP_SHORT report type (total message lenth 7 bytes) and
 * the HIDPP_LONG report type (total message length 20 bytes)
 *
 * The RAP protocol uses both report types, whereas the FAP only uses HIDPP_LONG
 * messages. The Unifying receiver itself responds to RAP messages (device index
 * is 0xFF for the receiver), and all messages (short or long) with a device
 * index between 1 and 6 are passed untouched to the corresponding paired
 * Unifying device.
 *
 * The paired device can be RAP or FAP, it will receive the message untouched
 * from the Unifiying receiver.
 */

struct fap {};

struct rap {};

struct hidpp_report {} __packed;

struct hidpp_battery {};

/**
 * struct hidpp_scroll_counter - Utility class for processing high-resolution
 *                             scroll events.
 * @dev: the input device for which events should be reported.
 * @wheel_multiplier: the scalar multiplier to be applied to each wheel event
 * @remainder: counts the number of high-resolution units moved since the last
 *             low-resolution event (REL_WHEEL or REL_HWHEEL) was sent. Should
 *             only be used by class methods.
 * @direction: direction of last movement (1 or -1)
 * @last_time: last event time, used to reset remainder after inactivity
 */
struct hidpp_scroll_counter {};

struct hidpp_device {};

/* HID++ 1.0 error codes */
#define HIDPP_ERROR
#define HIDPP_ERROR_SUCCESS
#define HIDPP_ERROR_INVALID_SUBID
#define HIDPP_ERROR_INVALID_ADRESS
#define HIDPP_ERROR_INVALID_VALUE
#define HIDPP_ERROR_CONNECT_FAIL
#define HIDPP_ERROR_TOO_MANY_DEVICES
#define HIDPP_ERROR_ALREADY_EXISTS
#define HIDPP_ERROR_BUSY
#define HIDPP_ERROR_UNKNOWN_DEVICE
#define HIDPP_ERROR_RESOURCE_ERROR
#define HIDPP_ERROR_REQUEST_UNAVAILABLE
#define HIDPP_ERROR_INVALID_PARAM_VALUE
#define HIDPP_ERROR_WRONG_PIN_CODE
/* HID++ 2.0 error codes */
#define HIDPP20_ERROR_NO_ERROR
#define HIDPP20_ERROR_UNKNOWN
#define HIDPP20_ERROR_INVALID_ARGS
#define HIDPP20_ERROR_OUT_OF_RANGE
#define HIDPP20_ERROR_HW_ERROR
#define HIDPP20_ERROR_NOT_ALLOWED
#define HIDPP20_ERROR_INVALID_FEATURE_INDEX
#define HIDPP20_ERROR_INVALID_FUNCTION_ID
#define HIDPP20_ERROR_BUSY
#define HIDPP20_ERROR_UNSUPPORTED
#define HIDPP20_ERROR

static int __hidpp_send_report(struct hid_device *hdev,
				struct hidpp_report *hidpp_report)
{}

/*
 * Effectively send the message to the device, waiting for its answer.
 *
 * Must be called with hidpp->send_mutex locked
 *
 * Same return protocol than hidpp_send_message_sync():
 * - success on 0
 * - negative error means transport error
 * - positive value means protocol error
 */
static int __do_hidpp_send_message_sync(struct hidpp_device *hidpp,
	struct hidpp_report *message,
	struct hidpp_report *response)
{}

/*
 * hidpp_send_message_sync() returns 0 in case of success, and something else
 * in case of a failure.
 *
 * See __do_hidpp_send_message_sync() for a detailed explanation of the returned
 * value.
 */
static int hidpp_send_message_sync(struct hidpp_device *hidpp,
	struct hidpp_report *message,
	struct hidpp_report *response)
{}

/*
 * hidpp_send_fap_command_sync() returns 0 in case of success, and something else
 * in case of a failure.
 *
 * See __do_hidpp_send_message_sync() for a detailed explanation of the returned
 * value.
 */
static int hidpp_send_fap_command_sync(struct hidpp_device *hidpp,
	u8 feat_index, u8 funcindex_clientid, u8 *params, int param_count,
	struct hidpp_report *response)
{}

/*
 * hidpp_send_rap_command_sync() returns 0 in case of success, and something else
 * in case of a failure.
 *
 * See __do_hidpp_send_message_sync() for a detailed explanation of the returned
 * value.
 */
static int hidpp_send_rap_command_sync(struct hidpp_device *hidpp_dev,
	u8 report_id, u8 sub_id, u8 reg_address, u8 *params, int param_count,
	struct hidpp_report *response)
{}

static inline bool hidpp_match_answer(struct hidpp_report *question,
		struct hidpp_report *answer)
{}

static inline bool hidpp_match_error(struct hidpp_report *question,
		struct hidpp_report *answer)
{}

static inline bool hidpp_report_is_connect_event(struct hidpp_device *hidpp,
		struct hidpp_report *report)
{}

/*
 * hidpp_prefix_name() prefixes the current given name with "Logitech ".
 */
static void hidpp_prefix_name(char **name, int name_length)
{}

/*
 * Updates the USB wireless_status based on whether the headset
 * is turned on and reachable.
 */
static void hidpp_update_usb_wireless_status(struct hidpp_device *hidpp)
{}

/**
 * hidpp_scroll_counter_handle_scroll() - Send high- and low-resolution scroll
 *                                        events given a high-resolution wheel
 *                                        movement.
 * @input_dev: Pointer to the input device
 * @counter: a hid_scroll_counter struct describing the wheel.
 * @hi_res_value: the movement of the wheel, in the mouse's high-resolution
 *                units.
 *
 * Given a high-resolution movement, this function converts the movement into
 * fractions of 120 and emits high-resolution scroll events for the input
 * device. It also uses the multiplier from &struct hid_scroll_counter to
 * emit low-resolution scroll events when appropriate for
 * backwards-compatibility with userspace input libraries.
 */
static void hidpp_scroll_counter_handle_scroll(struct input_dev *input_dev,
					       struct hidpp_scroll_counter *counter,
					       int hi_res_value)
{}

/* -------------------------------------------------------------------------- */
/* HIDP++ 1.0 commands                                                        */
/* -------------------------------------------------------------------------- */

#define HIDPP_SET_REGISTER
#define HIDPP_GET_REGISTER
#define HIDPP_SET_LONG_REGISTER
#define HIDPP_GET_LONG_REGISTER

/**
 * hidpp10_set_register - Modify a HID++ 1.0 register.
 * @hidpp_dev: the device to set the register on.
 * @register_address: the address of the register to modify.
 * @byte: the byte of the register to modify. Should be less than 3.
 * @mask: mask of the bits to modify
 * @value: new values for the bits in mask
 * Return: 0 if successful, otherwise a negative error code.
 */
static int hidpp10_set_register(struct hidpp_device *hidpp_dev,
	u8 register_address, u8 byte, u8 mask, u8 value)
{}

#define HIDPP_REG_ENABLE_REPORTS
#define HIDPP_ENABLE_CONSUMER_REPORT
#define HIDPP_ENABLE_WHEEL_REPORT
#define HIDPP_ENABLE_MOUSE_EXTRA_BTN_REPORT
#define HIDPP_ENABLE_BAT_REPORT
#define HIDPP_ENABLE_HWHEEL_REPORT

static int hidpp10_enable_battery_reporting(struct hidpp_device *hidpp_dev)
{}

#define HIDPP_REG_FEATURES
#define HIDPP_ENABLE_SPECIAL_BUTTON_FUNC
#define HIDPP_ENABLE_FAST_SCROLL

/* On HID++ 1.0 devices, high-res scroll was called "scrolling acceleration". */
static int hidpp10_enable_scrolling_acceleration(struct hidpp_device *hidpp_dev)
{}

#define HIDPP_REG_BATTERY_STATUS

static int hidpp10_battery_status_map_level(u8 param)
{}

static int hidpp10_battery_status_map_status(u8 param)
{}

static int hidpp10_query_battery_status(struct hidpp_device *hidpp)
{}

#define HIDPP_REG_BATTERY_MILEAGE

static int hidpp10_battery_mileage_map_status(u8 param)
{}

static int hidpp10_query_battery_mileage(struct hidpp_device *hidpp)
{}

static int hidpp10_battery_event(struct hidpp_device *hidpp, u8 *data, int size)
{}

#define HIDPP_REG_PAIRING_INFORMATION
#define HIDPP_EXTENDED_PAIRING
#define HIDPP_DEVICE_NAME

static char *hidpp_unifying_get_name(struct hidpp_device *hidpp_dev)
{}

static int hidpp_unifying_get_serial(struct hidpp_device *hidpp, u32 *serial)
{}

static int hidpp_unifying_init(struct hidpp_device *hidpp)
{}

/* -------------------------------------------------------------------------- */
/* 0x0000: Root                                                               */
/* -------------------------------------------------------------------------- */

#define HIDPP_PAGE_ROOT
#define HIDPP_PAGE_ROOT_IDX

#define CMD_ROOT_GET_FEATURE
#define CMD_ROOT_GET_PROTOCOL_VERSION

static int hidpp_root_get_feature(struct hidpp_device *hidpp, u16 feature,
	u8 *feature_index, u8 *feature_type)
{}

static int hidpp_root_get_protocol_version(struct hidpp_device *hidpp)
{}

/* -------------------------------------------------------------------------- */
/* 0x0003: Device Information                                                 */
/* -------------------------------------------------------------------------- */

#define HIDPP_PAGE_DEVICE_INFORMATION

#define CMD_GET_DEVICE_INFO

static int hidpp_get_serial(struct hidpp_device *hidpp, u32 *serial)
{}

static int hidpp_serial_init(struct hidpp_device *hidpp)
{}

/* -------------------------------------------------------------------------- */
/* 0x0005: GetDeviceNameType                                                  */
/* -------------------------------------------------------------------------- */

#define HIDPP_PAGE_GET_DEVICE_NAME_TYPE

#define CMD_GET_DEVICE_NAME_TYPE_GET_COUNT
#define CMD_GET_DEVICE_NAME_TYPE_GET_DEVICE_NAME
#define CMD_GET_DEVICE_NAME_TYPE_GET_TYPE

static int hidpp_devicenametype_get_count(struct hidpp_device *hidpp,
	u8 feature_index, u8 *nameLength)
{}

static int hidpp_devicenametype_get_device_name(struct hidpp_device *hidpp,
	u8 feature_index, u8 char_index, char *device_name, int len_buf)
{}

static char *hidpp_get_device_name(struct hidpp_device *hidpp)
{}

/* -------------------------------------------------------------------------- */
/* 0x1000: Battery level status                                               */
/* -------------------------------------------------------------------------- */

#define HIDPP_PAGE_BATTERY_LEVEL_STATUS

#define CMD_BATTERY_LEVEL_STATUS_GET_BATTERY_LEVEL_STATUS
#define CMD_BATTERY_LEVEL_STATUS_GET_BATTERY_CAPABILITY

#define EVENT_BATTERY_LEVEL_STATUS_BROADCAST

#define FLAG_BATTERY_LEVEL_DISABLE_OSD
#define FLAG_BATTERY_LEVEL_MILEAGE
#define FLAG_BATTERY_LEVEL_RECHARGEABLE

static int hidpp_map_battery_level(int capacity)
{}

static int hidpp20_batterylevel_map_status_capacity(u8 data[3], int *capacity,
						    int *next_capacity,
						    int *level)
{}

static int hidpp20_batterylevel_get_battery_capacity(struct hidpp_device *hidpp,
						     u8 feature_index,
						     int *status,
						     int *capacity,
						     int *next_capacity,
						     int *level)
{}

static int hidpp20_batterylevel_get_battery_info(struct hidpp_device *hidpp,
						  u8 feature_index)
{}

static int hidpp20_query_battery_info_1000(struct hidpp_device *hidpp)
{}

static int hidpp20_battery_event_1000(struct hidpp_device *hidpp,
				 u8 *data, int size)
{}

/* -------------------------------------------------------------------------- */
/* 0x1001: Battery voltage                                                    */
/* -------------------------------------------------------------------------- */

#define HIDPP_PAGE_BATTERY_VOLTAGE

#define CMD_BATTERY_VOLTAGE_GET_BATTERY_VOLTAGE

#define EVENT_BATTERY_VOLTAGE_STATUS_BROADCAST

static int hidpp20_battery_map_status_voltage(u8 data[3], int *voltage,
						int *level, int *charge_type)
{}

static int hidpp20_battery_get_battery_voltage(struct hidpp_device *hidpp,
						 u8 feature_index,
						 int *status, int *voltage,
						 int *level, int *charge_type)
{}

static int hidpp20_map_battery_capacity(struct hid_device *hid_dev, int voltage)
{}

static int hidpp20_query_battery_voltage_info(struct hidpp_device *hidpp)
{}

static int hidpp20_battery_voltage_event(struct hidpp_device *hidpp,
					    u8 *data, int size)
{}

/* -------------------------------------------------------------------------- */
/* 0x1004: Unified battery                                                    */
/* -------------------------------------------------------------------------- */

#define HIDPP_PAGE_UNIFIED_BATTERY

#define CMD_UNIFIED_BATTERY_GET_CAPABILITIES
#define CMD_UNIFIED_BATTERY_GET_STATUS

#define EVENT_UNIFIED_BATTERY_STATUS_EVENT

#define FLAG_UNIFIED_BATTERY_LEVEL_CRITICAL
#define FLAG_UNIFIED_BATTERY_LEVEL_LOW
#define FLAG_UNIFIED_BATTERY_LEVEL_GOOD
#define FLAG_UNIFIED_BATTERY_LEVEL_FULL

#define FLAG_UNIFIED_BATTERY_FLAGS_RECHARGEABLE
#define FLAG_UNIFIED_BATTERY_FLAGS_STATE_OF_CHARGE

static int hidpp20_unifiedbattery_get_capabilities(struct hidpp_device *hidpp,
						   u8 feature_index)
{}

static int hidpp20_unifiedbattery_map_status(struct hidpp_device *hidpp,
					     u8 charging_status,
					     u8 external_power_status)
{}

static int hidpp20_unifiedbattery_map_level(struct hidpp_device *hidpp,
					    u8 battery_level)
{}

static int hidpp20_unifiedbattery_get_status(struct hidpp_device *hidpp,
					     u8 feature_index,
					     u8 *state_of_charge,
					     int *status,
					     int *level)
{}

static int hidpp20_query_battery_info_1004(struct hidpp_device *hidpp)
{}

static int hidpp20_battery_event_1004(struct hidpp_device *hidpp,
				 u8 *data, int size)
{}

/* -------------------------------------------------------------------------- */
/* Battery feature helpers                                                    */
/* -------------------------------------------------------------------------- */

static enum power_supply_property hidpp_battery_props[] =;

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

/* -------------------------------------------------------------------------- */
/* 0x1d4b: Wireless device status                                             */
/* -------------------------------------------------------------------------- */
#define HIDPP_PAGE_WIRELESS_DEVICE_STATUS

static int hidpp_get_wireless_feature_index(struct hidpp_device *hidpp, u8 *feature_index)
{}

/* -------------------------------------------------------------------------- */
/* 0x1f20: ADC measurement                                                    */
/* -------------------------------------------------------------------------- */

#define HIDPP_PAGE_ADC_MEASUREMENT

#define CMD_ADC_MEASUREMENT_GET_ADC_MEASUREMENT

#define EVENT_ADC_MEASUREMENT_STATUS_BROADCAST

static int hidpp20_map_adc_measurement_1f20_capacity(struct hid_device *hid_dev, int voltage)
{}

static int hidpp20_map_adc_measurement_1f20(u8 data[3], int *voltage)
{}

/* Return value is whether the device is online */
static bool hidpp20_get_adc_measurement_1f20(struct hidpp_device *hidpp,
						 u8 feature_index,
						 int *status, int *voltage)
{}

static int hidpp20_query_adc_measurement_info_1f20(struct hidpp_device *hidpp)
{}

static int hidpp20_adc_measurement_event_1f20(struct hidpp_device *hidpp,
					    u8 *data, int size)
{}

/* -------------------------------------------------------------------------- */
/* 0x2120: Hi-resolution scrolling                                            */
/* -------------------------------------------------------------------------- */

#define HIDPP_PAGE_HI_RESOLUTION_SCROLLING

#define CMD_HI_RESOLUTION_SCROLLING_SET_HIGHRES_SCROLLING_MODE

static int hidpp_hrs_set_highres_scrolling_mode(struct hidpp_device *hidpp,
	bool enabled, u8 *multiplier)
{}

/* -------------------------------------------------------------------------- */
/* 0x2121: HiRes Wheel                                                        */
/* -------------------------------------------------------------------------- */

#define HIDPP_PAGE_HIRES_WHEEL

#define CMD_HIRES_WHEEL_GET_WHEEL_CAPABILITY
#define CMD_HIRES_WHEEL_SET_WHEEL_MODE

static int hidpp_hrw_get_wheel_capability(struct hidpp_device *hidpp,
	u8 *multiplier)
{}

static int hidpp_hrw_set_wheel_mode(struct hidpp_device *hidpp, bool invert,
	bool high_resolution, bool use_hidpp)
{}

/* -------------------------------------------------------------------------- */
/* 0x4301: Solar Keyboard                                                     */
/* -------------------------------------------------------------------------- */

#define HIDPP_PAGE_SOLAR_KEYBOARD

#define CMD_SOLAR_SET_LIGHT_MEASURE

#define EVENT_SOLAR_BATTERY_BROADCAST
#define EVENT_SOLAR_BATTERY_LIGHT_MEASURE
#define EVENT_SOLAR_CHECK_LIGHT_BUTTON

static int hidpp_solar_request_battery_event(struct hidpp_device *hidpp)
{}

static int hidpp_solar_battery_event(struct hidpp_device *hidpp,
				     u8 *data, int size)
{}

/* -------------------------------------------------------------------------- */
/* 0x6010: Touchpad FW items                                                  */
/* -------------------------------------------------------------------------- */

#define HIDPP_PAGE_TOUCHPAD_FW_ITEMS

#define CMD_TOUCHPAD_FW_ITEMS_SET

struct hidpp_touchpad_fw_items {};

/*
 * send a set state command to the device by reading the current items->state
 * field. items is then filled with the current state.
 */
static int hidpp_touchpad_fw_items_set(struct hidpp_device *hidpp,
				       u8 feature_index,
				       struct hidpp_touchpad_fw_items *items)
{}

/* -------------------------------------------------------------------------- */
/* 0x6100: TouchPadRawXY                                                      */
/* -------------------------------------------------------------------------- */

#define HIDPP_PAGE_TOUCHPAD_RAW_XY

#define CMD_TOUCHPAD_GET_RAW_INFO
#define CMD_TOUCHPAD_SET_RAW_REPORT_STATE

#define EVENT_TOUCHPAD_RAW_XY

#define TOUCHPAD_RAW_XY_ORIGIN_LOWER_LEFT
#define TOUCHPAD_RAW_XY_ORIGIN_UPPER_LEFT

struct hidpp_touchpad_raw_info {};

struct hidpp_touchpad_raw_xy_finger {};

struct hidpp_touchpad_raw_xy {};

static int hidpp_touchpad_get_raw_info(struct hidpp_device *hidpp,
	u8 feature_index, struct hidpp_touchpad_raw_info *raw_info)
{}

static int hidpp_touchpad_set_raw_report_state(struct hidpp_device *hidpp_dev,
		u8 feature_index, bool send_raw_reports,
		bool sensor_enhanced_settings)
{}

static void hidpp_touchpad_touch_event(u8 *data,
	struct hidpp_touchpad_raw_xy_finger *finger)
{}

static void hidpp_touchpad_raw_xy_event(struct hidpp_device *hidpp_dev,
		u8 *data, struct hidpp_touchpad_raw_xy *raw_xy)
{}

/* -------------------------------------------------------------------------- */
/* 0x8123: Force feedback support                                             */
/* -------------------------------------------------------------------------- */

#define HIDPP_FF_GET_INFO
#define HIDPP_FF_RESET_ALL
#define HIDPP_FF_DOWNLOAD_EFFECT
#define HIDPP_FF_SET_EFFECT_STATE
#define HIDPP_FF_DESTROY_EFFECT
#define HIDPP_FF_GET_APERTURE
#define HIDPP_FF_SET_APERTURE
#define HIDPP_FF_GET_GLOBAL_GAINS
#define HIDPP_FF_SET_GLOBAL_GAINS

#define HIDPP_FF_EFFECT_STATE_GET
#define HIDPP_FF_EFFECT_STATE_STOP
#define HIDPP_FF_EFFECT_STATE_PLAY
#define HIDPP_FF_EFFECT_STATE_PAUSE

#define HIDPP_FF_EFFECT_CONSTANT
#define HIDPP_FF_EFFECT_PERIODIC_SINE
#define HIDPP_FF_EFFECT_PERIODIC_SQUARE
#define HIDPP_FF_EFFECT_PERIODIC_TRIANGLE
#define HIDPP_FF_EFFECT_PERIODIC_SAWTOOTHUP
#define HIDPP_FF_EFFECT_PERIODIC_SAWTOOTHDOWN
#define HIDPP_FF_EFFECT_SPRING
#define HIDPP_FF_EFFECT_DAMPER
#define HIDPP_FF_EFFECT_FRICTION
#define HIDPP_FF_EFFECT_INERTIA
#define HIDPP_FF_EFFECT_RAMP

#define HIDPP_FF_EFFECT_AUTOSTART

#define HIDPP_FF_EFFECTID_NONE
#define HIDPP_FF_EFFECTID_AUTOCENTER
#define HIDPP_AUTOCENTER_PARAMS_LENGTH

#define HIDPP_FF_MAX_PARAMS
#define HIDPP_FF_RESERVED_SLOTS

struct hidpp_ff_private_data {};

struct hidpp_ff_work_data {};

static const signed short hidpp_ff_effects[] =;

static const signed short hidpp_ff_effects_v2[] =;

static const u8 HIDPP_FF_CONDITION_CMDS[] =;

static const char *HIDPP_FF_CONDITION_NAMES[] =;


static u8 hidpp_ff_find_effect(struct hidpp_ff_private_data *data, int effect_id)
{}

static void hidpp_ff_work_handler(struct work_struct *w)
{}

static int hidpp_ff_queue_work(struct hidpp_ff_private_data *data, int effect_id, u8 command, u8 *params, u8 size)
{}

static int hidpp_ff_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old)
{}

static int hidpp_ff_playback(struct input_dev *dev, int effect_id, int value)
{}

static int hidpp_ff_erase_effect(struct input_dev *dev, int effect_id)
{}

static void hidpp_ff_set_autocenter(struct input_dev *dev, u16 magnitude)
{}

static void hidpp_ff_set_gain(struct input_dev *dev, u16 gain)
{}

static ssize_t hidpp_ff_range_show(struct device *dev, struct device_attribute *attr, char *buf)
{}

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

static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, hidpp_ff_range_show, hidpp_ff_range_store);

static void hidpp_ff_destroy(struct ff_device *ff)
{}

static int hidpp_ff_init(struct hidpp_device *hidpp,
			 struct hidpp_ff_private_data *data)
{}

/* ************************************************************************** */
/*                                                                            */
/* Device Support                                                             */
/*                                                                            */
/* ************************************************************************** */

/* -------------------------------------------------------------------------- */
/* Touchpad HID++ devices                                                     */
/* -------------------------------------------------------------------------- */

#define WTP_MANUAL_RESOLUTION

struct wtp_data {};

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

static void wtp_populate_input(struct hidpp_device *hidpp,
			       struct input_dev *input_dev)
{}

static void wtp_touch_event(struct hidpp_device *hidpp,
	struct hidpp_touchpad_raw_xy_finger *touch_report)
{}

static void wtp_send_raw_xy_event(struct hidpp_device *hidpp,
		struct hidpp_touchpad_raw_xy *raw)
{}

static int wtp_mouse_raw_xy_event(struct hidpp_device *hidpp, u8 *data)
{}

static int wtp_raw_event(struct hid_device *hdev, u8 *data, int size)
{}

static int wtp_get_config(struct hidpp_device *hidpp)
{}

static int wtp_allocate(struct hid_device *hdev, const struct hid_device_id *id)
{
	struct hidpp_device *hidpp = hid_get_drvdata(hdev);
	struct wtp_data *wd;

	wd = devm_kzalloc(&hdev->dev, sizeof(struct wtp_data),
			GFP_KERNEL);
	if (!wd)
		return -ENOMEM;

	hidpp->private_data = wd;

	return 0;
};

static int wtp_connect(struct hid_device *hdev)
{}

/* ------------------------------------------------------------------------- */
/* Logitech M560 devices                                                     */
/* ------------------------------------------------------------------------- */

/*
 * Logitech M560 protocol overview
 *
 * The Logitech M560 mouse, is designed for windows 8. When the middle and/or
 * the sides buttons are pressed, it sends some keyboard keys events
 * instead of buttons ones.
 * To complicate things further, the middle button keys sequence
 * is different from the odd press and the even press.
 *
 * forward button -> Super_R
 * backward button -> Super_L+'d' (press only)
 * middle button -> 1st time: Alt_L+SuperL+XF86TouchpadOff (press only)
 *                  2nd time: left-click (press only)
 * NB: press-only means that when the button is pressed, the
 * KeyPress/ButtonPress and KeyRelease/ButtonRelease events are generated
 * together sequentially; instead when the button is released, no event is
 * generated !
 *
 * With the command
 *	10<xx>0a 3500af03 (where <xx> is the mouse id),
 * the mouse reacts differently:
 * - it never sends a keyboard key event
 * - for the three mouse button it sends:
 *	middle button               press   11<xx>0a 3500af00...
 *	side 1 button (forward)     press   11<xx>0a 3500b000...
 *	side 2 button (backward)    press   11<xx>0a 3500ae00...
 *	middle/side1/side2 button   release 11<xx>0a 35000000...
 */

static const u8 m560_config_parameter[] =;

/* how buttons are mapped in the report */
#define M560_MOUSE_BTN_LEFT
#define M560_MOUSE_BTN_RIGHT
#define M560_MOUSE_BTN_WHEEL_LEFT
#define M560_MOUSE_BTN_WHEEL_RIGHT

#define M560_SUB_ID
#define M560_BUTTON_MODE_REGISTER

static int m560_send_config_command(struct hid_device *hdev)
{}

static int m560_raw_event(struct hid_device *hdev, u8 *data, int size)
{}

static void m560_populate_input(struct hidpp_device *hidpp,
				struct input_dev *input_dev)
{}

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

/* ------------------------------------------------------------------------- */
/* Logitech K400 devices                                                     */
/* ------------------------------------------------------------------------- */

/*
 * The Logitech K400 keyboard has an embedded touchpad which is seen
 * as a mouse from the OS point of view. There is a hardware shortcut to disable
 * tap-to-click but the setting is not remembered accross reset, annoying some
 * users.
 *
 * We can toggle this feature from the host by using the feature 0x6010:
 * Touchpad FW items
 */

struct k400_private_data {};

static int k400_disable_tap_to_click(struct hidpp_device *hidpp)
{}

static int k400_allocate(struct hid_device *hdev)
{
	struct hidpp_device *hidpp = hid_get_drvdata(hdev);
	struct k400_private_data *k400;

	k400 = devm_kzalloc(&hdev->dev, sizeof(struct k400_private_data),
			    GFP_KERNEL);
	if (!k400)
		return -ENOMEM;

	hidpp->private_data = k400;

	return 0;
};

static int k400_connect(struct hid_device *hdev)
{}

/* ------------------------------------------------------------------------- */
/* Logitech G920 Driving Force Racing Wheel for Xbox One                     */
/* ------------------------------------------------------------------------- */

#define HIDPP_PAGE_G920_FORCE_FEEDBACK

static int g920_ff_set_autocenter(struct hidpp_device *hidpp,
				  struct hidpp_ff_private_data *data)
{}

static int g920_get_config(struct hidpp_device *hidpp,
			   struct hidpp_ff_private_data *data)
{}

/* -------------------------------------------------------------------------- */
/* Logitech Dinovo Mini keyboard with builtin touchpad                        */
/* -------------------------------------------------------------------------- */
#define DINOVO_MINI_PRODUCT_ID

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

/* -------------------------------------------------------------------------- */
/* HID++1.0 devices which use HID++ reports for their wheels                  */
/* -------------------------------------------------------------------------- */
static int hidpp10_wheel_connect(struct hidpp_device *hidpp)
{}

static int hidpp10_wheel_raw_event(struct hidpp_device *hidpp,
				   u8 *data, int size)
{}

static void hidpp10_wheel_populate_input(struct hidpp_device *hidpp,
					 struct input_dev *input_dev)
{}

/* -------------------------------------------------------------------------- */
/* HID++1.0 mice which use HID++ reports for extra mouse buttons              */
/* -------------------------------------------------------------------------- */
static int hidpp10_extra_mouse_buttons_connect(struct hidpp_device *hidpp)
{}

static int hidpp10_extra_mouse_buttons_raw_event(struct hidpp_device *hidpp,
				    u8 *data, int size)
{}

static void hidpp10_extra_mouse_buttons_populate_input(
			struct hidpp_device *hidpp, struct input_dev *input_dev)
{}

/* -------------------------------------------------------------------------- */
/* HID++1.0 kbds which only report 0x10xx consumer usages through sub-id 0x03 */
/* -------------------------------------------------------------------------- */

/* Find the consumer-page input report desc and change Maximums to 0x107f */
static u8 *hidpp10_consumer_keys_report_fixup(struct hidpp_device *hidpp,
					      u8 *_rdesc, unsigned int *rsize)
{}

static int hidpp10_consumer_keys_connect(struct hidpp_device *hidpp)
{}

static int hidpp10_consumer_keys_raw_event(struct hidpp_device *hidpp,
					   u8 *data, int size)
{}

/* -------------------------------------------------------------------------- */
/* High-resolution scroll wheels                                              */
/* -------------------------------------------------------------------------- */

static int hi_res_scroll_enable(struct hidpp_device *hidpp)
{}

static int hidpp_initialize_hires_scroll(struct hidpp_device *hidpp)
{}

/* -------------------------------------------------------------------------- */
/* Generic HID++ devices                                                      */
/* -------------------------------------------------------------------------- */

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

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

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


static void hidpp_populate_input(struct hidpp_device *hidpp,
				 struct input_dev *input)
{}

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

static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data,
		int size)
{}

static int hidpp_raw_event(struct hid_device *hdev, struct hid_report *report,
		u8 *data, int size)
{}

static int hidpp_event(struct hid_device *hdev, struct hid_field *field,
	struct hid_usage *usage, __s32 value)
{}

static int hidpp_initialize_battery(struct hidpp_device *hidpp)
{}

/* Get name + serial for USB and Bluetooth HID++ devices */
static void hidpp_non_unifying_init(struct hidpp_device *hidpp)
{}

static int hidpp_input_open(struct input_dev *dev)
{}

static void hidpp_input_close(struct input_dev *dev)
{}

static struct input_dev *hidpp_allocate_input(struct hid_device *hdev)
{}

static void hidpp_connect_event(struct work_struct *work)
{}

static DEVICE_ATTR(builtin_power_supply, 0000, NULL, NULL);

static struct attribute *sysfs_attrs[] =;

static const struct attribute_group ps_attribute_group =;

static int hidpp_get_report_length(struct hid_device *hdev, int id)
{}

static u8 hidpp_validate_device(struct hid_device *hdev)
{}

static bool hidpp_application_equals(struct hid_device *hdev,
				     unsigned int application)
{}

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

static void hidpp_remove(struct hid_device *hdev)
{}

#define LDJ_DEVICE(product)

#define L27MHZ_DEVICE(product)

static const struct hid_device_id hidpp_devices[] =;

MODULE_DEVICE_TABLE(hid, hidpp_devices);

static const struct hid_usage_id hidpp_usages[] =;

static struct hid_driver hidpp_driver =;

module_hid_driver();