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

Add ability to passthrough a Bluetooth adapter #4195

Merged
merged 8 commits into from Oct 3, 2016

Conversation

leoetlino
Copy link
Member

@leoetlino leoetlino commented Sep 7, 2016

This adds the ability to passthrough a whole Bluetooth adapter and skip the majority of the Bluetooth emulation code. We use libusb to send HCI commands, receive HCI events and transfer ACL data directly to the first adapter that is found, or to a specific adapter (if configured to).

This is possible because the Wii's Bluetooth module is actually just a pretty standard Bluetooth adapter…

…except for two vendor-specific commands and one other HCI command (for which replies are faked), and also for the sync button. On the Wii, the sync button triggers an HCI event, which emulated software interpret as a command to perform a BT inquiry. We definitely need to emulate that, so this PR also adds a hotkey and a button to trigger the "sync button" event.

What works in this passthrough mode:

  • Pairing and reconnecting Wiimotes on button press
  • Letting the emulated software really disconnect Wiimotes
  • Reconnecting Wiimotes after e.g. an ES_Launch (depending on the adapter)
  • Wiimote audio with all Wiimotes, -TR or non -TR
  • Third-party Wiimote support just like on the Wii, even on Windows
  • Generally improved Wiimote input, especially with a Motion+

Limitations:

  • It is difficult to connect more than 3 Wiimotes at the same time. A Wii Bluetooth module works perfectly, so this really depends on the quality of the adapter.
  • Loading a state save breaks it completely, even if the state load is reverted. Not much I can do, since we're doing hardware passthrough.

This change is Reviewable

@mbc07
Copy link
Contributor

mbc07 commented Sep 7, 2016

I assume this is Linux only at the moment? Or would it work with Windows too if the user manually installs libusb for its bluetooth adapter (e.g. with Zadig, as used with Rock Band accessories or Skylanders Portal of Power)?

Anyway this PR is awesome!

@leoetlino
Copy link
Member Author

Currently, the only thing holding this from working on Windows as well is that the Windows builds do not use cmake, and so you can't use the compile-time option to enable the passthrough mode. I'm trying to make it a runtime option.

@jloehr
Copy link
Contributor

jloehr commented Sep 7, 2016

Nice PR! Finally a way to get Wiimote Audio working :D As assumed it indeed seems to be an issue with the driver stacks (or their delayed timings).

@leoetlino
Copy link
Member Author

@jloehr I think you're correct. It would be interesting to see if that also fixes the connection issues and random disconnects that were reported in the forum (and that we both reproduced too).

@leoetlino leoetlino force-pushed the direct-hci branch 6 times, most recently from 4cada3c to 2f449b5 Compare September 7, 2016 21:49
@leoetlino
Copy link
Member Author

This should now work on Windows as well (as passthrough mode is now a runtime option). However, the setting is currently not exposed in the UI, so it has to be manually enabled in Dolphin.ini:

[BluetoothPassthrough]
Mode = 0
# 0 for Enabled, 1 for Disabled

You will also need to use Zadig to let Dolphin use the raw USB device.

@mbc07
Copy link
Contributor

mbc07 commented Sep 7, 2016

I'm having trouble getting it to work on Windows. I enabled passthrough in Dolphin.ini but always get "Bluetooth passthrough mode enabled, but no usable Bluetooth USB device was found." when starting. My BT adapter is an Atheros AR3012, tried with WinUSB and libusb-win32 drivers but nothing changed. Tried also to manually add the VID and PID in the INI and nothing. Am I missing something?

@JMC47
Copy link
Contributor

JMC47 commented Sep 7, 2016

I got it working in the latest version of it. You may want to redownload it if you haven't.

@mbc07
Copy link
Contributor

mbc07 commented Sep 7, 2016

Okay, Dolphin is now seeing my BT adapter with WinUSB driver, but can't open it. On the log I get
18:25:130 IPC_HLE\WII_IPC_HLE_Device_usb_real.cpp:248 E[WII_IPC_WIIMOTE]: Failed to open Bluetooth device: LIBUSB_ERROR_ACCESS

Any clue?

@mbc07
Copy link
Contributor

mbc07 commented Sep 7, 2016

Nevermind, SCP DS3 Service also communicates with BT Adapter through WinUSB. Stopping the service before running this PR resolved that and the game boots successfully. However, when I trigger a sync with the Hotkey, I get some "ScheduleEvent from wrong thread (non-cpu)" and the Wiimote remains unsynced...

@JMC47
Copy link
Contributor

JMC47 commented Sep 7, 2016

Try single core, I've been having no issues with this.

@mbc07
Copy link
Contributor

mbc07 commented Sep 8, 2016

Okay, managed to test this. It's a little bit unstable, at least with my BT Adapter (which is an Atheros AR3012, Bluetooth 4.0 + LE).

  • Firstly, it won't remember paired controllers, I managed to connect only by using the sync hotkey in Dolphin and the Red Sync at back of my Wiimote (which is a genuine, non-TR Wii Remote Plus); However, after syncing once it always reconnected with a button press, but only until I stopped the emulation. On next run I would need to sync with the hotkey and red button once before being able to reconnect with a single button press.
  • The "ScheduleEvent from wrong thread (non-cpu)" kept popping even in Single Core mode (disabling Panic Handlers though let the controller successfully sync, probably because it wouldn't block the emulation in that case)
  • It didn't connect to any controller if you booted a game, stopped emulation then started another game (without closing and reopening Dolphin). After some boots, the BT Adapter seems to stop completely (no sync, no connection, nothing) until you either rolled the driver back to the default MS BT Stack then installing WinUSB driver again. Not even a computer reboot would fix that other than switching drivers (maybe it's something isolated to this particular BT Adapter I have). I also noticed that when I got into this state, all games would eventually throw the following in the log:
    13:07:661 HW\EXI_DeviceIPL.cpp:344 N[OSREPORT]: BTU HCI command timeout - cmd opcode = 0xc1a 13:07:661 HW\EXI_DeviceIPL.cpp:344 N[OSREPORT]: ---- WARNING: USB FATAL ERROR! ----
  • Wiimote Speaker works flawlessly, and sounds good even if the emulation slows down (but it starts clipping). It stops working completely if you set frame limiter to anything higher than 130%, though.
  • On SSBB I could successfully save custom control schemes into Wiimote's EEPROM through "Transfer Names" feature. (on master it would disconnect the controllers and Dolphin would complain)

@mbc07
Copy link
Contributor

mbc07 commented Sep 8, 2016

Did some stress testing with somewhat motion "intense" games:

  • On any Just Dance game (especially on Just Dance 1): it's way easier to score points now, probably due to lower latency since the emulated software controls the BT Adapter directly;
  • On any Motion Plus game (tested on Zelda SS and Wii Play: Motion): the Motion Plus rarely to never requires being recalibrated. In fact, after some intense Sword Play in Zelda SS the pointer was still accurately tracked and I didn't need to recalibrate the controller, not even once!

TL;DR the Wiimote response seems identical (and sometimes even better) than a real Wii! This PR is GOLDEN!

@leoetlino
Copy link
Member Author

Yes, the pairing is currently a bit broken: it doesn't work (or it does, sometimes) the first time after starting a game, but always works after you pair it again, until the emulation is stopped or even an ES_Launch. It's weird, as it was definitely working at some point. But at least it breaks deterministically ;)

"ScheduleEvent from wrong thread (non-cpu)"

I will remove the thread checks. It looks like the reply events sometimes get scheduled from the wrong thread (no idea how), but this isn't an issue at all.

After some boots, the BT Adapter seems to stop completely (no sync, no connection, nothing)

That will probably be fixed by resetting the Bluetooth adapter completely (at the USB level, not a HCI reset).

I also noticed that when I got into this state, all games would eventually throw the following in the log

Some games seem to be more strict and show warnings. Since it doesn't happen for all games I'm not sure if this is an issue with the implementation. I will try to get rid of the warnings; maybe that could fix something else.

@leoetlino
Copy link
Member Author

@mbc07 It turns out the pairing issue is actually caused by the Bluetooth dongle I was using. With another dongle, pairing works perfectly fine, so you may want to try using another dongle. (Same for the stop/start issue)

@mbc07
Copy link
Contributor

mbc07 commented Sep 8, 2016

I have an old BT 2.0 + EDR USB dongle laying around somewhere, will test the PR on it later (well, if I find it 😛 )

@JMC47
Copy link
Contributor

JMC47 commented Sep 9, 2016

Balance Board works without disconnects! Nice. Wii Bowling works perfectly with one Wiimote. When I add more the lag seems to interfere.

@MayImilae
Copy link
Contributor

Just to report what happened on IRC, we tried and tried, but Mac OS 10.11 did not allow Dolphin to take over a bluetooth adapter. :(

@Helios747
Copy link
Contributor

Reviewed 2 of 19 files at r1, 5 of 29 files at r2.
Review status: 7 of 28 files reviewed at latest revision, 2 unresolved discussions.


Source/Core/DolphinWX/ControllerConfigDiag.cpp, line 262 [r4] (raw file):

        0, wxALIGN_CENTER | wxALL, 5);

  auto* const enable_passthrough = new wxCheckBox(this, wxID_ANY, _("Enable Passthrough Mode"));

I think "Enable Bluetooth Adapter Passthrough" would work better here. The user needs to know that they're passing through their adapter.


Source/Core/DolphinWX/Frame.cpp, line 51 [r1] (raw file):

#if PASSTHROUGH_BLUETOOTH
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_57e_305.h"
#endif

Do we usually do conditional includes like this? Somebody smarter than me should confirm or deny this.


Comments from Reviewable

@Helios747
Copy link
Contributor

Helios747 commented Sep 10, 2016

Ignore my comment about the headers.

Anyways, regarding UX stuff.

Controller diag

  • ControllerDiag looks good visually, but there's a couple issues I see. When looking at the real wiimotes section the first thing you see is Dolphin telling you "A supported BT device cannot be found". Dolphin isn't lying! But this is confusing for the user. I recommend if the "enable passthrough mode" is checked, change that UI label to either be blank or say something like "BT Adapter will be passed through to the game"
  • The checkbox title itself, but that comment is already in reviewable for you.
  • I think it may be a good idea when passthrough mode is checked to disable the other related controls in that section. The user doesn't need them and may end up mucking something up if they fiddle with it and hit some corner case we didn't think of.

General stuff:

I like that you give a UI warning to the user that Dolphin could not detect a passable adapter to connect through, but it looks like the dialog you chose has yes/no buttons. Just make that a single "Ok" Okay that's not possible.

Lastly, we'll need documentation on how to set this up from start to finish, as well as documenting what won't work anymore with this before this is merged. But that's probably pretty obvious.

@mbc07
Copy link
Contributor

mbc07 commented Sep 10, 2016

I like that you give a UI warning to the user that Dolphin could not detect a passable adapter to connect through, but it looks like the dialog you chose has yes/no buttons. Just make that a single "Ok"

At least the last time I tried, that's a Assert Message, that's why it have yes/no. Also, Dolphin will crash anyways if you get that message (if you click No it'll crash immediately and if you click Yes it'll crash some seconds later)...

This stores the address of paired devices and associated link keys.
It is needed because some adapters forget all stored link keys when
they are reset, which breaks pairings because the Wii relies on the
Bluetooth module to remember them.

It doesn't fix adapters that can't remember any link key
at all and always return 0 for the number of stored/written link keys.
For those adapters, there is no fix.

This also improves the usability of passthrough mode for adapters that
already work, since pairings will now keep working even if the link
keys get cleared by something else (for example by the host Bluetooth
stack).
Homebrew programs seem to rely on getting a reply to the vendor
specific commands, without which Bluetooth initialisation will never
complete.

This vendor-specific command is typically used to patch the Wii's
Bluetooth module, so the replies are only faked when the passed through
adapter is not a Wii Bluetooth module.
This fixes an issue where the Bluetooth info section could be fully
filled up by syncing 5 Wiimotes in passthrough mode then switching to
emulated Bluetooth; emulated Wiimotes were then unable to be used.

The "real" SYSCONF section is now backed up before being replaced with
a blank section that the emulated BT adapter can always fill with 5
Wiimotes without issues.

This backup is restored by the passthrough code, instead of during
the Bluetooth mode switch because this should be done regardless of the
user interface, and even without UI (if the config file is edited
manually).
It doesn't make much sense to prefix g_ to static variables and for
some to be completely unprefixed.

Also renames a lot of other variables for the new conventions
@leoetlino
Copy link
Member Author

Review status: 16 of 37 files reviewed at latest revision, 18 unresolved discussions.


Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp, line 198 at r16 (raw file):

Previously, shuffle2 wrote…

Oh sorry, I meant it would have been better to add some brackets to make the scope obvious (and perhaps end the lock scope before the end of the function - whenever it is not actually needed anymore). Moving it to the top makes it a bit harder to reason about what is actually going on while the lock is held.

Done.

Source/Core/DolphinWX/DolphinWX.vcxproj, line 100 at r17 (raw file):

Previously, shuffle2 wrote…

Could you please also remove these if not needed.

Done.

Source/Core/DolphinWX/DolphinWX.vcxproj, line 121 at r17 (raw file):

Previously, shuffle2 wrote…

Could you please also remove these if not needed. (ditto)

Done.

Comments from Reviewable

@shuffle2 shuffle2 merged commit 6ec7569 into dolphin-emu:master Oct 3, 2016
@leoetlino leoetlino deleted the direct-hci branch October 3, 2016 21:28
@leoetlino
Copy link
Member Author

In case someone needs instructions for Linux:

  1. A udev rule has to be installed to avoid having to run Dolphin with root privileges.

    SUBSYSTEM=="usb", ATTRS{idVendor}=="YOURVID", ATTRS{idProduct}=="YOURPID", TAG+="uaccess"
    
  2. The USB Bluetooth kernel module should be unloaded, or Dolphin will not be able to use the adapter. Note: you could also unbind the correct adapter from the btusb module, but for simplicity, unloading the whole module works too. (This step can be automated by tweaking the udev rule)

    modprobe -r btusb
    # and to reload the kernel module (if needed):
    modprobe btusb
    

@lazarus28
Copy link

lazarus28 commented Oct 4, 2016

Thanks for this. I've been holding off on a SS playthrough until this was ready to be merged. Using DolphinBar, I'm unable to launch. I get the 'Passthrough enabled, but no usable USB device" message. In Zadig, I see 7 devices corresponding to DolphinBar. There are 3 USB receivers at interface 0-2 and there are 4 Mayflash Wiimote PC adapters at 0-3. Which of these should I be asking Zadig to alter, and is there a preferred choice between the stock USB stacks?

@mbc07
Copy link
Contributor

mbc07 commented Oct 4, 2016

BT Passthrough won't work with the Dolphin Bar, only with real BT Adapters...

@MayImilae
Copy link
Contributor

@lazarus28 The very reason the DolphinBar is good is why it won't work with this: it does not expose the core bluetooth data, only sending HID commands. Connecting and everything are completely detached from the operating system.

@lazarus28
Copy link

That's rad and thanks for the edification. Am I correct in the assumption, then, that using the DolphinBar natively is equal in performance to using a different BT adapter in passthrough mode?

@MayImilae
Copy link
Contributor

For connectivity and things yes, but for things like wiimote speaker audio passthrough is the only way to get decent quality.

@lazarus28
Copy link

And, if I gleaned properly from reading the thread, isn't the wiimote speaker audio better in later revisions of the Wiimote? Do the newer Wiimotes still have issues with audio when not using passthrough mode?

@MayImilae
Copy link
Contributor

That is not really true with passthrough.

But this is not the proper venue for this. Bring up any questions you have on the forum or IRC. And we'll have lots and lots of details in the progress report.

@JMC47
Copy link
Contributor

JMC47 commented Oct 4, 2016

Passthrough is superior to dolphin bar in terms of skyward sword. Far
better motion defection and wiimote audio fidelity

On Tue, Oct 4, 2016, 12:52 AM MaJoR notifications@github.com wrote:

That is not really true with passthrough.

But this is not the proper venue for this. Bring up any questions you have
on the forum or IRC. And we'll have lots and lots of details in the
progress report.


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
#4195 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AGSuQSKt-PoQiPoMX64Uz6M_i5bzyrK7ks5qwdt7gaJpZM4J3Il2
.

@mimimi085181
Copy link
Contributor

Maybe it should be said here that not all bluetooth adapters work fine with this. Expect a list with test results and recommendations in the next progress report.

@psennermann
Copy link

Could you please in advance tell us at least a/some Bluetooth dongles that work? Because I have 2 dongles and none of them work with this code (with both comes out the error message "no usable Bluetooth USB Device was found")
Thanks

@JMC47
Copy link
Contributor

JMC47 commented Oct 7, 2016

Are you sure you're setting it up right? Most bluetooth adapters work for me. What devices are you trying to use?

@psennermann
Copy link

One is a "Bluetooth 2.1 Ultra Small USB adapter" from Trust (recognised in Windows as "Broadcom 2046 Bluetooth 2.1+EDR USB device with first connect")
http://www.trust.com/en/product/16008-ultra-small-bluetooth-2-1-usb-adapter

the other one is a "bBlue USB Bluetooth Receiver V2.0" from Eminent (recognised in Windows as "Generic Bluetooth Adapter")
http://icecat.us/us/p/eminent/em1081/networking-cards-bBLUE+USB+Bluetooth+Receiver+Class+2+-+10+m-1652226.html

@psennermann
Copy link

I finally got the Trust on to work (didn't know you had to overwrite the Driver of the dongle)...anyway for now I'm not too much impressed: with Cursed Mountain the Wiimote speaker (on my Wiimote plus TR model) works much better Emulating the Wii bluetooth adapter where I get perfect speech, while with Passthrough I get half speech because most of it is cut out; also starting and closing a game with Passthrough enabled is very slow (when it doesn't even get stuck at it).
For wiimote accuracy I tested Wii Sports Resort, but at the moment I can't really tell if there's some differences (well that's a bit more difficult than only listening to some sound)...isn't it possible that original Windows 10 bluetooth driver is so good that doesn't need this particular workaround (Passthrough) to work even better?

@leoetlino
Copy link
Member Author

That's curious, looks like there are really differences between adapters.

The main difference with Wii Sports Resort and other M+ games is that they never fail to detect the MotionPlus correctly, and motions are less likely to desync (which is most noticeable in Skyward Sword).

Btw, passthrough is not really meant to be a workaround, but a completely different mode for people who want Bluetooth to work just like on a Wii (given a decent adapter or the Wii's Bluetooth module if you want perfect Bluetooth).

@psennermann
Copy link

Well I've tested Sword Play and Tennis Table in Wii SPorts Resort and I'm not able to tell any differences (anyway I'll try SS later)...but I can confirm that Wiimote speaker with my adapter set on Passthrough is really broken (tested with the game "Calling": the Wiimote speaker voice is cutted/skipped like in Cursed Mountain); also when I exit a game very often Dolphin get stuck and I have to force close it using Windows Task manager.

@JMC47
Copy link
Contributor

JMC47 commented Oct 7, 2016

A lot of time broken audio means shitty adapter.

@psennermann
Copy link

Do you know wich is the bluetooth adapter that at the moment would work best with Passthrough?

@JMC47
Copy link
Contributor

JMC47 commented Oct 7, 2016

Buy a Wii Bluetooth adapter for ~5 dollars, solder it to a USB cable (like, a couple bucks max?) assuming you have very basic soldering skills and you need a 2 dollar regulator if you want to use USB power.

Beyond that, I find the Azio ones I have work ok. Audio still isn't great with multiple Wiimotes in those cases. The very best will always be the Wii bluetooth adapter unless something really great happens.

@psennermann
Copy link

Well I'm not very good at playing McGyver ;-) and I think Azio products are only sold in USA, but I found this Kensington one that seems to be one of the best available around here https://www.kensington.com/us/us/6756/k33956am/bluetooth-40-usb-adapter#.V_fxQ-iLSUk
Do you think it should be ok?

@mirh
Copy link

mirh commented Oct 25, 2016

@jloehr Wouldn't your HID driver allow to simply not need all of this?
And.. I mean, still retain usability of the bt adapter with other devices.

@dolphin-emu dolphin-emu locked and limited conversation to collaborators Oct 25, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet