diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/tmt300rs/hid-tmt300rs.c | 308 |
1 files changed, 181 insertions, 127 deletions
diff --git a/src/tmt300rs/hid-tmt300rs.c b/src/tmt300rs/hid-tmt300rs.c index 9b5d22d..4921e17 100644 --- a/src/tmt300rs/hid-tmt300rs.c +++ b/src/tmt300rs/hid-tmt300rs.c @@ -330,18 +330,9 @@ static u8 t300rs_rdesc_ps4_fixed[] = { 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 u8 condition_values[] = { + 0xfe, 0xff, 0xfe, 0xff, 0xfe, + 0xff, 0xfe, 0xff }; static void t300rs_calculate_periodic_values(struct ff_effect *effect) @@ -370,6 +361,63 @@ static void t300rs_calculate_periodic_values(struct ff_effect *effect) periodic->offset = clamp(periodic->offset, -headroom, headroom); } +static uint16_t t300rs_condition_max_saturation(uint16_t effect_type) +{ + if(effect_type == FF_SPRING) + return 0x6AA6; + + return 0x7FFC; +} + +static uint16_t t300rs_condition_effect_type(uint16_t effect_type) +{ + if(effect_type == FF_SPRING) + return 0x06; + + return 0x07; +} + +static int16_t t300rs_calculate_coefficient(int16_t coeff, uint16_t effect_type) +{ + uint8_t input_level; + + switch (effect_type) + { + case FF_SPRING: + input_level = spring_level; + break; + case FF_DAMPER: + input_level = damper_level; + break; + case FF_FRICTION: + input_level = friction_level; + break; + default: + input_level = 100; + break; + } + + return coeff * input_level / 100; +} + +static uint16_t t300rs_calculate_saturation(uint16_t sat, uint16_t effect_type) +{ + uint16_t max = t300rs_condition_max_saturation(effect_type); + + if(sat == 0) + return max; + + return sat * max / 0xFFFF; +} + +static void t300rs_calculate_deadband(int16_t *out_rband, int16_t *out_lband, uint16_t deadband, int16_t offset) +{ + /* max deadband value is 0x7FFF in either direction */ + /* deadband is the width of the deadzone, one direction is half of it */ + *out_rband = clamp(offset + (deadband / 2), -0x7FFF, 0x7FFF); + *out_lband = clamp(offset - (deadband / 2), -0x7FFF, 0x7FFF); +} + int t300rs_send_buf(struct t300rs_device_entry *t300rs, u8 *send_buffer, size_t len) { int i; @@ -772,81 +820,129 @@ error: return ret; } -static int t300rs_update_damper(struct t300rs_device_entry *t300rs, +static int t300rs_update_condition(struct t300rs_device_entry *t300rs, struct tmff2_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]; - struct __packed t300rs_packet_mod_damper { + struct ff_condition_effect cond = effect.u.condition[0]; + struct ff_condition_effect cond_old = old.u.condition[0]; + struct __packed t300rs_packet_mod_condition { 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; + } *packet_mod_condition = (struct t300rs_packet_mod_condition *)t300rs->send_buffer; - int ret, input_level; + int ret; + uint16_t right_sat, right_sat_old, left_sat, left_sat_old; + uint16_t right_coeff, right_coeff_old, left_coeff, left_coeff_old; + int16_t right_deadband, right_deadband_old, left_deadband, left_deadband_old; - input_level = damper_level; - if (state->effect.type == FF_FRICTION) - input_level = friction_level; + right_coeff = t300rs_calculate_coefficient(cond.right_coeff, effect.type); + right_coeff_old = t300rs_calculate_coefficient(cond_old.right_coeff, old.type); - if (state->effect.type == FF_SPRING) - input_level = spring_level; + left_coeff = t300rs_calculate_coefficient(cond.left_coeff, effect.type); + left_coeff_old = t300rs_calculate_coefficient(cond_old.left_coeff, old.type); + + t300rs_calculate_deadband(&right_deadband, &left_deadband, cond.deadband, cond.center); + t300rs_calculate_deadband(&right_deadband_old, &left_deadband_old, cond_old.deadband, cond_old.center); + + right_sat = t300rs_calculate_saturation(cond.right_saturation, effect.type); + right_sat_old = t300rs_calculate_saturation(cond_old.right_saturation, old.type); - if (damper.right_coeff != damper_old.right_coeff) { - int16_t coeff = damper.right_coeff * input_level / 100; + left_sat = t300rs_calculate_saturation(cond.left_saturation, effect.type); + left_sat_old = t300rs_calculate_saturation(cond_old.left_saturation, old.type); - t300rs_fill_header(&packet_mod_damper->header, effect.id, 0x0e); - packet_mod_damper->attribute = 0x41; - packet_mod_damper->value0 = cpu_to_le16(coeff); + if (right_coeff != right_coeff_old + && left_coeff != left_coeff_old) { + t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); + packet_mod_condition->attribute = 0x43; + packet_mod_condition->value0 = cpu_to_le16(right_coeff); + packet_mod_condition->value1 = cpu_to_le16(left_coeff); ret = t300rs_send_int(t300rs); if (ret) { - hid_err(t300rs->hdev, "failed modifying damper rc\n"); + hid_err(t300rs->hdev, "failed modifying condition coeff\n"); goto error; } + } + else if (right_coeff != right_coeff_old) { + t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); + packet_mod_condition->attribute = 0x41; + packet_mod_condition->value0 = cpu_to_le16(right_coeff); + ret = t300rs_send_int(t300rs); + if (ret) { + hid_err(t300rs->hdev, "failed modifying condition right coeff\n"); + goto error; + } } + else if (left_coeff != left_coeff_old) { + t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); + packet_mod_condition->attribute = 0x42; + packet_mod_condition->value0 = cpu_to_le16(left_coeff); - if (damper.left_coeff != damper_old.left_coeff) { - int16_t coeff = damper.left_coeff * input_level / 100; + ret = t300rs_send_int(t300rs); + if (ret) { + hid_err(t300rs->hdev, "failed modifying condition left coeff\n"); + goto error; + } + } - t300rs_fill_header(&packet_mod_damper->header, effect.id, 0x0e); - packet_mod_damper->attribute = 0x42; - packet_mod_damper->value0 = cpu_to_le16(coeff); + if ((right_deadband != right_deadband_old) + || (left_deadband != left_deadband_old)) { + t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); + packet_mod_condition->attribute = 0x4c; + packet_mod_condition->value0 = cpu_to_le16(right_deadband); + packet_mod_condition->value1 = cpu_to_le16(left_deadband); ret = t300rs_send_int(t300rs); if (ret) { - hid_err(t300rs->hdev, "failed modifying damper lc\n"); + hid_err(t300rs->hdev, "failed modifying condition deadband\n"); goto error; } - } - 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; + if (right_sat != right_sat_old + && left_sat != left_sat_old) { + t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); + packet_mod_condition->attribute = 0x70; + packet_mod_condition->value0 = cpu_to_le16(right_sat); + packet_mod_condition->value1 = cpu_to_le16(left_sat); - 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); + ret = t300rs_send_int(t300rs); + if (ret) { + hid_err(t300rs->hdev, "failed modifying condition saturation\n"); + goto error; + } + } + else if (right_sat != right_sat_old) { + t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); + packet_mod_condition->attribute = 0x50; + packet_mod_condition->value0 = cpu_to_le16(right_sat); ret = t300rs_send_int(t300rs); if (ret) { - hid_err(t300rs->hdev, "failed modifying damper deadband\n"); + hid_err(t300rs->hdev, "failed modifying condition right saturation\n"); goto error; } + } + else if (left_sat != left_sat_old) { + t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); + packet_mod_condition->attribute = 0x60; + packet_mod_condition->value0 = cpu_to_le16(left_sat); + ret = t300rs_send_int(t300rs); + if (ret) { + hid_err(t300rs->hdev, "failed modifying condition left saturation\n"); + goto error; + } } ret = t300rs_update_simple_duration(t300rs, state, 0x06); if (ret) { - hid_err(t300rs->hdev, "failed modifying damper duration\n"); + hid_err(t300rs->hdev, "failed modifying condition duration\n"); goto error; } @@ -854,12 +950,6 @@ error: return ret; } -static int t300rs_update_spring(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state) -{ - return t300rs_update_damper(t300rs, state); -} - static int t300rs_update_periodic(struct t300rs_device_entry *t300rs, struct tmff2_effect_state *state) { @@ -1060,95 +1150,61 @@ static int t300rs_upload_ramp(struct t300rs_device_entry *t300rs, return ret; } -static int t300rs_upload_spring(struct t300rs_device_entry *t300rs, +static int t300rs_upload_condition(struct t300rs_device_entry *t300rs, struct tmff2_effect_state *state) { struct ff_effect effect = state->effect; /* we only care about the first axis */ - struct ff_condition_effect spring = state->effect.u.condition[0]; - struct __packed t300rs_packet_spring { + struct ff_condition_effect cond = state->effect.u.condition[0]; + struct __packed t300rs_packet_condition { 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]; + int16_t right_coeff; + int16_t left_coeff; + int16_t right_deadband; + int16_t left_deadband; + uint16_t right_saturation; + uint16_t left_saturation; + uint8_t hardcoded[ARRAY_SIZE(condition_values)]; + uint16_t max_right_saturation; + uint16_t max_left_saturation; + uint8_t type; struct t300rs_packet_timing timing; - } *packet_spring = (struct t300rs_packet_spring *)t300rs->send_buffer; + } *packet_condition = (struct t300rs_packet_condition *)t300rs->send_buffer; int ret; - uint16_t duration, right_coeff, left_coeff, right_deadband, left_deadband, offset; + uint16_t duration, right_sat, left_sat, right_coeff, left_coeff, max_sat, offset; + int16_t right_deadband, left_deadband; - duration = effect.replay.length - 1; - - right_coeff = spring.right_coeff * spring_level / 100; - left_coeff = spring.left_coeff * spring_level / 100; - - right_deadband = 0xfffe - spring.deadband - spring.center; - left_deadband = 0xfffe - spring.deadband + spring.center; - - offset = effect.replay.delay; + right_coeff = t300rs_calculate_coefficient(cond.right_coeff, effect.type); + left_coeff = t300rs_calculate_coefficient(cond.left_coeff, effect.type); - t300rs_fill_header(&packet_spring->header, effect.id, 0x64); + t300rs_calculate_deadband(&right_deadband, &left_deadband, cond.deadband, cond.center); - 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); - - ret = t300rs_send_int(t300rs); - if (ret) - hid_err(t300rs->hdev, "failed uploading spring\n"); - - return ret; -} - -static int t300rs_upload_damper(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state) -{ - - struct ff_effect effect = state->effect; - /* we only care about the first axis */ - struct ff_condition_effect spring = state->effect.u.condition[0]; - 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; - uint8_t damper_start[17]; - 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; + right_sat = t300rs_calculate_saturation(cond.right_saturation, effect.type); + left_sat = t300rs_calculate_saturation(cond.left_saturation, effect.type); duration = effect.replay.length - 1; - input_level = damper_level; - if (state->effect.type == FF_FRICTION) - input_level = friction_level; - - right_coeff = spring.right_coeff * input_level / 100; - left_coeff = spring.left_coeff * input_level / 100; + offset = effect.replay.delay; - right_deadband = 0xfffe - spring.deadband - spring.center; - left_deadband = 0xfffe - spring.deadband + spring.center; + t300rs_fill_header(&packet_condition->header, effect.id, 0x64); - offset = effect.replay.delay; + packet_condition->right_coeff = cpu_to_le16(right_coeff); + packet_condition->left_coeff = cpu_to_le16(left_coeff); + packet_condition->right_deadband = cpu_to_le16(right_deadband); + packet_condition->left_deadband = cpu_to_le16(left_deadband); + packet_condition->right_saturation = cpu_to_le16(right_sat); + packet_condition->left_saturation = cpu_to_le16(left_sat); - t300rs_fill_header(&packet_damper->header, effect.id, 0x64); + memcpy(&packet_condition->hardcoded, condition_values, ARRAY_SIZE(condition_values)); - 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); + max_sat = t300rs_condition_max_saturation(effect.type); + /* it seems that the maximum values do not affect the wheel. */ + packet_condition->max_right_saturation = cpu_to_le16(max_sat); + packet_condition->max_left_saturation = cpu_to_le16(max_sat); + packet_condition->type = t300rs_condition_effect_type(effect.type); - memcpy(&packet_damper->damper_start, damper_values, ARRAY_SIZE(damper_values)); - t300rs_fill_timing(&packet_damper->timing, duration, offset); + t300rs_fill_timing(&packet_condition->timing, duration, offset); ret = t300rs_send_int(t300rs); if (ret) @@ -1219,11 +1275,10 @@ int t300rs_update_effect(void *data, struct tmff2_effect_state *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); + return t300rs_update_condition(t300rs, state); case FF_PERIODIC: return t300rs_update_periodic(t300rs, state); default: @@ -1242,11 +1297,10 @@ int t300rs_upload_effect(void *data, struct tmff2_effect_state *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); + return t300rs_upload_condition(t300rs, state); case FF_PERIODIC: return t300rs_upload_periodic(t300rs, state); default: |
