Open upintheairsheep opened 5 months ago
To be fair I would like to ^^
But I need to learn how exactly the kernel development work and there is also the current issue that usb-hid driver take the upper hand as the GameCube adapter report itself as a USB hid device.
I will close this issue if it got into the kernel :)
Patch send for review :3 Cover letter Patch Well not without struggle as it seems the link between those two message didn't worked....
and there is also the current issue that usb-hid driver take the upper hand as the GameCube adapter report itself as a USB hid device.
I haven’t narrowed it down, but I got it working after many failed attempts using the following udev rules:
SUBSYSTEMS=="usb", ACTION=="add", DRIVERS=="usb", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="0337", ATTR{authorized}="0"
SUBSYSTEMS=="usb", ACTION=="add", DRIVERS=="usbhid", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="0337", ATTR{authorized}="0"
SUBSYSTEMS=="usb", ACTION=="add", DRIVERS=="hid-generic", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="0337", ATTR{authorized}="0"
SUBSYSTEM=="usb", ACTION=="add", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="0337", ATTR{authorized}="1", \
RUN+="/bin/bash -c 'echo $kernel > /sys/bus/usb/drivers/gamecube-adapter/bind'"
Those first rules were my attempt to prevent the built-in drivers to bind the USB device by not authorizing them. The last rule then authorizes the device and binds your driver to it.
Note: I’ve installed the driver under the name gamecube-adapter
via dkms on my system.
System log:
[33866.848513] usb 5-1.1.3: new full-speed USB device number 42 using xhci_hcd
[33866.968225] usb 5-1.1.3: New USB device found, idVendor=057e, idProduct=0337, bcdDevice= 1.00
[33866.968233] usb 5-1.1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[33866.968237] usb 5-1.1.3: Product: WUP-028
[33866.968239] usb 5-1.1.3: Manufacturer: Nintendo
[33866.968241] usb 5-1.1.3: SerialNumber: 15/07/2014
[33866.972798] hid-generic 0003:057E:0337.0034: hiddev1,hidraw2: USB HID v1.10 Device [Nintendo WUP-028] on usb-0000:03:00.0-1.1.3/input0
[33866.977629] hid-generic 0003:057E:0337.0035: hiddev1,hidraw2: USB HID v1.10 Device [Nintendo WUP-028] on usb-0000:03:00.0-1.1.3/input0
[33866.977681] usb 5-1.1.3: authorized to connect
[33866.989426] gamecube-adapter 5-1.1.3:1.0: New device registered
[33867.019990] gamecube-adapter 5-1.1.3:1.0: New device registered
[33867.028391] input: Nintendo GameCube Controller as /devices/virtual/input/input44
[33867.029764] input: Nintendo GameCube Controller as /devices/virtual/input/input45
Works fine in Firefox on https://hardwaretester.com/gamepad for example :) Chromium only supports a single controller plugged into the adapter (only the last one), not sure if that’s something you can fix.
Edit: Rumble didn’t work in Chromium nor with fftest
. Power was plugged in. Hmm
Hi @max-m , Thank for your time trying my module.
Chromium only supports a single controller plugged into the adapter (only the last one), not sure if that’s something you can fix.
Concerning Chromium support, if you tell me it work with firefox, it means that it seems to that chrome does not handle it correctly, and modifying chrome is out of scope of this project
Those first rules were my attempt to prevent the built-in drivers to bind the USB device by not authorizing them. The last rule then authorizes the device and binds your driver to it.
Works correctly might add it with an automatic install script
Edit: Rumble didn’t work in Chromium nor with fftest. Power was plugged in. Hmm
Do you test fftest on the correct device ? It should not be jsX but eventX corresponding to the controller in question and also make sure to plug the grey plug of the gamecube controller as it provide power for rumble functionnalities.
Hi :)
Concerning Chromium support, if you tell me it work with firefox, it means that it seems to that chrome does not handle it correctly, and modifying chrome is out of scope of this project
Oh, no. I meant by changing the way the controllers are reported to the system. I already tried the easy and simple things: giving each controller a unique display name (this did not change Chrome's behavior, Firefox uses those names), setting the parent device (this made Chrome pick the manufacturer and product name of the parent device, Nintendo WUP-028, as the display name), probably some other simple tweaks I tried and forgot. Chrome also refuses to detect my Switch Pro Controller which Firefox happily picks up (this one is handled by hid-nx via dkms on my system). So it's sort of expected that controller support feels wonky in that browser. :^)
Do you test fftest on the correct device ? It should not be jsX but eventX corresponding to the controller in question and also make sure to plug the grey plug of the gamecube controller as it provide power for rumble functionnalities.
I used the corresponding eventX
devices. When you try to use a jsX
device fftest
complains :)
When I opened an event
device it was happy with, it let me send FF patterns to the controller, but nothing happened. As a sanity check I tried the same with a DualShock 3 and it rumbled violently. haha
I also had both USB plugs connected, that was the first thing I checked :D
Maybe I'll play around with that feature tomorrow, it hasn't bothered me enough yet.
Do you obtain the same output as me with fftest ?
Features:
* Absolute axes: X, Y, Z, RX, RY, RZ,
[3F 00 00 00 00 00 00 00 ]
* Relative axes:
[00 00 ]
* Force feedback effects types: Periodic, Rumble, Gain,
Force feedback periodic effects: Square, Triangle, Sine,
[00 00 00 00 00 00 00 00 00 00 03 07 01 00 00 00 ]
* Number of simultaneous effects: 16
Setting master gain to 75% ... OK
Uploading effect #0 (Periodic sinusoidal) ... OK (id 0)
Uploading effect #1 (Constant) ... Error: Invalid argument
Uploading effect #2 (Spring) ... Error: Invalid argument
Uploading effect #3 (Damper) ... Error: Invalid argument
Uploading effect #4 (Strong rumble, with heavy motor) ... OK (id 1)
Uploading effect #5 (Weak rumble, with light motor) ... OK (id 2)
Hmm, I actually missed that it reports Error: Invalid argument
for all effect types:
$ cat /sys/devices/virtual/input/input32/name
Nintendo GameCube Controller #1
$ ls /sys/devices/virtual/input/input32/
capabilities/ event8/ id/ inhibited js0/ modalias name phys power/ properties subsystem@ uevent uniq
$ fftest /dev/input/event8
Force feedback test program.
HOLD FIRMLY YOUR WHEEL OR JOYSTICK TO PREVENT DAMAGES
Device /dev/input/event8 opened
Features:
* Absolute axes: X, Y, Z, RX, RY, RZ,
[3F 00 00 00 00 00 00 00 ]
* Relative axes:
[00 00 ]
* Force feedback effects types: Rumble, Gain,
Force feedback periodic effects:
[00 00 00 00 00 00 00 00 00 00 01 00 01 00 00 00 ]
* Number of simultaneous effects: 16
Setting master gain to 75% ... OK
Uploading effect #0 (Periodic sinusoidal) ... Error:: Invalid argument
Uploading effect #1 (Constant) ... Error: Invalid argument
Uploading effect #2 (Spring) ... Error: Invalid argument
Uploading effect #3 (Damper) ... Error: Invalid argument
Uploading effect #4 (Strong rumble, with heavy motor) ... Error: Invalid argument
Uploading effect #5 (Weak rumble, with light motor) ... Error: Invalid argument
Enter effect number, -1 to exit
The reported ff effect types and periodic effects differ from your results. :s
I’m on kernel 5.15.0-102-generic
if that matters.
It does work with my DualShock 3 though:
Device /dev/input/event11 opened
Features:
* Absolute axes: X, Y, Z, RX, RY, RZ,
[3F 00 00 00 00 00 00 00 ]
* Relative axes:
[00 00 ]
* Force feedback effects types: Periodic, Rumble, Gain,
Force feedback periodic effects: Square, Triangle, Sine,
[00 00 00 00 00 00 00 00 00 00 03 07 01 00 00 00 ]
* Number of simultaneous effects: 16
Setting master gain to 75% ... OK
Uploading effect #0 (Periodic sinusoidal) ... OK (id 0)
Uploading effect #1 (Constant) ... Error: Invalid argument
Uploading effect #2 (Spring) ... Error: Invalid argument
Uploading effect #3 (Damper) ... Error: Invalid argument
Uploading effect #4 (Strong rumble, with heavy motor) ... OK (id 1)
Uploading effect #5 (Weak rumble, with light motor) ... OK (id 2)
Enter effect number, -1 to exit
By the way, the adapter also sets a bit in the controller status flags when the external power is plugged in, so you might be able to dynamically report FF support per controller and update it when this state changes. And as far as I know the Wavebird (the official wireless GC controller) does not support rumble, so I’ve excluded it in my patch to log the rumble status:
[ 2937.971212] gamecube-adapter 3-4:1.0: Port 0; Status: 00010100; Enable: 1; Rumble Allowed: 1
[ 2937.971222] gamecube-adapter 3-4:1.0: Port 1; Status: 00010100; Enable: 1; Rumble Allowed: 1
[ 2937.971225] gamecube-adapter 3-4:1.0: Port 2; Status: 00000100; Enable: 0; Rumble Allowed: 1
[ 2937.971228] gamecube-adapter 3-4:1.0: Port 3; Status: 00000100; Enable: 0; Rumble Allowed: 1
# Unplugging the power cable =>
[ 2939.419132] gamecube-adapter 3-4:1.0: Port 0; Status: 00010000; Enable: 1; Rumble Allowed: 0
[ 2939.419136] gamecube-adapter 3-4:1.0: Port 1; Status: 00010000; Enable: 1; Rumble Allowed: 0
[ 2939.419138] gamecube-adapter 3-4:1.0: Port 2; Status: 00000000; Enable: 0; Rumble Allowed: 0
[ 2939.419139] gamecube-adapter 3-4:1.0: Port 3; Status: 00000000; Enable: 0; Rumble Allowed: 0
# Plugged it back in =>
[ 2942.091189] gamecube-adapter 3-4:1.0: Port 0; Status: 00010100; Enable: 1; Rumble Allowed: 1
[ 2942.091200] gamecube-adapter 3-4:1.0: Port 1; Status: 00010100; Enable: 1; Rumble Allowed: 1
[ 2942.091204] gamecube-adapter 3-4:1.0: Port 2; Status: 00000100; Enable: 0; Rumble Allowed: 1
[ 2942.091207] gamecube-adapter 3-4:1.0: Port 3; Status: 00000100; Enable: 0; Rumble Allowed: 1
# Unplugged =>
[ 2945.091132] gamecube-adapter 3-4:1.0: Port 0; Status: 00010000; Enable: 1; Rumble Allowed: 0
[ 2945.091143] gamecube-adapter 3-4:1.0: Port 1; Status: 00010000; Enable: 1; Rumble Allowed: 0
[ 2945.091147] gamecube-adapter 3-4:1.0: Port 2; Status: 00000000; Enable: 0; Rumble Allowed: 0
[ 2945.091151] gamecube-adapter 3-4:1.0: Port 3; Status: 00000000; Enable: 0; Rumble Allowed: 0
# You get the idea
[ 2950.411101] gamecube-adapter 3-4:1.0: Port 0; Status: 00010100; Enable: 1; Rumble Allowed: 1
[ 2950.411112] gamecube-adapter 3-4:1.0: Port 1; Status: 00010100; Enable: 1; Rumble Allowed: 1
[ 2950.411115] gamecube-adapter 3-4:1.0: Port 2; Status: 00000100; Enable: 0; Rumble Allowed: 1
[ 2950.411118] gamecube-adapter 3-4:1.0: Port 3; Status: 00000100; Enable: 0; Rumble Allowed: 1
My current diff:
diff --git a/dkms.conf b/dkms.conf
new file mode 100644
index 0000000..291758a
--- /dev/null
+++ b/dkms.conf
@@ -0,0 +1,10 @@
+BUILT_MODULE_NAME[0]="gamecube-adapter"
+DEST_MODULE_LOCATION[0]="/extra"
+
+PACKAGE_NAME="$BUILT_MODULE_NAME"
+PACKAGE_VERSION="1.0.2"
+
+MAKE[0]="make KERNEL_SOURCE_DIR=$kernel_source_dir"
+CLEAN[0]="make KERNEL_SOURCE_DIR=$kernel_source_dir clean"
+
+AUTOINSTALL="yes"
diff --git a/usb-gamecube-adapter.c b/gamecube-adapter.c
similarity index 92%
rename from usb-gamecube-adapter.c
rename to gamecube-adapter.c
index aef5029..e1d4a54 100644
--- a/usb-gamecube-adapter.c
+++ b/gamecube-adapter.c
@@ -4,7 +4,7 @@
#include <linux/input.h>
#include <linux/usb/input.h>
-#include "usb-gamecube-adapter.h"
+#include "gamecube-adapter.h"
/* Callers must hold gdata->odata_lock spinlock */
static int gc_queue_rumble(struct gc_data *gdata)
@@ -116,15 +116,22 @@ static void gcc_input(struct gcc_data *gccdata, const u8 *keys)
input_report_key(gccdata->input, BTN_DPAD_UP, !!(keys[1] & BIT(7)));
input_report_key(gccdata->input, BTN_START, !!(keys[2] & BIT(0)));
- input_report_key(gccdata->input, BTN_TR2, !!(keys[2] & BIT(1)));
- input_report_key(gccdata->input, BTN_TR, !!(keys[2] & BIT(2)));
- input_report_key(gccdata->input, BTN_TL, !!(keys[2] & BIT(3)));
+ input_report_key(gccdata->input, BTN_TR2, !!(keys[2] & BIT(1))); // Z
+ input_report_key(gccdata->input, BTN_TR, !!(keys[2] & BIT(2))); // L (digital)
+ input_report_key(gccdata->input, BTN_TL, !!(keys[2] & BIT(3))); // R (digital)
+ // Left analog stick
input_report_abs(gccdata->input, ABS_X, keys[3]);
input_report_abs(gccdata->input, ABS_Y, keys[4] ^ 0xFF);
+
+ // Right analog stick (C stick)
input_report_abs(gccdata->input, ABS_RX, keys[5]);
input_report_abs(gccdata->input, ABS_RY, keys[6] ^ 0xFF);
+
+ // Left trigger
input_report_abs(gccdata->input, ABS_Z, keys[7]);
+
+ // Right trigger
input_report_abs(gccdata->input, ABS_RZ, keys[8]);
input_sync(gccdata->input);
@@ -195,9 +202,13 @@ static int gc_controller_init(struct gcc_data *gccdev, u8 status)
input_set_drvdata(gccdev->input, gccdev);
usb_to_input_id(gccdev->adapter->udev, &gccdev->input->id);
- gccdev->input->name = "Nintendo GameCube Controller";
+
+ gccdev->input->name = gccdev->name;
gccdev->input->phys = gccdev->adapter->phys;
+ // dev_set_name(&gccdev->input->dev, "input%d", gccdev->no);
+ // gccdev->input->dev.parent = &gccdev->adapter->intf->dev;
+
set_bit(EV_KEY, gccdev->input->evbit);
set_bit(BTN_A, gccdev->input->keybit);
@@ -249,17 +260,32 @@ gc_deinit_controller:
return error;
}
+#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
+#define BYTE_TO_BINARY(byte) \
+ ((byte) & 0x80 ? '1' : '0'), \
+ ((byte) & 0x40 ? '1' : '0'), \
+ ((byte) & 0x20 ? '1' : '0'), \
+ ((byte) & 0x10 ? '1' : '0'), \
+ ((byte) & 0x08 ? '1' : '0'), \
+ ((byte) & 0x04 ? '1' : '0'), \
+ ((byte) & 0x02 ? '1' : '0'), \
+ ((byte) & 0x01 ? '1' : '0')
+
static void gc_controller_update_work(struct work_struct *work)
{
int i;
u8 status[4];
bool enable[4];
+ bool rumble_allowed[4];
unsigned long flags;
struct gc_data *gdata = container_of(work, struct gc_data, work);
for (i = 0; i < 4; i++) {
status[i] = gdata->controllers[i].status;
enable[i] = gc_connected_type(status[i]) != 0;
+ rumble_allowed[i] = (status[i] & GAMECUBE_WIRELESS) == 0 && (status[i] & 0x04) != 0;
+
+ dev_info(&gdata->intf->dev, "Port %d; Status: "BYTE_TO_BINARY_PATTERN"; Enable: %d; Rumble Allowed: %d\n", i, BYTE_TO_BINARY(status[i]), enable[i], rumble_allowed[i]);
}
for (i = 0; i < 4; i++) {
@@ -449,6 +475,8 @@ static void gc_init_controllers(struct gc_data *gdata)
gdata->controllers[i].no = i;
gdata->controllers[i].status = GAMECUBE_NONE;
gdata->controllers[i].enable = false;
+
+ snprintf(gdata->controllers[i].name, 32, "Nintendo GameCube Controller #%d", i + 1);
}
}
@@ -530,7 +558,7 @@ static const struct usb_device_id gc_usb_devices[] = {
MODULE_DEVICE_TABLE(usb, gc_usb_devices);
static struct usb_driver gc_usb_driver = {
- .name = "gamecube_adapter",
+ .name = "gamecube-adapter",
.id_table = gc_usb_devices,
.probe = gc_usb_probe,
.disconnect = gc_usb_disconnect,
diff --git a/usb-gamecube-adapter.h b/gamecube-adapter.h
similarity index 98%
rename from usb-gamecube-adapter.h
rename to gamecube-adapter.h
index 26b794b..c835167 100644
--- a/usb-gamecube-adapter.h
+++ b/gamecube-adapter.h
@@ -32,6 +32,7 @@ struct gcc_data {
u8 no;
u8 status;
bool enable;
+ char name[32];
};
struct gc_data {
Well I know that there is a flag for that but I first wanted a module which work ^^' and is simple enought to understand Supporting rumble change also mean recreating the controller as I'm not sure adding it on the fly won't cause some issues ^^'
Can you mainline this driver please? The driver will be deployed to billions of devices, and the adapter will work with future Linux, Android, and ChromeOS devices.