Skip to content

feat(libSceUsbd): implement the device path over the host libusb - #1743

Closed
Dextroid17 wants to merge 1 commit into
boykopovar:mainfrom
Dextroid17:feat/usbd-libusb
Closed

Dextroid17 wants to merge 1 commit into
boykopovar:mainfrom
Dextroid17:feat/usbd-libusb

Conversation

@Dextroid17

Copy link
Copy Markdown
Contributor

What

libSceUsbd implemented only the no-device path: 25 of its 30 declarations called NotImplemented_nid_no_patch, the device list was always empty and the documented debt entry read "calls that need a device throw". This implements the whole surface over the host's libusb, resolved at runtime, so no new build dependency is added and a build without libusb keeps today's behaviour.

How the device path is reached

libusb-1.0 is resolved with SDL_LoadObject / SDL_LoadFunction — the same way libSceAgcDriver resolves the Vulkan loader — and libSceUsbd links SDL2-static for it. Where libusb is absent (or a symbol is missing), every call that needs a device returns SCE_USBD_ERROR_NOT_SUPPORTED (0x8024000C) instead of throwing, the device list stays the empty null-terminated array, and sceUsbdInit still succeeds. So the no-libusb path is a documented result, not a stub.

Signatures

The 25 stubs were declared without parameters, so their signatures are part of this change. They agree with public sources and with the five that already existed:

  • the PS5 3.20 libSceUsbd export list (DNNDHH/PS5-3.20_Libs) for the names — it also shows the library mirrors libusb's API;
  • the PS4 SDK header include/orbis/Usbd.h (OpenOrbis/OpenOrbis-PS4-Toolchain) for the prototypes;
  • shadPS4's src/core/libraries/usbd/usbd.cpp for the mapping and the error translation: LIBUSB_ERROR_OTHER to 0x802400FF, otherwise 0x80240000 - result — which reproduces the existing SCE_USBD_ERROR_INVALID_ARG = 0x80240002 for LIBUSB_ERROR_INVALID_PARAM.

What is implemented

All 30 declarations: enumeration and list lifetime, open / close, ref / unref, bus number and device address, get_configuration, set_configuration, the three descriptor reads and free_config_descriptor, claim / release_interface, kernel_driver_active / attach_kernel_driver, reset_device, check_connected, transfer alloc / free / fill_interrupt / submit / cancel, control_transfer, event_handling_ok and handle_events_timeout. Every pointer argument is validated before it reaches libusb, which does not null-check its own.

Tested

  • Built for Linux; guest_usbd passes (it is registered already, so no new test target).
  • With libusb present: sceUsbdInit succeeds, sceUsbdGetDeviceList returns a null-terminated list that sceUsbdFreeDeviceList accepts, sceUsbdAllocTransfer(0) returns a transfer that frees, sceUsbdEventHandlingOk returns 1, and the null-argument contracts hold (open, claim, reset, control_transfer, submit, cancel, the descriptor reads).
  • With libusb blocked (LD_PRELOAD interposing dlopen for the libusb soname) the same test passes and asserts the fallback: calls needing a device report SCE_USBD_ERROR_NOT_SUPPORTED.
  • tools/progress.py: libSceUsbd goes from 5/30 to 30/30, overall 84.76% to 85.58%.
  • Not tested: no transfer, descriptor read or interface claim against a real USB device — there is none attached here and the CI runners have none either. The signatures are taken from the sources above rather than measured on the console, and the debt entry now says so.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • AI-assisted: yes

@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown

Progress report (6b56175 → b375bea)

📈 System libraries: 85.58% (+0.82%, +25 implemented functions)

✅ 25 implemented
Library Name
libSceUsbd sceUsbdAllocTransfer
libSceUsbd sceUsbdAttachKernelDriver
libSceUsbd sceUsbdCancelTransfer
libSceUsbd sceUsbdCheckConnected
libSceUsbd sceUsbdClaimInterface
libSceUsbd sceUsbdClose
libSceUsbd sceUsbdControlTransfer
libSceUsbd sceUsbdEventHandlingOk
libSceUsbd sceUsbdFillInterruptTransfer
libSceUsbd sceUsbdFreeConfigDescriptor
libSceUsbd sceUsbdFreeTransfer
libSceUsbd sceUsbdGetActiveConfigDescriptor
libSceUsbd sceUsbdGetBusNumber
libSceUsbd sceUsbdGetConfigDescriptor
libSceUsbd sceUsbdGetDeviceAddress
libSceUsbd sceUsbdGetDeviceDescriptor
libSceUsbd sceUsbdGetStringDescriptor
libSceUsbd sceUsbdKernelDriverActive
libSceUsbd sceUsbdOpen
libSceUsbd sceUsbdRefDevice
libSceUsbd sceUsbdReleaseInterface
libSceUsbd sceUsbdResetDevice
libSceUsbd sceUsbdSetConfiguration
libSceUsbd sceUsbdSubmitTransfer
libSceUsbd sceUsbdUnrefDevice

@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
#1983 docs/dev/TechnicalDebt.md L23-24
#2001 core/libs/prx/libSceUsbd/CMakeLists.txt L1-15
core/libs/prx/libSceUsbd/Export.cpp L3-22, L25-172
core/libs/tests/GuestUsbd.cpp L1-64
docs/dev/TechnicalDebt.md L24-26

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Closing: no title needs these, and loading the host's libusb at runtime with a NOT_SUPPORTED path when it's missing is a fallback the project doesn't take (third-party code goes in as a submodule built from source). If a game turns out to use libSceUsbd, please reopen with the title ID and the call it stops at.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants