ArduinoJoystickWithFFBLibrary icon indicating copy to clipboard operation
ArduinoJoystickWithFFBLibrary copied to clipboard

Force feedback doesn't work in linux

Open sgtnoodle opened this issue 3 years ago • 4 comments

I'm not particularly familiar with USB HID descriptors, but it appears that the usbhid driver, hid-pidff.c, is looking for 0xa7 and not finding it.

[1172477.418129] hid-generic 0003:2341:8036.001A: starting pid init
[1172477.418132] hid-generic 0003:2341:8036.001A: found usage 0x21 from field->logical
[1172477.418134] hid-generic 0003:2341:8036.001A: found usage 0x5a from field->logical
[1172477.418135] hid-generic 0003:2341:8036.001A: found usage 0x5f from field->logical
[1172477.418137] hid-generic 0003:2341:8036.001A: found usage 0x6e from field->logical
[1172477.418138] hid-generic 0003:2341:8036.001A: found usage 0x73 from field->logical
[1172477.418139] hid-generic 0003:2341:8036.001A: found usage 0x74 from field->logical
[1172477.418140] hid-generic 0003:2341:8036.001A: found usage 0x77 from field->logical
[1172477.418142] hid-generic 0003:2341:8036.001A: found usage 0x90 from field->logical
[1172477.418143] hid-generic 0003:2341:8036.001A: found usage 0x96 from field->logical
[1172477.418144] hid-generic 0003:2341:8036.001A: found usage 0x7d from field->logical
[1172477.418145] hid-generic 0003:2341:8036.001A: found usage 0xab from collection array
[1172477.418147] hid-generic 0003:2341:8036.001A: found usage 0x89 from field->logical
[1172477.418148] hid-generic 0003:2341:8036.001A: found usage 0x7f from field->logical
[1172477.418149] usbhid: found 0 at 0->0
[1172477.418151] usbhid: maxusage and report_count do not match, skipping
[1172477.418152] usbhid: found 1 at 2->0
[1172477.418153] usbhid: maxusage and report_count do not match, skipping
[1172477.418154] usbhid: found 2 at 3->0
[1172477.418155] usbhid: maxusage and report_count do not match, skipping
[1172477.418156] usbhid: found 3 at 4->0
[1172477.418157] usbhid: maxusage and report_count do not match, skipping
[1172477.418158] usbhid: found 4 at 2->1
[1172477.418158] usbhid: maxusage and report_count do not match, skipping
[1172477.418159] usbhid: found 5 at 6->0
[1172477.418160] usbhid: maxusage and report_count do not match, skipping
[1172477.418161] usbhid: failed to locate 6
[1172477.418163] hid-generic 0003:2341:8036.001A: unknown set_effect report layout
[1172477.418165] hid-generic 0003:2341:8036.001A: input,hidraw8: USB HID v1.11 Multi-Axis Controller [Arduino LLC Arduino Leonardo] on usb-0000:02:00.0-3/input2

This is apparently a "start delay" parameter. Looking in PIDReportType.h, I can see that it's commented out in the corresponding struct:

typedef struct //FFB: Set Effect Output Report
{
	uint8_t	reportId;	// =1
	uint8_t	effectBlockIndex;	// 1..40
	uint8_t	effectType;	// 1..12 (effect usages: 26,27,30,31,32,33,34,40,41,42,43,28)
	uint16_t duration; // 0..32767 ms
	uint16_t triggerRepeatInterval; // 0..32767 ms
	uint16_t samplePeriod;	// 0..32767 ms
	uint8_t	gain;	// 0..255	 (physical 0..10000)
	uint8_t	triggerButton;	// button ID (0..8)
	uint8_t	enableAxis; // bits: 0=X, 1=Y, 2=DirectionEnable
	uint8_t	directionX;	// angle (0=0 .. 255=360deg)
	uint8_t	directionY;	// angle (0=0 .. 255=360deg)
	//	uint16_t	startDelay;	// 0..32767 ms
} USB_FFBReport_SetEffect_Output_Data_t;

This thread seems to talk about the same issue on a Granite Devices SimuCUBE. https://www.spinics.net/lists/linux-usb/msg190787.html

It seems like this is part of the HID PID spec, but maybe the windows driver is buggy and doesn't implement it, and so it's been omitted from the descriptor to make the device work in windows?

It's kind of a bummer that it doesn't work in linux, because it's much easier to develop my firmware from there. I'll try to work around it and report back, but maybe someone else has a better idea.

sgtnoodle avatar Jun 29 '21 05:06 sgtnoodle

For what it's worth, I added this to the descriptor:

#define ENABLE_START_DELAY 1

and

	  0x95, 0x02,           //          Report Count (2)
	  0x91, 0x02,           //          Output (Data,Var,Abs)
	  0x55, 0x00,           //          Unit Exponent (0)
	  0x66, 0x00, 0x00,     //          Unit (0)
	0xC0,                 //        End Collection Datalink (Logical)

#if ENABLE_START_DELAY
	0x05,0x0F, // USAGE_PAGE (Physical Interface)
	0x09,0xA7, // USAGE (Start Delay)
	0x66,0x03,0x10, // UNIT (Eng Lin:Time)
	0x55,0xFD, // UNIT_EXPONENT (-3)
	0x15,0x00, // LOGICAL_MINIMUM (00)
	0x26,0xFF,0x7F, // LOGICAL_MAXIMUM (7F FF)
	0x35,0x00, // PHYSICAL_MINIMUM (00)
	0x46,0xFF,0x7F, // PHYSICAL_MAXIMUM (7F FF)
	0x75,0x10, // REPORT_SIZE (10)
	0x95,0x01, // REPORT_COUNT (01)
	0x91,0x02, // OUTPUT (Data,Var,Abs)
	0x66,0x00,0x00, // UNIT (None)
	0x55,0x00, // UNIT_EXPONENT (00)
#endif

	0x05, 0x0F,           //    Usage Page (Physical Interface)
	0x09, 0x58,           //      Usage (Type Specific Block Offset)
	0xA1, 0x02,           //        Collection (Logical)
	  0x0B, 0x01, 0, 0x0A, 0,  //          Usage (Ordinals: Instance 1)

and I uncommented startDelay from the struct, and force feedback now seems to "work" in linux, in that the driver is at least happy and fftest can twiddle it. Of course, my version of fftest drives a 100Hz sine wave when it intends to drive a 10Hz sine wave, and so the resulting force output on the arduino simply toggles between -255 and 255 cycle-to-cycle... :-P

I haven't tried it in windows yet, but I am just getting started on developing the firmware for my steering wheel project.

sgtnoodle avatar Jun 29 '21 07:06 sgtnoodle

I'll test it on Linux. But I lack of the ffb test application on linux platform, can you provide?

YukMingLaw avatar Oct 07 '21 17:10 YukMingLaw

There's fftest available in most distributions. It's pretty crappy, though.

I think just looking at the dmesg output will get you pretty far, though. If it gets past unknown set_effect report layout then it's probably good.

I have my fix here, which seems to work well: https://github.com/sgtnoodle/ArduinoJoystickWithFFBLibrary/commit/61ac57ed0b97a10ec6fa04f65267f67741d8d19f

I haven't tried it in windows, so I'd be curious to know if its driver implementation chokes on the startDelay field or not.

I also have this commit which adds in default auto-centering. I "reverse engineered" it from what the linux driver was expecting, so I don't know how well it would work with the windows driver: https://github.com/sgtnoodle/ArduinoJoystickWithFFBLibrary/commit/7a7df9973ccd18b31e1cbbec08d35346fe68f8db

sgtnoodle avatar Oct 10 '21 21:10 sgtnoodle

fftest is mentioned at https://docs.kernel.org/input/ff.html Unfortunately it is not clear to me which of the /dev/input/eventXX files to pick - but this may be related to my hardware, which is not Arduino-based at the moment.

HiranChaudhuri avatar Jan 14 '23 08:01 HiranChaudhuri