Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions src/hid-tmff2.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ module_param(gain, int, 0);
MODULE_PARM_DESC(gain,
"Level of gain (0-65535)");


//Combine Pedals / Center Clutch patch
bool combine_pedals = false;
bool center_clutch = false;

module_param(combine_pedals, bool, 0);
MODULE_PARM_DESC(combine_pedals, "Combine gas and brake into a single Z axis (default: false)");

module_param(center_clutch, bool, 0);
MODULE_PARM_DESC(center_clutch, "Center clutch axis when combine_pedals is active (default: false)");

//Combine Pedals / Center Clutch patch

static spinlock_t lock;

static struct tmff2_device_entry *tmff2_from_hdev(struct hid_device *hdev)
Expand Down Expand Up @@ -255,6 +268,78 @@ static ssize_t gain_show(struct device *dev,
}
static DEVICE_ATTR_RW(gain);

//Combine Pedals patch

static ssize_t combine_pedals_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;

ret = kstrtouint(buf, 0, &value);
if (ret) {
dev_err(dev, "kstrtouint failed at combine_pedals_store: %i", ret);
return ret;
}

combine_pedals = (bool)value;

if (tmff2)
tmff2->combine_pedals = (bool)value;

return count;
}

static ssize_t combine_pedals_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;

return scnprintf(buf, PAGE_SIZE, "%u\n", tmff2->combine_pedals);
}

static DEVICE_ATTR_RW(combine_pedals);

//Center Clutch Settings
static ssize_t center_clutch_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;

ret = kstrtouint(buf, 0, &value);
if (ret) {
dev_err(dev, "kstrtouint failed at center_clutch_store: %i", ret);
return ret;
}

center_clutch = (bool)value;

if (tmff2)
tmff2->center_clutch = (bool)value;

return count;
}

static ssize_t center_clutch_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;

return scnprintf(buf, PAGE_SIZE, "%u\n", tmff2->center_clutch);
}
static DEVICE_ATTR_RW(center_clutch);

//Combine Pedals / Center Clutch patch

static void tmff2_set_gain(struct input_dev *dev, uint16_t value)
{
struct tmff2_device_entry *tmff2 = tmff2_from_input(dev);
Expand Down Expand Up @@ -569,8 +654,28 @@ static int tmff2_create_files(struct tmff2_device_entry *tmff2)
}
}

//Combine Pedals / Center Clutch patch
if (tmff2->params & PARAM_COMBINE_PEDALS) {
if ((ret = device_create_file(dev, &dev_attr_combine_pedals))) {
hid_warn(tmff2->hdev, "unable to create sysfs for combine_pedals\n");
goto combine_err;
}
}

//Combine Pedals / Center Clutch patch
if (tmff2->params & PARAM_CENTER_CLUTCH) {
if ((ret = device_create_file(dev, &dev_attr_center_clutch))) {
hid_warn(tmff2->hdev, "unable to create sysfs for center_clutch\n");
goto center_clutch_err;
}
}

return 0;

center_clutch_err:
device_remove_file(dev, &dev_attr_combine_pedals); //Combine Pedals / Center Clutch patch
combine_err:
device_remove_file(dev, &dev_attr_friction_level); //Combine Pedals / Center Clutch patch
friction_err:
device_remove_file(dev, &dev_attr_damper_level);
damper_err:
Expand Down Expand Up @@ -716,6 +821,10 @@ static int tmff2_probe(struct hid_device *hdev, const struct hid_device_id *id)
goto wheel_err;
}

//Combine Pedals / Center Clutch patch
tmff2->combine_pedals = combine_pedals;
tmff2->center_clutch = center_clutch;

if ((ret = hid_parse(tmff2->hdev))) {
hid_err(hdev, "parse failed\n");
goto hid_err;
Expand Down Expand Up @@ -764,6 +873,17 @@ static const __u8 *tmff2_report_fixup(struct hid_device *hdev, __u8 *rdesc,
return rdesc;
}

static int tmff2_raw_event(struct hid_device *hdev, struct hid_report *report,
u8 *data, int size)
{
struct tmff2_device_entry *tmff2 = tmff2_from_hdev(hdev);

if (!tmff2 || !tmff2->raw_event)
return 0;

return tmff2->raw_event(hdev, report, data, size);
}

static void tmff2_remove(struct hid_device *hdev)
{
struct tmff2_device_entry *tmff2 = tmff2_from_hdev(hdev);
Expand Down Expand Up @@ -794,6 +914,12 @@ static void tmff2_remove(struct hid_device *hdev)
if (tmff2->params & PARAM_GAIN)
device_remove_file(dev, &dev_attr_gain);

if (tmff2->params & PARAM_COMBINE_PEDALS)
device_remove_file(dev, &dev_attr_combine_pedals);

if (tmff2->params & PARAM_CENTER_CLUTCH)
device_remove_file(dev, &dev_attr_center_clutch);

hid_hw_stop(hdev);
tmff2->wheel_destroy(tmff2->data);

Expand Down Expand Up @@ -825,6 +951,7 @@ static struct hid_driver tmff2_driver = {
.probe = tmff2_probe,
.remove = tmff2_remove,
.report_fixup = tmff2_report_fixup,
.raw_event = tmff2_raw_event, //Combine Pedals patch
};
module_hid_driver(tmff2_driver);

Expand Down
14 changes: 14 additions & 0 deletions src/hid-tmff2.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ extern int range;
extern int gain;
extern int alt_mode;

//Combine Pedals / Center Clutch patch
extern bool combine_pedals;
extern bool center_clutch;

#define USB_VENDOR_ID_THRUSTMASTER 0x044f

/* the wheel seems to only be capable of processing a certain number of
Expand All @@ -37,6 +41,10 @@ extern int alt_mode;
#define PARAM_ALT_MODE (1 << 4)
#define PARAM_GAIN (1 << 5)

//Combine Pedals / Center Clutch patch
#define PARAM_COMBINE_PEDALS (1 << 6) //Combine Pedals
#define PARAM_CENTER_CLUTCH (1 << 7) //Clutch always 512 (Centered)

#undef fixp_sin16
#define fixp_sin16(v) (((v % 360) > 180) ?\
-(fixp_sin32((v % 360) - 180) >> 16)\
Expand Down Expand Up @@ -93,9 +101,15 @@ struct tmff2_device_entry {
ssize_t (*alt_mode_store)(void *data, const char *buf, size_t count);
int (*set_autocenter)(void *data, uint16_t autocenter);
__u8 *(*wheel_fixup)(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize);
int (*raw_event)(struct hid_device *hdev, struct hid_report *report, u8 *data, int size);

/* void pointers are dangerous, I know, but in this case likely the
* best option... */

//Combine Pedals / Center Clutch patch
bool combine_pedals;
bool center_clutch;

};

/* external */
Expand Down
120 changes: 118 additions & 2 deletions src/tmt300rs/hid-tmt300rs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <linux/usb.h>
#include <linux/hid.h>
#include "../hid-tmff2.h"
#include <linux/unaligned.h>

#define T300RS_MAX_EFFECTS 16
#define T300RS_NORM_BUFFER_LENGTH 63
Expand All @@ -17,6 +18,8 @@ static const unsigned long t300rs_params =
| PARAM_GAIN
| PARAM_RANGE
| PARAM_ALT_MODE
| PARAM_COMBINE_PEDALS
| PARAM_CENTER_CLUTCH
;

static const signed short t300rs_effects[] = {
Expand Down Expand Up @@ -84,6 +87,73 @@ struct t300rs_data {
void *device_props;
};

static u8 t300rs_rdesc_nrm_combined[] = {
0x05, 0x01,
0x09, 0x04,
0xa1, 0x01,
0x09, 0x01,
0xa1, 0x00,
0x85, 0x07,
0x09, 0x30, /* X (wheel) */
0x15, 0x00,
0x27, 0xff, 0xff, 0x00, 0x00,
0x35, 0x00,
0x47, 0xff, 0xff, 0x00, 0x00,
0x75, 0x10,
0x95, 0x01,
0x81, 0x02,
0x81, 0x03, /* brake slot → constant (hidden) */
0x09, 0x32, /* Z (combined gas/brake) */
0x26, 0xff, 0x03,
0x46, 0xff, 0x03,
0x75, 0x10,
0x95, 0x01,
0x81, 0x02,
0x09, 0x31, /* Y (clutch) — unchanged */
0x81, 0x02,
0x81, 0x03,
/* rest identical to t300rs_rdesc_nrm_fixed from buttons onward */
0x05, 0x09,
0x19, 0x01,
0x29, 0x0d,
0x25, 0x01,
0x45, 0x01,
0x75, 0x01,
0x95, 0x0d,
0x81, 0x02,
0x75, 0x0b,
0x95, 0x01,
0x81, 0x03,
0x05, 0x01,
0x09, 0x39,
0x25, 0x07,
0x46, 0x3b, 0x01,
0x55, 0x00,
0x65, 0x14,
0x75, 0x04,
0x81, 0x42,
0x65, 0x00,
0x81, 0x03,
0x85, 0x60,
0x06, 0x00, 0xff,
0x09, 0x60,
0x75, 0x08,
0x95, 0x3f,
0x26, 0xff, 0x7f,
0x15, 0x00,
0x46, 0xff, 0x7f,
0x36, 0x00, 0x80,
0x91, 0x02,
0x85, 0x02,
0x09, 0x02,
0x81, 0x02,
0x09, 0x14,
0x85, 0x14,
0x81, 0x02,
0xc0,
0xc0,
};

static u8 t300rs_rdesc_nrm_fixed[] = {
0x05, 0x01, /* Usage page (Generic Desktop) */
0x09, 0x04, /* Usage (Joystick) */
Expand Down Expand Up @@ -1512,11 +1582,20 @@ static int t300rs_wheel_destroy(void *data)
static __u8 *t300rs_wheel_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
struct tmff2_device_entry *tmff2 = hid_get_drvdata(hdev);

switch (hdev->product) {
case TMT300RS_PS3_NORM_ID:
/* normal PS3 mode */
rdesc = t300rs_rdesc_nrm_fixed;
*rsize = sizeof(t300rs_rdesc_nrm_fixed);

//Combine Pedals patch
if (tmff2 && tmff2->combine_pedals) {
rdesc = t300rs_rdesc_nrm_combined;
*rsize = sizeof(t300rs_rdesc_nrm_combined);
} else {
rdesc = t300rs_rdesc_nrm_fixed;
*rsize = sizeof(t300rs_rdesc_nrm_fixed);
}
break;

case TMT300RS_PS4_NORM_ID:
Expand All @@ -1535,6 +1614,41 @@ static __u8 *t300rs_wheel_fixup(struct hid_device *hdev, __u8 *rdesc,
return rdesc;
}

//Combine Pedals / Center Clutch patch
//This method is the one that actually modifies the raw data coming from the wheel
static int t300rs_raw_event(struct hid_device *hdev, struct hid_report *report,
u8 *data, int size)
{
struct tmff2_device_entry *tmff2 = hid_get_drvdata(hdev);
struct t300rs_device_entry *t300rs;
s32 combined;
u16 gas, brake;

if (!tmff2 || !tmff2->combine_pedals)
return 0;

if (hdev->product != TMT300RS_PS3_NORM_ID)
return 0;

if (data[0] != 0x07 || size < 9)
return 0;

brake = get_unaligned_le16(&data[3]);
gas = get_unaligned_le16(&data[5]);

combined = ((s32)gas - (s32)brake + 1023) / 2;
combined = clamp(combined, 0, 1023);

put_unaligned_le16(0, &data[3]);
put_unaligned_le16((u16)combined, &data[5]);

t300rs = tmff2->data;
if (t300rs && tmff2->center_clutch)
put_unaligned_le16(512, &data[7]);

return 0;
}

int t300rs_populate_api(struct tmff2_device_entry *tmff2)
{
/* set callbacks */
Expand All @@ -1556,5 +1670,7 @@ int t300rs_populate_api(struct tmff2_device_entry *tmff2)
tmff2->set_autocenter = t300rs_set_autocenter;
tmff2->wheel_fixup = t300rs_wheel_fixup;

tmff2->raw_event = t300rs_raw_event; //Combine Pedals patch

return 0;
}