aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2020-07-08 13:24:30 +0300
committerGitHub <noreply@github.com>2020-07-08 13:24:30 +0300
commit6faa9ae6a8cf242679ce4e493a66fcb31d231c09 (patch)
treedcb24238668f47a0df178d4ae5d2a3444c4594a4
parenta00ee26228e895922f72a4afc2daa09a75e3501e (diff)
parentc7171a1fe795911a925f47af15352deb6609b001 (diff)
downloadhid-tmff2-6faa9ae6a8cf242679ce4e493a66fcb31d231c09.tar.gz
hid-tmff2-6faa9ae6a8cf242679ce4e493a66fcb31d231c09.zip
Merge pull request #1 from Kimplul/testing
Testing has pretty much got me where I want to be at the moment
-rw-r--r--compile_commands.json104
-rw-r--r--force-effects.txt240
-rw-r--r--hid-tmff2.c84
3 files changed, 390 insertions, 38 deletions
diff --git a/compile_commands.json b/compile_commands.json
new file mode 100644
index 0000000..0ac6efe
--- /dev/null
+++ b/compile_commands.json
@@ -0,0 +1,104 @@
+[
+ {
+ "arguments": [
+ "gcc-9",
+ "-c",
+ "-Wp,-MD,/home/kimi/Documents/Projects/hid-tmff2/.hid-tmff2.o.d",
+ "-nostdinc",
+ "-isystem",
+ "/usr/lib/gcc/x86_64-linux-gnu/9/include",
+ "-I/usr/src/linux-headers-5.7.0-1-common/arch/x86/include",
+ "-I./arch/x86/include/generated",
+ "-I/usr/src/linux-headers-5.7.0-1-common/include",
+ "-I./include",
+ "-I/usr/src/linux-headers-5.7.0-1-common/arch/x86/include/uapi",
+ "-I./arch/x86/include/generated/uapi",
+ "-I/usr/src/linux-headers-5.7.0-1-common/include/uapi",
+ "-I./include/generated/uapi",
+ "-include",
+ "/usr/src/linux-headers-5.7.0-1-common/include/linux/kconfig.h",
+ "-include",
+ "/usr/src/linux-headers-5.7.0-1-common/include/linux/compiler_types.h",
+ "-D__KERNEL__",
+ "-Wall",
+ "-Wundef",
+ "-Werror=strict-prototypes",
+ "-Wno-trigraphs",
+ "-fno-strict-aliasing",
+ "-fno-common",
+ "-fshort-wchar",
+ "-fno-PIE",
+ "-Werror=implicit-function-declaration",
+ "-Werror=implicit-int",
+ "-Wno-format-security",
+ "-std=gnu89",
+ "-mno-sse",
+ "-mno-mmx",
+ "-mno-sse2",
+ "-mno-3dnow",
+ "-mno-avx",
+ "-m64",
+ "-falign-jumps=1",
+ "-falign-loops=1",
+ "-mno-80387",
+ "-mno-fp-ret-in-387",
+ "-mpreferred-stack-boundary=3",
+ "-mskip-rax-setup",
+ "-mtune=generic",
+ "-mno-red-zone",
+ "-mcmodel=kernel",
+ "-DCONFIG_X86_X32_ABI",
+ "-Wno-sign-compare",
+ "-fno-asynchronous-unwind-tables",
+ "-mindirect-branch=thunk-extern",
+ "-mindirect-branch-register",
+ "-fno-jump-tables",
+ "-fno-delete-null-pointer-checks",
+ "-Wno-frame-address",
+ "-Wno-format-truncation",
+ "-Wno-format-overflow",
+ "-Wno-address-of-packed-member",
+ "-O2",
+ "--param=allow-store-data-races=0",
+ "-Wframe-larger-than=2048",
+ "-fstack-protector-strong",
+ "-Wno-unused-but-set-variable",
+ "-Wimplicit-fallthrough",
+ "-Wno-unused-const-variable",
+ "-fno-var-tracking-assignments",
+ "-g",
+ "-pg",
+ "-mrecord-mcount",
+ "-mfentry",
+ "-DCC_USING_FENTRY",
+ "-flive-patching=inline-clone",
+ "-Wdeclaration-after-statement",
+ "-Wvla",
+ "-Wno-pointer-sign",
+ "-Wno-stringop-truncation",
+ "-Wno-array-bounds",
+ "-Wno-stringop-overflow",
+ "-Wno-restrict",
+ "-Wno-maybe-uninitialized",
+ "-fno-strict-overflow",
+ "-fno-merge-all-constants",
+ "-fmerge-constants",
+ "-fno-stack-check",
+ "-fconserve-stack",
+ "-Werror=date-time",
+ "-Werror=incompatible-pointer-types",
+ "-Werror=designated-init",
+ "-fmacro-prefix-map=/usr/src/linux-headers-5.7.0-1-common/=",
+ "-fcf-protection=none",
+ "-Wno-packed-not-aligned",
+ "-DMODULE",
+ "-DKBUILD_BASENAME=\"hid_tmff2\"",
+ "-DKBUILD_MODNAME=\"hid_tmff2\"",
+ "-o",
+ "/home/kimi/Documents/Projects/hid-tmff2/hid-tmff2.o",
+ "../../../home/kimi/Documents/Projects/hid-tmff2/hid-tmff2.c"
+ ],
+ "directory": "/usr/src/linux-headers-5.7.0-1-amd64",
+ "file": "../../../home/kimi/Documents/Projects/hid-tmff2/hid-tmff2.c"
+ }
+] \ No newline at end of file
diff --git a/force-effects.txt b/force-effects.txt
new file mode 100644
index 0000000..6c205f7
--- /dev/null
+++ b/force-effects.txt
@@ -0,0 +1,240 @@
+Here I will gather all info I can find out about the different force effects and
+their USB commands. All values seem to be little-endian.
+Also, general note, it seems like some effects are affected by the direction of
+the force, denoted by ***
+
+As far as I can tell, fade_level and attack_level values are calculated by
+mapping the u16 into s16 and taking the absolute value, and after that
+multiplying by the direction.
+
+All values are examples of actual commands that I captured on the USB interface,
+not the only ones available.
+
+GENERAL:
+
+ Playing:
+ 60 00 - standard header
+ 01 - ID
+ 89 - playing options
+ 01 - play
+ 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+
+ Stopping/removing: (why are they rolled into one?)
+ 60 00 - standard header
+ 01 - ID
+ 89 - playing options
+ 00 - stop
+ 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 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_CONSTANT:
+ Initialization:
+ 60 00 - standard header
+ 01 - ID
+ 6a - new constant effect(?)
+ fe ff - strength ***
+ 00 00 - attack_length
+ 00 00 - attack_level ***
+ 00 00 - fade_length
+ 00 00 - fade_level ***
+ 00 4f - ?
+ f7 17 - time in milliseconds, unsigned
+ 00 00
+ 07 00 - offset from start(?)
+ 00 ff ff - end of new effect(?)
+ 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+
+ Modifying: (It may be possible to modify the effects all at once, not sure)
+ (In any case, so far I only investigated the constant modifiers)
+ Direction: n/a
+
+ Constant force:
+ 60 00 - standard header
+ 01 - ID
+ 0a - modify constant force
+ 05 16 - constant force
+ 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 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:
+ 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
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 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 - standard header
+ 01 - ID
+ 49 00 41 - modify timing?
+ 6c 20 - length 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 00 00
+
+
+FF_RAMP:
+ (Why on earth is it this difficult to figure out how a fucking ramp works?)
+ 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)
+ 00 00
+ f7 17 - time
+ 00 80 - some kind of marker
+ 00 00 - attack_length
+ f6 7f - attack_level ***
+ 00 00 - fade_length
+ f6 7f - fade_level***
+ 04 - invert (going "down", 05, going "up", 04)
+ 4f
+ f7 17 - time again?
+ 00 00
+ 00 00 - offset
+ 00 ff ff - end of init
+ 00 00 00 00 00 00 00 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_SPRING:
+ Init:
+ 60 00 - standard header
+ 01 - ID
+ 64 - new conditional effect
+ fc 7f - positive coefficient (right?)
+ fc 7f - negative coefficient (left?)
+ fe ff - deadband (left?) (deadband + offset) (fe ff means no deadband)
+ fe ff - deadband (right?) (deadband + offset)
+ a6 6a a6 6a fe ff fe ff fe ff fe ff df 58 a6 6a 06 - some weird hard-coded
+ values to do with springs?
+
+ 4f
+ f7 17 - duration
+ 00 00
+ 00 00 - offset
+ 00 ff ff - end of init
+ 00 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:
+ Init:
+ 60 00 - standard header
+ 02 -ID
+ 64 - new conditional effect
+ fc 7f - positive coefficient (right?)
+ fc 7f - negative coefficient (left?)
+ fe ff - deadband (left?) (deadband + offset) (fe ff means no deadband)
+ fe ff - deadband (right?) (deadband + offset)
+ fc 7f fc 7f fe ff fe ff fe ff fe ff fc 7f fc 7f 07 - some weird hard-coded
+ values to do with friction?
+ 4f
+ f7 17 - duration
+ 00 00
+ 00 00 - offset
+ 00 ff ff - end of init
+ 00 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_PERIODIC:
+ 60 00 - standard header
+ 01 - ID
+ 6b - new periodic effect
+ 00 00 - magnitude ***
+ fe ff - phase (left/right)
+ 00 00 - offset of effect (forward/backward)
+ e8 03 - period
+ 00 80
+ 00 00 - attack_length
+ 00 00 - attack_level ***
+ 00 00 - fade_length
+ 00 00 - fade_level ***
+ 01 - type of periodic ( square 01,
+ sine 03,
+ triangle 02,
+ sawtooth down 05,
+ sawtooth up 04 )
+ 4f
+ f7 17 - duration
+ 00 00
+ 00 00 - offset
+ 00 ff ff - end of init
+ 00 00 00 00 00 00 00 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_AUTOCENTER:
+ 60 08 - header plus settings?
+ 03 - set autocenter force
+ 8f 02 - force (between ff ff and 00 00)
+ 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 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_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
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+Rotation angle:
+ 60 08 - header plus settings?
+ 11 - set rotation angle
+ 55 d5 - angle (between ff ff and 7b 09, one degree is roughly 3c)
+ 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+Open:
+ 60 01 - standard header?
+ 04 - ?
+ 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+ (this command doesn't appear every time, odd)
+ 60 12 - ?
+ bf 04 00 00 03 b7 1e - ?
+ 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+ 60 01 - ?
+ 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 00 00
+
+Close:
+ 60 01 - standard header?
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
diff --git a/hid-tmff2.c b/hid-tmff2.c
index 2bfc38f..b26185f 100644
--- a/hid-tmff2.c
+++ b/hid-tmff2.c
@@ -265,12 +265,13 @@ static inline int tmff_scale_s8(int in, int minimum, int maximum)
return maximum;
return ret;
}
-
+bool transferred = true;
static void tmff_ctrl(struct urb *urb){
if(urb->status){
hid_warn(urb->dev, "urb status %d received\n", urb->status);
}
usb_free_urb(urb);
+ transferred = true;
}
static void tmff_init_ctrl(struct urb *urb){
@@ -326,57 +327,43 @@ out:
return retval;
}
+bool last_stop = false;
+
static int tmff_play(struct input_dev *dev, void *data,
struct ff_effect *effect)
{
//spin_lock_irqsave(report_lock, flags);
struct hid_device *hid = input_get_drvdata(dev);
- struct tmff_device *tmff = data;
- struct hid_field *ff_field = tmff->ff_field;
- int x, y;
- int left, right; /* Rumbling */
- int trans, b_ep, err;
- unsigned long flags;
struct device *d_dev = &hid->dev;
struct usb_interface *usbif = to_usb_interface(d_dev->parent);
struct usb_device *usbdev = interface_to_usbdev(usbif);
struct usb_host_endpoint *ep;
-
- if((ktime_get_ns() - last) < 4000000){
- return 0;
- }
-
- last = ktime_get_ns();
-
+ struct tmff_device *tmff = data;
+ struct hid_field *ff_field = tmff->ff_field;
struct urb *urb = usb_alloc_urb(0, GFP_ATOMIC);
-
u8 *send_buf = kmalloc(1024, GFP_ATOMIC);
+ __s16 x;
+
+ if(!transferred){
+ return 0;
+ }
+
+
memcpy(send_buf, ff_constant_array, ARRAY_SIZE(ff_constant_array));
ep = &usbif->cur_altsetting->endpoint[1];
- b_ep = ep->desc.bEndpointAddress;
-
- switch (effect->type) {
+
+ switch (effect->type) {
case FF_CONSTANT:
+ // this only works with input_ff_create_memless, which clamps
+ // constant forces to s8 for some reason
+ x = tmff_scale_s8(effect->u.constant.level,
+ ff_field->logical_minimum,
+ ff_field->logical_maximum);
- x = tmff_scale_s8((tmff_gain * effect->u.constant.level) / ((u16)0xffff),
- ff_field->logical_minimum,
- ff_field->logical_maximum);
-
- if(x == 128){
- memcpy(send_buf, ff_stop_array, ARRAY_SIZE(ff_stop_array));
- } else {
-
- if(x < 128){
- x = 128 + x;
- } else if(x > 128){
- x = 256 - x;
- }
-
- send_buf[5] = x;
-
- }
+ send_buf[4] = x & 0xff;
+ send_buf[5] = x >> 8;
usb_fill_int_urb(
urb,
@@ -388,6 +375,7 @@ static int tmff_play(struct input_dev *dev, void *data,
hid,
ep->desc.bInterval
);
+ transferred = false;
usb_submit_urb(urb, GFP_ATOMIC);
@@ -666,7 +654,8 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits)
tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL);
if (!tmff)
return -ENOMEM;
-
+
+ hid_info(hid, "what is going ong here???");
spin_lock_init(&tmff->report_lock);
report_lock = &tmff->report_lock;
@@ -677,6 +666,7 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits)
for (fieldnum = 0; fieldnum < report->maxfield; ++fieldnum) {
struct hid_field *field = report->field[fieldnum];
+ printk("found field at fieldnum %i\n", fieldnum);
if (field->maxusage <= 0)
continue;
@@ -707,7 +697,7 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits)
tmff->report = report;
tmff->ff_field = field;
-
+
for (i = 0; ff_bits[i] >= 0; i++)
set_bit(ff_bits[i], input_dev->ffbit);
@@ -738,6 +728,7 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits)
return 0;
fail:
+ hid_err(hid, "We have failed creating a force feedback memless device!!!\n");
kfree(tmff);
return error;
}
@@ -754,7 +745,6 @@ static int tmff_afterthought_t300rs(struct hid_device *hid){
struct usb_interface *usbif = to_usb_interface(dev->parent);
struct usb_device *usbdev = interface_to_usbdev(usbif);
struct usb_host_endpoint *ep;
- struct urb *urb;
ep = &usbif->cur_altsetting->endpoint[0];
bb_ep = ep->desc.bEndpointAddress;
@@ -844,6 +834,23 @@ static void tm_remove(struct hid_device *hdev){
hid_hw_stop(hdev);
}
+static __u8 t300rs_rdesc_fixed[] = {0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0x09, 0x01, 0xa1, 0x00, 0x85, 0x07, 0x09, 0x30, 0x15, 0x00, 0x27, 0xff, 0xff, 0x00, 0x00, 0x35, 0x00, 0x47, 0xff, 0xff, 0x00, 0x00, 0x75, 0x10, 0x95, 0x01, 0x81, 0x02, 0x09, 0x31, 0x26, 0xff, 0x03, 0x46, 0xff, 0x03, 0x81, 0x02, 0x09, 0x35, 0x81, 0x02, 0x09, 0x36, 0x81, 0x02, 0x81, 0x03, 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, 0x0a, 0x06, 0x00, 0xff, 0x09, 0x0a, 0x75, 0x08, 0x95, 0x3f,
+ 0x26, 0xff, 0x7f,
+ 0x16, 0x00, 0x80,
+ 0x46, 0xff, 0x7f,
+ 0x36, 0x00, 0x80,
+ 0x91, 0x02, 0x85, 0x02, 0x09, 0x02, 0x81, 0x02, 0x09, 0x14, 0x85, 0x14, 0x81, 0x02, 0xc0, 0xc0,};
+
+static __u8 *tmff_t300rs_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize){
+ if(hdev->product != 0xb66e){
+ return rdesc;
+ }
+ printk("wahey");
+ rdesc = t300rs_rdesc_fixed;
+ *rsize = sizeof(t300rs_rdesc_fixed);
+ return rdesc;
+};
+
static const struct hid_device_id tm_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65d),
.driver_data = (unsigned long)ff_constant }, /* die */
@@ -858,6 +865,7 @@ static struct hid_driver tm_driver = {
.id_table = tm_devices,
.probe = tm_probe,
.remove = tm_remove,
+ .report_fixup = tmff_t300rs_report_fixup,
};
module_hid_driver(tm_driver);