From 51dfd633de3cd46794f9547344066e5b22111e96 Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Thu, 18 Jul 2024 18:57:39 +0200 Subject: update ramp effect documentation --- docs/FFBEFFECTS.md | 257 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 230 insertions(+), 27 deletions(-) diff --git a/docs/FFBEFFECTS.md b/docs/FFBEFFECTS.md index 93dbb80..60b2e50 100644 --- a/docs/FFBEFFECTS.md +++ b/docs/FFBEFFECTS.md @@ -190,14 +190,70 @@ have model specific peculiarities, though. Ramps seem to follow triangle wave parameters. +``` +00001110 00000001 0e 01 - slope +00001110 00000010 0e 02 - center +01001001 49 - invert +00001110 00000011 0e 03 - slope + center +01001110 00000001 4e 01 - slope + invert +01001110 00000011 4e 03 - slope + center + invert +01001110 00001000 4e 08 - duration +01001001 49 - offset +01001110 00001000 4e 08 - duration + offset +00110001 10000001 31 81 - envelope attack length +00110001 10000010 31 82 - envelope attack level +00110001 10000100 31 84 - envelope fade length +00110001 10001000 31 88 - envelope fade level +00101001 29 - envelope (all) +01110110 00000011 76 03 - envelope attack & fade length + slope + center + invert +00101110 00000011 2e 03 - envelope + slope + center + invert +01101110 00001011 6e 0b - duration + offset + envelope + slope + center + invert +``` + +### Notes + +#### Invert + +There is a bug in the Windows driver during the Ramp effect update. +If the update requires inverting the effect and the duration or the offset is +not changed, the effect just stops. + +This can be fixed by adding the `update type` byte with the value of `40`. + +Affected examples: + - slope + invert + - slope + center + invert + - invert + - envelope attack & fade length + slope + center + invert + - envelope + slope + center + invert + +Example: +``` +Invalid: + 60 00 - standard header + 01 - ID + 49 + 05 - effect type? + 00 <- missing "update type" + [...] + +Valid: + 60 00 - standard header + 01 - ID + 49 + 05 - effect type? + 40 - update type <- correct update type + [...] +``` + + ### Init: ``` 60 00 - standard header 01 - ID 6b - new ramp effect - f6 7f - difference *** - fe ff - level? *** (level = (if end_level > start_level, end_level, else - start_level) - difference?) (signed) + f6 7f - slope *** abs(start - stop) / 2 + fe ff - center *** (start + end) / 2 (signed) 00 00 f7 17 - time 00 80 - some kind of marker @@ -216,53 +272,200 @@ Ramps seem to follow triangle wave parameters. ``` ### Modifying: + ``` +center: + 60 00 - standard header + 01 - ID + 0e 02 + 1e 40 - center + 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +slope + invert: + This packet is affected by the "invert" driver bug. See Notes above. + + 60 00 - standard header + 01 - ID + 4e 01 + 20 00 - slope + 04 - effect type? (invert) 04 or 05 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +slope + center + invert: + This packet is affected by the "invert" driver bug. See Notes above. + 60 00 - standard header 01 - ID - 0e - ??? - 03 - ramp? - e3 04 - difference? - 7d 75 - "level"? - 05 - ???? + 4e 03 + 06 00 - slope + 25 40 - center + 04 - effect type? (invert) 04 or 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ``` -#### Envelope: +#### Duration, offset, invert: + ``` +duration: 60 00 - standard header 01 - ID - 31 - modify envelope - 84 - ID of envelope attribute ( attack_level 82, - attack_length 81, - fade_level 88, - fade_length 84 ) - 63 04 - value attribute should be set to - 00 00 00 00 00 00 00 00 00 + 4e 08 + 88 13 - duration + 04 - effect type? must reflect the actual inversion 04 or 05 + 41 - update type + 88 13 - duration + 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +offset: + 60 00 - standard header + 01 - ID + 49 + 04 - effect type? must reflect the actual inversion 04 or 05 + 44 - update type + 00 00 - offset + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +duration + offset: + 60 00 - standard header + 01 - ID + 4e 08 + 88 13 - duration + 04 - effect type? must reflect the actual inversion 04 or 05 + 45 - update type + 88 13 - duration + 00 00 - offset + 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +dir + offset: + 60 00 - standard header + 01 - ID + 49 + 05 - effect type? must reflect the actual inversion 04 or 05 + 44 - update type + 00 00 - offset + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +invert: + This packet is affected by the "invert" driver bug. See Notes above. + + 60 00 - standard header + 01 - ID + 49 + 05 - effect type? invert 04 or 05 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ``` -#### Duration: -``` - 60 00 +#### Envelope: + +``` +envelope attack/fade level/length: + multiple values can be updated with one packet + + 60 00 - standard header 01 - ID - 4e - ? - 08 - ? - 01 00 - time in milliseconds - 05 - ? - 41 - ? - 01 00 - time in milliseconds - 00 00 00 00 00 + 31 85 + d0 07 - attack length + dc 05 - fade length + 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +envelope (all): + 60 00 - standard header + 01 - ID + 29 + d0 07 - attack length + 69 34 - attack level + dc 05 - fade length + 32 1a - fade level + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ``` -#### Offset: `N/A` +#### Combined: + +``` +envelope attack & fade length + slope + center + invert: + This packet is affected by the "invert" driver bug. See Notes above. + + 60 00 - standard header + 01 - ID + 76 03 + 06 00 - slope + 25 40 - center + 85 - envelope update type + d0 07 - attack length + dc 05 - fade length + 04 - effect type? (invert) 04 or 05 + 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +envelope + slope + center + invert: + This packet is affected by the "invert" driver bug. See Notes above. + + 60 00 - standard header + 01 - ID + 6e 03 + 06 00 - slope + 25 40 - center + d0 07 - attack length + 69 34 - attack level + dc 05 - fade length + 32 1a - fade level + 04 - effect type? (invert) 04 or 05 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +duration + offset + envelope + slope + center + invert: + 60 00 - standard header + 01 - ID + 6e 0b + 06 00 - slope + 25 40 - center + 88 13 - length + d0 07 - attack length + 69 34 - attack level + dc 05 - fade length + 32 1a - fade level + 04 - effect type? (invert) 04 or 05 + 45 - update type + 88 13 - length 2 + 00 00 - offset + 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +``` ## FF_DAMPER + FF_FRICTION + FF_INERTIA + FF_SPRING: ### Init: -- cgit v1.3 From 7ba0884ca4ef4663698071c56f4b6f85d7faaff1 Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Fri, 19 Jul 2024 18:05:45 +0200 Subject: fix ramp effect upload and update --- src/tmt300rs/hid-tmt300rs.c | 172 +++++++++++++++++++------------------------- 1 file changed, 74 insertions(+), 98 deletions(-) diff --git a/src/tmt300rs/hid-tmt300rs.c b/src/tmt300rs/hid-tmt300rs.c index 40be801..bf0645a 100644 --- a/src/tmt300rs/hid-tmt300rs.c +++ b/src/tmt300rs/hid-tmt300rs.c @@ -419,6 +419,24 @@ static void t300rs_calculate_deadband(int16_t *out_rband, int16_t *out_lband, *out_lband = clamp(offset - (deadband / 2), -0x7fff, 0x7fff); } +static void t300rs_calculate_ramp_parameters(uint16_t *out_slope, + int16_t *out_center, + uint8_t *out_invert, + struct ff_effect *effect) +{ + struct ff_ramp_effect *ramp = &effect->u.ramp; + + int16_t start_level, end_level; + + start_level = (ramp->start_level * fixp_sin16(effect->direction * 360 / 0x10000)) / 0x7fff; + end_level = (ramp->end_level * fixp_sin16(effect->direction * 360 / 0x10000)) / 0x7fff; + + *out_slope = abs(start_level - end_level) / 2; + *out_center = (start_level + end_level) / 2; + + *out_invert = (start_level < end_level) ? 0x04 : 0x05; +} + int t300rs_send_buf(struct t300rs_device_entry *t300rs, u8 *send_buffer, size_t len) { int i; @@ -661,41 +679,6 @@ error: return ret; } -static int t300rs_update_ramp_duration(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state) -{ - struct ff_effect effect = state->effect; - struct __packed t300rs_packet_mod_duration { - struct t300rs_packet_header header; - uint8_t marker0; - uint16_t duration0; - uint8_t marker1; - uint8_t marker2; - uint16_t duration1; - } *packet_mod_duration = (struct t300rs_packet_mod_duration *)t300rs->send_buffer; - - uint16_t duration; - int ret = 0; - - duration = effect.replay.length - 1; - - t300rs_fill_header(&packet_mod_duration->header, effect.id, 0x4e); - packet_mod_duration->marker0 = 0x08; - packet_mod_duration->duration0 = cpu_to_le16(duration); - packet_mod_duration->marker1 = 0x05; - packet_mod_duration->marker2 = 0x41; - packet_mod_duration->duration1 = cpu_to_le16(duration); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying duration\n"); - goto error; - } - -error: - return ret; -} - static int t300rs_update_constant(struct t300rs_device_entry *t300rs, struct tmff2_effect_state *state) { @@ -760,64 +743,62 @@ static int t300rs_update_ramp(struct t300rs_device_entry *t300rs, struct ff_ramp_effect ramp_old = old.u.ramp; struct __packed t300rs_packet_mod_ramp { struct t300rs_packet_header header; - uint8_t attribute; - uint16_t difference; - uint16_t level; + uint8_t type; + uint16_t slope; + uint16_t center; + uint16_t length; + struct t300rs_packet_envelope envelope; + uint8_t effect_type; + uint8_t update_type; + uint16_t length2; + uint16_t offset; } *packet_mod_ramp = (struct t300rs_packet_mod_ramp *)t300rs->send_buffer; - int ret; - - 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; - + int ret = 0; - difference = ((top - bottom) * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; + uint8_t invert, old_invert; + uint16_t slope, old_slope, length, old_length; + int16_t center, old_center; + t300rs_calculate_ramp_parameters(&slope, ¢er, &invert, &effect); + t300rs_calculate_ramp_parameters(&old_slope, &old_center, &old_invert, &old); - level = (top * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; + length = effect.replay.length - 1; + old_length = old.replay.length - 1; - if ((ramp.start_level != ramp_old.start_level) - || (ramp.end_level != ramp_old.end_level) - || (effect.direction != old.direction)) { + if (slope != old_slope + || center != old_center + || invert != old_invert + || ramp.envelope.attack_length != ramp_old.envelope.attack_length + || ramp.envelope.attack_level != ramp_old.envelope.attack_level + || ramp.envelope.fade_length != ramp_old.envelope.fade_length + || ramp.envelope.fade_level != ramp_old.envelope.fade_level + || length != old_length + || effect.replay.delay != old.replay.delay) { - 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); + t300rs_fill_header(&packet_mod_ramp->header, effect.id, 0x6e); + packet_mod_ramp->type = 0x0b; + packet_mod_ramp->slope = cpu_to_le16(slope); + packet_mod_ramp->center = cpu_to_le16(center); + packet_mod_ramp->length = cpu_to_le16(length); + packet_mod_ramp->envelope.attack_length = + cpu_to_le16(ramp.envelope.attack_length); + packet_mod_ramp->envelope.attack_level = + cpu_to_le16(ramp.envelope.attack_level); + packet_mod_ramp->envelope.fade_length = + cpu_to_le16(ramp.envelope.fade_length); + packet_mod_ramp->envelope.fade_level = + cpu_to_le16(ramp.envelope.fade_level); + packet_mod_ramp->effect_type = invert; + packet_mod_ramp->update_type = 0x45; + packet_mod_ramp->length2 = packet_mod_ramp->length; + packet_mod_ramp->offset = cpu_to_le16(effect.replay.delay); ret = t300rs_send_int(t300rs); - if (ret) { + if (ret) hid_err(t300rs->hdev, "failed modifying ramp effect\n"); - goto error; - } - - } - - ret = t300rs_update_envelope(t300rs, - state, - level, - effect.replay.length, - effect.id, - ramp.envelope, - ramp_old.envelope - ); - - - if (ret) { - hid_err(t300rs->hdev, "failed modifying ramp envelope\n"); - goto error; - } - - ret = t300rs_update_ramp_duration(t300rs, state); - if (ret) { - hid_err(t300rs->hdev, "failed modifying ramp duration\n"); - goto error; } -error: return ret; } @@ -1053,43 +1034,38 @@ static int t300rs_upload_ramp(struct t300rs_device_entry *t300rs, struct ff_ramp_effect ramp = state->effect.u.ramp; struct __packed t300rs_packet_ramp { struct t300rs_packet_header header; - uint16_t difference; - uint16_t level; + uint16_t slope; + uint16_t center; uint8_t zero1[2]; uint16_t duration; uint16_t marker; struct t300rs_packet_envelope envelope; - uint8_t direction; + uint8_t invert; 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; + uint8_t invert; + uint16_t slope, offset, duration; + int16_t center; - duration = effect.replay.length - 1; + t300rs_calculate_ramp_parameters(&slope, ¢er, &invert, &effect); - 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; - - - difference = ((top - bottom) * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; - level = (top * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; + duration = effect.replay.length - 1; offset = effect.replay.delay; - t300rs_fill_header(&packet_ramp->header, effect.id, 0x6b); - packet_ramp->difference = cpu_to_le16(difference); - packet_ramp->level = cpu_to_le16(level); + packet_ramp->slope = cpu_to_le16(slope); + packet_ramp->center = cpu_to_le16(center); packet_ramp->duration = cpu_to_le16(duration); packet_ramp->marker = cpu_to_le16(0x8000); - t300rs_fill_envelope(&packet_ramp->envelope, level, duration, + t300rs_fill_envelope(&packet_ramp->envelope, slope, duration, &ramp.envelope); - packet_ramp->direction = ramp.end_level > ramp.start_level ? 0x04 : 0x05; + packet_ramp->invert = invert; t300rs_fill_timing(&packet_ramp->timing, duration, offset); ret = t300rs_send_int(t300rs); -- cgit v1.3 From 03fa8fcdf35fa0757f283d7f3f0c69b46fb9bd47 Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Fri, 26 Jul 2024 16:57:13 +0200 Subject: document periodic effect update packets --- docs/FFBEFFECTS.md | 184 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 108 insertions(+), 76 deletions(-) diff --git a/docs/FFBEFFECTS.md b/docs/FFBEFFECTS.md index 60b2e50..8ce57b9 100644 --- a/docs/FFBEFFECTS.md +++ b/docs/FFBEFFECTS.md @@ -662,11 +662,10 @@ Update type: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ``` -### Offset: `N/A` - ## FF_PERIODIC: + ### Init -``` +``` 60 00 - standard header 01 - ID 6b - new periodic effect @@ -675,7 +674,7 @@ Update type: 00 00 - phase (left/right) between 00 00 and 4a f7 (32586) meaning is 0 to ~359 deg phase shift in 5b steps e8 03 - period between 00 00 and ff ff (in milliseconds) - 00 80 + 00 80 00 00 - attack_length 00 00 - attack_level *** 00 00 - fade_length @@ -695,8 +694,27 @@ Update type: ``` ### Modifying: + +``` +4th byte 5th byte hex +00001110 00000001 0e 01 - magnitude +00001110 00000010 0e 02 - offset +00001110 00000100 0e 04 - phase +00001110 00001000 0e 08 - period +00001110 00001111 0e 0f - magnitude + offset + phase + period +01001001 49 - duration / offset / duration + offset +00110001 10000001 31 81 - envelope attack length +00110001 10000010 31 82 - envelope attack level +00110001 10000100 31 84 - envelope fade length +00110001 10001000 31 88 - envelope fade level +00101001 29 - envelope (all) +00101110 00001111 2e 0f - magnitude + offset + phase + period + envelope +00110110 00001111 36 0f - magnitude + offset + phase + period + envelope attack length & level +01101110 00001111 6e 0f - magnitude + offset + phase + period + envelope + duration + offset ``` - magnitude: + +``` +magnitude: 60 00 02 - ID 0e 01 @@ -706,118 +724,132 @@ Update type: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - offset of effect: - 60 00 - 02 - ID - 0e 02 - 64 35 - value, between ff bf (-16385) and fd 3f (16381) - 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - - phase: +magnitude + offset + phase + period: 60 00 - 02 - ID - 0e 04 - 64 35 - value, between 00 00 and 4a f7 (32586) in 5b steps + 01 - ID + 0e 0f + dd 3f - magnitude, between 00 00 and fc 7f (32764) + cb 0c - offset, between ff bf (-16385) and fd 3f (16381) + 5a 00 - phase, between 00 00 and 4a f7 (32586) in 5b steps meaning is 0 to 359 deg phase shift - 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - - period: - 60 00 - 02 - ID - 0e 08 - 64 35 - value, between 00 00 and ff ff (in milliseconds) - 00 00 00 00 00 00 00 00 00 + f8 2a - period, between 00 00 and ff ff (in milliseconds) + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ``` -### Envelope: +#### Envelope: ``` +envelope attack/fade level/length: + multiple values can be updated with one packet + 60 00 - standard header 01 - ID - 31 - modify envelope - 84 - ID of envelope attribute ( attack_level 82, - attack_length 81, - fade_level 88, - fade_length 84 ) - 63 04 - value attribute should be set to - 00 00 00 00 00 00 00 00 00 + 31 85 + d0 07 - attack length + dc 05 - fade length + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -``` -### Duration: -``` - Square: - 60 00 +envelope (all): + 60 00 - standard header 01 - ID - 49 - ? - 01 - Effect type - 41 - ? - 4e 0c - Time in milliseconds - 00 00 00 00 00 00 00 00 + 29 + d0 07 - attack length + 69 34 - attack level + dc 05 - fade length + 32 1a - fade level + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +``` - Sine: +#### Duration: +``` 60 00 01 - ID - 49 - ? - 03 - Effect type - 41 - ? - ec 13 - Time in milliseconds - 00 00 00 00 00 00 00 00 + 49 + 03 - effect type 01 - Square + 02 - Triangle + 03 - Sine + 04 - Sawtooth up + 05 - Sawtooth down + 45 - update type 41 - duration + 44 - offset + 45 - duration + offset + 74 27 - duration + 00 00 - offset + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +``` + +#### Combined - Triangle: +``` +magnitude + offset + phase + period + envelope: 60 00 01 - ID - 49 - ? - 02 - Effect type - 41 - ? - 4e 0c - Time in milliseconds - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 2e 0f + dd 3f - magnitude, between 00 00 and fc 7f (32764) + cb 0c - offset + 5a 00 - phase + f8 2a - period + dc 05 - attack length + 30 73 - attack level + e8 03 - fade length + 30 73 - fade level + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - Sawtooth up: +magnitude + offset + phase + period + envelope attack length & level: 60 00 01 - ID - 49 - ? - 04 - Effect type - 41 - ? - 4e 0c - Time in milliseconds - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 36 0f + dd 3f - magnitude + cb 0c - offset + 5a 00 - phase + f8 2a - period + 83 - envelope update type + e8 03 - attack length + cc 0c - attack level + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - Sawtooth down: +magnitude + offset + phase + period + envelope + duration + offset: 60 00 01 - ID - 49 - ? - 05 - Effect type - 41 - ? - ec 13 - Time in milliseconds - 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 6e 0f + dd 3f - magnitude + cb 0c - offset + 5a 00 - phase + f8 2a - period + cc 0c - attack length + e8 03 - attack level + dc 05 - fade length + cc 0c - fade level + 03 - effect type 01 - Square + 02 - Triangle + 03 - Sine + 04 - Sawtooth up + 05 - Sawtooth down + 45 - update type 41 - duration + 44 - offset + 45 - duration + offset + 74 27 - duration + 00 00 - offset + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ``` -### Offset: `N/A ?` ## PS4 Input `rdesc` ``` -- cgit v1.3 From 541377b53ce8b2103c8c2924622ca11cee7ac6a2 Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Fri, 26 Jul 2024 17:18:24 +0200 Subject: use single packet in periodic effect update --- src/tmt300rs/hid-tmt300rs.c | 158 +++++++++++++------------------------------- 1 file changed, 46 insertions(+), 112 deletions(-) diff --git a/src/tmt300rs/hid-tmt300rs.c b/src/tmt300rs/hid-tmt300rs.c index bf0645a..2a61199 100644 --- a/src/tmt300rs/hid-tmt300rs.c +++ b/src/tmt300rs/hid-tmt300rs.c @@ -648,37 +648,6 @@ error: return ret; } -static int t300rs_update_periodic_duration(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state, unsigned type) -{ - struct ff_effect effect = state->effect; - struct __packed t300rs_packet_mod_duration { - struct t300rs_packet_header header; - uint8_t type; - uint8_t marker; - uint16_t duration; - } *packet_mod_duration = (struct t300rs_packet_mod_duration *)t300rs->send_buffer; - - uint16_t duration; - int ret = 0; - - duration = effect.replay.length - 1; - - t300rs_fill_header(&packet_mod_duration->header, effect.id, 0x49); - packet_mod_duration->type = type; - packet_mod_duration->marker = 0x41; - packet_mod_duration->duration = cpu_to_le16(duration); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying duration\n"); - goto error; - } - -error: - return ret; -} - static int t300rs_update_constant(struct t300rs_device_entry *t300rs, struct tmff2_effect_state *state) { @@ -887,103 +856,68 @@ static int t300rs_update_periodic(struct t300rs_device_entry *t300rs, struct ff_effect old = state->old; struct __packed t300rs_packet_mod_periodic { struct t300rs_packet_header header; - uint8_t attribute; - uint16_t value; + uint8_t type; + uint16_t magnitude; + uint16_t offset; + uint16_t phase; + uint16_t period; + struct t300rs_packet_envelope envelope; + uint8_t effect_type; + uint8_t update_type; + uint16_t duration; + uint16_t play_offset; } *packet_mod_periodic = (struct t300rs_packet_mod_periodic *)t300rs->send_buffer; struct ff_periodic_effect periodic, periodic_old; - int ret; - uint16_t phase; - int16_t magnitude; + int ret = 0; + uint16_t length, old_length; t300rs_calculate_periodic_values(&effect); periodic = effect.u.periodic; - magnitude = periodic.magnitude; - phase = periodic.phase; t300rs_calculate_periodic_values(&old); periodic_old = old.u.periodic; - if ((periodic.magnitude != periodic_old.magnitude) - || (effect.direction != old.direction)) { - - t300rs_fill_header(&packet_mod_periodic->header, effect.id, 0x0e); - packet_mod_periodic->attribute = 0x01; - packet_mod_periodic->value = cpu_to_le16(magnitude); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying periodic magnitude\n"); - goto error; - } - - } - - if (periodic.offset != periodic_old.offset) { - uint16_t offset = periodic.offset; - - t300rs_fill_header(&packet_mod_periodic->header, effect.id, 0x0e); - packet_mod_periodic->attribute = 0x02; - packet_mod_periodic->value = cpu_to_le16(offset); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying periodic offset\n"); - goto error; - } - - } - - if (periodic.phase != periodic_old.phase) { - - t300rs_fill_header(&packet_mod_periodic->header, effect.id, 0x0e); - packet_mod_periodic->attribute = 0x04; - packet_mod_periodic->value = cpu_to_le16(phase); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying periodic phase\n"); - goto error; - } - - } + length = effect.replay.length - 1; + old_length = old.replay.length - 1; - if (periodic.period != periodic_old.period) { - int16_t period = periodic.period; + if (periodic.magnitude != periodic_old.magnitude + || periodic.offset != periodic_old.offset + || periodic.phase != periodic_old.phase + || periodic.period != periodic_old.period + || periodic.envelope.attack_length != periodic_old.envelope.attack_length + || periodic.envelope.attack_level != periodic_old.envelope.attack_level + || periodic.envelope.fade_length != periodic_old.envelope.fade_length + || periodic.envelope.fade_level != periodic_old.envelope.fade_level + || length != old_length + || effect.replay.delay != old.replay.delay) { - t300rs_fill_header(&packet_mod_periodic->header, effect.id, 0x0e); - packet_mod_periodic->attribute = 0x08; - packet_mod_periodic->value = cpu_to_le16(period); + t300rs_fill_header(&packet_mod_periodic->header, effect.id, 0x6e); + packet_mod_periodic->type = 0x0f; + packet_mod_periodic->magnitude = cpu_to_le16(periodic.magnitude); + packet_mod_periodic->offset = cpu_to_le16(periodic.offset); + packet_mod_periodic->phase = cpu_to_le16(periodic.phase); + packet_mod_periodic->period = cpu_to_le16(periodic.period); + + packet_mod_periodic->envelope.attack_length = + cpu_to_le16(periodic.envelope.attack_length); + packet_mod_periodic->envelope.attack_level = + cpu_to_le16(periodic.envelope.attack_level); + packet_mod_periodic->envelope.fade_length = + cpu_to_le16(periodic.envelope.fade_length); + packet_mod_periodic->envelope.fade_level = + cpu_to_le16(periodic.envelope.fade_level); + + packet_mod_periodic->effect_type = periodic.waveform - 0x57; + packet_mod_periodic->update_type = 0x45; + packet_mod_periodic->duration = length; + packet_mod_periodic->play_offset = effect.replay.delay; ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying periodic period\n"); - goto error; - } - - } - - ret = t300rs_update_envelope(t300rs, - state, - magnitude, - effect.replay.length, - effect.id, - periodic.envelope, - periodic_old.envelope - ); - - if (ret) { - hid_err(t300rs->hdev, "failed modifying periodic envelope\n"); - goto error; - } - - ret = t300rs_update_periodic_duration(t300rs, state, periodic.waveform - 0x57); - if (ret) { - hid_err(t300rs->hdev, "failed modifying periodic duration\n"); - goto error; + if (ret) + hid_err(t300rs->hdev, "failed modifying periodic effect\n"); } -error: return ret; } -- cgit v1.3 From bf9e08e1abc0a934e8cdb096527be217264c4af7 Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Fri, 26 Jul 2024 23:07:20 +0200 Subject: document constant effect update packets --- docs/FFBEFFECTS.md | 111 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 99 insertions(+), 12 deletions(-) diff --git a/docs/FFBEFFECTS.md b/docs/FFBEFFECTS.md index 8ce57b9..a88b55b 100644 --- a/docs/FFBEFFECTS.md +++ b/docs/FFBEFFECTS.md @@ -142,7 +142,21 @@ have model specific peculiarities, though. ### Modifying (For dynamic updating of effects) -#### Direction: ``N/A`` +``` +4th byte 5th byte hex +00001010 0a - magnitude +01001001 49 - duration / offset / duration + offset +00110001 10000001 31 81 - envelope attack length +00110001 10000010 31 82 - envelope attack level +00110001 10000100 31 84 - envelope fade length +00110001 10001000 31 88 - envelope fade level +00101001 29 - envelope (all) +00101010 2a - magnitude + envelope +01101010 6a - magnitude + envelope + offset +00110010 32 - magnitude + envelope attack length & level +01110010 72 - magnitude + envelope attack length & level + duration +01101010 6a - magnitude + envelope + duration + offset +``` #### Constant force: ``` @@ -158,33 +172,106 @@ have model specific peculiarities, though. #### Envelope: ``` +envelope attack/fade level/length: + multiple values can be updated with one packet + 60 00 - standard header 01 - ID - 31 - modify envelope - 84 - ID of envelope attribute ( attack_level 82, - attack_length 81, - fade_level 88, - fade_length 84 ) - 63 04 - value attribute should be set to ?***? - 00 00 00 00 00 00 00 00 00 + 31 85 + e8 03 - attack length + dc 05 - fade length + 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +envelope (all): + 60 00 - standard header + 01 - ID + 29 + e8 03 - attack length + cc 0c - attack level + dc 05 - fade length + cc 0c - fade level + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ``` #### Duration: +Update type: + +``` + binary hex +01000001 41 duration +01000100 44 offset +01000101 45 duration + offset +``` + ``` 60 00 - standard header 01 - ID - 49 00 41 - modify timing? - 6c 20 - length in milliseconds - 00 00 00 00 00 00 00 00 + 49 + 00 - effect type? + 45 - update type + 88 13 - duration in milliseconds + 00 00 - offset in milliseconds + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ``` -#### Offset: `N/A` +#### Combined: +``` +magnitude + envelope: + 60 00 - standard header + 01 - ID + 2a + fd 3f - magnitude + e8 03 - attack length + cc 0c - attack level + dc 05 - fade length + cc 0c - fade level + 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +magnitude + envelope attack length & level + duration: + 60 00 - standard header + 01 - ID + 72 + fd 3f - magnitude + 83 - envelope update type + e8 03 - attack length + cc 0c - attack level + 00 - effect type? + 41 - update type + 88 13 - duration + 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +magnitude + envelope + duration + offset: + 60 00 - standard header + 01 - ID + 6a + fd 3f - magnitude + e8 03 - attack length + cc 0c - attack level + dc 05 - fade length + cc 0c - fade level + 00 - effect type? + 45 - update type + 88 13 - duration + 00 00 - offset + 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +``` ## FF_RAMP -- cgit v1.3 From ca9f0bd3a9d4173731df8e4c760bf650ddd5c827 Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Fri, 26 Jul 2024 23:10:58 +0200 Subject: use single packet in constant effect update --- src/tmt300rs/hid-tmt300rs.c | 112 +++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 64 deletions(-) diff --git a/src/tmt300rs/hid-tmt300rs.c b/src/tmt300rs/hid-tmt300rs.c index 2a61199..3316c00 100644 --- a/src/tmt300rs/hid-tmt300rs.c +++ b/src/tmt300rs/hid-tmt300rs.c @@ -335,6 +335,16 @@ static u8 condition_values[] = { 0xff, 0xfe, 0xff }; +static int16_t t300rs_calculate_constant_level(int16_t level, uint16_t direction) +{ + level = (level * fixp_sin16(direction * 360 / 0x10000)) / 0x7fff; + + /* the Windows driver uses the range [-16385;16381] */ + level = level / 2; + + return level; +} + static void t300rs_calculate_periodic_values(struct ff_effect *effect) { struct ff_periodic_effect *periodic = &effect->u.periodic; @@ -619,35 +629,6 @@ error: return ret; } -static int t300rs_update_simple_duration(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state, unsigned type) -{ - struct ff_effect effect = state->effect; - struct __packed t300rs_packet_mod_duration { - struct t300rs_packet_header header; - uint16_t marker; - uint16_t duration; - } *packet_mod_duration = (struct t300rs_packet_mod_duration *)t300rs->send_buffer; - - uint16_t duration; - int ret = 0; - - duration = effect.replay.length - 1; - - t300rs_fill_header(&packet_mod_duration->header, effect.id, 0x49); - packet_mod_duration->marker = cpu_to_le16(0x4100 + type); - packet_mod_duration->duration = cpu_to_le16(duration); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying duration\n"); - goto error; - } - -error: - return ret; -} - static int t300rs_update_constant(struct t300rs_device_entry *t300rs, struct tmff2_effect_state *state) { @@ -657,49 +638,54 @@ static int t300rs_update_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; - uint16_t level; + uint16_t magnitude; + struct t300rs_packet_envelope envelope; + uint8_t effect_type; + uint8_t update_type; + uint16_t duration; + uint16_t offset; } *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; - /* the Windows driver uses the range [-16385;16381] */ - level = level / 2; + int ret = 0; + int16_t level, old_level; + uint16_t length, old_length; - if ((constant.level != constant_old.level) || (effect.direction != old.direction)) { + level = t300rs_calculate_constant_level(constant.level, effect.direction); + old_level = t300rs_calculate_constant_level(constant_old.level, old.direction); - t300rs_fill_header(&packet_mod_constant->header, effect.id, 0x0a); - packet_mod_constant->level = cpu_to_le16(level); + length = effect.replay.length - 1; + old_length = old.replay.length - 1; - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying constant effect\n"); - goto error; - } + if (level != old_level + || constant.envelope.attack_length != constant_old.envelope.attack_length + || constant.envelope.attack_level != constant_old.envelope.attack_level + || constant.envelope.fade_length != constant_old.envelope.fade_length + || constant.envelope.fade_level != constant_old.envelope.fade_level + || length != old_length + || effect.replay.delay != old.replay.delay) { - } + t300rs_fill_header(&packet_mod_constant->header, effect.id, 0x6a); + packet_mod_constant->magnitude = cpu_to_le16(level); - ret = t300rs_update_envelope(t300rs, - state, - level, - effect.replay.length, - effect.id, - constant.envelope, - constant_old.envelope - ); + packet_mod_constant->envelope.attack_length = + cpu_to_le16(constant.envelope.attack_length); + packet_mod_constant->envelope.attack_level = + cpu_to_le16(constant.envelope.attack_level); + packet_mod_constant->envelope.fade_length = + cpu_to_le16(constant.envelope.fade_length); + packet_mod_constant->envelope.fade_level = + cpu_to_le16(constant.envelope.fade_level); - if (ret) { - hid_err(t300rs->hdev, "failed modifying constant envelope\n"); - goto error; - } + packet_mod_constant->effect_type = 0x00; + packet_mod_constant->update_type = 0x45; + packet_mod_constant->duration = length; + packet_mod_constant->offset = effect.replay.delay; - ret = t300rs_update_simple_duration(t300rs, state, 0x00); - if (ret) { - hid_err(t300rs->hdev, "failed modifying constant duration\n"); - goto error; + ret = t300rs_send_int(t300rs); + if (ret) + hid_err(t300rs->hdev, "failed modifying constant effect\n"); } -error: return ret; } @@ -939,9 +925,7 @@ static int t300rs_upload_constant(struct t300rs_device_entry *t300rs, int ret; - level = (constant.level * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; - /* the Windows driver uses the range [-16385;16381] */ - level = level / 2; + level = t300rs_calculate_constant_level(constant.level, effect.direction); duration = effect.replay.length - 1; offset = effect.replay.delay; -- cgit v1.3 From ef17e25c92d252be192ecf1c291ee7586ef9a5e7 Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Tue, 20 Aug 2024 23:16:55 +0200 Subject: envelope documentation --- docs/FFBEFFECTS.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/docs/FFBEFFECTS.md b/docs/FFBEFFECTS.md index a88b55b..3e90475 100644 --- a/docs/FFBEFFECTS.md +++ b/docs/FFBEFFECTS.md @@ -938,6 +938,52 @@ magnitude + offset + phase + period + envelope + duration + offset: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ``` +## Envelope + +Envelope related parameters are the same across all the effects. The only +difference is which effect specific parameters are used during the calculations. + +Damper, Friction, Inertia, and Spring do not support envelope. + +### attack length + +between 0 and 65535 + +On Windows, it has a minimum value depending on how far is the target from the +attack/fade level. This means that in case of an envelope that goes from zero +to max has the minimum length of 256ms. + +```length = abs((effectval * 32768 / effectmax - level) / 128)``` + +`effectval` is the current value of an effect specific parameter + +`effectmax` is the maximum value of `effectval` + +`level` is the current value of the attack/fade level + +Used parameters for each effect: + +| Effect | Parameter | +|----------|-----------| +| Constant | Strength | +| Periodic | Magnitude | +| Ramp | Slope | + +### attack level + +between 0 and 32764 + +### fade length + +between 0 and 65535 + +Uses the same calculation as attack length. + +### fade level + +between 0 and 32764 + + ## PS4 Input `rdesc` ``` ff00.0021 = 0 -- cgit v1.3 From dec88faeaf0d43b6c7a20d43ddf008d1bfb1890c Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Tue, 20 Aug 2024 23:26:12 +0200 Subject: rework envelope handling --- src/tmt300rs/hid-tmt300rs.c | 158 ++++++++------------------------------------ 1 file changed, 28 insertions(+), 130 deletions(-) diff --git a/src/tmt300rs/hid-tmt300rs.c b/src/tmt300rs/hid-tmt300rs.c index 3316c00..32e93e3 100644 --- a/src/tmt300rs/hid-tmt300rs.c +++ b/src/tmt300rs/hid-tmt300rs.c @@ -529,17 +529,23 @@ int t300rs_stop_effect(void *data, struct tmff2_effect_state *state) } static void t300rs_fill_envelope(struct t300rs_packet_envelope *packet_envelope, - int16_t level, uint16_t duration, struct ff_envelope *envelope) + struct ff_envelope *envelope) { - 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); + // Note: minimal length limitations are not enforced + // as per my testing, the wheel can handle lower values well + packet_envelope->attack_length = cpu_to_le16(envelope->attack_length); + packet_envelope->attack_level = cpu_to_le16(envelope->attack_level); + packet_envelope->fade_length = cpu_to_le16(envelope->fade_length); + packet_envelope->fade_level = cpu_to_le16(envelope->fade_level); +} + +static int t300rs_is_envelope_changed(struct ff_envelope *new, + struct ff_envelope *old) +{ + return new->attack_length != old->attack_length + || new->attack_level != old->attack_level + || new->fade_length != old->fade_length + || new->fade_level != old->fade_level; } static void t300rs_fill_timing(struct t300rs_packet_timing *packet_timing, @@ -552,83 +558,6 @@ static void t300rs_fill_timing(struct t300rs_packet_timing *packet_timing, packet_timing->end_marker = 0xffff; } -static int t300rs_update_envelope(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state, - int16_t level, - uint16_t duration, - uint8_t id, - struct ff_envelope envelope, - struct ff_envelope envelope_old - ) -{ - 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; - - 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; - - if (envelope.attack_length != envelope_old.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); - if (ret) { - hid_err(t300rs->hdev, "failed modifying effect envelope\n"); - goto error; - } - } - - if (envelope.attack_level != envelope_old.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); - if (ret) { - hid_err(t300rs->hdev, "failed modifying effect envelope\n"); - goto error; - } - } - - if (envelope.fade_length != envelope_old.fade_length) { - t300rs_fill_header(&packet_mod_envelope->header, id, 0x31); - packet_mod_envelope->attribute = 0x84; - packet_mod_envelope->value = cpu_to_le16(fade_length); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying effect envelope\n"); - goto error; - } - } - - if (envelope.fade_level != envelope_old.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); - if (ret) { - hid_err(t300rs->hdev, "failed modifying effect envelope\n"); - goto error; - } - } - -error: - return ret; -} - static int t300rs_update_constant(struct t300rs_device_entry *t300rs, struct tmff2_effect_state *state) { @@ -657,24 +586,14 @@ static int t300rs_update_constant(struct t300rs_device_entry *t300rs, old_length = old.replay.length - 1; if (level != old_level - || constant.envelope.attack_length != constant_old.envelope.attack_length - || constant.envelope.attack_level != constant_old.envelope.attack_level - || constant.envelope.fade_length != constant_old.envelope.fade_length - || constant.envelope.fade_level != constant_old.envelope.fade_level + || t300rs_is_envelope_changed(&constant.envelope, &constant_old.envelope) || length != old_length || effect.replay.delay != old.replay.delay) { t300rs_fill_header(&packet_mod_constant->header, effect.id, 0x6a); packet_mod_constant->magnitude = cpu_to_le16(level); - packet_mod_constant->envelope.attack_length = - cpu_to_le16(constant.envelope.attack_length); - packet_mod_constant->envelope.attack_level = - cpu_to_le16(constant.envelope.attack_level); - packet_mod_constant->envelope.fade_length = - cpu_to_le16(constant.envelope.fade_length); - packet_mod_constant->envelope.fade_level = - cpu_to_le16(constant.envelope.fade_level); + t300rs_fill_envelope(&packet_mod_constant->envelope, &constant.envelope); packet_mod_constant->effect_type = 0x00; packet_mod_constant->update_type = 0x45; @@ -724,26 +643,18 @@ static int t300rs_update_ramp(struct t300rs_device_entry *t300rs, if (slope != old_slope || center != old_center || invert != old_invert - || ramp.envelope.attack_length != ramp_old.envelope.attack_length - || ramp.envelope.attack_level != ramp_old.envelope.attack_level - || ramp.envelope.fade_length != ramp_old.envelope.fade_length - || ramp.envelope.fade_level != ramp_old.envelope.fade_level || length != old_length - || effect.replay.delay != old.replay.delay) { + || effect.replay.delay != old.replay.delay + || t300rs_is_envelope_changed(&ramp.envelope, &ramp_old.envelope)) { t300rs_fill_header(&packet_mod_ramp->header, effect.id, 0x6e); packet_mod_ramp->type = 0x0b; packet_mod_ramp->slope = cpu_to_le16(slope); packet_mod_ramp->center = cpu_to_le16(center); packet_mod_ramp->length = cpu_to_le16(length); - packet_mod_ramp->envelope.attack_length = - cpu_to_le16(ramp.envelope.attack_length); - packet_mod_ramp->envelope.attack_level = - cpu_to_le16(ramp.envelope.attack_level); - packet_mod_ramp->envelope.fade_length = - cpu_to_le16(ramp.envelope.fade_length); - packet_mod_ramp->envelope.fade_level = - cpu_to_le16(ramp.envelope.fade_level); + + t300rs_fill_envelope(&packet_mod_ramp->envelope, &ramp.envelope); + packet_mod_ramp->effect_type = invert; packet_mod_ramp->update_type = 0x45; packet_mod_ramp->length2 = packet_mod_ramp->length; @@ -871,10 +782,7 @@ static int t300rs_update_periodic(struct t300rs_device_entry *t300rs, || periodic.offset != periodic_old.offset || periodic.phase != periodic_old.phase || periodic.period != periodic_old.period - || periodic.envelope.attack_length != periodic_old.envelope.attack_length - || periodic.envelope.attack_level != periodic_old.envelope.attack_level - || periodic.envelope.fade_length != periodic_old.envelope.fade_length - || periodic.envelope.fade_level != periodic_old.envelope.fade_level + || t300rs_is_envelope_changed(&periodic.envelope, &periodic_old.envelope) || length != old_length || effect.replay.delay != old.replay.delay) { @@ -885,14 +793,7 @@ static int t300rs_update_periodic(struct t300rs_device_entry *t300rs, packet_mod_periodic->phase = cpu_to_le16(periodic.phase); packet_mod_periodic->period = cpu_to_le16(periodic.period); - packet_mod_periodic->envelope.attack_length = - cpu_to_le16(periodic.envelope.attack_length); - packet_mod_periodic->envelope.attack_level = - cpu_to_le16(periodic.envelope.attack_level); - packet_mod_periodic->envelope.fade_length = - cpu_to_le16(periodic.envelope.fade_length); - packet_mod_periodic->envelope.fade_level = - cpu_to_le16(periodic.envelope.fade_level); + t300rs_fill_envelope(&packet_mod_periodic->envelope, &periodic.envelope); packet_mod_periodic->effect_type = periodic.waveform - 0x57; packet_mod_periodic->update_type = 0x45; @@ -934,8 +835,7 @@ static int t300rs_upload_constant(struct t300rs_device_entry *t300rs, packet_constant->level = cpu_to_le16(level); - t300rs_fill_envelope(&packet_constant->envelope, level, duration, - &constant.envelope); + t300rs_fill_envelope(&packet_constant->envelope, &constant.envelope); t300rs_fill_timing(&packet_constant->timing, duration, offset); ret = t300rs_send_int(t300rs); @@ -980,8 +880,7 @@ static int t300rs_upload_ramp(struct t300rs_device_entry *t300rs, packet_ramp->marker = cpu_to_le16(0x8000); - t300rs_fill_envelope(&packet_ramp->envelope, slope, duration, - &ramp.envelope); + t300rs_fill_envelope(&packet_ramp->envelope, &ramp.envelope); packet_ramp->invert = invert; t300rs_fill_timing(&packet_ramp->timing, duration, offset); @@ -1097,8 +996,7 @@ static int t300rs_upload_periodic(struct t300rs_device_entry *t300rs, packet_periodic->marker = cpu_to_le16(0x8000); - t300rs_fill_envelope(&packet_periodic->envelope, magnitude, duration, - &periodic.envelope); + t300rs_fill_envelope(&packet_periodic->envelope, &periodic.envelope); packet_periodic->waveform = periodic.waveform - 0x57; -- cgit v1.3 From ab061f834ced0c6d4ccdd77defa762e2e7ec1382 Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Thu, 22 Aug 2024 20:54:44 +0200 Subject: doc cleanup --- docs/FFBEFFECTS.md | 67 +++++++++++++++++++++--------------------------------- 1 file changed, 26 insertions(+), 41 deletions(-) diff --git a/docs/FFBEFFECTS.md b/docs/FFBEFFECTS.md index 3e90475..a9a313a 100644 --- a/docs/FFBEFFECTS.md +++ b/docs/FFBEFFECTS.md @@ -43,7 +43,7 @@ have model specific peculiarities, though. ### Stopping/removing (why are they rolled into one?) ``` - 60 00 - standard header + 60 00 - standard header 01 - ID 89 - playing options 00 - stop @@ -99,7 +99,7 @@ have model specific peculiarities, though. ``` ## FF_AUTOCENTER: -``` +``` 60 08 - header plus settings? 03 - set autocenter force 8f 02 - force (between ff ff and 00 00) @@ -110,7 +110,7 @@ have model specific peculiarities, though. ``` ## FF_GAIN: -``` +``` 60 02 - header plus gain? bf - gain (between ff and 00) 00 00 00 00 00 00 00 00 00 00 00 00 00 @@ -130,7 +130,8 @@ have model specific peculiarities, though. 00 00 - attack_level *** 00 00 - fade_length 00 00 - fade_level *** - 00 4f - ? + 00 - effect type? + 4f f7 17 - time in milliseconds, unsigned 00 00 07 00 - offset from start(?) @@ -200,15 +201,6 @@ envelope (all): ``` #### Duration: -Update type: - -``` - binary hex -01000001 41 duration -01000100 44 offset -01000101 45 duration + offset -``` - ``` 60 00 - standard header 01 - ID @@ -275,8 +267,6 @@ magnitude + envelope + duration + offset: ## FF_RAMP -Ramps seem to follow triangle wave parameters. - ``` 00001110 00000001 0e 01 - slope 00001110 00000010 0e 02 - center @@ -361,7 +351,7 @@ Valid: ### Modifying: ``` -center: +center: 60 00 - standard header 01 - ID 0e 02 @@ -408,7 +398,7 @@ duration: 4e 08 88 13 - duration 04 - effect type? must reflect the actual inversion 04 or 05 - 41 - update type + 41 - update type, see Update type section 88 13 - duration 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 @@ -420,7 +410,7 @@ offset: 01 - ID 49 04 - effect type? must reflect the actual inversion 04 or 05 - 44 - update type + 44 - update type, see Update type section 00 00 - offset 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 @@ -433,7 +423,7 @@ duration + offset: 4e 08 88 13 - duration 04 - effect type? must reflect the actual inversion 04 or 05 - 45 - update type + 45 - update type, see Update type section 88 13 - duration 00 00 - offset 00 00 00 @@ -446,7 +436,7 @@ dir + offset: 01 - ID 49 05 - effect type? must reflect the actual inversion 04 or 05 - 44 - update type + 44 - update type, see Update type section 00 00 - offset 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 @@ -545,7 +535,7 @@ duration + offset + envelope + slope + center + invert: dc 05 - fade length 32 1a - fade level 04 - effect type? (invert) 04 or 05 - 45 - update type + 45 - update type, see Update type section 88 13 - length 2 00 00 - offset 00 00 00 00 00 00 00 @@ -595,7 +585,7 @@ duration + offset + envelope + slope + center + invert: 4th byte 5th byte hex 00001110 01000001 0e 41 positive coefficient 00001110 01000010 0e 42 negative coefficient -00001110 01000011 0e 43 both coefficint +00001110 01000011 0e 43 both coefficient 00001110 01001100 0e 4c right and left deadband 00001110 01010000 0e 50 positive saturation 00001110 01100000 0e 60 negative saturation @@ -638,7 +628,7 @@ The order of the fields are defined in the `all effect specific parameters + dur positive and negative coefficient: 60 00 01 - ID - 0e 43 + 0e 43 ab 67 - right coefficient, signed, between 01 80 (-32767) and fc 7f (32764) 50 18 - left coefficient, signed, between 01 80 (-32767) and fc 7f (32764) 00 00 00 00 00 00 00 @@ -715,7 +705,7 @@ The order of the fields are defined in the `all effect specific parameters + dur fd 5f - positive saturation fd 5f - negative saturation 06 - effect type (condition)? - 45 - update type, see below + 45 - update type, see Update type section 10 27 - length in milliseconds 00 00 - offset in milliseconds 00 00 00 00 00 00 00 00 00 00 @@ -725,22 +715,12 @@ The order of the fields are defined in the `all effect specific parameters + dur ``` ### Duration: - -Update type: - -``` -6th byte hex -01000001 41 length -01000100 44 offset -01000101 45 length + offset -``` - ``` 60 00 - standard header 01 - ID 49 06 - effect type (condition)? - 45 - update type + 45 - update type, see Update type section 6c 20 - length in milliseconds 00 00 - offset in milliseconds 00 00 00 00 00 00 @@ -866,9 +846,7 @@ envelope (all): 03 - Sine 04 - Sawtooth up 05 - Sawtooth down - 45 - update type 41 - duration - 44 - offset - 45 - duration + offset + 45 - update type, see Update type section 74 27 - duration 00 00 - offset 00 00 00 00 00 00 @@ -928,9 +906,7 @@ magnitude + offset + phase + period + envelope + duration + offset: 03 - Sine 04 - Sawtooth up 05 - Sawtooth down - 45 - update type 41 - duration - 44 - offset - 45 - duration + offset + 45 - update type, see Update type section 74 27 - duration 00 00 - offset 00 00 00 00 00 @@ -984,6 +960,15 @@ Uses the same calculation as attack length. between 0 and 32764 +## Update type + +``` +binary hex +01000001 41 duration +01000100 44 offset +01000101 45 duration + offset +``` + ## PS4 Input `rdesc` ``` ff00.0021 = 0 -- cgit v1.3 From 760a3bb24312d0feb728008aa2c21543145dc639 Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Sun, 1 Sep 2024 16:32:59 +0200 Subject: fix missing cpu_to_le16 --- src/tmt300rs/hid-tmt300rs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tmt300rs/hid-tmt300rs.c b/src/tmt300rs/hid-tmt300rs.c index 32e93e3..7d540dc 100644 --- a/src/tmt300rs/hid-tmt300rs.c +++ b/src/tmt300rs/hid-tmt300rs.c @@ -597,8 +597,8 @@ static int t300rs_update_constant(struct t300rs_device_entry *t300rs, packet_mod_constant->effect_type = 0x00; packet_mod_constant->update_type = 0x45; - packet_mod_constant->duration = length; - packet_mod_constant->offset = effect.replay.delay; + packet_mod_constant->duration = cpu_to_le16(length); + packet_mod_constant->offset = cpu_to_le16(effect.replay.delay); ret = t300rs_send_int(t300rs); if (ret) @@ -797,8 +797,8 @@ static int t300rs_update_periodic(struct t300rs_device_entry *t300rs, packet_mod_periodic->effect_type = periodic.waveform - 0x57; packet_mod_periodic->update_type = 0x45; - packet_mod_periodic->duration = length; - packet_mod_periodic->play_offset = effect.replay.delay; + packet_mod_periodic->duration = cpu_to_le16(length); + packet_mod_periodic->play_offset = cpu_to_le16(effect.replay.delay); ret = t300rs_send_int(t300rs); if (ret) -- cgit v1.3 From dcbf4f07ae927e9284b53c795496d591fdcc10c2 Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Sun, 1 Sep 2024 16:34:54 +0200 Subject: fix incorrect return type --- src/tmt300rs/hid-tmt300rs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tmt300rs/hid-tmt300rs.c b/src/tmt300rs/hid-tmt300rs.c index 7d540dc..7f95b8d 100644 --- a/src/tmt300rs/hid-tmt300rs.c +++ b/src/tmt300rs/hid-tmt300rs.c @@ -379,7 +379,7 @@ static uint16_t t300rs_condition_max_saturation(uint16_t effect_type) return 0x7ffc; } -static uint16_t t300rs_condition_effect_type(uint16_t effect_type) +static uint8_t t300rs_condition_effect_type(uint16_t effect_type) { if(effect_type == FF_SPRING) return 0x06; -- cgit v1.3 From 901b37cd82a002da9112fa2882eb2fdfa2f6729b Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Sun, 1 Sep 2024 16:41:29 +0200 Subject: fix style --- src/tmt300rs/hid-tmt300rs.c | 186 ++++++++++++++++++++++---------------------- 1 file changed, 93 insertions(+), 93 deletions(-) diff --git a/src/tmt300rs/hid-tmt300rs.c b/src/tmt300rs/hid-tmt300rs.c index 7f95b8d..2f3e0e8 100644 --- a/src/tmt300rs/hid-tmt300rs.c +++ b/src/tmt300rs/hid-tmt300rs.c @@ -531,8 +531,8 @@ int t300rs_stop_effect(void *data, struct tmff2_effect_state *state) static void t300rs_fill_envelope(struct t300rs_packet_envelope *packet_envelope, struct ff_envelope *envelope) { - // Note: minimal length limitations are not enforced - // as per my testing, the wheel can handle lower values well + // Note: Minimal length limitations are not enforced, + // as testing shows that the wheel can handle lower values well packet_envelope->attack_length = cpu_to_le16(envelope->attack_length); packet_envelope->attack_level = cpu_to_le16(envelope->attack_level); packet_envelope->fade_length = cpu_to_le16(envelope->fade_length); @@ -585,25 +585,25 @@ static int t300rs_update_constant(struct t300rs_device_entry *t300rs, length = effect.replay.length - 1; old_length = old.replay.length - 1; - if (level != old_level - || t300rs_is_envelope_changed(&constant.envelope, &constant_old.envelope) - || length != old_length - || effect.replay.delay != old.replay.delay) { + if (!t300rs_is_envelope_changed(&constant.envelope, &constant_old.envelope) + && level == old_level + && length == old_length + && effect.replay.delay == old.replay.delay) + return ret; - t300rs_fill_header(&packet_mod_constant->header, effect.id, 0x6a); - packet_mod_constant->magnitude = cpu_to_le16(level); + t300rs_fill_header(&packet_mod_constant->header, effect.id, 0x6a); + packet_mod_constant->magnitude = cpu_to_le16(level); - t300rs_fill_envelope(&packet_mod_constant->envelope, &constant.envelope); + t300rs_fill_envelope(&packet_mod_constant->envelope, &constant.envelope); - packet_mod_constant->effect_type = 0x00; - packet_mod_constant->update_type = 0x45; - packet_mod_constant->duration = cpu_to_le16(length); - packet_mod_constant->offset = cpu_to_le16(effect.replay.delay); + packet_mod_constant->effect_type = 0x00; + packet_mod_constant->update_type = 0x45; + packet_mod_constant->duration = cpu_to_le16(length); + packet_mod_constant->offset = cpu_to_le16(effect.replay.delay); - ret = t300rs_send_int(t300rs); - if (ret) - hid_err(t300rs->hdev, "failed modifying constant effect\n"); - } + ret = t300rs_send_int(t300rs); + if (ret) + hid_err(t300rs->hdev, "failed modifying constant effect\n"); return ret; } @@ -640,30 +640,30 @@ static int t300rs_update_ramp(struct t300rs_device_entry *t300rs, length = effect.replay.length - 1; old_length = old.replay.length - 1; - if (slope != old_slope - || center != old_center - || invert != old_invert - || length != old_length - || effect.replay.delay != old.replay.delay - || t300rs_is_envelope_changed(&ramp.envelope, &ramp_old.envelope)) { - - t300rs_fill_header(&packet_mod_ramp->header, effect.id, 0x6e); - packet_mod_ramp->type = 0x0b; - packet_mod_ramp->slope = cpu_to_le16(slope); - packet_mod_ramp->center = cpu_to_le16(center); - packet_mod_ramp->length = cpu_to_le16(length); - - t300rs_fill_envelope(&packet_mod_ramp->envelope, &ramp.envelope); - - packet_mod_ramp->effect_type = invert; - packet_mod_ramp->update_type = 0x45; - packet_mod_ramp->length2 = packet_mod_ramp->length; - packet_mod_ramp->offset = cpu_to_le16(effect.replay.delay); - - ret = t300rs_send_int(t300rs); - if (ret) - hid_err(t300rs->hdev, "failed modifying ramp effect\n"); - } + if (!t300rs_is_envelope_changed(&ramp.envelope, &ramp_old.envelope) + && slope == old_slope + && center == old_center + && invert == old_invert + && length == old_length + && effect.replay.delay == old.replay.delay) + return ret; + + t300rs_fill_header(&packet_mod_ramp->header, effect.id, 0x6e); + packet_mod_ramp->type = 0x0b; + packet_mod_ramp->slope = cpu_to_le16(slope); + packet_mod_ramp->center = cpu_to_le16(center); + packet_mod_ramp->length = cpu_to_le16(length); + + t300rs_fill_envelope(&packet_mod_ramp->envelope, &ramp.envelope); + + packet_mod_ramp->effect_type = invert; + packet_mod_ramp->update_type = 0x45; + packet_mod_ramp->length2 = packet_mod_ramp->length; + packet_mod_ramp->offset = cpu_to_le16(effect.replay.delay); + + ret = t300rs_send_int(t300rs); + if (ret) + hid_err(t300rs->hdev, "failed modifying ramp effect\n"); return ret; } @@ -716,32 +716,32 @@ static int t300rs_update_condition(struct t300rs_device_entry *t300rs, duration = effect.replay.length - 1; duration_old = old.replay.length - 1; - if (right_coeff != right_coeff_old - || left_coeff != left_coeff_old - || right_deadband != right_deadband_old - || left_deadband != left_deadband_old - || right_sat != right_sat_old - || left_sat != left_sat_old - || duration != duration_old - || effect.replay.delay != old.replay.delay) { - - packet_mod_condition->right_coeff = cpu_to_le16(right_coeff); - packet_mod_condition->left_coeff = cpu_to_le16(left_coeff); - packet_mod_condition->right_deadband = cpu_to_le16(right_deadband); - packet_mod_condition->left_deadband = cpu_to_le16(left_deadband); - packet_mod_condition->right_saturation = cpu_to_le16(right_sat); - packet_mod_condition->left_saturation = cpu_to_le16(left_sat); - packet_mod_condition->effect_type = 0x06; - packet_mod_condition->update_type = 0x45; - packet_mod_condition->duration = cpu_to_le16(duration); - packet_mod_condition->delay = cpu_to_le16(effect.replay.delay); - - t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x4c); - - ret = t300rs_send_int(t300rs); - if (ret) - hid_err(t300rs->hdev, "failed modifying condition effect\n"); - } + if (right_coeff == right_coeff_old + && left_coeff == left_coeff_old + && right_deadband == right_deadband_old + && left_deadband == left_deadband_old + && right_sat == right_sat_old + && left_sat == left_sat_old + && duration == duration_old + && effect.replay.delay == old.replay.delay) + return ret; + + packet_mod_condition->right_coeff = cpu_to_le16(right_coeff); + packet_mod_condition->left_coeff = cpu_to_le16(left_coeff); + packet_mod_condition->right_deadband = cpu_to_le16(right_deadband); + packet_mod_condition->left_deadband = cpu_to_le16(left_deadband); + packet_mod_condition->right_saturation = cpu_to_le16(right_sat); + packet_mod_condition->left_saturation = cpu_to_le16(left_sat); + packet_mod_condition->effect_type = 0x06; + packet_mod_condition->update_type = 0x45; + packet_mod_condition->duration = cpu_to_le16(duration); + packet_mod_condition->delay = cpu_to_le16(effect.replay.delay); + + t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x4c); + + ret = t300rs_send_int(t300rs); + if (ret) + hid_err(t300rs->hdev, "failed modifying condition effect\n"); return ret; } @@ -778,32 +778,32 @@ static int t300rs_update_periodic(struct t300rs_device_entry *t300rs, length = effect.replay.length - 1; old_length = old.replay.length - 1; - if (periodic.magnitude != periodic_old.magnitude - || periodic.offset != periodic_old.offset - || periodic.phase != periodic_old.phase - || periodic.period != periodic_old.period - || t300rs_is_envelope_changed(&periodic.envelope, &periodic_old.envelope) - || length != old_length - || effect.replay.delay != old.replay.delay) { - - t300rs_fill_header(&packet_mod_periodic->header, effect.id, 0x6e); - packet_mod_periodic->type = 0x0f; - packet_mod_periodic->magnitude = cpu_to_le16(periodic.magnitude); - packet_mod_periodic->offset = cpu_to_le16(periodic.offset); - packet_mod_periodic->phase = cpu_to_le16(periodic.phase); - packet_mod_periodic->period = cpu_to_le16(periodic.period); - - t300rs_fill_envelope(&packet_mod_periodic->envelope, &periodic.envelope); - - packet_mod_periodic->effect_type = periodic.waveform - 0x57; - packet_mod_periodic->update_type = 0x45; - packet_mod_periodic->duration = cpu_to_le16(length); - packet_mod_periodic->play_offset = cpu_to_le16(effect.replay.delay); - - ret = t300rs_send_int(t300rs); - if (ret) - hid_err(t300rs->hdev, "failed modifying periodic effect\n"); - } + if (!t300rs_is_envelope_changed(&periodic.envelope, &periodic_old.envelope) + && periodic.magnitude == periodic_old.magnitude + && periodic.offset == periodic_old.offset + && periodic.phase == periodic_old.phase + && periodic.period == periodic_old.period + && length == old_length + && effect.replay.delay == old.replay.delay) + return ret; + + t300rs_fill_header(&packet_mod_periodic->header, effect.id, 0x6e); + packet_mod_periodic->type = 0x0f; + packet_mod_periodic->magnitude = cpu_to_le16(periodic.magnitude); + packet_mod_periodic->offset = cpu_to_le16(periodic.offset); + packet_mod_periodic->phase = cpu_to_le16(periodic.phase); + packet_mod_periodic->period = cpu_to_le16(periodic.period); + + t300rs_fill_envelope(&packet_mod_periodic->envelope, &periodic.envelope); + + packet_mod_periodic->effect_type = periodic.waveform - 0x57; + packet_mod_periodic->update_type = 0x45; + packet_mod_periodic->duration = cpu_to_le16(length); + packet_mod_periodic->play_offset = cpu_to_le16(effect.replay.delay); + + ret = t300rs_send_int(t300rs); + if (ret) + hid_err(t300rs->hdev, "failed modifying periodic effect\n"); return ret; } -- cgit v1.3