From 3c63b9f0ae74f0d65df13deecb949536613f2ca4 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 14 Jul 2021 20:03:01 +0300 Subject: Small cleanup --- hid-tmt300rs.c | 345 ++++++++++++++++++++++----------------------------------- 1 file changed, 133 insertions(+), 212 deletions(-) diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 54ace09..7b615e0 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -17,6 +17,7 @@ static int friction_level = 30; module_param(friction_level, int, 0); MODULE_PARM_DESC(friction_level, "Level of friction force (0-100), as per Oversteer standards"); +#define FIT16_ARR(x, i, v) { (x)[(i)] = (v) & 0xff; (x)[(i) + 1] = ((v) >> 8) & 0xff; } static struct t300rs_device_entry *t300rs_get_device(struct hid_device *hdev) { @@ -104,14 +105,20 @@ static void t300rs_fill_envelope(u8 *send_buffer, int i, s16 level, u16 fade_length = (duration * envelope->fade_length) / 0x7fff; u16 fade_level = (level * envelope->fade_level) / 0x7fff; - send_buffer[i + 0] = attack_length & 0xff; - send_buffer[i + 1] = attack_length >> 8; - send_buffer[i + 2] = attack_level & 0xff; - send_buffer[i + 3] = attack_level >> 8; - send_buffer[i + 4] = fade_length & 0xff; - send_buffer[i + 5] = fade_length >> 8; - send_buffer[i + 6] = fade_level & 0xff; - send_buffer[i + 7] = fade_level >> 8; + FIT16_ARR(send_buffer, i + 0, attack_length); + FIT16_ARR(send_buffer, i + 2, attack_level); + FIT16_ARR(send_buffer, i + 4, fade_length); + FIT16_ARR(send_buffer, i + 6, fade_level); +} + +static void t300rs_fill_timing(u8 *send_buffer, int i, u16 duration, u16 offset){ + send_buffer[i] = 0x4f; + + FIT16_ARR(send_buffer, i + 1, duration); + FIT16_ARR(send_buffer, i + 5, offset); + + send_buffer[i + 8] = 0xff; + send_buffer[i + 9] = 0xff; } static int t300rs_modify_envelope(struct t300rs_device_entry *t300rs, @@ -142,8 +149,7 @@ static int t300rs_modify_envelope(struct t300rs_device_entry *t300rs, if (envelope.attack_length != envelope_old.attack_length) { send_buffer[3] = 0x81; - send_buffer[4] = attack_length & 0xff; - send_buffer[5] = attack_length >> 8; + FIT16_ARR(send_buffer, 4, attack_length); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) { @@ -155,8 +161,7 @@ static int t300rs_modify_envelope(struct t300rs_device_entry *t300rs, if (envelope.attack_level != envelope_old.attack_level) { send_buffer[3] = 0x82; - send_buffer[4] = attack_level & 0xff; - send_buffer[5] = attack_level >> 8; + FIT16_ARR(send_buffer, 4, attack_level); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) { @@ -168,8 +173,7 @@ static int t300rs_modify_envelope(struct t300rs_device_entry *t300rs, if (envelope.fade_length != envelope_old.fade_length) { send_buffer[3] = 0x84; - send_buffer[4] = fade_length & 0xff; - send_buffer[5] = fade_length >> 8; + FIT16_ARR(send_buffer, 4, fade_length); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) { @@ -181,8 +185,7 @@ static int t300rs_modify_envelope(struct t300rs_device_entry *t300rs, if (envelope.fade_level != envelope_old.fade_level) { send_buffer[3] = 0x88; - send_buffer[4] = fade_level & 0xff; - send_buffer[5] = fade_level >> 8; + FIT16_ARR(send_buffer, 4, fade_level); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) { @@ -214,8 +217,7 @@ static int t300rs_modify_duration(struct t300rs_device_entry *t300rs, send_buffer[2] = 0x49; send_buffer[4] = 0x41; - send_buffer[5] = duration & 0xff; - send_buffer[6] = duration >> 8; + FIT16_ARR(send_buffer, 5, duration); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) { @@ -223,6 +225,7 @@ static int t300rs_modify_duration(struct t300rs_device_entry *t300rs, goto error; } } + error: return ret; } @@ -244,8 +247,7 @@ static int t300rs_modify_constant(struct t300rs_device_entry *t300rs, send_buffer[1] = effect.id + 1; send_buffer[2] = 0x0a; - send_buffer[3] = level & 0xff; - send_buffer[4] = level >> 8; + FIT16_ARR(send_buffer, 3, level); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) { @@ -264,6 +266,7 @@ static int t300rs_modify_constant(struct t300rs_device_entry *t300rs, constant.envelope, constant_old.envelope ); + if (ret) { hid_err(t300rs->hdev, "failed modifying constant envelope\n"); goto error; @@ -276,7 +279,6 @@ static int t300rs_modify_constant(struct t300rs_device_entry *t300rs, } error: - return ret; } @@ -307,11 +309,8 @@ static int t300rs_modify_ramp(struct t300rs_device_entry *t300rs, send_buffer[2] = 0x0e; send_buffer[3] = 0x03; - send_buffer[4] = difference & 0xff; - send_buffer[5] = difference >> 8; - - send_buffer[6] = level & 0xff; - send_buffer[7] = level >> 8; + FIT16_ARR(send_buffer, 4, difference); + FIT16_ARR(send_buffer, 6, level); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) { @@ -331,6 +330,7 @@ static int t300rs_modify_ramp(struct t300rs_device_entry *t300rs, ramp_old.envelope ); + if (ret) { hid_err(t300rs->hdev, "failed modifying ramp envelope\n"); goto error; @@ -343,7 +343,6 @@ static int t300rs_modify_ramp(struct t300rs_device_entry *t300rs, } error: - return ret; } static int t300rs_modify_damper(struct t300rs_device_entry *t300rs, @@ -370,8 +369,7 @@ static int t300rs_modify_damper(struct t300rs_device_entry *t300rs, send_buffer[2] = 0x0e; send_buffer[3] = 0x41; - send_buffer[4] = coeff & 0xff; - send_buffer[5] = coeff >> 8; + FIT16_ARR(send_buffer, 4, coeff); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) { @@ -389,8 +387,7 @@ static int t300rs_modify_damper(struct t300rs_device_entry *t300rs, send_buffer[2] = 0x0e; send_buffer[3] = 0x42; - send_buffer[4] = coeff & 0xff; - send_buffer[5] = coeff >> 8; + FIT16_ARR(send_buffer, 4, coeff); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) { @@ -401,7 +398,7 @@ static int t300rs_modify_damper(struct t300rs_device_entry *t300rs, } if ((damper.deadband != damper_old.deadband) || - (damper.center != damper_old.center)) { + (damper.center != damper_old.center)) { u16 deadband_right = 0xfffe - damper.deadband - damper.center; u16 deadband_left = 0xfffe - damper.deadband + damper.center; @@ -410,11 +407,8 @@ static int t300rs_modify_damper(struct t300rs_device_entry *t300rs, send_buffer[2] = 0x0e; send_buffer[3] = 0x4c; - send_buffer[4] = deadband_right & 0xff; - send_buffer[5] = deadband_right >> 8; - - send_buffer[6] = deadband_left & 0xff; - send_buffer[7] = deadband_left >> 8; + FIT16_ARR(send_buffer, 4, deadband_right); + FIT16_ARR(send_buffer, 6, deadband_left); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) { @@ -431,7 +425,6 @@ static int t300rs_modify_damper(struct t300rs_device_entry *t300rs, } error: - return ret; } @@ -448,15 +441,13 @@ static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, level = (periodic.magnitude * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; - if (periodic.magnitude != periodic_old.magnitude) { send_buffer[1] = effect.id + 1; send_buffer[2] = 0x0e; send_buffer[3] = 0x01; - send_buffer[4] = level & 0xff; - send_buffer[5] = level >> 8; + FIT16_ARR(send_buffer, 4, level); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) { @@ -469,13 +460,11 @@ static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, if (periodic.offset != periodic_old.offset) { s16 offset = periodic.offset; - send_buffer[1] = effect.id + 1; send_buffer[2] = 0x0e; send_buffer[3] = 0x02; - send_buffer[4] = offset & 0xff; - send_buffer[5] = offset >> 8; + FIT16_ARR(send_buffer, 4, offset); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) { @@ -488,13 +477,11 @@ static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, if (periodic.phase != periodic_old.phase) { s16 phase = periodic.phase; - send_buffer[1] = effect.id + 1; send_buffer[2] = 0x0e; send_buffer[3] = 0x04; - send_buffer[4] = phase & 0xff; - send_buffer[5] = phase >> 8; + FIT16_ARR(send_buffer, 4, phase); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) { @@ -507,13 +494,11 @@ static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, if (periodic.period != periodic_old.period) { s16 period = periodic.period; - send_buffer[1] = effect.id + 1; send_buffer[2] = 0x0e; send_buffer[3] = 0x08; - send_buffer[4] = period & 0xff; - send_buffer[5] = period >> 8; + FIT16_ARR(send_buffer, 4, period); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) { @@ -530,7 +515,9 @@ static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, effect.replay.length, effect.id, periodic.envelope, - periodic_old.envelope); + periodic_old.envelope + ); + if (ret) { hid_err(t300rs->hdev, "failed modifying periodic envelope\n"); goto error; @@ -543,7 +530,6 @@ static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, } error: - return ret; } @@ -565,9 +551,11 @@ static int t300rs_upload_constant(struct t300rs_device_entry *t300rs, * constant envelope, but right now I don't know. */ - if (test_bit(FF_EFFECT_PLAYING, &state->flags) && - test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { + if (test_bit(FF_EFFECT_PLAYING, &state->flags) + && test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { + __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); + return t300rs_modify_constant(t300rs, state, send_buffer); } @@ -583,22 +571,10 @@ static int t300rs_upload_constant(struct t300rs_device_entry *t300rs, send_buffer[1] = effect.id + 1; send_buffer[2] = 0x6a; - send_buffer[3] = level & 0xff; - send_buffer[4] = level >> 8; + FIT16_ARR(send_buffer, 3, level); - t300rs_fill_envelope(send_buffer, 5, level, - duration, &constant.envelope); - - send_buffer[14] = 0x4f; - - send_buffer[15] = duration & 0xff; - send_buffer[16] = duration >> 8; - - send_buffer[19] = offset & 0xff; - send_buffer[20] = offset >> 8; - - send_buffer[22] = 0xff; - send_buffer[23] = 0xff; + t300rs_fill_envelope(send_buffer, 5, level, duration, &constant.envelope); + t300rs_fill_timing(send_buffer, 14, duration, offset); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) @@ -617,8 +593,8 @@ static int t300rs_upload_ramp(struct t300rs_device_entry *t300rs, u16 difference, offset, top, bottom, duration; s16 level; - if (test_bit(FF_EFFECT_PLAYING, &state->flags) && - test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { + if (test_bit(FF_EFFECT_PLAYING, &state->flags) + && test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); @@ -642,14 +618,9 @@ static int t300rs_upload_ramp(struct t300rs_device_entry *t300rs, send_buffer[1] = effect.id + 1; send_buffer[2] = 0x6b; - send_buffer[3] = difference & 0xff; - send_buffer[4] = difference >> 8; - - send_buffer[5] = level & 0xff; - send_buffer[6] = level >> 8; - - send_buffer[9] = duration & 0xff; - send_buffer[10] = duration >> 8; + FIT16_ARR(send_buffer, 3, difference); + FIT16_ARR(send_buffer, 5, level); + FIT16_ARR(send_buffer, 9, duration); send_buffer[12] = 0x80; @@ -657,16 +628,7 @@ static int t300rs_upload_ramp(struct t300rs_device_entry *t300rs, effect.replay.length, &ramp.envelope); send_buffer[22] = ramp.end_level > ramp.start_level ? 0x04 : 0x05; - send_buffer[23] = 0x4f; - - send_buffer[24] = duration & 0xff; - send_buffer[25] = duration >> 8; - - send_buffer[28] = offset & 0xff; - send_buffer[29] = offset >> 8; - - send_buffer[31] = 0xff; - send_buffer[32] = 0xff; + t300rs_fill_timing(send_buffer, 23, duration, offset); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) @@ -685,8 +647,8 @@ static int t300rs_upload_spring(struct t300rs_device_entry *t300rs, int ret, trans; u16 duration, right_coeff, left_coeff, deadband_right, deadband_left, offset; - if (test_bit(FF_EFFECT_PLAYING, &state->flags) && - test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { + if (test_bit(FF_EFFECT_PLAYING, &state->flags) + && test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); @@ -698,9 +660,6 @@ static int t300rs_upload_spring(struct t300rs_device_entry *t300rs, else duration = effect.replay.length; - send_buffer[1] = effect.id + 1; - send_buffer[2] = 0x64; - right_coeff = spring.right_coeff * spring_level / 100; left_coeff = spring.left_coeff * spring_level / 100; @@ -709,29 +668,16 @@ static int t300rs_upload_spring(struct t300rs_device_entry *t300rs, offset = effect.replay.delay; - send_buffer[3] = right_coeff & 0xff; - send_buffer[4] = right_coeff >> 8; - - send_buffer[5] = left_coeff & 0xff; - send_buffer[6] = left_coeff >> 8; - - send_buffer[7] = deadband_right & 0xff; - send_buffer[8] = deadband_right >> 8; + send_buffer[1] = effect.id + 1; + send_buffer[2] = 0x64; - send_buffer[9] = deadband_left & 0xff; - send_buffer[10] = deadband_left >> 8; + FIT16_ARR(send_buffer, 3, right_coeff); + FIT16_ARR(send_buffer, 5, left_coeff); + FIT16_ARR(send_buffer, 7, deadband_right); + FIT16_ARR(send_buffer, 9, deadband_left); memcpy(&send_buffer[11], spring_values, ARRAY_SIZE(spring_values)); - send_buffer[28] = 0x4f; - - send_buffer[29] = duration & 0xff; - send_buffer[30] = duration >> 8; - - send_buffer[33] = offset & 0xff; - send_buffer[34] = offset >> 8; - - send_buffer[36] = 0xff; - send_buffer[37] = 0xff; + t300rs_fill_timing(send_buffer, 28, duration, offset); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) @@ -751,7 +697,7 @@ static int t300rs_upload_damper(struct t300rs_device_entry *t300rs, u16 duration, right_coeff, left_coeff, deadband_right, deadband_left, offset; if (test_bit(FF_EFFECT_PLAYING, &state->flags) && - test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { + test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); @@ -767,10 +713,6 @@ static int t300rs_upload_damper(struct t300rs_device_entry *t300rs, if (state->effect.type == FF_FRICTION) input_level = friction_level; - - send_buffer[1] = effect.id + 1; - send_buffer[2] = 0x64; - right_coeff = spring.right_coeff * input_level / 100; left_coeff = spring.left_coeff * input_level / 100; @@ -779,29 +721,16 @@ static int t300rs_upload_damper(struct t300rs_device_entry *t300rs, offset = effect.replay.delay; - send_buffer[3] = right_coeff & 0xff; - send_buffer[4] = right_coeff >> 8; - - send_buffer[5] = left_coeff & 0xff; - send_buffer[6] = left_coeff >> 8; - - send_buffer[7] = deadband_right & 0xff; - send_buffer[8] = deadband_right >> 8; + send_buffer[1] = effect.id + 1; + send_buffer[2] = 0x64; - send_buffer[9] = deadband_left & 0xff; - send_buffer[10] = deadband_left >> 8; + FIT16_ARR(send_buffer, 3, right_coeff); + FIT16_ARR(send_buffer, 5, left_coeff); + FIT16_ARR(send_buffer, 7, deadband_right); + FIT16_ARR(send_buffer, 9, deadband_left); memcpy(&send_buffer[11], damper_values, ARRAY_SIZE(damper_values)); - send_buffer[28] = 0x4f; - - send_buffer[29] = duration & 0xff; - send_buffer[30] = duration >> 8; - - send_buffer[33] = offset & 0xff; - send_buffer[34] = offset >> 8; - - send_buffer[36] = 0xff; - send_buffer[37] = 0xff; + t300rs_fill_timing(send_buffer, 28, duration, offset); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) @@ -821,7 +750,7 @@ static int t300rs_upload_periodic(struct t300rs_device_entry *t300rs, s16 periodic_offset; if (test_bit(FF_EFFECT_PLAYING, &state->flags) && - test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { + test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); @@ -840,21 +769,13 @@ static int t300rs_upload_periodic(struct t300rs_device_entry *t300rs, period = periodic.period; offset = effect.replay.delay; - send_buffer[1] = effect.id + 1; send_buffer[2] = 0x6b; - send_buffer[3] = magnitude & 0xff; - send_buffer[4] = magnitude >> 8; - - send_buffer[7] = phase & 0xff; - send_buffer[8] = phase >> 8; - - send_buffer[5] = periodic_offset & 0xff; - send_buffer[6] = periodic_offset >> 8; - - send_buffer[9] = period & 0xff; - send_buffer[10] = period >> 8; + FIT16_ARR(send_buffer, 3, magnitude); + FIT16_ARR(send_buffer, 5, periodic_offset); + FIT16_ARR(send_buffer, 7, phase); + FIT16_ARR(send_buffer, 9, period); send_buffer[12] = 0x80; @@ -862,16 +783,7 @@ static int t300rs_upload_periodic(struct t300rs_device_entry *t300rs, effect.replay.length, &periodic.envelope); send_buffer[21] = periodic.waveform - 0x57; - send_buffer[22] = 0x4f; - - send_buffer[23] = duration & 0xff; - send_buffer[24] = duration >> 8; - - send_buffer[27] = offset & 0xff; - send_buffer[28] = offset >> 8; - - send_buffer[30] = 0xff; - send_buffer[31] = 0xff; + t300rs_fill_timing(send_buffer, 22, duration, offset); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) @@ -884,21 +796,21 @@ static int t300rs_upload_effect(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state) { switch (state->effect.type) { - case FF_CONSTANT: - return t300rs_upload_constant(t300rs, state); - case FF_RAMP: - return t300rs_upload_ramp(t300rs, state); - case FF_SPRING: - return t300rs_upload_spring(t300rs, state); - case FF_DAMPER: - case FF_FRICTION: - case FF_INERTIA: - return t300rs_upload_damper(t300rs, state); - case FF_PERIODIC: - return t300rs_upload_periodic(t300rs, state); - default: - hid_err(t300rs->hdev, "invalid effect type: %x", state->effect.type); - return -1; + case FF_CONSTANT: + return t300rs_upload_constant(t300rs, state); + case FF_RAMP: + return t300rs_upload_ramp(t300rs, state); + case FF_SPRING: + return t300rs_upload_spring(t300rs, state); + case FF_DAMPER: + case FF_FRICTION: + case FF_INERTIA: + return t300rs_upload_damper(t300rs, state); + case FF_PERIODIC: + return t300rs_upload_periodic(t300rs, state); + default: + hid_err(t300rs->hdev, "invalid effect type: %x", state->effect.type); + return -1; } } @@ -1060,13 +972,13 @@ static ssize_t spring_level_store(struct device *dev, { struct hid_device *hdev = to_hid_device(dev); unsigned int value; - int ret; + int ret; ret = kstrtouint(buf, 0, &value); - if (ret) { - hid_err(hdev, "kstrtouint failed at spring_level_store: %i", ret); - return ret; - } + if (ret) { + hid_err(hdev, "kstrtouint failed at spring_level_store: %i", ret); + return ret; + } if (value > 100) value = 100; @@ -1092,13 +1004,13 @@ static ssize_t damper_level_store(struct device *dev, { struct hid_device *hdev = to_hid_device(dev); unsigned int value; - int ret; + int ret; ret = kstrtouint(buf, 0, &value); - if (ret) { - hid_err(hdev, "kstrtouint failed at damper_level_store: %i", ret); - return ret; - } + if (ret) { + hid_err(hdev, "kstrtouint failed at damper_level_store: %i", ret); + return ret; + } if (value > 100) value = 100; @@ -1125,13 +1037,13 @@ static ssize_t friction_level_store(struct device *dev, { struct hid_device *hdev = to_hid_device(dev); unsigned int value; - int ret; + int ret; ret = kstrtouint(buf, 0, &value); - if (ret) { - hid_err(hdev, "kstrtouint failed at friction_level_store: %i", ret); - return ret; - } + if (ret) { + hid_err(hdev, "kstrtouint failed at friction_level_store: %i", ret); + return ret; + } if (value > 100) value = 100; @@ -1162,10 +1074,10 @@ static ssize_t range_store(struct device *dev, int ret, trans; ret = kstrtouint(buf, 0, &range); - if (ret) { - hid_err(hdev, "kstrtouint failed at range_store: %i", ret); - return ret; - } + if (ret) { + hid_err(hdev, "kstrtouint failed at range_store: %i", ret); + return ret; + } t300rs = t300rs_get_device(hdev); if (!t300rs) { @@ -1186,8 +1098,8 @@ static ssize_t range_store(struct device *dev, send_buffer[0] = 0x08; send_buffer[1] = 0x11; - send_buffer[2] = range & 0xff; - send_buffer[3] = range >> 8; + + FIT16_ARR(send_buffer, 2, range); ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); if (ret) { @@ -1247,8 +1159,7 @@ static void t300rs_set_autocenter(struct input_dev *dev, u16 value) send_buffer[0] = 0x08; send_buffer[1] = 0x03; - send_buffer[2] = value & 0xff; - send_buffer[3] = value >> 8; + FIT16_ARR(send_buffer, 2, value); ret = t300rs_send_int(dev, send_buffer, &trans); if (ret) @@ -1270,7 +1181,7 @@ static void t300rs_set_gain(struct input_dev *dev, u16 gain) send_buffer = t300rs->send_buffer; send_buffer[0] = 0x02; - send_buffer[1] = SCALE_VALUE_U16(gain, 8); + send_buffer[1] = (gain >> 8) & 0xff; ret = t300rs_send_int(dev, send_buffer, &trans); if (ret) @@ -1397,7 +1308,7 @@ static int t300rs_init(struct hid_device *hdev, const signed short *ff_bits) if (!drv_data) { hid_err(hdev, "private driver data not allocated\n"); ret = -ENOMEM; - goto err; + goto drvdata_err; } t300rs = kzalloc(sizeof(struct t300rs_device_entry), GFP_KERNEL); @@ -1441,19 +1352,19 @@ static int t300rs_init(struct hid_device *hdev, const signed short *ff_bits) t300rs->firmware_response, t300rs_firmware_request.wLength, USB_CTRL_SET_TIMEOUT - ); + ); // Educated guess if (t300rs->firmware_response->firmware_version < 31 && ret >= 0) { hid_err(t300rs->hdev, - "firmware version %i is too old, please update.", - t300rs->firmware_response->firmware_version - ); + "firmware version %i is too old, please update.", + t300rs->firmware_response->firmware_version + ); hid_info(t300rs->hdev, "note: this has to be done through Windows."); ret = -EINVAL; - goto out; + goto version_err; } spin_lock_init(&t300rs->lock); @@ -1473,7 +1384,7 @@ static int t300rs_init(struct hid_device *hdev, const signed short *ff_bits) ret = input_ff_create(input_dev, T300RS_MAX_EFFECTS); if (ret) { hid_err(hdev, "could not create input_ff\n"); - goto out; + goto input_ff_err; } ff = input_dev->ff; @@ -1494,7 +1405,7 @@ static int t300rs_init(struct hid_device *hdev, const signed short *ff_bits) // this might not be a catastrophic issue, but it could affect // programs such as oversteer, best play it safe hid_err(hdev, "could not create sysfs files\n"); - goto out; + goto sysfs_err; } @@ -1507,18 +1418,26 @@ static int t300rs_init(struct hid_device *hdev, const signed short *ff_bits) hid_info(hdev, "force feedback for T300RS\n"); return 0; -out: +sysfs_err: kfree(t300rs->firmware_response); + +input_ff_err: +version_err: firmware_err: kfree(t300rs->send_buffer); + send_err: kfree(t300rs->states); + states_err: kfree(t300rs); + t300rs_err: kfree(drv_data); -err: + +drvdata_err: hid_err(hdev, "failed creating force feedback device\n"); + return ret; } @@ -1556,7 +1475,7 @@ static int t300rs_probe(struct hid_device *hdev, const struct hid_device_id *id) hid_err(hdev, "t300rs_init failed\n"); goto err; } - return 0; + err: return ret; } @@ -1611,4 +1530,6 @@ static struct hid_driver t300rs_driver = { }; module_hid_driver(t300rs_driver); +#undef FIT16_ARR + MODULE_LICENSE("GPL"); -- cgit v1.3 From 00e68ba093778b5eb9e3b3f507daaad6a6997624 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 14 Jul 2021 22:58:28 +0300 Subject: More radical clean: functionality needs testing --- hid-tmt300rs.c | 659 +++++++++++++++++++++++++++++++-------------------------- hid-tmt300rs.h | 27 +++ 2 files changed, 382 insertions(+), 304 deletions(-) diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 7b615e0..3764fc8 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -17,8 +17,6 @@ static int friction_level = 30; module_param(friction_level, int, 0); MODULE_PARM_DESC(friction_level, "Level of friction force (0-100), as per Oversteer standards"); -#define FIT16_ARR(x, i, v) { (x)[(i)] = (v) & 0xff; (x)[(i) + 1] = ((v) >> 8) & 0xff; } - static struct t300rs_device_entry *t300rs_get_device(struct hid_device *hdev) { struct t300rs_data *drv_data; @@ -40,40 +38,41 @@ static struct t300rs_device_entry *t300rs_get_device(struct hid_device *hdev) return t300rs; } -static int t300rs_send_int(struct input_dev *dev, u8 *send_buffer, int *trans) +static int t300rs_send_int(struct t300rs_device_entry *t300rs) { - struct hid_device *hdev = input_get_drvdata(dev); - struct t300rs_device_entry *t300rs; int i; - - t300rs = t300rs_get_device(hdev); - if (!t300rs) { - hid_err(hdev, "could not get device\n"); - return -1; - } - for (i = 0; i < T300RS_BUFFER_LENGTH; ++i) - t300rs->ff_field->value[i] = send_buffer[i]; + t300rs->ff_field->value[i] = t300rs->send_buffer[i]; hid_hw_request(t300rs->hdev, t300rs->report, HID_REQ_SET_REPORT); - memset(send_buffer, 0, T300RS_BUFFER_LENGTH); + memset(t300rs->send_buffer, 0, T300RS_BUFFER_LENGTH); return 0; } +static void t300rs_fill_header(struct t300rs_packet_header *packet_header, + uint8_t id, uint8_t code) +{ + packet_header->id = id + 1; + packet_header->code = code; +} + static int t300rs_play_effect(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state) { - u8 *send_buffer = t300rs->send_buffer; - int ret, trans; + struct __packed t300rs_packet_play { + struct t300rs_packet_header header; + uint8_t value; + } *play_packet = (struct t300rs_packet_play *)t300rs->send_buffer; + + int ret; - send_buffer[1] = state->effect.id + 1; - send_buffer[2] = 0x89; - send_buffer[3] = 0x01; + t300rs_fill_header(&play_packet->header, state->effect.id, 0x89); + play_packet->value = 0x01; - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) hid_err(t300rs->hdev, "failed starting effect play\n"); @@ -83,75 +82,78 @@ static int t300rs_play_effect(struct t300rs_device_entry *t300rs, static int t300rs_stop_effect(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state) { - u8 *send_buffer = t300rs->send_buffer; - int ret, trans; + struct __packed t300rs_packet_stop { + struct t300rs_packet_header header; + uint8_t value; + } *stop_packet = (struct t300rs_packet_stop *)t300rs->send_buffer; + + int ret; - send_buffer[1] = state->effect.id + 1; - send_buffer[2] = 0x89; + t300rs_fill_header(&stop_packet->header, state->effect.id, 0x89); - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) hid_err(t300rs->hdev, "failed stopping effect play\n"); return ret; } -static void t300rs_fill_envelope(u8 *send_buffer, int i, s16 level, - u16 duration, struct ff_envelope *envelope) +static void t300rs_fill_envelope(struct t300rs_packet_envelope *packet_envelope, + int16_t level, uint16_t duration, struct ff_envelope *envelope) { - u16 attack_length = (duration * envelope->attack_length) / 0x7fff; - u16 attack_level = (level * envelope->attack_level) / 0x7fff; - u16 fade_length = (duration * envelope->fade_length) / 0x7fff; - u16 fade_level = (level * envelope->fade_level) / 0x7fff; - - FIT16_ARR(send_buffer, i + 0, attack_length); - FIT16_ARR(send_buffer, i + 2, attack_level); - FIT16_ARR(send_buffer, i + 4, fade_length); - FIT16_ARR(send_buffer, i + 6, fade_level); + uint16_t attack_length = (duration * envelope->attack_length) / 0x7fff; + uint16_t attack_level = (level * envelope->attack_level) / 0x7fff; + uint16_t fade_length = (duration * envelope->fade_length) / 0x7fff; + uint16_t fade_level = (level * envelope->fade_level) / 0x7fff; + + packet_envelope->attack_length = cpu_to_le16(attack_length); + packet_envelope->attack_level = cpu_to_le16(attack_level); + packet_envelope->fade_length = cpu_to_le16(fade_length); + packet_envelope->fade_level = cpu_to_le16(fade_level); } -static void t300rs_fill_timing(u8 *send_buffer, int i, u16 duration, u16 offset){ - send_buffer[i] = 0x4f; +static void t300rs_fill_timing(struct t300rs_packet_timing *packet_timing, + uint16_t duration, uint16_t offset){ + packet_timing->start_marker = 0x47; - FIT16_ARR(send_buffer, i + 1, duration); - FIT16_ARR(send_buffer, i + 5, offset); + packet_timing->duration = cpu_to_le16(duration); + packet_timing->offset = cpu_to_le16(offset); - send_buffer[i + 8] = 0xff; - send_buffer[i + 9] = 0xff; + packet_timing->end_marker = 0xffff; } static int t300rs_modify_envelope(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state, - u8 *send_buffer, - s16 level, - u16 duration, - u8 id, + int16_t level, + uint16_t duration, + uint8_t id, struct ff_envelope envelope, struct ff_envelope envelope_old ) { - u16 attack_length, attack_level, fade_length, fade_level; - int ret = 0, trans; + struct __packed t300rs_packet_mod_envelope { + struct t300rs_packet_header header; + uint8_t attribute; + uint16_t value; + } *packet_mod_envelope = (struct t300rs_packet_mod_envelope *)t300rs->send_buffer; - if (duration == 0) - duration = 0xffff; + uint16_t attack_length, attack_level, fade_length, fade_level; + int ret = 0; + + duration = duration - 1; attack_length = (duration * envelope.attack_length) / 0x7fff; attack_level = (level * envelope.attack_level) / 0x7fff; fade_length = (duration * envelope.fade_length) / 0x7fff; fade_level = (level * envelope.fade_level) / 0x7fff; - - send_buffer[1] = id + 1; - send_buffer[2] = 0x31; - if (envelope.attack_length != envelope_old.attack_length) { - send_buffer[3] = 0x81; - - FIT16_ARR(send_buffer, 4, attack_length); + t300rs_fill_header(&packet_mod_envelope->header, id, 0x31); + packet_mod_envelope->attribute = 0x81; + packet_mod_envelope->value = cpu_to_le16(attack_length); - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) { hid_err(t300rs->hdev, "failed modifying effect envelope\n"); goto error; @@ -159,11 +161,11 @@ static int t300rs_modify_envelope(struct t300rs_device_entry *t300rs, } if (envelope.attack_level != envelope_old.attack_level) { - send_buffer[3] = 0x82; - - FIT16_ARR(send_buffer, 4, attack_level); + t300rs_fill_header(&packet_mod_envelope->header, id, 0x31); + packet_mod_envelope->attribute = 0x82; + packet_mod_envelope->value = cpu_to_le16(attack_level); - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) { hid_err(t300rs->hdev, "failed modifying effect envelope\n"); goto error; @@ -171,11 +173,11 @@ static int t300rs_modify_envelope(struct t300rs_device_entry *t300rs, } if (envelope.fade_length != envelope_old.fade_length) { - send_buffer[3] = 0x84; + t300rs_fill_header(&packet_mod_envelope->header, id, 0x31); + packet_mod_envelope->attribute = 0x84; + packet_mod_envelope->value = cpu_to_le16(fade_length); - FIT16_ARR(send_buffer, 4, fade_length); - - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) { hid_err(t300rs->hdev, "failed modifying effect envelope\n"); goto error; @@ -183,11 +185,11 @@ static int t300rs_modify_envelope(struct t300rs_device_entry *t300rs, } if (envelope.fade_level != envelope_old.fade_level) { - send_buffer[3] = 0x88; - - FIT16_ARR(send_buffer, 4, fade_level); + t300rs_fill_header(&packet_mod_envelope->header, id, 0x31); + packet_mod_envelope->attribute = 0x88; + packet_mod_envelope->value = cpu_to_le16(fade_level); - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) { hid_err(t300rs->hdev, "failed modifying effect envelope\n"); goto error; @@ -199,27 +201,29 @@ error: } static int t300rs_modify_duration(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state, u8 *send_buffer) + struct t300rs_effect_state *state) { struct ff_effect effect = state->effect; struct ff_effect old = state->old; - u16 duration; - int ret = 0, trans; + struct t300rs_packet_mod_duration { + struct t300rs_packet_header header; + padding: 8; + uint8_t marker; + uint16_t duration; + } *packet_mod_duration = (struct t300rs_packet_mod_duration *)t300rs->send_buffer; - if (effect.replay.length == 0) - duration = 0xffff; - else - duration = effect.replay.length; + uint16_t duration; + int ret = 0; - if (effect.replay.length != old.replay.length) { + duration = effect.replay.length - 1; - send_buffer[1] = effect.id + 1; - send_buffer[2] = 0x49; - send_buffer[4] = 0x41; + if (effect.replay.length != old.replay.length) { - FIT16_ARR(send_buffer, 5, duration); + t300rs_fill_header(&packet_mod_duration->header, effect.id, 0x49); + packet_mod_duration->marker = 0x41; + packet_mod_duration->duration = cpu_to_le16(duration); - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) { hid_err(t300rs->hdev, "failed modifying duration\n"); goto error; @@ -231,25 +235,27 @@ error: } static int t300rs_modify_constant(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state, u8 *send_buffer) + struct t300rs_effect_state *state) { struct ff_effect effect = state->effect; struct ff_effect old = state->old; struct ff_constant_effect constant = effect.u.constant; struct ff_constant_effect constant_old = old.u.constant; - int ret, trans; - s16 level; + struct __packed t300rs_packet_mod_constant { + struct t300rs_packet_header header; + uint8_t level; + } *packet_mod_constant = (struct t300rs_packet_mod_constant *)t300rs->send_buffer; + int ret; + int16_t level; level = (constant.level * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; if (constant.level != constant_old.level) { - send_buffer[1] = effect.id + 1; - send_buffer[2] = 0x0a; - - FIT16_ARR(send_buffer, 3, level); + t300rs_fill_header(&packet_mod_constant->header, effect.id, 0x0a); + packet_mod_constant->level = level; - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) { hid_err(t300rs->hdev, "failed modifying constant effect\n"); goto error; @@ -259,7 +265,6 @@ static int t300rs_modify_constant(struct t300rs_device_entry *t300rs, ret = t300rs_modify_envelope(t300rs, state, - send_buffer, level, effect.replay.length, effect.id, @@ -272,7 +277,7 @@ static int t300rs_modify_constant(struct t300rs_device_entry *t300rs, goto error; } - ret = t300rs_modify_duration(t300rs, state, send_buffer); + ret = t300rs_modify_duration(t300rs, state); if (ret) { hid_err(t300rs->hdev, "failed modifying constant duration\n"); goto error; @@ -283,16 +288,23 @@ error: } static int t300rs_modify_ramp(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state, u8 *send_buffer) + struct t300rs_effect_state *state) { struct ff_effect effect = state->effect; struct ff_effect old = state->old; struct ff_ramp_effect ramp = effect.u.ramp; struct ff_ramp_effect ramp_old = old.u.ramp; - int ret, trans; + struct __packed t300rs_packet_mod_ramp { + struct t300rs_packet_header header; + uint8_t attribute; + uint16_t difference; + uint16_t level; + } *packet_mod_ramp = (struct t300rs_packet_mod_ramp *)t300rs->send_buffer; + + int ret; - u16 difference, top, bottom; - s16 level; + uint16_t difference, top, bottom; + int16_t level; top = ramp.end_level > ramp.start_level ? ramp.end_level : ramp.start_level; bottom = ramp.end_level > ramp.start_level ? ramp.start_level : ramp.end_level; @@ -305,14 +317,12 @@ static int t300rs_modify_ramp(struct t300rs_device_entry *t300rs, if (ramp.start_level != ramp_old.start_level || ramp.end_level != ramp_old.end_level) { - send_buffer[1] = effect.id + 1; - send_buffer[2] = 0x0e; - send_buffer[3] = 0x03; + t300rs_fill_header(&packet_mod_ramp->header, effect.id, 0x0e); + packet_mod_ramp->attribute = 0x03; + packet_mod_ramp->difference = cpu_to_le16(difference); + packet_mod_ramp->level = cpu_to_le16(level); - FIT16_ARR(send_buffer, 4, difference); - FIT16_ARR(send_buffer, 6, level); - - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) { hid_err(t300rs->hdev, "failed modifying ramp effect\n"); goto error; @@ -322,7 +332,6 @@ static int t300rs_modify_ramp(struct t300rs_device_entry *t300rs, ret = t300rs_modify_envelope(t300rs, state, - send_buffer, level, effect.replay.length, effect.id, @@ -336,7 +345,7 @@ static int t300rs_modify_ramp(struct t300rs_device_entry *t300rs, goto error; } - ret = t300rs_modify_duration(t300rs, state, send_buffer); + ret = t300rs_modify_duration(t300rs, state); if (ret) { hid_err(t300rs->hdev, "failed modifying ramp duration\n"); goto error; @@ -346,13 +355,20 @@ error: return ret; } static int t300rs_modify_damper(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state, u8 *send_buffer) + struct t300rs_effect_state *state) { struct ff_effect effect = state->effect; struct ff_effect old = state->old; struct ff_condition_effect damper = effect.u.condition[0]; struct ff_condition_effect damper_old = old.u.condition[0]; - int ret, trans, input_level; + struct __packed t300rs_packet_mod_damper { + struct t300rs_packet_header header; + uint8_t attribute; + uint16_t value0; + uint16_t value1; + } *packet_mod_damper = (struct t300rs_packet_mod_damper *)t300rs->send_buffer; + + int ret, input_level; input_level = damper_level; if (state->effect.type == FF_FRICTION) @@ -362,16 +378,13 @@ static int t300rs_modify_damper(struct t300rs_device_entry *t300rs, input_level = spring_level; if (damper.right_coeff != damper_old.right_coeff) { - s16 coeff = damper.right_coeff * input_level / 100; - + int16_t coeff = damper.right_coeff * input_level / 100; - send_buffer[1] = effect.id + 1; - send_buffer[2] = 0x0e; - send_buffer[3] = 0x41; + t300rs_fill_header(&packet_mod_damper->header, effect.id, 0x0e); + packet_mod_damper->attribute = 0x41; + packet_mod_damper->value0 = cpu_to_le16(coeff); - FIT16_ARR(send_buffer, 4, coeff); - - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) { hid_err(t300rs->hdev, "failed modifying damper rc\n"); goto error; @@ -380,16 +393,13 @@ static int t300rs_modify_damper(struct t300rs_device_entry *t300rs, } if (damper.left_coeff != damper_old.left_coeff) { - s16 coeff = damper.left_coeff * input_level / 100; - - - send_buffer[1] = effect.id + 1; - send_buffer[2] = 0x0e; - send_buffer[3] = 0x42; + int16_t coeff = damper.left_coeff * input_level / 100; - FIT16_ARR(send_buffer, 4, coeff); + t300rs_fill_header(&packet_mod_damper->header, effect.id, 0x0e); + packet_mod_damper->attribute = 0x42; + packet_mod_damper->value0 = cpu_to_le16(coeff); - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) { hid_err(t300rs->hdev, "failed modifying damper lc\n"); goto error; @@ -397,20 +407,18 @@ static int t300rs_modify_damper(struct t300rs_device_entry *t300rs, } - if ((damper.deadband != damper_old.deadband) || - (damper.center != damper_old.center)) { - u16 deadband_right = 0xfffe - damper.deadband - damper.center; - u16 deadband_left = 0xfffe - damper.deadband + damper.center; + if ((damper.deadband != damper_old.deadband) + || (damper.center != damper_old.center)) { + uint16_t right_deadband = 0xfffe - damper.deadband - damper.center; + uint16_t left_deadband = 0xfffe - damper.deadband + damper.center; - send_buffer[1] = effect.id + 1; - send_buffer[2] = 0x0e; - send_buffer[3] = 0x4c; + t300rs_fill_header(&packet_mod_damper->header, effect.id, 0x0e); + packet_mod_damper->attribute = 0x4c; + packet_mod_damper->value0 = cpu_to_le16(right_deadband); + packet_mod_damper->value1 = cpu_to_le16(left_deadband); - FIT16_ARR(send_buffer, 4, deadband_right); - FIT16_ARR(send_buffer, 6, deadband_left); - - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) { hid_err(t300rs->hdev, "failed modifying damper deadband\n"); goto error; @@ -418,7 +426,7 @@ static int t300rs_modify_damper(struct t300rs_device_entry *t300rs, } - ret = t300rs_modify_duration(t300rs, state, send_buffer); + ret = t300rs_modify_duration(t300rs, state); if (ret) { hid_err(t300rs->hdev, "failed modifying damper duration\n"); goto error; @@ -430,26 +438,30 @@ error: static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state, u8 *send_buffer) + struct t300rs_effect_state *state) { struct ff_effect effect = state->effect; struct ff_effect old = state->old; struct ff_periodic_effect periodic = effect.u.periodic; struct ff_periodic_effect periodic_old = old.u.periodic; - int ret, trans; - s16 level; + struct __packed t300rs_packet_mod_periodic { + struct t300rs_packet_header header; + uint8_t attribute; + uint16_t value; + } *packet_mod_periodic = (struct t300rs_packet_mod_periodic *)t300rs->send_buffer; + + int ret; + int16_t level; level = (periodic.magnitude * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; if (periodic.magnitude != periodic_old.magnitude) { - send_buffer[1] = effect.id + 1; - send_buffer[2] = 0x0e; - send_buffer[3] = 0x01; - - FIT16_ARR(send_buffer, 4, level); + t300rs_fill_header(&packet_mod_periodic->header, effect.id, 0x0e); + packet_mod_periodic->attribute = 0x01; + packet_mod_periodic->value = cpu_to_le16(level); - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) { hid_err(t300rs->hdev, "failed modifying periodic magnitude\n"); goto error; @@ -458,15 +470,13 @@ static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, } if (periodic.offset != periodic_old.offset) { - s16 offset = periodic.offset; + int16_t offset = periodic.offset; - send_buffer[1] = effect.id + 1; - send_buffer[2] = 0x0e; - send_buffer[3] = 0x02; + t300rs_fill_header(&packet_mod_periodic->header, effect.id, 0x0e); + packet_mod_periodic->attribute = 0x02; + packet_mod_periodic->value = cpu_to_le16(offset); - FIT16_ARR(send_buffer, 4, offset); - - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) { hid_err(t300rs->hdev, "failed modifying periodic offset\n"); goto error; @@ -475,15 +485,13 @@ static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, } if (periodic.phase != periodic_old.phase) { - s16 phase = periodic.phase; - - send_buffer[1] = effect.id + 1; - send_buffer[2] = 0x0e; - send_buffer[3] = 0x04; + int16_t phase = periodic.phase; - FIT16_ARR(send_buffer, 4, phase); + t300rs_fill_header(&packet_mod_periodic->header, effect.id, 0x0e); + packet_mod_periodic->attribute = 0x04; + packet_mod_periodic->value = phase; - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) { hid_err(t300rs->hdev, "failed modifying periodic phase\n"); goto error; @@ -492,15 +500,13 @@ static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, } if (periodic.period != periodic_old.period) { - s16 period = periodic.period; + int16_t period = periodic.period; - send_buffer[1] = effect.id + 1; - send_buffer[2] = 0x0e; - send_buffer[3] = 0x08; + t300rs_fill_header(&packet_mod_periodic->header, effect.id, 0x0e); + packet_mod_periodic->attribute = 0x08; + packet_mod_periodic->value = period; - FIT16_ARR(send_buffer, 4, period); - - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) { hid_err(t300rs->hdev, "failed modifying periodic period\n"); goto error; @@ -510,7 +516,6 @@ static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, ret = t300rs_modify_envelope(t300rs, state, - send_buffer, level, effect.replay.length, effect.id, @@ -523,7 +528,7 @@ static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, goto error; } - ret = t300rs_modify_duration(t300rs, state, send_buffer); + ret = t300rs_modify_duration(t300rs, state); if (ret) { hid_err(t300rs->hdev, "failed modifying periodic duration\n"); goto error; @@ -533,17 +538,22 @@ error: return ret; } - static int t300rs_upload_constant(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state) { - u8 *send_buffer = t300rs->send_buffer; struct ff_effect effect = state->effect; struct ff_constant_effect constant = state->effect.u.constant; - s16 level; - u16 duration, offset; + struct __packed t300rs_packet_constant { + struct t300rs_packet_header header; + uint16_t level; + struct t300rs_packet_envelope envelope; + struct t300rs_packet_timing timing; + } *packet_constant = (struct t300rs_packet_constant *)t300rs->send_buffer; - int ret, trans; + int16_t level; + uint16_t duration, offset; + + int ret; /* some games, such as DiRT Rally 2 have a weird feeling to them, sort of * like the wheel pulls just a bit to the right or left and then it just @@ -556,27 +566,23 @@ static int t300rs_upload_constant(struct t300rs_device_entry *t300rs, __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); - return t300rs_modify_constant(t300rs, state, send_buffer); + return t300rs_modify_constant(t300rs, state); } level = (constant.level * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; - if (effect.replay.length == 0) - duration = 0xffff; - else - duration = effect.replay.length; + duration = effect.replay.length - 1; offset = effect.replay.delay; + t300rs_fill_header(&packet_constant->header, effect.id, 0x6a); - send_buffer[1] = effect.id + 1; - send_buffer[2] = 0x6a; - - FIT16_ARR(send_buffer, 3, level); + packet_constant->level = cpu_to_le16(level); - t300rs_fill_envelope(send_buffer, 5, level, duration, &constant.envelope); - t300rs_fill_timing(send_buffer, 14, duration, offset); + t300rs_fill_envelope(&packet_constant->envelope, level, duration, + &constant.envelope); + t300rs_fill_timing(&packet_constant->timing, duration, offset); - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) hid_err(t300rs->hdev, "failed uploading constant effect\n"); @@ -586,25 +592,32 @@ static int t300rs_upload_constant(struct t300rs_device_entry *t300rs, static int t300rs_upload_ramp(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state) { - u8 *send_buffer = t300rs->send_buffer; struct ff_effect effect = state->effect; struct ff_ramp_effect ramp = state->effect.u.ramp; - int ret, trans; - u16 difference, offset, top, bottom, duration; - s16 level; + struct __packed t300rs_packet_ramp { + struct t300rs_packet_header header; + uint16_t difference; + uint16_t level; + uint16_t duration; + uint8_t marker; + uint8_t direction; + struct t300rs_packet_envelope envelope; + struct t300rs_packet_timing timing; + } *packet_ramp = (struct t300rs_packet_ramp *)t300rs->send_buffer; + + int ret; + uint16_t difference, offset, top, bottom, duration; + int16_t level; if (test_bit(FF_EFFECT_PLAYING, &state->flags) && test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); - return t300rs_modify_ramp(t300rs, state, send_buffer); + return t300rs_modify_ramp(t300rs, state); } - if (effect.replay.length == 0) - duration = 0xffff; - else - duration = effect.replay.length; + duration = effect.replay.length - 1; top = ramp.end_level > ramp.start_level ? ramp.end_level : ramp.start_level; bottom = ramp.end_level > ramp.start_level ? ramp.start_level : ramp.end_level; @@ -615,22 +628,21 @@ static int t300rs_upload_ramp(struct t300rs_device_entry *t300rs, offset = effect.replay.delay; - send_buffer[1] = effect.id + 1; - send_buffer[2] = 0x6b; + t300rs_fill_header(&packet_ramp->header, effect.id, 0x6b); - FIT16_ARR(send_buffer, 3, difference); - FIT16_ARR(send_buffer, 5, level); - FIT16_ARR(send_buffer, 9, duration); + packet_ramp->difference = cpu_to_le16(difference); + packet_ramp->level = cpu_to_le16(level); + packet_ramp->duration = cpu_to_le16(duration); - send_buffer[12] = 0x80; + packet_ramp->marker = 0x80; - t300rs_fill_envelope(send_buffer, 13, level, - effect.replay.length, &ramp.envelope); + t300rs_fill_envelope(&packet_ramp->envelope, level, duration, + &ramp.envelope); - send_buffer[22] = ramp.end_level > ramp.start_level ? 0x04 : 0x05; - t300rs_fill_timing(send_buffer, 23, duration, offset); + packet_ramp->direction = ramp.end_level > ramp.start_level ? 0x04 : 0x05; + t300rs_fill_timing(&packet_ramp->timing, duration, offset); - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) hid_err(t300rs->hdev, "failed uploading ramp"); @@ -640,46 +652,52 @@ static int t300rs_upload_ramp(struct t300rs_device_entry *t300rs, static int t300rs_upload_spring(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state) { - u8 *send_buffer = t300rs->send_buffer; struct ff_effect effect = state->effect; /* we only care about the first axis */ struct ff_condition_effect spring = state->effect.u.condition[0]; - int ret, trans; - u16 duration, right_coeff, left_coeff, deadband_right, deadband_left, offset; + struct __packed t300rs_packet_spring { + struct t300rs_packet_header header; + uint16_t right_coeff; + uint16_t left_coeff; + uint16_t right_deadband; + uint16_t left_deadband; + uint8_t spring_start[17]; + struct t300rs_packet_envelope envelope; + struct t300rs_packet_timing timing; + } *packet_spring = (struct t300rs_packet_spring *)t300rs->send_buffer; + + int ret; + uint16_t duration, right_coeff, left_coeff, right_deadband, left_deadband, offset; if (test_bit(FF_EFFECT_PLAYING, &state->flags) && test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); - return t300rs_modify_damper(t300rs, state, send_buffer); + return t300rs_modify_damper(t300rs, state); } - if (effect.replay.length == 0) - duration = 0xffff; - else - duration = effect.replay.length; + duration = effect.replay.length - 1; right_coeff = spring.right_coeff * spring_level / 100; left_coeff = spring.left_coeff * spring_level / 100; - deadband_right = 0xfffe - spring.deadband - spring.center; - deadband_left = 0xfffe - spring.deadband + spring.center; + right_deadband = 0xfffe - spring.deadband - spring.center; + left_deadband = 0xfffe - spring.deadband + spring.center; offset = effect.replay.delay; - send_buffer[1] = effect.id + 1; - send_buffer[2] = 0x64; + t300rs_fill_header(&packet_spring->header, effect.id, 0x64); - FIT16_ARR(send_buffer, 3, right_coeff); - FIT16_ARR(send_buffer, 5, left_coeff); - FIT16_ARR(send_buffer, 7, deadband_right); - FIT16_ARR(send_buffer, 9, deadband_left); + packet_spring->right_coeff = right_coeff; + packet_spring->left_coeff = left_coeff; + packet_spring->right_deadband = right_deadband; + packet_spring->left_deadband = left_deadband; - memcpy(&send_buffer[11], spring_values, ARRAY_SIZE(spring_values)); - t300rs_fill_timing(send_buffer, 28, duration, offset); + memcpy(&packet_spring->spring_start, spring_values, ARRAY_SIZE(spring_values)); + t300rs_fill_timing(&packet_spring->timing, duration, offset); - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) hid_err(t300rs->hdev, "failed uploading spring\n"); @@ -689,25 +707,34 @@ static int t300rs_upload_spring(struct t300rs_device_entry *t300rs, static int t300rs_upload_damper(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state) { - u8 *send_buffer = t300rs->send_buffer; + struct ff_effect effect = state->effect; /* we only care about the first axis */ struct ff_condition_effect spring = state->effect.u.condition[0]; - int ret, trans, input_level; - u16 duration, right_coeff, left_coeff, deadband_right, deadband_left, offset; + struct __packed t300rs_packet_damper { + struct t300rs_packet_header header; + uint16_t right_coeff; + uint16_t left_coeff; + uint16_t right_deadband; + uint16_t left_deadband; + /* space for spring const */ + uint8_t damper_start[17]; + struct t300rs_packet_envelope envelope; + struct t300rs_packet_timing timing; + } *packet_damper = (struct t300rs_packet_damper *)t300rs->send_buffer; + + int ret, input_level; + uint16_t duration, right_coeff, left_coeff, right_deadband, left_deadband, offset; if (test_bit(FF_EFFECT_PLAYING, &state->flags) && test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); - return t300rs_modify_damper(t300rs, state, send_buffer); + return t300rs_modify_damper(t300rs, state); } - if (effect.replay.length == 0) - duration = 0xffff; - else - duration = effect.replay.length; + duration = effect.replay.length - 1; input_level = damper_level; if (state->effect.type == FF_FRICTION) @@ -716,23 +743,22 @@ static int t300rs_upload_damper(struct t300rs_device_entry *t300rs, right_coeff = spring.right_coeff * input_level / 100; left_coeff = spring.left_coeff * input_level / 100; - deadband_right = 0xfffe - spring.deadband - spring.center; - deadband_left = 0xfffe - spring.deadband + spring.center; + right_deadband = 0xfffe - spring.deadband - spring.center; + left_deadband = 0xfffe - spring.deadband + spring.center; offset = effect.replay.delay; - send_buffer[1] = effect.id + 1; - send_buffer[2] = 0x64; + t300rs_fill_header(&packet_damper->header, effect.id, 0x64); - FIT16_ARR(send_buffer, 3, right_coeff); - FIT16_ARR(send_buffer, 5, left_coeff); - FIT16_ARR(send_buffer, 7, deadband_right); - FIT16_ARR(send_buffer, 9, deadband_left); + packet_damper->right_coeff = right_coeff; + packet_damper->left_coeff = left_coeff; + packet_damper->right_deadband = right_deadband; + packet_damper->left_deadband = left_deadband; - memcpy(&send_buffer[11], damper_values, ARRAY_SIZE(damper_values)); - t300rs_fill_timing(send_buffer, 28, duration, offset); + memcpy(&packet_damper->damper_start, damper_values, ARRAY_SIZE(damper_values)); + t300rs_fill_timing(&packet_damper->timing, duration, offset); - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) hid_err(t300rs->hdev, "failed uploading spring\n"); @@ -742,25 +768,34 @@ static int t300rs_upload_damper(struct t300rs_device_entry *t300rs, static int t300rs_upload_periodic(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state) { - u8 *send_buffer = t300rs->send_buffer; struct ff_effect effect = state->effect; struct ff_periodic_effect periodic = state->effect.u.periodic; - int ret, trans; - u16 duration, magnitude, phase, period, offset; - s16 periodic_offset; + struct __packed t300rs_packet_periodic { + struct t300rs_packet_header header; + uint16_t magnitude; + uint16_t periodic_offset; + uint16_t phase; + uint16_t period; +padding : 8; + uint8_t marker; + struct t300rs_packet_envelope envelope; + uint8_t waveform; + struct t300rs_packet_timing timing; + } *packet_periodic = (struct t300rs_packet_periodic *)t300rs->send_buffer; + + int ret; + uint16_t duration, magnitude, phase, period, offset; + int16_t periodic_offset; if (test_bit(FF_EFFECT_PLAYING, &state->flags) && test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); - return t300rs_modify_periodic(t300rs, state, send_buffer); + return t300rs_modify_periodic(t300rs, state); } - if (effect.replay.length == 0) - duration = 0xffff; - else - duration = effect.replay.length; + duration = effect.replay.length - 1; magnitude = (periodic.magnitude * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; @@ -769,23 +804,23 @@ static int t300rs_upload_periodic(struct t300rs_device_entry *t300rs, period = periodic.period; offset = effect.replay.delay; - send_buffer[1] = effect.id + 1; - send_buffer[2] = 0x6b; + t300rs_fill_header(&packet_periodic->header, effect.id, 0x6b); - FIT16_ARR(send_buffer, 3, magnitude); - FIT16_ARR(send_buffer, 5, periodic_offset); - FIT16_ARR(send_buffer, 7, phase); - FIT16_ARR(send_buffer, 9, period); + packet_periodic->magnitude = magnitude; + packet_periodic->periodic_offset = periodic_offset; + packet_periodic->phase = phase; + packet_periodic->period = period; - send_buffer[12] = 0x80; + packet_periodic->marker = 0x80; - t300rs_fill_envelope(send_buffer, 13, magnitude, - effect.replay.length, &periodic.envelope); + t300rs_fill_envelope(&packet_periodic->envelope, magnitude, duration, + &periodic.envelope); - send_buffer[21] = periodic.waveform - 0x57; - t300rs_fill_timing(send_buffer, 22, duration, offset); + packet_periodic->waveform = periodic.waveform - 0x57; - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + t300rs_fill_timing(&packet_periodic->timing, duration, offset); + + ret = t300rs_send_int(t300rs); if (ret) hid_err(t300rs->hdev, "failed uploading periodic effect"); @@ -1069,9 +1104,13 @@ static ssize_t range_store(struct device *dev, { struct hid_device *hdev = to_hid_device(dev); struct t300rs_device_entry *t300rs; - u8 *send_buffer; + struct __packed t300rs_packet_range { + struct t300rs_setup_header header; + uint16_t range; + } *packet_range; + unsigned int range; - int ret, trans; + int ret; ret = kstrtouint(buf, 0, &range); if (ret) { @@ -1085,7 +1124,7 @@ static ssize_t range_store(struct device *dev, return -1; } - send_buffer = t300rs->send_buffer; + packet_range = (struct t300rs_packet_range *)t300rs->send_buffer; if (range < 40) range = 40; @@ -1096,12 +1135,12 @@ static ssize_t range_store(struct device *dev, range *= 0x3c; - send_buffer[0] = 0x08; - send_buffer[1] = 0x11; + packet_range->header.cmd = 0x08; + packet_range->header.code = 0x11; - FIT16_ARR(send_buffer, 2, range); + packet_range->range = cpu_to_le16(range); - ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) { hid_err(hdev, "failed sending interrupts\n"); return -1; @@ -1131,12 +1170,16 @@ static ssize_t range_show(struct device *dev, static DEVICE_ATTR_RW(range); -static void t300rs_set_autocenter(struct input_dev *dev, u16 value) +static void t300rs_set_autocenter(struct input_dev *dev, uint16_t value) { struct hid_device *hdev = input_get_drvdata(dev); struct t300rs_device_entry *t300rs; - u8 *send_buffer; - int ret, trans; + struct __packed t300rs_packet_autocenter { + struct t300rs_setup_header header; + uint16_t value; + } *autocenter_packet; + + int ret; t300rs = t300rs_get_device(hdev); if (!t300rs) { @@ -1144,34 +1187,37 @@ static void t300rs_set_autocenter(struct input_dev *dev, u16 value) return; } - send_buffer = t300rs->send_buffer; + autocenter_packet = (struct t300rs_packet_autocenter *)t300rs->send_buffer; - send_buffer[0] = 0x08; - send_buffer[1] = 0x04; - send_buffer[2] = 0x01; + autocenter_packet->header.cmd = 0x08; + autocenter_packet->header.code = 0x04; + autocenter_packet->value = cpu_to_le16(0x01); - ret = t300rs_send_int(dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) { hid_err(hdev, "failed setting autocenter"); return; } - send_buffer[0] = 0x08; - send_buffer[1] = 0x03; + autocenter_packet->header.cmd = 0x08; + autocenter_packet->header.code = 0x03; - FIT16_ARR(send_buffer, 2, value); + autocenter_packet->value = cpu_to_le16(value); - ret = t300rs_send_int(dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) hid_err(hdev, "failed setting autocenter"); } -static void t300rs_set_gain(struct input_dev *dev, u16 gain) +static void t300rs_set_gain(struct input_dev *dev, uint16_t gain) { struct hid_device *hdev = input_get_drvdata(dev); struct t300rs_device_entry *t300rs; - u8 *send_buffer; - int ret, trans; + struct __packed t300rs_packet_gain { + struct t300rs_setup_header header; + } *gain_packet; + + int ret; t300rs = t300rs_get_device(hdev); if (!t300rs) { @@ -1179,11 +1225,12 @@ static void t300rs_set_gain(struct input_dev *dev, u16 gain) return; } - send_buffer = t300rs->send_buffer; - send_buffer[0] = 0x02; - send_buffer[1] = (gain >> 8) & 0xff; + gain_packet = (struct t300rs_packet_gain *)t300rs->send_buffer; + + gain_packet->header.cmd = 0x02; + gain_packet->header.code = (gain >> 8) & 0xff; - ret = t300rs_send_int(dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) hid_err(hdev, "failed setting gain: %i\n", ret); } @@ -1197,8 +1244,11 @@ static int t300rs_open(struct input_dev *dev) { struct t300rs_device_entry *t300rs; struct hid_device *hdev = input_get_drvdata(dev); - u8 *send_buffer; - int ret, trans; + struct __packed t300rs_packet_open { + struct t300rs_setup_header header; + } *open_packet; + + int ret; t300rs = t300rs_get_device(hdev); if (!t300rs) { @@ -1206,12 +1256,12 @@ static int t300rs_open(struct input_dev *dev) return -1; } - send_buffer = t300rs->send_buffer; + open_packet = (struct t300rs_packet_open *)t300rs->send_buffer; - send_buffer[0] = 0x01; - send_buffer[1] = 0x05; + open_packet->header.cmd = 0x01; + open_packet->header.code = 0x05; - ret = t300rs_send_int(dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) { hid_err(hdev, "failed sending interrupts\n"); goto err; @@ -1223,10 +1273,13 @@ err: static void t300rs_close(struct input_dev *dev) { - int ret, trans; - struct hid_device *hdev = input_get_drvdata(dev); struct t300rs_device_entry *t300rs; - u8 *send_buffer; + struct hid_device *hdev = input_get_drvdata(dev); + struct t300rs_packet_close { + struct t300rs_setup_header header; + } *close_packet; + + int ret; t300rs = t300rs_get_device(hdev); if (!t300rs) { @@ -1234,11 +1287,11 @@ static void t300rs_close(struct input_dev *dev) return; } - send_buffer = t300rs->send_buffer; + close_packet = (struct t300rs_packet_close *)t300rs->send_buffer; - send_buffer[0] = 0x01; + close_packet->header.cmd = 0x01; - ret = t300rs_send_int(dev, send_buffer, &trans); + ret = t300rs_send_int(t300rs); if (ret) { hid_err(hdev, "failed sending interrupts\n"); goto err; @@ -1530,6 +1583,4 @@ static struct hid_driver t300rs_driver = { }; module_hid_driver(t300rs_driver); -#undef FIT16_ARR - MODULE_LICENSE("GPL"); diff --git a/hid-tmt300rs.h b/hid-tmt300rs.h index 496ba8f..7566f1a 100644 --- a/hid-tmt300rs.h +++ b/hid-tmt300rs.h @@ -73,6 +73,33 @@ struct __packed t300rs_firmware_response { uint8_t unknown2; }; +#define padding unsigned + +struct __packed t300rs_packet_header { +padding : 8; + uint8_t id; + uint8_t code; +}; + +struct __packed t300rs_setup_header { + uint8_t cmd; + uint8_t code; +}; + +struct __packed t300rs_packet_envelope { + uint16_t attack_length; + uint16_t attack_level; + uint16_t fade_length; + uint16_t fade_level; +}; + +struct __packed t300rs_packet_timing { + uint8_t start_marker; + uint16_t duration; + uint16_t offset; +padding : 16; + uint16_t end_marker; +}; struct usb_ctrlrequest t300rs_firmware_request = { .bRequestType = 0xc1, -- cgit v1.3 From 3beba5071da29644f9bb06e08358885be92dc16d Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sat, 17 Jul 2021 22:41:21 +0300 Subject: Continued cleanup --- hid-tmt300rs.c | 29 ++++----- hid-tmt300rs.h | 185 ++++++++++++++++++++++++++++----------------------------- 2 files changed, 105 insertions(+), 109 deletions(-) diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 3764fc8..0ee8a5d 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -115,7 +115,7 @@ static void t300rs_fill_envelope(struct t300rs_packet_envelope *packet_envelope, static void t300rs_fill_timing(struct t300rs_packet_timing *packet_timing, uint16_t duration, uint16_t offset){ - packet_timing->start_marker = 0x47; + packet_timing->start_marker = 0x4f; packet_timing->duration = cpu_to_le16(duration); packet_timing->offset = cpu_to_le16(offset); @@ -207,8 +207,7 @@ static int t300rs_modify_duration(struct t300rs_device_entry *t300rs, struct ff_effect old = state->old; struct t300rs_packet_mod_duration { struct t300rs_packet_header header; - padding: 8; - uint8_t marker; + uint16_t marker; uint16_t duration; } *packet_mod_duration = (struct t300rs_packet_mod_duration *)t300rs->send_buffer; @@ -220,7 +219,7 @@ static int t300rs_modify_duration(struct t300rs_device_entry *t300rs, if (effect.replay.length != old.replay.length) { t300rs_fill_header(&packet_mod_duration->header, effect.id, 0x49); - packet_mod_duration->marker = 0x41; + packet_mod_duration->marker = cpu_to_le16(0x4100); packet_mod_duration->duration = cpu_to_le16(duration); ret = t300rs_send_int(t300rs); @@ -547,6 +546,7 @@ static int t300rs_upload_constant(struct t300rs_device_entry *t300rs, struct t300rs_packet_header header; uint16_t level; struct t300rs_packet_envelope envelope; + uint8_t zero; struct t300rs_packet_timing timing; } *packet_constant = (struct t300rs_packet_constant *)t300rs->send_buffer; @@ -562,7 +562,7 @@ static int t300rs_upload_constant(struct t300rs_device_entry *t300rs, */ if (test_bit(FF_EFFECT_PLAYING, &state->flags) - && test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { + && test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); @@ -598,10 +598,11 @@ static int t300rs_upload_ramp(struct t300rs_device_entry *t300rs, struct t300rs_packet_header header; uint16_t difference; uint16_t level; + uint8_t zero1[2]; uint16_t duration; - uint8_t marker; - uint8_t direction; + uint16_t marker; struct t300rs_packet_envelope envelope; + uint8_t direction; struct t300rs_packet_timing timing; } *packet_ramp = (struct t300rs_packet_ramp *)t300rs->send_buffer; @@ -610,7 +611,7 @@ static int t300rs_upload_ramp(struct t300rs_device_entry *t300rs, int16_t level; if (test_bit(FF_EFFECT_PLAYING, &state->flags) - && test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { + && test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); @@ -634,7 +635,7 @@ static int t300rs_upload_ramp(struct t300rs_device_entry *t300rs, packet_ramp->level = cpu_to_le16(level); packet_ramp->duration = cpu_to_le16(duration); - packet_ramp->marker = 0x80; + packet_ramp->marker = cpu_to_le16(0x8000); t300rs_fill_envelope(&packet_ramp->envelope, level, duration, &ramp.envelope); @@ -662,7 +663,6 @@ static int t300rs_upload_spring(struct t300rs_device_entry *t300rs, uint16_t right_deadband; uint16_t left_deadband; uint8_t spring_start[17]; - struct t300rs_packet_envelope envelope; struct t300rs_packet_timing timing; } *packet_spring = (struct t300rs_packet_spring *)t300rs->send_buffer; @@ -670,7 +670,7 @@ static int t300rs_upload_spring(struct t300rs_device_entry *t300rs, uint16_t duration, right_coeff, left_coeff, right_deadband, left_deadband, offset; if (test_bit(FF_EFFECT_PLAYING, &state->flags) - && test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { + && test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); @@ -717,9 +717,7 @@ static int t300rs_upload_damper(struct t300rs_device_entry *t300rs, uint16_t left_coeff; uint16_t right_deadband; uint16_t left_deadband; - /* space for spring const */ uint8_t damper_start[17]; - struct t300rs_packet_envelope envelope; struct t300rs_packet_timing timing; } *packet_damper = (struct t300rs_packet_damper *)t300rs->send_buffer; @@ -776,8 +774,7 @@ static int t300rs_upload_periodic(struct t300rs_device_entry *t300rs, uint16_t periodic_offset; uint16_t phase; uint16_t period; -padding : 8; - uint8_t marker; + uint16_t marker; struct t300rs_packet_envelope envelope; uint8_t waveform; struct t300rs_packet_timing timing; @@ -811,7 +808,7 @@ padding : 8; packet_periodic->phase = phase; packet_periodic->period = period; - packet_periodic->marker = 0x80; + packet_periodic->marker = cpu_to_le16(0x8000); t300rs_fill_envelope(&packet_periodic->envelope, magnitude, duration, &periodic.envelope); diff --git a/hid-tmt300rs.h b/hid-tmt300rs.h index 7566f1a..3f5af4e 100644 --- a/hid-tmt300rs.h +++ b/hid-tmt300rs.h @@ -40,45 +40,43 @@ spinlock_t data_lock; unsigned long data_flags; static const signed short t300rs_ff_effects[] = { - FF_CONSTANT, - FF_RAMP, - FF_SPRING, - FF_DAMPER, - FF_FRICTION, - FF_INERTIA, - FF_PERIODIC, - FF_SINE, - FF_TRIANGLE, - FF_SQUARE, - FF_SAW_UP, - FF_SAW_DOWN, - FF_AUTOCENTER, - FF_GAIN, - -1 + FF_CONSTANT, + FF_RAMP, + FF_SPRING, + FF_DAMPER, + FF_FRICTION, + FF_INERTIA, + FF_PERIODIC, + FF_SINE, + FF_TRIANGLE, + FF_SQUARE, + FF_SAW_UP, + FF_SAW_DOWN, + FF_AUTOCENTER, + FF_GAIN, + -1 }; struct t300rs_effect_state { - struct ff_effect effect; - struct ff_effect old; - bool old_set; - unsigned long flags; - unsigned long start_time; - unsigned long count; + struct ff_effect effect; + struct ff_effect old; + bool old_set; + unsigned long flags; + unsigned long start_time; + unsigned long count; }; struct __packed t300rs_firmware_response { - uint8_t unknown0; - uint8_t unknown1; - uint8_t firmware_version; - uint8_t unknown2; + uint8_t unused1[2]; + uint8_t firmware_version; + uint8_t unused2; }; -#define padding unsigned struct __packed t300rs_packet_header { -padding : 8; - uint8_t id; - uint8_t code; + uint8_t zero1; + uint8_t id; + uint8_t code; }; struct __packed t300rs_setup_header { @@ -96,90 +94,91 @@ struct __packed t300rs_packet_envelope { struct __packed t300rs_packet_timing { uint8_t start_marker; uint16_t duration; + uint8_t zero1[2]; uint16_t offset; -padding : 16; + uint8_t zero2; uint16_t end_marker; }; struct usb_ctrlrequest t300rs_firmware_request = { - .bRequestType = 0xc1, - .bRequest = 86, - .wValue = 0, - .wIndex = 0, - .wLength = 8 + .bRequestType = 0xc1, + .bRequest = 86, + .wValue = 0, + .wIndex = 0, + .wLength = 8 }; struct t300rs_device_entry { - struct hid_device *hdev; - struct input_dev *input_dev; - struct hid_report *report; - struct hid_field *ff_field; - struct usb_device *usbdev; - struct usb_interface *usbif; - struct t300rs_effect_state *states; - struct t300rs_firmware_response *firmware_response; - struct hrtimer hrtimer; - - int (*open)(struct input_dev *dev); - void (*close)(struct input_dev *dev); - - spinlock_t lock; - unsigned long lock_flags; - - u8 *send_buffer; - - u16 range; - u8 effects_used; + struct hid_device *hdev; + struct input_dev *input_dev; + struct hid_report *report; + struct hid_field *ff_field; + struct usb_device *usbdev; + struct usb_interface *usbif; + struct t300rs_effect_state *states; + struct t300rs_firmware_response *firmware_response; + struct hrtimer hrtimer; + + int (*open)(struct input_dev *dev); + void (*close)(struct input_dev *dev); + + spinlock_t lock; + unsigned long lock_flags; + + u8 *send_buffer; + + u16 range; + u8 effects_used; }; struct t300rs_data { - unsigned long quirks; - void *device_props; + unsigned long quirks; + void *device_props; }; static __u8 t300rs_rdesc_fixed[] = { - 0x05, 0x01, 0x09, 0x04, 0xa1, - 0x01, 0x09, 0x01, 0xa1, 0x00, - 0x85, 0x07, 0x09, 0x30, 0x15, - 0x00, 0x27, 0xff, 0xff, 0x00, - 0x00, 0x35, 0x00, 0x47, 0xff, - 0xff, 0x00, 0x00, 0x75, 0x10, - 0x95, 0x01, 0x81, 0x02, 0x09, - 0x35, 0x26, 0xff, 0x03, 0x46, - 0xff, 0x03, 0x81, 0x02, 0x09, - 0x32, 0x81, 0x02, 0x09, 0x31, - 0x81, 0x02, 0x81, 0x03, 0x05, - 0x09, 0x19, 0x01, 0x29, 0x0d, - 0x25, 0x01, 0x45, 0x01, 0x75, - 0x01, 0x95, 0x0d, 0x81, 0x02, - 0x75, 0x0b, 0x95, 0x01, 0x81, - 0x03, 0x05, 0x01, 0x09, 0x39, - 0x25, 0x07, 0x46, 0x3b, 0x01, - 0x55, 0x00, 0x65, 0x14, 0x75, - 0x04, 0x81, 0x42, 0x65, 0x00, - 0x81, 0x03, 0x85, 0x60, // here 0x0a - 0x06, 0x00, 0xff, 0x09, 0x60, // here 0x0a - 0x75, 0x08, 0x95, 0x3f, 0x26, - 0xff, 0x7f, 0x15, 0x00, 0x46, - 0xff, 0x7f, 0x36, 0x00, 0x80, - 0x91, 0x02, 0x85, 0x02, 0x09, - 0x02, 0x81, 0x02, 0x09, 0x14, - 0x85, 0x14, 0x81, 0x02, 0xc0, - 0xc0, + 0x05, 0x01, 0x09, 0x04, 0xa1, + 0x01, 0x09, 0x01, 0xa1, 0x00, + 0x85, 0x07, 0x09, 0x30, 0x15, + 0x00, 0x27, 0xff, 0xff, 0x00, + 0x00, 0x35, 0x00, 0x47, 0xff, + 0xff, 0x00, 0x00, 0x75, 0x10, + 0x95, 0x01, 0x81, 0x02, 0x09, + 0x35, 0x26, 0xff, 0x03, 0x46, + 0xff, 0x03, 0x81, 0x02, 0x09, + 0x32, 0x81, 0x02, 0x09, 0x31, + 0x81, 0x02, 0x81, 0x03, 0x05, + 0x09, 0x19, 0x01, 0x29, 0x0d, + 0x25, 0x01, 0x45, 0x01, 0x75, + 0x01, 0x95, 0x0d, 0x81, 0x02, + 0x75, 0x0b, 0x95, 0x01, 0x81, + 0x03, 0x05, 0x01, 0x09, 0x39, + 0x25, 0x07, 0x46, 0x3b, 0x01, + 0x55, 0x00, 0x65, 0x14, 0x75, + 0x04, 0x81, 0x42, 0x65, 0x00, + 0x81, 0x03, 0x85, 0x60, // here 0x0a + 0x06, 0x00, 0xff, 0x09, 0x60, // here 0x0a + 0x75, 0x08, 0x95, 0x3f, 0x26, + 0xff, 0x7f, 0x15, 0x00, 0x46, + 0xff, 0x7f, 0x36, 0x00, 0x80, + 0x91, 0x02, 0x85, 0x02, 0x09, + 0x02, 0x81, 0x02, 0x09, 0x14, + 0x85, 0x14, 0x81, 0x02, 0xc0, + 0xc0, }; static u8 spring_values[] = { - 0xa6, 0x6a, 0xa6, 0x6a, 0xfe, - 0xff, 0xfe, 0xff, 0xfe, 0xff, - 0xfe, 0xff, 0xdf, 0x58, 0xa6, - 0x6a, 0x06 + 0xa6, 0x6a, 0xa6, 0x6a, 0xfe, + 0xff, 0xfe, 0xff, 0xfe, 0xff, + 0xfe, 0xff, 0xdf, 0x58, 0xa6, + 0x6a, 0x06 }; static u8 damper_values[] = { - 0xfc, 0x7f, 0xfc, 0x7f, 0xfe, - 0xff, 0xfe, 0xff, 0xfe, 0xff, - 0xfe, 0xff, 0xfc, 0x7f, 0xfc, - 0x7f, 0x07 + 0xfc, 0x7f, 0xfc, 0x7f, 0xfe, + 0xff, 0xfe, 0xff, 0xfe, 0xff, + 0xfe, 0xff, 0xfc, 0x7f, 0xfc, + 0x7f, 0x07 }; -- cgit v1.3 From 4216aaa61bfb753158be9e719c59626aeb368231 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sun, 18 Jul 2021 16:56:56 +0300 Subject: Fixed constant issue --- hid-tmt300rs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 0ee8a5d..d60adf5 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -242,7 +242,7 @@ static int t300rs_modify_constant(struct t300rs_device_entry *t300rs, struct ff_constant_effect constant_old = old.u.constant; struct __packed t300rs_packet_mod_constant { struct t300rs_packet_header header; - uint8_t level; + uint16_t level; } *packet_mod_constant = (struct t300rs_packet_mod_constant *)t300rs->send_buffer; int ret; int16_t level; @@ -252,7 +252,7 @@ static int t300rs_modify_constant(struct t300rs_device_entry *t300rs, if (constant.level != constant_old.level) { t300rs_fill_header(&packet_mod_constant->header, effect.id, 0x0a); - packet_mod_constant->level = level; + packet_mod_constant->level = cpu_to_le16(level); ret = t300rs_send_int(t300rs); if (ret) { -- cgit v1.3 From c6c0c50a442fb943b0c0f9949e54ad4e6c1203d1 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sun, 18 Jul 2021 19:06:09 +0300 Subject: Improved periodic effect --- hid-tmt300rs.c | 59 ++++++++++++++++++++++++++++++++++++---------------------- hid-tmt300rs.h | 4 ++-- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index d60adf5..a330d83 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -450,15 +450,25 @@ static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, } *packet_mod_periodic = (struct t300rs_packet_mod_periodic *)t300rs->send_buffer; int ret; - int16_t level; + int16_t magnitude; + uint16_t phase; + bool update_phase = false; - level = (periodic.magnitude * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; + magnitude = (periodic.magnitude * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; + phase = periodic.phase; + if(magnitude < 0){ + phase += 0x4000; + phase = phase < 0 ? -phase : phase; + update_phase = true; + } + + magnitude = magnitude < 0 ? -magnitude : magnitude; if (periodic.magnitude != periodic_old.magnitude) { t300rs_fill_header(&packet_mod_periodic->header, effect.id, 0x0e); packet_mod_periodic->attribute = 0x01; - packet_mod_periodic->value = cpu_to_le16(level); + packet_mod_periodic->value = cpu_to_le16(magnitude); ret = t300rs_send_int(t300rs); if (ret) { @@ -483,12 +493,11 @@ static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, } - if (periodic.phase != periodic_old.phase) { - int16_t phase = periodic.phase; + if (periodic.phase != periodic_old.phase || update_phase) { t300rs_fill_header(&packet_mod_periodic->header, effect.id, 0x0e); packet_mod_periodic->attribute = 0x04; - packet_mod_periodic->value = phase; + packet_mod_periodic->value = cpu_to_le16(phase); ret = t300rs_send_int(t300rs); if (ret) { @@ -503,7 +512,7 @@ static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, t300rs_fill_header(&packet_mod_periodic->header, effect.id, 0x0e); packet_mod_periodic->attribute = 0x08; - packet_mod_periodic->value = period; + packet_mod_periodic->value = cpu_to_le16(period); ret = t300rs_send_int(t300rs); if (ret) { @@ -515,7 +524,7 @@ static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, ret = t300rs_modify_envelope(t300rs, state, - level, + magnitude, effect.replay.length, effect.id, periodic.envelope, @@ -689,10 +698,10 @@ static int t300rs_upload_spring(struct t300rs_device_entry *t300rs, t300rs_fill_header(&packet_spring->header, effect.id, 0x64); - packet_spring->right_coeff = right_coeff; - packet_spring->left_coeff = left_coeff; - packet_spring->right_deadband = right_deadband; - packet_spring->left_deadband = left_deadband; + packet_spring->right_coeff = cpu_to_le16(right_coeff); + packet_spring->left_coeff = cpu_to_le16(left_coeff); + packet_spring->right_deadband = cpu_to_le16(right_deadband); + packet_spring->left_deadband = cpu_to_le16(left_deadband); memcpy(&packet_spring->spring_start, spring_values, ARRAY_SIZE(spring_values)); t300rs_fill_timing(&packet_spring->timing, duration, offset); @@ -748,10 +757,10 @@ static int t300rs_upload_damper(struct t300rs_device_entry *t300rs, t300rs_fill_header(&packet_damper->header, effect.id, 0x64); - packet_damper->right_coeff = right_coeff; - packet_damper->left_coeff = left_coeff; - packet_damper->right_deadband = right_deadband; - packet_damper->left_deadband = left_deadband; + packet_damper->right_coeff = cpu_to_le16(right_coeff); + packet_damper->left_coeff = cpu_to_le16(left_coeff); + packet_damper->right_deadband = cpu_to_le16(right_deadband); + packet_damper->left_deadband = cpu_to_le16(left_deadband); memcpy(&packet_damper->damper_start, damper_values, ARRAY_SIZE(damper_values)); t300rs_fill_timing(&packet_damper->timing, duration, offset); @@ -781,8 +790,8 @@ static int t300rs_upload_periodic(struct t300rs_device_entry *t300rs, } *packet_periodic = (struct t300rs_packet_periodic *)t300rs->send_buffer; int ret; - uint16_t duration, magnitude, phase, period, offset; - int16_t periodic_offset; + uint16_t duration, magnitude, period, offset; + int16_t periodic_offset, phase; if (test_bit(FF_EFFECT_PLAYING, &state->flags) && test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { @@ -797,16 +806,22 @@ static int t300rs_upload_periodic(struct t300rs_device_entry *t300rs, magnitude = (periodic.magnitude * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; phase = periodic.phase; + if(magnitude < 0){ + phase += 0x4000; + phase = phase < 0 ? -phase : phase; + } + + magnitude = magnitude < 0 ? -magnitude : magnitude; periodic_offset = periodic.offset; period = periodic.period; offset = effect.replay.delay; t300rs_fill_header(&packet_periodic->header, effect.id, 0x6b); - packet_periodic->magnitude = magnitude; - packet_periodic->periodic_offset = periodic_offset; - packet_periodic->phase = phase; - packet_periodic->period = period; + packet_periodic->magnitude = cpu_to_le16(magnitude); + packet_periodic->periodic_offset = cpu_to_le16(periodic_offset); + packet_periodic->phase = cpu_to_le16(phase); + packet_periodic->period = cpu_to_le16(period); packet_periodic->marker = cpu_to_le16(0x8000); diff --git a/hid-tmt300rs.h b/hid-tmt300rs.h index 3f5af4e..80146ef 100644 --- a/hid-tmt300rs.h +++ b/hid-tmt300rs.h @@ -29,8 +29,8 @@ #define FF_EFFECT_PLAYING 3 #define FF_EFFECT_QUEUE_UPDATE 4 -#define CLAMP_VALUE_U16(x) ((unsigned short)((x) > 0xffff ? 0xffff : (x))) -#define SCALE_VALUE_U16(x, bits) (CLAMP_VALUE_U16(x) >> (16 - bits)) +#undef fixp_sin16 +#define fixp_sin16(v) (((v % 360) > 180)? -(fixp_sin32((v % 360) - 180) >> 16) : fixp_sin32(v) >> 16) #define JIFFIES2MS(jiffies) ((jiffies) * 1000 / HZ) spinlock_t lock; -- cgit v1.3 From 0ce71ffd905875847c5d973e4c67c45b4d525914 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sun, 24 Oct 2021 19:02:12 +0300 Subject: Added adv_mode + Doesn't seem to do anything to my wheel, but I don't have the wheel attachment that this mode is intended for, needs further testing in other words. --- hid-tmt300rs.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hid-tmt300rs.h | 2 ++ 2 files changed, 59 insertions(+) diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index a330d83..5ec163a 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -1182,6 +1182,50 @@ static ssize_t range_show(struct device *dev, static DEVICE_ATTR_RW(range); +static ssize_t adv_mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct hid_device *hdev = to_hid_device(dev); + struct t300rs_device_entry *t300rs; + + t300rs = t300rs_get_device(hdev); + if (!t300rs) { + hid_err(hdev, "could not get device\n"); + return -1; + } + + if(t300rs->adv_mode) + usb_control_msg(t300rs->usbdev, + usb_sndctrlpipe(t300rs->usbdev, 0), + 83, 0x41, 5, 0, 0, 0, + USB_CTRL_SET_TIMEOUT + ); + else + usb_control_msg(t300rs->usbdev, + usb_sndctrlpipe(t300rs->usbdev, 0), + 83, 0x41, 3, 0, 0, 0, + USB_CTRL_SET_TIMEOUT + ); + + return count; +} + +static ssize_t adv_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct hid_device *hdev = to_hid_device(dev); + struct t300rs_device_entry *t300rs; + + t300rs = t300rs_get_device(hdev); + if (!t300rs) { + hid_err(hdev, "could not get device\n"); + return -1; + } + + return scnprintf(buf, PAGE_SIZE, "%s\n", t300rs->adv_mode ? "Yes" : "No"); +} +static DEVICE_ATTR_RW(adv_mode); + static void t300rs_set_autocenter(struct input_dev *dev, uint16_t value) { struct hid_device *hdev = input_get_drvdata(dev); @@ -1316,6 +1360,12 @@ static int t300rs_create_files(struct hid_device *hdev) { int ret; + ret = device_create_file(&hdev->dev, &dev_attr_adv_mode); + if (ret) { + hid_warn(hdev, "unable to create sysfs interface for adv_mode\n"); + goto attr_adv_err; + } + ret = device_create_file(&hdev->dev, &dev_attr_range); if (ret) { hid_warn(hdev, "unable to create sysfs interface for range\n"); @@ -1351,6 +1401,8 @@ attr_damper_err: attr_spring_err: device_remove_file(&hdev->dev, &dev_attr_range); attr_range_err: + device_remove_file(&hdev->dev, &dev_attr_adv_mode); +attr_adv_err: return ret; } @@ -1480,6 +1532,8 @@ static int t300rs_init(struct hid_device *hdev, const signed short *ff_bits) range_store(dev, &dev_attr_range, range, 10); t300rs_set_gain(input_dev, 0xffff); + t300rs->adv_mode = (hdev->product == 0xb66f); + hid_info(hdev, "force feedback for T300RS\n"); return 0; @@ -1560,6 +1614,7 @@ static void t300rs_remove(struct hid_device *hdev) hrtimer_cancel(&t300rs->hrtimer); device_remove_file(&hdev->dev, &dev_attr_range); + device_remove_file(&hdev->dev, &dev_attr_adv_mode); device_remove_file(&hdev->dev, &dev_attr_spring_level); device_remove_file(&hdev->dev, &dev_attr_damper_level); device_remove_file(&hdev->dev, &dev_attr_friction_level); @@ -1582,6 +1637,8 @@ static __u8 *t300rs_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned static const struct hid_device_id t300rs_devices[] = { {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb66e), .driver_data = (unsigned long)t300rs_ff_effects}, + {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb66f), + .driver_data = (unsigned long)t300rs_ff_effects}, {} }; MODULE_DEVICE_TABLE(hid, t300rs_devices); diff --git a/hid-tmt300rs.h b/hid-tmt300rs.h index 80146ef..caf38cf 100644 --- a/hid-tmt300rs.h +++ b/hid-tmt300rs.h @@ -130,6 +130,8 @@ struct t300rs_device_entry { u16 range; u8 effects_used; + + u8 adv_mode; }; -- cgit v1.3 From 4179def302185641a17ab66c835aca4a69f27825 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 3 Nov 2021 23:40:55 +0200 Subject: Added T300RS advanced mode rdesc --- hid-tmt300rs.c | 12 +++-- hid-tmt300rs.h | 154 ++++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 134 insertions(+), 32 deletions(-) diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 5ec163a..b08e838 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -1629,8 +1629,14 @@ static void t300rs_remove(struct hid_device *hdev) static __u8 *t300rs_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { - rdesc = t300rs_rdesc_fixed; - *rsize = sizeof(t300rs_rdesc_fixed); + if(hdev->product == 0xb66e) { + rdesc = t300rs_rdesc_nrm_fixed; + *rsize = sizeof(t300rs_rdesc_nrm_fixed); + } else { + rdesc = t300rs_rdesc_adv_fixed; + *rsize = sizeof(t300rs_rdesc_adv_fixed); + } + return rdesc; } @@ -1638,7 +1644,7 @@ static const struct hid_device_id t300rs_devices[] = { {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb66e), .driver_data = (unsigned long)t300rs_ff_effects}, {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb66f), - .driver_data = (unsigned long)t300rs_ff_effects}, + .driver_data = (unsigned long)t300rs_ff_effects}, {} }; MODULE_DEVICE_TABLE(hid, t300rs_devices); diff --git a/hid-tmt300rs.h b/hid-tmt300rs.h index caf38cf..9ffd87c 100644 --- a/hid-tmt300rs.h +++ b/hid-tmt300rs.h @@ -140,35 +140,131 @@ struct t300rs_data { void *device_props; }; -static __u8 t300rs_rdesc_fixed[] = { - 0x05, 0x01, 0x09, 0x04, 0xa1, - 0x01, 0x09, 0x01, 0xa1, 0x00, - 0x85, 0x07, 0x09, 0x30, 0x15, - 0x00, 0x27, 0xff, 0xff, 0x00, - 0x00, 0x35, 0x00, 0x47, 0xff, - 0xff, 0x00, 0x00, 0x75, 0x10, - 0x95, 0x01, 0x81, 0x02, 0x09, - 0x35, 0x26, 0xff, 0x03, 0x46, - 0xff, 0x03, 0x81, 0x02, 0x09, - 0x32, 0x81, 0x02, 0x09, 0x31, - 0x81, 0x02, 0x81, 0x03, 0x05, - 0x09, 0x19, 0x01, 0x29, 0x0d, - 0x25, 0x01, 0x45, 0x01, 0x75, - 0x01, 0x95, 0x0d, 0x81, 0x02, - 0x75, 0x0b, 0x95, 0x01, 0x81, - 0x03, 0x05, 0x01, 0x09, 0x39, - 0x25, 0x07, 0x46, 0x3b, 0x01, - 0x55, 0x00, 0x65, 0x14, 0x75, - 0x04, 0x81, 0x42, 0x65, 0x00, - 0x81, 0x03, 0x85, 0x60, // here 0x0a - 0x06, 0x00, 0xff, 0x09, 0x60, // here 0x0a - 0x75, 0x08, 0x95, 0x3f, 0x26, - 0xff, 0x7f, 0x15, 0x00, 0x46, - 0xff, 0x7f, 0x36, 0x00, 0x80, - 0x91, 0x02, 0x85, 0x02, 0x09, - 0x02, 0x81, 0x02, 0x09, 0x14, - 0x85, 0x14, 0x81, 0x02, 0xc0, - 0xc0, +static __u8 t300rs_rdesc_nrm_fixed[] = { + 0x05, 0x01, /* Usage page (Generic Desktop) */ + 0x09, 0x04, /* Usage (Joystick) */ + 0xa1, 0x01, /* Collection (Application) */ + 0x09, 0x01, /* Usage (Pointer) */ + 0xa1, 0x00, /* Collection (Physical) */ + 0x85, 0x07, /* Report ID (7) */ + 0x09, 0x30, /* Usage (X) */ + 0x15, 0x00, /* Logical minimum (0) */ + 0x27, 0xff, 0xff, 0x00, 0x00, /* Logical maximum (65535) */ + 0x35, 0x00, /* Physical minimum (0) */ + 0x47, 0xff, 0xff, 0x00, 0x00, /* Physical maximum (65535) */ + 0x75, 0x10, /* Report size (16) */ + 0x95, 0x01, /* Report count (1) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x35, /* Usage (Rz) */ + 0x26, 0xff, 0x03, /* Logical maximum (1023) */ + 0x46, 0xff, 0x03, /* Physical maximum (1023) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x32, /* Usage (Z) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x31, /* Usage (Y) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x81, 0x03, /* Input (Variable, Absolute, Constant) */ + 0x05, 0x09, /* Usage page (Button) */ + 0x19, 0x01, /* Usage minimum (1) */ + 0x29, 0x0d, /* Usage maximum (13) */ + 0x25, 0x01, /* Logical maximum (1) */ + 0x45, 0x01, /* Physical maximum (1) */ + 0x75, 0x01, /* Report size (1) */ + 0x95, 0x0d, /* Report count (13) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x75, 0x0b, /* Report size (13) */ + 0x95, 0x01, /* Report count (1) */ + 0x81, 0x03, /* Usage (Variable, Absolute, Constant) */ + 0x05, 0x01, /* Usage page (Generic Desktop) */ + 0x09, 0x39, /* Usage (Hat Switch) */ + 0x25, 0x07, /* Logical maximum (7) */ + 0x46, 0x3b, 0x01, /* Physical maximum (315) */ + 0x55, 0x00, /* Unit exponent (0) */ + 0x65, 0x14, /* Unit (Eng Rot, Angular Pos) */ + 0x75, 0x04, /* Report size (4) */ + 0x81, 0x42, /* Input (Variable, Absolute, NullState) */ + 0x65, 0x00, /* Unit (None) */ + 0x81, 0x03, /* Input (Variable, Absolute, Constant) */ + 0x85, 0x60, /* Report ID (96), prev 10 */ + 0x06, 0x00, 0xff, /* Usage page (Vendor 1) */ + 0x09, 0x60, /* Usage (96), prev 10 */ + 0x75, 0x08, /* Report size (8) */ + 0x95, 0x3f, /* Report count (63) */ + 0x26, 0xff, 0x7f, /* Logical maximum (32767) */ + 0x15, 0x00, /* Logical minimum (0) */ + 0x46, 0xff, 0x7f, /* Physical maximum (32767) */ + 0x36, 0x00, 0x80, /* Physical minimum (-32768) */ + 0x91, 0x02, /* Output (Variable, Absolute) */ + 0x85, 0x02, /* Report ID (2) */ + 0x09, 0x02, /* Usage (2) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x14, /* Usage (20) */ + 0x85, 0x14, /* Report ID (20) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0xc0, /* End collection */ + 0xc0, /* End collection */ +}; + +static __u8 t300rs_rdesc_adv_fixed[] = { + 0x05, 0x01, /* Usage page (Generic Desktop) */ + 0x09, 0x04, /* Usage (Joystick) */ + 0xa1, 0x01, /* Collection (Application) */ + 0x09, 0x01, /* Usage (Pointer) */ + 0xa1, 0x00, /* Collection (Physical) */ + 0x85, 0x07, /* Report ID (7) */ + 0x09, 0x30, /* Usage (X) */ + 0x15, 0x00, /* Logical minimum (0) */ + 0x27, 0xff, 0xff, 0x00, 0x00, /* Logical maximum (65535) */ + 0x35, 0x00, /* Physical minimum (0) */ + 0x47, 0xff, 0xff, 0x00, 0x00, /* Physical maximum (65535) */ + 0x75, 0x10, /* Report size (16) */ + 0x95, 0x01, /* Report count (1) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x31, /* Usage (Y) */ + 0x26, 0xff, 0x03, /* Logical maximum (1023) */ + 0x46, 0xff, 0x03, /* Physical maximum (1023) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x35, /* Usage (Rz) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x36, /* Usage (Slider) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x81, 0x03, /* Input (Variable, Absolute, Constant) ? */ + 0x05, 0x09, /* Usage page (Button) */ + 0x19, 0x01, /* Usage minimum (1) */ + 0x29, 0x19, /* Usage maximum (25) */ + 0x25, 0x01, /* Logical maximum (1) */ + 0x45, 0x01, /* Physical maximum (1) */ + 0x75, 0x01, /* Report size (1) */ + 0x95, 0x19, /* Report count (25) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x75, 0x03, /* Report size (3) */ + 0x95, 0x01, /* Report count (1) */ + 0x81, 0x03, /* Input (Variable, Absolute, Constant) */ + 0x05, 0x01, /* Usage page (Generic Desktop) */ + 0x09, 0x39, /* Usage (Hat Switch) */ + 0x25, 0x07, /* Logical maximum (7) */ + 0x46, 0x3b, 0x01, /* Physical maximum (315) */ + 0x55, 0x00, /* Unit exponent (0) */ + 0x65, 0x14, /* Unit (Eng Rot, Angular Pos) */ + 0x75, 0x04, /* Report size (4) */ + 0x81, 0x42, /* Input (Variable, Absolute, NullState) */ + 0x65, 0x00, /* Unit (None) */ + 0x85, 0x60, /* Report ID (96), prev 10 */ + 0x06, 0x00, 0xff, /* Usage page (Vendor 1) */ + 0x09, 0x60, /* Usage (96), prev 10 (why?) */ + 0x75, 0x08, /* Report size (8) */ + 0x95, 0x3f, /* Report count (63) */ + 0x26, 0xff, 0x00, /* Logical maximum (255) */ + 0x46, 0xff, 0x00, /* Physical maximum (255) */ + 0x91, 0x02, /* Output (Variable, Absolute) */ + 0x85, 0x02, /* Report ID (2) */ + 0x09, 0x02, /* Usage (Mouse) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x14, /* Usage (20) */ + 0x85, 0x14, /* Report ID (20) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0xc0, /* End collection */ + 0xc0, /* End collection */ }; static u8 spring_values[] = { -- cgit v1.3 From 8c4e9e8635fcb84493ff583d0ef00a48a3eb796f Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 1 Dec 2021 14:16:16 +0200 Subject: Detect PS4 mode FFB seems to be working, buttons are recognised but no input from wheel rotation or pedals. --- hid-tmt300rs.c | 36 +++++++++++++++++------ hid-tmt300rs.h | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 116 insertions(+), 13 deletions(-) diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index b08e838..4bd8bc3 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -3,19 +3,23 @@ static int timer_msecs = DEFAULT_TIMER_PERIOD; module_param(timer_msecs, int, 0660); -MODULE_PARM_DESC(timer_msecs, "Timer resolution in msecs"); +MODULE_PARM_DESC(timer_msecs, + "Timer resolution in msecs"); static int spring_level = 30; module_param(spring_level, int, 0); -MODULE_PARM_DESC(spring_level, "Level of spring force (0-100), as per Oversteer standards"); +MODULE_PARM_DESC(spring_level, + "Level of spring force (0-100), as per Oversteer standards"); static int damper_level = 30; module_param(damper_level, int, 0); -MODULE_PARM_DESC(damper_level, "Level of damper force (0-100), as per Oversteer standards"); +MODULE_PARM_DESC(damper_level, + "Level of damper force (0-100), as per Oversteer standards"); static int friction_level = 30; module_param(friction_level, int, 0); -MODULE_PARM_DESC(friction_level, "Level of friction force (0-100), as per Oversteer standards"); +MODULE_PARM_DESC(friction_level, + "Level of friction force (0-100), as per Oversteer standards"); static struct t300rs_device_entry *t300rs_get_device(struct hid_device *hdev) { @@ -41,12 +45,12 @@ static struct t300rs_device_entry *t300rs_get_device(struct hid_device *hdev) static int t300rs_send_int(struct t300rs_device_entry *t300rs) { int i; - for (i = 0; i < T300RS_BUFFER_LENGTH; ++i) + for (i = 0; i < t300rs->buffer_length; ++i) t300rs->ff_field->value[i] = t300rs->send_buffer[i]; hid_hw_request(t300rs->hdev, t300rs->report, HID_REQ_SET_REPORT); - memset(t300rs->send_buffer, 0, T300RS_BUFFER_LENGTH); + memset(t300rs->send_buffer, 0, t300rs->buffer_length); return 0; } @@ -1447,7 +1451,12 @@ static int t300rs_init(struct hid_device *hdev, const signed short *ff_bits) goto states_err; } - t300rs->send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_KERNEL); + if(hdev->product == 0xb66d) + t300rs->buffer_length = T300RS_PS4_BUFFER_LENGTH; + else + t300rs->buffer_length = T300RS_NORM_BUFFER_LENGTH; + + t300rs->send_buffer = kzalloc(t300rs->buffer_length, GFP_KERNEL); if (!t300rs->send_buffer) { ret = -ENOMEM; goto send_err; @@ -1627,12 +1636,19 @@ static void t300rs_remove(struct hid_device *hdev) kfree(drv_data); } -static __u8 *t300rs_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) +static __u8 *t300rs_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { if(hdev->product == 0xb66e) { + /* PS3 normal mode */ rdesc = t300rs_rdesc_nrm_fixed; *rsize = sizeof(t300rs_rdesc_nrm_fixed); - } else { + } else if (hdev->product == 0xb66d){ + /* PS4 normal mode */ + rdesc = t300rs_rdesc_ps4_fixed; + *rsize = sizeof(t300rs_rdesc_ps4_fixed); + } else if (hdev->product == 0xb66f){ + /* PS3 advanced mode */ rdesc = t300rs_rdesc_adv_fixed; *rsize = sizeof(t300rs_rdesc_adv_fixed); } @@ -1645,6 +1661,8 @@ static const struct hid_device_id t300rs_devices[] = { .driver_data = (unsigned long)t300rs_ff_effects}, {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb66f), .driver_data = (unsigned long)t300rs_ff_effects}, + {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb66d), + .driver_data = (unsigned long)t300rs_ff_effects}, {} }; MODULE_DEVICE_TABLE(hid, t300rs_devices); diff --git a/hid-tmt300rs.h b/hid-tmt300rs.h index 9ffd87c..3c3a3a9 100644 --- a/hid-tmt300rs.h +++ b/hid-tmt300rs.h @@ -13,7 +13,8 @@ #define USB_VENDOR_ID_THRUSTMASTER 0x044f #define T300RS_MAX_EFFECTS 16 -#define T300RS_BUFFER_LENGTH 63 +#define T300RS_NORM_BUFFER_LENGTH 63 +#define T300RS_PS4_BUFFER_LENGTH 31 /* the wheel seems to only be capable of processing a certain number of * interrupts per second, and if this value is too low the kernel urb buffer(or @@ -126,6 +127,7 @@ struct t300rs_device_entry { spinlock_t lock; unsigned long lock_flags; + u8 buffer_length; u8 *send_buffer; u16 range; @@ -140,7 +142,7 @@ struct t300rs_data { void *device_props; }; -static __u8 t300rs_rdesc_nrm_fixed[] = { +static u8 t300rs_rdesc_nrm_fixed[] = { 0x05, 0x01, /* Usage page (Generic Desktop) */ 0x09, 0x04, /* Usage (Joystick) */ 0xa1, 0x01, /* Collection (Application) */ @@ -205,7 +207,7 @@ static __u8 t300rs_rdesc_nrm_fixed[] = { 0xc0, /* End collection */ }; -static __u8 t300rs_rdesc_adv_fixed[] = { +static u8 t300rs_rdesc_adv_fixed[] = { 0x05, 0x01, /* Usage page (Generic Desktop) */ 0x09, 0x04, /* Usage (Joystick) */ 0xa1, 0x01, /* Collection (Application) */ @@ -243,7 +245,7 @@ static __u8 t300rs_rdesc_adv_fixed[] = { 0x05, 0x01, /* Usage page (Generic Desktop) */ 0x09, 0x39, /* Usage (Hat Switch) */ 0x25, 0x07, /* Logical maximum (7) */ - 0x46, 0x3b, 0x01, /* Physical maximum (315) */ + 0x46, 0x3b, 0x01, /* Physical maximum (315) */ 0x55, 0x00, /* Unit exponent (0) */ 0x65, 0x14, /* Unit (Eng Rot, Angular Pos) */ 0x75, 0x04, /* Report size (4) */ @@ -267,6 +269,89 @@ static __u8 t300rs_rdesc_adv_fixed[] = { 0xc0, /* End collection */ }; +static u8 t300rs_rdesc_ps4_fixed[] = { + 0x05, 0x01, /* Usage page (Generic Desktop) */ + 0x09, 0x05, /* Usage (GamePad) */ + 0xa1, 0x01, /* Collection (Application) */ + 0x85, 0x01, /* Report ID (1) */ + 0x09, 0x30, /* Usage (X) */ + 0x09, 0x31, /* Usage (Y) */ + 0x09, 0x32, /* Usage (Z) */ + 0x09, 0x35, /* Usage (Rz) */ + 0x15, 0x00, /* Logical minimum (0) */ + 0x26, 0xff, 0x00, /* Logical maximum (255) */ + 0x75, 0x08, /* Report size (8) */ + 0x95, 0x04, /* Report count (4) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x39, /* Usage (Hat Switch) */ + 0x15, 0x00, /* Logical minimum (0) */ + 0x25, 0x07, /* Logical maximum (7)*/ + 0x35, 0x00, /* Physical minimum (0) */ + 0x46, 0x3b, 0x01, /* Physical maximum (315) */ + 0x65, 0x14, /* Unit (Eng Rot, Angular Pos) */ + 0x75, 0x04, /* Report size (4) */ + 0x95, 0x01, /* Report count (1) */ + 0x81, 0x42, /* Input (Variable, Absolute, NullState) */ + 0x65, 0x00, /* Input (None) */ + 0x05, 0x09, /* Usage page (Button) */ + 0x19, 0x01, /* Usage minimum (1) */ + 0x29, 0x0e, /* Usage maximum (14) */ + 0x15, 0x00, /* Logical minimum (0) */ + 0x25, 0x01, /* Logical maximum (1) */ + 0x75, 0x01, /* Report size (1) */ + 0x95, 0x0e, /* Report size (14) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x06, 0x00, 0xff, /* Usage page (Vendor 1) */ + 0x09, 0x20, /* Usage (32) */ + 0x75, 0x06, /* Report size (6) */ + 0x95, 0x01, /* Report count (1) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x05, 0x01, /* Usage page (Generic Desktop) */ + 0x09, 0x33, /* Usage (Rx) */ + 0x09, 0x34, /* Usage (Ry) */ + 0x15, 0x00, /* Logical minimum (0) */ + 0x26, 0xff, 0x00, /* Logical maximum (255) */ + 0x75, 0x08, /* Report size (8) */ + 0x95, 0x02, /* Report count (2) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x06, 0x00, 0xff, /* Usage page (Vendor 1) */ + 0x09, 0x21, /* Usage (33) */ + 0x95, 0x36, /* Report count (54) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x85, 0x60, /* Report ID (5) (change to 0x60?) */ + 0x09, 0x60, /* Usage (34) (change to 0x60?) */ + 0x95, 0x1f, /* Report count (31) () */ + 0x91, 0x02, /* Output (Variable, Absolute) */ + 0x85, 0x03, /* Report ID (3) */ + 0x0a, 0x21, 0x27, /* ??? */ + 0x95, 0x2f, /* Report count (47) */ + 0xb1, 0x02, /* Feature (Data, Var, Abs) */ + 0xc0, /* End collection */ + + /* From here on out no clue */ + 0x06, 0xf0, + 0xff, 0x09, + 0x40, 0xa1, + 0x01, 0x85, + 0xf0, 0x09, + 0x47, 0x95, + 0x3f, 0xb1, + 0x02, 0x85, + 0xf1, 0x09, + 0x48, 0x95, + 0x3f, 0xb1, + 0x02, 0x85, + 0xf2, 0x09, + 0x49, 0x95, + 0x0f, 0xb1, + 0x02, 0x85, + 0xf3, 0x0a, + 0x01, 0x47, + 0x95, 0x07, + 0xb1, 0x02, + 0xc0, +}; + static u8 spring_values[] = { 0xa6, 0x6a, 0xa6, 0x6a, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, -- cgit v1.3 From e6859e323c1d914c7811d572d0377601d8e16f97 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 1 Dec 2021 14:53:47 +0200 Subject: Added inputs to ps4 rdesc based on my wheel --- hid-tmt300rs.h | 44 +++++++++++++++++++++++++++++++++++--------- ps4-input.txt | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 ps4-input.txt diff --git a/hid-tmt300rs.h b/hid-tmt300rs.h index 3c3a3a9..f50e789 100644 --- a/hid-tmt300rs.h +++ b/hid-tmt300rs.h @@ -274,10 +274,10 @@ static u8 t300rs_rdesc_ps4_fixed[] = { 0x09, 0x05, /* Usage (GamePad) */ 0xa1, 0x01, /* Collection (Application) */ 0x85, 0x01, /* Report ID (1) */ - 0x09, 0x30, /* Usage (X) */ - 0x09, 0x31, /* Usage (Y) */ - 0x09, 0x32, /* Usage (Z) */ - 0x09, 0x35, /* Usage (Rz) */ + 0x09, 0x00, /* Usage (U) (was X) */ + 0x09, 0x00, /* Usage (U) (was Y) */ + 0x09, 0x00, /* Usage (U) (was Z) */ + 0x09, 0x00, /* Usage (U) (was Rz)*/ 0x15, 0x00, /* Logical minimum (0) */ 0x26, 0xff, 0x00, /* Logical maximum (255) */ 0x75, 0x08, /* Report size (8) */ @@ -307,17 +307,43 @@ static u8 t300rs_rdesc_ps4_fixed[] = { 0x95, 0x01, /* Report count (1) */ 0x81, 0x02, /* Input (Variable, Absolute) */ 0x05, 0x01, /* Usage page (Generic Desktop) */ - 0x09, 0x33, /* Usage (Rx) */ - 0x09, 0x34, /* Usage (Ry) */ + 0x09, 0x00, /* Usage (U) (was Rx)*/ + 0x09, 0x00, /* Usage (U) (was Ry) */ 0x15, 0x00, /* Logical minimum (0) */ 0x26, 0xff, 0x00, /* Logical maximum (255) */ 0x75, 0x08, /* Report size (8) */ 0x95, 0x02, /* Report count (2) */ 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x06, 0x00, 0xff, /* Usage page (Vendor 1) */ - 0x09, 0x21, /* Usage (33) */ - 0x95, 0x36, /* Report count (54) */ + 0x05, 0x01, /* Usage page (Vendor 1) */ + /* constant zero? */ + 0x09, 0x00, /* Usage (33) */ + 0x95, 0x21, /* Report count (54) */ + 0x81, 0x03, /* Input (Variable, Absolute, Constant) */ + /* wheel */ + 0x09, 0x30, /* Usage (X) */ + 0x15, 0x00, /* Logical minimum (0) */ + 0x27, 0xff, 0xff, 0x00, 0x00, /* Logical maximum (65535) */ + 0x35, 0x00, /* Physical minimum (0) */ + 0x47, 0xff, 0xff, 0x00, 0x00, /* Physical maximum (65535) */ + 0x75, 0x10, /* Report size (16) */ + 0x95, 0x01, /* Report count (1) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + /* gas */ + 0x09, 0x31, /* Usage (Y) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + /* brake */ + 0x09, 0x32, /* Usage (Z) */ 0x81, 0x02, /* Input (Variable, Absolute) */ + /* clutch */ + 0x09, 0x35, /* Usage (Rz) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + /* no clue */ + 0x09, 0x00, /* Usage (U) */ + 0x75, 0x08, /* Report size (8) */ + 0x95, 0x0d, /* Report count (13) */ + 0x81, 0x03, /* Input (Variable, Absolute, Constant) */ + /* continue unmodified */ + 0x06, 0x00, 0xff, /* Usage page (Vendor defined 1) */ 0x85, 0x60, /* Report ID (5) (change to 0x60?) */ 0x09, 0x60, /* Usage (34) (change to 0x60?) */ 0x95, 0x1f, /* Report count (31) () */ diff --git a/ps4-input.txt b/ps4-input.txt new file mode 100644 index 0000000..9286c7e --- /dev/null +++ b/ps4-input.txt @@ -0,0 +1,54 @@ +1 ff00.0021 = 0 +2 ff00.0021 = 0 +3 ff00.0021 = 0 +4 ff00.0021 = 0 +5 ff00.0021 = 0 +6 ff00.0021 = 0 +7 ff00.0021 = 0 +8 ff00.0021 = 0 +9 ff00.0021 = 0 +10 ff00.0021 = 0 +11 ff00.0021 = 0 +12 ff00.0021 = 0 +13 ff00.0021 = 0 +14 ff00.0021 = 0 +15 ff00.0021 = 0 +16 ff00.0021 = 0 +17 ff00.0021 = 0 +18 ff00.0021 = 0 +19 ff00.0021 = 0 +20 ff00.0021 = 0 +21 ff00.0021 = 0 +22 ff00.0021 = 0 +23 ff00.0021 = 0 +24 ff00.0021 = 0 +25 ff00.0021 = 0 +26 ff00.0021 = 0 +27 ff00.0021 = 0 +28 ff00.0021 = 0 +29 ff00.0021 = 0 +30 ff00.0021 = 0 +31 ff00.0021 = 0 +32 ff00.0021 = 0 +33 ff00.0021 = 0 +34 ff00.0021 = 226 /* wheel */ +35 ff00.0021 = 125 /* wheel */ +36 ff00.0021 = 255 /* gas */ +37 ff00.0021 = 255 /* gas */ +38 ff00.0021 = 255 /* brake */ +39 ff00.0021 = 255 /* brake */ +40 ff00.0021 = 255 /* clutch */ +41 ff00.0021 = 255 /* clutch */ +42 ff00.0021 = 0 +43 ff00.0021 = 255 +44 ff00.0021 = 255 +45 ff00.0021 = 0 +46 ff00.0021 = 0 +47 ff00.0021 = 0 +48 ff00.0021 = 0 +49 ff00.0021 = 0 +50 ff00.0021 = 0 +51 ff00.0021 = 0 +52 ff00.0021 = 0 +53 ff00.0021 = 0 +54 ff00.0021 = 0 -- cgit v1.3 From a491f6dc947f428f4f1977bd06d336492989feeb Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 1 Dec 2021 14:58:33 +0200 Subject: Removed constant attribute --- hid-tmt300rs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hid-tmt300rs.h b/hid-tmt300rs.h index f50e789..f86770f 100644 --- a/hid-tmt300rs.h +++ b/hid-tmt300rs.h @@ -317,8 +317,8 @@ static u8 t300rs_rdesc_ps4_fixed[] = { 0x05, 0x01, /* Usage page (Vendor 1) */ /* constant zero? */ 0x09, 0x00, /* Usage (33) */ - 0x95, 0x21, /* Report count (54) */ - 0x81, 0x03, /* Input (Variable, Absolute, Constant) */ + 0x95, 0x21, /* Report count (33) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ /* wheel */ 0x09, 0x30, /* Usage (X) */ 0x15, 0x00, /* Logical minimum (0) */ @@ -341,7 +341,7 @@ static u8 t300rs_rdesc_ps4_fixed[] = { 0x09, 0x00, /* Usage (U) */ 0x75, 0x08, /* Report size (8) */ 0x95, 0x0d, /* Report count (13) */ - 0x81, 0x03, /* Input (Variable, Absolute, Constant) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ /* continue unmodified */ 0x06, 0x00, 0xff, /* Usage page (Vendor defined 1) */ 0x85, 0x60, /* Report ID (5) (change to 0x60?) */ -- cgit v1.3 From 695bb2443b8b698d74a8dfc3887911b08a7c5f2a Mon Sep 17 00:00:00 2001 From: Kimplul Date: Fri, 3 Dec 2021 00:11:19 +0200 Subject: Normal mode pedal default inputs fixed + Defaults modified in accordance to DiRT 4 T300RS defaults. Should work alright in other games as well. --- hid-tmt300rs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hid-tmt300rs.h b/hid-tmt300rs.h index f86770f..d5d6169 100644 --- a/hid-tmt300rs.h +++ b/hid-tmt300rs.h @@ -157,13 +157,13 @@ static u8 t300rs_rdesc_nrm_fixed[] = { 0x75, 0x10, /* Report size (16) */ 0x95, 0x01, /* Report count (1) */ 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x35, /* Usage (Rz) */ + 0x09, 0x31, /* Usage (Y) (was Rz) (Brake) */ 0x26, 0xff, 0x03, /* Logical maximum (1023) */ 0x46, 0xff, 0x03, /* Physical maximum (1023) */ 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x32, /* Usage (Z) */ + 0x09, 0x35, /* Usage (Rz) (was Z) (Gas) */ 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x31, /* Usage (Y) */ + 0x09, 0x33, /* Usage (Rx) (was Y) (Clutch) */ 0x81, 0x02, /* Input (Variable, Absolute) */ 0x81, 0x03, /* Input (Variable, Absolute, Constant) */ 0x05, 0x09, /* Usage page (Button) */ -- cgit v1.3 From 6435ec299af7caedca4f0e648b122b52e76f34fb Mon Sep 17 00:00:00 2001 From: Kimplul Date: Fri, 3 Dec 2021 17:58:53 +0200 Subject: Revert to more standard pedal mapping Remap in games when needed. --- hid-tmt300rs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hid-tmt300rs.h b/hid-tmt300rs.h index d5d6169..114cafd 100644 --- a/hid-tmt300rs.h +++ b/hid-tmt300rs.h @@ -157,13 +157,13 @@ static u8 t300rs_rdesc_nrm_fixed[] = { 0x75, 0x10, /* Report size (16) */ 0x95, 0x01, /* Report count (1) */ 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x31, /* Usage (Y) (was Rz) (Brake) */ + 0x09, 0x35, /* Usage (Rz) (Brake) */ 0x26, 0xff, 0x03, /* Logical maximum (1023) */ 0x46, 0xff, 0x03, /* Physical maximum (1023) */ 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x35, /* Usage (Rz) (was Z) (Gas) */ + 0x09, 0x32, /* Usage (Z) (Gas) */ 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x33, /* Usage (Rx) (was Y) (Clutch) */ + 0x09, 0x31, /* Usage (Y) (Clutch) */ 0x81, 0x02, /* Input (Variable, Absolute) */ 0x81, 0x03, /* Input (Variable, Absolute, Constant) */ 0x05, 0x09, /* Usage page (Button) */ -- cgit v1.3 From 4503f35397f24623ecb286dbea6685a9be67b7d9 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Thu, 27 Jan 2022 15:45:41 +0200 Subject: add in stick shifter to T300RS PS4 rdesc --- hid-tmt300rs.c | 1 + hid-tmt300rs.h | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 4bd8bc3..36df5ee 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -1621,6 +1621,7 @@ static void t300rs_remove(struct hid_device *hdev) } hrtimer_cancel(&t300rs->hrtimer); + drv_data->device_props = NULL; device_remove_file(&hdev->dev, &dev_attr_range); device_remove_file(&hdev->dev, &dev_attr_adv_mode); diff --git a/hid-tmt300rs.h b/hid-tmt300rs.h index 114cafd..d811b90 100644 --- a/hid-tmt300rs.h +++ b/hid-tmt300rs.h @@ -337,10 +337,19 @@ static u8 t300rs_rdesc_ps4_fixed[] = { /* clutch */ 0x09, 0x35, /* Usage (Rz) */ 0x81, 0x02, /* Input (Variable, Absolute) */ + /* stick shifter (check model no) */ + 0x05, 0x09, /* Usage page (Button) */ + 0x19, 0x0f, /* Usage minimum (15) */ + 0x29, 0x17, /* Usage maximum (23) */ + 0x15, 0x00, /* Logical minimum (1) */ + 0x25, 0x01, /* Logical maximum (1) */ + 0x75, 0x01, /* Report size (1) */ + 0x95, 0x08, /* Report count (8) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ /* no clue */ 0x09, 0x00, /* Usage (U) */ 0x75, 0x08, /* Report size (8) */ - 0x95, 0x0d, /* Report count (13) */ + 0x95, 0x0c, /* Report count (12) */ 0x81, 0x02, /* Input (Variable, Absolute) */ /* continue unmodified */ 0x06, 0x00, 0xff, /* Usage page (Vendor defined 1) */ -- cgit v1.3 From c78811a22895bf2dd7645a69a9676c0534936f5e Mon Sep 17 00:00:00 2001 From: Kimplul Date: Thu, 27 Jan 2022 16:01:32 +0200 Subject: add generic desktop usage page after shifter + Not sure if strictly necessary, but follows better form (I think) --- hid-tmt300rs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/hid-tmt300rs.h b/hid-tmt300rs.h index d811b90..a875a2e 100644 --- a/hid-tmt300rs.h +++ b/hid-tmt300rs.h @@ -347,6 +347,7 @@ static u8 t300rs_rdesc_ps4_fixed[] = { 0x95, 0x08, /* Report count (8) */ 0x81, 0x02, /* Input (Variable, Absolute) */ /* no clue */ + 0x05, 0x01, /* Usage page (Generic Desktop) */ 0x09, 0x00, /* Usage (U) */ 0x75, 0x08, /* Report size (8) */ 0x95, 0x0c, /* Report count (12) */ -- cgit v1.3 From 3162692e2b59803ad947421879fbc4ca35c43b01 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Fri, 11 Mar 2022 01:00:55 +0200 Subject: more sensible handling of effect updating --- TODO | 4 ++ hid-tminit | 2 +- hid-tmt300rs.c | 138 +++++++++++++++++++++++++++++---------------------------- 3 files changed, 76 insertions(+), 68 deletions(-) create mode 100644 TODO diff --git a/TODO b/TODO new file mode 100644 index 0000000..87db3d1 --- /dev/null +++ b/TODO @@ -0,0 +1,4 @@ ++ Make code more general to allow for stuff like T150/T248/T500 to be relatively +easily included. + ++ Use workqueues instead of doing everything in t300rs_timer diff --git a/hid-tminit b/hid-tminit index 8b9802a..53fde05 160000 --- a/hid-tminit +++ b/hid-tminit @@ -1 +1 @@ -Subproject commit 8b9802ac40ade7a09c6bc52298e3501cfdc0732c +Subproject commit 53fde059e88a4314d987ab75518edb8ce86cf8a3 diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 36df5ee..0c2de06 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -127,7 +127,7 @@ static void t300rs_fill_timing(struct t300rs_packet_timing *packet_timing, packet_timing->end_marker = 0xffff; } -static int t300rs_modify_envelope(struct t300rs_device_entry *t300rs, +static int t300rs_update_envelope(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state, int16_t level, uint16_t duration, @@ -204,7 +204,7 @@ error: return ret; } -static int t300rs_modify_duration(struct t300rs_device_entry *t300rs, +static int t300rs_update_duration(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state) { struct ff_effect effect = state->effect; @@ -237,7 +237,7 @@ error: return ret; } -static int t300rs_modify_constant(struct t300rs_device_entry *t300rs, +static int t300rs_update_constant(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state) { struct ff_effect effect = state->effect; @@ -266,7 +266,7 @@ static int t300rs_modify_constant(struct t300rs_device_entry *t300rs, } - ret = t300rs_modify_envelope(t300rs, + ret = t300rs_update_envelope(t300rs, state, level, effect.replay.length, @@ -280,7 +280,7 @@ static int t300rs_modify_constant(struct t300rs_device_entry *t300rs, goto error; } - ret = t300rs_modify_duration(t300rs, state); + ret = t300rs_update_duration(t300rs, state); if (ret) { hid_err(t300rs->hdev, "failed modifying constant duration\n"); goto error; @@ -290,7 +290,7 @@ error: return ret; } -static int t300rs_modify_ramp(struct t300rs_device_entry *t300rs, +static int t300rs_update_ramp(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state) { struct ff_effect effect = state->effect; @@ -333,7 +333,7 @@ static int t300rs_modify_ramp(struct t300rs_device_entry *t300rs, } - ret = t300rs_modify_envelope(t300rs, + ret = t300rs_update_envelope(t300rs, state, level, effect.replay.length, @@ -348,7 +348,7 @@ static int t300rs_modify_ramp(struct t300rs_device_entry *t300rs, goto error; } - ret = t300rs_modify_duration(t300rs, state); + ret = t300rs_update_duration(t300rs, state); if (ret) { hid_err(t300rs->hdev, "failed modifying ramp duration\n"); goto error; @@ -357,7 +357,8 @@ static int t300rs_modify_ramp(struct t300rs_device_entry *t300rs, error: return ret; } -static int t300rs_modify_damper(struct t300rs_device_entry *t300rs, + +static int t300rs_update_damper(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state) { struct ff_effect effect = state->effect; @@ -429,7 +430,7 @@ static int t300rs_modify_damper(struct t300rs_device_entry *t300rs, } - ret = t300rs_modify_duration(t300rs, state); + ret = t300rs_update_duration(t300rs, state); if (ret) { hid_err(t300rs->hdev, "failed modifying damper duration\n"); goto error; @@ -439,8 +440,14 @@ error: return ret; } +static int t300rs_update_spring(struct t300rs_device_entry *t300rs, + struct t300rs_effect_state *state) +{ + return t300rs_update_damper(t300rs, state); +} + -static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, +static int t300rs_update_periodic(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state) { struct ff_effect effect = state->effect; @@ -526,7 +533,7 @@ static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, } - ret = t300rs_modify_envelope(t300rs, + ret = t300rs_update_envelope(t300rs, state, magnitude, effect.replay.length, @@ -540,7 +547,7 @@ static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, goto error; } - ret = t300rs_modify_duration(t300rs, state); + ret = t300rs_update_duration(t300rs, state); if (ret) { hid_err(t300rs->hdev, "failed modifying periodic duration\n"); goto error; @@ -568,20 +575,6 @@ static int t300rs_upload_constant(struct t300rs_device_entry *t300rs, int ret; - /* some games, such as DiRT Rally 2 have a weird feeling to them, sort of - * like the wheel pulls just a bit to the right or left and then it just - * stops. I wouldn't be surprised if it's got something to do with the - * constant envelope, but right now I don't know. - */ - - if (test_bit(FF_EFFECT_PLAYING, &state->flags) - && test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { - - __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); - - return t300rs_modify_constant(t300rs, state); - } - level = (constant.level * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; duration = effect.replay.length - 1; @@ -623,14 +616,6 @@ static int t300rs_upload_ramp(struct t300rs_device_entry *t300rs, uint16_t difference, offset, top, bottom, duration; int16_t level; - if (test_bit(FF_EFFECT_PLAYING, &state->flags) - && test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { - - __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); - - return t300rs_modify_ramp(t300rs, state); - } - duration = effect.replay.length - 1; top = ramp.end_level > ramp.start_level ? ramp.end_level : ramp.start_level; @@ -682,14 +667,6 @@ static int t300rs_upload_spring(struct t300rs_device_entry *t300rs, int ret; uint16_t duration, right_coeff, left_coeff, right_deadband, left_deadband, offset; - if (test_bit(FF_EFFECT_PLAYING, &state->flags) - && test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { - - __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); - - return t300rs_modify_damper(t300rs, state); - } - duration = effect.replay.length - 1; right_coeff = spring.right_coeff * spring_level / 100; @@ -737,14 +714,6 @@ static int t300rs_upload_damper(struct t300rs_device_entry *t300rs, int ret, input_level; uint16_t duration, right_coeff, left_coeff, right_deadband, left_deadband, offset; - if (test_bit(FF_EFFECT_PLAYING, &state->flags) && - test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { - - __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); - - return t300rs_modify_damper(t300rs, state); - } - duration = effect.replay.length - 1; input_level = damper_level; @@ -797,14 +766,6 @@ static int t300rs_upload_periodic(struct t300rs_device_entry *t300rs, uint16_t duration, magnitude, period, offset; int16_t periodic_offset, phase; - if (test_bit(FF_EFFECT_PLAYING, &state->flags) && - test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { - - __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); - - return t300rs_modify_periodic(t300rs, state); - } - duration = effect.replay.length - 1; magnitude = (periodic.magnitude * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; @@ -814,7 +775,7 @@ static int t300rs_upload_periodic(struct t300rs_device_entry *t300rs, phase += 0x4000; phase = phase < 0 ? -phase : phase; } - + magnitude = magnitude < 0 ? -magnitude : magnitude; periodic_offset = periodic.offset; period = periodic.period; @@ -843,6 +804,28 @@ static int t300rs_upload_periodic(struct t300rs_device_entry *t300rs, return ret; } +static int t300rs_update_effect(struct t300rs_device_entry *t300rs, + struct t300rs_effect_state *state) +{ + switch (state->effect.type) { + case FF_CONSTANT: + return t300rs_update_constant(t300rs, state); + case FF_RAMP: + return t300rs_update_ramp(t300rs, state); + case FF_SPRING: + return t300rs_update_spring(t300rs, state); + case FF_DAMPER: + case FF_FRICTION: + case FF_INERTIA: + return t300rs_update_damper(t300rs, state); + case FF_PERIODIC: + return t300rs_update_periodic(t300rs, state); + default: + hid_err(t300rs->hdev, "invalid effect type: %x", state->effect.type); + return -1; + } +} + static int t300rs_upload_effect(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state) { @@ -892,35 +875,51 @@ static int t300rs_timer_helper(struct t300rs_device_entry *t300rs) if (test_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags)) { __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); + /* if we're uploading an effect, it's bound to be the + * most up to date available */ + __clear_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags); ret = t300rs_upload_effect(t300rs, state); if (ret) { - hid_err(t300rs->hdev, "failed uploading effects"); + hid_err(t300rs->hdev, "failed uploading effect"); return ret; } } + if (test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { + __clear_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags); + + ret = t300rs_update_effect(t300rs, state); + if (ret) { + hid_err(t300rs->hdev, "failed updating effect"); + return ret; + } + } + + /* TODO TODO: add in effect data dump, macro or something? */ + if (test_bit(FF_EFFECT_QUEUE_START, &state->flags)) { __clear_bit(FF_EFFECT_QUEUE_START, &state->flags); - __set_bit(FF_EFFECT_PLAYING, &state->flags); ret = t300rs_play_effect(t300rs, state); if (ret) { - hid_err(t300rs->hdev, "failed starting effects\n"); + hid_err(t300rs->hdev, "failed starting effect\n"); return ret; } + __set_bit(FF_EFFECT_PLAYING, &state->flags); } if (test_bit(FF_EFFECT_QUEUE_STOP, &state->flags)) { __clear_bit(FF_EFFECT_QUEUE_STOP, &state->flags); - __clear_bit(FF_EFFECT_PLAYING, &state->flags); ret = t300rs_stop_effect(t300rs, state); if (ret) { hid_err(t300rs->hdev, "failed stopping effect\n"); return ret; } + + __clear_bit(FF_EFFECT_PLAYING, &state->flags); } if (state->count > max_count) @@ -932,10 +931,14 @@ static int t300rs_timer_helper(struct t300rs_device_entry *t300rs) static enum hrtimer_restart t300rs_timer(struct hrtimer *t) { + /* TODO: use workqueues to be sure nothing is accidentally done in + * atomic context */ struct t300rs_device_entry *t300rs = container_of(t, struct t300rs_device_entry, hrtimer); int max_count; + spin_lock_irqsave(&t300rs->lock, t300rs->lock_flags); max_count = t300rs_timer_helper(t300rs); + spin_unlock_irqrestore(&t300rs->lock, t300rs->lock_flags); if (max_count > 0) { hrtimer_forward_now(&t300rs->hrtimer, ms_to_ktime(timer_msecs)); @@ -968,12 +971,13 @@ static int t300rs_upload(struct input_dev *dev, state->effect = *effect; if (old) { - state->old = *old; + if (test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) + state->old = *old; + __set_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags); } else { - __clear_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags); + __set_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); } - __set_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); spin_unlock_irqrestore(&t300rs->lock, t300rs->lock_flags); -- cgit v1.3 From 4d0e647f17560d968e8a0243f2783627ca632db0 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Fri, 11 Mar 2022 14:24:24 +0200 Subject: move to using delayed workqueues --- hid-tmt300rs.c | 54 ++++++++++++++++++++---------------------------------- hid-tmt300rs.h | 4 ++-- 2 files changed, 22 insertions(+), 36 deletions(-) diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 0c2de06..5bbf295 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include "hid-tmt300rs.h" static int timer_msecs = DEFAULT_TIMER_PERIOD; @@ -848,13 +849,15 @@ static int t300rs_upload_effect(struct t300rs_device_entry *t300rs, } } -static int t300rs_timer_helper(struct t300rs_device_entry *t300rs) +static void t300rs_work_handler(struct work_struct *w) { + struct delayed_work *dw = container_of(w, struct delayed_work, work); + struct t300rs_device_entry *t300rs = container_of(dw, struct t300rs_device_entry, work); struct t300rs_effect_state *state; - unsigned long jiffies_now = JIFFIES2MS(jiffies); int max_count = 0, effect_id, ret; for (effect_id = 0; effect_id < T300RS_MAX_EFFECTS; ++effect_id) { + unsigned long jiffies_now = JIFFIES2MS(jiffies); state = &t300rs->states[effect_id]; @@ -882,7 +885,7 @@ static int t300rs_timer_helper(struct t300rs_device_entry *t300rs) ret = t300rs_upload_effect(t300rs, state); if (ret) { hid_err(t300rs->hdev, "failed uploading effect"); - return ret; + return; } } @@ -892,7 +895,7 @@ static int t300rs_timer_helper(struct t300rs_device_entry *t300rs) ret = t300rs_update_effect(t300rs, state); if (ret) { hid_err(t300rs->hdev, "failed updating effect"); - return ret; + return; } } @@ -904,7 +907,7 @@ static int t300rs_timer_helper(struct t300rs_device_entry *t300rs) ret = t300rs_play_effect(t300rs, state); if (ret) { hid_err(t300rs->hdev, "failed starting effect\n"); - return ret; + return; } __set_bit(FF_EFFECT_PLAYING, &state->flags); @@ -916,7 +919,7 @@ static int t300rs_timer_helper(struct t300rs_device_entry *t300rs) ret = t300rs_stop_effect(t300rs, state); if (ret) { hid_err(t300rs->hdev, "failed stopping effect\n"); - return ret; + return; } __clear_bit(FF_EFFECT_PLAYING, &state->flags); @@ -926,26 +929,8 @@ static int t300rs_timer_helper(struct t300rs_device_entry *t300rs) max_count = state->count; } - return max_count; -} - -static enum hrtimer_restart t300rs_timer(struct hrtimer *t) -{ - /* TODO: use workqueues to be sure nothing is accidentally done in - * atomic context */ - struct t300rs_device_entry *t300rs = container_of(t, struct t300rs_device_entry, hrtimer); - int max_count; - - spin_lock_irqsave(&t300rs->lock, t300rs->lock_flags); - max_count = t300rs_timer_helper(t300rs); - spin_unlock_irqrestore(&t300rs->lock, t300rs->lock_flags); - - if (max_count > 0) { - hrtimer_forward_now(&t300rs->hrtimer, ms_to_ktime(timer_msecs)); - return HRTIMER_RESTART; - } else { - return HRTIMER_NORESTART; - } + if (max_count) + schedule_delayed_work(&t300rs->work, msecs_to_jiffies(timer_msecs)); } static int t300rs_upload(struct input_dev *dev, @@ -1015,10 +1000,11 @@ static int t300rs_play(struct input_dev *dev, int effect_id, int value) __set_bit(FF_EFFECT_QUEUE_STOP, &state->flags); } - if (!hrtimer_active(&t300rs->hrtimer)) - hrtimer_start(&t300rs->hrtimer, ms_to_ktime(timer_msecs), HRTIMER_MODE_REL); - spin_unlock_irqrestore(&t300rs->lock, t300rs->lock_flags); + + if (!delayed_work_pending(&t300rs->work)) + schedule_delayed_work(&t300rs->work, 0); + return 0; } @@ -1497,6 +1483,8 @@ static int t300rs_init(struct hid_device *hdev, const signed short *ff_bits) goto version_err; } + INIT_DELAYED_WORK(&t300rs->work, t300rs_work_handler); + spin_lock_init(&t300rs->lock); drv_data->device_props = t300rs; @@ -1539,9 +1527,6 @@ static int t300rs_init(struct hid_device *hdev, const signed short *ff_bits) } - hrtimer_init(&t300rs->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - t300rs->hrtimer.function = t300rs_timer; - range_store(dev, &dev_attr_range, range, 10); t300rs_set_gain(input_dev, 0xffff); @@ -1624,8 +1609,7 @@ static void t300rs_remove(struct hid_device *hdev) return; } - hrtimer_cancel(&t300rs->hrtimer); - drv_data->device_props = NULL; + cancel_delayed_work_sync(&t300rs->work); device_remove_file(&hdev->dev, &dev_attr_range); device_remove_file(&hdev->dev, &dev_attr_adv_mode); @@ -1634,6 +1618,8 @@ static void t300rs_remove(struct hid_device *hdev) device_remove_file(&hdev->dev, &dev_attr_friction_level); hid_hw_stop(hdev); + + drv_data->device_props = NULL; kfree(t300rs->states); kfree(t300rs->send_buffer); kfree(t300rs->firmware_response); diff --git a/hid-tmt300rs.h b/hid-tmt300rs.h index a875a2e..4b565ce 100644 --- a/hid-tmt300rs.h +++ b/hid-tmt300rs.h @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -119,7 +118,8 @@ struct t300rs_device_entry { struct usb_interface *usbif; struct t300rs_effect_state *states; struct t300rs_firmware_response *firmware_response; - struct hrtimer hrtimer; + + struct delayed_work work; int (*open)(struct input_dev *dev); void (*close)(struct input_dev *dev); -- cgit v1.3 From 68a0e85104c2f6b7b91d26b9d6592ba7efa545f6 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Fri, 11 Mar 2022 14:35:16 +0200 Subject: add locks around work handler --- hid-tmt300rs.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 5bbf295..4a73d60 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -855,10 +855,12 @@ static void t300rs_work_handler(struct work_struct *w) struct t300rs_device_entry *t300rs = container_of(dw, struct t300rs_device_entry, work); struct t300rs_effect_state *state; int max_count = 0, effect_id, ret; + unsigned long jiffies_now; for (effect_id = 0; effect_id < T300RS_MAX_EFFECTS; ++effect_id) { - unsigned long jiffies_now = JIFFIES2MS(jiffies); + spin_lock(&t300rs->lock); + jiffies_now = JIFFIES2MS(jiffies); state = &t300rs->states[effect_id]; if (test_bit(FF_EFFECT_PLAYING, &state->flags) && state->effect.replay.length) { @@ -927,6 +929,8 @@ static void t300rs_work_handler(struct work_struct *w) if (state->count > max_count) max_count = state->count; + + spin_unlock(&t300rs->lock); } if (max_count) @@ -951,7 +955,7 @@ static int t300rs_upload(struct input_dev *dev, state = &t300rs->states[effect->id]; - spin_lock_irqsave(&t300rs->lock, t300rs->lock_flags); + spin_lock(&t300rs->lock); state->effect = *effect; @@ -964,7 +968,7 @@ static int t300rs_upload(struct input_dev *dev, __set_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); } - spin_unlock_irqrestore(&t300rs->lock, t300rs->lock_flags); + spin_unlock(&t300rs->lock); return 0; } @@ -986,7 +990,7 @@ static int t300rs_play(struct input_dev *dev, int effect_id, int value) if (&state->effect == 0) return 0; - spin_lock_irqsave(&t300rs->lock, t300rs->lock_flags); + spin_lock(&t300rs->lock); if (value > 0) { state->count = value; @@ -1000,7 +1004,7 @@ static int t300rs_play(struct input_dev *dev, int effect_id, int value) __set_bit(FF_EFFECT_QUEUE_STOP, &state->flags); } - spin_unlock_irqrestore(&t300rs->lock, t300rs->lock_flags); + spin_unlock(&t300rs->lock); if (!delayed_work_pending(&t300rs->work)) schedule_delayed_work(&t300rs->work, 0); -- cgit v1.3 From 3da7cf43b6b5de10a1f349cdd9db2b705bf66e93 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sat, 12 Mar 2022 12:53:31 +0200 Subject: change errors to warnings in work_handler --- hid-tmt300rs.c | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 4a73d60..e32bb28 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -854,7 +854,7 @@ static void t300rs_work_handler(struct work_struct *w) struct delayed_work *dw = container_of(w, struct delayed_work, work); struct t300rs_device_entry *t300rs = container_of(dw, struct t300rs_device_entry, work); struct t300rs_effect_state *state; - int max_count = 0, effect_id, ret; + int max_count = 0, effect_id; unsigned long jiffies_now; for (effect_id = 0; effect_id < T300RS_MAX_EFFECTS; ++effect_id) { @@ -884,21 +884,15 @@ static void t300rs_work_handler(struct work_struct *w) * most up to date available */ __clear_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags); - ret = t300rs_upload_effect(t300rs, state); - if (ret) { - hid_err(t300rs->hdev, "failed uploading effect"); - return; - } + if (t300rs_upload_effect(t300rs, state)) + hid_warn(t300rs->hdev, "failed uploading effect"); } if (test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { __clear_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags); - ret = t300rs_update_effect(t300rs, state); - if (ret) { - hid_err(t300rs->hdev, "failed updating effect"); - return; - } + if (t300rs_update_effect(t300rs, state)) + hid_warn(t300rs->hdev, "failed updating effect"); } /* TODO TODO: add in effect data dump, macro or something? */ @@ -906,11 +900,8 @@ static void t300rs_work_handler(struct work_struct *w) if (test_bit(FF_EFFECT_QUEUE_START, &state->flags)) { __clear_bit(FF_EFFECT_QUEUE_START, &state->flags); - ret = t300rs_play_effect(t300rs, state); - if (ret) { - hid_err(t300rs->hdev, "failed starting effect\n"); - return; - } + if (t300rs_play_effect(t300rs, state)) + hid_warn(t300rs->hdev, "failed starting effect\n"); __set_bit(FF_EFFECT_PLAYING, &state->flags); } @@ -918,11 +909,8 @@ static void t300rs_work_handler(struct work_struct *w) if (test_bit(FF_EFFECT_QUEUE_STOP, &state->flags)) { __clear_bit(FF_EFFECT_QUEUE_STOP, &state->flags); - ret = t300rs_stop_effect(t300rs, state); - if (ret) { - hid_err(t300rs->hdev, "failed stopping effect\n"); - return; - } + if (t300rs_stop_effect(t300rs, state)) + hid_warn(t300rs->hdev, "failed stopping effect\n"); __clear_bit(FF_EFFECT_PLAYING, &state->flags); } -- cgit v1.3 From dc3f9610f24fe43540541f2ab1a990903be20ed3 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sat, 12 Mar 2022 12:54:10 +0200 Subject: rename jiffies_now -> time_now --- hid-tmt300rs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index e32bb28..e522861 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -855,16 +855,16 @@ static void t300rs_work_handler(struct work_struct *w) struct t300rs_device_entry *t300rs = container_of(dw, struct t300rs_device_entry, work); struct t300rs_effect_state *state; int max_count = 0, effect_id; - unsigned long jiffies_now; + unsigned long time_now; for (effect_id = 0; effect_id < T300RS_MAX_EFFECTS; ++effect_id) { spin_lock(&t300rs->lock); - jiffies_now = JIFFIES2MS(jiffies); + time_now = JIFFIES2MS(jiffies); state = &t300rs->states[effect_id]; if (test_bit(FF_EFFECT_PLAYING, &state->flags) && state->effect.replay.length) { - if ((jiffies_now - state->start_time) >= state->effect.replay.length) { + if ((time_now - state->start_time) >= state->effect.replay.length) { __clear_bit(FF_EFFECT_PLAYING, &state->flags); /* lazy bum fix? */ -- cgit v1.3 From 60e90e0a96039c58968de551aadca0fab490d35d Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sat, 12 Mar 2022 18:00:40 +0200 Subject: allow for wheel 'backends' --- Makefile | 2 +- hid-tmff2.c | 577 +++++++++++++++++++++++++ hid-tmff2.h | 76 ++++ hid-tmt300rs.c | 1313 ++++++++++++++++++++++++++------------------------------ hid-tmt300rs.h | 403 ----------------- 5 files changed, 1261 insertions(+), 1110 deletions(-) create mode 100644 hid-tmff2.c create mode 100644 hid-tmff2.h delete mode 100644 hid-tmt300rs.h diff --git a/Makefile b/Makefile index 1b4e1f4..9a7b851 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -obj-m += hid-tmt300rs.o +obj-m += hid-tmff2.o KDIR ?= /lib/modules/$(shell uname -r)/build all: hid-tminit diff --git a/hid-tmff2.c b/hid-tmff2.c new file mode 100644 index 0000000..f1d1f84 --- /dev/null +++ b/hid-tmff2.c @@ -0,0 +1,577 @@ +#include +#include +#include +#include "hid-tmff2.h" + +static int timer_msecs = DEFAULT_TIMER_PERIOD; +module_param(timer_msecs, int, 0660); +MODULE_PARM_DESC(timer_msecs, + "Timer resolution in msecs"); + +/* should these be removed and just rely on /sys? */ +static int spring_level = 30; +module_param(spring_level, int, 0); +MODULE_PARM_DESC(spring_level, + "Level of spring force (0-100), as per Oversteer standards"); + +static int damper_level = 30; +module_param(damper_level, int, 0); +MODULE_PARM_DESC(damper_level, + "Level of damper force (0-100), as per Oversteer standards"); + +static int friction_level = 30; +module_param(friction_level, int, 0); +MODULE_PARM_DESC(friction_level, + "Level of friction force (0-100), as per Oversteer standards"); + +static int range = 900; +module_param(range, int, 0); +MODULE_PARM_DESC(range, + "Range of wheel, depends on the wheel. Invalid values are ignored."); + +static int alt_mode = 0; +module_param(alt_mode, int, 0); +MODULE_PARM_DESC(alt_mode, + "Alternate mode, eg. T300RS F1 mode."); + +static spinlock_t lock; +static unsigned long lock_flags; + +static struct tmff2_device_entry *tmff2_from_hdev(struct hid_device *hdev) +{ + struct tmff2_device_entry *tmff2; + spin_lock_irqsave(&lock, lock_flags); + if (!(tmff2 = hid_get_drvdata(hdev))) { + dev_err(&hdev->dev, "hdev private data not found\n"); + return NULL; + } + spin_unlock_irqrestore(&lock, lock_flags); + + return tmff2; +} + +static struct tmff2_device_entry *tmff2_from_input(struct input_dev *input_dev) +{ + struct tmff2_device_entry *tmff2; + spin_lock_irqsave(&lock, lock_flags); + if (!(tmff2 = input_get_drvdata(input_dev))) { + dev_err(&input_dev->dev, "input_dev private data not found\n"); + return NULL; + } + spin_unlock_irqrestore(&lock, lock_flags); + + return tmff2; +} + +static ssize_t spring_level_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int value; + int ret; + + ret = kstrtouint(buf, 0, &value); + if (ret) { + dev_err(dev, "kstrtouint failed at spring_level_store: %i", ret); + return ret; + } + + if (value > 100) { + dev_info(dev, "value %i larger than max 100, clamping to 100.\n", value); + value = 100; + } + + spring_level = value; + + return count; +} + +static ssize_t spring_level_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%u\n", spring_level); +} +static DEVICE_ATTR_RW(spring_level); + +static ssize_t damper_level_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int value; + int ret; + + ret = kstrtouint(buf, 0, &value); + if (ret) { + dev_err(dev, "kstrtouint failed at damper_level_store: %i", ret); + return ret; + } + + if (value > 100) { + dev_info(dev, "value %i larger than max 100, clamping to 100.\n", value); + value = 100; + } + + damper_level = value; + + return count; +} + +static ssize_t damper_level_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%u\n", damper_level); +} +static DEVICE_ATTR_RW(damper_level); + +static ssize_t friction_level_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int value; + int ret; + + ret = kstrtouint(buf, 0, &value); + if (ret) { + dev_err(dev, "kstrtouint failed at friction_level_store: %i", ret); + return ret; + } + + if (value > 100) { + dev_info(dev, "value %i larger than max 100, clamping to 100.\n", value); + value = 100; + } + + friction_level = value; + + return count; +} + +static ssize_t friction_level_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + size_t count; + + count = scnprintf(buf, PAGE_SIZE, "%u\n", friction_level); + + return count; +} +static DEVICE_ATTR_RW(friction_level); + +static ssize_t range_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct tmff2_device_entry *tmff2 = tmff2_from_hdev(to_hid_device(dev)); + unsigned int value; + int ret; + + if (!tmff2) + return -ENODEV; + + if ((ret = kstrtouint(buf, 0, &value))) { + hid_err(tmff2->hdev, "kstrtouint failed at range_store: %i", ret); + return ret; + } + + if (tmff2->set_range) { + if ((ret = tmff2->set_range(tmff2->data, value))) + return ret; + } + + return count; +} + +static ssize_t range_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%u\n", range); +} +static DEVICE_ATTR_RW(range); + +static ssize_t alt_mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct tmff2_device_entry *tmff2 = tmff2_from_hdev(to_hid_device(dev)); + unsigned int value; + int ret; + + if (!tmff2) + return -ENODEV; + + if ((ret = kstrtouint(buf, 0, &value))) { + hid_err(tmff2->hdev, "kstrtouint failed at alt_mode_store: %i", ret); + return ret; + } + + if (tmff2->switch_mode) { + if ((ret = tmff2->switch_mode(tmff2->data, value))) + return ret; + } + + return count; +} + +static ssize_t alt_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + /* TODO: could be cool to add in something like a small menu that gives + * names and corresponding index to modes, or maybe parsing modes + * directly? */ + return scnprintf(buf, PAGE_SIZE, "%i\n", alt_mode); +} +static DEVICE_ATTR_RW(alt_mode); + +/* include each wheel */ +#include "hid-tmt300rs.c" + +static void tmff2_set_gain(struct input_dev *dev, uint16_t gain) +{ + struct tmff2_device_entry *tmff2 = tmff2_from_input(dev); + if (!tmff2) + return; + + if (!tmff2->set_gain) { + hid_err(tmff2->hdev, "missing set_gain\n"); + return; + } + + if (tmff2->set_gain(tmff2->data, gain)) + hid_warn(tmff2->hdev, "unable to set gain\n"); +} + +static void tmff2_set_autocenter(struct input_dev *dev, uint16_t autocenter) +{ + struct tmff2_device_entry *tmff2 = tmff2_from_input(dev); + if (!tmff2) + return; + + if (!tmff2->set_autocenter) { + hid_err(tmff2->hdev, "missing set_autocenter\n"); + return; + } + + if (tmff2->set_autocenter(tmff2->data, autocenter)) + hid_warn(tmff2->hdev, "unable to set autocenter\n"); +} + +static void tmff2_work_handler(struct work_struct *w) +{ + struct delayed_work *dw = container_of(w, struct delayed_work, work); + struct tmff2_device_entry *tmff2 = container_of(dw, struct tmff2_device_entry, work); + struct tmff2_effect_state *state; + int max_count = 0, effect_id; + unsigned long time_now; + __u16 effect_length; + + if (!tmff2) + return; + + for (effect_id = 0; effect_id < tmff2->max_effects; ++effect_id) { + spin_lock(&tmff2->lock); + + time_now = JIFFIES2MS(jiffies); + state = &tmff2->states[effect_id]; + + effect_length = state->effect.replay.length; + if (test_bit(FF_EFFECT_PLAYING, &state->flags) && effect_length) { + if ((time_now - state->start_time) >= effect_length) { + __clear_bit(FF_EFFECT_PLAYING, &state->flags); + __clear_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags); + + if (state->count) + state->count--; + + if (state->count) + __set_bit(FF_EFFECT_QUEUE_START, &state->flags); + } + } + + if (test_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags)) { + if (tmff2->upload_effect(tmff2->data, state)) { + hid_warn(tmff2->hdev, "failed uploading effect\n"); + } else { + __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); + /* if we're uploading an effect, it's bound to be the up + * to date available */ + __clear_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags); + } + } + + if (test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { + if (tmff2->update_effect(tmff2->data, state)) + hid_warn(tmff2->hdev, "failed updating effect\n"); + else + __clear_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags); + } + + if (test_bit(FF_EFFECT_QUEUE_START, &state->flags)) { + if (tmff2->play_effect(tmff2, state)) { + hid_warn(tmff2->hdev, "failed starting effect\n"); + } else { + __clear_bit(FF_EFFECT_QUEUE_START, &state->flags); + __set_bit(FF_EFFECT_PLAYING, &state->flags); + } + + } + + if (test_bit(FF_EFFECT_QUEUE_STOP, &state->flags)) { + if (tmff2->stop_effect(tmff2, state)) { + hid_warn(tmff2->hdev, "failed stopping effect\n"); + } else { + __clear_bit(FF_EFFECT_PLAYING, &state->flags); + __clear_bit(FF_EFFECT_QUEUE_STOP, &state->flags); + } + } + + if (state->count > max_count) + max_count = state->count; + + spin_unlock(&tmff2->lock); + } + + if (max_count) + schedule_delayed_work(&tmff2->work, msecs_to_jiffies(timer_msecs)); +} + +static int tmff2_upload(struct input_dev *dev, + struct ff_effect *effect, struct ff_effect *old) +{ + struct tmff2_effect_state *state; + struct tmff2_device_entry *tmff2 = tmff2_from_input(dev); + if (!tmff2) + return -ENODEV; + + if (effect->type == FF_PERIODIC && effect->u.periodic.period == 0) + return -EINVAL; + + state = &tmff2->states[effect->id]; + + spin_lock(&tmff2->lock); + + state->effect = *effect; + + if (old) { + if (test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) + state->old = *old; + + __set_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags); + } else { + __set_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); + } + + spin_unlock(&tmff2->lock); + return 0; +} + +static int tmff2_play(struct input_dev *dev, int effect_id, int value) +{ + struct tmff2_effect_state *state; + struct tmff2_device_entry *tmff2 = tmff2_from_input(dev); + if (!tmff2) + return -ENODEV; + + state = &tmff2->states[effect_id]; + if (&state->effect == 0) + return 0; + + spin_lock(&tmff2->lock); + if (value > 0) { + state->count = value; + state->start_time = JIFFIES2MS(jiffies); + __set_bit(FF_EFFECT_QUEUE_START, &state->flags); + __clear_bit(FF_EFFECT_QUEUE_STOP, &state->flags); + } else { + __set_bit(FF_EFFECT_QUEUE_STOP, &state->flags); + __clear_bit(FF_EFFECT_QUEUE_START, &state->flags); + } + + spin_unlock(&tmff2->lock); + + if (!delayed_work_pending(&tmff2->work)) + schedule_delayed_work(&tmff2->work, 0); + + return 0; +} + +static int tmff2_open(struct input_dev *dev) +{ + struct tmff2_device_entry *tmff2 = tmff2_from_input(dev); + if (!tmff2) + return -ENODEV; + + if (tmff2->open) + return tmff2->open(tmff2->data); + + hid_err(tmff2->hdev, "no open callback set\n"); + return -EINVAL; +} + +static void tmff2_close(struct input_dev *dev) +{ + struct tmff2_device_entry *tmff2 = tmff2_from_input(dev); + if (!tmff2) + return; + + if (tmff2->close) { + tmff2->close(tmff2->data); + return; + } + + hid_err(tmff2->hdev, "no close callback set\n"); +} + +static int tmff2_wheel_init(struct tmff2_device_entry *tmff2) +{ + int ret, i; + struct ff_device *ff; + spin_lock_init(&tmff2->lock); + INIT_DELAYED_WORK(&tmff2->work, tmff2_work_handler); + + tmff2->states = kzalloc(sizeof(struct tmff2_effect_state) * tmff2->max_effects, + GFP_KERNEL); + + if (!tmff2->states) { + ret = -ENOMEM; + goto err; + } + + /* is this required or should it be done in t300rs_populate_api? */ + if ((ret = tmff2->wheel_init(tmff2->data))) + goto err; + + /* set supported effects into input_dev->ffbit */ + for (i = 0; tmff2->supported_effects[i] >= 0; ++i) + __set_bit(tmff2->supported_effects[i], tmff2->input_dev->ffbit); + + /* create actual ff device*/ + if ((ret = input_ff_create(tmff2->input_dev, tmff2->max_effects))) { + hid_err(tmff2->hdev, "could not create input_ff\n"); + goto err; + } + + /* set ff callbacks */ + ff = tmff2->input_dev->ff; + ff->upload = tmff2_upload; + ff->playback = tmff2_play; + + if (tmff2->open) + tmff2->input_dev->open = tmff2_open; + + if (tmff2->close) + tmff2->input_dev->close = tmff2_close; + + if (tmff2->set_gain) + ff->set_gain = tmff2_set_gain; + + if (tmff2->set_autocenter) + ff->set_autocenter = tmff2_set_autocenter; + + return 0; + +err: + return ret; +} + +static int tmff2_probe(struct hid_device *hdev, const struct hid_device_id *id) +{ + struct tmff2_device_entry *tmff2 = + kzalloc(sizeof(struct tmff2_device_entry), GFP_KERNEL); + + int ret; + + if (!tmff2) { + ret = -ENOMEM; + goto oom_err; + } + + tmff2->hdev = hdev; + hid_set_drvdata(tmff2->hdev, tmff2); + tmff2->input_dev = list_entry(hdev->inputs.next, struct hid_input, list)->input; + input_set_drvdata(tmff2->input_dev, tmff2); + + switch (tmff2->hdev->product) { + /* t300rs */ + case 0xb66e: + case 0xb66f: + case 0xb66d: + if ((ret = t300rs_populate_api(tmff2))) + goto wheel_err; + break; + default: + ret = -ENODEV; + goto wheel_err; + } + + if ((ret = hid_parse(tmff2->hdev))) { + hid_err(hdev, "parse failed\n"); + goto hid_err; + } + + if ((ret = hid_hw_start(tmff2->hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF))) { + hid_err(hdev, "hw start failed\n"); + goto hid_err; + } + + if ((ret = tmff2_wheel_init(tmff2))) { + hid_err(hdev, "init failed\n"); + goto init_err; + } + + return 0; + +init_err: + hid_hw_stop(hdev); + +hid_err: + tmff2->wheel_destroy(tmff2->data); + +wheel_err: + kfree(tmff2); + +oom_err: + return ret; +} + +static __u8 *tmff2_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) +{ + struct tmff2_device_entry *tmff2 = tmff2_from_hdev(hdev); + if (!tmff2) /* not entirely sure what the best course of action would be here */ + return rdesc; + + if (tmff2->wheel_fixup) + return tmff2->wheel_fixup(hdev, rdesc, rsize); + + return rdesc; +} + +static void tmff2_remove(struct hid_device *hdev) +{ + struct tmff2_device_entry *tmff2 = tmff2_from_hdev(hdev); + if (!tmff2) + return; + + cancel_delayed_work_sync(&tmff2->work); + tmff2->wheel_destroy(tmff2->data); + + hid_hw_stop(hdev); + + kfree(tmff2->states); + kfree(tmff2); +} + +static const struct hid_device_id tmff2_devices[] = { + /* t300rs and variations */ + {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb66e)}, + {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb66f)}, + {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb66d)}, + {} +}; +MODULE_DEVICE_TABLE(hid, tmff2_devices); + +static struct hid_driver tmff2_driver = { + .name = "tmff2", + .id_table = tmff2_devices, + .probe = tmff2_probe, + .remove = tmff2_remove, + .report_fixup = tmff2_report_fixup, +}; +module_hid_driver(tmff2_driver); + +MODULE_LICENSE("GPL"); diff --git a/hid-tmff2.h b/hid-tmff2.h new file mode 100644 index 0000000..bdde1a7 --- /dev/null +++ b/hid-tmff2.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _HID_TMFF2 +#define _HID_TMFF2 + +#include +#include +#include + +#define USB_VENDOR_ID_THRUSTMASTER 0x044f + +/* the wheel seems to only be capable of processing a certain number of + * interrupts per second, and if this value is too low the kernel urb buffer(or + * some buffer at least) fills up. Optimally I would figure out some way to + * space out the interrupts so that they all leave at regular intervals, but + * for now this is good enough, go slow enough that everything works. + */ +#define DEFAULT_TIMER_PERIOD 8 + +#define FF_EFFECT_QUEUE_UPLOAD 0 +#define FF_EFFECT_QUEUE_START 1 +#define FF_EFFECT_QUEUE_STOP 2 +#define FF_EFFECT_QUEUE_UPDATE 3 +#define FF_EFFECT_PLAYING 4 + +#undef fixp_sin16 +#define fixp_sin16(v) (((v % 360) > 180) ?\ + -(fixp_sin32((v % 360) - 180) >> 16)\ + : fixp_sin32(v) >> 16) + +#define JIFFIES2MS(jiffies) ((jiffies) * 1000 / HZ) + +struct tmff2_effect_state { + struct ff_effect effect; + struct ff_effect old; + + unsigned long flags; + unsigned long count; + unsigned long start_time; +}; + +struct tmff2_device_entry { + struct hid_device *hdev; + struct input_dev *input_dev; + + /* pointer to array */ + struct tmff2_effect_state *states; + + struct delayed_work work; + + spinlock_t lock; + + /* fields relevant to each actual device (T300, T150...) */ + void *data; + unsigned long max_effects; + signed short supported_effects[FF_CNT]; + + /* obligatory callbacks */ + int (*play_effect)(void *data, struct tmff2_effect_state *state); + int (*upload_effect)(void *data, struct tmff2_effect_state *state); + int (*update_effect)(void *data, struct tmff2_effect_state *state); + int (*stop_effect)(void *data, struct tmff2_effect_state *state); + + int (*wheel_init)(void *data); + int (*wheel_destroy)(void *data); + + /* optional callbacks */ + int (*open)(void *data); + int (*close)(void *data); + int (*set_gain)(void *data, uint16_t gain); + int (*set_range)(void *data, uint16_t range); + int (*switch_mode)(void *data, uint16_t mode); + int (*set_autocenter)(void *data, uint16_t autocenter); + __u8 *(*wheel_fixup)(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize); +}; + +#endif /* _HID_TMFF2 */ diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index e522861..ee0e817 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -1,56 +1,373 @@ // SPDX-License-Identifier: GPL-2.0 -#include -#include "hid-tmt300rs.h" - -static int timer_msecs = DEFAULT_TIMER_PERIOD; -module_param(timer_msecs, int, 0660); -MODULE_PARM_DESC(timer_msecs, - "Timer resolution in msecs"); - -static int spring_level = 30; -module_param(spring_level, int, 0); -MODULE_PARM_DESC(spring_level, - "Level of spring force (0-100), as per Oversteer standards"); - -static int damper_level = 30; -module_param(damper_level, int, 0); -MODULE_PARM_DESC(damper_level, - "Level of damper force (0-100), as per Oversteer standards"); - -static int friction_level = 30; -module_param(friction_level, int, 0); -MODULE_PARM_DESC(friction_level, - "Level of friction force (0-100), as per Oversteer standards"); - -static struct t300rs_device_entry *t300rs_get_device(struct hid_device *hdev) -{ - struct t300rs_data *drv_data; - struct t300rs_device_entry *t300rs; - - spin_lock_irqsave(&lock, lock_flags); - drv_data = hid_get_drvdata(hdev); - if (!drv_data) { - hid_err(hdev, "private data not found\n"); - return NULL; - } +#include + +#define T300RS_MAX_EFFECTS 16 +#define T300RS_NORM_BUFFER_LENGTH 63 +#define T300RS_PS4_BUFFER_LENGTH 31 + +static const signed short t300rs_effects[] = { + FF_CONSTANT, + FF_RAMP, + FF_SPRING, + FF_DAMPER, + FF_FRICTION, + FF_INERTIA, + FF_PERIODIC, + FF_SINE, + FF_TRIANGLE, + FF_SQUARE, + FF_SAW_UP, + FF_SAW_DOWN, + FF_AUTOCENTER, + FF_GAIN, + -1 +}; - t300rs = drv_data->device_props; - if (!t300rs) { - hid_err(hdev, "device properties not found\n"); - return NULL; - } - spin_unlock_irqrestore(&lock, lock_flags); - return t300rs; -} +struct __packed t300rs_fw_response { + uint8_t unused1[2]; + uint8_t fw_version; + uint8_t unused2; +}; -static int t300rs_send_int(struct t300rs_device_entry *t300rs) + +struct __packed t300rs_packet_header { + uint8_t zero1; + uint8_t id; + uint8_t code; +}; + +struct __packed t300rs_setup_header { + uint8_t cmd; + uint8_t code; +}; + +struct __packed t300rs_packet_envelope { + uint16_t attack_length; + uint16_t attack_level; + uint16_t fade_length; + uint16_t fade_level; +}; + +struct __packed t300rs_packet_timing { + uint8_t start_marker; + uint16_t duration; + uint8_t zero1[2]; + uint16_t offset; + uint8_t zero2; + uint16_t end_marker; +}; + +struct usb_ctrlrequest t300rs_fw_request = { + .bRequestType = 0xc1, + .bRequest = 86, + .wValue = 0, + .wIndex = 0, + .wLength = 8 +}; + + +struct t300rs_device_entry { + struct hid_device *hdev; + struct input_dev *input_dev; + struct hid_report *report; + struct hid_field *ff_field; + struct usb_device *usbdev; + + int (*open)(struct input_dev *dev); + void (*close)(struct input_dev *dev); + + u8 buffer_length; + u8 *send_buffer; +}; + + +struct t300rs_data { + unsigned long quirks; + void *device_props; +}; + +static u8 t300rs_rdesc_nrm_fixed[] = { + 0x05, 0x01, /* Usage page (Generic Desktop) */ + 0x09, 0x04, /* Usage (Joystick) */ + 0xa1, 0x01, /* Collection (Application) */ + 0x09, 0x01, /* Usage (Pointer) */ + 0xa1, 0x00, /* Collection (Physical) */ + 0x85, 0x07, /* Report ID (7) */ + 0x09, 0x30, /* Usage (X) */ + 0x15, 0x00, /* Logical minimum (0) */ + 0x27, 0xff, 0xff, 0x00, 0x00, /* Logical maximum (65535) */ + 0x35, 0x00, /* Physical minimum (0) */ + 0x47, 0xff, 0xff, 0x00, 0x00, /* Physical maximum (65535) */ + 0x75, 0x10, /* Report size (16) */ + 0x95, 0x01, /* Report count (1) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x35, /* Usage (Rz) (Brake) */ + 0x26, 0xff, 0x03, /* Logical maximum (1023) */ + 0x46, 0xff, 0x03, /* Physical maximum (1023) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x32, /* Usage (Z) (Gas) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x31, /* Usage (Y) (Clutch) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x81, 0x03, /* Input (Variable, Absolute, Constant) */ + 0x05, 0x09, /* Usage page (Button) */ + 0x19, 0x01, /* Usage minimum (1) */ + 0x29, 0x0d, /* Usage maximum (13) */ + 0x25, 0x01, /* Logical maximum (1) */ + 0x45, 0x01, /* Physical maximum (1) */ + 0x75, 0x01, /* Report size (1) */ + 0x95, 0x0d, /* Report count (13) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x75, 0x0b, /* Report size (13) */ + 0x95, 0x01, /* Report count (1) */ + 0x81, 0x03, /* Usage (Variable, Absolute, Constant) */ + 0x05, 0x01, /* Usage page (Generic Desktop) */ + 0x09, 0x39, /* Usage (Hat Switch) */ + 0x25, 0x07, /* Logical maximum (7) */ + 0x46, 0x3b, 0x01, /* Physical maximum (315) */ + 0x55, 0x00, /* Unit exponent (0) */ + 0x65, 0x14, /* Unit (Eng Rot, Angular Pos) */ + 0x75, 0x04, /* Report size (4) */ + 0x81, 0x42, /* Input (Variable, Absolute, NullState) */ + 0x65, 0x00, /* Unit (None) */ + 0x81, 0x03, /* Input (Variable, Absolute, Constant) */ + 0x85, 0x60, /* Report ID (96), prev 10 */ + 0x06, 0x00, 0xff, /* Usage page (Vendor 1) */ + 0x09, 0x60, /* Usage (96), prev 10 */ + 0x75, 0x08, /* Report size (8) */ + 0x95, 0x3f, /* Report count (63) */ + 0x26, 0xff, 0x7f, /* Logical maximum (32767) */ + 0x15, 0x00, /* Logical minimum (0) */ + 0x46, 0xff, 0x7f, /* Physical maximum (32767) */ + 0x36, 0x00, 0x80, /* Physical minimum (-32768) */ + 0x91, 0x02, /* Output (Variable, Absolute) */ + 0x85, 0x02, /* Report ID (2) */ + 0x09, 0x02, /* Usage (2) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x14, /* Usage (20) */ + 0x85, 0x14, /* Report ID (20) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0xc0, /* End collection */ + 0xc0, /* End collection */ +}; + +static u8 t300rs_rdesc_adv_fixed[] = { + 0x05, 0x01, /* Usage page (Generic Desktop) */ + 0x09, 0x04, /* Usage (Joystick) */ + 0xa1, 0x01, /* Collection (Application) */ + 0x09, 0x01, /* Usage (Pointer) */ + 0xa1, 0x00, /* Collection (Physical) */ + 0x85, 0x07, /* Report ID (7) */ + 0x09, 0x30, /* Usage (X) */ + 0x15, 0x00, /* Logical minimum (0) */ + 0x27, 0xff, 0xff, 0x00, 0x00, /* Logical maximum (65535) */ + 0x35, 0x00, /* Physical minimum (0) */ + 0x47, 0xff, 0xff, 0x00, 0x00, /* Physical maximum (65535) */ + 0x75, 0x10, /* Report size (16) */ + 0x95, 0x01, /* Report count (1) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x31, /* Usage (Y) */ + 0x26, 0xff, 0x03, /* Logical maximum (1023) */ + 0x46, 0xff, 0x03, /* Physical maximum (1023) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x35, /* Usage (Rz) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x36, /* Usage (Slider) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x81, 0x03, /* Input (Variable, Absolute, Constant) ? */ + 0x05, 0x09, /* Usage page (Button) */ + 0x19, 0x01, /* Usage minimum (1) */ + 0x29, 0x19, /* Usage maximum (25) */ + 0x25, 0x01, /* Logical maximum (1) */ + 0x45, 0x01, /* Physical maximum (1) */ + 0x75, 0x01, /* Report size (1) */ + 0x95, 0x19, /* Report count (25) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x75, 0x03, /* Report size (3) */ + 0x95, 0x01, /* Report count (1) */ + 0x81, 0x03, /* Input (Variable, Absolute, Constant) */ + 0x05, 0x01, /* Usage page (Generic Desktop) */ + 0x09, 0x39, /* Usage (Hat Switch) */ + 0x25, 0x07, /* Logical maximum (7) */ + 0x46, 0x3b, 0x01, /* Physical maximum (315) */ + 0x55, 0x00, /* Unit exponent (0) */ + 0x65, 0x14, /* Unit (Eng Rot, Angular Pos) */ + 0x75, 0x04, /* Report size (4) */ + 0x81, 0x42, /* Input (Variable, Absolute, NullState) */ + 0x65, 0x00, /* Unit (None) */ + 0x85, 0x60, /* Report ID (96), prev 10 */ + 0x06, 0x00, 0xff, /* Usage page (Vendor 1) */ + 0x09, 0x60, /* Usage (96), prev 10 (why?) */ + 0x75, 0x08, /* Report size (8) */ + 0x95, 0x3f, /* Report count (63) */ + 0x26, 0xff, 0x00, /* Logical maximum (255) */ + 0x46, 0xff, 0x00, /* Physical maximum (255) */ + 0x91, 0x02, /* Output (Variable, Absolute) */ + 0x85, 0x02, /* Report ID (2) */ + 0x09, 0x02, /* Usage (Mouse) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x14, /* Usage (20) */ + 0x85, 0x14, /* Report ID (20) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0xc0, /* End collection */ + 0xc0, /* End collection */ +}; + +static u8 t300rs_rdesc_ps4_fixed[] = { + 0x05, 0x01, /* Usage page (Generic Desktop) */ + 0x09, 0x05, /* Usage (GamePad) */ + 0xa1, 0x01, /* Collection (Application) */ + 0x85, 0x01, /* Report ID (1) */ + 0x09, 0x00, /* Usage (U) (was X) */ + 0x09, 0x00, /* Usage (U) (was Y) */ + 0x09, 0x00, /* Usage (U) (was Z) */ + 0x09, 0x00, /* Usage (U) (was Rz)*/ + 0x15, 0x00, /* Logical minimum (0) */ + 0x26, 0xff, 0x00, /* Logical maximum (255) */ + 0x75, 0x08, /* Report size (8) */ + 0x95, 0x04, /* Report count (4) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x39, /* Usage (Hat Switch) */ + 0x15, 0x00, /* Logical minimum (0) */ + 0x25, 0x07, /* Logical maximum (7)*/ + 0x35, 0x00, /* Physical minimum (0) */ + 0x46, 0x3b, 0x01, /* Physical maximum (315) */ + 0x65, 0x14, /* Unit (Eng Rot, Angular Pos) */ + 0x75, 0x04, /* Report size (4) */ + 0x95, 0x01, /* Report count (1) */ + 0x81, 0x42, /* Input (Variable, Absolute, NullState) */ + 0x65, 0x00, /* Input (None) */ + 0x05, 0x09, /* Usage page (Button) */ + 0x19, 0x01, /* Usage minimum (1) */ + 0x29, 0x0e, /* Usage maximum (14) */ + 0x15, 0x00, /* Logical minimum (0) */ + 0x25, 0x01, /* Logical maximum (1) */ + 0x75, 0x01, /* Report size (1) */ + 0x95, 0x0e, /* Report size (14) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x06, 0x00, 0xff, /* Usage page (Vendor 1) */ + 0x09, 0x20, /* Usage (32) */ + 0x75, 0x06, /* Report size (6) */ + 0x95, 0x01, /* Report count (1) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x05, 0x01, /* Usage page (Generic Desktop) */ + 0x09, 0x00, /* Usage (U) (was Rx)*/ + 0x09, 0x00, /* Usage (U) (was Ry) */ + 0x15, 0x00, /* Logical minimum (0) */ + 0x26, 0xff, 0x00, /* Logical maximum (255) */ + 0x75, 0x08, /* Report size (8) */ + 0x95, 0x02, /* Report count (2) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x05, 0x01, /* Usage page (Vendor 1) */ + /* constant zero? */ + 0x09, 0x00, /* Usage (33) */ + 0x95, 0x21, /* Report count (33) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + /* wheel */ + 0x09, 0x30, /* Usage (X) */ + 0x15, 0x00, /* Logical minimum (0) */ + 0x27, 0xff, 0xff, 0x00, 0x00, /* Logical maximum (65535) */ + 0x35, 0x00, /* Physical minimum (0) */ + 0x47, 0xff, 0xff, 0x00, 0x00, /* Physical maximum (65535) */ + 0x75, 0x10, /* Report size (16) */ + 0x95, 0x01, /* Report count (1) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + /* gas */ + 0x09, 0x31, /* Usage (Y) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + /* brake */ + 0x09, 0x32, /* Usage (Z) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + /* clutch */ + 0x09, 0x35, /* Usage (Rz) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + /* stick shifter (check model no) */ + 0x05, 0x09, /* Usage page (Button) */ + 0x19, 0x0f, /* Usage minimum (15) */ + 0x29, 0x17, /* Usage maximum (23) */ + 0x15, 0x00, /* Logical minimum (1) */ + 0x25, 0x01, /* Logical maximum (1) */ + 0x75, 0x01, /* Report size (1) */ + 0x95, 0x08, /* Report count (8) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + /* no clue */ + 0x05, 0x01, /* Usage page (Generic Desktop) */ + 0x09, 0x00, /* Usage (U) */ + 0x75, 0x08, /* Report size (8) */ + 0x95, 0x0c, /* Report count (12) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + /* continue unmodified */ + 0x06, 0x00, 0xff, /* Usage page (Vendor defined 1) */ + 0x85, 0x60, /* Report ID (5) (change to 0x60?) */ + 0x09, 0x60, /* Usage (34) (change to 0x60?) */ + 0x95, 0x1f, /* Report count (31) () */ + 0x91, 0x02, /* Output (Variable, Absolute) */ + 0x85, 0x03, /* Report ID (3) */ + 0x0a, 0x21, 0x27, /* ??? */ + 0x95, 0x2f, /* Report count (47) */ + 0xb1, 0x02, /* Feature (Data, Var, Abs) */ + 0xc0, /* End collection */ + + /* From here on out no clue */ + 0x06, 0xf0, + 0xff, 0x09, + 0x40, 0xa1, + 0x01, 0x85, + 0xf0, 0x09, + 0x47, 0x95, + 0x3f, 0xb1, + 0x02, 0x85, + 0xf1, 0x09, + 0x48, 0x95, + 0x3f, 0xb1, + 0x02, 0x85, + 0xf2, 0x09, + 0x49, 0x95, + 0x0f, 0xb1, + 0x02, 0x85, + 0xf3, 0x0a, + 0x01, 0x47, + 0x95, 0x07, + 0xb1, 0x02, + 0xc0, +}; + +static u8 spring_values[] = { + 0xa6, 0x6a, 0xa6, 0x6a, 0xfe, + 0xff, 0xfe, 0xff, 0xfe, 0xff, + 0xfe, 0xff, 0xdf, 0x58, 0xa6, + 0x6a, 0x06 +}; + +static u8 damper_values[] = { + 0xfc, 0x7f, 0xfc, 0x7f, 0xfe, + 0xff, 0xfe, 0xff, 0xfe, 0xff, + 0xfe, 0xff, 0xfc, 0x7f, 0xfc, + 0x7f, 0x07 +}; + +static int t300rs_send_buf(struct t300rs_device_entry *t300rs, size_t len, u8 *send_buffer) { int i; - for (i = 0; i < t300rs->buffer_length; ++i) - t300rs->ff_field->value[i] = t300rs->send_buffer[i]; + /* check that send_buffer fits into our report */ + if (len > t300rs->buffer_length) + return -EINVAL; + + /* fill with actual data */ + for (i = 0; i < len; ++i) + t300rs->ff_field->value[i] = send_buffer[i]; + + /* fill the rest with zeroes */ + for (i = len; i < t300rs->buffer_length; ++i) + t300rs->ff_field->value[i] = 0; hid_hw_request(t300rs->hdev, t300rs->report, HID_REQ_SET_REPORT); + return 0; +} +static int t300rs_send_int(struct t300rs_device_entry *t300rs) +{ + t300rs_send_buf(t300rs, t300rs->buffer_length, t300rs->send_buffer); memset(t300rs->send_buffer, 0, t300rs->buffer_length); return 0; @@ -63,9 +380,9 @@ static void t300rs_fill_header(struct t300rs_packet_header *packet_header, packet_header->code = code; } -static int t300rs_play_effect(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state) +static int t300rs_play_effect(void *data, struct tmff2_effect_state *state) { + struct t300rs_device_entry *t300rs = data; struct __packed t300rs_packet_play { struct t300rs_packet_header header; uint8_t value; @@ -84,9 +401,9 @@ static int t300rs_play_effect(struct t300rs_device_entry *t300rs, return ret; } -static int t300rs_stop_effect(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state) +static int t300rs_stop_effect(void *data, struct tmff2_effect_state *state) { + struct t300rs_device_entry *t300rs = data; struct __packed t300rs_packet_stop { struct t300rs_packet_header header; uint8_t value; @@ -129,7 +446,7 @@ static void t300rs_fill_timing(struct t300rs_packet_timing *packet_timing, } static int t300rs_update_envelope(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state, + struct tmff2_effect_state *state, int16_t level, uint16_t duration, uint8_t id, @@ -206,7 +523,7 @@ error: } static int t300rs_update_duration(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state) + struct tmff2_effect_state *state) { struct ff_effect effect = state->effect; struct ff_effect old = state->old; @@ -239,7 +556,7 @@ error: } static int t300rs_update_constant(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state) + struct tmff2_effect_state *state) { struct ff_effect effect = state->effect; struct ff_effect old = state->old; @@ -292,7 +609,7 @@ error: } static int t300rs_update_ramp(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state) + struct tmff2_effect_state *state) { struct ff_effect effect = state->effect; struct ff_effect old = state->old; @@ -360,7 +677,7 @@ error: } static int t300rs_update_damper(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state) + struct tmff2_effect_state *state) { struct ff_effect effect = state->effect; struct ff_effect old = state->old; @@ -442,14 +759,14 @@ error: } static int t300rs_update_spring(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state) + struct tmff2_effect_state *state) { return t300rs_update_damper(t300rs, state); } static int t300rs_update_periodic(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state) + struct tmff2_effect_state *state) { struct ff_effect effect = state->effect; struct ff_effect old = state->old; @@ -559,7 +876,7 @@ error: } static int t300rs_upload_constant(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state) + struct tmff2_effect_state *state) { struct ff_effect effect = state->effect; struct ff_constant_effect constant = state->effect.u.constant; @@ -597,7 +914,7 @@ static int t300rs_upload_constant(struct t300rs_device_entry *t300rs, } static int t300rs_upload_ramp(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state) + struct tmff2_effect_state *state) { struct ff_effect effect = state->effect; struct ff_ramp_effect ramp = state->effect.u.ramp; @@ -650,7 +967,7 @@ static int t300rs_upload_ramp(struct t300rs_device_entry *t300rs, } static int t300rs_upload_spring(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state) + struct tmff2_effect_state *state) { struct ff_effect effect = state->effect; /* we only care about the first axis */ @@ -696,7 +1013,7 @@ static int t300rs_upload_spring(struct t300rs_device_entry *t300rs, } static int t300rs_upload_damper(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state) + struct tmff2_effect_state *state) { struct ff_effect effect = state->effect; @@ -747,7 +1064,7 @@ static int t300rs_upload_damper(struct t300rs_device_entry *t300rs, } static int t300rs_upload_periodic(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state) + struct tmff2_effect_state *state) { struct ff_effect effect = state->effect; struct ff_periodic_effect periodic = state->effect.u.periodic; @@ -805,9 +1122,9 @@ static int t300rs_upload_periodic(struct t300rs_device_entry *t300rs, return ret; } -static int t300rs_update_effect(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state) +static int t300rs_update_effect(void *data, struct tmff2_effect_state *state) { + struct t300rs_device_entry *t300rs = data; switch (state->effect.type) { case FF_CONSTANT: return t300rs_update_constant(t300rs, state); @@ -827,9 +1144,9 @@ static int t300rs_update_effect(struct t300rs_device_entry *t300rs, } } -static int t300rs_upload_effect(struct t300rs_device_entry *t300rs, - struct t300rs_effect_state *state) +static int t300rs_upload_effect(void *data, struct tmff2_effect_state *state) { + struct t300rs_device_entry *t300rs = data; switch (state->effect.type) { case FF_CONSTANT: return t300rs_upload_constant(t300rs, state); @@ -849,338 +1166,16 @@ static int t300rs_upload_effect(struct t300rs_device_entry *t300rs, } } -static void t300rs_work_handler(struct work_struct *w) -{ - struct delayed_work *dw = container_of(w, struct delayed_work, work); - struct t300rs_device_entry *t300rs = container_of(dw, struct t300rs_device_entry, work); - struct t300rs_effect_state *state; - int max_count = 0, effect_id; - unsigned long time_now; - - for (effect_id = 0; effect_id < T300RS_MAX_EFFECTS; ++effect_id) { - spin_lock(&t300rs->lock); - - time_now = JIFFIES2MS(jiffies); - state = &t300rs->states[effect_id]; - - if (test_bit(FF_EFFECT_PLAYING, &state->flags) && state->effect.replay.length) { - if ((time_now - state->start_time) >= state->effect.replay.length) { - __clear_bit(FF_EFFECT_PLAYING, &state->flags); - - /* lazy bum fix? */ - __clear_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags); - - if (state->count) - state->count--; - - if (state->count) - __set_bit(FF_EFFECT_QUEUE_START, &state->flags); - } - } - - if (test_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags)) { - __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); - /* if we're uploading an effect, it's bound to be the - * most up to date available */ - __clear_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags); - - if (t300rs_upload_effect(t300rs, state)) - hid_warn(t300rs->hdev, "failed uploading effect"); - } - - if (test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { - __clear_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags); - - if (t300rs_update_effect(t300rs, state)) - hid_warn(t300rs->hdev, "failed updating effect"); - } - - /* TODO TODO: add in effect data dump, macro or something? */ - - if (test_bit(FF_EFFECT_QUEUE_START, &state->flags)) { - __clear_bit(FF_EFFECT_QUEUE_START, &state->flags); - - if (t300rs_play_effect(t300rs, state)) - hid_warn(t300rs->hdev, "failed starting effect\n"); - - __set_bit(FF_EFFECT_PLAYING, &state->flags); - } - - if (test_bit(FF_EFFECT_QUEUE_STOP, &state->flags)) { - __clear_bit(FF_EFFECT_QUEUE_STOP, &state->flags); - - if (t300rs_stop_effect(t300rs, state)) - hid_warn(t300rs->hdev, "failed stopping effect\n"); - - __clear_bit(FF_EFFECT_PLAYING, &state->flags); - } - - if (state->count > max_count) - max_count = state->count; - - spin_unlock(&t300rs->lock); - } - - if (max_count) - schedule_delayed_work(&t300rs->work, msecs_to_jiffies(timer_msecs)); -} - -static int t300rs_upload(struct input_dev *dev, - struct ff_effect *effect, struct ff_effect *old) -{ - struct hid_device *hdev = input_get_drvdata(dev); - struct t300rs_device_entry *t300rs; - struct t300rs_effect_state *state; - - t300rs = t300rs_get_device(hdev); - if (!t300rs) { - hid_err(hdev, "could not get device\n"); - return -1; - } - - if (effect->type == FF_PERIODIC && effect->u.periodic.period == 0) - return -EINVAL; - - state = &t300rs->states[effect->id]; - - spin_lock(&t300rs->lock); - - state->effect = *effect; - - if (old) { - if (test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) - state->old = *old; - - __set_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags); - } else { - __set_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); - } - - spin_unlock(&t300rs->lock); - - return 0; -} - -static int t300rs_play(struct input_dev *dev, int effect_id, int value) +static int t300rs_switch_mode(void *data, uint16_t mode) { - struct hid_device *hdev = input_get_drvdata(dev); - struct t300rs_device_entry *t300rs; - struct t300rs_effect_state *state; - - t300rs = t300rs_get_device(hdev); - if (!t300rs) { - hid_err(hdev, "could not get device\n"); - return -1; - } - - state = &t300rs->states[effect_id]; + struct t300rs_device_entry *t300rs = data; + if (!t300rs) + return -ENODEV; - if (&state->effect == 0) + if(alt_mode == mode) /* already in specified mode */ return 0; - spin_lock(&t300rs->lock); - - if (value > 0) { - state->count = value; - state->start_time = JIFFIES2MS(jiffies); - __set_bit(FF_EFFECT_QUEUE_START, &state->flags); - - if (test_bit(FF_EFFECT_QUEUE_STOP, &state->flags)) - __clear_bit(FF_EFFECT_QUEUE_STOP, &state->flags); - - } else { - __set_bit(FF_EFFECT_QUEUE_STOP, &state->flags); - } - - spin_unlock(&t300rs->lock); - - if (!delayed_work_pending(&t300rs->work)) - schedule_delayed_work(&t300rs->work, 0); - - return 0; -} - -static ssize_t spring_level_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct hid_device *hdev = to_hid_device(dev); - unsigned int value; - int ret; - - ret = kstrtouint(buf, 0, &value); - if (ret) { - hid_err(hdev, "kstrtouint failed at spring_level_store: %i", ret); - return ret; - } - - if (value > 100) - value = 100; - - spring_level = value; - - return count; -} -static ssize_t spring_level_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - size_t count; - - count = scnprintf(buf, PAGE_SIZE, "%u\n", spring_level); - - return count; -} - -static DEVICE_ATTR_RW(spring_level); - -static ssize_t damper_level_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct hid_device *hdev = to_hid_device(dev); - unsigned int value; - int ret; - - ret = kstrtouint(buf, 0, &value); - if (ret) { - hid_err(hdev, "kstrtouint failed at damper_level_store: %i", ret); - return ret; - } - - if (value > 100) - value = 100; - - damper_level = value; - - return count; -} - -static ssize_t damper_level_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - size_t count; - - count = scnprintf(buf, PAGE_SIZE, "%u\n", damper_level); - - return count; -} - -static DEVICE_ATTR_RW(damper_level); - -static ssize_t friction_level_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct hid_device *hdev = to_hid_device(dev); - unsigned int value; - int ret; - - ret = kstrtouint(buf, 0, &value); - if (ret) { - hid_err(hdev, "kstrtouint failed at friction_level_store: %i", ret); - return ret; - } - - if (value > 100) - value = 100; - - friction_level = value; - - return count; -} -static ssize_t friction_level_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - size_t count; - - count = scnprintf(buf, PAGE_SIZE, "%u\n", friction_level); - - return count; -} - -static DEVICE_ATTR_RW(friction_level); - -static ssize_t range_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct hid_device *hdev = to_hid_device(dev); - struct t300rs_device_entry *t300rs; - struct __packed t300rs_packet_range { - struct t300rs_setup_header header; - uint16_t range; - } *packet_range; - - unsigned int range; - int ret; - - ret = kstrtouint(buf, 0, &range); - if (ret) { - hid_err(hdev, "kstrtouint failed at range_store: %i", ret); - return ret; - } - - t300rs = t300rs_get_device(hdev); - if (!t300rs) { - hid_err(hdev, "could not get device\n"); - return -1; - } - - packet_range = (struct t300rs_packet_range *)t300rs->send_buffer; - - if (range < 40) - range = 40; - - if (range > 1080) - range = 1080; - - range *= 0x3c; - - - packet_range->header.cmd = 0x08; - packet_range->header.code = 0x11; - - packet_range->range = cpu_to_le16(range); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(hdev, "failed sending interrupts\n"); - return -1; - } - - t300rs->range = range / 0x3c; - - return count; -} - -static ssize_t range_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct hid_device *hdev = to_hid_device(dev); - struct t300rs_device_entry *t300rs; - size_t count = 0; - - t300rs = t300rs_get_device(hdev); - if (!t300rs) { - hid_err(hdev, "could not get device\n"); - return -1; - } - - count = scnprintf(buf, PAGE_SIZE, "%u\n", t300rs->range); - return count; -} - -static DEVICE_ATTR_RW(range); - -static ssize_t adv_mode_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct hid_device *hdev = to_hid_device(dev); - struct t300rs_device_entry *t300rs; - - t300rs = t300rs_get_device(hdev); - if (!t300rs) { - hid_err(hdev, "could not get device\n"); - return -1; - } - - if(t300rs->adv_mode) + if (mode == 0) usb_control_msg(t300rs->usbdev, usb_sndctrlpipe(t300rs->usbdev, 0), 83, 0x41, 5, 0, 0, 0, @@ -1193,41 +1188,20 @@ static ssize_t adv_mode_store(struct device *dev, USB_CTRL_SET_TIMEOUT ); - return count; -} - -static ssize_t adv_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct hid_device *hdev = to_hid_device(dev); - struct t300rs_device_entry *t300rs; - - t300rs = t300rs_get_device(hdev); - if (!t300rs) { - hid_err(hdev, "could not get device\n"); - return -1; - } - - return scnprintf(buf, PAGE_SIZE, "%s\n", t300rs->adv_mode ? "Yes" : "No"); + return 0; } -static DEVICE_ATTR_RW(adv_mode); -static void t300rs_set_autocenter(struct input_dev *dev, uint16_t value) +static int t300rs_set_autocenter(void *data, uint16_t value) { - struct hid_device *hdev = input_get_drvdata(dev); - struct t300rs_device_entry *t300rs; + struct t300rs_device_entry *t300rs = data; struct __packed t300rs_packet_autocenter { struct t300rs_setup_header header; uint16_t value; } *autocenter_packet; - int ret; - t300rs = t300rs_get_device(hdev); - if (!t300rs) { - hid_err(hdev, "could not get device\n"); - return; - } + if (!t300rs) + return -ENODEV; autocenter_packet = (struct t300rs_packet_autocenter *)t300rs->send_buffer; @@ -1235,10 +1209,9 @@ static void t300rs_set_autocenter(struct input_dev *dev, uint16_t value) autocenter_packet->header.code = 0x04; autocenter_packet->value = cpu_to_le16(0x01); - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(hdev, "failed setting autocenter"); - return; + if ((ret = t300rs_send_int(t300rs))) { + hid_err(t300rs->hdev, "failed setting autocenter"); + return ret; } autocenter_packet->header.cmd = 0x08; @@ -1246,194 +1219,216 @@ static void t300rs_set_autocenter(struct input_dev *dev, uint16_t value) autocenter_packet->value = cpu_to_le16(value); - ret = t300rs_send_int(t300rs); - if (ret) - hid_err(hdev, "failed setting autocenter"); + if ((ret = t300rs_send_int(t300rs))) + hid_err(t300rs->hdev, "failed setting autocenter"); + + return ret; } -static void t300rs_set_gain(struct input_dev *dev, uint16_t gain) +static int t300rs_set_gain(void *data, uint16_t gain) { - struct hid_device *hdev = input_get_drvdata(dev); - struct t300rs_device_entry *t300rs; + struct t300rs_device_entry *t300rs = data; struct __packed t300rs_packet_gain { struct t300rs_setup_header header; } *gain_packet; - int ret; - t300rs = t300rs_get_device(hdev); - if (!t300rs) { - hid_err(hdev, "could not get device\n"); - return; - } + if (!t300rs) + return -ENODEV; gain_packet = (struct t300rs_packet_gain *)t300rs->send_buffer; - gain_packet->header.cmd = 0x02; gain_packet->header.code = (gain >> 8) & 0xff; - ret = t300rs_send_int(t300rs); - if (ret) - hid_err(hdev, "failed setting gain: %i\n", ret); + if ((ret = t300rs_send_int(t300rs))) + hid_err(t300rs->hdev, "failed setting gain: %i\n", ret); + + return ret; } -static void t300rs_destroy(struct ff_device *ff) +static int t300rs_set_range(void *data, uint16_t value) { - // maybe not necessary? + struct t300rs_device_entry *t300rs = data; + /* it's important that we don't use t300rs->send_buffer, as range can be + * set from outside of the FFB environment, and we don't want to + * accidentally overwrite any data. */ + u8 *send_buffer = kzalloc(t300rs->buffer_length, GFP_KERNEL); + uint16_t scaled_value; + int ret; + + if (value < 40) { + hid_info(t300rs->hdev, "value %i too small, clamping to 40\n", value); + value = 40; + } + + if (value > 1080) { + hid_info(t300rs->hdev, "value %i too large, clamping to 1080\n", value); + value = 1080; + } + + if (!send_buffer) { + ret = -EINVAL; + hid_err(t300rs->hdev, "could not allocate send_buffer\n"); + goto err; + } + + scaled_value = value * 0x3c; + send_buffer[0] = 0x08; + send_buffer[1] = 0x11; + send_buffer[2] = scaled_value & 0xff; + send_buffer[3] = scaled_value >> 8; + + if ((ret = t300rs_send_buf(t300rs, t300rs->buffer_length, send_buffer))) + hid_warn(t300rs->hdev, "failed setting range\n"); + + /* since everythin went OK, update the current range */ + range = value; +err: + kfree(send_buffer); + return ret; } -static int t300rs_open(struct input_dev *dev) +static int t300rs_open(void *data) { - struct t300rs_device_entry *t300rs; - struct hid_device *hdev = input_get_drvdata(dev); + struct t300rs_device_entry *t300rs = data; struct __packed t300rs_packet_open { struct t300rs_setup_header header; } *open_packet; - int ret; - - t300rs = t300rs_get_device(hdev); - if (!t300rs) { - hid_err(hdev, "could not get device\n"); - return -1; - } + if (!t300rs) + return -ENODEV; open_packet = (struct t300rs_packet_open *)t300rs->send_buffer; - open_packet->header.cmd = 0x01; open_packet->header.code = 0x05; - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(hdev, "failed sending interrupts\n"); - goto err; - } + if (t300rs_send_int(t300rs)) + hid_warn(t300rs->hdev, "failed sending open command\n"); -err: - return t300rs->open(dev); + return t300rs->open(t300rs->input_dev); } -static void t300rs_close(struct input_dev *dev) +static int t300rs_close(void *data) { - struct t300rs_device_entry *t300rs; - struct hid_device *hdev = input_get_drvdata(dev); + struct t300rs_device_entry *t300rs = data; struct t300rs_packet_close { struct t300rs_setup_header header; } *close_packet; - int ret; - t300rs = t300rs_get_device(hdev); - if (!t300rs) { - hid_err(hdev, "could not get device\n"); - return; - } + if (!t300rs) + return -ENODEV; close_packet = (struct t300rs_packet_close *)t300rs->send_buffer; - close_packet->header.cmd = 0x01; - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(hdev, "failed sending interrupts\n"); - goto err; - } -err: - t300rs->close(dev); + if ((ret = t300rs_send_int(t300rs))) + hid_warn(t300rs->hdev, "failed sending close command\n"); + + t300rs->close(t300rs->input_dev); + return ret; } static int t300rs_create_files(struct hid_device *hdev) { int ret; - - ret = device_create_file(&hdev->dev, &dev_attr_adv_mode); - if (ret) { - hid_warn(hdev, "unable to create sysfs interface for adv_mode\n"); - goto attr_adv_err; + if ((ret = device_create_file(&hdev->dev, &dev_attr_alt_mode))) { + hid_err(hdev, "unable to create sysfs interface for alt_mode\n"); + goto alt_err; } - ret = device_create_file(&hdev->dev, &dev_attr_range); - if (ret) { + if ((ret = device_create_file(&hdev->dev, &dev_attr_range))) { hid_warn(hdev, "unable to create sysfs interface for range\n"); - goto attr_range_err; + goto range_err; } - ret = device_create_file(&hdev->dev, &dev_attr_spring_level); - if (ret) { + if ((ret = device_create_file(&hdev->dev, &dev_attr_spring_level))) { hid_warn(hdev, "unable to create sysfs interface for spring_level\n"); - goto attr_spring_err; + goto spring_err; } - ret = device_create_file(&hdev->dev, &dev_attr_damper_level); - if (ret) { + if ((ret = device_create_file(&hdev->dev, &dev_attr_damper_level))) { hid_warn(hdev, "unable to create sysfs interface for damper_level\n"); - goto attr_damper_err; + goto damper_err; } - ret = device_create_file(&hdev->dev, &dev_attr_friction_level); - if (ret) { + if ((ret = device_create_file(&hdev->dev, &dev_attr_friction_level))) { hid_warn(hdev, "unable to create sysfs interface for friction_level\n"); - goto attr_friction_err; + goto friction_err; } return ret; - // if the creation of dev_attr_friction fails, we don't need to remove it - // device_remove_file(&hdev->dev, &dev_attr_friction_level); -attr_friction_err: + /* if the creation of dev_attr_friction fails, we don't need to remove it */ + /* device_remove_file(&hdev->dev, &dev_attr_friction_level); */ +friction_err: device_remove_file(&hdev->dev, &dev_attr_damper_level); -attr_damper_err: +damper_err: device_remove_file(&hdev->dev, &dev_attr_spring_level); -attr_spring_err: +spring_err: device_remove_file(&hdev->dev, &dev_attr_range); -attr_range_err: - device_remove_file(&hdev->dev, &dev_attr_adv_mode); -attr_adv_err: +range_err: + device_remove_file(&hdev->dev, &dev_attr_alt_mode); +alt_err: return ret; } -static int t300rs_init(struct hid_device *hdev, const signed short *ff_bits) +static int t300rs_check_firmware(struct t300rs_device_entry *t300rs) { - struct t300rs_device_entry *t300rs; - struct t300rs_data *drv_data; - struct list_head *report_list; - struct hid_input *hidinput = list_entry(hdev->inputs.next, - struct hid_input, list); - struct input_dev *input_dev = hidinput->input; - struct device *dev = &hdev->dev; - struct usb_interface *usbif = to_usb_interface(dev->parent); - struct usb_device *usbdev = interface_to_usbdev(usbif); - struct ff_device *ff; - char range[10] = "900"; // max - int i, ret; - - drv_data = hid_get_drvdata(hdev); - if (!drv_data) { - hid_err(hdev, "private driver data not allocated\n"); - ret = -ENOMEM; - goto drvdata_err; + int ret; + struct t300rs_fw_response *fw_response = + kzalloc(sizeof(struct t300rs_fw_response), GFP_KERNEL); + + if (!fw_response) { + hid_err(t300rs->hdev, "could not allocate fw_response\n"); + return -ENOMEM; } - t300rs = kzalloc(sizeof(struct t300rs_device_entry), GFP_KERNEL); - if (!t300rs) { - ret = -ENOMEM; - goto t300rs_err; + /* Fetch firmware version */ + ret = usb_control_msg(t300rs->usbdev, + usb_rcvctrlpipe(t300rs->usbdev, 0), + t300rs_fw_request.bRequest, + t300rs_fw_request.bRequestType, + t300rs_fw_request.wValue, + t300rs_fw_request.wIndex, + fw_response, + t300rs_fw_request.wLength, + USB_CTRL_SET_TIMEOUT + ); + + if (ret < 0) { + hid_err(t300rs->hdev, "could not fetch firmware version\n"); + goto out; } - t300rs->input_dev = input_dev; - t300rs->hdev = hdev; - t300rs->usbdev = usbdev; - t300rs->usbif = usbif; + /* Educated guess */ + if (fw_response->fw_version < 31 && ret >= 0) { + hid_err(t300rs->hdev, + "firmware version %i is too old, please update.\n", + fw_response->fw_version + ); - t300rs->states = kzalloc( - sizeof(struct t300rs_effect_state) * T300RS_MAX_EFFECTS, GFP_KERNEL); + hid_info(t300rs->hdev, "note: this has to be done through Windows.\n"); - if (!t300rs->states) { - ret = -ENOMEM; - goto states_err; + ret = -EINVAL; + goto out; } - if(hdev->product == 0xb66d) + /* everything OK */ + ret = 0; + +out: + kfree(fw_response); + return ret; +} + +static int t300rs_wheel_init(void *data) +{ + struct t300rs_device_entry *t300rs = data; + struct list_head *report_list; + int ret; + + if(t300rs->hdev->product == 0xb66d) t300rs->buffer_length = T300RS_PS4_BUFFER_LENGTH; else t300rs->buffer_length = T300RS_NORM_BUFFER_LENGTH; @@ -1444,219 +1439,125 @@ static int t300rs_init(struct hid_device *hdev, const signed short *ff_bits) goto send_err; } - t300rs->firmware_response = kzalloc(sizeof(struct t300rs_firmware_response), GFP_KERNEL); - if (!t300rs->firmware_response) { - ret = -ENOMEM; + if ((ret = t300rs_check_firmware(t300rs))) goto firmware_err; - } - // Check firmware version - ret = usb_control_msg(t300rs->usbdev, - usb_rcvctrlpipe(t300rs->usbdev, 0), - t300rs_firmware_request.bRequest, - t300rs_firmware_request.bRequestType, - t300rs_firmware_request.wValue, - t300rs_firmware_request.wIndex, - t300rs->firmware_response, - t300rs_firmware_request.wLength, - USB_CTRL_SET_TIMEOUT - ); - - // Educated guess - if (t300rs->firmware_response->firmware_version < 31 && ret >= 0) { - hid_err(t300rs->hdev, - "firmware version %i is too old, please update.", - t300rs->firmware_response->firmware_version - ); + report_list = &t300rs->hdev->report_enum[HID_OUTPUT_REPORT].report_list; - hid_info(t300rs->hdev, "note: this has to be done through Windows."); - - ret = -EINVAL; - goto version_err; - } - - INIT_DELAYED_WORK(&t300rs->work, t300rs_work_handler); - - spin_lock_init(&t300rs->lock); - - drv_data->device_props = t300rs; - - report_list = &hdev->report_enum[HID_OUTPUT_REPORT].report_list; - - // because we set the rdesc, we know exactly which report and field to use + /* because we set the rdesc, we know exactly which report and field to use */ t300rs->report = list_entry(report_list->next, struct hid_report, list); t300rs->ff_field = t300rs->report->field[0]; - // set ff capabilities - for (i = 0; ff_bits[i] >= 0; ++i) - __set_bit(ff_bits[i], input_dev->ffbit); - - ret = input_ff_create(input_dev, T300RS_MAX_EFFECTS); - if (ret) { - hid_err(hdev, "could not create input_ff\n"); - goto input_ff_err; - } + t300rs->open = t300rs->input_dev->open; + t300rs->close = t300rs->input_dev->close; - ff = input_dev->ff; - ff->upload = t300rs_upload; - ff->playback = t300rs_play; - ff->set_gain = t300rs_set_gain; - ff->set_autocenter = t300rs_set_autocenter; - ff->destroy = t300rs_destroy; - - t300rs->open = input_dev->open; - t300rs->close = input_dev->close; - - input_dev->open = t300rs_open; - input_dev->close = t300rs_close; - - ret = t300rs_create_files(hdev); - if (ret) { - // this might not be a catastrophic issue, but it could affect - // programs such as oversteer, best play it safe - hid_err(hdev, "could not create sysfs files\n"); + if ((ret = t300rs_create_files(t300rs->hdev))) { + /* probably not a massive issue, but could affect programs like + * Oversteer, best play it safe */ + hid_err(t300rs->hdev, "could not create sysfs files\n"); goto sysfs_err; } + t300rs_set_range(t300rs, range); + t300rs_set_gain(t300rs, 0xffff); - range_store(dev, &dev_attr_range, range, 10); - t300rs_set_gain(input_dev, 0xffff); - - t300rs->adv_mode = (hdev->product == 0xb66f); + /* TODO: PS4 advanced mode? */ + alt_mode = (t300rs->hdev->product == 0xb66f); - hid_info(hdev, "force feedback for T300RS\n"); + hid_info(t300rs->hdev, "force feedback for T300RS\n"); return 0; sysfs_err: - kfree(t300rs->firmware_response); - -input_ff_err: -version_err: firmware_err: kfree(t300rs->send_buffer); send_err: - kfree(t300rs->states); - -states_err: - kfree(t300rs); - -t300rs_err: - kfree(drv_data); - -drvdata_err: - hid_err(hdev, "failed creating force feedback device\n"); - - return ret; - -} - -static int t300rs_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - struct t300rs_data *drv_data; - - spin_lock_init(&lock); - - drv_data = kzalloc(sizeof(struct t300rs_data), GFP_KERNEL); - if (!drv_data) { - ret = -ENOMEM; - goto err; - } - - drv_data->quirks = id->driver_data; - hid_set_drvdata(hdev, (void *)drv_data); - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err; - } - - ret = t300rs_init(hdev, (void *)id->driver_data); - if (ret) { - hid_err(hdev, "t300rs_init failed\n"); - goto err; - } - -err: + hid_err(t300rs->hdev, "failed creating force feedback device\n"); return ret; } -static void t300rs_remove(struct hid_device *hdev) +static int t300rs_wheel_destroy(void *data) { - struct t300rs_device_entry *t300rs; - struct t300rs_data *drv_data; - - drv_data = hid_get_drvdata(hdev); - t300rs = t300rs_get_device(hdev); - if (!t300rs) { - hid_err(hdev, "could not get device\n"); - return; - } - - cancel_delayed_work_sync(&t300rs->work); + struct t300rs_device_entry *t300rs = data; + if (!t300rs) + return -ENODEV; + + /* apparently should be safe to call these even without the files + * existing */ + device_remove_file(&t300rs->hdev->dev, &dev_attr_range); + device_remove_file(&t300rs->hdev->dev, &dev_attr_alt_mode); + device_remove_file(&t300rs->hdev->dev, &dev_attr_spring_level); + device_remove_file(&t300rs->hdev->dev, &dev_attr_damper_level); + device_remove_file(&t300rs->hdev->dev, &dev_attr_friction_level); - device_remove_file(&hdev->dev, &dev_attr_range); - device_remove_file(&hdev->dev, &dev_attr_adv_mode); - device_remove_file(&hdev->dev, &dev_attr_spring_level); - device_remove_file(&hdev->dev, &dev_attr_damper_level); - device_remove_file(&hdev->dev, &dev_attr_friction_level); - - hid_hw_stop(hdev); - - drv_data->device_props = NULL; - kfree(t300rs->states); kfree(t300rs->send_buffer); - kfree(t300rs->firmware_response); kfree(t300rs); - kfree(drv_data); + return 0; } -static __u8 *t300rs_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static __u8 *t300rs_wheel_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { - if(hdev->product == 0xb66e) { - /* PS3 normal mode */ + switch (hdev->product) { + case 0xb66e: + /* normal PS3 mode */ rdesc = t300rs_rdesc_nrm_fixed; *rsize = sizeof(t300rs_rdesc_nrm_fixed); - } else if (hdev->product == 0xb66d){ + break; + + case 0xb66d: /* PS4 normal mode */ rdesc = t300rs_rdesc_ps4_fixed; *rsize = sizeof(t300rs_rdesc_ps4_fixed); - } else if (hdev->product == 0xb66f){ + break; + + case 0xb66f: /* PS3 advanced mode */ rdesc = t300rs_rdesc_adv_fixed; *rsize = sizeof(t300rs_rdesc_adv_fixed); + break; } return rdesc; } -static const struct hid_device_id t300rs_devices[] = { - {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb66e), - .driver_data = (unsigned long)t300rs_ff_effects}, - {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb66f), - .driver_data = (unsigned long)t300rs_ff_effects}, - {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb66d), - .driver_data = (unsigned long)t300rs_ff_effects}, - {} -}; -MODULE_DEVICE_TABLE(hid, t300rs_devices); - -static struct hid_driver t300rs_driver = { - .name = "t300rs", - .id_table = t300rs_devices, - .probe = t300rs_probe, - .remove = t300rs_remove, - .report_fixup = t300rs_report_fixup, -}; -module_hid_driver(t300rs_driver); +static int t300rs_populate_api(struct tmff2_device_entry *tmff2) +{ + struct t300rs_device_entry *t300rs = + kzalloc(sizeof(struct t300rs_device_entry), GFP_KERNEL); + + /* we must populate wheel_destroy at the least, even if t300rs didn't + * get allocated */ + tmff2->data = t300rs; + tmff2->max_effects = T300RS_MAX_EFFECTS; + + /* copy over supported effects */ + memcpy(tmff2->supported_effects, t300rs_effects, ARRAY_SIZE(t300rs_effects)); + + /* set callbacks */ + tmff2->play_effect = t300rs_play_effect; + tmff2->upload_effect = t300rs_upload_effect; + tmff2->update_effect = t300rs_update_effect; + tmff2->stop_effect = t300rs_stop_effect; + + tmff2->wheel_init = t300rs_wheel_init; + tmff2->wheel_destroy = t300rs_wheel_destroy; + + tmff2->open = t300rs_open; + tmff2->close = t300rs_close; + tmff2->set_gain = t300rs_set_gain; + tmff2->set_range = t300rs_set_range; + tmff2->switch_mode = t300rs_switch_mode; + tmff2->set_autocenter = t300rs_set_autocenter; + tmff2->wheel_fixup = t300rs_wheel_fixup; + + if (!t300rs) + return -ENOMEM; + + /* copy over stuff we need */ + t300rs->hdev = tmff2->hdev; + t300rs->input_dev = tmff2->input_dev; + t300rs->usbdev = to_usb_device(&tmff2->hdev->dev); -MODULE_LICENSE("GPL"); + return 0; +} diff --git a/hid-tmt300rs.h b/hid-tmt300rs.h deleted file mode 100644 index 4b565ce..0000000 --- a/hid-tmt300rs.h +++ /dev/null @@ -1,403 +0,0 @@ -/* SPDX-License-Identifier: GLP-2.0 */ -#include -#include -#include -#include -#include -#include -#include - -//#include "hid-ids.h" - -#define USB_VENDOR_ID_THRUSTMASTER 0x044f - -#define T300RS_MAX_EFFECTS 16 -#define T300RS_NORM_BUFFER_LENGTH 63 -#define T300RS_PS4_BUFFER_LENGTH 31 - -/* the wheel seems to only be capable of processing a certain number of - * interrupts per second, and if this value is too low the kernel urb buffer(or - * some buffer at least) fills up. Optimally I would figure out some way to - * space out the interrupts so that they all leave at regular intervals, but - * for now this is good enough, go slow enough that everything works. - */ -#define DEFAULT_TIMER_PERIOD 8 - -#define FF_EFFECT_QUEUE_UPLOAD 0 -#define FF_EFFECT_QUEUE_START 1 -#define FF_EFFECT_QUEUE_STOP 2 -#define FF_EFFECT_PLAYING 3 -#define FF_EFFECT_QUEUE_UPDATE 4 - -#undef fixp_sin16 -#define fixp_sin16(v) (((v % 360) > 180)? -(fixp_sin32((v % 360) - 180) >> 16) : fixp_sin32(v) >> 16) -#define JIFFIES2MS(jiffies) ((jiffies) * 1000 / HZ) - -spinlock_t lock; -unsigned long lock_flags; - -spinlock_t data_lock; -unsigned long data_flags; - -static const signed short t300rs_ff_effects[] = { - FF_CONSTANT, - FF_RAMP, - FF_SPRING, - FF_DAMPER, - FF_FRICTION, - FF_INERTIA, - FF_PERIODIC, - FF_SINE, - FF_TRIANGLE, - FF_SQUARE, - FF_SAW_UP, - FF_SAW_DOWN, - FF_AUTOCENTER, - FF_GAIN, - -1 -}; - -struct t300rs_effect_state { - struct ff_effect effect; - struct ff_effect old; - bool old_set; - unsigned long flags; - unsigned long start_time; - unsigned long count; -}; - -struct __packed t300rs_firmware_response { - uint8_t unused1[2]; - uint8_t firmware_version; - uint8_t unused2; -}; - - -struct __packed t300rs_packet_header { - uint8_t zero1; - uint8_t id; - uint8_t code; -}; - -struct __packed t300rs_setup_header { - uint8_t cmd; - uint8_t code; -}; - -struct __packed t300rs_packet_envelope { - uint16_t attack_length; - uint16_t attack_level; - uint16_t fade_length; - uint16_t fade_level; -}; - -struct __packed t300rs_packet_timing { - uint8_t start_marker; - uint16_t duration; - uint8_t zero1[2]; - uint16_t offset; - uint8_t zero2; - uint16_t end_marker; -}; - -struct usb_ctrlrequest t300rs_firmware_request = { - .bRequestType = 0xc1, - .bRequest = 86, - .wValue = 0, - .wIndex = 0, - .wLength = 8 -}; - - -struct t300rs_device_entry { - struct hid_device *hdev; - struct input_dev *input_dev; - struct hid_report *report; - struct hid_field *ff_field; - struct usb_device *usbdev; - struct usb_interface *usbif; - struct t300rs_effect_state *states; - struct t300rs_firmware_response *firmware_response; - - struct delayed_work work; - - int (*open)(struct input_dev *dev); - void (*close)(struct input_dev *dev); - - spinlock_t lock; - unsigned long lock_flags; - - u8 buffer_length; - u8 *send_buffer; - - u16 range; - u8 effects_used; - - u8 adv_mode; -}; - - -struct t300rs_data { - unsigned long quirks; - void *device_props; -}; - -static u8 t300rs_rdesc_nrm_fixed[] = { - 0x05, 0x01, /* Usage page (Generic Desktop) */ - 0x09, 0x04, /* Usage (Joystick) */ - 0xa1, 0x01, /* Collection (Application) */ - 0x09, 0x01, /* Usage (Pointer) */ - 0xa1, 0x00, /* Collection (Physical) */ - 0x85, 0x07, /* Report ID (7) */ - 0x09, 0x30, /* Usage (X) */ - 0x15, 0x00, /* Logical minimum (0) */ - 0x27, 0xff, 0xff, 0x00, 0x00, /* Logical maximum (65535) */ - 0x35, 0x00, /* Physical minimum (0) */ - 0x47, 0xff, 0xff, 0x00, 0x00, /* Physical maximum (65535) */ - 0x75, 0x10, /* Report size (16) */ - 0x95, 0x01, /* Report count (1) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x35, /* Usage (Rz) (Brake) */ - 0x26, 0xff, 0x03, /* Logical maximum (1023) */ - 0x46, 0xff, 0x03, /* Physical maximum (1023) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x32, /* Usage (Z) (Gas) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x31, /* Usage (Y) (Clutch) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x81, 0x03, /* Input (Variable, Absolute, Constant) */ - 0x05, 0x09, /* Usage page (Button) */ - 0x19, 0x01, /* Usage minimum (1) */ - 0x29, 0x0d, /* Usage maximum (13) */ - 0x25, 0x01, /* Logical maximum (1) */ - 0x45, 0x01, /* Physical maximum (1) */ - 0x75, 0x01, /* Report size (1) */ - 0x95, 0x0d, /* Report count (13) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x75, 0x0b, /* Report size (13) */ - 0x95, 0x01, /* Report count (1) */ - 0x81, 0x03, /* Usage (Variable, Absolute, Constant) */ - 0x05, 0x01, /* Usage page (Generic Desktop) */ - 0x09, 0x39, /* Usage (Hat Switch) */ - 0x25, 0x07, /* Logical maximum (7) */ - 0x46, 0x3b, 0x01, /* Physical maximum (315) */ - 0x55, 0x00, /* Unit exponent (0) */ - 0x65, 0x14, /* Unit (Eng Rot, Angular Pos) */ - 0x75, 0x04, /* Report size (4) */ - 0x81, 0x42, /* Input (Variable, Absolute, NullState) */ - 0x65, 0x00, /* Unit (None) */ - 0x81, 0x03, /* Input (Variable, Absolute, Constant) */ - 0x85, 0x60, /* Report ID (96), prev 10 */ - 0x06, 0x00, 0xff, /* Usage page (Vendor 1) */ - 0x09, 0x60, /* Usage (96), prev 10 */ - 0x75, 0x08, /* Report size (8) */ - 0x95, 0x3f, /* Report count (63) */ - 0x26, 0xff, 0x7f, /* Logical maximum (32767) */ - 0x15, 0x00, /* Logical minimum (0) */ - 0x46, 0xff, 0x7f, /* Physical maximum (32767) */ - 0x36, 0x00, 0x80, /* Physical minimum (-32768) */ - 0x91, 0x02, /* Output (Variable, Absolute) */ - 0x85, 0x02, /* Report ID (2) */ - 0x09, 0x02, /* Usage (2) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x14, /* Usage (20) */ - 0x85, 0x14, /* Report ID (20) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0xc0, /* End collection */ - 0xc0, /* End collection */ -}; - -static u8 t300rs_rdesc_adv_fixed[] = { - 0x05, 0x01, /* Usage page (Generic Desktop) */ - 0x09, 0x04, /* Usage (Joystick) */ - 0xa1, 0x01, /* Collection (Application) */ - 0x09, 0x01, /* Usage (Pointer) */ - 0xa1, 0x00, /* Collection (Physical) */ - 0x85, 0x07, /* Report ID (7) */ - 0x09, 0x30, /* Usage (X) */ - 0x15, 0x00, /* Logical minimum (0) */ - 0x27, 0xff, 0xff, 0x00, 0x00, /* Logical maximum (65535) */ - 0x35, 0x00, /* Physical minimum (0) */ - 0x47, 0xff, 0xff, 0x00, 0x00, /* Physical maximum (65535) */ - 0x75, 0x10, /* Report size (16) */ - 0x95, 0x01, /* Report count (1) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x31, /* Usage (Y) */ - 0x26, 0xff, 0x03, /* Logical maximum (1023) */ - 0x46, 0xff, 0x03, /* Physical maximum (1023) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x35, /* Usage (Rz) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x36, /* Usage (Slider) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x81, 0x03, /* Input (Variable, Absolute, Constant) ? */ - 0x05, 0x09, /* Usage page (Button) */ - 0x19, 0x01, /* Usage minimum (1) */ - 0x29, 0x19, /* Usage maximum (25) */ - 0x25, 0x01, /* Logical maximum (1) */ - 0x45, 0x01, /* Physical maximum (1) */ - 0x75, 0x01, /* Report size (1) */ - 0x95, 0x19, /* Report count (25) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x75, 0x03, /* Report size (3) */ - 0x95, 0x01, /* Report count (1) */ - 0x81, 0x03, /* Input (Variable, Absolute, Constant) */ - 0x05, 0x01, /* Usage page (Generic Desktop) */ - 0x09, 0x39, /* Usage (Hat Switch) */ - 0x25, 0x07, /* Logical maximum (7) */ - 0x46, 0x3b, 0x01, /* Physical maximum (315) */ - 0x55, 0x00, /* Unit exponent (0) */ - 0x65, 0x14, /* Unit (Eng Rot, Angular Pos) */ - 0x75, 0x04, /* Report size (4) */ - 0x81, 0x42, /* Input (Variable, Absolute, NullState) */ - 0x65, 0x00, /* Unit (None) */ - 0x85, 0x60, /* Report ID (96), prev 10 */ - 0x06, 0x00, 0xff, /* Usage page (Vendor 1) */ - 0x09, 0x60, /* Usage (96), prev 10 (why?) */ - 0x75, 0x08, /* Report size (8) */ - 0x95, 0x3f, /* Report count (63) */ - 0x26, 0xff, 0x00, /* Logical maximum (255) */ - 0x46, 0xff, 0x00, /* Physical maximum (255) */ - 0x91, 0x02, /* Output (Variable, Absolute) */ - 0x85, 0x02, /* Report ID (2) */ - 0x09, 0x02, /* Usage (Mouse) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x14, /* Usage (20) */ - 0x85, 0x14, /* Report ID (20) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0xc0, /* End collection */ - 0xc0, /* End collection */ -}; - -static u8 t300rs_rdesc_ps4_fixed[] = { - 0x05, 0x01, /* Usage page (Generic Desktop) */ - 0x09, 0x05, /* Usage (GamePad) */ - 0xa1, 0x01, /* Collection (Application) */ - 0x85, 0x01, /* Report ID (1) */ - 0x09, 0x00, /* Usage (U) (was X) */ - 0x09, 0x00, /* Usage (U) (was Y) */ - 0x09, 0x00, /* Usage (U) (was Z) */ - 0x09, 0x00, /* Usage (U) (was Rz)*/ - 0x15, 0x00, /* Logical minimum (0) */ - 0x26, 0xff, 0x00, /* Logical maximum (255) */ - 0x75, 0x08, /* Report size (8) */ - 0x95, 0x04, /* Report count (4) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x39, /* Usage (Hat Switch) */ - 0x15, 0x00, /* Logical minimum (0) */ - 0x25, 0x07, /* Logical maximum (7)*/ - 0x35, 0x00, /* Physical minimum (0) */ - 0x46, 0x3b, 0x01, /* Physical maximum (315) */ - 0x65, 0x14, /* Unit (Eng Rot, Angular Pos) */ - 0x75, 0x04, /* Report size (4) */ - 0x95, 0x01, /* Report count (1) */ - 0x81, 0x42, /* Input (Variable, Absolute, NullState) */ - 0x65, 0x00, /* Input (None) */ - 0x05, 0x09, /* Usage page (Button) */ - 0x19, 0x01, /* Usage minimum (1) */ - 0x29, 0x0e, /* Usage maximum (14) */ - 0x15, 0x00, /* Logical minimum (0) */ - 0x25, 0x01, /* Logical maximum (1) */ - 0x75, 0x01, /* Report size (1) */ - 0x95, 0x0e, /* Report size (14) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x06, 0x00, 0xff, /* Usage page (Vendor 1) */ - 0x09, 0x20, /* Usage (32) */ - 0x75, 0x06, /* Report size (6) */ - 0x95, 0x01, /* Report count (1) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x05, 0x01, /* Usage page (Generic Desktop) */ - 0x09, 0x00, /* Usage (U) (was Rx)*/ - 0x09, 0x00, /* Usage (U) (was Ry) */ - 0x15, 0x00, /* Logical minimum (0) */ - 0x26, 0xff, 0x00, /* Logical maximum (255) */ - 0x75, 0x08, /* Report size (8) */ - 0x95, 0x02, /* Report count (2) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x05, 0x01, /* Usage page (Vendor 1) */ - /* constant zero? */ - 0x09, 0x00, /* Usage (33) */ - 0x95, 0x21, /* Report count (33) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - /* wheel */ - 0x09, 0x30, /* Usage (X) */ - 0x15, 0x00, /* Logical minimum (0) */ - 0x27, 0xff, 0xff, 0x00, 0x00, /* Logical maximum (65535) */ - 0x35, 0x00, /* Physical minimum (0) */ - 0x47, 0xff, 0xff, 0x00, 0x00, /* Physical maximum (65535) */ - 0x75, 0x10, /* Report size (16) */ - 0x95, 0x01, /* Report count (1) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - /* gas */ - 0x09, 0x31, /* Usage (Y) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - /* brake */ - 0x09, 0x32, /* Usage (Z) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - /* clutch */ - 0x09, 0x35, /* Usage (Rz) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - /* stick shifter (check model no) */ - 0x05, 0x09, /* Usage page (Button) */ - 0x19, 0x0f, /* Usage minimum (15) */ - 0x29, 0x17, /* Usage maximum (23) */ - 0x15, 0x00, /* Logical minimum (1) */ - 0x25, 0x01, /* Logical maximum (1) */ - 0x75, 0x01, /* Report size (1) */ - 0x95, 0x08, /* Report count (8) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - /* no clue */ - 0x05, 0x01, /* Usage page (Generic Desktop) */ - 0x09, 0x00, /* Usage (U) */ - 0x75, 0x08, /* Report size (8) */ - 0x95, 0x0c, /* Report count (12) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - /* continue unmodified */ - 0x06, 0x00, 0xff, /* Usage page (Vendor defined 1) */ - 0x85, 0x60, /* Report ID (5) (change to 0x60?) */ - 0x09, 0x60, /* Usage (34) (change to 0x60?) */ - 0x95, 0x1f, /* Report count (31) () */ - 0x91, 0x02, /* Output (Variable, Absolute) */ - 0x85, 0x03, /* Report ID (3) */ - 0x0a, 0x21, 0x27, /* ??? */ - 0x95, 0x2f, /* Report count (47) */ - 0xb1, 0x02, /* Feature (Data, Var, Abs) */ - 0xc0, /* End collection */ - - /* From here on out no clue */ - 0x06, 0xf0, - 0xff, 0x09, - 0x40, 0xa1, - 0x01, 0x85, - 0xf0, 0x09, - 0x47, 0x95, - 0x3f, 0xb1, - 0x02, 0x85, - 0xf1, 0x09, - 0x48, 0x95, - 0x3f, 0xb1, - 0x02, 0x85, - 0xf2, 0x09, - 0x49, 0x95, - 0x0f, 0xb1, - 0x02, 0x85, - 0xf3, 0x0a, - 0x01, 0x47, - 0x95, 0x07, - 0xb1, 0x02, - 0xc0, -}; - -static u8 spring_values[] = { - 0xa6, 0x6a, 0xa6, 0x6a, 0xfe, - 0xff, 0xfe, 0xff, 0xfe, 0xff, - 0xfe, 0xff, 0xdf, 0x58, 0xa6, - 0x6a, 0x06 -}; - -static u8 damper_values[] = { - 0xfc, 0x7f, 0xfc, 0x7f, 0xfe, - 0xff, 0xfe, 0xff, 0xfe, 0xff, - 0xfe, 0xff, 0xfc, 0x7f, 0xfc, - 0x7f, 0x07 -}; -- cgit v1.3 From 9b6810ba6e1bd2553e205eb6719844253d5ce051 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sat, 12 Mar 2022 20:53:39 +0200 Subject: fix crashes --- hid-tmff2.c | 24 +++++++++--------- hid-tmff2.h | 4 ++- hid-tmt300rs.c | 78 +++++++++++++++++++++++++++------------------------------- 3 files changed, 52 insertions(+), 54 deletions(-) diff --git a/hid-tmff2.c b/hid-tmff2.c index f1d1f84..6a112fa 100644 --- a/hid-tmff2.c +++ b/hid-tmff2.c @@ -52,15 +52,15 @@ static struct tmff2_device_entry *tmff2_from_hdev(struct hid_device *hdev) static struct tmff2_device_entry *tmff2_from_input(struct input_dev *input_dev) { - struct tmff2_device_entry *tmff2; + struct hid_device *hdev; spin_lock_irqsave(&lock, lock_flags); - if (!(tmff2 = input_get_drvdata(input_dev))) { + if (!(hdev = input_get_drvdata(input_dev))) { dev_err(&input_dev->dev, "input_dev private data not found\n"); return NULL; } spin_unlock_irqrestore(&lock, lock_flags); - return tmff2; + return tmff2_from_hdev(hdev); } static ssize_t spring_level_store(struct device *dev, @@ -301,7 +301,7 @@ static void tmff2_work_handler(struct work_struct *w) } if (test_bit(FF_EFFECT_QUEUE_START, &state->flags)) { - if (tmff2->play_effect(tmff2, state)) { + if (tmff2->play_effect(tmff2->data, state)) { hid_warn(tmff2->hdev, "failed starting effect\n"); } else { __clear_bit(FF_EFFECT_QUEUE_START, &state->flags); @@ -311,7 +311,7 @@ static void tmff2_work_handler(struct work_struct *w) } if (test_bit(FF_EFFECT_QUEUE_STOP, &state->flags)) { - if (tmff2->stop_effect(tmff2, state)) { + if (tmff2->stop_effect(tmff2->data, state)) { hid_warn(tmff2->hdev, "failed stopping effect\n"); } else { __clear_bit(FF_EFFECT_PLAYING, &state->flags); @@ -420,9 +420,15 @@ static int tmff2_wheel_init(struct tmff2_device_entry *tmff2) { int ret, i; struct ff_device *ff; + spin_lock_init(&lock); spin_lock_init(&tmff2->lock); INIT_DELAYED_WORK(&tmff2->work, tmff2_work_handler); + /* get parameters etc from backend */ + if ((ret = tmff2->wheel_init(tmff2))) + goto err; + + tmff2->states = kzalloc(sizeof(struct tmff2_effect_state) * tmff2->max_effects, GFP_KERNEL); @@ -431,10 +437,6 @@ static int tmff2_wheel_init(struct tmff2_device_entry *tmff2) goto err; } - /* is this required or should it be done in t300rs_populate_api? */ - if ((ret = tmff2->wheel_init(tmff2->data))) - goto err; - /* set supported effects into input_dev->ffbit */ for (i = 0; tmff2->supported_effects[i] >= 0; ++i) __set_bit(tmff2->supported_effects[i], tmff2->input_dev->ffbit); @@ -482,8 +484,6 @@ static int tmff2_probe(struct hid_device *hdev, const struct hid_device_id *id) tmff2->hdev = hdev; hid_set_drvdata(tmff2->hdev, tmff2); - tmff2->input_dev = list_entry(hdev->inputs.next, struct hid_input, list)->input; - input_set_drvdata(tmff2->input_dev, tmff2); switch (tmff2->hdev->product) { /* t300rs */ @@ -508,6 +508,8 @@ static int tmff2_probe(struct hid_device *hdev, const struct hid_device_id *id) goto hid_err; } + tmff2->input_dev = list_entry(hdev->inputs.next, struct hid_input, list)->input; + if ((ret = tmff2_wheel_init(tmff2))) { hid_err(hdev, "init failed\n"); goto init_err; diff --git a/hid-tmff2.h b/hid-tmff2.h index bdde1a7..b2a46c9 100644 --- a/hid-tmff2.h +++ b/hid-tmff2.h @@ -60,7 +60,7 @@ struct tmff2_device_entry { int (*update_effect)(void *data, struct tmff2_effect_state *state); int (*stop_effect)(void *data, struct tmff2_effect_state *state); - int (*wheel_init)(void *data); + int (*wheel_init)(struct tmff2_device_entry *tmff2); int (*wheel_destroy)(void *data); /* optional callbacks */ @@ -71,6 +71,8 @@ struct tmff2_device_entry { int (*switch_mode)(void *data, uint16_t mode); int (*set_autocenter)(void *data, uint16_t autocenter); __u8 *(*wheel_fixup)(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize); + + /* void pointers are dangerous, I know, but in this case likely the best option... */ }; #endif /* _HID_TMFF2 */ diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index ee0e817..8171578 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -1329,31 +1329,31 @@ static int t300rs_close(void *data) return ret; } -static int t300rs_create_files(struct hid_device *hdev) +static int t300rs_create_files(struct t300rs_device_entry *t300rs) { int ret; - if ((ret = device_create_file(&hdev->dev, &dev_attr_alt_mode))) { - hid_err(hdev, "unable to create sysfs interface for alt_mode\n"); + if ((ret = device_create_file(&t300rs->hdev->dev, &dev_attr_alt_mode))) { + hid_err(t300rs->hdev, "unable to create sysfs interface for alt_mode\n"); goto alt_err; } - if ((ret = device_create_file(&hdev->dev, &dev_attr_range))) { - hid_warn(hdev, "unable to create sysfs interface for range\n"); + if ((ret = device_create_file(&t300rs->hdev->dev, &dev_attr_range))) { + hid_warn(t300rs->hdev, "unable to create sysfs interface for range\n"); goto range_err; } - if ((ret = device_create_file(&hdev->dev, &dev_attr_spring_level))) { - hid_warn(hdev, "unable to create sysfs interface for spring_level\n"); + if ((ret = device_create_file(&t300rs->hdev->dev, &dev_attr_spring_level))) { + hid_warn(t300rs->hdev, "unable to create sysfs interface for spring_level\n"); goto spring_err; } - if ((ret = device_create_file(&hdev->dev, &dev_attr_damper_level))) { - hid_warn(hdev, "unable to create sysfs interface for damper_level\n"); + if ((ret = device_create_file(&t300rs->hdev->dev, &dev_attr_damper_level))) { + hid_warn(t300rs->hdev, "unable to create sysfs interface for damper_level\n"); goto damper_err; } - if ((ret = device_create_file(&hdev->dev, &dev_attr_friction_level))) { - hid_warn(hdev, "unable to create sysfs interface for friction_level\n"); + if ((ret = device_create_file(&t300rs->hdev->dev, &dev_attr_friction_level))) { + hid_warn(t300rs->hdev, "unable to create sysfs interface for friction_level\n"); goto friction_err; } @@ -1362,13 +1362,13 @@ static int t300rs_create_files(struct hid_device *hdev) /* if the creation of dev_attr_friction fails, we don't need to remove it */ /* device_remove_file(&hdev->dev, &dev_attr_friction_level); */ friction_err: - device_remove_file(&hdev->dev, &dev_attr_damper_level); + device_remove_file(&t300rs->hdev->dev, &dev_attr_damper_level); damper_err: - device_remove_file(&hdev->dev, &dev_attr_spring_level); + device_remove_file(&t300rs->hdev->dev, &dev_attr_spring_level); spring_err: - device_remove_file(&hdev->dev, &dev_attr_range); + device_remove_file(&t300rs->hdev->dev, &dev_attr_range); range_err: - device_remove_file(&hdev->dev, &dev_attr_alt_mode); + device_remove_file(&t300rs->hdev->dev, &dev_attr_alt_mode); alt_err: return ret; } @@ -1397,7 +1397,7 @@ static int t300rs_check_firmware(struct t300rs_device_entry *t300rs) ); if (ret < 0) { - hid_err(t300rs->hdev, "could not fetch firmware version\n"); + hid_err(t300rs->hdev, "could not fetch firmware version: %i\n", ret); goto out; } @@ -1422,12 +1422,21 @@ out: return ret; } -static int t300rs_wheel_init(void *data) +static int t300rs_wheel_init(struct tmff2_device_entry *tmff2) { - struct t300rs_device_entry *t300rs = data; + struct t300rs_device_entry *t300rs = kzalloc(sizeof(struct t300rs_device_entry), GFP_KERNEL); struct list_head *report_list; int ret; + if (!t300rs) { + ret = -ENOMEM; + goto t300rs_err; + } + + t300rs->hdev = tmff2->hdev; + t300rs->input_dev = tmff2->input_dev; + t300rs->usbdev = to_usb_device(tmff2->hdev->dev.parent->parent); + if(t300rs->hdev->product == 0xb66d) t300rs->buffer_length = T300RS_PS4_BUFFER_LENGTH; else @@ -1451,19 +1460,21 @@ static int t300rs_wheel_init(void *data) t300rs->open = t300rs->input_dev->open; t300rs->close = t300rs->input_dev->close; - if ((ret = t300rs_create_files(t300rs->hdev))) { + if ((ret = t300rs_create_files(t300rs))) { /* probably not a massive issue, but could affect programs like * Oversteer, best play it safe */ hid_err(t300rs->hdev, "could not create sysfs files\n"); goto sysfs_err; } - t300rs_set_range(t300rs, range); - t300rs_set_gain(t300rs, 0xffff); - /* TODO: PS4 advanced mode? */ alt_mode = (t300rs->hdev->product == 0xb66f); + /* everythin went OK */ + tmff2->data = t300rs; + tmff2->max_effects = T300RS_MAX_EFFECTS; + memcpy(tmff2->supported_effects, t300rs_effects, sizeof(t300rs_effects)); + hid_info(t300rs->hdev, "force feedback for T300RS\n"); return 0; @@ -1471,8 +1482,10 @@ sysfs_err: firmware_err: kfree(t300rs->send_buffer); +t300rs_err: + kfree(t300rs); send_err: - hid_err(t300rs->hdev, "failed creating force feedback device\n"); + hid_err(tmff2->hdev, "failed creating force feedback device\n"); return ret; } @@ -1523,17 +1536,6 @@ static __u8 *t300rs_wheel_fixup(struct hid_device *hdev, __u8 *rdesc, static int t300rs_populate_api(struct tmff2_device_entry *tmff2) { - struct t300rs_device_entry *t300rs = - kzalloc(sizeof(struct t300rs_device_entry), GFP_KERNEL); - - /* we must populate wheel_destroy at the least, even if t300rs didn't - * get allocated */ - tmff2->data = t300rs; - tmff2->max_effects = T300RS_MAX_EFFECTS; - - /* copy over supported effects */ - memcpy(tmff2->supported_effects, t300rs_effects, ARRAY_SIZE(t300rs_effects)); - /* set callbacks */ tmff2->play_effect = t300rs_play_effect; tmff2->upload_effect = t300rs_upload_effect; @@ -1551,13 +1553,5 @@ static int t300rs_populate_api(struct tmff2_device_entry *tmff2) tmff2->set_autocenter = t300rs_set_autocenter; tmff2->wheel_fixup = t300rs_wheel_fixup; - if (!t300rs) - return -ENOMEM; - - /* copy over stuff we need */ - t300rs->hdev = tmff2->hdev; - t300rs->input_dev = tmff2->input_dev; - t300rs->usbdev = to_usb_device(&tmff2->hdev->dev); - return 0; } -- cgit v1.3 From 0dcf31ff3fe8eb9bc079d94242253290a30eb97e Mon Sep 17 00:00:00 2001 From: Kimplul Date: Mon, 14 Mar 2022 00:23:40 +0200 Subject: don't include .c directly Arguably more hygienic. --- Kbuild | 2 ++ Makefile | 1 - hid-tmff2.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++--------- hid-tmff2.h | 32 ++++++++++++++----- hid-tmt300rs.c | 74 +++++++------------------------------------- hid-tmt300rs.h | 9 ++++++ 6 files changed, 131 insertions(+), 85 deletions(-) create mode 100644 Kbuild create mode 100644 hid-tmt300rs.h diff --git a/Kbuild b/Kbuild new file mode 100644 index 0000000..697f3e1 --- /dev/null +++ b/Kbuild @@ -0,0 +1,2 @@ +obj-m := hid-tmff-new.o +hid-tmff-new-y := hid-tmff2.o hid-tmt300rs.o diff --git a/Makefile b/Makefile index 9a7b851..2d88264 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,3 @@ -obj-m += hid-tmff2.o KDIR ?= /lib/modules/$(shell uname -r)/build all: hid-tminit diff --git a/hid-tmff2.c b/hid-tmff2.c index 6a112fa..811d75b 100644 --- a/hid-tmff2.c +++ b/hid-tmff2.c @@ -1,38 +1,40 @@ #include #include #include +#define TMFF2_MAIN #include "hid-tmff2.h" +#include "hid-tmt300rs.h" -static int timer_msecs = DEFAULT_TIMER_PERIOD; +int timer_msecs = DEFAULT_TIMER_PERIOD; module_param(timer_msecs, int, 0660); MODULE_PARM_DESC(timer_msecs, "Timer resolution in msecs"); /* should these be removed and just rely on /sys? */ -static int spring_level = 30; +int spring_level = 30; module_param(spring_level, int, 0); MODULE_PARM_DESC(spring_level, "Level of spring force (0-100), as per Oversteer standards"); -static int damper_level = 30; +int damper_level = 30; module_param(damper_level, int, 0); MODULE_PARM_DESC(damper_level, "Level of damper force (0-100), as per Oversteer standards"); -static int friction_level = 30; +int friction_level = 30; module_param(friction_level, int, 0); MODULE_PARM_DESC(friction_level, "Level of friction force (0-100), as per Oversteer standards"); -static int range = 900; +int range = 900; module_param(range, int, 0); MODULE_PARM_DESC(range, "Range of wheel, depends on the wheel. Invalid values are ignored."); -static int alt_mode = 0; +int alt_mode = 0; module_param(alt_mode, int, 0); MODULE_PARM_DESC(alt_mode, - "Alternate mode, eg. T300RS F1 mode."); + "Alternate mode, eg. F1 mode."); static spinlock_t lock; static unsigned long lock_flags; @@ -217,9 +219,6 @@ static ssize_t alt_mode_show(struct device *dev, } static DEVICE_ATTR_RW(alt_mode); -/* include each wheel */ -#include "hid-tmt300rs.c" - static void tmff2_set_gain(struct input_dev *dev, uint16_t gain) { struct tmff2_device_entry *tmff2 = tmff2_from_input(dev); @@ -416,6 +415,61 @@ static void tmff2_close(struct input_dev *dev) hid_err(tmff2->hdev, "no close callback set\n"); } +static int tmff2_create_files(struct tmff2_device_entry *tmff2) +{ + struct device *dev = &tmff2->hdev->dev; + int ret; + + /* could use short circuiting but this is more explicit */ + if (tmff2->params & HAS_ALT_MODE) { + if ((ret = device_create_file(dev, &dev_attr_alt_mode))) { + hid_err(tmff2->hdev, "unable to create sysfs for alt_mode\n"); + goto alt_err; + } + } + + if (tmff2->params & HAS_RANGE) { + if ((ret = device_create_file(dev, &dev_attr_range))) { + hid_warn(tmff2->hdev, "unable to create sysfs for range\n"); + goto range_err; + } + } + + if (tmff2->params & HAS_SPRING_LEVEL) { + if ((ret = device_create_file(dev, &dev_attr_spring_level))) { + hid_warn(tmff2->hdev, "unable to create sysfs for spring_level\n"); + goto spring_err; + } + } + + if (tmff2->params & HAS_DAMPER_LEVEL) { + if ((ret = device_create_file(dev, &dev_attr_damper_level))) { + hid_warn(tmff2->hdev, "unable to create sysfs for damper_level\n"); + goto damper_err; + } + } + + if (tmff2->params & HAS_FRICTION_LEVEL) { + if ((ret = device_create_file(dev, &dev_attr_friction_level))) { + hid_warn(tmff2->hdev, "unable to create sysfs for friction_level\n"); + goto friction_err; + } + } + + return 0; + +friction_err: + device_remove_file(dev, &dev_attr_damper_level); +damper_err: + device_remove_file(dev, &dev_attr_spring_level); +spring_err: + device_remove_file(dev, &dev_attr_range); +range_err: + device_remove_file(dev, &dev_attr_alt_mode); +alt_err: + return ret; +} + static int tmff2_wheel_init(struct tmff2_device_entry *tmff2) { int ret, i; @@ -464,6 +518,10 @@ static int tmff2_wheel_init(struct tmff2_device_entry *tmff2) if (tmff2->set_autocenter) ff->set_autocenter = tmff2_set_autocenter; + /* create files */ + if ((ret = tmff2_create_files(tmff2))) + goto err; + return 0; err: @@ -519,13 +577,10 @@ static int tmff2_probe(struct hid_device *hdev, const struct hid_device_id *id) init_err: hid_hw_stop(hdev); - hid_err: tmff2->wheel_destroy(tmff2->data); - wheel_err: kfree(tmff2); - oom_err: return ret; } @@ -546,12 +601,27 @@ static __u8 *tmff2_report_fixup(struct hid_device *hdev, __u8 *rdesc, static void tmff2_remove(struct hid_device *hdev) { struct tmff2_device_entry *tmff2 = tmff2_from_hdev(hdev); + struct device *dev; if (!tmff2) return; + cancel_delayed_work_sync(&tmff2->work); - tmff2->wheel_destroy(tmff2->data); + dev = &tmff2->hdev->dev; + if (tmff2->params & HAS_DAMPER_LEVEL) + device_remove_file(dev, &dev_attr_damper_level); + + if (tmff2->params & HAS_SPRING_LEVEL) + device_remove_file(dev, &dev_attr_spring_level); + + if (tmff2->params & HAS_RANGE) + device_remove_file(dev, &dev_attr_range); + + if (tmff2->params & HAS_ALT_MODE) + device_remove_file(dev, &dev_attr_alt_mode); + + tmff2->wheel_destroy(tmff2->data); hid_hw_stop(hdev); kfree(tmff2->states); diff --git a/hid-tmff2.h b/hid-tmff2.h index b2a46c9..1585649 100644 --- a/hid-tmff2.h +++ b/hid-tmff2.h @@ -1,11 +1,20 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _HID_TMFF2 -#define _HID_TMFF2 +#ifndef __HID_TMFF2_H +#define __HID_TMFF2_H #include #include #include +#ifndef TMFF2_MAIN +extern int timer_msecs; +extern int spring_level; +extern int damper_level; +extern int friction_level; +extern int range; +extern int alt_mode; +#endif + #define USB_VENDOR_ID_THRUSTMASTER 0x044f /* the wheel seems to only be capable of processing a certain number of @@ -16,11 +25,17 @@ */ #define DEFAULT_TIMER_PERIOD 8 -#define FF_EFFECT_QUEUE_UPLOAD 0 -#define FF_EFFECT_QUEUE_START 1 -#define FF_EFFECT_QUEUE_STOP 2 -#define FF_EFFECT_QUEUE_UPDATE 3 -#define FF_EFFECT_PLAYING 4 +#define FF_EFFECT_QUEUE_UPLOAD 0 +#define FF_EFFECT_QUEUE_START 1 +#define FF_EFFECT_QUEUE_STOP 2 +#define FF_EFFECT_QUEUE_UPDATE 3 +#define FF_EFFECT_PLAYING 4 + +#define HAS_SPRING_LEVEL (1 << 0) +#define HAS_DAMPER_LEVEL (1 << 1) +#define HAS_FRICTION_LEVEL (1 << 2) +#define HAS_RANGE (1 << 3) +#define HAS_ALT_MODE (1 << 4) #undef fixp_sin16 #define fixp_sin16(v) (((v % 360) > 180) ?\ @@ -51,6 +66,7 @@ struct tmff2_device_entry { /* fields relevant to each actual device (T300, T150...) */ void *data; + unsigned long params; unsigned long max_effects; signed short supported_effects[FF_CNT]; @@ -75,4 +91,4 @@ struct tmff2_device_entry { /* void pointers are dangerous, I know, but in this case likely the best option... */ }; -#endif /* _HID_TMFF2 */ +#endif /* __HID_TMFF2_H */ diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 8171578..b253562 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -1,10 +1,20 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include +#include "hid-tmff2.h" +#include "hid-tmt300rs.h" #define T300RS_MAX_EFFECTS 16 #define T300RS_NORM_BUFFER_LENGTH 63 #define T300RS_PS4_BUFFER_LENGTH 31 +static const unsigned long t300rs_params = + HAS_SPRING_LEVEL + | HAS_DAMPER_LEVEL + | HAS_FRICTION_LEVEL + | HAS_RANGE + | HAS_ALT_MODE; + static const signed short t300rs_effects[] = { FF_CONSTANT, FF_RAMP, @@ -1329,50 +1339,6 @@ static int t300rs_close(void *data) return ret; } -static int t300rs_create_files(struct t300rs_device_entry *t300rs) -{ - int ret; - if ((ret = device_create_file(&t300rs->hdev->dev, &dev_attr_alt_mode))) { - hid_err(t300rs->hdev, "unable to create sysfs interface for alt_mode\n"); - goto alt_err; - } - - if ((ret = device_create_file(&t300rs->hdev->dev, &dev_attr_range))) { - hid_warn(t300rs->hdev, "unable to create sysfs interface for range\n"); - goto range_err; - } - - if ((ret = device_create_file(&t300rs->hdev->dev, &dev_attr_spring_level))) { - hid_warn(t300rs->hdev, "unable to create sysfs interface for spring_level\n"); - goto spring_err; - } - - if ((ret = device_create_file(&t300rs->hdev->dev, &dev_attr_damper_level))) { - hid_warn(t300rs->hdev, "unable to create sysfs interface for damper_level\n"); - goto damper_err; - } - - if ((ret = device_create_file(&t300rs->hdev->dev, &dev_attr_friction_level))) { - hid_warn(t300rs->hdev, "unable to create sysfs interface for friction_level\n"); - goto friction_err; - } - - return ret; - - /* if the creation of dev_attr_friction fails, we don't need to remove it */ - /* device_remove_file(&hdev->dev, &dev_attr_friction_level); */ -friction_err: - device_remove_file(&t300rs->hdev->dev, &dev_attr_damper_level); -damper_err: - device_remove_file(&t300rs->hdev->dev, &dev_attr_spring_level); -spring_err: - device_remove_file(&t300rs->hdev->dev, &dev_attr_range); -range_err: - device_remove_file(&t300rs->hdev->dev, &dev_attr_alt_mode); -alt_err: - return ret; -} - static int t300rs_check_firmware(struct t300rs_device_entry *t300rs) { int ret; @@ -1460,28 +1426,20 @@ static int t300rs_wheel_init(struct tmff2_device_entry *tmff2) t300rs->open = t300rs->input_dev->open; t300rs->close = t300rs->input_dev->close; - if ((ret = t300rs_create_files(t300rs))) { - /* probably not a massive issue, but could affect programs like - * Oversteer, best play it safe */ - hid_err(t300rs->hdev, "could not create sysfs files\n"); - goto sysfs_err; - } - /* TODO: PS4 advanced mode? */ alt_mode = (t300rs->hdev->product == 0xb66f); /* everythin went OK */ tmff2->data = t300rs; + tmff2->params = t300rs_params; tmff2->max_effects = T300RS_MAX_EFFECTS; memcpy(tmff2->supported_effects, t300rs_effects, sizeof(t300rs_effects)); hid_info(t300rs->hdev, "force feedback for T300RS\n"); return 0; -sysfs_err: firmware_err: kfree(t300rs->send_buffer); - t300rs_err: kfree(t300rs); send_err: @@ -1495,14 +1453,6 @@ static int t300rs_wheel_destroy(void *data) if (!t300rs) return -ENODEV; - /* apparently should be safe to call these even without the files - * existing */ - device_remove_file(&t300rs->hdev->dev, &dev_attr_range); - device_remove_file(&t300rs->hdev->dev, &dev_attr_alt_mode); - device_remove_file(&t300rs->hdev->dev, &dev_attr_spring_level); - device_remove_file(&t300rs->hdev->dev, &dev_attr_damper_level); - device_remove_file(&t300rs->hdev->dev, &dev_attr_friction_level); - kfree(t300rs->send_buffer); kfree(t300rs); return 0; @@ -1534,7 +1484,7 @@ static __u8 *t300rs_wheel_fixup(struct hid_device *hdev, __u8 *rdesc, return rdesc; } -static int t300rs_populate_api(struct tmff2_device_entry *tmff2) +int t300rs_populate_api(struct tmff2_device_entry *tmff2) { /* set callbacks */ tmff2->play_effect = t300rs_play_effect; diff --git a/hid-tmt300rs.h b/hid-tmt300rs.h new file mode 100644 index 0000000..9357ce1 --- /dev/null +++ b/hid-tmt300rs.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __HID_TMT300RS_H +#define __HID_TMT300RS_H + +#include "hid-tmff2.h" + +int t300rs_populate_api(struct tmff2_device_entry *tmff2); + +#endif /* __HID_TM300RS_H */ -- cgit v1.3 From 28d0a3f76748a2555fc1417216ed51112dba945c Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sun, 20 Mar 2022 17:48:19 +0200 Subject: merge headers into one --- hid-tmff2.c | 35 ++++++++++++++++++----------------- hid-tmff2.h | 21 +++++++++++++-------- hid-tmt300rs.c | 35 ++++++++++++++++++----------------- 3 files changed, 49 insertions(+), 42 deletions(-) diff --git a/hid-tmff2.c b/hid-tmff2.c index 811d75b..2e7221f 100644 --- a/hid-tmff2.c +++ b/hid-tmff2.c @@ -1,9 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 #include #include #include -#define TMFF2_MAIN #include "hid-tmff2.h" -#include "hid-tmt300rs.h" + int timer_msecs = DEFAULT_TIMER_PERIOD; module_param(timer_msecs, int, 0660); @@ -421,35 +421,35 @@ static int tmff2_create_files(struct tmff2_device_entry *tmff2) int ret; /* could use short circuiting but this is more explicit */ - if (tmff2->params & HAS_ALT_MODE) { + if (tmff2->params & PARAM_ALT_MODE) { if ((ret = device_create_file(dev, &dev_attr_alt_mode))) { hid_err(tmff2->hdev, "unable to create sysfs for alt_mode\n"); goto alt_err; } } - if (tmff2->params & HAS_RANGE) { + if (tmff2->params & PARAM_RANGE) { if ((ret = device_create_file(dev, &dev_attr_range))) { hid_warn(tmff2->hdev, "unable to create sysfs for range\n"); goto range_err; } } - if (tmff2->params & HAS_SPRING_LEVEL) { + if (tmff2->params & PARAM_SPRING_LEVEL) { if ((ret = device_create_file(dev, &dev_attr_spring_level))) { hid_warn(tmff2->hdev, "unable to create sysfs for spring_level\n"); goto spring_err; } } - if (tmff2->params & HAS_DAMPER_LEVEL) { + if (tmff2->params & PARAM_DAMPER_LEVEL) { if ((ret = device_create_file(dev, &dev_attr_damper_level))) { hid_warn(tmff2->hdev, "unable to create sysfs for damper_level\n"); goto damper_err; } } - if (tmff2->params & HAS_FRICTION_LEVEL) { + if (tmff2->params & PARAM_FRICTION_LEVEL) { if ((ret = device_create_file(dev, &dev_attr_friction_level))) { hid_warn(tmff2->hdev, "unable to create sysfs for friction_level\n"); goto friction_err; @@ -545,12 +545,13 @@ static int tmff2_probe(struct hid_device *hdev, const struct hid_device_id *id) switch (tmff2->hdev->product) { /* t300rs */ - case 0xb66e: - case 0xb66f: - case 0xb66d: + case TMT300RS_PS3_NORM_ID: + case TMT300RS_PS3_ADV_ID: + case TMT300RS_PS4_NORM_ID: if ((ret = t300rs_populate_api(tmff2))) goto wheel_err; break; + default: ret = -ENODEV; goto wheel_err; @@ -609,16 +610,16 @@ static void tmff2_remove(struct hid_device *hdev) cancel_delayed_work_sync(&tmff2->work); dev = &tmff2->hdev->dev; - if (tmff2->params & HAS_DAMPER_LEVEL) + if (tmff2->params & PARAM_DAMPER_LEVEL) device_remove_file(dev, &dev_attr_damper_level); - if (tmff2->params & HAS_SPRING_LEVEL) + if (tmff2->params & PARAM_SPRING_LEVEL) device_remove_file(dev, &dev_attr_spring_level); - if (tmff2->params & HAS_RANGE) + if (tmff2->params & PARAM_RANGE) device_remove_file(dev, &dev_attr_range); - if (tmff2->params & HAS_ALT_MODE) + if (tmff2->params & PARAM_ALT_MODE) device_remove_file(dev, &dev_attr_alt_mode); tmff2->wheel_destroy(tmff2->data); @@ -630,9 +631,9 @@ static void tmff2_remove(struct hid_device *hdev) static const struct hid_device_id tmff2_devices[] = { /* t300rs and variations */ - {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb66e)}, - {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb66f)}, - {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb66d)}, + {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, TMT300RS_PS3_NORM_ID)}, + {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, TMT300RS_PS3_ADV_ID)}, + {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, TMT300RS_PS4_NORM_ID)}, {} }; MODULE_DEVICE_TABLE(hid, tmff2_devices); diff --git a/hid-tmff2.h b/hid-tmff2.h index 1585649..d59104a 100644 --- a/hid-tmff2.h +++ b/hid-tmff2.h @@ -6,14 +6,12 @@ #include #include -#ifndef TMFF2_MAIN extern int timer_msecs; extern int spring_level; extern int damper_level; extern int friction_level; extern int range; extern int alt_mode; -#endif #define USB_VENDOR_ID_THRUSTMASTER 0x044f @@ -23,7 +21,7 @@ extern int alt_mode; * space out the interrupts so that they all leave at regular intervals, but * for now this is good enough, go slow enough that everything works. */ -#define DEFAULT_TIMER_PERIOD 8 +#define DEFAULT_TIMER_PERIOD 8 #define FF_EFFECT_QUEUE_UPLOAD 0 #define FF_EFFECT_QUEUE_START 1 @@ -31,11 +29,11 @@ extern int alt_mode; #define FF_EFFECT_QUEUE_UPDATE 3 #define FF_EFFECT_PLAYING 4 -#define HAS_SPRING_LEVEL (1 << 0) -#define HAS_DAMPER_LEVEL (1 << 1) -#define HAS_FRICTION_LEVEL (1 << 2) -#define HAS_RANGE (1 << 3) -#define HAS_ALT_MODE (1 << 4) +#define PARAM_SPRING_LEVEL (1 << 0) +#define PARAM_DAMPER_LEVEL (1 << 1) +#define PARAM_FRICTION_LEVEL (1 << 2) +#define PARAM_RANGE (1 << 3) +#define PARAM_ALT_MODE (1 << 4) #undef fixp_sin16 #define fixp_sin16(v) (((v % 360) > 180) ?\ @@ -91,4 +89,11 @@ struct tmff2_device_entry { /* void pointers are dangerous, I know, but in this case likely the best option... */ }; +/* external */ +int t300rs_populate_api(struct tmff2_device_entry *tmff2); + +#define TMT300RS_PS3_NORM_ID 0xb66e +#define TMT300RS_PS3_ADV_ID 0xb66f +#define TMT300RS_PS4_NORM_ID 0xb66d + #endif /* __HID_TMFF2_H */ diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index b253562..8c4655b 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -2,18 +2,18 @@ #include #include #include "hid-tmff2.h" -#include "hid-tmt300rs.h" #define T300RS_MAX_EFFECTS 16 #define T300RS_NORM_BUFFER_LENGTH 63 #define T300RS_PS4_BUFFER_LENGTH 31 static const unsigned long t300rs_params = - HAS_SPRING_LEVEL - | HAS_DAMPER_LEVEL - | HAS_FRICTION_LEVEL - | HAS_RANGE - | HAS_ALT_MODE; + PARAM_SPRING_LEVEL + | PARAM_DAMPER_LEVEL + | PARAM_FRICTION_LEVEL + | PARAM_RANGE + | PARAM_ALT_MODE + ; static const signed short t300rs_effects[] = { FF_CONSTANT, @@ -356,7 +356,7 @@ static u8 damper_values[] = { 0x7f, 0x07 }; -static int t300rs_send_buf(struct t300rs_device_entry *t300rs, size_t len, u8 *send_buffer) +static int t300rs_send_buf(struct t300rs_device_entry *t300rs, u8 *send_buffer, size_t len) { int i; /* check that send_buffer fits into our report */ @@ -377,7 +377,7 @@ static int t300rs_send_buf(struct t300rs_device_entry *t300rs, size_t len, u8 *s static int t300rs_send_int(struct t300rs_device_entry *t300rs) { - t300rs_send_buf(t300rs, t300rs->buffer_length, t300rs->send_buffer); + t300rs_send_buf(t300rs, t300rs->send_buffer, t300rs->buffer_length); memset(t300rs->send_buffer, 0, t300rs->buffer_length); return 0; @@ -1213,6 +1213,7 @@ static int t300rs_set_autocenter(void *data, uint16_t value) if (!t300rs) return -ENODEV; + /* TODO: this should probably also use a separately allocated buffer? */ autocenter_packet = (struct t300rs_packet_autocenter *)t300rs->send_buffer; autocenter_packet->header.cmd = 0x08; @@ -1288,7 +1289,7 @@ static int t300rs_set_range(void *data, uint16_t value) send_buffer[2] = scaled_value & 0xff; send_buffer[3] = scaled_value >> 8; - if ((ret = t300rs_send_buf(t300rs, t300rs->buffer_length, send_buffer))) + if ((ret = t300rs_send_buf(t300rs, send_buffer, t300rs->buffer_length))) hid_warn(t300rs->hdev, "failed setting range\n"); /* since everythin went OK, update the current range */ @@ -1403,7 +1404,7 @@ static int t300rs_wheel_init(struct tmff2_device_entry *tmff2) t300rs->input_dev = tmff2->input_dev; t300rs->usbdev = to_usb_device(tmff2->hdev->dev.parent->parent); - if(t300rs->hdev->product == 0xb66d) + if(t300rs->hdev->product == TMT300RS_PS4_NORM_ID) t300rs->buffer_length = T300RS_PS4_BUFFER_LENGTH; else t300rs->buffer_length = T300RS_NORM_BUFFER_LENGTH; @@ -1427,7 +1428,7 @@ static int t300rs_wheel_init(struct tmff2_device_entry *tmff2) t300rs->close = t300rs->input_dev->close; /* TODO: PS4 advanced mode? */ - alt_mode = (t300rs->hdev->product == 0xb66f); + alt_mode = (t300rs->hdev->product == TMT300RS_PS3_ADV_ID); /* everythin went OK */ tmff2->data = t300rs; @@ -1440,10 +1441,10 @@ static int t300rs_wheel_init(struct tmff2_device_entry *tmff2) firmware_err: kfree(t300rs->send_buffer); -t300rs_err: - kfree(t300rs); send_err: - hid_err(tmff2->hdev, "failed creating force feedback device\n"); + kfree(t300rs); +t300rs_err: + hid_err(tmff2->hdev, "failed initializing T300RS\n"); return ret; } @@ -1462,19 +1463,19 @@ static __u8 *t300rs_wheel_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { switch (hdev->product) { - case 0xb66e: + case TMT300RS_PS3_NORM_ID: /* normal PS3 mode */ rdesc = t300rs_rdesc_nrm_fixed; *rsize = sizeof(t300rs_rdesc_nrm_fixed); break; - case 0xb66d: + case TMT300RS_PS4_NORM_ID: /* PS4 normal mode */ rdesc = t300rs_rdesc_ps4_fixed; *rsize = sizeof(t300rs_rdesc_ps4_fixed); break; - case 0xb66f: + case TMT300RS_PS3_ADV_ID: /* PS3 advanced mode */ rdesc = t300rs_rdesc_adv_fixed; *rsize = sizeof(t300rs_rdesc_adv_fixed); -- cgit v1.3 From 725e8ea20b616b8cd29865a8819112ae2c61c54f Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sun, 20 Mar 2022 19:41:25 +0200 Subject: add initial t248 support --- Kbuild | 2 +- TODO | 3 + hid-tmff2.c | 7 ++ hid-tmff2.h | 38 ++++++++++- hid-tmt248.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hid-tmt300rs.c | 34 +++------- 6 files changed, 256 insertions(+), 29 deletions(-) create mode 100644 hid-tmt248.c diff --git a/Kbuild b/Kbuild index 697f3e1..590c69d 100644 --- a/Kbuild +++ b/Kbuild @@ -1,2 +1,2 @@ obj-m := hid-tmff-new.o -hid-tmff-new-y := hid-tmff2.o hid-tmt300rs.o +hid-tmff-new-y := hid-tmff2.o hid-tmt300rs.o hid-tmt248.o diff --git a/TODO b/TODO index 87db3d1..70d3652 100644 --- a/TODO +++ b/TODO @@ -2,3 +2,6 @@ easily included. + Use workqueues instead of doing everything in t300rs_timer + ++ T248 open/close seems to crash the wheel and the kernel along with it, check how Windows handles it ++ T248 fix rdesc, 0x0a somewhere needs to be set to 0x60 diff --git a/hid-tmff2.c b/hid-tmff2.c index 2e7221f..4aa6141 100644 --- a/hid-tmff2.c +++ b/hid-tmff2.c @@ -552,6 +552,11 @@ static int tmff2_probe(struct hid_device *hdev, const struct hid_device_id *id) goto wheel_err; break; + case TMT248_PC_ID: + if ((ret = t248_populate_api(tmff2))) + goto wheel_err; + break; + default: ret = -ENODEV; goto wheel_err; @@ -634,6 +639,8 @@ static const struct hid_device_id tmff2_devices[] = { {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, TMT300RS_PS3_NORM_ID)}, {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, TMT300RS_PS3_ADV_ID)}, {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, TMT300RS_PS4_NORM_ID)}, + /* t248 PC*/ + {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, TMT248_PC_ID)}, {} }; MODULE_DEVICE_TABLE(hid, tmff2_devices); diff --git a/hid-tmff2.h b/hid-tmff2.h index d59104a..f474ca7 100644 --- a/hid-tmff2.h +++ b/hid-tmff2.h @@ -91,9 +91,41 @@ struct tmff2_device_entry { /* external */ int t300rs_populate_api(struct tmff2_device_entry *tmff2); +int t248_populate_api(struct tmff2_device_entry *tmff2); -#define TMT300RS_PS3_NORM_ID 0xb66e -#define TMT300RS_PS3_ADV_ID 0xb66f -#define TMT300RS_PS4_NORM_ID 0xb66d +#define TMT300RS_PS3_NORM_ID 0xb66e +#define TMT300RS_PS3_ADV_ID 0xb66f +#define TMT300RS_PS4_NORM_ID 0xb66d + +#define TMT248_PC_ID 0xb696 + +/* apis to different wheel families */ +/* T248 at least uses the T300RS api, not sure if there are other wheels but that's + * why these functions are given global linkage */ + +struct t300rs_device_entry { + struct hid_device *hdev; + struct input_dev *input_dev; + struct hid_report *report; + struct hid_field *ff_field; + struct usb_device *usbdev; + + int (*open)(struct input_dev *dev); + void (*close)(struct input_dev *dev); + + u8 buffer_length; + u8 *send_buffer; +}; + +int t300rs_play_effect(void *, struct tmff2_effect_state *); +int t300rs_upload_effect(void *, struct tmff2_effect_state *); +int t300rs_update_effect(void *, struct tmff2_effect_state *); +int t300rs_stop_effect(void *, struct tmff2_effect_state *); + +int t300rs_open(void *); +int t300rs_close(void *); +int t300rs_set_gain(void *, uint16_t); +int t300rs_set_range(void *, uint16_t); +int t300rs_set_autocenter(void *, uint16_t); #endif /* __HID_TMFF2_H */ diff --git a/hid-tmt248.c b/hid-tmt248.c new file mode 100644 index 0000000..5a19bb0 --- /dev/null +++ b/hid-tmt248.c @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include "hid-tmff2.h" + +#define T248_MAX_EFFECTS 16 +#define T248_BUFFER_LENGTH 63 + +static const u8 setup_0[64] = { 0x42, 0x01 }; +static const u8 setup_1[64] = { 0x0a, 0x04, 0x90, 0x03 }; +static const u8 setup_2[64] = { 0x0a, 0x04, 0x00, 0x0c }; +static const u8 setup_3[64] = { 0x0a, 0x04, 0x12, 0x10 }; +static const u8 setup_4[64] = { 0x0a, 0x04, 0x00, 0x06 }; +static const u8 setup_5[64] = { 0x0a, 0x04, 0x00, 0x0e }; +static const u8 setup_6[64] = { 0x0a, 0x04, 0x00, 0x0e, 0x01 }; +static const u8 *const setup_arr[] = { setup_0, setup_1, setup_2, setup_3, setup_4, setup_5, setup_6 }; +static const unsigned int setup_arr_sizes[] = { + ARRAY_SIZE(setup_0), + ARRAY_SIZE(setup_1), + ARRAY_SIZE(setup_2), + ARRAY_SIZE(setup_3), + ARRAY_SIZE(setup_4), + ARRAY_SIZE(setup_5), + ARRAY_SIZE(setup_6) +}; + +static const unsigned long t248_params = + PARAM_SPRING_LEVEL + | PARAM_DAMPER_LEVEL + | PARAM_FRICTION_LEVEL + | PARAM_RANGE + ; + +static const signed short t248_effects[] = { + FF_CONSTANT, + FF_RAMP, + FF_SPRING, + FF_DAMPER, + FF_FRICTION, + FF_INERTIA, + FF_PERIODIC, + FF_SINE, + FF_TRIANGLE, + FF_SQUARE, + FF_SAW_UP, + FF_SAW_DOWN, + FF_AUTOCENTER, + FF_GAIN, + -1 +}; + +static int t248_interrupts(struct t300rs_device_entry *t248) +{ + u8 *send_buf = kmalloc(256, GFP_KERNEL); + struct usb_interface *usbif = to_usb_interface(t248->hdev->dev.parent); + struct usb_host_endpoint *ep; + int ret, trans, b_ep, i; + if (!send_buf) { + hid_err(t248->hdev, "failed allocating send buffer\n"); + return -ENOMEM; + } + + ep = &usbif->cur_altsetting->endpoint[1]; + b_ep = ep->desc.bEndpointAddress; + + for (i = 0; i < ARRAY_SIZE(setup_arr); ++i) { + memcpy(send_buf, setup_arr[i], setup_arr_sizes[i]); + + ret = usb_interrupt_msg(t248->usbdev, + usb_sndintpipe(t248->usbdev, b_ep), + send_buf, setup_arr_sizes[i], + &trans, + USB_CTRL_SET_TIMEOUT); + + if (ret) { + hid_err(t248->hdev, "setup data couldn't be sent\n"); + goto err; + } + } + +err: + kfree(send_buf); + return ret; +} + +int t248_wheel_init(struct tmff2_device_entry *tmff2) +{ + struct t300rs_device_entry *t248 = kzalloc(sizeof(struct t300rs_device_entry), GFP_KERNEL); + struct list_head *report_list; + int ret; + + if (!t248) { + ret = -ENOMEM; + goto t248_err; + } + + t248->hdev = tmff2->hdev; + t248->input_dev = tmff2->input_dev; + t248->usbdev = to_usb_device(tmff2->hdev->dev.parent->parent); + t248->buffer_length = T248_BUFFER_LENGTH; + + t248->send_buffer = kzalloc(t248->buffer_length, GFP_KERNEL); + if (!t248->send_buffer) { + ret = -ENOMEM; + goto send_err; + } + + report_list = &t248->hdev->report_enum[HID_OUTPUT_REPORT].report_list; + t248->report = list_entry(report_list->next, struct hid_report, list); + t248->ff_field = t248->report->field[0]; + + t248->open = t248->input_dev->open; + t248->close = t248->input_dev->close; + + if ((ret = t248_interrupts(t248))) + goto interrupt_err; + + /* everything went OK */ + tmff2->data = t248; + tmff2->params = t248_params; + tmff2->max_effects = T248_MAX_EFFECTS; + memcpy(tmff2->supported_effects, t248_effects, sizeof(t248_effects)); + + hid_info(t248->hdev, "force feedback for T248\n"); + return 0; + +interrupt_err: +send_err: + kfree(t248); +t248_err: + hid_err(tmff2->hdev, "failed initializing T248\n"); + return ret; +} + +int t248_wheel_destroy(void *data) +{ + struct t300rs_device_entry *t300rs = data; + if (!t300rs) + return -ENODEV; + + kfree(t300rs->send_buffer); + kfree(t300rs); + return 0; +} + +int t248_set_range(void *data, uint16_t value) +{ + struct t300rs_device_entry *t248 = data; + if (value < 140) { + hid_info(t248->hdev, "value %i too small, clamping to 140\n", value); + value = 140; + } + + if (value > 900) { + hid_info(t248->hdev, "value %i too large, clamping to 900\n", value); + value = 900; + } + + return t300rs_set_range(data, value); +} + +static int t248_open(void *data) +{ + struct t300rs_device_entry *t248 = data; + if (!t248) + return -ENODEV; + + /* TODO: send usb commands to actually open device */ + return t248->open(t248->input_dev); +} + +static int t248_close(void *data) +{ + struct t300rs_device_entry *t248 = data; + if (!t248) + return -ENODEV; + + /* TODO: send usb commands to actually close device */ + t248->close(t248->input_dev); + return 0; +} + +int t248_populate_api(struct tmff2_device_entry *tmff2) +{ + tmff2->play_effect = t300rs_play_effect; + tmff2->upload_effect = t300rs_upload_effect; + tmff2->update_effect = t300rs_update_effect; + tmff2->stop_effect = t300rs_stop_effect; + + tmff2->wheel_init = t248_wheel_init; + tmff2->wheel_destroy = t248_wheel_destroy; + + tmff2->open = t248_open; + tmff2->close = t248_close; + tmff2->set_gain = t300rs_set_gain; + /* T248 only has 900 degree range, instead of T300RS 1080 */ + tmff2->set_range = t248_set_range; + tmff2->set_autocenter = t300rs_set_autocenter; + + return 0; +} diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 8c4655b..92e9acd 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -75,22 +75,6 @@ struct usb_ctrlrequest t300rs_fw_request = { .wLength = 8 }; - -struct t300rs_device_entry { - struct hid_device *hdev; - struct input_dev *input_dev; - struct hid_report *report; - struct hid_field *ff_field; - struct usb_device *usbdev; - - int (*open)(struct input_dev *dev); - void (*close)(struct input_dev *dev); - - u8 buffer_length; - u8 *send_buffer; -}; - - struct t300rs_data { unsigned long quirks; void *device_props; @@ -390,7 +374,7 @@ static void t300rs_fill_header(struct t300rs_packet_header *packet_header, packet_header->code = code; } -static int t300rs_play_effect(void *data, struct tmff2_effect_state *state) +int t300rs_play_effect(void *data, struct tmff2_effect_state *state) { struct t300rs_device_entry *t300rs = data; struct __packed t300rs_packet_play { @@ -411,7 +395,7 @@ static int t300rs_play_effect(void *data, struct tmff2_effect_state *state) return ret; } -static int t300rs_stop_effect(void *data, struct tmff2_effect_state *state) +int t300rs_stop_effect(void *data, struct tmff2_effect_state *state) { struct t300rs_device_entry *t300rs = data; struct __packed t300rs_packet_stop { @@ -1132,7 +1116,7 @@ static int t300rs_upload_periodic(struct t300rs_device_entry *t300rs, return ret; } -static int t300rs_update_effect(void *data, struct tmff2_effect_state *state) +int t300rs_update_effect(void *data, struct tmff2_effect_state *state) { struct t300rs_device_entry *t300rs = data; switch (state->effect.type) { @@ -1154,7 +1138,7 @@ static int t300rs_update_effect(void *data, struct tmff2_effect_state *state) } } -static int t300rs_upload_effect(void *data, struct tmff2_effect_state *state) +int t300rs_upload_effect(void *data, struct tmff2_effect_state *state) { struct t300rs_device_entry *t300rs = data; switch (state->effect.type) { @@ -1201,7 +1185,7 @@ static int t300rs_switch_mode(void *data, uint16_t mode) return 0; } -static int t300rs_set_autocenter(void *data, uint16_t value) +int t300rs_set_autocenter(void *data, uint16_t value) { struct t300rs_device_entry *t300rs = data; struct __packed t300rs_packet_autocenter { @@ -1236,7 +1220,7 @@ static int t300rs_set_autocenter(void *data, uint16_t value) return ret; } -static int t300rs_set_gain(void *data, uint16_t gain) +int t300rs_set_gain(void *data, uint16_t gain) { struct t300rs_device_entry *t300rs = data; struct __packed t300rs_packet_gain { @@ -1257,7 +1241,7 @@ static int t300rs_set_gain(void *data, uint16_t gain) return ret; } -static int t300rs_set_range(void *data, uint16_t value) +int t300rs_set_range(void *data, uint16_t value) { struct t300rs_device_entry *t300rs = data; /* it's important that we don't use t300rs->send_buffer, as range can be @@ -1299,7 +1283,7 @@ err: return ret; } -static int t300rs_open(void *data) +int t300rs_open(void *data) { struct t300rs_device_entry *t300rs = data; struct __packed t300rs_packet_open { @@ -1319,7 +1303,7 @@ static int t300rs_open(void *data) return t300rs->open(t300rs->input_dev); } -static int t300rs_close(void *data) +int t300rs_close(void *data) { struct t300rs_device_entry *t300rs = data; struct t300rs_packet_close { -- cgit v1.3 From d12951deac141dcd026bc59ed9c0550f6630f345 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sun, 20 Mar 2022 19:45:51 +0200 Subject: dump default rdesc --- hid-tmt248.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hid-tmt248.c b/hid-tmt248.c index 5a19bb0..1c51ba8 100644 --- a/hid-tmt248.c +++ b/hid-tmt248.c @@ -49,6 +49,11 @@ static const signed short t248_effects[] = { -1 }; +/* TODO: sort through this stuff */ +static u8 t248_pc_rdesc_fixed[] = { +0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0x09, 0x01, 0xa1, 0x00, 0x85, 0x07, 0x09, 0x30, 0x15, 0x00, 0x27, 0xff, 0xff, 0x00, 0x00, 0x35, 0x00, 0x47, 0xff, 0xff, 0x00, 0x00, 0x75, 0x10, 0x95, 0x01, 0x81, 0x02, 0x09, 0x31, 0x26, 0xff, 0x03, 0x46, 0xff, 0x03, 0x81, 0x02, 0x09, 0x35, 0x81, 0x02, 0x09, 0x36, 0x81, 0x02, 0x75, 0x08, 0x26, 0xff, 0x00, 0x46, 0xff, 0x00, 0x09, 0x40, 0x81, 0x02, 0x09, 0x41, 0x81, 0x02, 0x09, 0x33, 0x81, 0x02, 0x09, 0x34, 0x81, 0x02, 0x09, 0x32, 0x81, 0x02, 0x09, 0x37, 0x81, 0x02, 0x05, 0x09, 0x19, 0x01, 0x29, 0x1a, 0x25, 0x01, 0x45, 0x01, 0x75, 0x01, 0x95, 0x1a, 0x81, 0x02, 0x75, 0x06, 0x95, 0x01, 0x81, 0x03, 0x05, 0x01, 0x09, 0x39, 0x25, 0x07, 0x46, 0x3b, 0x01, 0x55, 0x00, 0x65, 0x14, 0x75, 0x04, 0x81, 0x42, 0x65, 0x00, 0x81, 0x03, 0x85, 0x0a, 0x06, 0x00, 0xff, 0x09, 0x0a, 0x75, 0x08, 0x95, 0x3f, 0x26, 0xff, 0x00, 0x46, 0xff, 0x00, 0x91, 0x02, 0x85, 0x02, 0x09, 0x02, 0x81, 0x02, 0x09, 0x14, 0x85, 0x14 0x81, 0x02, 0xc0, 0xc0 +}; + static int t248_interrupts(struct t300rs_device_entry *t248) { u8 *send_buf = kmalloc(256, GFP_KERNEL); -- cgit v1.3 From 3eba47f56dcb539b3dd475b9906ed9af7bd8db7f Mon Sep 17 00:00:00 2001 From: Kimplul Date: Mon, 21 Mar 2022 21:47:10 +0200 Subject: annotate t248 rdesc --- hid-tmt248.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- t248-effects.txt | 2 ++ 2 files changed, 92 insertions(+), 7 deletions(-) create mode 100644 t248-effects.txt diff --git a/hid-tmt248.c b/hid-tmt248.c index 1c51ba8..2881ffc 100644 --- a/hid-tmt248.c +++ b/hid-tmt248.c @@ -51,7 +51,80 @@ static const signed short t248_effects[] = { /* TODO: sort through this stuff */ static u8 t248_pc_rdesc_fixed[] = { -0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0x09, 0x01, 0xa1, 0x00, 0x85, 0x07, 0x09, 0x30, 0x15, 0x00, 0x27, 0xff, 0xff, 0x00, 0x00, 0x35, 0x00, 0x47, 0xff, 0xff, 0x00, 0x00, 0x75, 0x10, 0x95, 0x01, 0x81, 0x02, 0x09, 0x31, 0x26, 0xff, 0x03, 0x46, 0xff, 0x03, 0x81, 0x02, 0x09, 0x35, 0x81, 0x02, 0x09, 0x36, 0x81, 0x02, 0x75, 0x08, 0x26, 0xff, 0x00, 0x46, 0xff, 0x00, 0x09, 0x40, 0x81, 0x02, 0x09, 0x41, 0x81, 0x02, 0x09, 0x33, 0x81, 0x02, 0x09, 0x34, 0x81, 0x02, 0x09, 0x32, 0x81, 0x02, 0x09, 0x37, 0x81, 0x02, 0x05, 0x09, 0x19, 0x01, 0x29, 0x1a, 0x25, 0x01, 0x45, 0x01, 0x75, 0x01, 0x95, 0x1a, 0x81, 0x02, 0x75, 0x06, 0x95, 0x01, 0x81, 0x03, 0x05, 0x01, 0x09, 0x39, 0x25, 0x07, 0x46, 0x3b, 0x01, 0x55, 0x00, 0x65, 0x14, 0x75, 0x04, 0x81, 0x42, 0x65, 0x00, 0x81, 0x03, 0x85, 0x0a, 0x06, 0x00, 0xff, 0x09, 0x0a, 0x75, 0x08, 0x95, 0x3f, 0x26, 0xff, 0x00, 0x46, 0xff, 0x00, 0x91, 0x02, 0x85, 0x02, 0x09, 0x02, 0x81, 0x02, 0x09, 0x14, 0x85, 0x14 0x81, 0x02, 0xc0, 0xc0 + 0x05, 0x01, /* Usage page (Generic Desktop) */ + 0x09, 0x04, /* Usage (Joystick) */ + 0xa1, 0x01, /* Collection (Application) */ + 0x09, 0x01, /* Usage (Pointer) */ + 0xa1, 0x00, /* Collection (Physical) */ + 0x85, 0x07, /* Report ID (7) */ + 0x09, 0x30, /* Usage (X) */ + 0x15, 0x00, /* Logical minimum (0) */ + 0x27, 0xff, 0xff, 0x00, 0x00, /* Logical maximum (65535) */ + 0x35, 0x00, /* Physical minimum (0) */ + 0x47, 0xff, 0xff, 0x00, 0x00, /* Physical maximum (65535) */ + 0x75, 0x10, /* Report size (16) */ + 0x95, 0x01, /* Report count (1) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x31, /* Usage (Y) TODO: clutch? */ + 0x26, 0xff, 0x03, /* Logical maximum (1023) */ + 0x46, 0xff, 0x03, /* Physical maximum (1023) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x35, /* Usage (Rz) TODO: brake? */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x36, /* Usage (Slider) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x75, 0x08, /* Report size (8) */ + 0x26, 0xff, 0x00, /* Logical maximum (255) */ + 0x46, 0xff, 0x00, /* Physical maximum (255) */ + 0x09, 0x40, /* Usage (Vx) TODO: what is this? */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x41, /* Usage (Vy) TODO: --||-- */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x33, /* Usage (Rx) TODO: --||-- */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x34, /* Usage (Ry) TODO: --||-- */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x32, /* Usage (Z) TODO: --||-- (gas?) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x37, /* Usage (Dial) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x05, 0x09, /* Usage page (Button) */ + 0x19, 0x01, /* Usage minimum (1) */ + 0x29, 0x1a, /* Usage maximum (13) */ + 0x25, 0x01, /* Logical maximum (1) */ + 0x45, 0x01, /* Physical maximum (1) */ + 0x75, 0x01, /* Report size (1) */ + 0x95, 0x1a, /* Report count (26) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x75, 0x06, /* Report size (6) */ + 0x95, 0x01, /* Report count (1) */ + 0x81, 0x03, /* Usage (Variable, Absolute, Constant) */ + 0x05, 0x01, /* Usage page (Generic Desktop) */ + 0x09, 0x39, /* Usage (Hat Switch) */ + 0x25, 0x07, /* Logical maximum (7) */ + 0x46, 0x3b, 0x01, /* Physical maximum (315) */ + 0x55, 0x00, /* Unit exponent (0) */ + 0x65, 0x14, /* Unit (Eng rot, Angular Pos) */ + 0x75, 0x04, /* Report size (4) */ + 0x81, 0x42, /* Input (Variable, Absolute, NullState) */ + 0x65, 0x00, /* Input (None) */ + 0x81, 0x03, /* Input (Variable, Absolute, Constant) */ + 0x85, 0x60, /* Report ID (96), prev 10 */ + 0x06, 0x00, 0xff, /* Usage page (Vendor 1) */ + 0x09, 0x60, /* Usage (96), prev 10 */ + 0x75, 0x08, /* Report size (8) */ + 0x95, 0x3f, /* Report count (63) */ + 0x26, 0xff, 0x00, /* Logical maximum (256) */ + 0x46, 0xff, 0x00, /* Physical maximum (256) */ + 0x91, 0x02, /* Output (Variable, Absolute) */ + 0x85, 0x02, /* Report ID (2) */ + 0x09, 0x02, /* Usage (2) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0x09, 0x14, /* Usage (20) */ + 0x85, 0x14, /* Report ID (20) */ + 0x81, 0x02, /* Input (Variable, Absolute) */ + 0xc0, /* End collection */ + 0xc0, /* End collection */ }; static int t248_interrupts(struct t300rs_device_entry *t248) @@ -185,6 +258,14 @@ static int t248_close(void *data) return 0; } +static __u8 *t248_wheel_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) +{ + rdesc = t248_pc_rdesc_fixed; + *rsize = sizeof(t248_pc_rdesc_fixed); + return rdesc; +} + int t248_populate_api(struct tmff2_device_entry *tmff2) { tmff2->play_effect = t300rs_play_effect; @@ -192,15 +273,17 @@ int t248_populate_api(struct tmff2_device_entry *tmff2) tmff2->update_effect = t300rs_update_effect; tmff2->stop_effect = t300rs_stop_effect; - tmff2->wheel_init = t248_wheel_init; - tmff2->wheel_destroy = t248_wheel_destroy; - - tmff2->open = t248_open; - tmff2->close = t248_close; tmff2->set_gain = t300rs_set_gain; + tmff2->set_autocenter = t300rs_set_autocenter; /* T248 only has 900 degree range, instead of T300RS 1080 */ tmff2->set_range = t248_set_range; - tmff2->set_autocenter = t300rs_set_autocenter; + tmff2->wheel_fixup = t248_wheel_fixup; + + tmff2->open = t248_open; + tmff2->close = t248_close; + + tmff2->wheel_init = t248_wheel_init; + tmff2->wheel_destroy = t248_wheel_destroy; return 0; } diff --git a/t248-effects.txt b/t248-effects.txt new file mode 100644 index 0000000..821fc7a --- /dev/null +++ b/t248-effects.txt @@ -0,0 +1,2 @@ +Open: Identical to T300 +Close: Identical to T300 -- cgit v1.3 From fed8081d45d05ecf2b557515e17a5005b90a7e96 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 23 Mar 2022 18:39:27 +0200 Subject: test open/close --- hid-tmff2.h | 3 +++ hid-tmt248.c | 18 ++++++++++++++++-- hid-tmt300rs.c | 4 ++-- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/hid-tmff2.h b/hid-tmff2.h index f474ca7..b396d78 100644 --- a/hid-tmff2.h +++ b/hid-tmff2.h @@ -128,4 +128,7 @@ int t300rs_set_gain(void *, uint16_t); int t300rs_set_range(void *, uint16_t); int t300rs_set_autocenter(void *, uint16_t); +int t300rs_send_buf(struct t300rs_device_entry *t300rs, u8 *send_buffer, size_t len); +int t300rs_send_int(struct t300rs_device_entry *t300rs); + #endif /* __HID_TMFF2_H */ diff --git a/hid-tmt248.c b/hid-tmt248.c index 2881ffc..f3d4700 100644 --- a/hid-tmt248.c +++ b/hid-tmt248.c @@ -243,7 +243,14 @@ static int t248_open(void *data) if (!t248) return -ENODEV; - /* TODO: send usb commands to actually open device */ + t248->send_buffer[0] = 0x01; + t248->send_buffer[1] = 0x04; + t300rs_send_int(t248); + + t248->send_buffer[0] = 0x01; + t248->send_buffer[1] = 0x05; + t300rs_send_int(t248); + return t248->open(t248->input_dev); } @@ -253,7 +260,14 @@ static int t248_close(void *data) if (!t248) return -ENODEV; - /* TODO: send usb commands to actually close device */ + t248->send_buffer[0] = 0x01; + t248->send_buffer[1] = 0x05; + t300rs_send_int(t248); + + t248->send_buffer[0] = 0x01; + t248->send_buffer[1] = 0x00; + t300rs_send_int(t248); + t248->close(t248->input_dev); return 0; } diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 92e9acd..167262c 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -340,7 +340,7 @@ static u8 damper_values[] = { 0x7f, 0x07 }; -static int t300rs_send_buf(struct t300rs_device_entry *t300rs, u8 *send_buffer, size_t len) +int t300rs_send_buf(struct t300rs_device_entry *t300rs, u8 *send_buffer, size_t len) { int i; /* check that send_buffer fits into our report */ @@ -359,7 +359,7 @@ static int t300rs_send_buf(struct t300rs_device_entry *t300rs, u8 *send_buffer, return 0; } -static int t300rs_send_int(struct t300rs_device_entry *t300rs) +int t300rs_send_int(struct t300rs_device_entry *t300rs) { t300rs_send_buf(t300rs, t300rs->send_buffer, t300rs->buffer_length); memset(t300rs->send_buffer, 0, t300rs->buffer_length); -- cgit v1.3 From 62412528ae90b37172675264d7129663a0341ccb Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 23 Mar 2022 22:39:07 +0200 Subject: fixed possible kernel oops when unplugging device --- hid-tmff2.c | 2 +- hid-tmff2.h | 4 ++-- hid-tmt248.c | 16 +++++++++------- hid-tmt300rs.c | 12 +++++++----- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/hid-tmff2.c b/hid-tmff2.c index 4aa6141..3cfd1ad 100644 --- a/hid-tmff2.c +++ b/hid-tmff2.c @@ -627,8 +627,8 @@ static void tmff2_remove(struct hid_device *hdev) if (tmff2->params & PARAM_ALT_MODE) device_remove_file(dev, &dev_attr_alt_mode); - tmff2->wheel_destroy(tmff2->data); hid_hw_stop(hdev); + tmff2->wheel_destroy(tmff2->data); kfree(tmff2->states); kfree(tmff2); diff --git a/hid-tmff2.h b/hid-tmff2.h index b396d78..4058cf7 100644 --- a/hid-tmff2.h +++ b/hid-tmff2.h @@ -79,7 +79,7 @@ struct tmff2_device_entry { /* optional callbacks */ int (*open)(void *data); - int (*close)(void *data); + int (*close)(void *data, int dev_accessible); int (*set_gain)(void *data, uint16_t gain); int (*set_range)(void *data, uint16_t range); int (*switch_mode)(void *data, uint16_t mode); @@ -123,7 +123,7 @@ int t300rs_update_effect(void *, struct tmff2_effect_state *); int t300rs_stop_effect(void *, struct tmff2_effect_state *); int t300rs_open(void *); -int t300rs_close(void *); +int t300rs_close(void *, int); int t300rs_set_gain(void *, uint16_t); int t300rs_set_range(void *, uint16_t); int t300rs_set_autocenter(void *, uint16_t); diff --git a/hid-tmt248.c b/hid-tmt248.c index f3d4700..839f670 100644 --- a/hid-tmt248.c +++ b/hid-tmt248.c @@ -254,19 +254,21 @@ static int t248_open(void *data) return t248->open(t248->input_dev); } -static int t248_close(void *data) +static int t248_close(void *data, int dev_accessible) { struct t300rs_device_entry *t248 = data; if (!t248) return -ENODEV; - t248->send_buffer[0] = 0x01; - t248->send_buffer[1] = 0x05; - t300rs_send_int(t248); + if (dev_accessible) { + t248->send_buffer[0] = 0x01; + t248->send_buffer[1] = 0x05; + t300rs_send_int(t248); - t248->send_buffer[0] = 0x01; - t248->send_buffer[1] = 0x00; - t300rs_send_int(t248); + t248->send_buffer[0] = 0x01; + t248->send_buffer[1] = 0x00; + t300rs_send_int(t248); + } t248->close(t248->input_dev); return 0; diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 167262c..c2a6c64 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -1303,7 +1303,7 @@ int t300rs_open(void *data) return t300rs->open(t300rs->input_dev); } -int t300rs_close(void *data) +int t300rs_close(void *data, int dev_accessible) { struct t300rs_device_entry *t300rs = data; struct t300rs_packet_close { @@ -1314,11 +1314,13 @@ int t300rs_close(void *data) if (!t300rs) return -ENODEV; - close_packet = (struct t300rs_packet_close *)t300rs->send_buffer; - close_packet->header.cmd = 0x01; + if (dev_accessible) { + close_packet = (struct t300rs_packet_close *)t300rs->send_buffer; + close_packet->header.cmd = 0x01; - if ((ret = t300rs_send_int(t300rs))) - hid_warn(t300rs->hdev, "failed sending close command\n"); + if ((ret = t300rs_send_int(t300rs))) + hid_warn(t300rs->hdev, "failed sending close command\n"); + } t300rs->close(t300rs->input_dev); return ret; -- cgit v1.3 From 3865f5c94cb90d16810b7e751fa79034321ea836 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 23 Mar 2022 22:39:07 +0200 Subject: fixed possible kernel oops when unplugging device --- hid-tmff2.c | 9 ++++++--- hid-tmff2.h | 4 ++-- hid-tmt248.c | 16 +++++++++------- hid-tmt300rs.c | 12 +++++++----- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/hid-tmff2.c b/hid-tmff2.c index 4aa6141..d632b09 100644 --- a/hid-tmff2.c +++ b/hid-tmff2.c @@ -408,7 +408,7 @@ static void tmff2_close(struct input_dev *dev) return; if (tmff2->close) { - tmff2->close(tmff2->data); + tmff2->close(tmff2->data, tmff2->hdev != 0); return; } @@ -524,6 +524,7 @@ static int tmff2_wheel_init(struct tmff2_device_entry *tmff2) return 0; + input_ff_destroy(tmff2->input_dev); err: return ret; } @@ -611,7 +612,6 @@ static void tmff2_remove(struct hid_device *hdev) if (!tmff2) return; - cancel_delayed_work_sync(&tmff2->work); dev = &tmff2->hdev->dev; @@ -627,8 +627,11 @@ static void tmff2_remove(struct hid_device *hdev) if (tmff2->params & PARAM_ALT_MODE) device_remove_file(dev, &dev_attr_alt_mode); - tmff2->wheel_destroy(tmff2->data); + /* indicate that the underlying usb device should not be assumed to be + * accessible */ + tmff2->hdev = 0; hid_hw_stop(hdev); + tmff2->wheel_destroy(tmff2->data); kfree(tmff2->states); kfree(tmff2); diff --git a/hid-tmff2.h b/hid-tmff2.h index b396d78..4058cf7 100644 --- a/hid-tmff2.h +++ b/hid-tmff2.h @@ -79,7 +79,7 @@ struct tmff2_device_entry { /* optional callbacks */ int (*open)(void *data); - int (*close)(void *data); + int (*close)(void *data, int dev_accessible); int (*set_gain)(void *data, uint16_t gain); int (*set_range)(void *data, uint16_t range); int (*switch_mode)(void *data, uint16_t mode); @@ -123,7 +123,7 @@ int t300rs_update_effect(void *, struct tmff2_effect_state *); int t300rs_stop_effect(void *, struct tmff2_effect_state *); int t300rs_open(void *); -int t300rs_close(void *); +int t300rs_close(void *, int); int t300rs_set_gain(void *, uint16_t); int t300rs_set_range(void *, uint16_t); int t300rs_set_autocenter(void *, uint16_t); diff --git a/hid-tmt248.c b/hid-tmt248.c index f3d4700..839f670 100644 --- a/hid-tmt248.c +++ b/hid-tmt248.c @@ -254,19 +254,21 @@ static int t248_open(void *data) return t248->open(t248->input_dev); } -static int t248_close(void *data) +static int t248_close(void *data, int dev_accessible) { struct t300rs_device_entry *t248 = data; if (!t248) return -ENODEV; - t248->send_buffer[0] = 0x01; - t248->send_buffer[1] = 0x05; - t300rs_send_int(t248); + if (dev_accessible) { + t248->send_buffer[0] = 0x01; + t248->send_buffer[1] = 0x05; + t300rs_send_int(t248); - t248->send_buffer[0] = 0x01; - t248->send_buffer[1] = 0x00; - t300rs_send_int(t248); + t248->send_buffer[0] = 0x01; + t248->send_buffer[1] = 0x00; + t300rs_send_int(t248); + } t248->close(t248->input_dev); return 0; diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 167262c..c2a6c64 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -1303,7 +1303,7 @@ int t300rs_open(void *data) return t300rs->open(t300rs->input_dev); } -int t300rs_close(void *data) +int t300rs_close(void *data, int dev_accessible) { struct t300rs_device_entry *t300rs = data; struct t300rs_packet_close { @@ -1314,11 +1314,13 @@ int t300rs_close(void *data) if (!t300rs) return -ENODEV; - close_packet = (struct t300rs_packet_close *)t300rs->send_buffer; - close_packet->header.cmd = 0x01; + if (dev_accessible) { + close_packet = (struct t300rs_packet_close *)t300rs->send_buffer; + close_packet->header.cmd = 0x01; - if ((ret = t300rs_send_int(t300rs))) - hid_warn(t300rs->hdev, "failed sending close command\n"); + if ((ret = t300rs_send_int(t300rs))) + hid_warn(t300rs->hdev, "failed sending close command\n"); + } t300rs->close(t300rs->input_dev); return ret; -- cgit v1.3 From 51623455c8136f40f47ad98a0532ea70dd1c99e4 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Thu, 24 Mar 2022 13:34:49 +0200 Subject: fix work handler being run after destruction --- hid-tmff2.c | 47 +++++++++++++++++++++++++++++++++++------------ hid-tmff2.h | 6 ++++-- hid-tmt248.c | 22 +++++++++++++--------- hid-tmt300rs.c | 12 +++++------- 4 files changed, 57 insertions(+), 30 deletions(-) diff --git a/hid-tmff2.c b/hid-tmff2.c index d632b09..fe4950d 100644 --- a/hid-tmff2.c +++ b/hid-tmff2.c @@ -43,10 +43,10 @@ static struct tmff2_device_entry *tmff2_from_hdev(struct hid_device *hdev) { struct tmff2_device_entry *tmff2; spin_lock_irqsave(&lock, lock_flags); - if (!(tmff2 = hid_get_drvdata(hdev))) { + + if (!(tmff2 = hid_get_drvdata(hdev))) dev_err(&hdev->dev, "hdev private data not found\n"); - return NULL; - } + spin_unlock_irqrestore(&lock, lock_flags); return tmff2; @@ -56,10 +56,10 @@ static struct tmff2_device_entry *tmff2_from_input(struct input_dev *input_dev) { struct hid_device *hdev; spin_lock_irqsave(&lock, lock_flags); - if (!(hdev = input_get_drvdata(input_dev))) { + + if (!(hdev = input_get_drvdata(input_dev))) dev_err(&input_dev->dev, "input_dev private data not found\n"); - return NULL; - } + spin_unlock_irqrestore(&lock, lock_flags); return tmff2_from_hdev(hdev); @@ -90,6 +90,7 @@ static ssize_t spring_level_store(struct device *dev, static ssize_t spring_level_show(struct device *dev, struct device_attribute *attr, char *buf) { + return scnprintf(buf, PAGE_SIZE, "%u\n", spring_level); } static DEVICE_ATTR_RW(spring_level); @@ -100,6 +101,7 @@ static ssize_t damper_level_store(struct device *dev, unsigned int value; int ret; + ret = kstrtouint(buf, 0, &value); if (ret) { dev_err(dev, "kstrtouint failed at damper_level_store: %i", ret); @@ -119,6 +121,7 @@ static ssize_t damper_level_store(struct device *dev, static ssize_t damper_level_show(struct device *dev, struct device_attribute *attr, char *buf) { + return scnprintf(buf, PAGE_SIZE, "%u\n", damper_level); } static DEVICE_ATTR_RW(damper_level); @@ -129,6 +132,7 @@ static ssize_t friction_level_store(struct device *dev, unsigned int value; int ret; + ret = kstrtouint(buf, 0, &value); if (ret) { dev_err(dev, "kstrtouint failed at friction_level_store: %i", ret); @@ -150,6 +154,7 @@ static ssize_t friction_level_show(struct device *dev, { size_t count; + count = scnprintf(buf, PAGE_SIZE, "%u\n", friction_level); return count; @@ -163,6 +168,7 @@ static ssize_t range_store(struct device *dev, unsigned int value; int ret; + if (!tmff2) return -ENODEV; @@ -182,6 +188,7 @@ static ssize_t range_store(struct device *dev, static ssize_t range_show(struct device *dev, struct device_attribute *attr, char *buf) { + return scnprintf(buf, PAGE_SIZE, "%u\n", range); } static DEVICE_ATTR_RW(range); @@ -193,6 +200,7 @@ static ssize_t alt_mode_store(struct device *dev, unsigned int value; int ret; + if (!tmff2) return -ENODEV; @@ -215,6 +223,7 @@ static ssize_t alt_mode_show(struct device *dev, /* TODO: could be cool to add in something like a small menu that gives * names and corresponding index to modes, or maybe parsing modes * directly? */ + return scnprintf(buf, PAGE_SIZE, "%i\n", alt_mode); } static DEVICE_ATTR_RW(alt_mode); @@ -222,6 +231,7 @@ static DEVICE_ATTR_RW(alt_mode); static void tmff2_set_gain(struct input_dev *dev, uint16_t gain) { struct tmff2_device_entry *tmff2 = tmff2_from_input(dev); + if (!tmff2) return; @@ -237,6 +247,7 @@ static void tmff2_set_gain(struct input_dev *dev, uint16_t gain) static void tmff2_set_autocenter(struct input_dev *dev, uint16_t autocenter) { struct tmff2_device_entry *tmff2 = tmff2_from_input(dev); + if (!tmff2) return; @@ -258,6 +269,7 @@ static void tmff2_work_handler(struct work_struct *w) unsigned long time_now; __u16 effect_length; + if (!tmff2) return; @@ -324,7 +336,7 @@ static void tmff2_work_handler(struct work_struct *w) spin_unlock(&tmff2->lock); } - if (max_count) + if (max_count && tmff2->allow_scheduling) schedule_delayed_work(&tmff2->work, msecs_to_jiffies(timer_msecs)); } @@ -333,6 +345,7 @@ static int tmff2_upload(struct input_dev *dev, { struct tmff2_effect_state *state; struct tmff2_device_entry *tmff2 = tmff2_from_input(dev); + if (!tmff2) return -ENODEV; @@ -362,6 +375,7 @@ static int tmff2_play(struct input_dev *dev, int effect_id, int value) { struct tmff2_effect_state *state; struct tmff2_device_entry *tmff2 = tmff2_from_input(dev); + if (!tmff2) return -ENODEV; @@ -382,7 +396,7 @@ static int tmff2_play(struct input_dev *dev, int effect_id, int value) spin_unlock(&tmff2->lock); - if (!delayed_work_pending(&tmff2->work)) + if (!delayed_work_pending(&tmff2->work) && tmff2->allow_scheduling) schedule_delayed_work(&tmff2->work, 0); return 0; @@ -391,6 +405,7 @@ static int tmff2_play(struct input_dev *dev, int effect_id, int value) static int tmff2_open(struct input_dev *dev) { struct tmff2_device_entry *tmff2 = tmff2_from_input(dev); + if (!tmff2) return -ENODEV; @@ -404,11 +419,15 @@ static int tmff2_open(struct input_dev *dev) static void tmff2_close(struct input_dev *dev) { struct tmff2_device_entry *tmff2 = tmff2_from_input(dev); + if (!tmff2) return; + /* since we're closing the device, no need to continue feeding it new data */ + cancel_delayed_work_sync(&tmff2->work); + if (tmff2->close) { - tmff2->close(tmff2->data, tmff2->hdev != 0); + tmff2->close(tmff2->data); return; } @@ -420,6 +439,7 @@ static int tmff2_create_files(struct tmff2_device_entry *tmff2) struct device *dev = &tmff2->hdev->dev; int ret; + /* could use short circuiting but this is more explicit */ if (tmff2->params & PARAM_ALT_MODE) { if ((ret = device_create_file(dev, &dev_attr_alt_mode))) { @@ -474,6 +494,7 @@ static int tmff2_wheel_init(struct tmff2_device_entry *tmff2) { int ret, i; struct ff_device *ff; + spin_lock_init(&lock); spin_lock_init(&tmff2->lock); INIT_DELAYED_WORK(&tmff2->work, tmff2_work_handler); @@ -522,6 +543,7 @@ static int tmff2_wheel_init(struct tmff2_device_entry *tmff2) if ((ret = tmff2_create_files(tmff2))) goto err; + tmff2->allow_scheduling = 1; return 0; input_ff_destroy(tmff2->input_dev); @@ -536,6 +558,7 @@ static int tmff2_probe(struct hid_device *hdev, const struct hid_device_id *id) int ret; + if (!tmff2) { ret = -ENOMEM; goto oom_err; @@ -596,6 +619,7 @@ static __u8 *tmff2_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { struct tmff2_device_entry *tmff2 = tmff2_from_hdev(hdev); + if (!tmff2) /* not entirely sure what the best course of action would be here */ return rdesc; @@ -609,9 +633,11 @@ static void tmff2_remove(struct hid_device *hdev) { struct tmff2_device_entry *tmff2 = tmff2_from_hdev(hdev); struct device *dev; + if (!tmff2) return; + tmff2->allow_scheduling = 0; cancel_delayed_work_sync(&tmff2->work); dev = &tmff2->hdev->dev; @@ -627,9 +653,6 @@ static void tmff2_remove(struct hid_device *hdev) if (tmff2->params & PARAM_ALT_MODE) device_remove_file(dev, &dev_attr_alt_mode); - /* indicate that the underlying usb device should not be assumed to be - * accessible */ - tmff2->hdev = 0; hid_hw_stop(hdev); tmff2->wheel_destroy(tmff2->data); diff --git a/hid-tmff2.h b/hid-tmff2.h index 4058cf7..390bd94 100644 --- a/hid-tmff2.h +++ b/hid-tmff2.h @@ -62,6 +62,8 @@ struct tmff2_device_entry { spinlock_t lock; + int allow_scheduling; + /* fields relevant to each actual device (T300, T150...) */ void *data; unsigned long params; @@ -79,7 +81,7 @@ struct tmff2_device_entry { /* optional callbacks */ int (*open)(void *data); - int (*close)(void *data, int dev_accessible); + int (*close)(void *data); int (*set_gain)(void *data, uint16_t gain); int (*set_range)(void *data, uint16_t range); int (*switch_mode)(void *data, uint16_t mode); @@ -123,7 +125,7 @@ int t300rs_update_effect(void *, struct tmff2_effect_state *); int t300rs_stop_effect(void *, struct tmff2_effect_state *); int t300rs_open(void *); -int t300rs_close(void *, int); +int t300rs_close(void *); int t300rs_set_gain(void *, uint16_t); int t300rs_set_range(void *, uint16_t); int t300rs_set_autocenter(void *, uint16_t); diff --git a/hid-tmt248.c b/hid-tmt248.c index 839f670..aef2944 100644 --- a/hid-tmt248.c +++ b/hid-tmt248.c @@ -133,6 +133,7 @@ static int t248_interrupts(struct t300rs_device_entry *t248) struct usb_interface *usbif = to_usb_interface(t248->hdev->dev.parent); struct usb_host_endpoint *ep; int ret, trans, b_ep, i; + if (!send_buf) { hid_err(t248->hdev, "failed allocating send buffer\n"); return -ENOMEM; @@ -167,6 +168,7 @@ int t248_wheel_init(struct tmff2_device_entry *tmff2) struct list_head *report_list; int ret; + if (!t248) { ret = -ENOMEM; goto t248_err; @@ -213,6 +215,7 @@ t248_err: int t248_wheel_destroy(void *data) { struct t300rs_device_entry *t300rs = data; + if (!t300rs) return -ENODEV; @@ -224,6 +227,7 @@ int t248_wheel_destroy(void *data) int t248_set_range(void *data, uint16_t value) { struct t300rs_device_entry *t248 = data; + if (value < 140) { hid_info(t248->hdev, "value %i too small, clamping to 140\n", value); value = 140; @@ -240,6 +244,7 @@ int t248_set_range(void *data, uint16_t value) static int t248_open(void *data) { struct t300rs_device_entry *t248 = data; + if (!t248) return -ENODEV; @@ -254,21 +259,20 @@ static int t248_open(void *data) return t248->open(t248->input_dev); } -static int t248_close(void *data, int dev_accessible) +static int t248_close(void *data) { struct t300rs_device_entry *t248 = data; + if (!t248) return -ENODEV; - if (dev_accessible) { - t248->send_buffer[0] = 0x01; - t248->send_buffer[1] = 0x05; - t300rs_send_int(t248); + t248->send_buffer[0] = 0x01; + t248->send_buffer[1] = 0x05; + t300rs_send_int(t248); - t248->send_buffer[0] = 0x01; - t248->send_buffer[1] = 0x00; - t300rs_send_int(t248); - } + t248->send_buffer[0] = 0x01; + t248->send_buffer[1] = 0x00; + t300rs_send_int(t248); t248->close(t248->input_dev); return 0; diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index c2a6c64..167262c 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -1303,7 +1303,7 @@ int t300rs_open(void *data) return t300rs->open(t300rs->input_dev); } -int t300rs_close(void *data, int dev_accessible) +int t300rs_close(void *data) { struct t300rs_device_entry *t300rs = data; struct t300rs_packet_close { @@ -1314,13 +1314,11 @@ int t300rs_close(void *data, int dev_accessible) if (!t300rs) return -ENODEV; - if (dev_accessible) { - close_packet = (struct t300rs_packet_close *)t300rs->send_buffer; - close_packet->header.cmd = 0x01; + close_packet = (struct t300rs_packet_close *)t300rs->send_buffer; + close_packet->header.cmd = 0x01; - if ((ret = t300rs_send_int(t300rs))) - hid_warn(t300rs->hdev, "failed sending close command\n"); - } + if ((ret = t300rs_send_int(t300rs))) + hid_warn(t300rs->hdev, "failed sending close command\n"); t300rs->close(t300rs->input_dev); return ret; -- cgit v1.3 From 2814c3eb42a0ed97d40a42aaefa1bfcd79781bdc Mon Sep 17 00:00:00 2001 From: Kimplul Date: Thu, 24 Mar 2022 20:43:42 +0200 Subject: add master gain --- hid-tmff2.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ hid-tmff2.h | 2 ++ hid-tmt248.c | 1 + hid-tmt300rs.c | 1 + 4 files changed, 64 insertions(+), 7 deletions(-) diff --git a/hid-tmff2.c b/hid-tmff2.c index fe4950d..f5202ae 100644 --- a/hid-tmff2.c +++ b/hid-tmff2.c @@ -29,12 +29,18 @@ MODULE_PARM_DESC(friction_level, int range = 900; module_param(range, int, 0); MODULE_PARM_DESC(range, - "Range of wheel, depends on the wheel. Invalid values are ignored."); + "Range of wheel, depends on the wheel. Invalid values are ignored"); int alt_mode = 0; module_param(alt_mode, int, 0); MODULE_PARM_DESC(alt_mode, - "Alternate mode, eg. F1 mode."); + "Alternate mode, eg. F1 mode"); + +#define GAIN_MAX 65535 +int gain = 40000; +module_param(gain, int, 0); +MODULE_PARM_DESC(gain, + "Level of gain (0-65535)"); static spinlock_t lock; static unsigned long lock_flags; @@ -228,7 +234,36 @@ static ssize_t alt_mode_show(struct device *dev, } static DEVICE_ATTR_RW(alt_mode); -static void tmff2_set_gain(struct input_dev *dev, uint16_t gain) +static ssize_t gain_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct tmff2_device_entry *tmff2 = tmff2_from_hdev(to_hid_device(dev)); + unsigned int value; + int ret; + + if (!tmff2) + return -ENODEV; + + if ((ret = kstrtouint(buf, 0, &value))) { + dev_err(dev, "kstrtouint failed at gain_store: %i", ret); + return ret; + } + + gain = value; + if (tmff2->set_gain) /* if we can, update gain immediately */ + tmff2->set_gain(tmff2->data, (GAIN_MAX * gain) / GAIN_MAX); + + return count; +} + +static ssize_t gain_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%i\n", gain); +} +static DEVICE_ATTR_RW(gain); + +static void tmff2_set_gain(struct input_dev *dev, uint16_t value) { struct tmff2_device_entry *tmff2 = tmff2_from_input(dev); @@ -240,11 +275,11 @@ static void tmff2_set_gain(struct input_dev *dev, uint16_t gain) return; } - if (tmff2->set_gain(tmff2->data, gain)) + if (tmff2->set_gain(tmff2->data, (value * gain) / GAIN_MAX)) hid_warn(tmff2->hdev, "unable to set gain\n"); } -static void tmff2_set_autocenter(struct input_dev *dev, uint16_t autocenter) +static void tmff2_set_autocenter(struct input_dev *dev, uint16_t value) { struct tmff2_device_entry *tmff2 = tmff2_from_input(dev); @@ -256,7 +291,7 @@ static void tmff2_set_autocenter(struct input_dev *dev, uint16_t autocenter) return; } - if (tmff2->set_autocenter(tmff2->data, autocenter)) + if (tmff2->set_autocenter(tmff2->data, value)) hid_warn(tmff2->hdev, "unable to set autocenter\n"); } @@ -441,6 +476,13 @@ static int tmff2_create_files(struct tmff2_device_entry *tmff2) /* could use short circuiting but this is more explicit */ + if (tmff2->params & PARAM_GAIN) { + if ((ret = device_create_file(dev, &dev_attr_gain))) { + hid_err(tmff2->hdev, "unable to create sysfs for gain\n"); + goto gain_err; + } + } + if (tmff2->params & PARAM_ALT_MODE) { if ((ret = device_create_file(dev, &dev_attr_alt_mode))) { hid_err(tmff2->hdev, "unable to create sysfs for alt_mode\n"); @@ -487,6 +529,8 @@ spring_err: range_err: device_remove_file(dev, &dev_attr_alt_mode); alt_err: + device_remove_file(dev, &dev_attr_gain); +gain_err: return ret; } @@ -533,12 +577,18 @@ static int tmff2_wheel_init(struct tmff2_device_entry *tmff2) if (tmff2->close) tmff2->input_dev->close = tmff2_close; - if (tmff2->set_gain) + /* set defaults wherever possible */ + if (tmff2->set_gain) { ff->set_gain = tmff2_set_gain; + tmff2->set_gain(tmff2->data, (GAIN_MAX * gain) / GAIN_MAX); + } if (tmff2->set_autocenter) ff->set_autocenter = tmff2_set_autocenter; + if (tmff2->set_range) + tmff2->set_range(tmff2->data, range); + /* create files */ if ((ret = tmff2_create_files(tmff2))) goto err; @@ -653,6 +703,9 @@ static void tmff2_remove(struct hid_device *hdev) if (tmff2->params & PARAM_ALT_MODE) device_remove_file(dev, &dev_attr_alt_mode); + if (tmff2->params & PARAM_GAIN) + device_remove_file(dev, &dev_attr_gain); + hid_hw_stop(hdev); tmff2->wheel_destroy(tmff2->data); diff --git a/hid-tmff2.h b/hid-tmff2.h index 390bd94..765f071 100644 --- a/hid-tmff2.h +++ b/hid-tmff2.h @@ -11,6 +11,7 @@ extern int spring_level; extern int damper_level; extern int friction_level; extern int range; +extern int gain; extern int alt_mode; #define USB_VENDOR_ID_THRUSTMASTER 0x044f @@ -34,6 +35,7 @@ extern int alt_mode; #define PARAM_FRICTION_LEVEL (1 << 2) #define PARAM_RANGE (1 << 3) #define PARAM_ALT_MODE (1 << 4) +#define PARAM_GAIN (1 << 5) #undef fixp_sin16 #define fixp_sin16(v) (((v % 360) > 180) ?\ diff --git a/hid-tmt248.c b/hid-tmt248.c index aef2944..e241301 100644 --- a/hid-tmt248.c +++ b/hid-tmt248.c @@ -29,6 +29,7 @@ static const unsigned long t248_params = | PARAM_DAMPER_LEVEL | PARAM_FRICTION_LEVEL | PARAM_RANGE + | PARAM_GAIN ; static const signed short t248_effects[] = { diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 167262c..5e4a848 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -11,6 +11,7 @@ static const unsigned long t300rs_params = PARAM_SPRING_LEVEL | PARAM_DAMPER_LEVEL | PARAM_FRICTION_LEVEL + | PARAM_GAIN | PARAM_RANGE | PARAM_ALT_MODE ; -- cgit v1.3 From 41c46e46415bfe9d393a5a3858f0c58f0a914c6b Mon Sep 17 00:00:00 2001 From: Kimplul Date: Fri, 25 Mar 2022 14:14:18 +0200 Subject: change alternate mode handling --- hid-tmff2.c | 45 ++++++++++++++++------------------ hid-tmff2.h | 5 ++++ hid-tmt300rs.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 100 insertions(+), 27 deletions(-) diff --git a/hid-tmff2.c b/hid-tmff2.c index f5202ae..12e8e25 100644 --- a/hid-tmff2.c +++ b/hid-tmff2.c @@ -199,40 +199,34 @@ static ssize_t range_show(struct device *dev, } static DEVICE_ATTR_RW(range); -static ssize_t alt_mode_store(struct device *dev, +static ssize_t alternate_modes_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct tmff2_device_entry *tmff2 = tmff2_from_hdev(to_hid_device(dev)); - unsigned int value; - int ret; - if (!tmff2) return -ENODEV; - if ((ret = kstrtouint(buf, 0, &value))) { - hid_err(tmff2->hdev, "kstrtouint failed at alt_mode_store: %i", ret); - return ret; - } - - if (tmff2->switch_mode) { - if ((ret = tmff2->switch_mode(tmff2->data, value))) - return ret; - } + if (tmff2->alt_mode_store) + return tmff2->alt_mode_store(tmff2->data, buf, count); - return count; + return 0; } -static ssize_t alt_mode_show(struct device *dev, +static ssize_t alternate_modes_show(struct device *dev, struct device_attribute *attr, char *buf) { - /* TODO: could be cool to add in something like a small menu that gives - * names and corresponding index to modes, or maybe parsing modes - * directly? */ + struct tmff2_device_entry *tmff2 = tmff2_from_hdev(to_hid_device(dev)); - return scnprintf(buf, PAGE_SIZE, "%i\n", alt_mode); + if (!tmff2) + return -ENODEV; + + if (tmff2->alt_mode_show) + return tmff2->alt_mode_show(tmff2->data, buf); + + return 0; } -static DEVICE_ATTR_RW(alt_mode); +static DEVICE_ATTR_RW(alternate_modes); static ssize_t gain_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -484,8 +478,8 @@ static int tmff2_create_files(struct tmff2_device_entry *tmff2) } if (tmff2->params & PARAM_ALT_MODE) { - if ((ret = device_create_file(dev, &dev_attr_alt_mode))) { - hid_err(tmff2->hdev, "unable to create sysfs for alt_mode\n"); + if ((ret = device_create_file(dev, &dev_attr_alternate_modes))) { + hid_err(tmff2->hdev, "unable to create sysfs for alternate_modes\n"); goto alt_err; } } @@ -527,7 +521,7 @@ damper_err: spring_err: device_remove_file(dev, &dev_attr_range); range_err: - device_remove_file(dev, &dev_attr_alt_mode); + device_remove_file(dev, &dev_attr_alternate_modes); alt_err: device_remove_file(dev, &dev_attr_gain); gain_err: @@ -589,6 +583,9 @@ static int tmff2_wheel_init(struct tmff2_device_entry *tmff2) if (tmff2->set_range) tmff2->set_range(tmff2->data, range); + if (tmff2->switch_mode) + tmff2->switch_mode(tmff2->data, alt_mode); + /* create files */ if ((ret = tmff2_create_files(tmff2))) goto err; @@ -701,7 +698,7 @@ static void tmff2_remove(struct hid_device *hdev) device_remove_file(dev, &dev_attr_range); if (tmff2->params & PARAM_ALT_MODE) - device_remove_file(dev, &dev_attr_alt_mode); + device_remove_file(dev, &dev_attr_alternate_modes); if (tmff2->params & PARAM_GAIN) device_remove_file(dev, &dev_attr_gain); diff --git a/hid-tmff2.h b/hid-tmff2.h index 765f071..a57b434 100644 --- a/hid-tmff2.h +++ b/hid-tmff2.h @@ -86,7 +86,11 @@ struct tmff2_device_entry { int (*close)(void *data); int (*set_gain)(void *data, uint16_t gain); int (*set_range)(void *data, uint16_t range); + /* switch_mode has to not do anything if we're alredy in the specified + * mode */ int (*switch_mode)(void *data, uint16_t mode); + ssize_t (*alt_mode_show)(void *data, char *buf); + ssize_t (*alt_mode_store)(void *data, const char *buf, size_t count); int (*set_autocenter)(void *data, uint16_t autocenter); __u8 *(*wheel_fixup)(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize); @@ -117,6 +121,7 @@ struct t300rs_device_entry { int (*open)(struct input_dev *dev); void (*close)(struct input_dev *dev); + int mode; u8 buffer_length; u8 *send_buffer; }; diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 5e4a848..687832f 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -1167,25 +1167,94 @@ static int t300rs_switch_mode(void *data, uint16_t mode) if (!t300rs) return -ENODEV; - if(alt_mode == mode) /* already in specified mode */ + if(t300rs->mode == mode) /* already in specified mode */ return 0; if (mode == 0) + /* go to normal mode */ usb_control_msg(t300rs->usbdev, usb_sndctrlpipe(t300rs->usbdev, 0), 83, 0x41, 5, 0, 0, 0, USB_CTRL_SET_TIMEOUT ); - else + else if (mode == 1) + /* go to advanced mode */ usb_control_msg(t300rs->usbdev, usb_sndctrlpipe(t300rs->usbdev, 0), 83, 0x41, 3, 0, 0, 0, USB_CTRL_SET_TIMEOUT ); + else + hid_warn(t300rs->hdev, "mode %i not supported\n", mode); + return 0; } +static struct t300rs_alt_modes { + char *id; + char *label; + uint16_t mode; +} t300rs_modes[] = { + {"native", "T300RS base", 0}, + {"F1", "T300RS with F1 wheel attachment", 1} +}; + +static ssize_t t300rs_alt_mode_show(void *data, char *buf) +{ + struct t300rs_device_entry *t300rs = data; + ssize_t count = 0; + int i; + if (!t300rs) + return -ENODEV; + + for (i = 0; i < ARRAY_SIZE(t300rs_modes); ++i) { + count += scnprintf(buf + count, PAGE_SIZE - count, "%s: %s", + t300rs_modes[i].id, t300rs_modes[i].label); + + if (count >= PAGE_SIZE - 1) + return count; + + if (t300rs_modes[i].mode == t300rs->mode) + count += scnprintf(buf + count, PAGE_SIZE - count, " *\n"); + else + count += scnprintf(buf + count, PAGE_SIZE - count, "\n"); + + if (count >= PAGE_SIZE - 1) + return count; + } + + return count; +} + +static ssize_t t300rs_alt_mode_store(void *data, const char *buf, size_t count) +{ + struct tmff2_device_entry *t300rs = data; + int i, len, mode_len; + char *lbuf; + if (!t300rs) + return -ENODEV; + + lbuf = kasprintf(GFP_KERNEL, "%s", buf); + if (!lbuf) + return -ENOMEM; + + len = strlen(buf); + for (i = 0; i < ARRAY_SIZE(t300rs_modes); ++i) { + mode_len = strlen(t300rs_modes[i].id); + if (mode_len > len) + continue; + + if (strncmp(lbuf, t300rs_modes[i].id, mode_len) == 0) { + t300rs_switch_mode(data, t300rs_modes[i].mode); + break; + } + } + + kfree(lbuf); + return count; +} + int t300rs_set_autocenter(void *data, uint16_t value) { struct t300rs_device_entry *t300rs = data; @@ -1413,7 +1482,7 @@ static int t300rs_wheel_init(struct tmff2_device_entry *tmff2) t300rs->close = t300rs->input_dev->close; /* TODO: PS4 advanced mode? */ - alt_mode = (t300rs->hdev->product == TMT300RS_PS3_ADV_ID); + t300rs->mode = (t300rs->hdev->product == TMT300RS_PS3_ADV_ID); /* everythin went OK */ tmff2->data = t300rs; @@ -1486,6 +1555,8 @@ int t300rs_populate_api(struct tmff2_device_entry *tmff2) tmff2->set_gain = t300rs_set_gain; tmff2->set_range = t300rs_set_range; tmff2->switch_mode = t300rs_switch_mode; + tmff2->alt_mode_show = t300rs_alt_mode_show; + tmff2->alt_mode_store = t300rs_alt_mode_store; tmff2->set_autocenter = t300rs_set_autocenter; tmff2->wheel_fixup = t300rs_wheel_fixup; -- cgit v1.3 From bb853865fce78d062186c808dc63fcfe12ebf195 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Fri, 25 Mar 2022 15:23:59 +0200 Subject: allow only specific attachments to change mode --- hid-tmff2.h | 1 + hid-tmt300rs.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/hid-tmff2.h b/hid-tmff2.h index a57b434..d5de938 100644 --- a/hid-tmff2.h +++ b/hid-tmff2.h @@ -122,6 +122,7 @@ struct t300rs_device_entry { void (*close)(struct input_dev *dev); int mode; + int attachment; u8 buffer_length; u8 *send_buffer; }; diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 687832f..c5b4655 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -7,6 +7,9 @@ #define T300RS_NORM_BUFFER_LENGTH 63 #define T300RS_PS4_BUFFER_LENGTH 31 +#define T300RS_DEFAULT_ATTACHMENT 0x06 +#define T300RS_F1_ATTACHMENT 0x03 + static const unsigned long t300rs_params = PARAM_SPRING_LEVEL | PARAM_DAMPER_LEVEL @@ -1208,6 +1211,11 @@ static ssize_t t300rs_alt_mode_show(void *data, char *buf) if (!t300rs) return -ENODEV; + if (t300rs->attachment != T300RS_F1_ATTACHMENT) + /* we only support one native mode */ + return scnprintf(buf, PAGE_SIZE, "%s: %s *\n", + t300rs_modes[0].id, t300rs_modes[0].label); + for (i = 0; i < ARRAY_SIZE(t300rs_modes); ++i) { count += scnprintf(buf + count, PAGE_SIZE - count, "%s: %s", t300rs_modes[i].id, t300rs_modes[i].label); @@ -1229,12 +1237,15 @@ static ssize_t t300rs_alt_mode_show(void *data, char *buf) static ssize_t t300rs_alt_mode_store(void *data, const char *buf, size_t count) { - struct tmff2_device_entry *t300rs = data; + struct t300rs_device_entry *t300rs = data; int i, len, mode_len; char *lbuf; if (!t300rs) return -ENODEV; + if (t300rs->attachment != T300RS_F1_ATTACHMENT) + return count; /* don't do anything */ + lbuf = kasprintf(GFP_KERNEL, "%s", buf); if (!lbuf) return -ENOMEM; @@ -1443,6 +1454,79 @@ out: return ret; } +static int t300rs_get_attachment(struct t300rs_device_entry *t300rs) +{ + /* taken directly from hid_tminit */ + struct __packed t300rs_attachment_response + { + uint16_t type; + + union { + struct __packed { + uint16_t field0; + uint16_t field1; + uint8_t attachment; + uint8_t model; + uint16_t field2; + uint16_t field3; + uint16_t field4; + uint16_t field5; + } a; + + struct __packed { + uint16_t field0; + uint16_t field1; + uint8_t attachment; + uint8_t model; + } b; + }; + } *response = kzalloc(GFP_KERNEL, sizeof(struct t300rs_attachment_response)); + struct usb_ctrlrequest t300rs_attachment_rq = { + .bRequestType = 0xc1, + .bRequest = 73, + .wValue = 0, + .wIndex = 0, + .wLength = sizeof(struct t300rs_attachment_response) + }; + int ret, attachment; + if (!response) + return -ENODEV; + + ret = usb_control_msg(t300rs->usbdev, + usb_rcvctrlpipe(t300rs->usbdev, 0), + t300rs_attachment_rq.bRequest, + t300rs_attachment_rq.bRequestType, + t300rs_attachment_rq.wValue, + t300rs_attachment_rq.wIndex, + response, + sizeof(struct t300rs_attachment_response), + USB_CTRL_SET_TIMEOUT + ); + + if (ret < 0) { + hid_err(t300rs->hdev, "could not fetch attachment: %i\n", ret); + goto out; + } + + if (response->type == cpu_to_le16(0x49)) { + attachment = response->a.attachment; + } else if (response->type == cpu_to_le16(0x47)) { + attachment = response->b.attachment; + } else { + hid_err(t300rs->hdev, "unknown packet type %hx\n, please contact a maintainer", + response->type); + ret = -EINVAL; + goto out; + } + + kfree(response); + return attachment; + +out: + kfree(response); + return ret; +} + static int t300rs_wheel_init(struct tmff2_device_entry *tmff2) { struct t300rs_device_entry *t300rs = kzalloc(sizeof(struct t300rs_device_entry), GFP_KERNEL); @@ -1483,6 +1567,8 @@ static int t300rs_wheel_init(struct tmff2_device_entry *tmff2) /* TODO: PS4 advanced mode? */ t300rs->mode = (t300rs->hdev->product == TMT300RS_PS3_ADV_ID); + if ((t300rs->attachment = t300rs_get_attachment(t300rs)) < 0) + t300rs->attachment = T300RS_DEFAULT_ATTACHMENT; /* everythin went OK */ tmff2->data = t300rs; -- cgit v1.3 From 864a7c582518538c209f5d81043816b5e2696ca3 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Fri, 25 Mar 2022 18:35:02 +0200 Subject: change 'native' to 'base' --- hid-tmt300rs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index c5b4655..2c44d1e 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -1199,7 +1199,7 @@ static struct t300rs_alt_modes { char *label; uint16_t mode; } t300rs_modes[] = { - {"native", "T300RS base", 0}, + {"base", "T300RS base", 0}, {"F1", "T300RS with F1 wheel attachment", 1} }; @@ -1212,7 +1212,7 @@ static ssize_t t300rs_alt_mode_show(void *data, char *buf) return -ENODEV; if (t300rs->attachment != T300RS_F1_ATTACHMENT) - /* we only support one native mode */ + /* we only support one base mode */ return scnprintf(buf, PAGE_SIZE, "%s: %s *\n", t300rs_modes[0].id, t300rs_modes[0].label); -- cgit v1.3 From c06a80f1d1e2ef003eb99d8b1fb24e9562f5eb27 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sat, 2 Apr 2022 21:30:40 +0300 Subject: set alt_mode to not reset the wheel's mode --- hid-tmt300rs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 2c44d1e..d637431 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -1170,6 +1170,7 @@ static int t300rs_switch_mode(void *data, uint16_t mode) if (!t300rs) return -ENODEV; + hid_info(t300rs->hdev, "switch\n"); if(t300rs->mode == mode) /* already in specified mode */ return 0; @@ -1566,7 +1567,7 @@ static int t300rs_wheel_init(struct tmff2_device_entry *tmff2) t300rs->close = t300rs->input_dev->close; /* TODO: PS4 advanced mode? */ - t300rs->mode = (t300rs->hdev->product == TMT300RS_PS3_ADV_ID); + alt_mode = t300rs->mode = (t300rs->hdev->product == TMT300RS_PS3_ADV_ID); if ((t300rs->attachment = t300rs_get_attachment(t300rs)) < 0) t300rs->attachment = T300RS_DEFAULT_ATTACHMENT; -- cgit v1.3 From 0471da28f10feb5f3ad58fe8233810cf031b90da Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sat, 2 Apr 2022 21:43:28 +0300 Subject: remove debugging print --- hid-tmt300rs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index d637431..aee30d5 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -1170,7 +1170,6 @@ static int t300rs_switch_mode(void *data, uint16_t mode) if (!t300rs) return -ENODEV; - hid_info(t300rs->hdev, "switch\n"); if(t300rs->mode == mode) /* already in specified mode */ return 0; @@ -1567,7 +1566,7 @@ static int t300rs_wheel_init(struct tmff2_device_entry *tmff2) t300rs->close = t300rs->input_dev->close; /* TODO: PS4 advanced mode? */ - alt_mode = t300rs->mode = (t300rs->hdev->product == TMT300RS_PS3_ADV_ID); + alt_mode = (t300rs->mode = (t300rs->hdev->product == TMT300RS_PS3_ADV_ID)); if ((t300rs->attachment = t300rs_get_attachment(t300rs)) < 0) t300rs->attachment = T300RS_DEFAULT_ATTACHMENT; -- cgit v1.3