TNB Library
TnbCeBluetoothCom.h
[詳解]
1#pragma once
13#ifndef _WIN32_WCE
14 #error TnbCeBluetoothCom.h is only supported on Windows CE platforms.
15#endif // _WIN32_WCE
16
17
18
19#include "TnbRs232c.h"
20#include "TnbCeBluetooth.h"
21
22
23
24//TNB Library
25namespace TNB{
26
27
28
43{
44public:
45
48 : m_hVirCom(NULL), m_spdHandle(0), m_btAddr(0), m_hServerCom(INVALID_HANDLE_VALUE)
49 {
50 }
51
54 {
55 Delete();
56 }
57
70 bool CreateClientPort(CRs232c::CPort portNo, const BT_ADDR& btAddr, int channel = -1, GUID service = SerialPortServiceClass_UUID)
71 {
72 Delete();
73 m_btAddr = btAddr;
74 m_port = portNo;
75 m_hVirCom = ms_Create(m_port, m_btAddr, false, 0, channel, service);
76 return m_hVirCom != NULL;
77 }
78
89 bool CreateServerPort(CRs232c::CPort portNo, int portFlag = RFCOMM_PORT_FLAGS_AUTHENTICATE | RFCOMM_PORT_FLAGS_ENCRYPT)
90 {
91 Delete();
92 m_btAddr = 0;
93 m_port = portNo;
94 m_hVirCom = ms_Create(portNo, m_btAddr, true, portFlag, 0);
95 if ( m_hVirCom != NULL )
96 {
97 DWORD desiredAccess = GENERIC_READ | GENERIC_WRITE; // アクセス (読み取りおよび書き込み) モード
98 DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
99 DWORD flag = FILE_ATTRIBUTE_NORMAL;
100 m_hServerCom = ::CreateFile(portNo.GetPortName(), desiredAccess, shareMode, NULL, OPEN_EXISTING, flag, NULL);
101 m_spdHandle = ms_RegisterSDP(m_hServerCom);
102 }
103 return m_hVirCom != NULL;
104 }
105
111 bool IsValid(void) const
112 {
113 return m_hVirCom != NULL;
114 }
115
122 {
123 return m_port;
124 }
125
134 bool GetPeerAddress(BT_ADDR& _btAddr) const
135 {
136 if ( m_btAddr != 0 )
137 {
138 _btAddr = m_btAddr;
139 return true;
140 }
141 DWORD dwSizeOut = 0;
142 BOOL r = ::DeviceIoControl(m_hServerCom, IOCTL_BLUETOOTH_GET_PEER_DEVICE, NULL, 0, &_btAddr, sizeof(_btAddr), &dwSizeOut, NULL);
143 return !! r;
144 }
145
151 void Delete(void)
152 {
153 if ( m_hServerCom != INVALID_HANDLE_VALUE )
154 {
155 ::CloseHandle(m_hServerCom);
156 m_hServerCom = INVALID_HANDLE_VALUE;
157 }
158 if ( m_spdHandle != 0 )
159 {
160 ms_DeRegisterSDP(m_spdHandle);
161 m_spdHandle = 0;
162 }
163 if ( m_hVirCom != NULL )
164 {
165 ::DeregisterDevice(m_hVirCom);
166 m_hVirCom = NULL;
167 }
168 }
169
170private:
171 // 作成
172 static HANDLE ms_Create(CRs232c::CPort portNo, const BT_ADDR& btAddr, bool isServer, int portFlag, int channel
173 , GUID service = SerialPortServiceClass_UUID)
174 {
175 int port = portNo.GetNumber();
176 CStr prefix = portNo.GetPrefix();
177 //== COM ポートの使用状態チェック
178 DEVMGR_DEVICE_INFORMATION ddi = { 0 };
179 ddi.dwSize = sizeof(DEVMGR_DEVICE_INFORMATION);
180 HANDLE hh = ::FindFirstDevice(DeviceSearchByDeviceName
181 , CStr::Fmt(_T("%s%d"), prefix, port), &ddi);
182 if ( hh != INVALID_HANDLE_VALUE )
183 {
184 TTRACE1("found hDevice = 0x%08X\n", ddi.hDevice);
185 TTRACE1(" hParent = 0x%08X\n", ddi.hParentDevice);
186 TTRACE1(" szDeviceName = %s\n", ddi.szDeviceName);
187 TTRACE1(" szLegacyName = %s\n", ddi.szLegacyName);
188 TTRACE1(" szBusName = %s\n", ddi.szBusName);
189 TTRACE1(" szDeviceKey = %s\n", ddi.szDeviceKey);
190 if ( ddi.szDeviceKey[0] == 0 )
191 {
192 if ( ! ::DeregisterDevice(ddi.hDevice) )
193 {
194 _GetLastError("DeregisterDevice");
195 }
196 }
197 ::FindClose(hh);
198 }
199 //== 割当
200 PORTEMUPortParams pp = { 0 };
201 pp.device = btAddr;
202 pp.flocal = isServer;
203 pp.uiportflags = portFlag;// | RFCOMM_PORT_FLAGS_REMOTE_DCB;
204 if ( isServer )
205 {
206 pp.channel = RFCOMM_CHANNEL_MULTIPLE;
207 }
208 else
209 {
210 if ( channel >= 0 )
211 {
212 pp.channel = channel;
213 }
214 else
215 {
216 pp.channel = 0;
217 pp.uuidService = service;
218 }
219 }
220 DWORD info = reinterpret_cast<DWORD>(&pp);
221 HANDLE h = ::RegisterDevice(prefix, port, _T("btd.dll"), info);
222 if ( h == NULL )
223 {
224 _GetLastError("RegisterDevice");
225 }
226 return h;
227 }
228
229 // [登録] SDP登録.
230 static ULONG ms_RegisterSDP(HANDLE handle)
231 {
232 CBluetoothApi api;
233 const int SDP_RECORD_SIZE = 0x0000004d;
234 const int SDP_CHANNEL_OFFSET = 26;
235 static const BYTE rgbSdpRecordSPP[SDP_RECORD_SIZE] =
236 {
237 0x35, 0x4b, 0x09, 0x00, 0x01, 0x35, 0x03, 0x19,
238 0x11, 0x01, 0x09, 0x00, 0x04, 0x35, 0x0c, 0x35,
239 0x03, 0x19, 0x01, 0x00, 0x35, 0x05, 0x19, 0x00,
240 0x03, 0x08,
241 0x01, // server channel goes here (+26)
242 0x09, 0x00, 0x06, 0x35, 0x09,
243 0x09, 0x65, 0x6e, 0x09, 0x00, 0x6a, 0x09, 0x01,
244 0x00, 0x09, 0x00, 0x09, 0x35, 0x08, 0x35, 0x06,
245 0x19, 0x11, 0x01, 0x09, 0x01, 0x00, 0x09, 0x01, // 0x1101 シリアル
246 0x00, 0x25, 0x12, 'S', 'h', 'a', 'r', 'e',
247 'd', ' ', 'S', 'e', 'r', 'i', 'a', 'l',
248 ' ', 'P', 'o', 'r', 't'
249 };
250 ASSERT( rgbSdpRecordSPP[SDP_CHANNEL_OFFSET - 1] == 0x08 );
251 ASSERT( rgbSdpRecordSPP[SDP_CHANNEL_OFFSET ] == 0x01 );
252 ASSERT( rgbSdpRecordSPP[SDP_CHANNEL_OFFSET + 1] == 0x09 );
253 ULONG recordHandle = 0;
254 DWORD port = 0;
255 DWORD dwSizeOut = 0;
256 if ( ! ::DeviceIoControl(handle, IOCTL_BLUETOOTH_GET_RFCOMM_CHANNEL, NULL, 0, &port, sizeof(port), &dwSizeOut, NULL))
257 {
258 TRACE1("BLUETOOTH GATEWAY:: Failed to retrieve port server channel, error = %d\n", GetLastError());
259 return 0;
260 }
261 struct
262 {
263 BTHNS_SETBLOB b;
264 unsigned char uca[SDP_RECORD_SIZE];
265 } bigBlob;
266 ULONG ulSdpVersion = BTH_SDP_VERSION;
267 bigBlob.b.pRecordHandle = &recordHandle;
268 bigBlob.b.pSdpVersion = &ulSdpVersion;
269 bigBlob.b.fSecurity = 0;
270 bigBlob.b.fOptions = 0;
271 bigBlob.b.ulRecordLength = SDP_RECORD_SIZE;
272 memcpy(bigBlob.b.pRecord, rgbSdpRecordSPP, SDP_RECORD_SIZE);
273 bigBlob.b.pRecord[SDP_CHANNEL_OFFSET] = static_cast<BYTE>(port);
274 BLOB blob;
275 blob.cbSize = sizeof(BTHNS_SETBLOB) + SDP_RECORD_SIZE - 1;
276 blob.pBlobData = reinterpret_cast<BYTE*>(&bigBlob);
277 WSAQUERYSET service = { 0 };
278 service.dwSize = sizeof(service);
279 service.lpBlob = &blob;
280 service.dwNameSpace = NS_BTH;
281 int r = api.BthNsSetService(&service, RNRSERVICE_REGISTER, 0);
282 if ( r != ERROR_SUCCESS )
283 {
284 TRACE1("BLUETOOTH GATEWAY:: BthNsSetService fails with status %d\n", r);
285 return 0;
286 }
287 TRACE2("BLUETOOTH GATEWAY:: Created SDP record 0x%08x, channel %d\n", recordHandle, port);
288 return recordHandle;
289 }
290
291 // [登録] SDP登録解除.
292 static void ms_DeRegisterSDP(ULONG recordHandle)
293 {
294 CBluetoothApi api;
295 ULONG ulSdpVersion = BTH_SDP_VERSION;
296 BTHNS_SETBLOB delBlob = { 0 };
297 delBlob.pRecordHandle = &recordHandle;
298 delBlob.pSdpVersion = &ulSdpVersion;
299 BLOB blob = { 0 };
300 blob.cbSize = sizeof(BTHNS_SETBLOB);
301 blob.pBlobData = (PBYTE) &delBlob;
302 WSAQUERYSET service = { 0 };
303 service.dwSize = sizeof(service);
304 service.lpBlob = &blob;
305 service.dwNameSpace = NS_BTH;
306 int r = api.BthNsSetService (&service, RNRSERVICE_DELETE, 0);
307 TRACE2("BLUETOOTH GATEWAY: removed SDP record 0x%08x (%d)\n", recordHandle, r);
308 }
309
310 HANDLE m_hVirCom;
311 HANDLE m_hServerCom;
312 ULONG m_spdHandle;
313 CRs232c::CPort m_port;
314 BT_ADDR m_btAddr;
315};
316
317
318
333class CBluetoothCom : public CRs232c
334{
335 DEFSUPER(CRs232c);
336public:
337
339 CBluetoothCom(void) : m_btAddr(0), m_isServer(false)
340 {
341 }
342
345 {
346 Close();
347 }
348
355 void SetClientParameter(const BT_ADDR& btAddr, int channel = -1)
356 {
357 Close();
358 m_btAddr = btAddr;
359 m_channel = channel;
360 m_isServer = false;
361 }
362
368 void SetServerParameter(int portFlag = RFCOMM_PORT_FLAGS_AUTHENTICATE | RFCOMM_PORT_FLAGS_ENCRYPT)
369 {
370 Close();
371 m_btAddr = 0;
372 m_channel = -1;
373 m_portFlag = portFlag;
374 m_isServer = true;
375 }
376
385 bool GetPeerAddress(BT_ADDR& _btAddr) const
386 {
387 if ( ! m_isServer )
388 {
389 _btAddr = m_btAddr;
390 return true;
391 }
392 return m_virCom.GetPeerAddress(_btAddr);
393 }
394
403 virtual bool Open(void)
404 {
405 CPort comPort;
406 DWORD dwBaudRate;
407 BYTE bByteSize;
408 EParity eParity;
409 EStopBits eStopBits;
410 _super::GetParameter(comPort, dwBaudRate, bByteSize, eParity, eStopBits);
411 _super::Close();
412 bool r = false;
413 if ( m_isServer )
414 {
415 r = m_virCom.CreateServerPort(comPort, m_portFlag);
416 }
417 else
418 {
419 r = m_virCom.CreateClientPort(comPort, m_btAddr, m_channel);
420 }
421 if ( r )
422 {
423 return _super::Open();
424 }
425 return false;
426 }
427
433 virtual void Close(void)
434 {
435 _super::Close();
436 m_virCom.Delete();
437 }
438
440 struct TChannel
441 {
444 };
445
448
457 static CChannels FindChannels(const BT_ADDR& btAddr, WORD classId = SerialPortServiceClassID_UUID16)
458 {
459 CChannels vb;
460 CBluetoothDevice ba(btAddr);
462 if ( ba.HasService(attr, classId) && attr.IsValid() )
463 {
464 loop ( i, attr.GetRecordCount() )
465 {
466 if ( attr.SearchRecord(i) )
467 {
468 TChannel pp;
469 pp.channel = -1;
470 const CBluetoothServiceAttribute::TValuesList& list = attr.GetAttributeData(4/*protocol descriptor list*/);
471 loop ( j, list.GetSize() )
472 {
473 if ( list[j].spec == SDP_ST_UUID16 && list[j].uuid16 == 3 )
474 {
475 if ( j + 1 < list.GetSize() && list[j + 1].spec == SDP_ST_UINT8 )
476 {
477 pp.channel = list[j + 1].uint8;
478 }
479 break;
480 }
481 }
483 loop ( j, l2.GetSize() )
484 {
485 if ( l2[j].type == SDP_TYPE_STRING )
486 {
487 pp.portName = l2[j].str;
488 break;
489 }
490 }
491 if ( pp.channel >= 0 )
492 {
493 vb.Add(pp);
494 }
495 }
496 }
497 }
498 return vb;
499 }
500
501private:
502 CBluetoothVirtualComPort m_virCom;
503 BT_ADDR m_btAddr;
504 int m_channel;
505 bool m_isServer;
506 int m_portFlag;
507};
508
509
510
511};//TNB
CE 用 Bluetooth関係のヘッダ
#define loop(VAR, CNT)
loop構文.
Definition: TnbDef.h:343
RS232Cのアクセス関係のヘッダ
Bluetooth(CE) クライアントシリアルアクセスクラス.
void SetServerParameter(int portFlag=RFCOMM_PORT_FLAGS_AUTHENTICATE|RFCOMM_PORT_FLAGS_ENCRYPT)
[設定] サーバ設定.
virtual bool Open(void)
[処理] オープン.
~CBluetoothCom(void)
デストラクタ
bool GetPeerAddress(BT_ADDR &_btAddr) const
[取得] 相手アドレス取得.
CVectorT< TChannel > CChannels
チャネル情報リスト型
CBluetoothCom(void)
コンストラクタ
virtual void Close(void)
[処理] クローズ.
void SetClientParameter(const BT_ADDR &btAddr, int channel=-1)
[設定] クライアント設定.
static CChannels FindChannels(const BT_ADDR &btAddr, WORD classId=SerialPortServiceClassID_UUID16)
[取得] RFCOMMチャネル検索.
Bluetooth(CE) デバイス管理.
bool HasService(CWorkMem &_raw, WORD uuid16) const
[確認] サービス確認.
Bluetooth(CE) サービス属性管理.
bool IsValid(void) const
[確認] 有効確認.
const TValuesList & GetAttributeData(WORD attributeId) const
[取得] 属性IDデータ取得.
bool SearchRecord(INDEX record)
[検索] レコード検索.
size_t GetRecordCount(void) const
[取得] 保持レコード数.
Bluetooth(CE) 仮想COMポート管理クラス.
CBluetoothVirtualComPort(void)
コンストラクタ
bool CreateServerPort(CRs232c::CPort portNo, int portFlag=RFCOMM_PORT_FLAGS_AUTHENTICATE|RFCOMM_PORT_FLAGS_ENCRYPT)
[作成] サーバポート作成.
bool IsValid(void) const
[確認] 有効確認.
const CRs232c::CPort & GetCreatedPort(void) const
[取得] 作成ポート名取得.
bool GetPeerAddress(BT_ADDR &_btAddr) const
[取得] 相手アドレス取得.
void Delete(void)
[破棄] ポート破棄.
bool CreateClientPort(CRs232c::CPort portNo, const BT_ADDR &btAddr, int channel=-1, GUID service=SerialPortServiceClass_UUID)
[作成] クライアントポート作成.
~CBluetoothVirtualComPort(void)
デストラクタ
[ETC] コピー不可能スーパークラス.
Definition: TnbDef.h:599
RS232C ポート管理
Definition: TnbRs232c.h:84
int GetNumber(void) const
[取得] 数値取得.
Definition: TnbRs232c.h:139
CStr GetPrefix(void) const
[取得] プリフィックス取得
Definition: TnbRs232c.h:154
const CStr & GetPortName(void) const
[取得] ポート名取得.
Definition: TnbRs232c.h:130
RS232Cアクセスクラス
Definition: TnbRs232c.h:72
EParity
パリティ設定値
Definition: TnbRs232c.h:195
EStopBits
ストップビット設定値
Definition: TnbRs232c.h:212
static CStrT Fmt(const TCHAR *lpszFormat,...)
[作成] 書式付き文字列作成
Definition: TnbStr.h:1206
配列型情報管理テンプレート
Definition: TnbVector.h:75
virtual size_t GetSize(void) const
[取得] サイズ取得
Definition: TnbVector.h:368
virtual INDEX Add(const TYP &t)
[追加] 要素一つ追加.
Definition: TnbVector.h:383
TNB Library
Definition: TnbDoxyTitle.txt:2
ULONGLONG BT_ADDR
Bluetooth(CE) アドレス.
Bluetooth(CE) クライアントシリアルアクセスのチャネル情報.