From 75006183d0a379a2b0fa844fc32b3e27d229f368 Mon Sep 17 00:00:00 2001 From: RaySlash Date: Mon, 2 Oct 2023 13:08:52 +1000 Subject: src: initial refactoring --- src/hid-tmff2.h | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 src/hid-tmff2.h (limited to 'src/hid-tmff2.h') diff --git a/src/hid-tmff2.h b/src/hid-tmff2.h new file mode 100644 index 0000000..c8019dd --- /dev/null +++ b/src/hid-tmff2.h @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef __HID_TMFF2_H +#define __HID_TMFF2_H + +#include +#include +#include + +extern int timer_msecs; +extern int spring_level; +extern int damper_level; +extern int friction_level; +extern int range; +extern int gain; +extern int alt_mode; + +#define USB_VENDOR_ID_THRUSTMASTER 0x044f + +/* the wheel seems to only be capable of processing a certain number of + * interrupts per second, and if this value is too low the kernel urb buffer(or + * some buffer at least) fills up. Optimally I would figure out some way to + * space out the interrupts so that they all leave at regular intervals, but + * for now this is good enough, go slow enough that everything works. + */ +#define DEFAULT_TIMER_PERIOD 8 + +#define FF_EFFECT_QUEUE_UPLOAD 0 +#define FF_EFFECT_QUEUE_START 1 +#define FF_EFFECT_QUEUE_STOP 2 +#define FF_EFFECT_QUEUE_UPDATE 3 +#define FF_EFFECT_PLAYING 4 + +#define PARAM_SPRING_LEVEL (1 << 0) +#define PARAM_DAMPER_LEVEL (1 << 1) +#define PARAM_FRICTION_LEVEL (1 << 2) +#define PARAM_RANGE (1 << 3) +#define PARAM_ALT_MODE (1 << 4) +#define PARAM_GAIN (1 << 5) + +#undef fixp_sin16 +#define fixp_sin16(v) (((v % 360) > 180) ?\ + -(fixp_sin32((v % 360) - 180) >> 16)\ + : fixp_sin32(v) >> 16) + +#define JIFFIES2MS(jiffies) ((jiffies) * 1000 / HZ) + +struct tmff2_effect_state { + struct ff_effect effect; + struct ff_effect old; + + unsigned long flags; + unsigned long count; + unsigned long start_time; +}; + +struct tmff2_device_entry { + struct hid_device *hdev; + struct input_dev *input_dev; + + /* pointer to array */ + struct tmff2_effect_state *states; + + struct delayed_work work; + + spinlock_t lock; + + int allow_scheduling; + + /* fields relevant to each actual device (T300, T150...) */ + void *data; + unsigned long params; + unsigned long max_effects; + signed short supported_effects[FF_CNT]; + + /* obligatory callbacks */ + int (*play_effect)(void *data, struct tmff2_effect_state *state); + int (*upload_effect)(void *data, struct tmff2_effect_state *state); + int (*update_effect)(void *data, struct tmff2_effect_state *state); + int (*stop_effect)(void *data, struct tmff2_effect_state *state); + + int (*wheel_init)(struct tmff2_device_entry *tmff2, int open_mode); + int (*wheel_destroy)(void *data); + + /* optional callbacks */ + int (*open)(void *data, int); + int (*close)(void *data, int); + int (*set_gain)(void *data, uint16_t gain); + int (*set_range)(void *data, uint16_t range); + /* switch_mode has to not do anything if we're alredy in the specified + * mode */ + int (*switch_mode)(void *data, uint16_t mode); + ssize_t (*alt_mode_show)(void *data, char *buf); + 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); + + /* void pointers are dangerous, I know, but in this case likely the best option... */ +}; + +/* external */ +int t300rs_populate_api(struct tmff2_device_entry *tmff2); +int t248_populate_api(struct tmff2_device_entry *tmff2); +int tx_populate_api(struct tmff2_device_entry *tmff2); + +#define TMT300RS_PS3_NORM_ID 0xb66e +#define TMT300RS_PS3_ADV_ID 0xb66f +#define TMT300RS_PS4_NORM_ID 0xb66d + +#define TMT248_PC_ID 0xb696 + +#define TX_ACTIVE 0xb669 + +/* APIs to different wheel families */ +/* T248 at least uses the T300RS api, not sure if there are other wheels but that's + * why these functions are given global linkage */ + +struct t300rs_device_entry { + struct hid_device *hdev; + struct input_dev *input_dev; + struct hid_report *report; + struct hid_field *ff_field; + struct usb_device *usbdev; + + int (*open)(struct input_dev *dev); + void (*close)(struct input_dev *dev); + + int mode; + int attachment; + u8 buffer_length; + u8 *send_buffer; +}; + +int t300rs_play_effect(void *, struct tmff2_effect_state *); +int t300rs_upload_effect(void *, struct tmff2_effect_state *); +int t300rs_update_effect(void *, struct tmff2_effect_state *); +int t300rs_stop_effect(void *, struct tmff2_effect_state *); + +int t300rs_open(void *, int); +int t300rs_close(void *, int); +int t300rs_set_gain(void *, uint16_t); +int t300rs_set_range(void *, uint16_t); +int t300rs_set_autocenter(void *, uint16_t); + +int t300rs_send_buf(struct t300rs_device_entry *t300rs, u8 *send_buffer, size_t len); +int t300rs_send_int(struct t300rs_device_entry *t300rs); + +#endif -- cgit v1.3 From 29400ff75b47ef4320c3fccef5860e44fd8f3a62 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sun, 8 Oct 2023 21:46:49 +0300 Subject: docs: general tidbits --- README.md | 9 +++++---- docs/CONTRIBUTING.md | 9 ++++++--- docs/TODO.md | 12 ++---------- src/hid-tmff2.c | 16 ++++------------ src/hid-tmff2.h | 17 +++++++++-------- src/tmt300rs/hid-tmt300rs.c | 17 +++++++++++------ 6 files changed, 37 insertions(+), 43 deletions(-) (limited to 'src/hid-tmff2.h') diff --git a/README.md b/README.md index 683fb79..56520b9 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ for wheels: [upstreamed](https://github.com/scarburato/hid-tminit), you might want to blacklist the kernel module `hid-thrustmaster`. Do this with ```shell - echo 'blacklist hid_thrustmaster' > /etc/modprobe.d/hid_thrustmaster.con + echo 'blacklist hid_thrustmaster' > /etc/modprobe.d/hid_thrustmaster.conf ``` + If you've bought a new wheel, you will most likely have to update the firmware @@ -141,9 +141,9 @@ for wheels: + If a wheel has a deadzone in games, you can try setting up a udev rule: `/etc/udev/rules.d/99-joydev.rules` - ``` SUBSYSTEM=="input", ATTRS{idVendor}=="044f", - ATTRS{idProduct}=="WHEEL_ID", RUN+="/usr/bin/evdev-joystick --evdev - %E{DEVNAME} --deadzone 0" ``` + ``` + SUBSYSTEM=="input", ATTRS{idVendor}=="044f", ATTRS{idProduct}=="WHEEL_ID", RUN+="/usr/bin/evdev-joystick --evdev %E{DEVNAME} --deadzone 0" + ``` where `WHEEL_ID` is @@ -153,6 +153,7 @@ for wheels: | T300 RS, PS3 advanced mode | b66f | | T300 RS, PS4 normal mode | b66d | | T248 | b696 | + | TX | b669 | This should make sure that the wheel behaves like you'd want from a wheel. diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 46b8b26..7e4b0dd 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -15,13 +15,16 @@ Currently open requests for wheels: Other documents available are linked here: + [FFBEEFFECTS](./FFBEFFECTS.md): - Force feedback effects example for T300RS and compatible wheels + Force feedback effects example for T300RS and compatible wheels + [STRUCTURE](./STRUCTURE.md): - Structure of Thrustmaster device stack + Structure of Thrustmaster device stack + ++ [DRIVER.md](./DRIVER.md): + Info on installing Thrustmaster drivers under Wine + [TODO](./TODO.md): - TO-DO list for maintainers + TODO list for maintainers ## How to capture what effects a game sends to the driver? diff --git a/docs/TODO.md b/docs/TODO.md index 14b8d2e..632a8a8 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -1,11 +1,3 @@ -# TO-DO list +# TODO list -- Make code more general to allow for stuff like T150/T248/T500 to be relatively easily included. - -- Use workqueues instead of doing everything in t300rs_timer - -- Document changes to code in an organised manner. - -### T248 -- open/close seems to crash the wheel and the kernel along with it, check how Windows handles it -- fix rdesc, 0x0a somewhere needs to be set to 0x60 ++ Try to figure out how/if RRRE (#39) determines FFB from wheel input diff --git a/src/hid-tmff2.c b/src/hid-tmff2.c index 44df1e3..013039f 100644 --- a/src/hid-tmff2.c +++ b/src/hid-tmff2.c @@ -101,7 +101,6 @@ static ssize_t spring_level_store(struct device *dev, 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); @@ -132,7 +131,6 @@ static ssize_t damper_level_store(struct device *dev, 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); @@ -163,12 +161,7 @@ static ssize_t friction_level_store(struct device *dev, static ssize_t friction_level_show(struct device *dev, struct device_attribute *attr, char *buf) { - size_t count; - - - count = scnprintf(buf, PAGE_SIZE, "%u\n", friction_level); - - return count; + return scnprintf(buf, PAGE_SIZE, "%u\n", friction_level); } static DEVICE_ATTR_RW(friction_level); @@ -179,7 +172,6 @@ static ssize_t range_store(struct device *dev, unsigned int value; int ret; - if (!tmff2) return -ENODEV; @@ -199,7 +191,6 @@ static ssize_t range_store(struct device *dev, 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); @@ -333,7 +324,7 @@ static void tmff2_work_handler(struct work_struct *w) } else { __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags); /* if we're uploading an effect, it's bound to be the up - * to date available */ + * to date */ __clear_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags); } } @@ -458,6 +449,8 @@ static void tmff2_close(struct input_dev *dev) 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) { @@ -620,7 +613,6 @@ static int tmff2_probe(struct hid_device *hdev, const struct hid_device_id *id) hid_set_drvdata(tmff2->hdev, tmff2); switch (tmff2->hdev->product) { - /* t300rs */ case TMT300RS_PS3_NORM_ID: case TMT300RS_PS3_ADV_ID: case TMT300RS_PS4_NORM_ID: diff --git a/src/hid-tmff2.h b/src/hid-tmff2.h index c8019dd..1eb3546 100644 --- a/src/hid-tmff2.h +++ b/src/hid-tmff2.h @@ -17,7 +17,7 @@ extern int alt_mode; #define USB_VENDOR_ID_THRUSTMASTER 0x044f /* the wheel seems to only be capable of processing a certain number of - * interrupts per second, and if this value is too low the kernel urb buffer(or + * interrupts per second, and if this value is too low the kernel urb buffer (or * some buffer at least) fills up. Optimally I would figure out some way to * space out the interrupts so that they all leave at regular intervals, but * for now this is good enough, go slow enough that everything works. @@ -66,7 +66,7 @@ struct tmff2_device_entry { int allow_scheduling; - /* fields relevant to each actual device (T300, T150...) */ + /* fields relevant to each actual device (T300, T248...) */ void *data; unsigned long params; unsigned long max_effects; @@ -86,15 +86,16 @@ struct tmff2_device_entry { int (*close)(void *data, int); int (*set_gain)(void *data, uint16_t gain); int (*set_range)(void *data, uint16_t range); - /* switch_mode has to not do anything if we're alredy in the specified - * mode */ + /* switch_mode is required to not do anything if we're alredy in the + * specified mode */ int (*switch_mode)(void *data, uint16_t mode); ssize_t (*alt_mode_show)(void *data, char *buf); 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); - /* void pointers are dangerous, I know, but in this case likely the best option... */ + /* void pointers are dangerous, I know, but in this case likely the + * best option... */ }; /* external */ @@ -108,11 +109,11 @@ int tx_populate_api(struct tmff2_device_entry *tmff2); #define TMT248_PC_ID 0xb696 -#define TX_ACTIVE 0xb669 +#define TX_ACTIVE 0xb669 /* APIs to different wheel families */ -/* T248 at least uses the T300RS api, not sure if there are other wheels but that's - * why these functions are given global linkage */ +/* T248 and TX at least uses the T300RS api, not sure if there are other wheels + * but that's why these functions are given global linkage */ struct t300rs_device_entry { struct hid_device *hdev; diff --git a/src/tmt300rs/hid-tmt300rs.c b/src/tmt300rs/hid-tmt300rs.c index 20bb239..0191620 100644 --- a/src/tmt300rs/hid-tmt300rs.c +++ b/src/tmt300rs/hid-tmt300rs.c @@ -1187,7 +1187,8 @@ int t300rs_update_effect(void *data, struct tmff2_effect_state *state) case FF_PERIODIC: return t300rs_update_periodic(t300rs, state); default: - hid_err(t300rs->hdev, "invalid effect type: %x", state->effect.type); + hid_err(t300rs->hdev, "invalid effect type: %x", + state->effect.type); return -1; } } @@ -1209,7 +1210,8 @@ int t300rs_upload_effect(void *data, struct tmff2_effect_state *state) case FF_PERIODIC: return t300rs_upload_periodic(t300rs, state); default: - hid_err(t300rs->hdev, "invalid effect type: %x", state->effect.type); + hid_err(t300rs->hdev, "invalid effect type: %x", + state->effect.type); return -1; } } @@ -1328,7 +1330,9 @@ int t300rs_set_autocenter(void *data, uint16_t value) if (!t300rs) return -ENODEV; - /* TODO: this should probably also use a separately allocated buffer? */ + /* TODO: this should probably also use a separately allocated buffer? + * someone might change autocentering while we're updating the buffer + * which would cause corruption */ autocenter_packet = (struct t300rs_packet_autocenter *)t300rs->send_buffer; autocenter_packet->header.cmd = 0x08; @@ -1477,7 +1481,7 @@ static int t300rs_check_firmware(struct t300rs_device_entry *t300rs) return -ENOMEM; } - /* Fetch firmware version */ + /* fetch firmware version */ ret = usb_control_msg(t300rs->usbdev, usb_rcvctrlpipe(t300rs->usbdev, 0), t300rs_fw_request.bRequest, @@ -1494,7 +1498,7 @@ static int t300rs_check_firmware(struct t300rs_device_entry *t300rs) goto out; } - /* Educated guess */ + /* educated guess */ if (fw_response->fw_version < 31 && ret >= 0) { hid_err(t300rs->hdev, "firmware version %i is too old, please update.\n", @@ -1574,7 +1578,8 @@ static int t300rs_get_attachment(struct t300rs_device_entry *t300rs) } else if (response->type == cpu_to_le16(0x47)) { attachment = response->b.attachment; } else { - hid_err(t300rs->hdev, "unknown packet type %hx\n, please contact a maintainer", + hid_err(t300rs->hdev, + "unknown packet type %hx\n, please contact a maintainer", response->type); ret = -EINVAL; goto out; -- cgit v1.3