Skip to content

Conversation

@Zarithya
Copy link
Contributor

@Zarithya Zarithya commented Mar 26, 2025

This PR makes sweeping changes to how controllers are connected in homebrew apps, allowing for the pairing of new controllers without leaving a homebrew environment. This can be done either through pressing the red sync button on the front of the console (which is also exposed to homebrew authors via WPAD_SetSyncButtonCallback) for permanent pairing or by calling WPAD_Search/WPAD_StopSearch, which replicates the "Reconnect" button on the Home Menu and allows for guest controllers to be connected temporarily.

I wrote this as a convenience so I don't have to keep exiting to the Wii menu every time I want to test a new controller (I refurbish a lot of Wii controllers) but I figured it could be of use to others writing homebrew. This is my first time doing anything like this (including Wii software and Bluetooth driver development) so please let me know if anything needs to be tweaked!

The SYSCONF writing functionality was borrowed from AnyRegion Changer, written by tona.

@DacoTaco
Copy link
Member

WHOA.
this is huge!

ill have to look carefully at this, and test it fully but im looking forward to this!

@Aeplet
Copy link

Aeplet commented Mar 26, 2025

WOAH

@DacoTaco
Copy link
Member

DacoTaco commented Mar 26, 2025

ok so, i made a checklist for this PR that i will post below. i do this because of the huge impact this change has on the community. we've been waiting for this change for a LONG time but i never got around to do it nor do i understand BT/Wiiuse enough haha.

Anyway, i would like the following to be checked/done before merge:

  • Check Wiiuse changes to see if they don't have any conflicts upstream ( https://github.com/wiiuse/wiiuse ). this is because one day we will want to switch to upstream wiiuse
  • Test if code can handle a sync of a wiimote that is already synced (caused issues in past old wiimote demos)
  • Test Usage & syncing of classic remote and balance board
  • Test Regular & TR wiimotes
  • Test Syncing with red buttons
    • Test on vWii
    • Test on Wii Mini
    • Test on Wii
  • Test Syncing with search functions (temp sync)
    • Test on vWii
    • Test on Wii Mini
    • Test on Wii
  • Add Example in https://github.com/devkitPro/wii-examples
  • Do code review
  • Buy coffee to celebrate

this should be it. @Zarithya , it would be great if you could provide a small example program in the wii-examples repo that we can use/ship as an example but also use as a test to test the change :)

we (the wii community) are extremely happy with the change and would love to see this merged :)
because of this, i would like to invite anyone that wants to to help with the checklist above :)

@wiidev
Copy link

wiidev commented Mar 27, 2025

Also, Wiimotes won't reinit anymore after calling WPAD_Disconnect() followed by WPAD_Shutdown().

WPAD_Init();
printf("Wiimote LED should be on\n");
sleep(3);

// A lot of apps seem to loop through like this (including Priiloader)
for (int i = 0; i < WPAD_MAX_DEVICES; i++)
    WPAD_Disconnect(i);
WPAD_Shutdown();
printf("Wiimote LED should be off\n");
sleep(3);

WPAD_Init();
printf("Wiimote LED should be on again, but it remains off\n");
sleep(3);

If you skip calling WPAD_Disconnect() and only call WPAD_Shutdown() then it'll work correctly.

Thank you so much for sharing this with the community though. This has been on our wishlists for a long time 😊

@Zarithya
Copy link
Contributor Author

Zarithya commented Mar 27, 2025

Also, Wiimotes won't reinit anymore after calling WPAD_Disconnect() followed by WPAD_Shutdown().

@wiidev The bug is actually with Wiimotes reconnecting if you don't call WPAD_Disconnect() first. Seems like WPAD_Shutdown() isn't waiting long enough before uninitializing the Bluetooth subsystem, so the connection never gets fully disconnected and the Wiimote is left with an open connection that it tries to reconnect to once the Bluetooth subsystem is back online. The intended behavior is for the disconnect to finish processing before shutting down Bluetooth, which leaves the Wiimote satisfied and not trying to reconnect.

Of course, Wii games are able to disconnect Wiimotes and have them reconnect later, so I'm not sure how to properly replicate that. Maybe sniffing Bluetooth packets sent between the Wii menu and a Wiimote is in order...

Copy link
Member

@DacoTaco DacoTaco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, this is my first passthrough of the change. let this not demotivate you please. i love this and i hope you will see this through!

we would also love to see the test app ^^

@DacoTaco
Copy link
Member

Also, Wiimotes won't reinit anymore after calling WPAD_Disconnect() followed by WPAD_Shutdown().

@wiidev The bug is actually with Wiimotes reconnecting if you don't call WPAD_Disconnect() first. Seems like WPAD_Shutdown() isn't waiting long enough before uninitializing the Bluetooth subsystem, so the connection never gets fully disconnected and the Wiimote is left with an open connection that it tries to reconnect to once the Bluetooth subsystem is back online. The intended behavior is for the disconnect to finish processing before shutting down Bluetooth, which leaves the Wiimote satisfied and not trying to reconnect.

Of course, Wii games are able to disconnect Wiimotes and have them reconnect later, so I'm not sure how to properly replicate that. Maybe sniffing Bluetooth packets sent between the Wii menu and a Wiimote is in order...

aha, so the disconnect actually working as designed now haha
i suspect either SDK stuff doesnt call disconnect or indeed a feature is missing. this could be fixed in upstream wiiuse, i dont know...

@DacoTaco
Copy link
Member

DacoTaco commented Mar 27, 2025

ive logged in dolphin the following when in SM i boot a game:

13:27:474 Core/IOS/USB/Bluetooth/BTEmu.cpp:1461 I[IOS_WIIMOTE]: Command: HCI_CMD_RESET
13:29:823 Core/IOS/USB/Bluetooth/WiimoteDevice.cpp:65 I[IOS_WIIMOTE]: Wiimote: #0 Constructed
13:29:823 Core/IOS/USB/Bluetooth/WiimoteDevice.cpp:65 I[IOS_WIIMOTE]: Wiimote: #1 Constructed
13:29:823 Core/IOS/USB/Bluetooth/WiimoteDevice.cpp:65 I[IOS_WIIMOTE]: Wiimote: #2 Constructed
13:29:823 Core/IOS/USB/Bluetooth/WiimoteDevice.cpp:65 I[IOS_WIIMOTE]: Wiimote: #3 Constructed
13:29:823 Core/IOS/USB/Bluetooth/WiimoteDevice.cpp:65 I[IOS_WIIMOTE]: Wiimote: #4 Constructed

then the game boots, as code was running @80003400 which is no longer SM:

13:30:451 Core/IOS/USB/Bluetooth/BTEmu.cpp:1461 I[IOS_WIIMOTE]: Command: HCI_CMD_RESET
13:30:454 Core/IOS/USB/Bluetooth/BTEmu.cpp:1813 I[IOS_WIIMOTE]: Command: HCI_CMD_READ_BUFFER_SIZE:
13:30:455 Core/IOS/USB/Bluetooth/BTEmu.cpp:1644 I[IOS_WIIMOTE]: Command: HCI_CMD_WRITE_UNIT_CLASS:
13:30:455 Core/IOS/USB/Bluetooth/BTEmu.cpp:1583 I[IOS_WIIMOTE]: Command: HCI_CMD_WRITE_LOCAL_NAME:
13:30:456 Core/IOS/USB/Bluetooth/BTEmu.cpp:1502 I[IOS_WIIMOTE]: Command: HCI_CMD_WRITE_PIN_TYPE:
13:30:456 Core/IOS/USB/Bluetooth/BTEmu.cpp:1663 I[IOS_WIIMOTE]: Command: HCI_CMD_HOST_BUFFER_SIZE:
13:30:456 Core/IOS/USB/Bluetooth/BTEmu.cpp:1768 I[IOS_WIIMOTE]: Command: HCI_CMD_READ_LOCAL_VER:
13:30:457 Core/IOS/USB/Bluetooth/BTEmu.cpp:1829 I[IOS_WIIMOTE]: Command: HCI_CMD_READ_BDADDR:
13:30:457 Core/IOS/USB/Bluetooth/BTEmu.cpp:1792 I[IOS_WIIMOTE]: Command: HCI_CMD_READ_LOCAL_FEATURES:
13:30:459 Core/IOS/USB/Bluetooth/BTEmu.cpp:1729 I[IOS_WIIMOTE]: Command: HCI_CMD_WRITE_INQUIRY_MODE:
13:30:460 Core/IOS/USB/Bluetooth/BTEmu.cpp:1751 I[IOS_WIIMOTE]: Command: HCI_CMD_WRITE_PAGE_SCAN_TYPE:
13:30:461 Core/IOS/USB/Bluetooth/BTEmu.cpp:1704 I[IOS_WIIMOTE]: Command: HCI_CMD_WRITE_INQUIRY_SCAN_TYPE:
13:30:858 Core/IOS/USB/Bluetooth/BTEmu.cpp:1644 I[IOS_WIIMOTE]: Command: HCI_CMD_WRITE_UNIT_CLASS:
13:30:859 Core/IOS/USB/Bluetooth/BTEmu.cpp:1600 I[IOS_WIIMOTE]: Command: HCI_CMD_WRITE_PAGE_TIMEOUT:
13:30:870 Core/IOS/USB/Bluetooth/BTEmu.cpp:1526 I[IOS_WIIMOTE]: Command: HCI_CMD_READ_STORED_LINK_KEY:
13:30:888 Core/IOS/USB/Bluetooth/BTEmu.cpp:1850 I[IOS_WIIMOTE]: Command: CommandVendorSpecific_FC4F: (callstack WUDiRemovePatch)
13:30:889 Core/IOS/USB/Bluetooth/BTEmu.cpp:1850 I[IOS_WIIMOTE]: Command: CommandVendorSpecific_FC4F: (callstack WUDiRemovePatch)
13:30:890 Core/IOS/USB/Bluetooth/BTEmu.cpp:1461 I[IOS_WIIMOTE]: Command: HCI_CMD_RESET
13:30:891 Core/IOS/USB/Bluetooth/BTEmu.cpp:1813 I[IOS_WIIMOTE]: Command: HCI_CMD_READ_BUFFER_SIZE:
13:30:902 Core/IOS/USB/Bluetooth/BTEmu.cpp:1644 I[IOS_WIIMOTE]: Command: HCI_CMD_WRITE_UNIT_CLASS:
13:30:903 Core/IOS/USB/Bluetooth/BTEmu.cpp:1583 I[IOS_WIIMOTE]: Command: HCI_CMD_WRITE_LOCAL_NAME:
13:30:903 Core/IOS/USB/Bluetooth/BTEmu.cpp:1502 I[IOS_WIIMOTE]: Command: HCI_CMD_WRITE_PIN_TYPE:
13:30:904 Core/IOS/USB/Bluetooth/BTEmu.cpp:1663 I[IOS_WIIMOTE]: Command: HCI_CMD_HOST_BUFFER_SIZE:
13:30:905 Core/IOS/USB/Bluetooth/BTEmu.cpp:1768 I[IOS_WIIMOTE]: Command: HCI_CMD_READ_LOCAL_VER:
13:30:905 Core/IOS/USB/Bluetooth/BTEmu.cpp:1829 I[IOS_WIIMOTE]: Command: HCI_CMD_READ_BDADDR:
13:30:906 Core/IOS/USB/Bluetooth/BTEmu.cpp:1792 I[IOS_WIIMOTE]: Command: HCI_CMD_READ_LOCAL_FEATURES:
13:30:908 Core/IOS/USB/Bluetooth/BTEmu.cpp:1729 I[IOS_WIIMOTE]: Command: HCI_CMD_WRITE_INQUIRY_MODE:
13:30:910 Core/IOS/USB/Bluetooth/BTEmu.cpp:1751 I[IOS_WIIMOTE]: Command: HCI_CMD_WRITE_PAGE_SCAN_TYPE:
13:30:931 Core/IOS/USB/Bluetooth/BTEmu.cpp:1704 I[IOS_WIIMOTE]: Command: HCI_CMD_WRITE_INQUIRY_SCAN_TYPE:
13:30:951 Core/IOS/USB/Bluetooth/BTEmu.cpp:1644 I[IOS_WIIMOTE]: Command: HCI_CMD_WRITE_UNIT_CLASS:
13:30:956 Core/IOS/USB/Bluetooth/BTEmu.cpp:1600 I[IOS_WIIMOTE]: Command: HCI_CMD_WRITE_PAGE_TIMEOUT:
13:30:961 Core/IOS/USB/Bluetooth/BTEmu.cpp:1583 I[IOS_WIIMOTE]: Command: HCI_CMD_WRITE_LOCAL_NAME:
13:30:964 Core/IOS/USB/Bluetooth/BTEmu.cpp:1255 I[IOS_WIIMOTE]: Command: HCI_CMD_ACCEPT_CON
13:30:964 Core/IOS/USB/Bluetooth/BTEmu.cpp:757 I[IOS_WIIMOTE]: Event: Command Status (Opcode: 0x0409)
13:30:964 Core/HW/WiimoteEmu/EmuSubroutines.cpp:187 I[Wiimote]: Attaching Motion Plus (Wiimote 0 in slot 0)
13:30:964 Core/HW/WiimoteEmu/EmuSubroutines.cpp:213 I[Wiimote]: Switching to Extension 1 (Wiimote 0 in slot 0)
13:30:971 Core/IOS/USB/Bluetooth/BTEmu.cpp:1365 I[IOS_WIIMOTE]: Command: HCI_CMD_REMOTE_NAME_REQ
13:30:971 Core/IOS/USB/Bluetooth/BTEmu.cpp:757 I[IOS_WIIMOTE]: Event: Command Status (Opcode: 0x0419)
13:30:973 Core/IOS/USB/Bluetooth/BTEmu.cpp:1415 I[IOS_WIIMOTE]: Command: HCI_CMD_READ_CLOCK_OFFSET
13:30:973 Core/IOS/USB/Bluetooth/BTEmu.cpp:757 I[IOS_WIIMOTE]: Event: Command Status (Opcode: 0x041f)
13:30:973 Core/IOS/USB/Bluetooth/BTEmu.cpp:1400 I[IOS_WIIMOTE]: Command: HCI_CMD_READ_REMOTE_VER_INFO
13:30:973 Core/IOS/USB/Bluetooth/BTEmu.cpp:757 I[IOS_WIIMOTE]: Event: Command Status (Opcode: 0x041d)
13:30:984 Core/IOS/USB/Bluetooth/BTEmu.cpp:1385 I[IOS_WIIMOTE]: Command: HCI_CMD_READ_REMOTE_FEATURES
13:30:984 Core/IOS/USB/Bluetooth/BTEmu.cpp:757 I[IOS_WIIMOTE]: Event: Command Status (Opcode: 0x041b)
13:30:985 Core/IOS/USB/Bluetooth/BTEmu.cpp:1350 I[IOS_WIIMOTE]: Command: HCI_CMD_AUTH_REQ
13:30:985 Core/IOS/USB/Bluetooth/BTEmu.cpp:757 I[IOS_WIIMOTE]: Event: Command Status (Opcode: 0x0411)
13:30:987 Core/IOS/USB/Bluetooth/BTEmu.cpp:1334 I[IOS_WIIMOTE]: Command: HCI_CMD_CHANGE_CON_PACKET_TYPE
13:30:987 Core/IOS/USB/Bluetooth/BTEmu.cpp:757 I[IOS_WIIMOTE]: Event: Command Status (Opcode: 0x040f)
13:30:989 Core/IOS/USB/Bluetooth/BTEmu.cpp:1449 I[IOS_WIIMOTE]: Command: HCI_CMD_WRITE_LINK_POLICY_SETTINGS
13:30:989 Core/IOS/USB/Bluetooth/BTEmu.cpp:757 I[IOS_WIIMOTE]: Event: Command Status (Opcode: 0x080d)
13:30:990 Core/IOS/USB/Bluetooth/BTEmu.cpp:1681 I[IOS_WIIMOTE]: Command: HCI_CMD_WRITE_LINK_SUPERVISION_TIMEOUT
13:30:991 Core/IOS/USB/Bluetooth/BTEmu.cpp:1430 I[IOS_WIIMOTE]: Command: HCI_CMD_SNIFF_MODE
13:30:991 Core/IOS/USB/Bluetooth/BTEmu.cpp:757 I[IOS_WIIMOTE]: Event: Command Status (Opcode: 0x0803)

this doesn't say much to me, but i suspect it only reset the interface, but not actually disconnect wiimotes.
i say that because in priiloader, i found it sent a HCI_CMD_DISCONNECT command, which i assume is from the WPAD_Disconnect or WPAD_Shutdown (which also sends a disconnect btw).
log :

32:52:620 Core/IOS/USB/Bluetooth/BTEmu.cpp:1230 I[IOS_WIIMOTE]: Command: HCI_CMD_DISCONNECT
32:52:620 Core/IOS/USB/Bluetooth/BTEmu.cpp:757 I[IOS_WIIMOTE]: Event: Command Status (Opcode: 0x0406)
32:52:620 Core/HW/WiimoteEmu/EmuSubroutines.cpp:187 I[Wiimote]: Attaching Motion Plus (Wiimote 0 in slot 0)
32:52:620 Core/HW/WiimoteEmu/EmuSubroutines.cpp:213 I[Wiimote]: Switching to Extension 1 (Wiimote 0 in slot 0)
32:52:620 Core/IOS/USB/Bluetooth/BTEmu.cpp:1461 I[IOS_WIIMOTE]: Command: HCI_CMD_RESET

after this, SM boots and is running code @80003400

so i think, but would love @Zarithya & @wiidev's input on this, that we fixed the disconnect bug, but that on the sdk its left in searching state because SDK doesn't actively disconnect them unless its shutting down the system, which i saw when shutting down in dolphin when in SM :

27:33:365 Core/IOS/USB/Bluetooth/BTEmu.cpp:1230 I[IOS_WIIMOTE]: Command: HCI_CMD_DISCONNECT
27:33:365 Core/IOS/USB/Bluetooth/BTEmu.cpp:757 I[IOS_WIIMOTE]: Event: Command Status (Opcode: 0x0406)
27:33:365 Core/HW/WiimoteEmu/EmuSubroutines.cpp:187 I[Wiimote]: Attaching Motion Plus (Wiimote 0 in slot 0)
27:33:365 Core/HW/WiimoteEmu/EmuSubroutines.cpp:213 I[Wiimote]: Switching to Extension 1 (Wiimote 0 in slot 0)

@Aeplet
Copy link

Aeplet commented Apr 12, 2025

Updates on this?

@DacoTaco
Copy link
Member

DacoTaco commented Apr 12, 2025

Updates on this?

zari was at a con last weekend and has been recovering this week. we haven't forgotten about this aep :)

Copy link
Member

@DacoTaco DacoTaco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move cleanups! :p

Copy link
Member

@DacoTaco DacoTaco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overal looks a lot cleaner than before :)

wiidev added a commit to wiidev/usbloadergx that referenced this pull request Jun 25, 2025
wiidev added a commit to wiidev/usbloadergx that referenced this pull request Jun 25, 2025
wiidev added a commit to wiidev/usbloadergx that referenced this pull request Jun 25, 2025
@Aeplet
Copy link

Aeplet commented Jun 26, 2025

Any updates on when this can get fully merged? What's left for that?

@WinterMute
Copy link
Member

Any updates on when this can get fully merged? What's left for that?

It would be good to put together an example app to demonstrate usage that we can also use to test that everything works as expected.

@DacoTaco
Copy link
Member

Any updates on when this can get fully merged? What's left for that?

It would be good to put together an example app to demonstrate usage that we can also use to test that everything works as expected.

we do. i added a wiimote example to test it with ( https://github.com/devkitPro/wii-examples/blob/master/devices/wiimote/source/wiimote.c ) , but the guest sync isn't added yet because this isn't merged yet

@Aeplet
Copy link

Aeplet commented Jul 31, 2025

It's just Wiimote/Console Power button separation left, right?

@DacoTaco DacoTaco changed the title Add wireless controller syncing functionality to WPAD/LWBT Wiimote: Add wireless controller syncing functionality Aug 8, 2025
@DacoTaco DacoTaco merged commit ca84f9d into devkitPro:master Aug 8, 2025
1 check passed
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.

6 participants