// SPDX-License-Identifier: GPL-2.0-or-later #include #include #include #include #include "hid-tmff2.h" int open_mode = 1; module_param(open_mode, int, 0660); MODULE_PARM_DESC(open_mode, "Whether to send mode change commands on open/close"); 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? */ 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"); 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"); 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"); int range = 900; module_param(range, int, 0); MODULE_PARM_DESC(range, "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"); #define GAIN_MAX 65535 u16 gain = 40000; module_param(gain, ushort, 0); MODULE_PARM_DESC(gain, "Level of gain (0-65535)"); static u16 tmff2_scale_gain(u16 value) { return (u32)value * gain / GAIN_MAX; } static spinlock_t lock; static struct tmff2_device_entry *tmff2_from_hdev(struct hid_device *hdev) { unsigned long lock_flags = 0; 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"); spin_unlock_irqrestore(&lock, lock_flags); return tmff2; } static struct tmff2_device_entry *tmff2_from_input(struct input_dev *input_dev) { unsigned long lock_flags = 0; struct hid_device *hdev; spin_lock_irqsave(&lock, lock_flags); if (!(hdev = input_get_drvdata(input_dev))) dev_err(&input_dev->dev, "input_dev private data not found\n"); spin_unlock_irqrestore(&lock, lock_flags); return tmff2_from_hdev(hdev); } 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) { return scnprintf(buf, PAGE_SIZE, "%u\n", friction_level); } 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 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)); if (!tmff2) return -ENODEV; if (tmff2->alt_mode_store) return tmff2->alt_mode_store(tmff2->data, buf, count); return 0; } static ssize_t alternate_modes_show(struct device *dev, struct device_attribute *attr, char *buf) { struct tmff2_device_entry *tmff2 = tmff2_from_hdev(to_hid_device(dev)); if (!tmff2) return -ENODEV; if (tmff2->alt_mode_show) return tmff2->alt_mode_show(tmff2->data, buf); return 0; } static DEVICE_ATTR_RW(alternate_modes); 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)); u16 value; int ret; if (!tmff2) return -ENODEV; ret = kstrtou16(buf, 0, &value); if (ret) { dev_err(dev, "failed to parse gain: %d\n", ret); return ret; } gain = value; if (tmff2->set_gain) /* if we can, update gain immediately */ tmff2->set_gain(tmff2->data, gain); return count; } static ssize_t gain_show(struct device *dev, struct device_attribute *attr, char *buf) { return scnprintf(buf, PAGE_SIZE, "%u\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); if (!tmff2) return; if (!tmff2->set_gain) { hid_err(tmff2->hdev, "missing set_gain\n"); return; } if (tmff2->set_gain(tmff2->data, tmff2_scale_gain(value))) hid_warn(tmff2->hdev, "unable to set gain\n"); } static void tmff2_set_autocenter(struct input_dev *dev, uint16_t value) { 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, value)) hid_warn(tmff2->hdev, "unable to set autocenter\n"); } static void tmff2_work_handler(struct work_struct *w) { unsigned long lock_flags = 0; 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_delay, effect_length; if (!tmff2) return; for (effect_id = 0; effect_id < tmff2->max_effects; ++effect_id) { unsigned long actions = 0; struct tmff2_effect_state effect; time_now = JIFFIES2MS(jiffies); state = &tmff2->states[effect_id]; /* critical section for updating state flags, keep log of what * actions to take after the critical section with actions */ spin_lock_irqsave(&tmff2->lock, lock_flags); 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_delay + effect_length) * state->count) { __clear_bit(FF_EFFECT_PLAYING, &state->flags); __clear_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags); state->count = 0; } } if (test_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags)) { __set_bit(FF_EFFECT_QUEUE_UPLOAD, &actions); __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); /* if we're uploading an effect, it's bound to be up * to date */ __clear_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags); } if (test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)) { __set_bit(FF_EFFECT_QUEUE_UPDATE, &actions); __clear_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags); } if (test_bit(FF_EFFECT_QUEUE_START, &state->flags)) { __set_bit(FF_EFFECT_QUEUE_START, &actions); __clear_bit(FF_EFFECT_QUEUE_START, &state->flags); /* effect is playing since we're started it right now */ __set_bit(FF_EFFECT_PLAYING, &state->flags); } if (test_bit(FF_EFFECT_QUEUE_STOP, &state->flags)) { __set_bit(FF_EFFECT_QUEUE_STOP, &actions); __clear_bit(FF_EFFECT_QUEUE_STOP, &state->flags); /* the effect can't be playing if we're stopped, aye? */ __clear_bit(FF_EFFECT_PLAYING, &state->flags); } if (state->count > max_count) max_count = state->count; /* copy effect state to local variable so we can pass it around * after the atomic section */ effect = *state; spin_unlock_irqrestore(&tmff2->lock, lock_flags); /* perform the identified actions */ if (test_bit(FF_EFFECT_QUEUE_UPLOAD, &actions) && tmff2->upload_effect(tmff2->data, &effect)) { hid_warn(tmff2->hdev, "failed uploading effect\n"); } if (test_bit(FF_EFFECT_QUEUE_UPDATE, &actions) && tmff2->update_effect(tmff2->data, &effect)) { hid_warn(tmff2->hdev, "failed updating effect\n"); } if (test_bit(FF_EFFECT_QUEUE_START, &actions) && tmff2->play_effect(tmff2->data, &effect)) { hid_warn(tmff2->hdev, "failed starting effect\n"); } if (test_bit(FF_EFFECT_QUEUE_STOP, &actions) && tmff2->stop_effect(tmff2->data, &effect)) { hid_warn(tmff2->hdev, "failed stopping effect\n"); } /* wait for each effect update to actually be sent out to avoid * filling up usb output queue */ hid_hw_wait(tmff2->hdev); } if (max_count && tmff2->allow_scheduling) 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) { unsigned long lock_flags = 0; 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_irqsave(&tmff2->lock, lock_flags); state->effect = *effect; tmff2_rewrite_rumble(&state->effect); if (old) { 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 { __set_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); } spin_unlock_irqrestore(&tmff2->lock, lock_flags); return 0; } static int tmff2_play(struct input_dev *dev, int effect_id, int value) { unsigned long lock_flags = 0; 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) return 0; spin_lock_irqsave(&tmff2->lock, lock_flags); 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_irqrestore(&tmff2->lock, lock_flags); if (!delayed_work_pending(&tmff2->work) && tmff2->allow_scheduling) 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, open_mode); 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; /* since we're closing the device, no need to continue feeding it new data */ /* TODO: check somewhere that multiple users can't open us at the same * time */ cancel_delayed_work_sync(&tmff2->work); if (tmff2->close) { tmff2->close(tmff2->data, open_mode); return; } 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 & 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_alternate_modes))) { hid_err(tmff2->hdev, "unable to create sysfs for alternate_modes\n"); goto alt_err; } } 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 & 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 & 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 & 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; } } 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_alternate_modes); alt_err: device_remove_file(dev, &dev_attr_gain); gain_err: return ret; } 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, open_mode))) goto err; tmff2->states = kzalloc(sizeof(struct tmff2_effect_state) * tmff2->max_effects, GFP_KERNEL); if (!tmff2->states) { ret = -ENOMEM; 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); /* 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 ff_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; /* set defaults wherever possible */ if (tmff2->set_gain) { ff->set_gain = tmff2_set_gain; tmff2->set_gain(tmff2->data, gain); } if (tmff2->set_autocenter) ff->set_autocenter = tmff2_set_autocenter; 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 file_err; tmff2->allow_scheduling = 1; return 0; file_err: input_ff_destroy(tmff2->input_dev); ff_err: kfree(tmff2->states); 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); switch (tmff2->hdev->product) { 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; case TMT248_PC_ID: if ((ret = t248_populate_api(tmff2))) goto wheel_err; break; case TX_ACTIVE: if ((ret = tx_populate_api(tmff2))) goto wheel_err; break; case TSXW_ACTIVE: if ((ret = tsxw_populate_api(tmff2))) goto wheel_err; break; case TMTS_PC_RACER_ID: if ((ret = tspc_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; } 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; } return 0; init_err: hid_hw_stop(hdev); hid_err: tmff2->wheel_destroy(tmff2->data); wheel_err: kfree(tmff2); oom_err: return ret; } #if LINUX_VERSION_CODE < KERNEL_VERSION(6,12,0) static __u8 *tmff2_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) #else static const __u8 *tmff2_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) #endif { 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); struct device *dev; if (!tmff2) return; tmff2->allow_scheduling = 0; cancel_delayed_work_sync(&tmff2->work); dev = &tmff2->hdev->dev; if (tmff2->params & PARAM_FRICTION_LEVEL) device_remove_file(dev, &dev_attr_friction_level); if (tmff2->params & PARAM_DAMPER_LEVEL) device_remove_file(dev, &dev_attr_damper_level); if (tmff2->params & PARAM_SPRING_LEVEL) device_remove_file(dev, &dev_attr_spring_level); if (tmff2->params & PARAM_RANGE) device_remove_file(dev, &dev_attr_range); if (tmff2->params & PARAM_ALT_MODE) device_remove_file(dev, &dev_attr_alternate_modes); if (tmff2->params & PARAM_GAIN) device_remove_file(dev, &dev_attr_gain); hid_hw_stop(hdev); tmff2->wheel_destroy(tmff2->data); kfree(tmff2->states); kfree(tmff2); } static int tmff2_input_configured(struct hid_device *hdev, struct hid_input *hidinput) { struct input_dev *input = hidinput->input; int axis; if (!input->absinfo) return 0; for (axis = ABS_X; axis <= ABS_BRAKE; axis++) { if (!test_bit(axis, input->absbit)) continue; input_abs_set_fuzz(input, axis, 0); input_abs_set_flat(input, axis, 0); } return 0; } static const struct hid_device_id tmff2_devices[] = { /* t300rs and variations */ {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)}, /* tx */ {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, TX_ACTIVE)}, /* TS-PC RACER */ {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, TMTS_PC_RACER_ID)}, /* tsxw */ {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, TSXW_ACTIVE)}, {} }; 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, .input_configured = tmff2_input_configured, }; module_hid_driver(tmff2_driver); MODULE_DESCRIPTION("FFB for Thrustmaster wheels"); MODULE_LICENSE("GPL");