Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mainlining #2

Open
upintheairsheep opened this issue Feb 25, 2024 · 12 comments
Open

Mainlining #2

upintheairsheep opened this issue Feb 25, 2024 · 12 comments

Comments

@upintheairsheep
Copy link

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.

@Hinara
Copy link
Owner

Hinara commented Mar 3, 2024

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 :)

@Hinara
Copy link
Owner

Hinara commented Mar 28, 2024

Patch send for review :3
Cover letter
Patch
Well not without struggle as it seems the link between those two message didn't worked....

@max-m
Copy link

max-m commented Apr 11, 2024

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

@Hinara
Copy link
Owner

Hinara commented Apr 12, 2024

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.

@max-m
Copy link

max-m commented Apr 12, 2024

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.

@Hinara
Copy link
Owner

Hinara commented Apr 13, 2024

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)

@max-m
Copy link

max-m commented Apr 13, 2024

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 {

@Hinara
Copy link
Owner

Hinara commented Apr 13, 2024

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 ^^'

@daniele-bondi
Copy link

daniele-bondi commented Oct 22, 2024

Hi

In my quest to try to play with a gcc I stumbled on your driver, and also on a forum post where you asked for a review.

Some time ago I found this driver by sheer luck.
https://lore.kernel.org/linux-input/[email protected]/
https://lore.kernel.org/linux-input/[email protected]/

It ended up not being included in the kernel (for no apparent reason), but I changed it a little to turn it into a module and it works.
It's not perfect: for whatever reason parsec mixed up inputs and having steam open makes the controller stop working. It also would not be recognized by the RoA2 beta, with or without steam.
Aside from that, I've been using it to play on yuzu for a couple of years without major issues.

I thought you might be interested in studying it, so here it is.
Also, it's a HID driver, which may solve the priority problem I saw you mention.

@bemug
Copy link

bemug commented Oct 25, 2024

I just found this repository.

Some time ago I picked up your patches from the v3 serie, and made it compile on the latest kernel. You find this my work in my hid-gamecube-adapter repository.

The ultimate goal was to generate the hid-gamecube-adapter-dkms-git AUR package for Arch Linux. So that I can just build it as an out-of-tree module without bothering about kernel updates and stuff.

Now moving forward :

  • Should I merge my work into this git repository ?
  • Are you still planning on mainlining ?

@Hinara
Copy link
Owner

Hinara commented Oct 25, 2024

Hi,
Thank you to both of you for the interest and sorry for not providing any update on the matter ^^'
For the mainlining it still is something I would like to do, I made the change post them and was waiting for someone to comeback at me, and as it took 1 month for the review the first time, I thought it would be normal to not have any message until some time and forgot a bit about it as in the end I didn't received any reply ^^'
For your work on your branch feel free to send a merge request I will review it prompty.
Things I cannot test (so if you are interested in testing) so if you want to test it to make sure everything works fine:

  • I do not have a Wavebird under the hand and to make the kernel module as simple as possible choose to make my driver consider the wavebird as the same as a regular controller (also in the enumeration of rumble capabilities despite not having them available)
  • Multiple controllers ^^' (Test things by plugging a controller and switching on each port to make sure everything just works fine

@Hinara
Copy link
Owner

Hinara commented Oct 25, 2024

Hi

In my quest to try to play with a gcc I stumbled on your driver, and also on a forum post where you asked for a review.

Some time ago I found this driver by sheer luck. https://lore.kernel.org/linux-input/[email protected]/ https://lore.kernel.org/linux-input/[email protected]/

It ended up not being included in the kernel (for no apparent reason), but I changed it a little to turn it into a module and it works. It's not perfect: for whatever reason parsec mixed up inputs and having steam open makes the controller stop working. It also would not be recognized by the RoA2 beta, with or without steam. Aside from that, I've been using it to play on yuzu for a couple of years without major issues.

I thought you might be interested in studying it, so here it is. Also, it's a HID driver, which may solve the priority problem I saw you mention.

Could you try to test with a controller already in the kernel ? I would suggest a XBox Controller or one of it's clone as I based my most of my work on xpad.c to see if you have the same issues with it ?
If it is the case I'm afraid that it is an issue with some of those software. If not I might need to dive a bit deeper onto this matter, but hope it is not an hardcoded list of supported controller on some of those software ^^'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants