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

usbd: Implement libusb passthrough #2271

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

deReeperJosh
Copy link

@deReeperJosh deReeperJosh commented Jan 29, 2025

Re-opening pull request that I had previously opened on accident to implement libusb passthrough for the USBD library.

It appears that the free bsd build that orbis os is based off of used libusb for it's usb transactions (seen here), so we can use libusb as a submodule, and pass on all functions and parameters directly to libusb.

I can't take full credit for this code, many thanks go to Osyotr in the discord server who posted this code stub, I just needed to add the submodule.

The only major differences from the linked code stub are that I return the return value from libusb if the return code is > 0 (for methods where a return value > 0 is expected), and in the sceUsbdClaimInterface method, I check to see if a kernel driver is active before claiming the interface (required on linux and macos before performing device transactions)

I have tested this as working for Skylanders Trap Team, Skylanders Superchargers and Skylanders Imaginators on MacOS - would like some help testing more usb passthrough games (Lego Dimensions or Disney Infinity) as well as any users on Windows/Linux. Just an FYI that users on Windows will need to install winUSB as a driver for their chosen passthrough device, which can be done using Zadig

@ElBread3
Copy link
Contributor

ElBread3 commented Jan 29, 2025

Lego Dimensions has this block of code, taken from Ghidra:

iVar13 = sceUsbdKernelDriverActive(*puVar3,0);
if ((iVar13 != 1) ||
   ((iVar13 = sceUsbdDetachKernelDriver(*puVar3,*pcVar1), iVar13 != 0 ||
    (iVar13 = sceUsbdClaimInterface(*puVar3), iVar13 != 0)))) {
  sceUsbdResetDevice(*puVar3);
  puts("USB DEVICE RESET ON INIT 1");
  goto LAB_01517144;
}

which, since on Windows sceUsbdDetachKernelDriver will error LIBUSB_ERROR_NOT_SUPPORTED, will need handled on unsupported platforms to pass this.

@ElBread3
Copy link
Contributor

Now since sceUsbdKernelDriverActive returns 0 it still doesn't pass this condition, so like the condition says it will need to return 1. For future proofing for games that may check sceUsbdKernelDriverActive after detaching it and think it's still attached though, I'd recommend storing the state of attachment in a variable and returning that.

@deReeperJosh
Copy link
Author

deReeperJosh commented Jan 29, 2025

libusb_kernel_driver_active returns 0 if no kernel driver is active though - not sure why I would pass 1 back? The initial (iVar13 != 1) will return true, which then means it will go straight to the sceUsbdResetDevice line. Unless it is unwanted behaviour to be heading to the sceUsbdResetDevice line, because the game is assuming it will return 1?

@ElBread3
Copy link
Contributor

Unless it is unwanted behaviour to be heading to the sceUsbdResetDevice line, because the game is assuming it will return 1?

Exactly.

@deReeperJosh
Copy link
Author

This is an example of libusb in action, getting past the no portal screen in Skylanders: Trap Team; https://youtu.be/G8ydGRB1pJw

@georgemoralis
Copy link
Collaborator

looking nice , i will try it on windows as well :)

@georgemoralis
Copy link
Collaborator

Ok it seems that it doesn't work on windows ;/

εικόνα

@deReeperJosh
Copy link
Author

Welp, at least it doesn't crash. Will see if I can test on Windows to see why it doesn't work there, my assumption would be some byte order issue

@georgemoralis
Copy link
Collaborator

it stucks here in main as well

@deReeperJosh
Copy link
Author

I assume you had a USB portal plugged in? On windows, winUSB drivers will need to be installed as well, the default HID drivers don't work with libusb

@georgemoralis
Copy link
Collaborator

oh need to have a USB portal to pass it :? (thought it was just skipping it)

@deReeperJosh
Copy link
Author

Yes sorry should have made that clear - the games will require a USB peripheral like you would use on your PS4 normally to be attached, specifically for Trap Team in order to get past the please plug in a portal screen it requires a portal plugged in

@deReeperJosh
Copy link
Author

Tested Windows and got in game on Skylanders Imaginators, had game crashes with the portal plugged in on Trap Team and Superchargers, Swap Force crashes with or without portal plugged in

image

@valjbp
Copy link

valjbp commented Jan 31, 2025

Tested on Windows with LEGO Dimensions, toypad was not detected and the game reached the point where it asks for it.
image

@deReeperJosh
Copy link
Author

What driver did you have installed for your ToyPad?

@valjbp
Copy link

valjbp commented Jan 31, 2025

WinUSB, tried libusb too but doesn't seem to detect.
image

@squidbus
Copy link
Collaborator

squidbus commented Feb 1, 2025

Not having much luck with LEGO Dimensions either, on Mac. I'm also getting occasional crashes while the game boots in darwin_reenumerate_device, called from sceUsbdResetDevice, here:

(*dpriv->device)->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);

With dpriv->device being null.

@deReeperJosh
Copy link
Author

Thanks for testing, might need to get myself the Dimensions starter set for PS4 to do some testing locally

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

Successfully merging this pull request may close these issues.

5 participants