diff options
Diffstat (limited to 'src/hid-tmff2.c')
| -rw-r--r-- | src/hid-tmff2.c | 69 |
1 files changed, 58 insertions, 11 deletions
diff --git a/src/hid-tmff2.c b/src/hid-tmff2.c index ee4232a..3b51445 100644 --- a/src/hid-tmff2.c +++ b/src/hid-tmff2.c @@ -292,7 +292,7 @@ static void tmff2_work_handler(struct work_struct *w) struct tmff2_effect_state *state; int max_count = 0, effect_id; unsigned long time_now; - __u16 effect_length; + __u16 effect_delay, effect_length; if (!tmff2) @@ -304,17 +304,14 @@ static void tmff2_work_handler(struct work_struct *w) time_now = JIFFIES2MS(jiffies); state = &tmff2->states[effect_id]; + effect_delay = state->effect.replay.delay; effect_length = state->effect.replay.length; if (test_bit(FF_EFFECT_PLAYING, &state->flags) && effect_length) { - if ((time_now - state->start_time) >= effect_length) { + if ((time_now - state->start_time) >= (effect_delay + effect_length) * state->count) { __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); + state->count = 0; } } @@ -359,6 +356,7 @@ static void tmff2_work_handler(struct work_struct *w) max_count = state->count; spin_unlock(&tmff2->lock); + /* wait for each effect update to actually be sent out to avoid * filling up usb output queue */ hid_hw_wait(tmff2->hdev); @@ -368,6 +366,32 @@ static void tmff2_work_handler(struct work_struct *w) schedule_delayed_work(&tmff2->work, msecs_to_jiffies(timer_msecs)); } +static void tmff2_rewrite_rumble(struct ff_effect *effect) +{ + /* this is more or less directly copied from + * https://elixir.bootlin.com/linux/latest/source/drivers/input/ff-core.c#L48 + * except we set the direction to east, to make sure the direction + * scaling doesn't do any funny business */ + int magnitude = 0; + if (effect->type != FF_RUMBLE) + return; + + magnitude = effect->u.rumble.strong_magnitude / 3 + + effect->u.rumble.weak_magnitude / 6; + + effect->type = FF_PERIODIC; + effect->direction = 16384; + effect->u.periodic.waveform = FF_SINE; + effect->u.periodic.period = 50; + effect->u.periodic.magnitude = magnitude; + effect->u.periodic.offset = 0; + effect->u.periodic.phase = 0; + effect->u.periodic.envelope.attack_length = 0; + effect->u.periodic.envelope.attack_level = 0; + effect->u.periodic.envelope.fade_length = 0; + effect->u.periodic.envelope.fade_level = 0; +} + static int tmff2_upload(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old) { @@ -385,10 +409,13 @@ static int tmff2_upload(struct input_dev *dev, spin_lock(&tmff2->lock); state->effect = *effect; + tmff2_rewrite_rumble(&state->effect); if (old) { - if (!test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) + if (!test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { state->old = *old; + tmff2_rewrite_rumble(&state->old); + } __set_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags); } else { @@ -555,10 +582,22 @@ static int tmff2_wheel_init(struct tmff2_device_entry *tmff2) for (i = 0; tmff2->supported_effects[i] >= 0; ++i) __set_bit(tmff2->supported_effects[i], tmff2->input_dev->ffbit); + /* tell ffb subsystem that we want to handle our own rumble effects, + * this is a (maybe kind of silly) workaround to the ffb subsystem + * setting the direction of rumble to 0, which in our case means 0 + * force. Instead, do exactly what the subsystem would do, but update + * the direction. + * + * It *might* be a good idea to change this in the subsystem proper, but + * I don't know if anyone relies on the rumble to be 0 degrees, consider + * this just a proof of concept for now */ + if (test_bit(FF_PERIODIC, tmff2->input_dev->ffbit)) + __set_bit(FF_RUMBLE, 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; + goto ff_err; } /* set ff callbacks */ @@ -589,12 +628,15 @@ static int tmff2_wheel_init(struct tmff2_device_entry *tmff2) /* create files */ if ((ret = tmff2_create_files(tmff2))) - goto err; + goto file_err; tmff2->allow_scheduling = 1; return 0; +file_err: input_ff_destroy(tmff2->input_dev); +ff_err: + kfree(tmff2->states); err: return ret; } @@ -632,7 +674,10 @@ static int tmff2_probe(struct hid_device *hdev, const struct hid_device_id *id) if ((ret = tx_populate_api(tmff2))) goto wheel_err; break; - + case TSXW_ACTIVE: + if ((ret = tsxw_populate_api(tmff2))) + goto wheel_err; + break; default: ret = -ENODEV; goto wheel_err; @@ -727,6 +772,8 @@ static const struct hid_device_id tmff2_devices[] = { {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, TMT248_PC_ID)}, /* tx */ {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, TX_ACTIVE)}, + /* tsxw */ + {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, TSXW_ACTIVE)}, {} }; |
