Permalink
Browse files

squash into bluetooth on windows

  • Loading branch information...
1 parent 16c4e74 commit 9d6c1e4fc0928840130ae4dc1b06663dabfedb41 @elupus committed May 18, 2012
Showing with 162 additions and 50 deletions.
  1. +162 −50 xbmc/bluetooth/win32/Win32BluetoothSyscall.cpp
@@ -34,7 +34,9 @@
#include "threads/Thread.h"
#include <string>
+#include <InitGuid.h>
#include "Win32BluetoothSyscall.h"
+#include "bluetooth/BluetoothManager.h"
#include <BluetoothAPIs.h>
#pragma comment(lib, "Bthprops.lib")
@@ -46,6 +48,16 @@
#define BLUETOOTH_AUTHENTICATE_EX 0
#endif
+static CStdString GUIDToString(const GUID& guid)
+{
+ CStdString buffer;
+ buffer.Format("%08X-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"
+ , guid.Data1, guid.Data2, guid.Data3
+ , guid.Data4[0], guid.Data4[1]
+ , guid.Data4[2], guid.Data4[3], guid.Data4[4]
+ , guid.Data4[5], guid.Data4[6], guid.Data4[7]);
+ return buffer;
+}
/**************** CWin32BluetoothDevice ***************/
@@ -80,29 +92,34 @@ static BOOL CALLBACK AuthCallbackEx(LPVOID pvParam, PBLUETOOTH_AUTHENTICATION_CA
resp.authMethod = params->authenticationMethod;
resp.bthAddressRemote = params->deviceInfo.Address;
+ IBluetoothDevicePtr device(new CWin32BluetoothDevice(params->deviceInfo));
+
+ bool res = FALSE;
+
switch(params->authenticationMethod) {
case BLUETOOTH_AUTHENTICATION_METHOD_PASSKEY_NOTIFICATION: {
key.Format("%lu", params->Passkey);
- if(!CGUIDialogYesNo::ShowAndGetInput(g_localizeStrings.Get(16500), g_localizeStrings.Get(16507), key, ""))
- return FALSE;
+ res = CBluetoothManager::OnDevicePairRequest(device, key, CBluetoothManager::EPAIRING_PASSKEY_DISPLAY);
+ break;
+ }
+ case BLUETOOTH_AUTHENTICATION_METHOD_PASSKEY: {
+ res = CBluetoothManager::OnDevicePairRequest(device, key, CBluetoothManager::EPAIRING_PASSKEY_REQUEST);
break;
}
- case BLUETOOTH_AUTHENTICATION_METHOD_PASSKEY:
case BLUETOOTH_AUTHENTICATION_METHOD_LEGACY: {
- if(!CGUIDialogKeyboard::ShowAndGetInput(key, g_localizeStrings.Get(16506), true, true))
- return FALSE;
+ res = CBluetoothManager::OnDevicePairRequest(device, key, CBluetoothManager::EPAIRING_LEGACY);
break;
}
case BLUETOOTH_AUTHENTICATION_METHOD_NUMERIC_COMPARISON: {
key.Format("%lu", params->Numeric_Value);
- if(!CGUIDialogYesNo::ShowAndGetInput(g_localizeStrings.Get(16500), g_localizeStrings.Get(16505), key, ""))
- return FALSE;
- break;
+ res = CBluetoothManager::OnDevicePairRequest(device, key, CBluetoothManager::EPAIRING_NUMERIC_COMPARE);
}
default:
CLog::Log(LOGWARNING, "CWin32BluetoothSyscall - unsupported authentication method requested %d", params->authenticationMethod);
return FALSE;
}
+ if(!res)
+ return FALSE;
switch(resp.authMethod) {
@@ -128,40 +145,26 @@ static BOOL CALLBACK AuthCallbackEx(LPVOID pvParam, PBLUETOOTH_AUTHENTICATION_CA
}
DWORD result = BluetoothSendAuthenticationResponseEx(NULL, &resp);
- if(result == ERROR_SUCCESS)
- {
- CGUIDialogKaiToast::QueueNotification(g_localizeStrings.Get(16500), "Paired with device");
- return TRUE;
- }
- else
- {
- CGUIDialogKaiToast::QueueNotification(g_localizeStrings.Get(16500), "Pairing failed with device");
+ if(result != ERROR_SUCCESS)
CLog::Log(LOGWARNING, "CWin32BluetoothSyscall - failed to authenticate device with error 0x%x", result);
- return FALSE;
- }
+ CBluetoothManager::OnDevicePairResult(device, result == ERROR_SUCCESS);
+ return TRUE;
}
#else
static BOOL CALLBACK AuthCallback(LPVOID pvParam, PBLUETOOTH_DEVICE_INFO params)
{
CStdString key;
- if(!CGUIDialogKeyboard::ShowAndGetInput(key, g_localizeStrings.Get(16506), true, true))
+ if(!CBluetoothManager::OnDevicePairRequest(device, key, CBluetoothManager::EPAIRING_LEGACY))
return FALSE;
CStdStringW keyW;
g_charsetConverter.utf8ToW(key, keyW);
DWORD result = BluetoothSendAuthenticationResponse(NULL, params, keyW.c_str());
- if(result == ERROR_SUCCESS)
- {
- CGUIDialogKaiToast::QueueNotification(g_localizeStrings.Get(16500), "Paired with device");
- return TRUE;
- }
- else
- {
- CGUIDialogKaiToast::QueueNotification(g_localizeStrings.Get(16500), "Pairing failed with device");
+ if(result != ERROR_SUCCESS)
CLog::Log(LOGWARNING, "CWin32BluetoothSyscall - failed to authenticate device with error 0x%x", result);
- return FALSE;
- }
+ CBluetoothManager::OnDevicePairResult(device, result == ERROR_SUCCESS);
+ return TRUE;
}
#endif
@@ -212,44 +215,76 @@ std::vector<BLUETOOTH_DEVICE_INFO_STRUCT> GetDeviceList(const BLUETOOTH_DEVICE_S
class DiscoveryDeviceThread : public CThread
{
public:
- DiscoveryDeviceThread()
+ DiscoveryDeviceThread(bool discovery)
: CThread("Bluetooth Discovery")
+ , m_inquiry(true)
{}
+ bool Get(std::vector<BLUETOOTH_DEVICE_INFO_STRUCT>& devices)
+ {
+ CSingleLock lock(m_section);
+ m_updated = false;
+ devices = m_devices;
+ return true;
+ }
+private:
+
virtual void Process()
{
+ int multiplier = 0;
+
while(!m_bStop)
{
BLUETOOTH_DEVICE_SEARCH_PARAMS params = {0};
params.dwSize = sizeof(params);
params.fReturnAuthenticated = TRUE;
- params.fReturnConnected = TRUE;
- params.fReturnRemembered = TRUE;
- params.fReturnUnknown = TRUE;
- params.fIssueInquiry = TRUE;
- params.cTimeoutMultiplier = 1;
+ params.fReturnConnected = TRUE;
+ params.fReturnRemembered = TRUE;
+ params.fReturnUnknown = TRUE;
+ if(m_inquiry)
+ {
+ params.fIssueInquiry = TRUE;
+ params.cTimeoutMultiplier = multiplier;
+ if(multiplier < 5)
+ multiplier++;
+ }
+ else
+ {
+ params.fIssueInquiry = FALSE;
+ params.cTimeoutMultiplier = 0;
+ }
params.hRadio = NULL;
std::vector<BLUETOOTH_DEVICE_INFO_STRUCT> devices = GetDeviceList(params);
- CSingleLock lock(m_section);
- m_devices = devices;
- Sleep(500);
+ { CSingleLock lock(m_section);
+ m_devices = devices;
+ m_updated = true;
+ }
+ Sleep(100);
}
}
+ bool m_inquiry;
+ bool m_updated;
CCriticalSection m_section;
std::vector<BLUETOOTH_DEVICE_INFO_STRUCT> m_devices;
};
-DiscoveryDeviceThread* g_discovery;
+static DiscoveryDeviceThread* g_discovery;
+static DiscoveryDeviceThread* g_inquiry;
void CWin32BluetoothSyscall::StartDiscovery()
{
if(g_discovery == NULL)
{
- g_discovery = new DiscoveryDeviceThread();
+ g_discovery = new DiscoveryDeviceThread(false);
g_discovery->Create();
}
+ if(g_inquiry == NULL)
+ {
+ g_inquiry = new DiscoveryDeviceThread(true);
+ g_inquiry->Create();
+ }
}
void CWin32BluetoothSyscall::StopDiscovery()
@@ -260,6 +295,12 @@ void CWin32BluetoothSyscall::StopDiscovery()
delete g_discovery;
g_discovery = NULL;
}
+ if(g_inquiry)
+ {
+ g_inquiry->StopThread(true);
+ delete g_inquiry;
+ g_inquiry = NULL;
+ }
}
class AuthenticateDeviceThread : public CThread
@@ -305,23 +346,94 @@ void CWin32BluetoothSyscall::RemoveDevice(const char *id)
}
}
+static DWORD SetServiceState(const BLUETOOTH_DEVICE_INFO_STRUCT& info, std::vector<GUID>& guids, DWORD flag)
+{
+ DWORD res;
+ for(std::vector<GUID>::iterator it = guids.begin(); it != guids.end(); ++it)
+ {
+ res = BluetoothSetServiceState(NULL, &info, &*it, BLUETOOTH_SERVICE_ENABLE);
+ if(res == ERROR_SERVICE_DOES_NOT_EXIST)
+ {
+ CLog::Log(LOGERROR, "CWin32BluetoothSyscall::Connect - service %s doesn't exist", GUIDToString(*it).c_str());
+ continue;
+ }
+
+ if(res == ERROR_SUCCESS)
+ CLog::Log(LOGERROR, "CWin32BluetoothSyscall::Connect - connected to service %s", GUIDToString(*it).c_str());
+ else
+ CLog::Log(LOGERROR, "CWin32BluetoothSyscall::Connect - faild to connect to service %s", GUIDToString(*it).c_str());
+
+ break;
+ }
+ return res;
+}
+
+static DWORD SetServiceState(const BLUETOOTH_DEVICE_INFO_STRUCT& info, GUID guid, DWORD flag)
+{
+ std::vector<GUID> guids;
+ guids.push_back(guid);
+ return SetServiceState(info, guids, flag);
+}
+
void CWin32BluetoothSyscall::ConnectDevice(const char *id)
{
+ boost::shared_ptr<CWin32BluetoothDevice> device = boost::dynamic_pointer_cast<CWin32BluetoothDevice>(GetDevice(id));
+ if(!device)
+ return;
+
+ if(device->GetDeviceType() == IBluetoothDevice::DEVICE_TYPE_HEADPHONES
+ || device->GetDeviceType() == IBluetoothDevice::DEVICE_TYPE_HEADSET)
+ {
+ std::vector<GUID> guids;
+ guids.push_back(AudioSinkServiceClass_UUID);
+ guids.push_back(AdvancedAudioDistributionServiceClass_UUID);
+ guids.push_back(HandsfreeAudioGatewayServiceClass_UUID);
+ guids.push_back(HeadsetAudioGatewayServiceClass_UUID);
+ guids.push_back(AVRemoteControlServiceClass_UUID);
+ SetServiceState(device->GetInfo(), guids, BLUETOOTH_SERVICE_ENABLE);
+ }
+ else if(device->GetDeviceType() == IBluetoothDevice::DEVICE_TYPE_KEYBOARD
+ || device->GetDeviceType() == IBluetoothDevice::DEVICE_TYPE_MOUSE)
+ {
+ SetServiceState(device->GetInfo(), HumanInterfaceDeviceServiceClass_UUID, BLUETOOTH_SERVICE_ENABLE);
+ }
+ else
+ {
+ CLog::Log(LOGERROR, "CWin32BluetoothSyscall::Connect - unkown service for device class %d", device->GetDeviceType());
+ }
}
void CWin32BluetoothSyscall::DisconnectDevice(const char *id)
{
+ boost::shared_ptr<CWin32BluetoothDevice> device = boost::dynamic_pointer_cast<CWin32BluetoothDevice>(GetDevice(id));
+ if(!device)
+ return;
+
+ GUID services[32];
+ DWORD services_count = sizeof(services) / sizeof(services[0]);
+
+ DWORD res = BluetoothEnumerateInstalledServices(NULL, &device->GetInfo(), &services_count, services);
+ if(res != ERROR_SUCCESS)
+ {
+ CLog::Log(LOGERROR, "CWin32BluetoothSyscall::Disconnect - unable to get service list for device, error: 0x%x", res);
+ return;
+ }
+
+ for(unsigned i = 0; i < services_count; ++i)
+ {
+ res = BluetoothSetServiceState(NULL, &device->GetInfo(), &services[i], BLUETOOTH_SERVICE_DISABLE);
+ if(res == ERROR_SUCCESS)
+ CLog::Log(LOGDEBUG, "CWin32BluetoothSyscall::DisconnectDevice - disconnected service %s" , GUIDToString(services[i]).c_str());
+ else
+ CLog::Log(LOGERROR, "CWin32BluetoothSyscall::DisconnectDevice - faild to disconnect service %s", GUIDToString(services[i]).c_str());
+ }
}
bool CWin32BluetoothSyscall::PumpBluetoothEvents(IBluetoothEventsCallback *callback)
{
- if(g_discovery)
+ std::vector<BLUETOOTH_DEVICE_INFO_STRUCT> devices;
+ if(g_discovery && g_discovery->Get(devices))
{
- std::vector<BLUETOOTH_DEVICE_INFO_STRUCT> devices;
- { CSingleLock lock(g_discovery->m_section);
- devices = g_discovery->m_devices;
- }
-
DeviceMap remain(m_devices);
for(std::vector<BLUETOOTH_DEVICE_INFO_STRUCT>::iterator it = devices.begin(); it != devices.end(); ++it)
@@ -337,15 +449,15 @@ bool CWin32BluetoothSyscall::PumpBluetoothEvents(IBluetoothEventsCallback *callb
else
{
if(!cur->second->IsConnected() && p->IsConnected())
- callback->OnDeviceConnected(cur->second.get());
+ callback->OnDeviceConnected(p.get());
if( cur->second->IsConnected() && !p->IsConnected())
- callback->OnDeviceDisconnected(cur->second.get());
+ callback->OnDeviceDisconnected(p.get());
if(!cur->second->IsCreated() && p->IsCreated())
- callback->OnDeviceCreated(cur->second.get());
+ callback->OnDeviceCreated(p.get());
if( cur->second->IsPaired() != p->IsPaired())
- callback->OnDeviceCreated(cur->second.get());
+ callback->OnDeviceCreated(p.get());
remain.erase(cur);
}
}

0 comments on commit 9d6c1e4

Please sign in to comment.