BlueTooth_WM.cpp
上传用户:hbzxgg2
上传日期:2009-03-28
资源大小:291k
文件大小:12k
源码类别:

Windows Mobile

开发平台:

Visual C++

  1. #include "StdAfx.h"
  2. #include "BlueTooth_WM.h"
  3. // for PORTEMUPortParams
  4. #include <bt_api.h>
  5. DEFINE_GUID(SerialPortServiceClass_UUID,               0x00001101, 0x0000, 0x1000, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB);
  6. DWORD WINAPI ThreadProc_ScanNearbyBthDev(
  7.   LPVOID lpParameter   // thread data
  8. )
  9. {
  10. CBlueTooth_WM *pBlueTooth_WM = reinterpret_cast<CBlueTooth_WM*>(lpParameter);
  11. if ( pBlueTooth_WM )
  12. pBlueTooth_WM->ThreadProc_ScanNearbyBthDev ();
  13. return TRUE;
  14. }
  15. CBlueTooth_WM::CBlueTooth_WM(void)
  16. : m_hThread_ScanNearbyBthDev ( NULL )
  17. , m_dwThreadID_ScanNearbyBthDev ( 0 )
  18. , m_hEvtEndModule ( NULL )
  19. , m_hEvt_Notify_ScanNearbyBthDev ( NULL )
  20. , m_hWnd_Noify_ScanNearbyBthDev ( NULL )
  21. , m_socketClient ( INVALID_SOCKET )
  22. {
  23. m_Ary_RemoteBthDevInfo.SetSize ( 0, 10*sizeof(t_RemoteBthDevInfo) );
  24. }
  25. CBlueTooth_WM::~CBlueTooth_WM(void)
  26. {
  27. if ( HANDLE_IS_VALID(m_hEvtEndModule) )
  28. ::SetEvent ( m_hEvtEndModule );
  29. WaitForThreadEnd ( &m_hThread_ScanNearbyBthDev, 10*1000 );
  30. SAFE_CLOSE_HANDLE ( m_hEvtEndModule );
  31. if ( m_socketClient != INVALID_SOCKET )
  32. closesocket ( m_socketClient );
  33. RemoveAll_RemoteBthDevInfo ();
  34. }
  35. //
  36. // 调用该类中任何函数之前必须先调用该函数来初始化
  37. //
  38. BOOL CBlueTooth_WM::Init ( LPCTSTR lpszCurDir )
  39. {
  40. m_hEvtEndModule = ::CreateEvent ( NULL, TRUE, FALSE, NULL );
  41. if ( !HANDLE_IS_VALID(m_hEvtEndModule) )
  42. return FALSE;
  43. m_csCurDir = GET_SAFE_STRING(lpszCurDir);
  44. Read_RemoteBthDevInfo_FromFile ( m_csCurDir );
  45. return TRUE;
  46. }
  47. void CBlueTooth_WM::ThreadProc_ScanNearbyBthDev ()
  48. {
  49. int nRetValue = ScanNearbyBthDev_Direct ();
  50. if ( HANDLE_IS_VALID(m_hEvt_Notify_ScanNearbyBthDev) )
  51. SetEvent ( m_hEvt_Notify_ScanNearbyBthDev );
  52. if ( IsWindow(m_hWnd_Noify_ScanNearbyBthDev) )
  53. PostMessage ( m_hWnd_Noify_ScanNearbyBthDev, WM_SCAN_BLUETOOTH_DEVICE_FINISHED, nRetValue, 0 );
  54. SAFE_CLOSE_HANDLE ( m_hThread_ScanNearbyBthDev );
  55. TRACE ( L"ThreadProc_ScanNearbyBthDev ENDn" );
  56. }
  57. //
  58. // 搜索附近的蓝牙设备,如果指定 hEvt_Notify 或 hWnd_Noify 参数,表示异步查找,完成后以这两个参数中的一个通知调用者
  59. // 如果这两个参数都未指定,表示同步查找,即完成后才会返回
  60. //
  61. BOOL CBlueTooth_WM::ScanNearbyBthDev ( HANDLE hEvt_Notify/*=NULL*/, HWND hWnd_Noify/*=NULL*/ )
  62. {
  63. if ( HANDLE_IS_VALID(m_hThread_ScanNearbyBthDev) ) return TRUE;
  64. // 异步查找蓝牙设备,启动查找函数
  65. if ( hEvt_Notify || IsWindow(hWnd_Noify) )
  66. {
  67. m_hEvt_Notify_ScanNearbyBthDev = hEvt_Notify;
  68. m_hWnd_Noify_ScanNearbyBthDev = hWnd_Noify;
  69. m_hThread_ScanNearbyBthDev = ::CreateThread ( NULL, 0, ::ThreadProc_ScanNearbyBthDev, this, 0, &m_dwThreadID_ScanNearbyBthDev );
  70. return HANDLE_IS_VALID(m_hThread_ScanNearbyBthDev);
  71. }
  72. return ( ScanNearbyBthDev_Direct() >= 0 );
  73. }
  74. //
  75. // 用 Socket 函数搜索附近的蓝牙设备,成功时返回设备数,否则返回-1
  76. //
  77. int CBlueTooth_WM::ScanNearbyBthDev_Direct ()
  78. {
  79. m_Ary_RemoteBthDevInfo.RemoveAll ();
  80. SetWaitCursor ();
  81. WSAQUERYSET querySet;
  82. HANDLE hLookup;
  83. DWORD flags = LUP_RETURN_NAME | LUP_RETURN_ADDR; 
  84. union
  85. {
  86. CHAR buf[5000];
  87. double __unused; // ensure proper alignment
  88. };
  89. LPWSAQUERYSET pwsaResults = (LPWSAQUERYSET) buf;
  90. DWORD dwSize = sizeof(buf);
  91. BOOL bHaveName;
  92. ZeroMemory(&querySet, sizeof(querySet));
  93. querySet.dwSize = sizeof(querySet);
  94. querySet.dwNameSpace = NS_BTH;
  95. if ( ::WaitForSingleObject ( m_hEvtEndModule, 0 ) == WAIT_OBJECT_0 )
  96. return -1;
  97. if (ERROR_SUCCESS != WSALookupServiceBegin (&querySet, LUP_CONTAINERS, &hLookup))
  98. {
  99. ResotreCursor ();
  100. MsgBoxErr ( _T("WSALookupServiceBegin failed") );
  101. return (-1);
  102. }
  103. ZeroMemory(pwsaResults, sizeof(WSAQUERYSET));
  104. pwsaResults->dwSize = sizeof(WSAQUERYSET);
  105. pwsaResults->dwNameSpace = NS_BTH;
  106. pwsaResults->lpBlob = NULL;
  107. BOOL bError = FALSE;
  108. while ( TRUE )
  109. {
  110. if ( ::WaitForSingleObject ( m_hEvtEndModule, 0 ) == WAIT_OBJECT_0 )
  111. break;
  112. if ( ERROR_SUCCESS == WSALookupServiceNext (hLookup, flags, &dwSize, pwsaResults) )
  113. {
  114. ASSERT (pwsaResults->dwNumberOfCsAddrs == 1);
  115. BT_ADDR b = ((SOCKADDR_BTH *)pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr)->btAddr;
  116. bHaveName = pwsaResults->lpszServiceInstanceName && *(pwsaResults->lpszServiceInstanceName);
  117. t_RemoteBthDevInfo RemoteBthDevInfo;
  118. if ( bHaveName )
  119. {
  120. hwSnprintf ( RemoteBthDevInfo.szName, sizeof(RemoteBthDevInfo.szName), _T("%s"), 
  121. pwsaResults->lpszServiceInstanceName );
  122. }
  123. RemoteBthDevInfo.RemoteAddr = b;
  124. CSADDR_INFO* pCSAddr = (CSADDR_INFO *)pwsaResults->lpcsaBuffer;
  125. RemoteBthDevInfo.LocalAddr = ((SOCKADDR_BTH *)pCSAddr->LocalAddr.lpSockaddr)->btAddr;
  126. TRACE (L"%s ( %04x%08x )n", RemoteBthDevInfo.szName, GET_NAP(b), GET_SAP(b) );
  127. Add_RemoteBthDevInfo ( RemoteBthDevInfo );
  128. }
  129. else
  130. {
  131. if ( WSAGetLastError() != WSA_E_NO_MORE )
  132. {
  133. bError = TRUE;
  134. ResotreCursor ();
  135. MsgBoxErr ( L"Lookup bluetooth device failed" );
  136. }
  137. break;
  138. }
  139. }
  140. WSALookupServiceEnd(hLookup);
  141. ResotreCursor ();
  142. if ( bError ) return (-1);
  143. return (int)m_Ary_RemoteBthDevInfo.GetSize();
  144. }
  145. CString CBlueTooth_WM::FormatBthAddress(BT_ADDR BthAddress)
  146. {
  147. ASSERT ( BthAddress );
  148. BLUETOOTH_ADDRESS Address;
  149. BYTE *pAddress = (BYTE*)&BthAddress;
  150. CString csBthAddress;
  151. for ( int i=0; i<LENGTH(Address.rgBytes); i++ )
  152. {
  153. CString csNode;
  154. csNode.Format ( _T("%.2x"), pAddress[LENGTH(Address.rgBytes)-i-1] );
  155. if ( !csBthAddress.IsEmpty() ) csBthAddress += ":";
  156. csBthAddress += csNode;
  157. }
  158. return csBthAddress;
  159. }
  160. int CBlueTooth_WM::Find_RemoteBthDevInfo ( LPCTSTR lpszName_Found, t_RemoteBthDevInfo *pRemoteBthDevInfo/*=NULL*/ )
  161. {
  162. if ( !lpszName_Found || strlen_s(lpszName_Found) < 1 ) return -1;
  163. for ( int i=0; i<m_Ary_RemoteBthDevInfo.GetSize(); i++ )
  164. {
  165. t_RemoteBthDevInfo &RemoteBthDevInfoRef = m_Ary_RemoteBthDevInfo.GetAt(i);
  166. if ( stricmp_s ( RemoteBthDevInfoRef.szName, lpszName_Found ) == 0 )
  167. {
  168. if ( pRemoteBthDevInfo )
  169. {
  170. memcpy ( pRemoteBthDevInfo, &RemoteBthDevInfoRef, sizeof(t_RemoteBthDevInfo) );
  171. }
  172. return i;
  173. }
  174. }
  175. return -1;
  176. }
  177. int CBlueTooth_WM::Find_RemoteBthDevInfo ( BT_ADDR Addr_Found, t_RemoteBthDevInfo *pRemoteBthDevInfo/*=NULL*/ )
  178. {
  179. for ( int i=0; i<m_Ary_RemoteBthDevInfo.GetSize(); i++ )
  180. {
  181. t_RemoteBthDevInfo &RemoteBthDevInfoRef = m_Ary_RemoteBthDevInfo.GetAt(i);
  182. if ( RemoteBthDevInfoRef.RemoteAddr == Addr_Found )
  183. {
  184. if ( pRemoteBthDevInfo )
  185. {
  186. memcpy ( pRemoteBthDevInfo, &RemoteBthDevInfoRef, sizeof(t_RemoteBthDevInfo) );
  187. }
  188. return i;
  189. }
  190. }
  191. return -1;
  192. }
  193. int CBlueTooth_WM::Add_RemoteBthDevInfo ( t_RemoteBthDevInfo &RemoteBthDevInfo )
  194. {
  195. if ( Find_RemoteBthDevInfo ( RemoteBthDevInfo.RemoteAddr ) >= 0 )
  196. return TRUE;
  197. m_Ary_RemoteBthDevInfo.Add ( RemoteBthDevInfo );
  198. }
  199. void CBlueTooth_WM::RemoveAll_RemoteBthDevInfo(void)
  200. {
  201. Save_RemoteBthDevInfo_ToFile ( m_csCurDir );
  202. for ( int i=0; i<m_Ary_RemoteBthDevInfo.GetSize(); i++ )
  203. {
  204. t_RemoteBthDevInfo &RemoteBthDevInfo = m_Ary_RemoteBthDevInfo.GetAt(i);
  205. }
  206. m_Ary_RemoteBthDevInfo.RemoveAll ();
  207. }
  208. //
  209. // 将周边蓝牙设备信息保存到文件中,这样就可以不用每次都重新搜索蓝牙设备了,只要当连接蓝牙设备失败的时候再重新搜索
  210. //
  211. BOOL CBlueTooth_WM::Save_RemoteBthDevInfo_ToFile(LPCTSTR lpszPath)
  212. {
  213. CString csFileName;
  214. csFileName.Format ( L"%sRemoteBthInfo.info", GET_SAFE_STRING(lpszPath) );
  215. CFile file;
  216. BOOL bRet = TRUE;
  217. TRY
  218. {
  219. if ( file.Open ( csFileName, CFile::modeCreate|CFile::modeWrite) )
  220. {
  221. for ( int i=0; i<m_Ary_RemoteBthDevInfo.GetSize(); i++ )
  222. {
  223. t_RemoteBthDevInfo &RemoteBthDevInfo = m_Ary_RemoteBthDevInfo.GetAt(i);
  224. file.Write ( &RemoteBthDevInfo, sizeof(RemoteBthDevInfo) );
  225. }
  226. }
  227. }
  228. CATCH( CFileException, e )
  229. {
  230. e->Delete ();
  231. bRet = FALSE;
  232. }
  233. END_CATCH
  234. if ( HANDLE_IS_VALID ( file.m_hFile ) )
  235. file.Close ();
  236. return bRet;
  237. }
  238. //
  239. // 从文件中读取上次保存的周边蓝牙设备信息,结果保存到 m_Ary_RemoteBthDevInfo 数组中
  240. //
  241. BOOL CBlueTooth_WM::Read_RemoteBthDevInfo_FromFile(LPCTSTR lpszPath)
  242. {
  243. CString csFileName;
  244. csFileName.Format ( L"%sRemoteBthInfo.info", GET_SAFE_STRING(lpszPath) );
  245. CFile file;
  246. BOOL bRet = TRUE;
  247. TRY
  248. {
  249. if ( file.Open ( csFileName, CFile::modeRead) )
  250. {
  251. while ( TRUE )
  252. {
  253. t_RemoteBthDevInfo RemoteBthDevInfo;
  254. if ( file.Read ( &RemoteBthDevInfo, sizeof(t_RemoteBthDevInfo) ) != sizeof(t_RemoteBthDevInfo) )
  255. break;
  256. else
  257. {
  258. Add_RemoteBthDevInfo ( RemoteBthDevInfo );
  259. }
  260. }
  261. }
  262. }
  263. CATCH( CFileException, e )
  264. {
  265. e->Delete ();
  266. bRet = FALSE;
  267. }
  268. END_CATCH
  269. if ( HANDLE_IS_VALID ( file.m_hFile ) )
  270. file.Close ();
  271. return bRet;
  272. }
  273. BOOL CBlueTooth_WM::StringToGUID ( LPCTSTR lpszGUID, GUID *pGUID)
  274. {
  275. if ( !lpszGUID ) return FALSE;
  276. int data1, data2, data3;
  277. int data4[8];
  278. if (11 ==  sscanf_s(lpszGUID, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02xn",
  279. &data1, &data2, &data3,
  280. &data4[0], &data4[1], &data4[2], &data4[3], 
  281. &data4[4], &data4[5], &data4[6], &data4[7])) {
  282. pGUID->Data1 = data1;
  283. pGUID->Data2 = data2 & 0xffff;
  284. pGUID->Data3 = data3 & 0xffff;
  285. for (int i = 0 ; i < 8 ; ++i)
  286. pGUID->Data4[i] = data4[i] & 0xff;
  287. return TRUE;
  288. }
  289. return FALSE;
  290. }
  291. //
  292. // 连接到蓝牙服务器中的某一个服务,成功返回0,失败返回错误代码
  293. //
  294. int CBlueTooth_WM::ConnectToBlueToothServer ( BT_ADDR ServerAddress, LPCTSTR lpszServiceGUID )
  295. {
  296. if ( m_socketClient==INVALID_SOCKET )
  297. {
  298. GUID ServerGuid;
  299. if ( !StringToGUID(lpszServiceGUID, &ServerGuid) )
  300. return -1;
  301. m_socketClient = socket (AF_BT, SOCK_STREAM, BTHPROTO_RFCOMM);
  302. if (m_socketClient == INVALID_SOCKET) 
  303. {
  304. return WSAGetLastError();
  305. }
  306. SOCKADDR_BTH sa;
  307. memset (&sa, 0, sizeof(sa));
  308. sa.addressFamily = AF_BT;
  309. sa.serviceClassId = ServerGuid;
  310. sa.btAddr = ServerAddress;
  311. if (connect (m_socketClient, (SOCKADDR *)&sa, sizeof(sa)) == SOCKET_ERROR) 
  312. {
  313. m_socketClient = INVALID_SOCKET;
  314. return WSAGetLastError();
  315. }
  316. }
  317. // Set nonblocking of socket
  318. /* long cmd = FIONBIO;
  319. u_long argp = 1; // 0 表示阻塞, 非0 表示非阻塞
  320. BOOL err = ioctlsocket ( m_socketClient, cmd, (u_long*)&argp );
  321. if ( err )
  322. {
  323. TRACE ( L"Set main socket to(#1) nonblocking failed!n" );
  324. }
  325. */
  326. return 0;
  327. }
  328. //
  329. // 断开连接
  330. //
  331. void CBlueTooth_WM::Disconnect ()
  332. {
  333. if ( m_socketClient==INVALID_SOCKET ) return;
  334. shutdown ( m_socketClient, SD_BOTH );
  335. closesocket ( m_socketClient );
  336. m_socketClient = INVALID_SOCKET;
  337. }
  338. //
  339. // 数据传输(收/发)
  340. // 返回成功传输的字节数。失败时返回 -1;连接已经断开,返回 -2;处理不能立即完成,返回-3
  341. //
  342. int CBlueTooth_WM::Transmite ( LPVOID lpData, int nSize, BOOL bSend )
  343. {
  344. if ( m_socketClient==INVALID_SOCKET ) return -1;
  345. if ( !lpData ) return -1;
  346. if ( nSize < 1 ) return 0;
  347. int iBytesTransmited = 0;
  348. if ( bSend )
  349. iBytesTransmited = send (m_socketClient, (char *)lpData, nSize, 0);
  350. else
  351. iBytesTransmited = recv (m_socketClient, (char *)lpData, nSize, 0);
  352. if ( iBytesTransmited > 0 ) return iBytesTransmited;
  353. int nLastError = WSAGetLastError ();
  354. if ( nLastError == WSAENETDOWN || nLastError == WSAENOTCONN || nLastError == WSAENOTSOCK || nLastError == WSAESHUTDOWN ||
  355. nLastError == WSAETIMEDOUT )
  356. {
  357. Disconnect ();
  358. return -2;
  359. }
  360. if ( nLastError == WSAEWOULDBLOCK )
  361. return -3;
  362. return -1;
  363. }
  364. //
  365. // 发送数据
  366. // 返回成功发送的字节数。失败时返回 -1;连接已经断开,返回 -2;处理不能立即完成,返回-3
  367. //
  368. int CBlueTooth_WM::Send ( LPVOID lpData, int nSize )
  369. {
  370. return Transmite ( lpData, nSize, TRUE );
  371. }
  372. //
  373. // 接收数据
  374. // 返回接受到的字节数。失败时返回 -1;连接已经断开,返回 -2;处理不能立即完成,返回-3
  375. //
  376. int CBlueTooth_WM::Recv ( LPVOID lpData, int nSize )
  377. {
  378. // 得到可读的数据长度
  379. long cmd = FIONREAD;
  380. u_long argp = 0;
  381. BOOL err = ioctlsocket ( m_socketClient, cmd, (u_long*)&argp );
  382. if ( err || argp < 1 )
  383. {
  384. return 0;
  385. }
  386. return Transmite ( lpData, nSize, FALSE );
  387. }