Skip to content

feat(libSceBluetoothHid): implement sceBluetoothHidThreadParamInitialize - #12638

Merged
oneandonlydean merged 1 commit into
boykopovar:mainfrom
Lindamea1:feat/bluetoothhid-thread-param-init
Oct 29, 2026
Merged

oneandonlydean merged 1 commit into
boykopovar:mainfrom
Lindamea1:feat/bluetoothhid-thread-param-init

Conversation

@Lindamea1

Copy link
Copy Markdown
Contributor

What

sceBluetoothHidThreadParamInitialize(BluetoothHidThreadParam* param, int32_t priority, uint64_t affinityMask) threw NotImplemented (Export.cpp L133-L136). It now fills the thread parameter block that sceBluetoothHidRegisterCallback reads:

  • A null param returns 0x81540001, the existing InvalidArgument (L23).
  • Otherwise it stores priority in the 32 bits at offset 0, affinityMask in the 64 bits at offset 8 and 0 in the 32 bits at offset 16 (reserved), and returns 0. The three members are stored one by one, with no struct assignment or memset, so bytes 4 to 7 (padding) and 20 to 23 (tailPadding) keep what the caller left there.
  • Like sceBluetoothHidParamInitialize (L121-L126), it checks no range, keeps no library state and does not need sceBluetoothHidInit.

The struct and the declaration already exist on main (Api.hpp L9-L15, L59), with the offsets pinned by the static_asserts at Export.cpp L11-L13. Only the body changes.

References:

  • BunnyFl's native run of firmware 13.42's libSceBluetoothHid.sprx on x86-64, not a console, fourth bullet of this comment: sceBluetoothHidThreadParamInitialize(thread, priority, affinity) writes the int priority at +0, the 64-bit affinity at +8 and 0 at +0x10. With (700, 0x3f) the bytes were bc 02 00 00 | 5a 5a 5a 5a | 3f 00 … | 00 00 00 00, the four bytes at +4 keeping their 0x5a fill. A null pointer returns 0x81540001. The second and third bullets show sceBluetoothHidRegisterCallback reading these fields: an int at +0, a 64-bit value at +8 and an int at +0x10, which it accepted as 0 and refused with 0x81540001 as 1. feat: answer the NpWebApi2 multipart calls and sceBluetoothHidParamInitialize from their sources #11124 used the same run for sceBluetoothHidParamInitialize.
  • SharpProspero L51-L53 types the arguments (uint* param, uint value1, ulong value2): a 32-bit priority and a 64-bit affinity, as declared on main.

Not covered by the run: the value returned on success, range checks of the priority or the affinity mask, bytes 20 to 23 and calls before sceBluetoothHidInit. The run covers one input, (700, 0x3f), and a null block. The 0 on success is unverified: it is what the same run's sceBluetoothHidParamInitialize returns, and SharpProspero's class comment, L11-L12, gives 0 on success for every call of the library. The same lines say sceBluetoothHidInit must run first; like sceBluetoothHidParamInitialize on main, this function does not check that. A new entry in docs/dev/debt/libSceBluetoothHid.md records these gaps, and the sceBluetoothHidParamInitialize entry drops its closing clause (L10: "The same run covers sceBluetoothHidThreadParamInitialize, still unimplemented here").

Unchanged: sceBluetoothHidRegisterCallback still throws for a non-null thread block after its reserved check (L42-L45, from aaf286859), because the host has no event-watcher thread to apply the priority and affinity to. A title that passes the block built here to sceBluetoothHidRegisterCallback still stops there, so this PR moves no title forward. No title is known to import sceBluetoothHidThreadParamInitialize: the exports that cb00552dd added, with signatures taken from one title, do not include it, and it came from the firmware export database in 173c827c6.

Test, in guest_bluetooth_hid (core/libs/tests/GuestBluetoothHid.cpp), after the existing sceBluetoothHidParamInitialize checks (L101-L117): a BluetoothHidThreadParam filled with 0x5a and initialised with (700, 0x3f) must return 0 and hold the run's bytes: bc 02 00 00 at 0 to 3, 5a 5a 5a 5a at 4 to 7, 3f and seven 00 at 8 to 15, and 00 00 00 00 at 16 to 19. A null block must return 0x81540001 with (700, 0x3f) and with (0, 0). Bytes 20 to 23, other values and calls before sceBluetoothHidInit are not checked, as the run does not cover them.

Overlap: tools/pr_overlap.py against the open PRs on 2026-10-28 reports only #9138, which conflicts with main and shares Export.cpp and docs/dev/debt/libSceBluetoothHid.md. Against its merge base, #9138 edits sceBluetoothHidGetDeviceName, sceBluetoothHidGetInputReport and sceBluetoothHidSetOutputReport, adds a Silent stubs entry for them and appends a comment line to each file. It touches neither sceBluetoothHidThreadParamInitialize nor the debt entries changed here, so neither PR needs to go first. gh pr list --state open --search ThreadParamInitialize finds no PR; --search BluetoothHid finds only #7658, which changes no BluetoothHid file.

Tested

Gentoo Linux, kernel 7.2.8, GCC 16.2.1, Release, BUILD_TESTING=ON, Ninja, this branch on main 319621b.

  • ctest --test-dir build -R '^guest_bluetooth_hid$|public_headers' --output-on-failure -j8 --timeout 300: 66/66 passed (guest_bluetooth_hid, public_headers and the 64 public_headers_compile_* batches).
  • ctest --test-dir build -R '^guest_bluetooth_hid$' --output-on-failure, three more times: 1/1 passed each time, in under 0.01 s.
  • Control: with main's Export.cpp (git show 319621ba2:core/libs/prx/libSceBluetoothHid/Export.cpp) and this test, rebuilt, guest_bluetooth_hid aborts with terminate called after throwing an instance of 'std::runtime_error', what(): sceBluetoothHidThreadParamInitialize not implemented.
  • CI test selection (tools/select_tests.py dump, select, ninja -C build -f select.ninja selected, tools/select_tests.py ctest build --output-on-failure -j8): 487 of the 2745 tests selected, 487/487 passed, none skipped.
  • python3 tools/check_test_registration.py build: 1515 test executables, 0 built and not run, none new.
  • python3 tools/check_conventions.py --base 319621ba2: all checks passed.
  • Windows: MinGW-w64 syntax check of the changed files only, not a Windows build or run. x86_64-w64-mingw32-g++ 16.2.0 with -std=gnu++20 -fsyntax-only -Wall -Wextra -D_WIN32_WINNT=0x0602 -I core/libs -I core/libs/nid/include -I core/libs/prx/libkernel on Export.cpp and GuestBluetoothHid.cpp: no errors. The only warnings are -Wunused-parameter on the unchanged stubs at Export.cpp lines 77 to 128.

Not tested: no console, no title, no Windows or macOS build or run.

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 under Silent stubs in their library's technical debt file
  • 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
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

🤖 Generated with Claude Code

sceBluetoothHidThreadParamInitialize threw NotImplemented. It now fills
the thread parameter block that sceBluetoothHidRegisterCallback reads:
the 32-bit priority at offset 0, the 64-bit affinity mask at offset 8
and 0 in the 32 bits at offset 16, leaving bytes 4 to 7 and 20 to 23
as they were, and returns 0. A null block returns 0x81540001.

This follows BunnyFl's native x86-64 run of firmware 13.42's
libSceBluetoothHid, not a console:
boykopovar#11124 (comment)
The test checks the run's bytes for (700, 0x3f) and the null answer.
The run does not show the success value, range checks, bytes 20 to 23
or calls before sceBluetoothHidInit; the debt entry records them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Progress report (3a2b919 → b2b07ce)

📈 System libraries: 45.92% (+0.01%, +1 implemented functions)

✅ 1 implemented
Library Name
libSceBluetoothHid sceBluetoothHidThreadParamInitialize

Changed libraries (implemented exports)

Library Before After Change
libSceBluetoothHid 7/17 (41.18%) 8/17 (47.06%) +5.88 pp

@adriadam10 adriadam10 self-assigned this Oct 29, 2026
@github-actions

Copy link
Copy Markdown

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 9138 core/libs/prx/libSceBluetoothHid/Export.cpp
docs/dev/debt/libSceBluetoothHid.md

@JJenkx

JJenkx commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Windows run of this head (b2b07ce33d), merged onto main 3a2b919816 (clean merge, local only). Windows 11 Enterprise 10.0.22621, Ryzen 9 5950X, WinLibs GCC 15.2.0 UCRT r7, Ninja, Release, BUILD_TESTING=ON, no Vulkan driver visible.

  • This PR: guest_bluetooth_hid passes 3 of 3 (ctest --repeat until-fail:3).
  • Negative control: with core/libs/prx/libSceBluetoothHid/Export.cpp put back to main's version and everything else from this PR, guest_bluetooth_hid fails.

AI-assisted: yes (Claude Code).

@oneandonlydean

Copy link
Copy Markdown
Collaborator

@Lindamea1 reviewed at b2b07ce: PASS. Null gives InvalidArgument (0x81540001). Otherwise it stores priority, affinityMask and a cleared reserved field and returns 0, matching the cited 13.42 module run byte for byte, with padding left untouched. The debt entry lists what that run doesn't cover. GuestBluetoothHid (registered) asserts the bytes and the null cases.

@adriadam10 exact-head CI is green (run 40790158087); we'll merge this in the next train unless you'd rather merge it yourself.

@oneandonlydean oneandonlydean self-assigned this Oct 29, 2026
@oneandonlydean
oneandonlydean merged commit 74fe94e into boykopovar:main Oct 29, 2026
11 checks passed
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.

4 participants