Files
AnyPS5/docs/dev/debt/libSceUsbStorage.md
T
simnJS 6988438d77 feat(libSceUsbStorage): pass host volumes through only with APS5_USB_STORAGE_PASSTHROUGH
Unset, ScanHostVolumes returns no volume, so nothing is scanned or
exposed and the guest sees no USB storage, as on main. The test checks
that injected volumes are neither listed nor raised by a rescan with the
switch off, and turns it on for the device cases.
2026-10-27 00:01:56 +01:00

23 lines
11 KiB
Markdown

# libSceUsbStorage technical debt
### Unknown function info
- [sceUsbStorageRegisterCallback, sceUsbStorageUnregisterCallback](../../../core/libs/prx/libSceUsbStorage/Export.cpp) (libSceUsbStorage) - the answers for a registration before `sceUsbStorageInit`, a second registration of the same callback for the same event type and the unregistration of a callback that is not registered are unknown, so the first two throw and the third keeps the marker. Whether the console raises mount events for devices attached before the registration is unknown; none are raised. A registration keeps its user data and receives [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Platform/UsbStorage.cs#L186-L199)'s 16-byte event (1 for a mount and 2 for an unmount, the device id, the device flags) for its event type only, on a service thread that rescans the host once a second instead of the automounter's IPC thread; an unregistered callback is not called again. Closes when: measured on a PS5
- [sceUsbStorageRegisterCallbackForMapAvailable, sceUsbStorageUnregisterCallbackForMapAvailable, sceUsbStorageRegisterCallbackForMapUnavailable, sceUsbStorageUnregisterCallbackForMapUnavailable](../../../core/libs/prx/libSceUsbStorage/Export.cpp) (libSceUsbStorage) - what a successful registration stores and when the callbacks fire is unverified: [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/f68923fe807f657348e6719ce658bcbd0a2b1c72/src/core/libraries/usbd/usbstorage.cpp#L128-L174) logs all four as `(STUBBED)` and returns 0 without storing anything, the success-without-a-reference pattern #6288 was closed for. The argument validation is implemented (0x80f40002 for a null callback or a null directory); past it they keep the marker until a reference or a measurement says what success does.
- [sceUsbStorageRequestUnmap, sceUsbStorageGetdentsClose](../../../core/libs/prx/libSceUsbStorage/Export.cpp) (libSceUsbStorage) - what the console answers for a mount point that is not mapped and a getdents descriptor that is not open is unknown: shadPS4's [unmap](https://github.com/shadps4-emu/shadPS4/blob/f68923fe807f657348e6719ce658bcbd0a2b1c72/src/core/libraries/usbd/usbstorage.cpp#L281-L288) only logs without keeping state and its [close](https://github.com/shadps4-emu/shadPS4/blob/f68923fe807f657348e6719ce658bcbd0a2b1c72/src/core/libraries/usbd/usbstorage.cpp#L378-L383) succeeds only because `erase` ignores a missing key. Both keep the marker on that path, after their argument validation; unmapping a mount point a map request returned, as [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Platform/UsbStorage.cs#L386-L398) does, and closing an open scan succeed.
- [sceUsbStorageClearFakeWriteProtection, sceUsbStorageSetFakeMapLockForDebug, sceUsbStorageSetFakeWriteProtection](../../../core/libs/prx/libSceUsbStorage/Export.cpp) (libSceUsbStorage) - names and NIDs are present in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceUsbStorage.c), but no credible prototypes were found. They are declared without parameters solely to resolve known imports; this is not an ABI claim.
- [sceUsbStorageGetMountPointOfShellCore](../../../core/libs/prx/libSceUsbStorage/Export.cpp) (libSceUsbStorage) - no reference says what the console writes or returns for a device that is not attached or a null buffer; both keep the marker. An attached device writes its mount point, `/mnt/usb<id>` after [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Platform/UsbStorage.cs#L22-L25)'s `/mnt/usb0`.
- [sceUsbStorageInit](../../../core/libs/prx/libSceUsbStorage/Export.cpp) (libSceUsbStorage) - the parameter is the attribute of the service's own thread ([SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Platform/UsbStorage.cs#L241-L242)), but its type is unresolved, so a non-null attribute throws. Initializing again while initialized succeeds without a rescan; that answer is not measured.
### Functional
- [the host passthrough](../../../core/libs/prx/libSceUsbStorage/src/HostVolumes.cpp) (libSceUsbStorage) - only with `APS5_USB_STORAGE_PASSTHROUGH` set; without it no host volume is scanned. The devices are the FAT and exFAT volumes the host mounted from USB mass-storage devices: on Linux the whole-file-system `vfat`, `msdos` and `exfat` entries of `/proc/self/mountinfo` whose block device sits under a USB interface of class 08 in sysfs, on [Windows](../../../core/libs/prx/libSceUsbStorage/src/HostVolumesWindows.cpp) the drive letters whose FAT, FAT32 or exFAT volume reports `BusTypeUsb`, and none on macOS. NTFS and a FUSE exFAT (`fuseblk`) are not listed. `sceUsbStorageInit` scans the host and a service thread rescans it once a second; a volume keeps its id, the lowest free of eight slots, while it stays mounted, and `/mnt/usb<id>` resolves to its current root until a scan drops it or `sceUsbStorageTerm`. How the console numbers its devices is unknown. Closes when: measured on a PS5
- [sceUsbStorageUnregisterCallback](../../../core/libs/prx/libSceUsbStorage/Export.cpp) (libSceUsbStorage) - it waits for a callback that is running, except when called from inside a callback, so a callback must not wait on a thread that is unregistering. Whether the console's unregistration waits is unknown. Closes when: measured on a PS5
- [the device-info record](../../../core/libs/prx/libSceUsbStorage/Export.cpp) (libSceUsbStorage) - the 0x338-byte record is unverified on hardware; its layout follows [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Platform/UsbStorage.cs#L34-L45), which recovered it from the module's own export: the u64 volume size at offset 0, the vendor, product and serial strings at 0x16, 0x120 and 0x228, and the flags the service masks with 0xd0 at 0x330. The vendor id, product id and release at 0x10, 0x12 and 0x14, the string lengths at 0x118, 0x220 and 0x328 and flag bits 4 (read-only), 6 (FAT) and 7 (exFAT) follow [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/f68923fe807f657348e6719ce658bcbd0a2b1c72/src/core/libraries/usbd/usbstorage.cpp#L28-L55), whose record otherwise starts with a device id where a title reads the volume size. Closes when: measured on a PS5
- [the device-info values](../../../core/libs/prx/libSceUsbStorage/Export.cpp) (libSceUsbStorage) - which strings and which size the console reports is unknown. The volume size is the capacity of the mounted file system, not of the partition; the vendor and product are the SCSI inquiry strings (sysfs `vendor` and `model`, or the storage device descriptor on Windows) without trailing spaces, and the serial number is the USB one, empty when the device has none. A string longer than 255 bytes throws. Closes when: measured on a PS5
- [the map requests](../../../core/libs/prx/libSceUsbStorage/Export.cpp) (libSceUsbStorage) - `sceUsbStorageRequestMap` and `sceUsbStorageRequestMapWSB` follow [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/f68923fe807f657348e6719ce658bcbd0a2b1c72/src/core/libraries/usbd/usbstorage.cpp#L245-L279): the mount point is `/mnt/usb<id>` followed by the requested directory (the device root for a null or empty one), the last argument receives 0 and null outputs are skipped. The directory must exist on the device; a missing one, a `.` or `..` component, a component with a root name (a drive letter on Windows), a backslash, a mount point longer than 127 bytes, a second map of the same directory, nonzero flags or volume size, and a nonzero fourth `RequestMapWSB` argument throw, as their answers are unknown. Unlike shadPS4, a directory that starts with `/mnt/usb` is not returned unchanged. The mapping limit SharpProspero names (0x80f40015) is not enforced. Closes when: measured on a PS5
- [sceUsbStorageIsExist](../../../core/libs/prx/libSceUsbStorage/Export.cpp) (libSceUsbStorage) - it reports whether the attached device holds the directory, resolved and refused as for a map request (the device root for a null or empty one), where shadPS4's [one-argument version](https://github.com/shadps4-emu/shadPS4/blob/f68923fe807f657348e6719ce658bcbd0a2b1c72/src/core/libraries/usbd/usbstorage.cpp#L237-L243) has no directory; what the console does with the directory or a null output, and whether the bool result reports success or failure, is unknown; a null output throws. Closes when: measured on a PS5
- [the getdents scan](../../../core/libs/prx/libSceUsbStorage/Export.cpp) (libSceUsbStorage) - `sceUsbStorageGetdentsOpen` lists the root of the device into descriptors numbered from 1 with a 0x8000-byte buffer size, skipping names that start with a dot, and `sceUsbStorageGetdentsRead` writes shadPS4's [packed dirent](https://github.com/shadps4-emu/shadPS4/blob/f68923fe807f657348e6719ce658bcbd0a2b1c72/src/core/libraries/usbd/usbstorage.cpp#L290-L376) (u32 file number from 1, u16 record length rounded to 8, type 4 for a directory and 8 otherwise, u8 name length, NUL-terminated name) until the buffer is full and zero bytes at the end. A name longer than 255 bytes, a host listing error and a buffer too small for the next record throw where shadPS4 truncates, ignores or answers zero bytes. None of this is measured on a console. Closes when: measured on a PS5
- [the argument validation](../../../core/libs/prx/libSceUsbStorage/Export.cpp) (libSceUsbStorage) - the null-pointer, null-callback, event-type and null-directory refusals with 0x80f40002, the answers 0x80f40004 for a device that is not attached, and the getdents read of a descriptor that is not open answering 0x80f40005 with zero bytes, follow [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/f68923fe807f657348e6719ce658bcbd0a2b1c72/src/core/libraries/usbd/usbstorage.cpp#L176-L383); the validation runs before the markers the exports keep above. None of this is measured on a console.
- [the prototypes of sceUsbStorageRequestMap and sceUsbStorageGetDeviceList](../../../core/libs/prx/libSceUsbStorage/Export.cpp) (libSceUsbStorage) - the signatures follow the ABI restored on `main` (the firmware-database sweep of 2026-10-21), which matches [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/f68923fe807f657348e6719ce658bcbd0a2b1c72/src/core/libraries/usbd/usbstorage.cpp#L176-L383): `RequestMap`'s six parameters, the typed `UsbStorageCallback` of the register/unregister family, `IsExist`'s three-argument bool form and `GetDeviceList`'s `std::int32_t*` count (the count also follows [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Platform/UsbStorage.cs#L233-L235), whose earlier eight-parameter `RequestMap` reading carried the trailing reserved pair the restored ABI drops).