From b470f71a3cf529cecfacbb8e8ba9673ed420f2ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ribeiro=20Bezerra?= Date: Mon, 31 Aug 2020 10:51:29 -0300 Subject: [PATCH 1/3] Update hid-nintendo --- README.md | 4 +- dkms.conf | 2 +- src/hid-nintendo.c | 417 +++++++++++++++++++++++++++++++++++---------- 3 files changed, 326 insertions(+), 97 deletions(-) diff --git a/README.md b/README.md index 54d5244..2d8c6dd 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ git clone https://github.com/nicman23/dkms-hid-nintendo cd dkms-hid-nintendo sudo dkms add . -sudo dkms build nintendo -v 1.0 -sudo dkms install nintendo -v 1.0 +sudo dkms build nintendo -v 3.0 +sudo dkms install nintendo -v 3.0 ``` diff --git a/dkms.conf b/dkms.conf index 8023c45..c07c239 100644 --- a/dkms.conf +++ b/dkms.conf @@ -1,5 +1,5 @@ PACKAGE_NAME="nintendo" -PACKAGE_VERSION=2.0 +PACKAGE_VERSION=3.0 MAKE="make -C $kernel_source_dir M=$dkms_tree/$PACKAGE_NAME/$PACKAGE_VERSION/build/src modules" CLEAN="make -C $kernel_source_dir M=$dkms_tree/$PACKAGE_NAME/$PACKAGE_VERSION/build/src clean" BUILT_MODULE_NAME[0]="hid-nintendo" diff --git a/src/hid-nintendo.c b/src/hid-nintendo.c index 063f37a..9bbab3b 100644 --- a/src/hid-nintendo.c +++ b/src/hid-nintendo.c @@ -2,7 +2,7 @@ /* * HID driver for Nintendo Switch Joy-Cons and Pro Controllers * - * Copyright (c) 2019 Daniel J. Ogorchock + * Copyright (c) 2019-2020 Daniel J. Ogorchock * * The following resources/projects were referenced for this driver: * https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering @@ -23,8 +23,10 @@ */ #include "hid-ids.h" +#include #include #include +#include #include #include #include @@ -133,17 +135,46 @@ static const u16 JC_MAX_DPAD_MAG = 1; static const u16 JC_DPAD_FUZZ /*= 0*/; static const u16 JC_DPAD_FLAT /*= 0*/; -/* The accel axes will be mapped in terms of this magnitude */ -static const u16 JC_MAX_ACCEL_MAG = 32767; -static const u16 JC_ACCEL_RES = 4096; -static const u16 JC_ACCEL_FUZZ = 10; -static const u16 JC_ACCEL_FLAT /*= 0*/; +/* Under most circumstances IMU reports are pushed every 15ms; use as default */ +static const u16 JC_IMU_DFLT_AVG_DELTA_MS = 15; +/* How many samples to sum before calculating average IMU report delta */ +static const u16 JC_IMU_SAMPLES_PER_DELTA_AVG = 300; +/* Controls how many dropped IMU packets at once trigger a warning message */ +static const u16 JC_IMU_DROPPED_PKT_WARNING = 3; -/* The gyro axes will be mapped in terms of this magnitude */ -static const u16 JC_MAX_GYRO_MAG = 32767; -static const u16 JC_GYRO_RES = 13371 / 936; /* 14 (14.285) */ -static const u16 JC_GYRO_FUZZ = 10; -static const u16 JC_GYRO_FLAT /*= 0*/; +/* + * The controller's accelerometer has a sensor resolution of 16bits and is + * configured with a range of +-8000 milliGs. Therefore, the resolution can be + * calculated thus: (2^16-1)/(8000 * 2) = 4.096 digits per milliG + * Resolution per G (rather than per millliG): 4.096 * 1000 = 4096 digits per G + * Alternatively: 1/4096 = .0002441 Gs per digit + */ +static const s32 JC_IMU_MAX_ACCEL_MAG = 32767; +static const u16 JC_IMU_ACCEL_RES_PER_G = 4096; +static const u16 JC_IMU_ACCEL_FUZZ = 10; +static const u16 JC_IMU_ACCEL_FLAT /*= 0*/; + +/* + * The controller's gyroscope has a sensor resolution of 16bits and is + * configured with a range of +-2000 degrees/second. + * Digits per dps: (2^16 -1)/(2000*2) = 16.38375 + * dps per digit: 16.38375E-1 = .0610 + * + * STMicro recommends in the datasheet to add 15% to the dps/digit. This allows + * the full sensitivity range to be saturated without clipping. This yields more + * accurate results, so it's the technique this driver uses. + * dps per digit (corrected): .0610 * 1.15 = .0702 + * digits per dps (corrected): .0702E-1 = 14.247 + * + * Now, 14.247 truncating to 14 loses a lot of precision, so we rescale the + * min/max range by 1000. + */ +static const s32 JC_IMU_PREC_RANGE_SCALE = 1000; +/* Note: change mag and res_per_dps if prec_range_scale is ever altered */ +static const s32 JC_IMU_MAX_GYRO_MAG = 32767000; /* (2^16-1)*1000 */ +static const u16 JC_IMU_GYRO_RES_PER_DPS = 14247; /* (14.247*1000) */ +static const u16 JC_IMU_GYRO_FUZZ = 10; +static const u16 JC_IMU_GYRO_FLAT /*= 0*/; /* frequency/amplitude tables for rumble */ struct joycon_rumble_freq_data { @@ -340,10 +371,6 @@ struct joycon_imu_data { s16 gyro_z; } __packed; -struct joycon_imu_report { - struct joycon_imu_data data[3]; -} __packed; - struct joycon_input_report { u8 id; u8 timer; @@ -355,7 +382,8 @@ struct joycon_input_report { union { struct joycon_subcmd_reply subcmd_reply; - struct joycon_imu_report imu_report; + /* IMU input reports contain 3 samples */ + u8 imu_raw_bytes[sizeof(struct joycon_imu_data) * 3]; }; } __packed; @@ -400,6 +428,10 @@ struct joycon_ctlr { struct joycon_imu_cal accel_cal; struct joycon_imu_cal gyro_cal; + /* prevents needlessly recalculating these divisors every sample */ + s32 imu_cal_accel_divisor[3]; + s32 imu_cal_gyro_divisor[3]; + /* power supply data */ struct power_supply *battery; struct power_supply_desc battery_desc; @@ -422,7 +454,13 @@ struct joycon_ctlr { /* imu */ struct input_dev *imu_input; - int timestamp; + bool imu_first_packet_received; /* helps in initiating timestamp */ + unsigned int imu_timestamp_us; /* timestamp we report to userspace */ + unsigned int imu_last_pkt_ms; /* used to calc imu report delta */ + /* the following are used to track the average imu report time delta */ + unsigned int imu_delta_samples_count; + unsigned int imu_delta_samples_sum; + unsigned int imu_avg_delta_ms; }; /* Helper macros for checking controller type */ @@ -597,10 +635,7 @@ static int joycon_request_spi_flash_read(struct joycon_ctlr *ctlr, req = (struct joycon_subcmd_request *)buffer; req->subcmd_id = JC_SUBCMD_SPI_FLASH_READ; data = req->data; - data[0] = 0xFF & start_addr; - data[1] = 0xFF & (start_addr >> 8); - data[2] = 0xFF & (start_addr >> 16); - data[3] = 0xFF & (start_addr >> 24); + put_unaligned_le32(start_addr, data); data[4] = size; hid_dbg(ctlr->hdev, "requesting SPI flash data\n"); @@ -770,6 +805,23 @@ static int joycon_request_calibration(struct joycon_ctlr *ctlr) return 0; } +/* + * These divisors are calculated once rather than for each sample. They are only + * dependent on the IMU calibration values. They are used when processing the + * IMU input reports. + */ +static void joycon_calc_imu_cal_divisors(struct joycon_ctlr *ctlr) +{ + int i; + + for (i = 0; i < 3; i++) { + ctlr->imu_cal_accel_divisor[i] = ctlr->accel_cal.scale[i] - + ctlr->accel_cal.offset[i]; + ctlr->imu_cal_gyro_divisor[i] = ctlr->gyro_cal.scale[i] - + ctlr->gyro_cal.offset[i]; + } +} + static const s16 DFLT_ACCEL_OFFSET /*= 0*/; static const s16 DFLT_ACCEL_SCALE = 16384; static const s16 DFLT_GYRO_OFFSET /*= 0*/; @@ -804,6 +856,7 @@ static int joycon_request_imu_calibration(struct joycon_ctlr *ctlr) ctlr->gyro_cal.offset[i] = DFLT_GYRO_OFFSET; ctlr->gyro_cal.scale[i] = DFLT_GYRO_SCALE; } + joycon_calc_imu_cal_divisors(ctlr); return ret; } @@ -811,16 +864,14 @@ static int joycon_request_imu_calibration(struct joycon_ctlr *ctlr) for (i = 0; i < 3; i++) { int j = i * 2; - ctlr->accel_cal.offset[i] = raw_cal[j + 0] | - ((s16)raw_cal[j + 1] << 8); - ctlr->accel_cal.scale[i] = raw_cal[j + 6] | - ((s16)raw_cal[j + 7] << 8); - ctlr->gyro_cal.offset[i] = raw_cal[j + 12] | - ((s16)raw_cal[j + 13] << 8); - ctlr->gyro_cal.scale[i] = raw_cal[j + 18] | - ((s16)raw_cal[j + 19] << 8); + ctlr->accel_cal.offset[i] = get_unaligned_le16(raw_cal + j); + ctlr->accel_cal.scale[i] = get_unaligned_le16(raw_cal + j + 6); + ctlr->gyro_cal.offset[i] = get_unaligned_le16(raw_cal + j + 12); + ctlr->gyro_cal.scale[i] = get_unaligned_le16(raw_cal + j + 18); } + joycon_calc_imu_cal_divisors(ctlr); + hid_dbg(ctlr->hdev, "IMU calibration:\n" "a_o[0]=%d a_o[1]=%d a_o[2]=%d\n" "a_s[0]=%d a_s[1]=%d a_s[2]=%d\n" @@ -899,6 +950,224 @@ static s32 joycon_map_stick_val(struct joycon_stick_cal *cal, s32 val) return new_val; } +static void joycon_input_report_parse_imu_data(struct joycon_ctlr *ctlr, + struct joycon_input_report *rep, + struct joycon_imu_data *imu_data) +{ + u8 *raw = rep->imu_raw_bytes; + int i; + + for (i = 0; i < 3; i++) { + struct joycon_imu_data *data = &imu_data[i]; + + data->accel_x = get_unaligned_le16(raw + 0); + data->accel_y = get_unaligned_le16(raw + 2); + data->accel_z = get_unaligned_le16(raw + 4); + data->gyro_x = get_unaligned_le16(raw + 6); + data->gyro_y = get_unaligned_le16(raw + 8); + data->gyro_z = get_unaligned_le16(raw + 10); + /* point to next imu sample */ + raw += sizeof(struct joycon_imu_data); + } +} + +static void joycon_parse_imu_report(struct joycon_ctlr *ctlr, + struct joycon_input_report *rep) +{ + struct joycon_imu_data imu_data[3] = {0}; /* 3 reports per packet */ + struct input_dev *idev = ctlr->imu_input; + unsigned int msecs = jiffies_to_msecs(jiffies); + unsigned int last_msecs = ctlr->imu_last_pkt_ms; + int i; + int value[6]; + + joycon_input_report_parse_imu_data(ctlr, rep, imu_data); + + /* + * There are complexities surrounding how we determine the timestamps we + * associate with the samples we pass to userspace. The IMU input + * reports do not provide us with a good timestamp. There's a quickly + * incrementing 8-bit counter per input report, but it is not very + * useful for this purpose (it is not entirely clear what rate it + * increments at or if it varies based on packet push rate - more on + * the push rate below...). + * + * The reverse engineering work done on the joy-cons and pro controllers + * by the community seems to indicate the following: + * - The controller samples the IMU every 1.35ms. It then does some of + * its own processing, probably averaging the samples out. + * - Each imu input report contains 3 IMU samples, (usually 5ms apart). + * - In the standard reporting mode (which this driver uses exclusively) + * input reports are pushed from the controller as follows: + * * joy-con (bluetooth): every 15 ms + * * joy-cons (in charging grip via USB): every 15 ms + * * pro controller (USB): every 15 ms + * * pro controller (bluetooth): every 8 ms (this is the wildcard) + * + * Further complicating matters is that some bluetooth stacks are known + * to alter the controller's packet rate by hardcoding the bluetooth + * SSR for the switch controllers (android's stack currently sets the + * SSR to 11ms for both the joy-cons and pro controllers). + * + * In my own testing, I've discovered that my pro controller either + * reports IMU sample batches every 11ms or every 15ms. This rate is + * stable after connecting. It isn't 100% clear what determines this + * rate. Importantly, even when sending every 11ms, none of the samples + * are duplicates. This seems to indicate that the time deltas between + * reported samples can vary based on the input report rate. + * + * The solution employed in this driver is to keep track of the average + * time delta between IMU input reports. In testing, this value has + * proven to be stable, staying at 15ms or 11ms, though other hardware + * configurations and bluetooth stacks could potentially see other rates + * (hopefully this will become more clear as more people use the + * driver). + * + * Keeping track of the average report delta allows us to submit our + * timestamps to userspace based on that. Each report contains 3 + * samples, so the IMU sampling rate should be avg_time_delta/3. We can + * also use this average to detect events where we have dropped a + * packet. The userspace timestamp for the samples will be adjusted + * accordingly to prevent unwanted behvaior. + */ + if (!ctlr->imu_first_packet_received) { + ctlr->imu_timestamp_us = 0; + ctlr->imu_delta_samples_count = 0; + ctlr->imu_delta_samples_sum = 0; + ctlr->imu_avg_delta_ms = JC_IMU_DFLT_AVG_DELTA_MS; + ctlr->imu_first_packet_received = true; + } else { + unsigned int delta = msecs - last_msecs; + unsigned int dropped_pkts; + unsigned int dropped_threshold; + + /* avg imu report delta housekeeping */ + ctlr->imu_delta_samples_sum += delta; + ctlr->imu_delta_samples_count++; + if (ctlr->imu_delta_samples_count >= + JC_IMU_SAMPLES_PER_DELTA_AVG) { + ctlr->imu_avg_delta_ms = ctlr->imu_delta_samples_sum / + ctlr->imu_delta_samples_count; + /* don't ever want divide by zero shenanigans */ + if (ctlr->imu_avg_delta_ms == 0) { + ctlr->imu_avg_delta_ms = 1; + hid_warn(ctlr->hdev, + "calculated avg imu delta of 0\n"); + } + ctlr->imu_delta_samples_count = 0; + ctlr->imu_delta_samples_sum = 0; + } + + /* useful for debugging IMU sample rate */ + hid_dbg(ctlr->hdev, + "imu_report: ms=%u last_ms=%u delta=%u avg_delta=%u\n", + msecs, last_msecs, delta, ctlr->imu_avg_delta_ms); + + /* check if any packets have been dropped */ + dropped_threshold = ctlr->imu_avg_delta_ms * 3 / 2; + dropped_pkts = (delta - min(delta, dropped_threshold)) / + ctlr->imu_avg_delta_ms; + ctlr->imu_timestamp_us += 1000 * ctlr->imu_avg_delta_ms; + if (dropped_pkts > JC_IMU_DROPPED_PKT_WARNING) { + hid_warn(ctlr->hdev, + "compensating for %u dropped IMU reports\n", + dropped_pkts); + hid_warn(ctlr->hdev, + "delta=%u avg_delta=%u\n", + delta, ctlr->imu_avg_delta_ms); + } + } + ctlr->imu_last_pkt_ms = msecs; + + /* Each IMU input report contains three samples */ + for (i = 0; i < 3; i++) { + input_event(idev, EV_MSC, MSC_TIMESTAMP, + ctlr->imu_timestamp_us); + + /* + * These calculations (which use the controller's calibration + * settings to improve the final values) are based on those + * found in the community's reverse-engineering repo (linked at + * top of driver). For hid-nintendo, we make sure that the final + * value given to userspace is always in terms of the axis + * resolution we provided. + * + * Currently only the gyro calculations subtract the calibration + * offsets from the raw value itself. In testing, doing the same + * for the accelerometer raw values decreased accuracy. + * + * Note that the gyro values are multiplied by the + * precision-saving scaling factor to prevent large inaccuracies + * due to truncation of the resolution value which would + * otherwise occur. To prevent overflow (without resorting to 64 + * bit integer math), the mult_frac macro is used. + */ + value[0] = mult_frac((JC_IMU_PREC_RANGE_SCALE * + (imu_data[i].gyro_x - + ctlr->gyro_cal.offset[0])), + ctlr->gyro_cal.scale[0], + ctlr->imu_cal_gyro_divisor[0]); + value[1] = mult_frac((JC_IMU_PREC_RANGE_SCALE * + (imu_data[i].gyro_y - + ctlr->gyro_cal.offset[1])), + ctlr->gyro_cal.scale[1], + ctlr->imu_cal_gyro_divisor[1]); + value[2] = mult_frac((JC_IMU_PREC_RANGE_SCALE * + (imu_data[i].gyro_z - + ctlr->gyro_cal.offset[2])), + ctlr->gyro_cal.scale[2], + ctlr->imu_cal_gyro_divisor[2]); + + value[3] = ((s32)imu_data[i].accel_x * + ctlr->accel_cal.scale[0]) / + ctlr->imu_cal_accel_divisor[0]; + value[4] = ((s32)imu_data[i].accel_y * + ctlr->accel_cal.scale[1]) / + ctlr->imu_cal_accel_divisor[1]; + value[5] = ((s32)imu_data[i].accel_z * + ctlr->accel_cal.scale[2]) / + ctlr->imu_cal_accel_divisor[2]; + + hid_dbg(ctlr->hdev, "raw_gyro: g_x=%hd g_y=%hd g_z=%hd\n", + imu_data[i].gyro_x, imu_data[i].gyro_y, + imu_data[i].gyro_z); + hid_dbg(ctlr->hdev, "raw_accel: a_x=%hd a_y=%hd a_z=%hd\n", + imu_data[i].accel_x, imu_data[i].accel_y, + imu_data[i].accel_z); + + /* + * The right joy-con has 2 axes negated, Y and Z. This is due to + * the orientation of the IMU in the controller. We negate those + * axes' values in order to be consistent with the left joy-con + * and the pro controller: + * X: positive is pointing toward the triggers + * Y: positive is pointing to the left + * Z: positive is pointing up (out of the buttons/sticks) + * The axes follow the right-hand rule. + */ + if (jc_type_is_joycon(ctlr) && jc_type_has_right(ctlr)) { + int j; + + /* negate all but x axis */ + for (j = 1; j < 6; ++j) { + if (j == 3) + continue; + value[j] *= -1; + } + } + + input_report_abs(idev, ABS_RX, value[0]); + input_report_abs(idev, ABS_RY, value[1]); + input_report_abs(idev, ABS_RZ, value[2]); + input_report_abs(idev, ABS_X, value[3]); + input_report_abs(idev, ABS_Y, value[4]); + input_report_abs(idev, ABS_Z, value[5]); + input_sync(idev); + /* convert to micros and divide by 3 (3 samples per report). */ + ctlr->imu_timestamp_us += ctlr->imu_avg_delta_ms * 1000 / 3; + } +} + static void joycon_parse_report(struct joycon_ctlr *ctlr, struct joycon_input_report *rep) { @@ -909,7 +1178,7 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr, unsigned long msecs = jiffies_to_msecs(jiffies); spin_lock_irqsave(&ctlr->lock, flags); - if (rep->vibrator_report && + if (IS_ENABLED(CONFIG_NINTENDO_FF) && rep->vibrator_report && (msecs - ctlr->rumble_msecs) >= JC_RUMBLE_PERIOD_MS && (ctlr->rumble_queue_head != ctlr->rumble_queue_tail || !ctlr->rumble_zero_amp)) @@ -1051,52 +1320,8 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr, } /* parse IMU data if present */ - if (rep->id == JC_INPUT_IMU_DATA) { - struct joycon_imu_data *imu_data = rep->imu_report.data; - struct input_dev *idev = ctlr->imu_input; - int i; - int value[6]; - - for (i = 0; i < 3; i++) { /* there are 3 reports */ - ctlr->timestamp += 5000; /* each is 5 ms apart */ - input_event(idev, EV_MSC, MSC_TIMESTAMP, - ctlr->timestamp); - - /* - * Rather than convert to floats, we adjust by - * calibration factors and then multiply by the default - * scaling values. This way, the consumer only needs to - * divide by the default scale values. - */ - value[0] = (imu_data[i].gyro_x - - ctlr->gyro_cal.offset[0]) * - DFLT_GYRO_SCALE / ctlr->gyro_cal.scale[0]; - value[1] = (imu_data[i].gyro_y - - ctlr->gyro_cal.offset[1]) * - DFLT_GYRO_SCALE / ctlr->gyro_cal.scale[1]; - value[2] = (imu_data[i].gyro_z - - ctlr->gyro_cal.offset[2]) * - DFLT_GYRO_SCALE / ctlr->gyro_cal.scale[2]; - - value[3] = (imu_data[i].accel_x - - ctlr->accel_cal.offset[0]) * - DFLT_ACCEL_SCALE / ctlr->accel_cal.scale[0]; - value[4] = (imu_data[i].accel_y - - ctlr->accel_cal.offset[1]) * - DFLT_ACCEL_SCALE / ctlr->accel_cal.scale[1]; - value[5] = (imu_data[i].accel_z - - ctlr->accel_cal.offset[2]) * - DFLT_ACCEL_SCALE / ctlr->accel_cal.scale[2]; - - input_report_abs(idev, ABS_RX, value[0]); - input_report_abs(idev, ABS_RY, value[1]); - input_report_abs(idev, ABS_RZ, value[2]); - input_report_abs(idev, ABS_X, value[3]); - input_report_abs(idev, ABS_Y, value[4]); - input_report_abs(idev, ABS_Z, value[5]); - input_sync(idev); - } - } + if (rep->id == JC_INPUT_IMU_DATA) + joycon_parse_imu_report(ctlr, rep); } static void joycon_rumble_worker(struct work_struct *work) @@ -1129,6 +1354,7 @@ 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) { const size_t length = ARRAY_SIZE(joycon_rumble_frequencies); @@ -1257,6 +1483,7 @@ static int joycon_play_effect(struct input_dev *dev, void *data, effect->u.rumble.strong_magnitude, true); } +#endif /* IS_ENABLED(CONFIG_NINTENDO_FF) */ static const unsigned int joycon_button_inputs_l[] = { BTN_SELECT, BTN_Z, BTN_THUMBL, @@ -1373,6 +1600,7 @@ static int joycon_input_create(struct joycon_ctlr *ctlr) input_set_capability(ctlr->input, EV_KEY, BTN_TL2); } +#if IS_ENABLED(CONFIG_NINTENDO_FF) /* set up rumble */ input_set_capability(ctlr->input, EV_FF, FF_RUMBLE); input_ff_create_memless(ctlr->input, NULL, joycon_play_effect); @@ -1383,6 +1611,7 @@ static int joycon_input_create(struct joycon_ctlr *ctlr) joycon_clamp_rumble_freqs(ctlr); joycon_set_rumble(ctlr, 0, 0, false); ctlr->rumble_msecs = jiffies_to_msecs(jiffies); +#endif ret = input_register_device(ctlr->input); if (ret) @@ -1403,31 +1632,31 @@ static int joycon_input_create(struct joycon_ctlr *ctlr) /* configure imu axes */ input_set_abs_params(ctlr->imu_input, ABS_X, - -JC_MAX_ACCEL_MAG, JC_MAX_ACCEL_MAG, - JC_ACCEL_FUZZ, JC_ACCEL_FLAT); + -JC_IMU_MAX_ACCEL_MAG, JC_IMU_MAX_ACCEL_MAG, + JC_IMU_ACCEL_FUZZ, JC_IMU_ACCEL_FLAT); input_set_abs_params(ctlr->imu_input, ABS_Y, - -JC_MAX_ACCEL_MAG, JC_MAX_ACCEL_MAG, - JC_ACCEL_FUZZ, JC_ACCEL_FLAT); + -JC_IMU_MAX_ACCEL_MAG, JC_IMU_MAX_ACCEL_MAG, + JC_IMU_ACCEL_FUZZ, JC_IMU_ACCEL_FLAT); input_set_abs_params(ctlr->imu_input, ABS_Z, - -JC_MAX_ACCEL_MAG, JC_MAX_ACCEL_MAG, - JC_ACCEL_FUZZ, JC_ACCEL_FLAT); - input_abs_set_res(ctlr->imu_input, ABS_X, JC_ACCEL_RES); - input_abs_set_res(ctlr->imu_input, ABS_Y, JC_ACCEL_RES); - input_abs_set_res(ctlr->imu_input, ABS_Z, JC_ACCEL_RES); + -JC_IMU_MAX_ACCEL_MAG, JC_IMU_MAX_ACCEL_MAG, + JC_IMU_ACCEL_FUZZ, JC_IMU_ACCEL_FLAT); + input_abs_set_res(ctlr->imu_input, ABS_X, JC_IMU_ACCEL_RES_PER_G); + input_abs_set_res(ctlr->imu_input, ABS_Y, JC_IMU_ACCEL_RES_PER_G); + input_abs_set_res(ctlr->imu_input, ABS_Z, JC_IMU_ACCEL_RES_PER_G); input_set_abs_params(ctlr->imu_input, ABS_RX, - -JC_MAX_GYRO_MAG, JC_MAX_GYRO_MAG, - JC_GYRO_FUZZ, JC_GYRO_FLAT); + -JC_IMU_MAX_GYRO_MAG, JC_IMU_MAX_GYRO_MAG, + JC_IMU_GYRO_FUZZ, JC_IMU_GYRO_FLAT); input_set_abs_params(ctlr->imu_input, ABS_RY, - -JC_MAX_GYRO_MAG, JC_MAX_GYRO_MAG, - JC_GYRO_FUZZ, JC_GYRO_FLAT); + -JC_IMU_MAX_GYRO_MAG, JC_IMU_MAX_GYRO_MAG, + JC_IMU_GYRO_FUZZ, JC_IMU_GYRO_FLAT); input_set_abs_params(ctlr->imu_input, ABS_RZ, - -JC_MAX_GYRO_MAG, JC_MAX_GYRO_MAG, - JC_GYRO_FUZZ, JC_GYRO_FLAT); + -JC_IMU_MAX_GYRO_MAG, JC_IMU_MAX_GYRO_MAG, + JC_IMU_GYRO_FUZZ, JC_IMU_GYRO_FLAT); - input_abs_set_res(ctlr->imu_input, ABS_RX, JC_GYRO_RES); - input_abs_set_res(ctlr->imu_input, ABS_RY, JC_GYRO_RES); - input_abs_set_res(ctlr->imu_input, ABS_RZ, JC_GYRO_RES); + input_abs_set_res(ctlr->imu_input, ABS_RX, JC_IMU_GYRO_RES_PER_DPS); + input_abs_set_res(ctlr->imu_input, ABS_RY, JC_IMU_GYRO_RES_PER_DPS); + input_abs_set_res(ctlr->imu_input, ABS_RZ, JC_IMU_GYRO_RES_PER_DPS); __set_bit(EV_MSC, ctlr->imu_input->evbit); __set_bit(MSC_TIMESTAMP, ctlr->imu_input->mscbit); From 63efdbceda620ab6cb601bc88660164c05e0e366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ribeiro=20Bezerra?= Date: Mon, 31 Aug 2020 10:59:48 -0300 Subject: [PATCH 2/3] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2d8c6dd..29105d3 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A Nintendo HID kernel module. Install it from source with: ``` -git clone https://github.com/nicman23/dkms-hid-nintendo +git clone https://github.com/joaorb64/dkms-hid-nintendo cd dkms-hid-nintendo sudo dkms add . From 9818c2a602274777982040513e6e5c1c7b5a5e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ribeiro=20Bezerra?= Date: Wed, 2 Sep 2020 18:27:26 -0300 Subject: [PATCH 3/3] Enable rumble --- src/hid-nintendo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hid-nintendo.c b/src/hid-nintendo.c index 9bbab3b..5d47968 100644 --- a/src/hid-nintendo.c +++ b/src/hid-nintendo.c @@ -22,6 +22,8 @@ * */ +#define CONFIG_NINTENDO_FF 1 + #include "hid-ids.h" #include #include