#include "hid-ids.h"
#include <asm/unaligned.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/hid.h>
#include <linux/idr.h>
#include <linux/input.h>
#include <linux/jiffies.h>
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/power_supply.h>
#include <linux/spinlock.h>
#define JC_OUTPUT_RUMBLE_AND_SUBCMD …
#define JC_OUTPUT_FW_UPDATE_PKT …
#define JC_OUTPUT_RUMBLE_ONLY …
#define JC_OUTPUT_MCU_DATA …
#define JC_OUTPUT_USB_CMD …
#define JC_SUBCMD_STATE …
#define JC_SUBCMD_MANUAL_BT_PAIRING …
#define JC_SUBCMD_REQ_DEV_INFO …
#define JC_SUBCMD_SET_REPORT_MODE …
#define JC_SUBCMD_TRIGGERS_ELAPSED …
#define JC_SUBCMD_GET_PAGE_LIST_STATE …
#define JC_SUBCMD_SET_HCI_STATE …
#define JC_SUBCMD_RESET_PAIRING_INFO …
#define JC_SUBCMD_LOW_POWER_MODE …
#define JC_SUBCMD_SPI_FLASH_READ …
#define JC_SUBCMD_SPI_FLASH_WRITE …
#define JC_SUBCMD_RESET_MCU …
#define JC_SUBCMD_SET_MCU_CONFIG …
#define JC_SUBCMD_SET_MCU_STATE …
#define JC_SUBCMD_SET_PLAYER_LIGHTS …
#define JC_SUBCMD_GET_PLAYER_LIGHTS …
#define JC_SUBCMD_SET_HOME_LIGHT …
#define JC_SUBCMD_ENABLE_IMU …
#define JC_SUBCMD_SET_IMU_SENSITIVITY …
#define JC_SUBCMD_WRITE_IMU_REG …
#define JC_SUBCMD_READ_IMU_REG …
#define JC_SUBCMD_ENABLE_VIBRATION …
#define JC_SUBCMD_GET_REGULATED_VOLTAGE …
#define JC_INPUT_BUTTON_EVENT …
#define JC_INPUT_SUBCMD_REPLY …
#define JC_INPUT_IMU_DATA …
#define JC_INPUT_MCU_DATA …
#define JC_INPUT_USB_RESPONSE …
#define JC_FEATURE_LAST_SUBCMD …
#define JC_FEATURE_OTA_FW_UPGRADE …
#define JC_FEATURE_SETUP_MEM_READ …
#define JC_FEATURE_MEM_READ …
#define JC_FEATURE_ERASE_MEM_SECTOR …
#define JC_FEATURE_MEM_WRITE …
#define JC_FEATURE_LAUNCH …
#define JC_USB_CMD_CONN_STATUS …
#define JC_USB_CMD_HANDSHAKE …
#define JC_USB_CMD_BAUDRATE_3M …
#define JC_USB_CMD_NO_TIMEOUT …
#define JC_USB_CMD_EN_TIMEOUT …
#define JC_USB_RESET …
#define JC_USB_PRE_HANDSHAKE …
#define JC_USB_SEND_UART …
#define JC_CAL_USR_MAGIC_0 …
#define JC_CAL_USR_MAGIC_1 …
#define JC_CAL_USR_MAGIC_SIZE …
#define JC_CAL_USR_LEFT_MAGIC_ADDR …
#define JC_CAL_USR_LEFT_DATA_ADDR …
#define JC_CAL_USR_LEFT_DATA_END …
#define JC_CAL_USR_RIGHT_MAGIC_ADDR …
#define JC_CAL_USR_RIGHT_DATA_ADDR …
#define JC_CAL_STICK_DATA_SIZE …
#define JC_CAL_FCT_DATA_LEFT_ADDR …
#define JC_CAL_FCT_DATA_RIGHT_ADDR …
#define JC_IMU_CAL_FCT_DATA_ADDR …
#define JC_IMU_CAL_FCT_DATA_END …
#define JC_IMU_CAL_DATA_SIZE …
#define JC_IMU_CAL_USR_MAGIC_ADDR …
#define JC_IMU_CAL_USR_DATA_ADDR …
#define JC_MAX_STICK_MAG …
#define JC_STICK_FUZZ …
#define JC_STICK_FLAT …
#define JC_MAX_DPAD_MAG …
#define JC_DPAD_FUZZ …
#define JC_DPAD_FLAT …
#define JC_IMU_DFLT_AVG_DELTA_MS …
#define JC_IMU_SAMPLES_PER_DELTA_AVG …
#define JC_IMU_DROPPED_PKT_WARNING …
#define JC_IMU_MAX_ACCEL_MAG …
#define JC_IMU_ACCEL_RES_PER_G …
#define JC_IMU_ACCEL_FUZZ …
#define JC_IMU_ACCEL_FLAT …
#define JC_IMU_PREC_RANGE_SCALE …
#define JC_IMU_MAX_GYRO_MAG …
#define JC_IMU_GYRO_RES_PER_DPS …
#define JC_IMU_GYRO_FUZZ …
#define JC_IMU_GYRO_FLAT …
struct joycon_rumble_freq_data { … };
struct joycon_rumble_amp_data { … };
#if IS_ENABLED(CONFIG_NINTENDO_FF)
static const struct joycon_rumble_freq_data joycon_rumble_frequencies[] = …;
#define joycon_max_rumble_amp …
static const struct joycon_rumble_amp_data joycon_rumble_amplitudes[] = …;
static const u16 JC_RUMBLE_DFLT_LOW_FREQ = …;
static const u16 JC_RUMBLE_DFLT_HIGH_FREQ = …;
static const unsigned short JC_RUMBLE_ZERO_AMP_PKT_CNT = …;
#endif
static const u16 JC_RUMBLE_PERIOD_MS = …;
enum joycon_ctlr_state { … };
enum joycon_ctlr_type { … };
struct joycon_stick_cal { … };
struct joycon_imu_cal { … };
#define JC_BTN_Y …
#define JC_BTN_X …
#define JC_BTN_B …
#define JC_BTN_A …
#define JC_BTN_SR_R …
#define JC_BTN_SL_R …
#define JC_BTN_R …
#define JC_BTN_ZR …
#define JC_BTN_MINUS …
#define JC_BTN_PLUS …
#define JC_BTN_RSTICK …
#define JC_BTN_LSTICK …
#define JC_BTN_HOME …
#define JC_BTN_CAP …
#define JC_BTN_DOWN …
#define JC_BTN_UP …
#define JC_BTN_RIGHT …
#define JC_BTN_LEFT …
#define JC_BTN_SR_L …
#define JC_BTN_SL_L …
#define JC_BTN_L …
#define JC_BTN_ZL …
struct joycon_ctlr_button_mapping { … };
static const struct joycon_ctlr_button_mapping left_joycon_button_mappings[] = …;
static const struct joycon_ctlr_button_mapping left_joycon_s_button_mappings[] = …;
static const struct joycon_ctlr_button_mapping right_joycon_button_mappings[] = …;
static const struct joycon_ctlr_button_mapping right_joycon_s_button_mappings[] = …;
static const struct joycon_ctlr_button_mapping procon_button_mappings[] = …;
static const struct joycon_ctlr_button_mapping nescon_button_mappings[] = …;
static const struct joycon_ctlr_button_mapping snescon_button_mappings[] = …;
static const struct joycon_ctlr_button_mapping gencon_button_mappings[] = …;
static const struct joycon_ctlr_button_mapping n64con_button_mappings[] = …;
enum joycon_msg_type { … };
struct joycon_rumble_output { … } __packed;
struct joycon_subcmd_request { … } __packed;
struct joycon_subcmd_reply { … } __packed;
struct joycon_imu_data { … } __packed;
struct joycon_input_report { … } __packed;
#define JC_MAX_RESP_SIZE …
#define JC_RUMBLE_DATA_SIZE …
#define JC_RUMBLE_QUEUE_SIZE …
static const char * const joycon_player_led_names[] = …;
#define JC_NUM_LEDS …
#define JC_NUM_LED_PATTERNS …
static const enum led_brightness joycon_player_led_patterns[JC_NUM_LED_PATTERNS][JC_NUM_LEDS] = …;
struct joycon_ctlr { … };
#define jc_type_is_joycon(ctlr) …
#define jc_type_is_procon(ctlr) …
#define jc_type_is_chrggrip(ctlr) …
#define jc_type_has_left(ctlr) …
#define jc_type_has_right(ctlr) …
static inline bool joycon_device_is_chrggrip(struct joycon_ctlr *ctlr)
{ … }
static inline bool joycon_type_is_left_joycon(struct joycon_ctlr *ctlr)
{ … }
static inline bool joycon_type_is_right_joycon(struct joycon_ctlr *ctlr)
{ … }
static inline bool joycon_type_is_procon(struct joycon_ctlr *ctlr)
{ … }
static inline bool joycon_type_is_snescon(struct joycon_ctlr *ctlr)
{ … }
static inline bool joycon_type_is_gencon(struct joycon_ctlr *ctlr)
{ … }
static inline bool joycon_type_is_n64con(struct joycon_ctlr *ctlr)
{ … }
static inline bool joycon_type_is_left_nescon(struct joycon_ctlr *ctlr)
{ … }
static inline bool joycon_type_is_right_nescon(struct joycon_ctlr *ctlr)
{ … }
static inline bool joycon_type_is_any_joycon(struct joycon_ctlr *ctlr)
{ … }
static inline bool joycon_type_is_any_nescon(struct joycon_ctlr *ctlr)
{ … }
static inline bool joycon_has_imu(struct joycon_ctlr *ctlr)
{ … }
static inline bool joycon_has_joysticks(struct joycon_ctlr *ctlr)
{ … }
static inline bool joycon_has_rumble(struct joycon_ctlr *ctlr)
{ … }
static inline bool joycon_using_usb(struct joycon_ctlr *ctlr)
{ … }
static int __joycon_hid_send(struct hid_device *hdev, u8 *data, size_t len)
{ … }
static void joycon_wait_for_input_report(struct joycon_ctlr *ctlr)
{ … }
#define JC_INPUT_REPORT_MIN_DELTA …
#define JC_INPUT_REPORT_MAX_DELTA …
#define JC_SUBCMD_TX_OFFSET_MS …
#define JC_SUBCMD_VALID_DELTA_REQ …
#define JC_SUBCMD_RATE_MAX_ATTEMPTS …
#define JC_SUBCMD_RATE_LIMITER_USB_MS …
#define JC_SUBCMD_RATE_LIMITER_BT_MS …
#define JC_SUBCMD_RATE_LIMITER_MS(ctlr) …
static void joycon_enforce_subcmd_rate(struct joycon_ctlr *ctlr)
{ … }
static int joycon_hid_send_sync(struct joycon_ctlr *ctlr, u8 *data, size_t len,
u32 timeout)
{ … }
static int joycon_send_usb(struct joycon_ctlr *ctlr, u8 cmd, u32 timeout)
{ … }
static int joycon_send_subcmd(struct joycon_ctlr *ctlr,
struct joycon_subcmd_request *subcmd,
size_t data_len, u32 timeout)
{ … }
static int joycon_set_player_leds(struct joycon_ctlr *ctlr, u8 flash, u8 on)
{ … }
static int joycon_set_home_led(struct joycon_ctlr *ctlr, enum led_brightness brightness)
{ … }
static int joycon_request_spi_flash_read(struct joycon_ctlr *ctlr,
u32 start_addr, u8 size, u8 **reply)
{ … }
static int joycon_check_for_cal_magic(struct joycon_ctlr *ctlr, u32 flash_addr)
{ … }
static int joycon_read_stick_calibration(struct joycon_ctlr *ctlr, u16 cal_addr,
struct joycon_stick_cal *cal_x,
struct joycon_stick_cal *cal_y,
bool left_stick)
{ … }
static const u16 DFLT_STICK_CAL_CEN = …;
static const u16 DFLT_STICK_CAL_MAX = …;
static const u16 DFLT_STICK_CAL_MIN = …;
static void joycon_use_default_calibration(struct hid_device *hdev,
struct joycon_stick_cal *cal_x,
struct joycon_stick_cal *cal_y,
const char *stick, int ret)
{ … }
static int joycon_request_calibration(struct joycon_ctlr *ctlr)
{ … }
static void joycon_calc_imu_cal_divisors(struct joycon_ctlr *ctlr)
{ … }
static const s16 DFLT_ACCEL_OFFSET ;
static const s16 DFLT_ACCEL_SCALE = …;
static const s16 DFLT_GYRO_OFFSET ;
static const s16 DFLT_GYRO_SCALE = …;
static int joycon_request_imu_calibration(struct joycon_ctlr *ctlr)
{ … }
static int joycon_set_report_mode(struct joycon_ctlr *ctlr)
{ … }
static int joycon_enable_rumble(struct joycon_ctlr *ctlr)
{ … }
static int joycon_enable_imu(struct joycon_ctlr *ctlr)
{ … }
static s32 joycon_map_stick_val(struct joycon_stick_cal *cal, s32 val)
{ … }
static void joycon_input_report_parse_imu_data(struct joycon_ctlr *ctlr,
struct joycon_input_report *rep,
struct joycon_imu_data *imu_data)
{ … }
static void joycon_parse_imu_report(struct joycon_ctlr *ctlr,
struct joycon_input_report *rep)
{ … }
static void joycon_handle_rumble_report(struct joycon_ctlr *ctlr, struct joycon_input_report *rep)
{ … }
static void joycon_parse_battery_status(struct joycon_ctlr *ctlr, struct joycon_input_report *rep)
{ … }
static void joycon_report_left_stick(struct joycon_ctlr *ctlr,
struct joycon_input_report *rep)
{ … }
static void joycon_report_right_stick(struct joycon_ctlr *ctlr,
struct joycon_input_report *rep)
{ … }
static void joycon_report_dpad(struct joycon_ctlr *ctlr,
struct joycon_input_report *rep)
{ … }
static void joycon_report_buttons(struct joycon_ctlr *ctlr,
struct joycon_input_report *rep,
const struct joycon_ctlr_button_mapping button_mappings[])
{ … }
static void joycon_parse_report(struct joycon_ctlr *ctlr,
struct joycon_input_report *rep)
{ … }
static int joycon_send_rumble_data(struct joycon_ctlr *ctlr)
{ … }
static void joycon_rumble_worker(struct work_struct *work)
{ … }
#if IS_ENABLED(CONFIG_NINTENDO_FF)
static struct joycon_rumble_freq_data joycon_find_rumble_freq(u16 freq)
{ … }
static struct joycon_rumble_amp_data joycon_find_rumble_amp(u16 amp)
{ … }
static void joycon_encode_rumble(u8 *data, u16 freq_low, u16 freq_high, u16 amp)
{ … }
static const u16 JOYCON_MAX_RUMBLE_HIGH_FREQ = …;
static const u16 JOYCON_MIN_RUMBLE_HIGH_FREQ = …;
static const u16 JOYCON_MAX_RUMBLE_LOW_FREQ = …;
static const u16 JOYCON_MIN_RUMBLE_LOW_FREQ = …;
static void joycon_clamp_rumble_freqs(struct joycon_ctlr *ctlr)
{ … }
static int joycon_set_rumble(struct joycon_ctlr *ctlr, u16 amp_r, u16 amp_l,
bool schedule_now)
{ … }
static int joycon_play_effect(struct input_dev *dev, void *data,
struct ff_effect *effect)
{ … }
#endif
static void joycon_config_left_stick(struct input_dev *idev)
{ … }
static void joycon_config_right_stick(struct input_dev *idev)
{ … }
static void joycon_config_dpad(struct input_dev *idev)
{ … }
static void joycon_config_buttons(struct input_dev *idev,
const struct joycon_ctlr_button_mapping button_mappings[])
{ … }
static void joycon_config_rumble(struct joycon_ctlr *ctlr)
{ … }
static int joycon_imu_input_create(struct joycon_ctlr *ctlr)
{ … }
static int joycon_input_create(struct joycon_ctlr *ctlr)
{ … }
static int joycon_player_led_brightness_set(struct led_classdev *led,
enum led_brightness brightness)
{ … }
static int joycon_home_led_brightness_set(struct led_classdev *led,
enum led_brightness brightness)
{ … }
static DEFINE_IDA(nintendo_player_id_allocator);
static int joycon_leds_create(struct joycon_ctlr *ctlr)
{ … }
static int joycon_battery_get_property(struct power_supply *supply,
enum power_supply_property prop,
union power_supply_propval *val)
{ … }
static enum power_supply_property joycon_battery_props[] = …;
static int joycon_power_supply_create(struct joycon_ctlr *ctlr)
{ … }
static int joycon_read_info(struct joycon_ctlr *ctlr)
{ … }
static int joycon_init(struct hid_device *hdev)
{ … }
static int joycon_ctlr_read_handler(struct joycon_ctlr *ctlr, u8 *data,
int size)
{ … }
static int joycon_ctlr_handle_event(struct joycon_ctlr *ctlr, u8 *data,
int size)
{ … }
static int nintendo_hid_event(struct hid_device *hdev,
struct hid_report *report, u8 *raw_data, int size)
{ … }
static int nintendo_hid_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{ … }
static void nintendo_hid_remove(struct hid_device *hdev)
{ … }
#ifdef CONFIG_PM
static int nintendo_hid_resume(struct hid_device *hdev)
{ … }
#endif
static const struct hid_device_id nintendo_hid_devices[] = …;
MODULE_DEVICE_TABLE(hid, nintendo_hid_devices);
static struct hid_driver nintendo_hid_driver = …;
static int __init nintendo_init(void)
{ … }
static void __exit nintendo_exit(void)
{ … }
module_init(…) …;
module_exit(nintendo_exit);
MODULE_LICENSE(…) …;
MODULE_AUTHOR(…) …;
MODULE_AUTHOR(…) …;
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;