Open steam3d opened 3 years ago
Historically BluetoothSetServiceState was used to enable/disable device manager entries for specific services e.g. virtual serial ports. I wouldn't recommend using it to toggle a headset. I will look to see if there is an alternative API which can be used to force a connection. It feels like this should be controlled via an Audio API by selecting a different default device but I'm not sure what APIs are available for this.
I already tried Audio APIs, there is no way to change state of mmdevice.
There is a partial way to connect (but you can't disconnect device)
using Windows.Devices.Bluetooth;
async void ConnectBTUWP()
{
btdevice = await BluetoothDevice.FromIdAsync(BTId);
rfcommResult = await btdevice.GetRfcommServicesAsync();
rfcomm = rfcommResult.Services[0];
if (btdevice.ConnectionStatus != BluetoothConnectionStatus.Connected)
{
// Create a socket and connect to the target
var _socket = new StreamSocket();
await _socket.ConnectAsync(
rfcomm.ConnectionHostName,
rfcomm.ConnectionServiceName,
SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication);
}
}
The only one dirty way to connect or disconnect device is disable all services or enable all services of device.
I'm having the same problem, I want to disconnect my computer from the Bluetooth connection or program it to disable it
I'm struggling with finding a solution for this problem as well. I have created a https://github.com/PolarGoose/BluetoothDevicePairing console utility where I want to implement connection to devices the same way it is done via Window GUI. I have asked the same question on StackOverflow (How to connect to a paired audio Bluetooth device using Windows UWP API?) but haven't got any answer.
I have tried every solution I could find but none of them worked. Let me describe these solutions and why they don't work bellow.
The fact that it doesn't work you can test yourself without any code
Control Panel\Hardware and Sound\Devices and Printers
.BluetoothSetServiceState OFF
Winapi method will do if you call it for every service.BluetoothSetServiceState ON
will do), it doesn't often make Windows connect to the device properly. I observed that the Windows pairing dialog will show the status of a device "Connected" but not "Connected as voice, music" and no sound device will be present for the headphones.In Windows.Devices.Enumeration
namespace there are two methods PairAsync and UnpairAsync. If device hasn't been paired before and you call PairAsync
Windows will pair and connect to the device. But if device is paired but not connected, PairAsync
will just fail.
But if we call UnpairAsync
in this case and then after it finishes call PairAsync
, Windows will pair and connect to the device. But it doesn't work reliably. In my case it only connected to my device as a "Music" but without "Voice".
This just doesn't work. After you call _socket.ConnectAsync
, Windows shows that device is just "Connected", but not "Connected as voice, music" and when the _socket
object gets disposed the device gets disconnected immediately.
There isn't currently an API (Win32 or WinRT/UWP) to do this. As already stated BluetoothSetServiceState is not appropriate for this and should not be used. If the reason for disabling the headset is to play audio through a different endpoint you can do this by setting the AudioDevice of a MediaPlayer object. Use the DeviceInformation.FindAllAsync() method with a Windows.Media.Devices.MediaDevice.GetAudioRenderSelector() selector to enumerate all output devices, and then choose the one you want which isn't the headset. However apps can't disconnect a headset device.
@peterfoot, Thank you for your reply. I'm just curious, do you know what happens when a user clicks "Connect" button in the Windows GUI? I mean what Bluetooth communication protocol Windows uses for that? For example do they open one of the Headphone's RFComm ports and write something to make headphones connect to the PC? Or maybe you know how Linux does it?
Windows connects via either Headset, Handsfree or A2DP profiles depending on the device. This causes a separate SCO channel to be opened for the audio (the main profile being an RFComm channel for control only). Trying to open a socket on one of those profiles yourself will not allow the normal Windows support for these to work, including the separate audio channel.
Has anyone tried directly requesting information from Microsoft?
@steam3d, I haven't tried to do that. Do you know how to do that?
The current place to ask technical questions is Microsoft Q&A - https://docs.microsoft.com/en-us/answers/topics/windows-api.html
@peterfoot , Thank you for the link, I have created a topic: https://docs.microsoft.com/en-us/answers/questions/718643/connect-to-a-paired-bluetooth-device-from-c.html
I think I have found something that works, even though it is still a workaround: Headphones have PnP devices related to them. Toggling states of these devices will make Windows connect to the headphones. Look at my answer on StackOverflow for more details: https://stackoverflow.com/a/71539568/7585517
Dunno if it helps, but here is a C++ project that successfully implemented connect/disconnect with (audio only) bluetooth devices, using winrt audio api: https://github.com/m2jean/ToothTray
And my CLI version fork: https://github.com/shunf4/ToothTray
@shunf4, The link https://github.com/shunf4/ToothTray doesn't work.
I have also briefly tested the original m2jean/ToothTray. Unfortunately, it doesn't work correctly. When I disconnect my Headset it still has a status Connected in the Windows Bluetooth & Devices dialog Or it disconnects only audio but leaves the microphone connected:
The link https://github.com/shunf4/ToothTray doesn't work.
Sorry, it's https://github.com/shunf4/ToothTrayCli .
I have also briefly tested the original m2jean/ToothTray. Unfortunately, it doesn't work correctly. When I disconnect my Headset it still has a status Connected in the Windows Bluetooth & Devices dialog
Can you try if it works in Windows 10?
BTW seems like Sony's headsets really have quirks with them; IIRC I tried using one in Ubuntu Linux but failed; the headset just won't connect.
@shunf4,
BTW seems like Sony's headsets really have quirks with them
It is not related to Sony, the same problem happens with Bose 700 and Jabra Evolve 75e, their status is left Connected or Connected mic when I try to disconnect them using ToothTray
Unfortunately, I don't have Windows 10 to test if ToothTray works there.
@shunf4, The link https://github.com/shunf4/ToothTray doesn't work.
I have also briefly tested the original m2jean/ToothTray. Unfortunately, it doesn't work correctly. When I disconnect my Headset it still has a status Connected in the Windows Bluetooth & Devices dialog Or it disconnects only audio but leaves the microphone connected:
https://github.com/m2jean/ToothTray is the correct way to connect and disconnect bluetooth audio device. But in win11, this way can only enumerate headset service, lost headsfree service, so connect or disconnect doest not work properly. Just change IMMDeviceEnumerator::EnumAudioEndpoints parameter EDataFlow from eCapture to eAll, this problem will be fixed.
@shunf4, The link https://github.com/shunf4/ToothTray doesn't work.
I have also briefly tested the original m2jean/ToothTray. Unfortunately, it doesn't work correctly. When I disconnect my Headset it still has a status Connected in the Windows Bluetooth & Devices dialog Or it disconnects only audio but leaves the microphone connected:
I have submitted a bug for this issue: https://github.com/m2jean/ToothTray/issues/10
Can i connect / disconnect programmatically headphones? I found the way to connect using https://docs.microsoft.com/en-us/windows/win32/api/bluetoothapis/nf-bluetoothapis-bluetoothsetservicestate, but it takes a lot of time and device can't be disconnected even if i disable all services.