TNB Library
TnbCeBluetooth.h
[詳解]
1#pragma once
13#include "TnbCeBluetoothApi.h"
14#include "TnbStrVector.h"
15#include "TnbRegistryAccessor.h"
16#include "TnbTickCount.h"
17
18
19
20//TNB Library
21namespace TNB{
22
23
24
25#ifdef _TnbDOXYGEN //Document作成用シンボル
34typedef ULONGLONG BT_ADDR;
35
44typedef unsigned short BT_HANDLE;
45#else
46 #define BT_HANDLE unsigned short
47#endif
48
49
50
62{
63public:
64
67 {
68 Zero(m_key);
69 }
70
75 BYTE* Refer(void)
76 {
77 return m_key;
78 }
79
84 const BYTE* Refer(void) const
85 {
86 return m_key;
87 }
88
94 BYTE& operator[](INDEX index)
95 {
96 ASSERT( index < 16 );
97 return m_key[index];
98 }
99
105 const BYTE& operator[](INDEX index) const
106 {
107 ASSERT( index < 16 );
108 return m_key[index];
109 }
110
111private:
112 BYTE m_key[16];
113};
114
115
116
129{
130public:
131
137 {
138 //Limited Discoverable Mode 0x0001,
139 Positioning = 0x0008,
140 Networking = 0x0010,
141 Rendering = 0x0020,
142 Capturing = 0x0040,
143 ObjectTransfer = 0x0080,
144 Audio = 0x0100,
145 Telephony = 0x0200,
146 Information = 0x0400,
147 };
148
153 {
155 Computer = 0x01,
156 Phone = 0x02,
157 Network = 0x03,
158 AV = 0x04,
159 Peripheral = 0x05,
160 Imaging = 0x06,
161 };
162
163
164 //----------------
165
166
172 {
173 m_class.cod = cod;
174 }
175
180 operator DWORD(void) const
181 {
182 return m_class.cod;
183 }
184
189 DWORD GetDeviceClass(void) const
190 {
191 return m_class.cod;
192 }
193
198 DWORD GetServiceClass(void) const
199 {
200 return m_class.serviceClass;
201 }
202
207 void SetServiceClass(DWORD c)
208 {
209 m_class.serviceClass = c;
210 }
211
216 DWORD GetMajorDeviceClass(void) const
217 {
218 return m_class.majorDeviceClass;
219 }
220
226 {
227 m_class.majorDeviceClass = c;
228 }
229
234 LPCTSTR GetMajorDeviceClassName(void) const
235 {
236 switch ( GetMajorDeviceClass() )
237 {
238 case Miscellaneous: return _T("Miscellaneous");
239 case Computer: return _T("Computer");
240 case Phone: return _T("Phone");
241 case Network: return _T("Network");
242 case AV: return _T("Audio/Video");
243 case Peripheral: return _T("Peripheral");
244 case Imaging: return _T("Imaging");
245 }
246 return _T("");
247 }
248
253 DWORD GetMinorDeviceClass(void) const
254 {
255 return m_class.minorDeviceClass;
256 }
257
263 {
264 m_class.minorDeviceClass = c;
265 }
266
271 LPCTSTR GetMinorDeviceClassName(void) const
272 {
273 switch ( GetMajorDeviceClass() )
274 {
275 case Computer: return m_ComputerDeviceClassName();
276 case Phone: return m_PhoneDeviceClassName();
277 case AV: return m_AvDeviceClassName();
278 case Peripheral: return m_PeripheralDeviceClassName();
279 case Imaging: return m_ImagingDeviceClassName();
280 }
281 return _T("");
282 }
283
284private:
289 LPCTSTR m_ComputerDeviceClassName(void) const
290 {
291 ASSERT ( GetMajorDeviceClass() == Computer );
292 switch ( GetMinorDeviceClass() )
293 {
294 case 0: return _T("Unclassified");
295 case 1: return _T("Desktop Computer");
296 case 2: return _T("Server Computer");
297 case 3: return _T("Laptop Computer");
298 case 4: return _T("Handled Computer");
299 case 5: return _T("Palm Computer");
300 case 6: return _T("Wearable Computer");
301 }
302 return _T("");
303 }
308 LPCTSTR m_PhoneDeviceClassName(void) const
309 {
310 ASSERT ( GetMajorDeviceClass() == Phone );
311 switch ( GetMinorDeviceClass() )
312 {
313 case 0: return _T("Unclassified");
314 case 1: return _T("Cellular Phone");
315 case 2: return _T("Cordless Phone");
316 case 3: return _T("Smartphone");
317 case 4: return _T("Modem");
318 case 5: return _T("ISDN Phone");
319 }
320 return _T("");
321 }
326 LPCTSTR m_AvDeviceClassName(void) const
327 {
328 ASSERT ( GetMajorDeviceClass() == AV );
329 switch ( GetMinorDeviceClass() )
330 {
331 case 0: return _T("Unclassified");
332 case 1: return _T("Headset");
333 case 2: return _T("Handsfree");
334 case 4: return _T("Microphone");
335 case 5: return _T("Loudspeaker");
336 case 6: return _T("Headphone");
337 case 7: return _T("Portable Audio");
338 case 8: return _T("Car Audio");
339 case 9: return _T("Set Top Box");
340 case 10: return _T("Hifi Audio");
341 case 11: return _T("VCR");
342 case 12: return _T("Video Camera");
343 case 13: return _T("Camcoder");
344 case 14: return _T("Video Monitor");
345 case 15: return _T("Video Display & Loundspeaker");
346 case 16: return _T("Video Conferencing");
347 case 18: return _T("Gaiming Toy");
348 }
349 return _T("");
350 }
355 LPCTSTR m_PeripheralDeviceClassName(void) const
356 {
357 ASSERT ( GetMajorDeviceClass() == Peripheral );
358 DWORD c = GetMinorDeviceClass();
359 switch ( c & 0x3F )
360 {
361 case 0: break;
362 case 1: return _T("Joystick");
363 case 2: return _T("Gamepad");
364 case 3: break;//return _T("Remote Control");
365 case 4: return _T("Sensing Device");
366 case 5: return _T("Digitizer Tablet");
367 case 6: return _T("Card Reader");
368 }
369 switch ( c & 0xC0 )
370 {
371 case 0x00:/*Unclassified*/ return _T("Unclassified");
372 case 0x40:/*Keyboard*/ return _T("Keyboard");
373 case 0x80:/*Pointer*/ return _T("Pointer");
374 case 0xC0:/*Combo*/ return _T("Combo Device");
375 }
376 return _T("");
377 }
382 LPCTSTR m_ImagingDeviceClassName(void) const
383 {
384 ASSERT ( GetMajorDeviceClass() == Imaging );
385 #if 0
386 switch ( GetMinorDeviceClass() )
387 {
388 #define RX_COD_MINOR_IMAJING_DISPLAY_MASK 0x10
389 #define RX_COD_MINOR_IMAJING_CAMERA_MASK 0x20
390 #define RX_COD_MINOR_IMAJING_SCANNER_MASK 0x40
391 #define RX_COD_MINOR_IMAJING_PRINTER_MASK 0x80
392 }
393 #endif
394 return _T("");
395 }
396 //
397 union
398 {
399 DWORD cod;
400 struct
401 {
402 DWORD formatType :2;
405 DWORD serviceClass :11;
406 DWORD padding :8;
407 };
408 } m_class;
409};
410
411
412
424{
425public:
426
435 struct TValue
436 {
437 SDP_TYPE type;
438 SDP_SPECIFICTYPE spec;
439 union
440 {
441 SDP_LARGE_INTEGER_16 int128;
442 SDP_ULARGE_INTEGER_16 uint128;
443 GUID uuid128;
444 DWORD uuid32;
445 WORD uuid16;
446 LONGLONG int64;
447 ULONGLONG uint64;
448 LONG int32;
449 DWORD uint32;
450 SHORT int16;
451 WORD uint16;
452 CHAR int8;
453 BYTE uint8;
455 };
457
463 TValue(SDP_TYPE t = SDP_TYPE_NIL, SDP_SPECIFICTYPE s = SDP_ST_NONE) : type(t), spec(s)
464 {
465 Zero(int128);
466 }
467
473 CStr ToString(CStr* pType = NULL) const
474 {
475 CStr value;
476 CStr typeName;
477 switch ( type )
478 {
479 case SDP_TYPE_NIL:
480 break;
481 case SDP_TYPE_UINT:
482 case SDP_TYPE_INT:
483 case SDP_TYPE_UUID:
484 switch ( spec )
485 {
486 case SDP_ST_UINT8:
487 value.Format(_T("0x%02X"), uint8);
488 typeName = _T("UINT8");
489 break;
490 case SDP_ST_UINT16:
491 value.Format(_T("0x%04X"), uint16);
492 typeName = _T("UINT16");
493 break;
494 case SDP_ST_UINT32:
495 value.Format(_T("0x%08X"), uint32);
496 typeName = _T("UINT32");
497 break;
498 case SDP_ST_UINT64:
499 value.Format(_T("0x%16I64X"), uint64);
500 typeName = _T("UINT64");
501 break;
502 case SDP_ST_UINT128:
503 value.Format(_T("0x%16I64X%16I64X"), uint128.HighPart, uint128.LowPart);
504 typeName = _T("UINT128");
505 break;
506 case SDP_ST_INT8:
507 value.Format(_T("%d"), int8);
508 typeName = _T("INT8");
509 break;
510 case SDP_ST_INT16:
511 value.Format(_T("%d"), int16);
512 typeName = _T("INT16");
513 break;
514 case SDP_ST_INT32:
515 value.Format(_T("%d"), int32);
516 typeName = _T("INT32");
517 break;
518 case SDP_ST_INT64:
519 value.Format(_T("%16I64d\n"), int64);
520 typeName = _T("INT64");
521 break;
522 case SDP_ST_INT128:
523 value.Format(_T("0x%16I64X%16I64X"), int128.HighPart, int128.LowPart);
524 typeName = _T("INT128");
525 break;
526 case SDP_ST_UUID16:
527 value.Format(_T("0x%04X"), uint16);
528 typeName = _T("UUID16");
529 break;
530 case SDP_ST_UUID32:
531 value.Format(_T("0x%08X"), uint32);
532 typeName = _T("UUID32");
533 break;
534 case SDP_ST_UUID128:
535 value.Format(_T("%08X-%04X-%04X-%02X%02X%02X%02X%02X%02X%02X%02X")
536 , uuid128.Data1, uuid128.Data2, uuid128.Data3
537 , uuid128.Data4[0], uuid128.Data4[1], uuid128.Data4[2], uuid128.Data4[3]
538 , uuid128.Data4[4], uuid128.Data4[5], uuid128.Data4[6], uuid128.Data4[7]);
539 typeName = _T("UUID128");
540 break;
541 default:
542 ASSERT( false );
543 break;
544 }
545 break;
546 case SDP_TYPE_BOOLEAN:
547 value = booleanVal ? _T("true") : _T("false");
548 typeName = _T("BOOL");
549 break;
550 case SDP_TYPE_STRING:
551 value = str;
552 typeName = _T("STRING");
553 break;
554 case SDP_TYPE_URL:
555 value = str;
556 typeName = _T("URL");
557 break;
558 default:
559 ASSERT( false );
560 break;
561 }
562 if ( pType != NULL )
563 {
564 *pType = typeName;
565 }
566 return value;
567 }
568 };
569
574
575
576 //----------------------------
577
578
580 CBluetoothServiceAttribute(void) : m_ppSdpRecords(NULL), m_numRecords(0), m_lastResult(S_OK)
581 {
582 ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
583 }
584
587 {
588 Free();
589 }
590
595 void Free(void)
596 {
597 if ( m_ppSdpRecords != NULL )
598 {
599 loop ( i, m_numRecords )
600 {
601 m_ppSdpRecords[i]->Release();
602 }
603 BYTE* B = reinterpret_cast<BYTE*>(m_ppSdpRecords);
604 delete[] B;
605 m_ppSdpRecords = NULL;
606 m_numRecords = 0;
607 }
608 }
609
616 bool IsValid(void) const
617 {
618 return m_ppSdpRecords != NULL;
619 }
620
625 size_t GetRecordCount(void) const
626 {
627 return m_numRecords;
628 }
629
634 HRESULT GetLastResult(void) const
635 {
636 return m_lastResult;
637 }
638
647 bool Analyze(size_t size, LPCVOID lpRawData)
648 {
649 CWorkMem raw;
650 raw.Reset(size, static_cast<const BYTE*>(lpRawData));
651 Free();
652 ISdpStream* pIStream = NULL;
653 HRESULT hr = ::CoCreateInstance(__uuidof(SdpStream), NULL, CLSCTX_INPROC_SERVER
654 , __uuidof(ISdpStream), reinterpret_cast<LPVOID*>(&pIStream));
655 if ( SUCCEEDED(hr) )
656 {
657 ULONG ulError;
658 hr = pIStream->Validate(raw.Ref(), raw.GetSize(), &ulError);
659 if ( SUCCEEDED(hr) )
660 {
661 hr = pIStream->VerifySequenceOf(raw.Ref(), raw.GetSize(), SDP_TYPE_SEQUENCE, NULL, &m_numRecords);
662 if ( SUCCEEDED(hr) )
663 {
664 ASSERT( m_numRecords > 0 );
665 BYTE* B = new BYTE[sizeof(ISdpRecord*) * m_numRecords];
666 m_ppSdpRecords = reinterpret_cast<ISdpRecord**>(B);
667 ASSERT( m_ppSdpRecords != NULL );
668 hr = pIStream->RetrieveRecords(raw.Ref(), raw.GetSize(), m_ppSdpRecords, &m_numRecords);
669 }
670 }
671 pIStream->Release();
672 pIStream = NULL;
673 }
674 if ( ! m_Res(hr) )
675 {
676 Free();
677 return false;
678 }
679 if ( m_numRecords == 0 )
680 {
681 return m_Res(E_FAIL);
682 }
683 return SearchRecord(0);
684 }
685
695 bool SearchRecord(INDEX record)
696 {
697 if ( record < m_numRecords )
698 {
699 return m_CheckRecord(m_ppSdpRecords[record]);
700 }
701 m_attrIds.RemoveAll();
702 m_attrDetails.RemoveAll();
703 return false;
704 }
705
712 bool HasAttribute(WORD attributeId) const
713 {
714 return m_attrIds.Find(attributeId) != INVALID_INDEX;
715 }
716
721 const TIdsList& GetAttributeIdList(void) const
722 {
723 return m_attrIds;
724 }
725
755 const TValuesList& GetAttributeData(WORD attributeId) const
756 {
757 INDEX f = m_attrIds.Find(attributeId);
758 if ( f != INVALID_INDEX )
759 {
760 return m_attrDetails[f];
761 }
762 return m_dummy;
763 }
764
771 {
772 CStrVector vs;
773 loop ( i, m_attrDetails )
774 {
775 const TValuesList& list = m_attrDetails[i];
776 loop ( i, list )
777 {
778 SDP_TYPE s = list[i].type;
779 if ( s == SDP_TYPE_STRING || s == SDP_TYPE_URL )
780 {
781 vs.Add(CStr(list[i].str));
782 }
783 }
784 }
785 return vs;
786 }
787
788private:
789 TIdsList m_attrIds;
790 CVectorT<TValuesList> m_attrDetails;
791 TValuesList m_dummy;
792 ISdpRecord** m_ppSdpRecords;
793 ULONG m_numRecords;
794 HRESULT m_lastResult;
796 bool m_CheckRecord(ISdpRecord* pRecord)
797 {
798 WORD* pList = NULL;
799 ULONG listSize = 0;
800 m_attrIds.RemoveAll();
801 m_attrDetails.RemoveAll();
802 HRESULT hr = pRecord->GetAttributeList(&pList, &listSize);
803 if ( SUCCEEDED(hr) )
804 {
805 m_attrIds.SetSize(listSize);
806 m_attrDetails.SetSize(listSize);
807 loop ( i, listSize )
808 {
809 BYTE* pStream = NULL;
810 ULONG size = 0;
811 WORD aid = pList[i];
812 m_attrIds[i] = aid;
813 hr = pRecord->GetAttributeAsStream(aid, &pStream, &size);
814 if ( SUCCEEDED(hr) )
815 {
816 TTRACE1("Attrib ID %04X\n", aid);
817 hr = m_CheckSub(m_attrDetails[i], pStream, size);
818 }
819 if ( pStream != NULL )
820 {
821 ::CoTaskMemFree(pStream);
822 }
823 if ( ! SUCCEEDED(hr) )
824 {
825 break;
826 }
827 }
828 }
829 if ( pList != NULL )
830 {
831 ::CoTaskMemFree(pList);
832 }
833 return m_Res(hr);
834 }
836 void m_CheckSubUint(TValue& _val, SDP_SPECIFICTYPE specType, BYTE* pSubElement, ISdpStream* pSdpStream)
837 {
838 switch ( specType )
839 {
840 case SDP_ST_UINT8:
841 _val.uint8 = *pSubElement;
842 break;
843 case SDP_ST_UINT16:
844 pSdpStream->RetrieveUint16(pSubElement, &_val.uint16);
845 _val.uint16 = SwapEndian(_val.uint16);
846 break;
847 case SDP_ST_UINT32:
848 pSdpStream->RetrieveUint32(pSubElement, &_val.uint32);
849 _val.uint32 = SwapEndian(_val.uint32);
850 break;
851 case SDP_ST_UINT64:
852 pSdpStream->RetrieveUint64(pSubElement, &_val.uint64);
853 _val.uint64 = SwapEndian(_val.uint64);
854 break;
855 case SDP_ST_UINT128:
856 pSdpStream->RetrieveUint128(pSubElement, &_val.uint128);
857 _val.uint128.LowPart = SwapEndian(_val.uint128.LowPart);
858 _val.uint128.HighPart = SwapEndian(_val.uint128.HighPart);
859 break;
860 default:
861 ASSERT( false );
862 break;
863 }
864 }
866 void m_CheckSubInt(TValue& _val, SDP_SPECIFICTYPE specType, BYTE* pSubElement, ISdpStream* pSdpStream)
867 {
868 switch ( specType )
869 {
870 case SDP_ST_INT8:
871 _val.int8 = *pSubElement;
872 break;
873 case SDP_ST_INT16:
874 pSdpStream->RetrieveInt16(pSubElement, &_val.int16);
875 _val.int16 = SwapEndian(static_cast<WORD>(_val.int16));
876 break;
877 case SDP_ST_INT32:
878 pSdpStream->RetrieveInt32(pSubElement, &_val.int32);
879 _val.int32 = SwapEndian(static_cast<DWORD>(_val.int32));
880 break;
881 case SDP_ST_INT64:
882 pSdpStream->RetrieveInt64(pSubElement, &_val.int64);
883 _val.int64 = SwapEndian(static_cast<ULONGLONG>(_val.int64));
884 break;
885 case SDP_ST_INT128:
886 pSdpStream->RetrieveInt128(pSubElement, &_val.int128);
887 _val.int128.LowPart = SwapEndian(static_cast<ULONGLONG>(_val.int128.LowPart));
888 _val.int128.HighPart = SwapEndian(static_cast<ULONGLONG>(_val.int128.HighPart));
889 break;
890 default:
891 ASSERT( false );
892 break;
893 }
894 }
896 void m_CheckSubUuid(TValue& _val, SDP_SPECIFICTYPE specType, BYTE* pSubElement, ISdpStream* pSdpStream)
897 {
898 switch ( specType )
899 {
900 case SDP_ST_UUID16:
901 pSdpStream->RetrieveUint16(pSubElement, &_val.uuid16);
902 _val.uuid16 = SwapEndian(_val.uuid16);
903 break;
904 case SDP_ST_UUID32:
905 pSdpStream->RetrieveUint32(pSubElement, &_val.uuid32);
906 _val.uuid32 = SwapEndian(_val.uuid32);
907 break;
908 case SDP_ST_UUID128:
909 pSdpStream->RetrieveUuid128(pSubElement, &_val.uuid128);
910 _val.uuid128.Data1 = SwapEndian(_val.uuid128.Data1);
911 _val.uuid128.Data2 = SwapEndian(_val.uuid128.Data2);
912 _val.uuid128.Data3 = SwapEndian(_val.uuid128.Data3);
913 break;
914 default:
915 ASSERT( false );
916 break;
917 }
918 }
920 bool m_CheckSub(TValuesList& _list, BYTE* pStream, ULONG size)
921 {
922 ISdpStream* pSdpStream = NULL;
923 if ( ! m_LoadAndValidate(&pSdpStream, &pStream, &size) )
924 {
925 return false;
926 }
927 HRESULT hr = E_FAIL;
928 while ( size > 0 )
929 {
930 SDP_TYPE type;
931 SDP_SPECIFICTYPE specType;
932 ULONG recordSize;
933 ULONG storageSize;
934 BYTE* pSubElement = NULL;
935 hr = pSdpStream->RetrieveElementInfo(pStream, &type, &specType, &recordSize, &storageSize, &pSubElement);
936 ASSERT( SUCCEEDED(hr) );
937 if ( type == SDP_TYPE_SEQUENCE || type == SDP_TYPE_ALTERNATIVE )
938 {
939 if ( ! m_CheckSub(_list, pSubElement, recordSize) )
940 {
941 return false;
942 }
943 }
944 else
945 {
946 TValue val(type, specType);
947 switch ( type )
948 {
949 case SDP_TYPE_NIL:
950 break;
951 case SDP_TYPE_UINT:
952 m_CheckSubUint(val, specType, pSubElement, pSdpStream);
953 break;
954 case SDP_TYPE_INT:
955 m_CheckSubInt(val, specType, pSubElement, pSdpStream);
956 break;
957 case SDP_TYPE_UUID:
958 m_CheckSubUuid(val, specType, pSubElement, pSdpStream);
959 break;
960 case SDP_TYPE_BOOLEAN:
961 val.booleanVal = ((*pSubElement) != 0);
962 break;
963 case SDP_TYPE_STRING:
964 val.str.SetFromLeft(reinterpret_cast<LPCSTR>(pSubElement), recordSize);
965 break;
966 case SDP_TYPE_URL:
967 val.str.SetFromLeft(reinterpret_cast<LPCSTR>(pSubElement), recordSize);
968 break;
969 default:
970 val.type = SDP_TYPE_NIL;
971 break;
972 }
973 if ( val.type != SDP_TYPE_NIL )
974 {
975 #ifdef _DEBUG
976 CStr type;
977 CStr va = val.ToString(&type);
978 TTRACE2(" %s: %s\n", type, va);
979 #endif
980 _list.Add(val);
981 }
982 }
983 recordSize += 1 + storageSize;
984 pStream += recordSize;
985 size -= recordSize;
986 }
987 pSdpStream->Release();
988 return m_Res(hr);
989 }
991 bool m_LoadAndValidate(ISdpStream **ppSdpStream, BYTE **ppStream, ULONG *pSize)
992 {
993 HRESULT hr = ::CoCreateInstance(__uuidof(SdpStream), NULL, CLSCTX_INPROC_SERVER
994 , __uuidof(ISdpStream), reinterpret_cast<LPVOID*>(ppSdpStream));
995 if ( SUCCEEDED(hr) )
996 {
997 ULONG_PTR sdpError;
998 ASSERT( *ppSdpStream != NULL );
999 hr = (*ppSdpStream)->Validate(*ppStream, *pSize, &sdpError);
1000 }
1001 return m_Res(hr);
1002 }
1004 bool m_Res(HRESULT hr)
1005 {
1006 m_lastResult = hr;
1007 return SUCCEEDED(hr);
1008 }
1009};
1010
1011
1012
1024{
1025public:
1026
1031 CBluetoothAddress(BT_ADDR btAddr = 0) : m_btAddr(btAddr)
1032 {
1033 }
1034
1040 {
1041 m_btAddr = other.m_btAddr;
1042 }
1043
1050 {
1051 m_btAddr = other.m_btAddr;
1052 return *this;
1053 }
1054
1061 bool IsValid(void) const
1062 {
1063 return m_btAddr != 0;
1064 }
1065
1070 operator const BT_ADDR&(void) const
1071 {
1072 return m_btAddr;
1073 }
1074
1079 const BT_ADDR& GetAddress(void) const
1080 {
1081 return m_btAddr;
1082 }
1083
1090 {
1091 CStr str;
1092 loop ( i, 6 )
1093 {
1094 if ( i != 0 )
1095 {
1096 str += _T(":");
1097 }
1098 str += CStr::Fmt(_T("%02X"), (m_btAddr >> ((5 - i) * 8)) & 0xFF);
1099 }
1100 return str;
1101 }
1102
1110 bool SetAddressString(LPCTSTR lpszAddress)
1111 {
1112 BT_ADDR a = 0;
1113 if ( STRLIB::GetLen(lpszAddress) == 6 * 2 + 5 )
1114 {
1115 loop ( i, 5 )
1116 {
1117 if ( lpszAddress[i * 3 + 2] != ':' )
1118 {
1119 return false;
1120 }
1121 }
1122 loop ( i, 6 )
1123 {
1124 LONGLONG r = m_ToInt(&lpszAddress[i * 3]);
1125 if ( r < 0 || r > 255 )
1126 {
1127 return false;
1128 }
1129 a += r << ((5 - i) * 8);
1130 }
1131 m_btAddr = a;
1132 return true;
1133 }
1134 return false;
1135 }
1136
1137protected:
1139
1140private:
1141 // int化
1142 int m_ToInt(LPCTSTR lpsz) const
1143 {
1144 int i1 = STRLIB::HexCharToInt(lpsz[0]);
1145 int i2 = STRLIB::HexCharToInt(lpsz[1]);
1146 if ( i1 >= 0 && i2 >= 0 )
1147 {
1148 return i1 << 4 | i2;
1149 }
1150 return -1;
1151 }
1152};
1153
1154
1155
1166class CBluetoothLocal : private CBluetoothApi
1167{
1168 DEFSUPER(CBluetoothApi);
1169public:
1170
1173 {
1174 }
1175
1183 {
1184 BT_ADDR ba;
1185 bool r = m_Ret(BthReadLocalAddr(&ba));
1186 if ( r )
1187 {
1188 _addr = ba;
1189 }
1190 return r;
1191 }
1192
1198 CStr GetName(void) const
1199 {
1200 CRegistryAccessor reg(HKEY_LOCAL_MACHINE, KEY_QUERY_VALUE);
1201 return reg[_T("Ident")].QueryString(_T("Name"));
1202 }
1203
1210 bool SetName(LPCTSTR lpszName)
1211 {
1212 CRegistryAccessor reg(HKEY_LOCAL_MACHINE);
1213 return reg[_T("Ident")].WriteString(_T("Name"), lpszName);
1214 }
1215
1222 bool GetClass(CBluetoothClass& _class) const
1223 {
1224 UINT cl = 0;
1225 bool r = m_Ret(BthReadCOD(&cl));
1226 _class = cl;
1227 return r;
1228 }
1229
1236 bool SetClass(const CBluetoothClass& clas)
1237 {
1238 UINT cl = clas.GetDeviceClass();
1239 return m_Ret(BthWriteCOD(cl));
1240 }
1241
1248 bool EnableAuthentication(bool isEnable)
1249 {
1250 return m_Ret(BthWriteAuthenticationEnable(isEnable ? 1 : 0));
1251 }
1252
1259 bool IsEnabledAuthentication(bool& _isEnabled) const
1260 {
1261 BYTE ae;
1262 bool r = m_Ret(BthReadAuthenticationEnable(&ae));
1263 if ( r )
1264 {
1265 _isEnabled = (ae != 0);
1266 }
1267 return r;
1268 }
1269
1272 {
1278 };
1279
1286 bool GetMode(EMode& _mode) const
1287 {
1288 DWORD mode = 0;
1289 BYTE mask = 0;
1290 int r = BthGetMode(&mode);
1291 if ( r == ERROR_SUCCESS )
1292 {
1293 if ( mode == BTH_POWER_OFF )
1294 {
1295 _mode = PowerOff;
1296 }
1297 else
1298 {
1299 r = BthReadScanEnableMask(&mask);
1300 if ( r == ERROR_SUCCESS )
1301 {
1302 ASSERT( mask >= 0 && mask <= 3 );
1303 _mode = static_cast<EMode>(mask);
1304 }
1305 }
1306 }
1307 return m_Ret(r);
1308 }
1309
1318 bool SetMode(EMode mode, DWORD timeout = 3000)
1319 {
1320 int e = ERROR_SUCCESS;
1321 if ( mode == PowerOff )
1322 {
1323 e = BthSetMode(BTH_POWER_OFF);
1324 }
1325 else
1326 {
1327 int status;
1328 e = BthGetHardwareStatus(&status);
1329 if ( e == ERROR_SUCCESS && status == HCI_HARDWARE_NOT_PRESENT )
1330 {
1331 e = ERROR_DEVICE_NOT_CONNECTED;
1332 }
1333 if ( e == ERROR_SUCCESS )
1334 {
1335 e = BthSetMode(BTH_DISCOVERABLE);
1336 }
1337 if ( e == ERROR_SUCCESS )
1338 {
1339 e = ERROR_TIMEOUT;
1340 CTickCount tick;
1341 do
1342 {
1343 int e1 = BthGetHardwareStatus(&status);
1344 if ( e1 != ERROR_SUCCESS )
1345 {
1346 e = e1;
1347 break;
1348 }
1349 if ( status == HCI_HARDWARE_RUNNING )
1350 {
1351 e = BthWriteScanEnableMask(mode);
1352 break;
1353 }
1354 ::Sleep(10);
1355 }
1356 while( ! tick.IsPassed(timeout) );
1357 }
1358 }
1359 return m_Ret(e);
1360 }
1361
1368 bool GetPageTimeout(DWORD& _timeout) const
1369 {
1370 WORD ot = 0;
1371 bool r = m_Ret(BthReadPageTimeout(&ot));
1372 if ( r )
1373 {
1374 _timeout = ot;
1375 }
1376 return r;
1377 }
1378
1385 bool SetPageTimeout(DWORD timeout)
1386 {
1387 WORD ot = static_cast<WORD>(timeout);
1388 return m_Ret(BthWritePageTimeout(ot));
1389 }
1390
1398 bool GetPageTimeoutMs(DWORD& _timeout) const
1399 {
1400 DWORD v = 0;
1401 bool r = GetPageTimeout(v);
1402 if ( r )
1403 {
1404 double d = v;
1405 _timeout = static_cast<DWORD>(d * .625);
1406 }
1407 return r;
1408 }
1409
1417 bool SetPageTimeoutMs(DWORD timeout)
1418 {
1419 double d = static_cast<double>(timeout);
1420 return SetPageTimeout(static_cast<DWORD>(d / .625));
1421 }
1422
1435 int GetStatus(void) const
1436 {
1437 int s = HCI_HARDWARE_UNKNOWN;
1438 int e = BthGetHardwareStatus(&s);
1439 if ( e == ERROR_SUCCESS && s == HCI_HARDWARE_UNKNOWN )
1440 {
1441 e = ERROR_SERVICE_NOT_ACTIVE;
1442 }
1443 ::SetLastError(e);
1444 return s;
1445 }
1446
1453 {
1454 return m_Ret(BthTerminateIdleConnections());
1455 }
1456
1466 {
1467 BT_ADDR ba = addr;
1468 return m_Ret(BthSetInquiryFilter(&ba));
1469 }
1470
1479 {
1480 return m_Ret(BthClearInquiryFilter());
1481 }
1482
1489 CVectorT<BthInquiryResult> Inquiry(DWORD timeout = 1000) const
1490 {
1492 const UINT LAP = 0x9e8b33; // GIAC_LAP
1493 DWORD length = timeout / 1280;
1494 if ( length == 0 )
1495 {
1496 length = 1;
1497 }
1498 if ( length > 0x30 )
1499 {
1500 length = 0x30;
1501 }
1502 UINT got = 0;
1504 bool r = m_Ret(BthPerformInquiry(LAP, static_cast<BYTE>(length), 0, 256, &got, ir));
1505 if ( r )
1506 {
1507 vb.CopyElements(got, ir);
1508 }
1509 else
1510 {
1511 vb.Invalid();
1512 }
1513 return vb;
1514 }
1515};
1516
1517
1518
1534class CBluetoothDevice : public CBluetoothAddress, private CBluetoothApi
1535{
1536 DEFSUPER(CBluetoothAddress);
1537public:
1538
1543 CBluetoothDevice(const BT_ADDR& btAddr = 0) : _super(btAddr)
1544 {
1545 }
1546
1552 {
1553 if ( BthGetAddress(btHandle, &m_btAddr) != ERROR_SUCCESS )
1554 {
1555 m_btAddr = 0;
1556 }
1557 }
1558
1564 {
1565 m_btAddr = other.m_btAddr;
1566 }
1567
1574 {
1575 m_btAddr = other.m_btAddr;
1576 return *this;
1577 }
1578
1581 {
1582 BYTE version;
1586 };
1587
1594 bool GetVersion(TVersion& _version)
1595 {
1597 int e = BthReadRemoteVersion(&m_btAddr,
1598 &_version.version, &_version.subVersion, &_version.manufacturer, &_version.features);
1599 if ( h != NULL )
1600 {
1601 CloseConnection(h);
1602 }
1603 return m_Ret(e);
1604 }
1605
1612 bool IsExist(void) const
1613 {
1614 return ! GetName().IsEmpty();
1615 }
1616
1624 bool GetClass(CBluetoothClass& _class) const
1625 {
1626 UINT cl = 0;
1627 BT_ADDR ba = m_btAddr;
1628 bool r = m_Ret(BthGetRemoteCOD(&ba, &cl));
1629 _class = cl;
1630 return r;
1631 }
1632
1641 {
1642 bool r = GetClass(_class);
1643 if ( ! r && ::GetLastError() == ERROR_NOT_FOUND )
1644 {
1646 r = GetClass(_class);
1647 CloseConnection(h);
1648 }
1649 return r;
1650 }
1651
1657 CStr GetName(void) const
1658 {
1659 BT_ADDR ba = m_btAddr;
1660 CUnicode str;
1661 const int len = 1024;
1662 UINT requ = 0;
1663 bool r = m_Ret(BthRemoteNameQuery(&ba, len, &requ, str.GetBuffer(len)));
1664 str.ReleaseBuffer();
1665 return r ? str : _T("");
1666 }
1667
1673 bool Authenticate(void) const
1674 {
1675 BT_ADDR ba = m_btAddr;
1676 return m_Ret(BthAuthenticate(&ba));
1677 }
1678
1691 {
1692 BT_HANDLE h = NULL;
1693 if ( ! m_Ret(BthCreateSCOConnection(&m_btAddr, &h)) )
1694 {
1695 return NULL;
1696 }
1697 return h;
1698 }
1699
1712 {
1713 BT_HANDLE h = NULL;
1714 if ( ! m_Ret(BthCreateACLConnection(&m_btAddr, &h)) )
1715 {
1716 return NULL;
1717 }
1718 return h;
1719 }
1720
1723 {
1727 PARK
1729
1737 bool GetCurrentMode(EMode& _mode) const
1738 {
1739 BT_ADDR ba = m_btAddr;
1740 BYTE m = 0;
1741 bool r = m_Ret(BthGetCurrentMode(&ba, &m));
1742 _mode = static_cast<EMode>(m);
1743 return r;
1744 }
1745
1755 bool EnterHoldMode(WORD& _interval, WORD hold_mode_max, WORD hold_mode_min)
1756 {
1757 return m_Ret(BthEnterHoldMode(&m_btAddr, hold_mode_max, hold_mode_min, &_interval));
1758 }
1759
1769 bool EnterParkMode(WORD& _interval, WORD beacon_max, WORD beacon_min)
1770 {
1771 return m_Ret(BthEnterParkMode(&m_btAddr, beacon_max, beacon_min, &_interval));
1772 }
1773
1785 bool EnterSniffMode(WORD& _interval, WORD sniff_mode_max, WORD sniff_mode_min, WORD sniff_attempt, WORD sniff_timeout)
1786 {
1787 return m_Ret(BthEnterSniffMode(&m_btAddr, sniff_mode_max, sniff_mode_min, sniff_attempt, sniff_timeout, &_interval));
1788 }
1789
1795 bool ExitParkMode(void)
1796 {
1797 return m_Ret(BthExitParkMode(&m_btAddr));
1798 }
1799
1805 bool ExitSniffMode(void)
1806 {
1807 return m_Ret(BthExitSniffMode(&m_btAddr));
1808 }
1809
1818 {
1819 BT_ADDR ba = m_btAddr;
1820 return m_Ret(BthGetLinkKey(&ba, _key.Refer()));
1821 }
1822
1829 {
1830 BT_ADDR ba = m_btAddr;
1831 return m_Ret(BthRefusePINRequest(&ba));
1832 }
1833
1841 bool PairRequest(LPCTSTR lpszPin)
1842 {
1843 CAscii pin = lpszPin;
1844 int len = pin.GetLength();
1845 if ( len == 0 )
1846 {
1847 BYTE b = 0;
1848 return m_Ret(BthPairRequest(&m_btAddr, 1, &b));
1849 }
1850 return m_Ret(BthPairRequest(&m_btAddr, len, reinterpret_cast<BYTE*>(pin.GetBuffer())));
1851 }
1852
1859 bool RevokeLinkKey(void)
1860 {
1861 return m_Ret(BthRevokeLinkKey(&m_btAddr));
1862 }
1863
1870 bool RevokePin(void)
1871 {
1872 return m_Ret(BthRevokePIN(&m_btAddr));
1873 }
1874
1882 bool SetEncryption(bool isEnable)
1883 {
1884 return m_Ret(BthSetEncryption(&m_btAddr, isEnable ? 1 : 0));
1885 }
1886
1895 {
1896 CBluetoothLinkKey k = key;
1897 return m_Ret(BthSetLinkKey(&m_btAddr, k.Refer()));
1898 }
1899
1907 bool SetPin(LPCTSTR lpszPin)
1908 {
1909 CAscii pin = lpszPin;
1910 int len = pin.GetLength();
1911 if ( len == 0 )
1912 {
1913 BYTE b = 0;
1914 return m_Ret(BthSetPIN(&m_btAddr, 1, &b));
1915 }
1916 return m_Ret(BthSetPIN(&m_btAddr, len, reinterpret_cast<BYTE*>(pin.GetBuffer())));
1917 }
1918
1930 bool HasService(CWorkMem& _raw, WORD uuid16) const
1931 {
1932 SdpAttributeRange range = { 0, 0x200 };
1933 if ( m_QueryService(_raw, range, uuid16) )
1934 {
1935 return true;
1936 }
1937 return false;
1938 }
1939
1951 bool HasService(CBluetoothServiceAttribute& _attr, WORD uuid16) const
1952 {
1953 CWorkMem sdp;
1954 if ( HasService(sdp, uuid16) )
1955 {
1956 _attr.Analyze(sdp.GetSize(), sdp.Ref());
1957 return true;
1958 }
1959 return false;
1960 }
1961
1970 bool HasService(WORD uuid16) const
1971 {
1972 CWorkMem sdp;
1973 return HasService(sdp, uuid16);
1974 }
1975
1976#if 0
1983 bool GetServicesList(CWorkMemT<WORD>& _list) const
1984 {
1985 CTickCount tick;
1986 CWorkMemT<WORD> v(0xFF);
1987 INDEX d = 0;
1988 loop ( i, 0x30 )
1989 {
1990 if ( HasService(i + 0x1100) )
1991 {
1992 v[d++] = i + 0x1100;
1993 }
1994 }
1995 loop ( i, 0x20 )
1996 {
1997 if ( HasService(i + 0x1200) )
1998 {
1999 v[d++] = i + 0x1200;
2000 }
2001 }
2002 _list.Reset(d, v.Ref());
2004 return true;
2005 }
2006#endif
2007
2036 bool GetServicesList(CWorkMemT<WORD>& _list, size_t baseListLength, const WORD* pBaseList) const
2037 {
2038 if ( baseListLength == 0 || pBaseList == NULL )
2039 {
2040// return GetServicesList(_list);
2041 return false;
2042 }
2043 ASSERT ( ! ::IsBadReadPtr(pBaseList, sizeof(WORD) * baseListLength) );
2044 CWorkMemT<WORD> v(baseListLength);
2045 INDEX d = 0;
2046 loop ( i, baseListLength )
2047 {
2048 if ( HasService(pBaseList[i]) )
2049 {
2050 v[d++] = pBaseList[i];
2051 }
2052 }
2053 _list.Reset(d, v.Ref());
2054 return true;
2055 }
2056
2063 static bool CloseConnection(BT_HANDLE handle)
2064 {
2065 CBluetoothApi api;
2066 int r = api.BthCloseConnection(handle);
2067 ::SetLastError(r);
2068 return r == ERROR_SUCCESS;
2069 }
2070
2078 {
2079 CBluetoothApi api;
2080 const int WORKLEN = 1000;
2082 int len = 0;
2083 int r = api.BthGetBasebandConnections(WORKLEN, w.Ref(), &len);
2084 if ( r == ERROR_SUCCESS )
2085 {
2086 _connections.Reset(len, w.Ref());
2087 return true;
2088 }
2089 return false;
2090 }
2091
2098 static CStr ServiceToString(WORD serviceUuid16)
2099 {
2100 CStr s;
2101 switch ( serviceUuid16 )
2102 {
2103 case 0x0001:// SDP
2104 s = _T("SDP");
2105 break;
2106 case 0x0003:// RFCOMM
2107 s = _T("RFCOMM");
2108 break;
2109 case 0x0011:// HIDP
2110 s = _T("HIDP");
2111 break;
2112 case 0x0100:// L2CAP
2113 s = _T("L2CAP");
2114 break;
2115 case PublicBrowseGroupServiceClassID_UUID16:
2116 s = _T("Public Browse Group");
2117 break;
2118 case SerialPortServiceClassID_UUID16:
2119 s = _T("Serial Port");
2120 break;
2121 case LANAccessUsingPPPServiceClassID_UUID16:
2122 s = _T("LAN Access Using PPP");
2123 break;
2124 case DialupNetworkingServiceClassID_UUID16:
2125 s = _T("Dialup Net working");
2126 break;
2127 case IrMCSyncServiceClassID_UUID16:
2128 s = _T("IrMC Sync");
2129 break;
2130 case OBEXObjectPushServiceClassID_UUID16:
2131 s = _T("OBEX Object Push");
2132 break;
2133 case OBEXFileTransferServiceClassID_UUID16:
2134 s = _T("OBEX File Transfer");
2135 break;
2136 case IrMcSyncCommandServiceClassID_UUID16:
2137 s = _T("IrMc Sync Command");
2138 break;
2139 case HeadsetServiceClassID_UUID16:
2140 s = _T("Headset");
2141 break;
2142 case CordlessServiceClassID_UUID16:
2143 s = _T("Cordless");
2144 break;
2145 case AudioSourceServiceClassID_UUID16:
2146 s = _T("Audio Source");
2147 break;
2148 case AudioSinkServiceClassID_UUID16:
2149 s = _T("Audio Sink");
2150 break;
2151 case AV_RemoteControlTargetServiceClassID_UUID16:
2152 s = _T("A/V Remote Control Target");
2153 break;
2154 case AdvancedAudioDistributionServiceClassID_UUID16:
2155 s = _T("Advanced Audio Distribution");
2156 break;
2157 case AV_RemoteControlServiceClassID_UUID16:
2158 s = _T("A/V Remote Control");
2159 break;
2160 case VideoConferencingServiceClassID_UUID16:
2161 s = _T("Video Conferencing");
2162 break;
2163 case IntercomServiceClassID_UUID16:
2164 s = _T("Intercom");
2165 break;
2166 case FaxServiceClassID_UUID16:
2167 s = _T("Fax");
2168 break;
2169 case HeadsetAudioGatewayServiceClassID_UUID16:
2170 s = _T("Headset Audio Gateway");
2171 break;
2172 case PANUServiceClassID_UUID16:
2173 s = _T("PANU");
2174 break;
2175 case NAPServiceClassID_UUID16:
2176 s = _T("NAP");
2177 break;
2178 case GNServiceClassID_UUID16:
2179 s = _T("GN");
2180 break;
2181 case HandsfreeServiceClassID_UUID16:
2182 s = _T("Handsfree");
2183 break;
2184 case HandsfreeAudioGatewayServiceClassID_UUID16:
2185 s = _T("Handsfree Audio Gateway");
2186 break;
2187 case PnPInformationServiceClassID_UUID16:
2188 s = _T("PnP Information");
2189 break;
2190 case GenericNetworkingServiceClassID_UUID16:
2191 s = _T("Generic Networking");
2192 break;
2193 case GenericFileTransferServiceClassID_UUID16:
2194 s = _T("Generic File Transfer");
2195 break;
2196 case GenericAudioServiceClassID_UUID16:
2197 s = _T("Generic Audio");
2198 break;
2199 case GenericTelephonyServiceClassID_UUID16:
2200 s = _T("Generic Telephony");
2201 break;
2202 case 0x1113://WAP
2203 s = _T("WAP");
2204 break;
2205 case 0x1114://WAP_CLIENT
2206 s = _T("WAP Client");
2207 break;
2208 case 0x1118://DIRECT_PRINTING
2209 s = _T("Direct Printing");
2210 break;
2211 case 0x1119://REFERENCE_PRINTING
2212 s = _T("Reference Printing");
2213 break;
2214 case 0x111a://IMAGING
2215 s = _T("Imaging");
2216 break;
2217 case 0x111b://IMAGING_RESPONDER
2218 s = _T("Imaging Responder");
2219 break;
2220 case 0x111c://IMAGING_AUTOMATIC_ARCHIVE
2221 s = _T("Imaging Automatic Archive");
2222 break;
2223 case 0x111d://IMAGING_REFERENCE_OBJECTS
2224 s = _T("Imaging Reference Objects");
2225 break;
2226 case 0x1124://HID (HumanInterfaceDeviceService)
2227 s = _T("HID");
2228 break;
2229 case 0x112F://PBAP PSE (Phonebook Access Profile,Phonebook Server Equipment)
2230 s = _T("PBAP PSE");
2231 break;
2232 }
2233 return s;
2234 }
2235
2236private:
2237
2238 // サービス問い合わせ
2239 bool m_QueryService(CWorkMem& _sdp, const SdpAttributeRange& range, WORD uuid16) const
2240 {
2241 // BLOB Data 準備
2242 BTHNS_RESTRICTIONBLOB resb = { 0 };
2243 resb.type = SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST;
2244 resb.numRange = 1;
2245 resb.pRange[0] = range;
2246 resb.uuids[0].uuidType = SDP_ST_UUID16;
2247 resb.uuids[0].u.uuid16 = uuid16;
2248 // BLOB 設定
2249 BLOB blob = { 0 };
2250 blob.cbSize = sizeof(BTHNS_RESTRICTIONBLOB);
2251 blob.pBlobData = reinterpret_cast<BYTE*>(&resb);
2252 // アドレス設定
2253 SOCKADDR_BTH sa = { 0 };
2254 sa.btAddr = m_btAddr;
2255 sa.addressFamily = AF_BT;
2256 CSADDR_INFO csai = { 0 };
2257 csai.RemoteAddr.lpSockaddr = reinterpret_cast<sockaddr*>(&sa);
2258 csai.RemoteAddr.iSockaddrLength = sizeof(sa);
2259 // QUERYSET設定
2260 WSAQUERYSET wsaq = { 0 };
2261 wsaq.dwSize = sizeof(wsaq);
2262 wsaq.dwNameSpace = NS_BTH;
2263 wsaq.lpBlob = &blob;
2264 wsaq.lpcsaBuffer = &csai;
2265 // 検索開始
2266 HANDLE hLookup = NULL;
2267 int ret = BthNsLookupServiceBegin(&wsaq, 0, &hLookup);
2268 if ( ret == ERROR_SUCCESS )
2269 {
2270 // バッファ確保
2271 CWorkMem work(1000);
2272 work.Fill(0);
2273 DWORD dwSize = work.GetSize();
2274 // デバイス検索
2275 WSAQUERYSET* pResults = reinterpret_cast<WSAQUERYSET*>(work.Ref());
2276 pResults->dwSize = sizeof(WSAQUERYSET);
2277 pResults->dwNameSpace = NS_BTH;
2278 int ret = BthNsLookupServiceNext(hLookup, 0, &dwSize, pResults);
2279 int ec = ::GetLastError();
2280 if ( ret != ERROR_SUCCESS && ec == ERROR_NOT_ENOUGH_MEMORY )
2281 {
2282 // 足りなかった.再確保&検索
2283 work.Resize(dwSize);
2284 work.Fill(0);
2285 pResults = reinterpret_cast<WSAQUERYSET*>(work.Ref());
2286 pResults->dwSize = sizeof(WSAQUERYSET);
2287 pResults->dwNameSpace = NS_BTH;
2288 ret = BthNsLookupServiceNext(hLookup, 0, &dwSize, pResults);
2289 ec = ::GetLastError();
2290 }
2291 BthNsLookupServiceEnd(hLookup);
2292 if ( ret == ERROR_SUCCESS )
2293 {
2294 if ( (pResults->lpBlob->cbSize) >= 4 )
2295 {
2296 _sdp.Reset(pResults->lpBlob->cbSize, pResults->lpBlob->pBlobData);
2297 return true;
2298 }
2299 ::SetLastError(WSASERVICE_NOT_FOUND);
2300 return false;
2301 }
2302 ::SetLastError(ec);
2303 _GetLastError("BthNsLookupServiceNext");
2304 return false;
2305 }
2306 _GetLastError("BthNsLookupServiceBegin");
2307 return false;
2308 }
2309};
2310
2311
2312
2328class CBluetoothFinder : CBluetoothApi
2329{
2330 DEFSUPER(CBluetoothApi);
2331public:
2332
2334 CBluetoothFinder(void) : m_hLookup(NULL)
2335 {
2336 }
2337
2340 {
2341 Finish();
2342 }
2343
2352 {
2353 BT_ADDR ba = addr;
2354 int r = BthSetInquiryFilter(&ba);
2355 ::SetLastError(r);
2356 return r == ERROR_SUCCESS;
2357 }
2358
2366 bool ResetFilter(void)
2367 {
2368 int r = BthClearInquiryFilter();
2369 ::SetLastError(r);
2370 return r == ERROR_SUCCESS;
2371 }
2372
2379 bool Start(void)
2380 {
2381 Finish();
2382 WSAQUERYSET wsaq = { 0 };
2383 wsaq.dwSize = sizeof(WSAQUERYSET);
2384 wsaq.dwNameSpace = NS_BTH;
2385 int ret = BthNsLookupServiceBegin(&wsaq, LUP_CONTAINERS, &m_hLookup);
2386 if ( ret != ERROR_SUCCESS )
2387 {
2388 m_hLookup = NULL;
2389 return false;
2390 }
2391 return Next();
2392 }
2393
2400 bool Next(void)
2401 {
2402 // バッファ確保
2403 CWorkMem work(1000);
2404 work.Fill(0);
2405 DWORD dwSize = work.GetSize();
2406 // デバイス検索
2407 DWORD flag = LUP_RETURN_NAME | LUP_RETURN_ADDR | LUP_RETURN_BLOB;
2408 WSAQUERYSET* pResults = reinterpret_cast<WSAQUERYSET*>(work.Ref());
2409 pResults->dwSize = sizeof(WSAQUERYSET);
2410 pResults->dwNameSpace = NS_BTH;
2411 int ret = BthNsLookupServiceNext(m_hLookup, flag, &dwSize, pResults);
2412 if ( ret != ERROR_SUCCESS && ::GetLastError() == ERROR_NOT_ENOUGH_MEMORY )
2413 {
2414 // 足りなかった.再確保&検索
2415 work.Resize(dwSize);
2416 work.Fill(0);
2417 pResults = reinterpret_cast<WSAQUERYSET*>(work.Ref());
2418 pResults->dwSize = sizeof(WSAQUERYSET);
2419 pResults->dwNameSpace = NS_BTH;
2420 ret = BthNsLookupServiceNext(m_hLookup, flag, &dwSize, pResults);
2421 }
2422 if ( ret != ERROR_SUCCESS )
2423 {
2424 if ( ::GetLastError() != WSA_E_NO_MORE )
2425 {
2426 _GetLastError("BthNsLookupServiceNext");
2427 }
2428 return false;
2429 }
2430 BT_ADDR ba = 0;
2431 if ( pResults->dwNumberOfCsAddrs == 1 )
2432 {
2433 LPSOCKADDR lpszAddr = pResults->lpcsaBuffer->RemoteAddr.lpSockaddr;
2434 SOCKADDR_BTH* P = reinterpret_cast<SOCKADDR_BTH*>(lpszAddr);
2435 ba = P->btAddr;
2436 }
2437 ASSERT( pResults->lpBlob->cbSize == sizeof(BthInquiryResult) );
2438 BthInquiryResult* pInqRes = reinterpret_cast<BthInquiryResult*>(pResults->lpBlob->pBlobData);
2439 // 情報記憶
2440 m_foundDevice = ba;
2441 m_foundName = pResults->lpszServiceInstanceName;
2442 m_foundClass = pInqRes->cod;
2443 return m_foundDevice.IsValid();
2444 }
2445
2447 void Finish(void)
2448 {
2449 if ( m_hLookup != NULL )
2450 {
2451 BthNsLookupServiceEnd(m_hLookup);
2452 m_hLookup = NULL;
2453 }
2454 }
2455
2462 {
2463 return m_foundDevice;
2464 }
2465
2472 {
2473 return m_foundClass;
2474 }
2475
2481 LPCTSTR GetFoundDeviceName(void) const
2482 {
2483 return m_foundName;
2484 }
2485
2486private:
2487 HANDLE m_hLookup;
2488 CBluetoothDevice m_foundDevice;
2489 CStr m_foundName;
2490 CBluetoothClass m_foundClass;
2491};
2492
2493
2494
2504{
2505public:
2506
2512 bool Disconnect(void)
2513 {
2514 CBag ag;
2515 return ag.Control(IOCTL_AG_CLOSE_CONTROL);
2516 }
2517
2523 bool Connect(void)
2524 {
2525 CBag ag;
2526 return ag.Control(IOCTL_AG_OPEN_CONTROL);
2527 }
2528
2534 bool AutoAnswer(void)
2535 {
2536 CBag ag;
2537 DWORD dwData = 1;
2538 return ag.Control(IOCTL_AG_SET_USE_HF_AUDIO, &dwData, sizeof(dwData));
2539 }
2540
2546 bool OpenAudio(void)
2547 {
2548 CBag ag;
2549 return ag.Control(IOCTL_AG_OPEN_AUDIO);
2550 }
2551
2557 bool CloseAudio(void)
2558 {
2559 CBag ag;
2560 return ag.Control(IOCTL_AG_CLOSE_AUDIO);
2561 }
2562
2569 bool SetInbandRing(bool isOn = true)
2570 {
2571 CBag ag;
2572 DWORD dwData = isOn ? 1 : 0;
2573 return ag.Control(IOCTL_AG_SET_INBAND_RING, &dwData, sizeof(dwData));
2574 }
2575
2582 bool SetPowerSaveMode(bool isOn = true)
2583 {
2584 CBag ag;
2585 DWORD dwData = isOn ? 1 : 0;
2586 return ag.Control(IOCTL_AG_SET_POWER_MODE, &dwData, sizeof(dwData));
2587 }
2588
2595 bool GetPowerSaveMode(bool& _isOn)
2596 {
2597 CBag ag;
2598 DWORD dwData = 0;
2599 bool r = ag.Control(IOCTL_AG_GET_POWER_MODE, NULL, 0, &dwData, sizeof(dwData));
2600 _isOn = (dwData != 0);
2601 return r;
2602 }
2603
2610 bool SetSpeakerVolume(int vol)
2611 {
2612 CBag ag;
2613 return ag.Control(IOCTL_AG_SET_SPEAKER_VOL, &vol, sizeof(vol));
2614 }
2615
2622 bool GetSpeakerVolume(int& _vol)
2623 {
2624 CBag ag;
2625 return ag.Control(IOCTL_AG_GET_SPEAKER_VOL, NULL, 0, &_vol, sizeof(_vol));
2626 }
2627
2634 bool SetMicVolume(int vol)
2635 {
2636 CBag ag;
2637 return ag.Control(IOCTL_AG_SET_MIC_VOL, &vol, sizeof(vol));
2638 }
2639
2646 bool GetMicVolume(int& _vol)
2647 {
2648 CBag ag;
2649 return ag.Control(IOCTL_AG_GET_MIC_VOL, NULL, 0, &_vol, sizeof(_vol));
2650 }
2651
2652private:
2654 class CBag
2655 {
2656 public:
2658 CBag(void) : m_handle(::CreateFile(_T("BAG0:"), 0, 0, NULL, OPEN_EXISTING, 0, NULL))
2659 {
2660 }
2662 ~CBag(void)
2663 {
2664 if ( m_handle != INVALID_HANDLE_VALUE )
2665 {
2666 ::CloseHandle(m_handle);
2667 m_handle = INVALID_HANDLE_VALUE;
2668 }
2669 }
2671 bool Control(DWORD dwIoControlCode, LPVOID lpInBuffer = NULL, DWORD nInBufferSize = 0, LPVOID lpOutBuffer = NULL, DWORD nOutBufferSize = 0, LPDWORD lpBytesReturned = NULL, LPOVERLAPPED lpOverlapped = NULL)
2672 {
2673 bool r = !! ::DeviceIoControl(m_handle, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped);
2674 if ( ! r )
2675 {
2676 _GetLastError("DeviceIoControl");
2677 }
2678 return r;
2679 }
2680 private:
2681 HANDLE m_handle;
2682 };
2683};
2684
2685
2686
2687#if 0
2688
2689 CE の SDP は、一個ずつしか検索できない。
2690
2691#endif
2692
2693};//TNB
CE 用 Bluetooth関係のヘッダ
#define loop(VAR, CNT)
loop構文.
Definition: TnbDef.h:343
レジストリアクセス関係のヘッダ
文字列情報配列管理関係のヘッダ
経過時間管理関係のヘッダ
Bluetooth(CE) アドレス管理.
const BT_ADDR & GetAddress(void) const
[取得] アドレス取得.
BT_ADDR m_btAddr
アドレス
CBluetoothAddress & operator=(const CBluetoothAddress &other)
コピーオペレータ.
bool IsValid(void) const
[確認] 有効確認.
CStr GetAddressString(void) const
[取得] アドレス文字列取得.
bool SetAddressString(LPCTSTR lpszAddress)
[設定] アドレス文字列設定.
CBluetoothAddress(BT_ADDR btAddr=0)
コンストラクタ.
CBluetoothAddress(const CBluetoothAddress &other)
コピーコンストラクタ.
Bluetooth(CE) Audio Gateway Service 管理.
bool SetInbandRing(bool isOn=true)
[設定] Turning on/off inband ring tones.
bool Disconnect(void)
[処理] Closing Bluetooth control connection.
bool GetSpeakerVolume(int &_vol)
[取得] Getting speaker volume.
bool GetMicVolume(int &_vol)
[取得] Getting microphone volume.
bool AutoAnswer(void)
[処理] Setting auto-answer option.
bool GetPowerSaveMode(bool &_isOn)
[取得] Getting Power-save mode.
bool CloseAudio(void)
[処理] Closing Bluetooth audio.
bool OpenAudio(void)
[処理] Opening Bluetooth audio.
bool SetSpeakerVolume(int vol)
[設定] Setting speaker volume.
bool SetMicVolume(int vol)
[設定] Setting microphone volume.
bool Connect(void)
[処理] Opening Bluetooth control connection.
bool SetPowerSaveMode(bool isOn=true)
[設定] Turning on/off Power-save mode.
Bluetooth(CE) デバイスクラス管理.
DWORD serviceClass
サービスクラス
DWORD majorDeviceClass
メジャーデバイスクラス
DWORD GetMajorDeviceClass(void) const
[取得] メジャーデバイスクラス取得.
void SetServiceClass(DWORD c)
[設定] サービスクラス設定.
LPCTSTR GetMinorDeviceClassName(void) const
[取得] マイナーデバイスクラス文字列取得.
DWORD GetServiceClass(void) const
[取得] サービスクラス取得.
DWORD cod
デバイスクラス
DWORD formatType
フォーマットタイプ
void SetMajorDeviceClass(DWORD c)
[設定] メジャーデバイスクラス設定.
LPCTSTR GetMajorDeviceClassName(void) const
[取得] メジャーデバイスクラス文字列取得.
EMajorDeviceClass
メジャーデバイスクラス種類.
@ Imaging
Imaging (printing, scanner, camera, display, ...)
@ Network
LAN /Network Access point
@ Miscellaneous
Miscellaneous
@ Peripheral
Peripheral (mouse, joystick, keyboards, ..... )
@ AV
Audio/Video (headset,speaker,stereo, video display, vcr.....
@ Phone
Phone (cellular, cordless, payphone, modem, ...)
@ Computer
Computer (desktop,notebook, PDA, organizers, .... )
EServiceClass
サービスクラス種類.
@ Positioning
Positioning (Location identification)
@ ObjectTransfer
Object Transfer (v-Inbox, v-Folder, ...)
@ Rendering
Rendering (Printing, Speaker, ...)
@ Networking
Networking (LAN, Ad hoc, ...)
@ Information
Information (WEB-server, WAP-server, ...)
@ Telephony
Telephony (Cordless telephony, Modem, Headset service, ...)
@ Audio
Audio (Speaker, Microphone, Headset service, ...)
@ Capturing
Capturing (Scanner, Microphone, ...)
DWORD GetMinorDeviceClass(void) const
[取得] マイナーデバイスクラス取得.
DWORD GetDeviceClass(void) const
[取得] デバイスクラス取得.
void SetMinorDeviceClass(DWORD c)
[設定] マイナーデバイスクラス設定.
CBluetoothClass(DWORD cod=0)
コンストラクタ.
DWORD minorDeviceClass
マイナーデバイスクラス
Bluetooth(CE) デバイス管理.
bool RefusePinRequest(void)
[処理] PIN リクエスト辞退.
bool GetClassEx(CBluetoothClass &_class)
[取得] デバイスクラス取得.
bool GetVersion(TVersion &_version)
[取得] バージョン取得.
bool IsExist(void) const
[確認] 存在確認.
CBluetoothDevice(const BT_ADDR &btAddr=0)
コンストラクタ.
bool HasService(WORD uuid16) const
[確認] サービス確認.
bool ExitParkMode(void)
[設定] パークモード終了
bool GetServicesList(CWorkMemT< WORD > &_list, size_t baseListLength, const WORD *pBaseList) const
[取得] サービス一覧取得.
CBluetoothDevice(BT_HANDLE btHandle)
コンストラクタ.
bool ExitSniffMode(void)
[設定] スニフモード終了
bool HasService(CWorkMem &_raw, WORD uuid16) const
[確認] サービス確認.
static bool GetBasebandConnections(CWorkMemT< BASEBAND_CONNECTION > &_connections)
[取得] ベースバンド接続一覧取得.
bool PairRequest(LPCTSTR lpszPin)
[処理] ペアリクエスト.
bool EnterHoldMode(WORD &_interval, WORD hold_mode_max, WORD hold_mode_min)
[設定] ホールドモード開始.
CBluetoothDevice(const CBluetoothDevice &other)
コピーコンストラクタ.
bool Authenticate(void) const
[処理] 認証.
CBluetoothDevice & operator=(const CBluetoothDevice &other)
コピーオペレータ.
@ ACTIVE
アクティブモード.
@ HOLD
ホールドモード.
@ PARK
パークモード.
@ SNIFF
スニフモード.
bool GetCurrentMode(EMode &_mode) const
[取得] .ACLモード取得.
static CStr ServiceToString(WORD serviceUuid16)
[取得] サービス名取得.
BT_HANDLE CreateAclConnection(void)
[処理] データ通信用パケットオープン.
bool SetEncryption(bool isEnable)
[設定] 暗号設定.
bool EnterParkMode(WORD &_interval, WORD beacon_max, WORD beacon_min)
[設定] パークモード開始.
bool SetPin(LPCTSTR lpszPin)
[設定] PIN コード設定.
bool EnterSniffMode(WORD &_interval, WORD sniff_mode_max, WORD sniff_mode_min, WORD sniff_attempt, WORD sniff_timeout)
[設定] スニフモード開始.
bool GetClass(CBluetoothClass &_class) const
[取得] デバイスクラス取得.
bool SetLinkKey(const CBluetoothLinkKey &key)
[設定] LINKキー設定.
bool HasService(CBluetoothServiceAttribute &_attr, WORD uuid16) const
[確認] サービス確認.
CStr GetName(void) const
[取得] デバイス名取得.
static bool CloseConnection(BT_HANDLE handle)
[処理] コネクションクローズ.
bool GetLinkKey(CBluetoothLinkKey &_key) const
[取得] LINKキー取得.
bool RevokePin(void)
[破棄] PINコード破棄.
BT_HANDLE CreateScoConnection(void)
[処理] 音声用パケットオープン.
bool RevokeLinkKey(void)
[破棄] LINKキー破棄.
Bluetooth(CE) デバイス検索.
const CBluetoothClass & GetFoundDeviceClass(void) const
[取得] 発見デバイスクラス取得.
CBluetoothFinder(void)
コンストラクタ
bool Next(void)
[検索] 次検索開
void Finish(void)
[検索] 検索終了
bool SetFilter(const CBluetoothAddress &addr)
[設定] フィルタ設定.
const CBluetoothDevice & GetFoundDevice(void) const
[取得] 発見デバイス取得.
bool Start(void)
[検索] 検索開始.
LPCTSTR GetFoundDeviceName(void) const
[取得] 発見デバイス名取得.
~CBluetoothFinder(void)
デストラクタ
bool ResetFilter(void)
[設定] フィルタ設定解除.
Bluetooth(CE) リンクキー管理.
const BYTE * Refer(void) const
[参照] アドレス参照.
const BYTE & operator[](INDEX index) const
[参照] 要素参照.
CBluetoothLinkKey(void)
コンストラクタ.
BYTE * Refer(void)
[参照] アドレス参照.
BYTE & operator[](INDEX index)
[参照] 要素参照.
Bluetooth(CE) ローカル管理.
bool IsEnabledAuthentication(bool &_isEnabled) const
[取得] 認証状態取得.
bool SetPageTimeout(DWORD timeout)
[設定] ページタイムアウト時間設定.
bool TerminateIdleConnections(void)
[設定] アイドル接続切断.
bool ClearInquiryFilter(void)
[設定] Inquiryフィルタ設定解除.
bool SetInquiryFilter(const CBluetoothAddress &addr)
[設定] Inquiryフィルタ設定.
bool GetPageTimeoutMs(DWORD &_timeout) const
[取得] ページタイムアウト時間取得.
bool GetPageTimeout(DWORD &_timeout) const
[取得] ページタイムアウト時間取得.
bool GetAddress(CBluetoothAddress &_addr) const
[取得] アドレス取得.
int GetStatus(void) const
[取得] 状態取得.
bool SetMode(EMode mode, DWORD timeout=3000)
[設定] モード設定.
bool SetName(LPCTSTR lpszName)
[設定] 名前設定.
@ PowerOff
Power OFF。
@ EnabledPageScan
Power ON。Inquiry は Disable、 Page Scan は Enable。
@ EnabledAll
Power ON。Inquiry は Enable、 Page Scan は Enable。
@ DisabledAll
Power ON。Inquiry は Disable、 Page Scan は Disable。
@ EnabledInquiry
Power ON。Inquiry は Enable、 Page Scan は Disable。
bool GetMode(EMode &_mode) const
[取得] モード取得.
CVectorT< BthInquiryResult > Inquiry(DWORD timeout=1000) const
[検索] Inquiry実行.
bool GetClass(CBluetoothClass &_class) const
[取得] デバイスクラス取得.
CStr GetName(void) const
[取得] 名前取得.
bool EnableAuthentication(bool isEnable)
[設定] 認証有効無効.
CBluetoothLocal(void)
コンストラクタ
bool SetPageTimeoutMs(DWORD timeout)
[設定] ページタイムアウト時間設定.
bool SetClass(const CBluetoothClass &clas)
[設定] デバイスクラス設定.
Bluetooth(CE) サービス属性管理.
~CBluetoothServiceAttribute(void)
デストラクタ
const TIdsList & GetAttributeIdList(void) const
[取得] 属性ID一覧取得.
bool HasAttribute(WORD attributeId) const
[確認] 属性データ確認.
bool Analyze(size_t size, LPCVOID lpRawData)
[解析] 解析.
CVectorT< WORD > TIdsList
ID配列.
bool IsValid(void) const
[確認] 有効確認.
CVectorT< TValue > TValuesList
値配列.
HRESULT GetLastResult(void) const
[取得] 最終リザルト取得.
CStrVector GetAttributeString(void) const
[取得] 属性文字列取得.
const TValuesList & GetAttributeData(WORD attributeId) const
[取得] 属性IDデータ取得.
bool SearchRecord(INDEX record)
[検索] レコード検索.
size_t GetRecordCount(void) const
[取得] 保持レコード数.
void Free(void)
[設定] 破棄.
CBluetoothServiceAttribute(void)
コンストラクタ
[ETC] コピー不可能スーパークラス.
Definition: TnbDef.h:599
レジストリアクセスクラス
bool IsEmpty(void) const
[確認] 空チェック
Definition: TnbStr.h:528
void ReleaseBuffer(void)
[操作] 割り当てたバッファを開放.
Definition: TnbStr.h:954
size_t GetLength(void) const
[取得] 文字列長
Definition: TnbStr.h:518
static CStrT Fmt(const TCHAR *lpszFormat,...)
[作成] 書式付き文字列作成
Definition: TnbStr.h:1206
void Format(const TYP *lpszFormat,...)
[代入] 書式付き文字列代入.
Definition: TnbStr.h:359
TYP * GetBuffer(size_t iLength=0)
[操作] 書き込みバッファ要求.
Definition: TnbStr.h:914
経過時間管理クラス
Definition: TnbTickCount.h:57
bool IsPassed(DWORD dwTime) const
[確認] 経過確認.
Definition: TnbTickCount.h:114
void OutputDebugPassedCount(void) const
[出力] 経過時間表示.
Definition: TnbTickCount.h:154
void Invalid(void)
[操作] 無効状態にする
Definition: TnbVector.h:604
virtual bool SetSize(size_t size)
[操作] サイズ指定
Definition: TnbVector.h:618
virtual bool RemoveAll(void)
[削除] 空化
Definition: TnbVector.h:565
virtual INDEX Add(const TYP &t)
[追加] 要素一つ追加.
Definition: TnbVector.h:383
size_t GetSize(void) const
[取得] サイズ取得
Definition: TnbDef.h:665
void Fill(const TYP &other)
[設定] 全情報代入.
Definition: TnbDef.h:724
void Resize(size_t l)
[設定] サイズ再設定
Definition: TnbDef.h:672
void Reset(size_t l, const TYP *P)
[設定] 再設定
Definition: TnbDef.h:690
const TYP * Ref(void) const
[取得] ポインタ取得
Definition: TnbDef.h:712
size_t GetLen(LPCSTR lpsz)
[計算] 文字列長計算(ASCII/SJIS用)
Definition: TnbStrLib.h:44
int HexCharToInt(int c)
[変換] HEX文字数値変換
Definition: TnbStrLib.h:492
TNB::CStrT< TCHAR > CStr
文字列クラス
Definition: TnbStr.h:1785
void Zero(V &value)
[設定] ゼロクリア.
Definition: TnbDef.h:399
WORD SwapEndian(WORD val)
[変換] エンディアン変換.
Definition: TnbDef.h:1018
TNB Library
Definition: TnbDoxyTitle.txt:2
unsigned short BT_HANDLE
Bluetooth(CE) ハンドル.
ULONGLONG BT_ADDR
Bluetooth(CE) アドレス.
Bluetooth(CE) デバイスのバージョン管理
WORD subVersion
サブバージョン
Bluetooth(CE) サービス属性値管理.
ULONGLONG uint64
spec = SDP_ST_UINT64 の場合の値
GUID uuid128
spec = SDP_ST_UUID128 の場合の値
LONGLONG int64
spec = SDP_ST_INT64 の場合の値
BYTE uint8
spec = SDP_ST_UINT8 の場合の値
WORD uint16
spec = SDP_ST_UINT16 の場合の値
bool booleanVal
type = SDP_TYPE_BOOLEAN / SDP_TYPE_STRING の場合の値
SDP_SPECIFICTYPE spec
詳細タイプ
SDP_ULARGE_INTEGER_16 uint128
spec = SDP_ST_UINT128 の場合の値
CHAR int8
spec = SDP_ST_INT8 の場合の値
TValue(SDP_TYPE t=SDP_TYPE_NIL, SDP_SPECIFICTYPE s=SDP_ST_NONE)
コンストラクタ.
CStr ToString(CStr *pType=NULL) const
[取得] 文字列化.
CAscii str
type = SDP_TYPE_URL の場合の値
DWORD uint32
spec = SDP_ST_UINT32 の場合の値
SDP_LARGE_INTEGER_16 int128
spec = SDP_ST_INT128 の場合の値
DWORD uuid32
spec = SDP_ST_UUID32 の場合の値
WORD uuid16
spec = SDP_ST_UUID16 の場合の値
LONG int32
spec = SDP_ST_INT32 の場合の値
SHORT int16
spec = SDP_ST_INT16 の場合の値
virtual size_t CopyElements(size_t size, const TYP *P=NULL)
[設定] コピー.
INDEX Find(const IChecker &checker, INDEX startIndex=0, bool boIsReverse=false) const
[検索] 条件一致要素の検索.