1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "device/bluetooth/bluetooth_service_record_win.h"
9 #include "base/basictypes.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/stringprintf.h"
12 #include "device/bluetooth/bluetooth_init_win.h"
13 #include "device/bluetooth/bluetooth_utils.h"
17 const uint16 kProtocolDescriptorListId
= 4;
18 const uint16 kRfcommUuid
= 3;
19 const uint16 kUuidId
= 1;
21 bool AdvanceToSdpType(const SDP_ELEMENT_DATA
& sequence_data
,
23 HBLUETOOTH_CONTAINER_ELEMENT
* element
,
24 SDP_ELEMENT_DATA
* sdp_data
) {
25 while (ERROR_SUCCESS
== BluetoothSdpGetContainerElementData(
26 sequence_data
.data
.sequence
.value
,
27 sequence_data
.data
.sequence
.length
,
30 if (sdp_data
->type
== type
) {
37 void ExtractChannels(const SDP_ELEMENT_DATA
& protocol_descriptor_list_data
,
38 bool* supports_rfcomm
,
39 uint8
* rfcomm_channel
) {
40 HBLUETOOTH_CONTAINER_ELEMENT sequence_element
= NULL
;
41 SDP_ELEMENT_DATA sequence_data
;
42 while (AdvanceToSdpType(protocol_descriptor_list_data
,
46 HBLUETOOTH_CONTAINER_ELEMENT inner_sequence_element
= NULL
;
47 SDP_ELEMENT_DATA inner_sequence_data
;
48 if (AdvanceToSdpType(sequence_data
,
50 &inner_sequence_element
,
51 &inner_sequence_data
) &&
52 inner_sequence_data
.data
.uuid32
== kRfcommUuid
&&
53 AdvanceToSdpType(sequence_data
,
55 &inner_sequence_element
,
56 &inner_sequence_data
) &&
57 inner_sequence_data
.specificType
== SDP_ST_UINT8
) {
58 *rfcomm_channel
= inner_sequence_data
.data
.uint8
;
59 *supports_rfcomm
= true;
64 void ExtractUuid(const SDP_ELEMENT_DATA
& uuid_data
, std::string
* uuid
) {
65 HBLUETOOTH_CONTAINER_ELEMENT inner_uuid_element
= NULL
;
66 SDP_ELEMENT_DATA inner_uuid_data
;
67 if (AdvanceToSdpType(uuid_data
,
71 if (inner_uuid_data
.specificType
== SDP_ST_UUID16
) {
72 std::string uuid_hex
=
73 base::StringPrintf("%04x", inner_uuid_data
.data
.uuid16
);
74 *uuid
= device::bluetooth_utils::CanonicalUuid(uuid_hex
);
75 } else if (inner_uuid_data
.specificType
== SDP_ST_UUID32
) {
76 std::string uuid_hex
=
77 base::StringPrintf("%08x", inner_uuid_data
.data
.uuid32
);
78 *uuid
= device::bluetooth_utils::CanonicalUuid(uuid_hex
);
79 } else if (inner_uuid_data
.specificType
== SDP_ST_UUID128
) {
80 *uuid
= base::StringPrintf(
81 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
82 inner_uuid_data
.data
.uuid128
.Data1
,
83 inner_uuid_data
.data
.uuid128
.Data2
,
84 inner_uuid_data
.data
.uuid128
.Data3
,
85 inner_uuid_data
.data
.uuid128
.Data4
[0],
86 inner_uuid_data
.data
.uuid128
.Data4
[1],
87 inner_uuid_data
.data
.uuid128
.Data4
[2],
88 inner_uuid_data
.data
.uuid128
.Data4
[3],
89 inner_uuid_data
.data
.uuid128
.Data4
[4],
90 inner_uuid_data
.data
.uuid128
.Data4
[5],
91 inner_uuid_data
.data
.uuid128
.Data4
[6],
92 inner_uuid_data
.data
.uuid128
.Data4
[7]);
99 BTH_ADDR
ConvertToBthAddr(const std::string
& address
) {
100 BTH_ADDR bth_addr
= 0;
101 std::string numbers_only
;
102 for (int i
= 0; i
< 6; ++i
) {
103 numbers_only
+= address
.substr(i
* 3, 2);
106 std::vector
<uint8
> address_bytes
;
107 base::HexStringToBytes(numbers_only
, &address_bytes
);
108 int byte_position
= 0;
109 for (std::vector
<uint8
>::reverse_iterator iter
= address_bytes
.rbegin();
110 iter
!= address_bytes
.rend();
112 bth_addr
+= *iter
* pow(256.0, byte_position
);
122 BluetoothServiceRecordWin::BluetoothServiceRecordWin(
123 const std::string
& name
,
124 const std::string
& address
,
126 uint8
* blob_data
) : bth_addr_(ConvertToBthAddr(address
)) {
129 supports_rfcomm_
= false;
130 SDP_ELEMENT_DATA protocol_descriptor_list_data
;
131 if (ERROR_SUCCESS
== BluetoothSdpGetAttributeValue(
134 kProtocolDescriptorListId
,
135 &protocol_descriptor_list_data
)) {
136 ExtractChannels(protocol_descriptor_list_data
,
140 SDP_ELEMENT_DATA uuid_data
;
141 if (ERROR_SUCCESS
== BluetoothSdpGetAttributeValue(
146 ExtractUuid(uuid_data
, &uuid_
);
150 } // namespace device