BlueTooth.cpp
上传用户:shmeyee
上传日期:2015-06-28
资源大小:108k
文件大小:13k
源码类别:

通讯编程

开发平台:

Visual C++

  1. #include "StdAfx.h"
  2. #include "BlueTooth.h"
  3. CBlueTooth::CBlueTooth(void)
  4. {
  5. m_Ary_RemoteBthDevInfo.SetSize ( 0, 10*sizeof(BLUETOOTH_DEVICE_INFO) );
  6. m_Ary_LocalRadioInfo.SetSize ( 0, 10*sizeof(t_LocalRadioInfo) );
  7. }
  8. CBlueTooth::~CBlueTooth(void)
  9. {
  10. RemoveAll_RemoteBthDevInfo ();
  11. RemoveAllLocalRadio ();
  12. }
  13. //
  14. // 用 Socket 函数搜索附近的蓝牙设备,成功时返回设备数,否则返回-1
  15. //
  16. int CBlueTooth::WSAScanNearbyBthDev ()
  17. {
  18. m_Ary_RemoteBthDevInfo.RemoveAll ();
  19. WSAQUERYSET wsaq;
  20. HANDLE hLookup;
  21. union
  22. {
  23. CHAR buf[5000];
  24. double __unused; // ensure proper alignment
  25. };
  26. LPWSAQUERYSET pwsaResults = (LPWSAQUERYSET) buf;
  27. DWORD dwSize = sizeof(buf);
  28. BOOL bHaveName;
  29. ZeroMemory(&wsaq, sizeof(wsaq));
  30. wsaq.dwSize = sizeof(wsaq);
  31. wsaq.dwNameSpace = NS_BTH;
  32. wsaq.lpcsaBuffer = NULL;
  33. if (ERROR_SUCCESS != WSALookupServiceBegin (&wsaq, LUP_CONTAINERS, &hLookup))
  34. {
  35. TRACE ( _T("WSALookupServiceBegin failedn") );
  36. return -1;
  37. }
  38. ZeroMemory(pwsaResults, sizeof(WSAQUERYSET));
  39. pwsaResults->dwSize = sizeof(WSAQUERYSET);
  40. pwsaResults->dwNameSpace = NS_BTH;
  41. pwsaResults->lpBlob = NULL;
  42. while (ERROR_SUCCESS == WSALookupServiceNext (hLookup, LUP_RETURN_NAME | LUP_RETURN_ADDR, &dwSize, pwsaResults))
  43. {
  44. ASSERT (pwsaResults->dwNumberOfCsAddrs == 1);
  45. BTH_ADDR b = ((SOCKADDR_BTH *)pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr)->btAddr;
  46. bHaveName = pwsaResults->lpszServiceInstanceName && *(pwsaResults->lpszServiceInstanceName);
  47. t_RemoteBthDevInfo RemoteBthDevInfo;
  48. if ( bHaveName )
  49. {
  50. StringCchPrintf ( RemoteBthDevInfo.szName, sizeof(RemoteBthDevInfo.szName), _T("%s"), 
  51. pwsaResults->lpszServiceInstanceName );
  52. }
  53. RemoteBthDevInfo.Address.ullLong = b;
  54. TRACE (L"%s ( %04x%08x )n", RemoteBthDevInfo.szName, GET_NAP(b), GET_SAP(b) );
  55. m_Ary_RemoteBthDevInfo.Add ( RemoteBthDevInfo );
  56. }
  57. WSALookupServiceEnd(hLookup);
  58. return (int)m_Ary_RemoteBthDevInfo.GetSize();
  59. }
  60. BOOL AUTHENTICATION_CALLBACK (LPVOID pvParam, PBLUETOOTH_DEVICE_INFO pDevice)
  61. {
  62. t_AUTHENTICATION_CALLBACK_Para *pAUTHENTICATION_CALLBACK_Para = (t_AUTHENTICATION_CALLBACK_Para*)pvParam;
  63. if ( pAUTHENTICATION_CALLBACK_Para )
  64. {
  65. pDevice->fAuthenticated = TRUE;
  66. DWORD result = BluetoothUpdateDeviceRecord ( pDevice );
  67. ASSERT ( result == ERROR_SUCCESS );
  68. result = BluetoothSendAuthenticationResponse ( pAUTHENTICATION_CALLBACK_Para->hRadio, pDevice, AUTHENTICATION_PASSKEY );
  69. if ( result == ERROR_SUCCESS )
  70. return TRUE;
  71. }
  72. return FALSE;
  73. }
  74. //
  75. // 用蓝牙 APIs 搜索附近的蓝牙设备,成功时返回设备数,否则返回-1
  76. //
  77. int CBlueTooth::ScanNearbyBthDev (
  78. HANDLE hRadio,
  79. BOOL fReturnAuthenticated/* = TRUE*/,
  80. BOOL fReturnRemembered/* = TRUE*/,
  81. BOOL fReturnUnknown/* = TRUE*/,
  82. BOOL fReturnConnected/* = TRUE*/,
  83. BOOL fIssueInquiry/* = FALSE*/,
  84. UCHAR cTimeoutMultiplier/* = 30*/
  85. )
  86. {
  87. RemoveAll_RemoteBthDevInfo ();
  88. CWaitCursor WaitCursor;
  89. BLUETOOTH_DEVICE_INFO bdi = { sizeof(BLUETOOTH_DEVICE_INFO) };
  90. BLUETOOTH_DEVICE_SEARCH_PARAMS bdsp;
  91. HBLUETOOTH_DEVICE_FIND hbf;
  92. ZeroMemory(&bdsp, sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS));
  93. bdsp.dwSize = sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS);
  94. bdsp.hRadio = hRadio;
  95. bdsp.fReturnAuthenticated = fReturnAuthenticated;
  96. bdsp.fReturnRemembered = fReturnRemembered;
  97. bdsp.fReturnUnknown = fReturnUnknown;
  98. bdsp.fReturnConnected = fReturnConnected;
  99. bdsp.fIssueInquiry = fIssueInquiry;
  100. bdsp.cTimeoutMultiplier = cTimeoutMultiplier;
  101. hbf = BluetoothFindFirstDevice(&bdsp, &bdi);
  102. if (hbf == NULL) return -1;
  103. while(true)
  104. {
  105. TRACE ( _T("%s ( %s )n"), bdi.szName, FormatBthAddress(bdi.Address.rgBytes) );
  106. t_RemoteBthDevInfo RemoteBthDevInfo;
  107. RemoteBthDevInfo.hRadio = hRadio;
  108. RemoteBthDevInfo.Address.ullLong = bdi.Address.ullLong;
  109. _snwprintf_s ( RemoteBthDevInfo.szName, LENGTH(RemoteBthDevInfo.szName), _T("%s"), bdi.szName );
  110. // 枚举服务
  111. EnumerateInstalledServices ( RemoteBthDevInfo );
  112. // 注册配对回调函数
  113. RemoteBthDevInfo.pAUTHENTICATION_CALLBACK_Para = new t_AUTHENTICATION_CALLBACK_Para;
  114. if ( RemoteBthDevInfo.pAUTHENTICATION_CALLBACK_Para )
  115. {
  116. RemoteBthDevInfo.pAUTHENTICATION_CALLBACK_Para->lpBlueTooth = this;
  117. RemoteBthDevInfo.pAUTHENTICATION_CALLBACK_Para->hRadio = hRadio;
  118. }
  119. BluetoothRegisterForAuthentication ( &bdi, &RemoteBthDevInfo.hRegHandle, AUTHENTICATION_CALLBACK, RemoteBthDevInfo.pAUTHENTICATION_CALLBACK_Para );
  120. m_Ary_RemoteBthDevInfo.Add ( RemoteBthDevInfo );
  121. if ( !BluetoothFindNextDevice(hbf, &bdi) )
  122. break;
  123. }
  124. BluetoothFindDeviceClose(hbf);
  125. return (int)m_Ary_RemoteBthDevInfo.GetSize();
  126. }
  127. //
  128. // 用向导手工搜索附近的蓝牙设备并建立连接,得到设备的详细信息,成功时返回设备数
  129. //
  130. int CBlueTooth::ScanNearbyBthDev_Wizard (
  131. HWND hwndParent,
  132. HANDLE hRadio,
  133. LPWSTR  pszInfo/*=NULL*/, //  IN  If not NULL, sets the "information" text
  134. BOOL    fForceAuthentication/*=FALSE*/, //  IN  If TRUE, authenication will be forced before returning
  135. BOOL    fShowAuthenticated/*=FALSE*/, //  IN  If TRUE, authenticated devices will be shown in the picker
  136. BOOL    fShowRemembered/*=TRUE*/, //  IN  If TRUE, remembered devices will be shown in the picker
  137. BOOL    fShowUnknown/*=TRUE*/, //  IN  If TRUE, unknown devices that are not authenticated or "remember" will be shown.
  138. BOOL    fAddNewDeviceWizard/*=TRUE*/, //  IN  If TRUE, invokes the add new device wizard.
  139. BOOL    fSkipServicesPage/*=FALSE*/, //  IN  If TRUE, skips the "Services" page in the wizard.
  140. PFN_DEVICE_CALLBACK pfnDeviceCallback/*=NULL*/, //  IN  If non-NULL, a callback that will be called for each device. If the
  141. //      the callback returns TRUE, the item will be added. If the callback is
  142. //      is FALSE, the item will not be shown.
  143. LPVOID  pvParam/*=NULL*/ //  IN  Parameter to be passed to pfnDeviceCallback as the pvParam.
  144. )
  145. {
  146. RemoveAll_RemoteBthDevInfo ();
  147. BLUETOOTH_SELECT_DEVICE_PARAMS btsdp = { sizeof(btsdp) };
  148. btsdp.hwndParent = hwndParent;
  149. btsdp.pszInfo = pszInfo;
  150. btsdp.fForceAuthentication = fForceAuthentication;
  151. btsdp.fShowAuthenticated = fShowAuthenticated;
  152. btsdp.fShowRemembered = fShowRemembered;
  153. btsdp.fShowUnknown = fShowUnknown;
  154. btsdp.fAddNewDeviceWizard = fAddNewDeviceWizard;
  155. btsdp.fSkipServicesPage = fSkipServicesPage;
  156. btsdp.pfnDeviceCallback = pfnDeviceCallback;
  157. btsdp.pvParam = pvParam;
  158. BOOL b = BluetoothSelectDevices( &btsdp );
  159. if ( b )
  160. {
  161. BLUETOOTH_DEVICE_INFO *pbtdi = btsdp.pDevices;
  162. for ( ULONG cDevice = 0; cDevice < btsdp.cNumDevices; cDevice ++ )
  163. {
  164. if ( pbtdi->fAuthenticated || pbtdi->fRemembered )
  165. {
  166. t_RemoteBthDevInfo RemoteBthDevInfo;
  167. RemoteBthDevInfo.hRadio = hRadio;
  168. RemoteBthDevInfo.Address = pbtdi->Address;
  169. _snwprintf_s ( RemoteBthDevInfo.szName, LENGTH(RemoteBthDevInfo.szName), _T("%s"), pbtdi->szName );
  170. EnumerateInstalledServices ( RemoteBthDevInfo );
  171. m_Ary_RemoteBthDevInfo.Add ( RemoteBthDevInfo );
  172. }
  173. pbtdi = (BLUETOOTH_DEVICE_INFO *) ((LPBYTE)pbtdi + pbtdi->dwSize);
  174. }
  175. BluetoothSelectDevicesFree( &btsdp );
  176. }
  177. return (int)m_Ary_RemoteBthDevInfo.GetSize();
  178. }
  179. //
  180. // 根据远程蓝牙设备的地址获取详细信息
  181. //
  182. BOOL CBlueTooth::BluetoothGetDeviceInfo ( IN t_RemoteBthDevInfo& RemoteBthDevInfo, OUT BLUETOOTH_DEVICE_INFO *pbtdi )
  183. {
  184. BLUETOOTH_DEVICE_INFO bdi = { sizeof(BLUETOOTH_DEVICE_INFO) };
  185. bdi.Address.ullLong = RemoteBthDevInfo.Address.ullLong;
  186. if ( ERROR_SUCCESS != ::BluetoothGetDeviceInfo ( RemoteBthDevInfo.hRadio, &bdi ) )
  187. return FALSE;
  188. if ( pbtdi ) memcpy ( pbtdi, &bdi, sizeof(BLUETOOTH_DEVICE_INFO) );
  189. return TRUE;
  190. }
  191. BOOL CBlueTooth::BluetoothSetServiceState ( HANDLE hRadio, BLUETOOTH_DEVICE_INFO &bdi, GUID guidService, DWORD dwServiceFlags )
  192. {
  193. DWORD result = ::BluetoothSetServiceState(hRadio, &bdi, &guidService, dwServiceFlags);
  194. if ( ERROR_SUCCESS != result && ERROR_SERVICE_DOES_NOT_EXIST != result )
  195. {
  196. TRACE ( _T("BluetoothSetServiceState failed : %sn"), hwFormatMessage (result) );
  197. return FALSE;
  198. }
  199. return TRUE;
  200. }
  201. // 枚举已安装的服务
  202. int CBlueTooth::EnumerateInstalledServices( t_RemoteBthDevInfo& RemoteBthDevInfo )
  203. {
  204. BLUETOOTH_DEVICE_INFO bdi = { sizeof(BLUETOOTH_DEVICE_INFO) };
  205. if ( !BluetoothGetDeviceInfo ( RemoteBthDevInfo, &bdi ) )
  206. return -1;
  207. BluetoothSetServiceState ( RemoteBthDevInfo.hRadio, bdi, SerialPortServiceClass_UUID, BLUETOOTH_SERVICE_ENABLE );
  208. BluetoothSetServiceState ( RemoteBthDevInfo.hRadio, bdi, LANAccessUsingPPPServiceClass_UUID, BLUETOOTH_SERVICE_ENABLE );
  209. BluetoothSetServiceState ( RemoteBthDevInfo.hRadio, bdi, DialupNetworkingServiceClass_UUID, BLUETOOTH_SERVICE_ENABLE );
  210. if ( !BluetoothGetDeviceInfo ( RemoteBthDevInfo, &bdi ) )
  211. return -1;
  212. DWORD numServices = LENGTH(RemoteBthDevInfo.guidServices);
  213. DWORD result = BluetoothEnumerateInstalledServices(RemoteBthDevInfo.hRadio,&bdi, &numServices, RemoteBthDevInfo.guidServices);
  214. if ( ERROR_SUCCESS == result ) return numServices;
  215. return -1;
  216. }
  217. // 显示序号为 nIndex 的蓝牙设备属性框
  218. BOOL CBlueTooth::ShowPropertySheet(int nIndex, HWND hwdParent/*=NULL*/)
  219. {
  220. if ( nIndex < 0 || nIndex >=m_Ary_RemoteBthDevInfo.GetSize() )
  221. return FALSE;
  222. t_RemoteBthDevInfo &RemoteBthDevInfo = m_Ary_RemoteBthDevInfo.GetAt ( nIndex );
  223. BLUETOOTH_DEVICE_INFO bdi = { sizeof(BLUETOOTH_DEVICE_INFO) };
  224. if ( !BluetoothGetDeviceInfo ( RemoteBthDevInfo, &bdi ) )
  225. return FALSE;
  226. return BluetoothDisplayDeviceProperties ( hwdParent, &bdi );
  227. }
  228. // 请求与远程蓝牙设备配对
  229. BOOL CBlueTooth::RequestAuthenticateDevice(int nIndex, HWND hwdParent/*=NULL*/, DWORD *presult/*=NULL*/)
  230. {
  231. if ( nIndex < 0 || nIndex >=m_Ary_RemoteBthDevInfo.GetSize() )
  232. return FALSE;
  233. t_RemoteBthDevInfo &RemoteBthDevInfo = m_Ary_RemoteBthDevInfo.GetAt ( nIndex );
  234. BLUETOOTH_DEVICE_INFO bdi = { sizeof(BLUETOOTH_DEVICE_INFO) };
  235. if ( !BluetoothGetDeviceInfo ( RemoteBthDevInfo, &bdi ) )
  236. return FALSE;
  237. if ( bdi.fAuthenticated ) return TRUE; // 已经配对了
  238. bdi.fAuthenticated = TRUE;
  239. VERIFY ( ERROR_SUCCESS == BluetoothUpdateDeviceRecord ( &bdi ) );
  240. DWORD result = BluetoothAuthenticateDevice ( hwdParent, RemoteBthDevInfo.hRadio, &bdi, AUTHENTICATION_PASSKEY, (ULONG)wcslen(AUTHENTICATION_PASSKEY) );
  241. if ( presult ) *presult = result;
  242. if ( result == ERROR_SUCCESS ) return TRUE;
  243. return FALSE;
  244. }
  245. CString CBlueTooth::FormatBthAddress(BYTE *BthAddress)
  246. {
  247. ASSERT ( BthAddress );
  248. BLUETOOTH_ADDRESS Address;
  249. ASSERT_ADDRESS ( BthAddress, LENGTH(Address.rgBytes)*sizeof(TCHAR) );
  250. CString csBthAddress;
  251. for ( int i=0; i<LENGTH(Address.rgBytes); i++ )
  252. {
  253. CString csNode;
  254. csNode.Format ( _T("%.2x"), BthAddress[LENGTH(Address.rgBytes)-i-1] );
  255. if ( !csBthAddress.IsEmpty() ) csBthAddress += ":";
  256. csBthAddress += csNode;
  257. }
  258. return csBthAddress;
  259. }
  260. // 枚举本地蓝牙设备,返回本地蓝牙设备数
  261. int CBlueTooth::EnumerateLocalRadios(void)
  262. {
  263. m_Ary_LocalRadioInfo.RemoveAll ();
  264. HANDLE hRadio = NULL;
  265. BLUETOOTH_FIND_RADIO_PARAMS btfrp = { sizeof(btfrp) };
  266. HBLUETOOTH_RADIO_FIND hFind = BluetoothFindFirstRadio( &btfrp, &hRadio );
  267. if ( NULL != hFind )
  268. {
  269. do
  270. {
  271. if ( hRadio )
  272. {
  273. t_LocalRadioInfo LocalRadioInfo;
  274. LocalRadioInfo.hRadio = hRadio;
  275. if ( ERROR_SUCCESS == BluetoothGetRadioInfo ( hRadio, &LocalRadioInfo.RadioInfo ) )
  276. {
  277. // 千万注意:以下代码让蓝牙虚拟传出串口能正常工作,我是花了一个通宵的时间才找到这个原因的。
  278. if (FALSE == BluetoothEnableDiscovery(hRadio, TRUE))
  279. {
  280. TRACE(_T("%sn"), hwFormatMessage(GetLastError()));
  281. }
  282. if (FALSE == BluetoothEnableIncomingConnections(hRadio, TRUE))
  283. {
  284. TRACE(_T("%sn"), hwFormatMessage(GetLastError()));
  285. }
  286. m_Ary_LocalRadioInfo.Add ( LocalRadioInfo );
  287. }
  288. }
  289. } while( BluetoothFindNextRadio( hFind, &hRadio ) );
  290. BluetoothFindRadioClose( hFind );
  291. return (int)m_Ary_LocalRadioInfo.GetSize ();
  292. }
  293. return 0;
  294. }
  295. void CBlueTooth::RemoveAllLocalRadio(void)
  296. {
  297. for ( int i=0; i<m_Ary_LocalRadioInfo.GetSize(); i++ )
  298. {
  299. t_LocalRadioInfo &LocalRadioInfo = m_Ary_LocalRadioInfo.GetAt(i);
  300. if ( LocalRadioInfo.hRadio )
  301. CloseHandle ( LocalRadioInfo.hRadio );
  302. }
  303. m_Ary_LocalRadioInfo.RemoveAll ();
  304. }
  305. void CBlueTooth::RemoveAll_RemoteBthDevInfo(void)
  306. {
  307. for ( int i=0; i<m_Ary_RemoteBthDevInfo.GetSize(); i++ )
  308. {
  309. t_RemoteBthDevInfo &RemoteBthDevInfo = m_Ary_RemoteBthDevInfo.GetAt(i);
  310. if ( RemoteBthDevInfo.hRegHandle )
  311. BluetoothUnregisterAuthentication ( RemoteBthDevInfo.hRegHandle );
  312. if ( RemoteBthDevInfo.pAUTHENTICATION_CALLBACK_Para )
  313. delete RemoteBthDevInfo.pAUTHENTICATION_CALLBACK_Para;
  314. }
  315. m_Ary_RemoteBthDevInfo.RemoveAll ();
  316. }
  317. int CBlueTooth::Test(void)
  318. {
  319. return 0;
  320. }