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_uuid.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
,
65 device::BluetoothUUID
* uuid
) {
66 HBLUETOOTH_CONTAINER_ELEMENT inner_uuid_element
= NULL
;
67 SDP_ELEMENT_DATA inner_uuid_data
;
68 if (AdvanceToSdpType(uuid_data
,
72 if (inner_uuid_data
.specificType
== SDP_ST_UUID16
) {
73 std::string uuid_hex
=
74 base::StringPrintf("%04x", inner_uuid_data
.data
.uuid16
);
75 *uuid
= device::BluetoothUUID(uuid_hex
);
76 } else if (inner_uuid_data
.specificType
== SDP_ST_UUID32
) {
77 std::string uuid_hex
=
78 base::StringPrintf("%08x", inner_uuid_data
.data
.uuid32
);
79 *uuid
= device::BluetoothUUID(uuid_hex
);
80 } else if (inner_uuid_data
.specificType
== SDP_ST_UUID128
) {
81 *uuid
= device::BluetoothUUID(base::StringPrintf(
82 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
83 inner_uuid_data
.data
.uuid128
.Data1
,
84 inner_uuid_data
.data
.uuid128
.Data2
,
85 inner_uuid_data
.data
.uuid128
.Data3
,
86 inner_uuid_data
.data
.uuid128
.Data4
[0],
87 inner_uuid_data
.data
.uuid128
.Data4
[1],
88 inner_uuid_data
.data
.uuid128
.Data4
[2],
89 inner_uuid_data
.data
.uuid128
.Data4
[3],
90 inner_uuid_data
.data
.uuid128
.Data4
[4],
91 inner_uuid_data
.data
.uuid128
.Data4
[5],
92 inner_uuid_data
.data
.uuid128
.Data4
[6],
93 inner_uuid_data
.data
.uuid128
.Data4
[7]));
95 *uuid
= device::BluetoothUUID();
100 BTH_ADDR
ConvertToBthAddr(const std::string
& address
) {
101 BTH_ADDR bth_addr
= 0;
102 std::string numbers_only
;
103 for (int i
= 0; i
< 6; ++i
) {
104 numbers_only
+= address
.substr(i
* 3, 2);
107 std::vector
<uint8
> address_bytes
;
108 base::HexStringToBytes(numbers_only
, &address_bytes
);
109 int byte_position
= 0;
110 for (std::vector
<uint8
>::reverse_iterator iter
= address_bytes
.rbegin();
111 iter
!= address_bytes
.rend();
113 bth_addr
+= *iter
* pow(256.0, byte_position
);
123 BluetoothServiceRecordWin::BluetoothServiceRecordWin(
124 const std::string
& device_address
,
125 const std::string
& name
,
126 const std::vector
<uint8
>& sdp_bytes
,
127 const BluetoothUUID
& gatt_uuid
)
128 : device_bth_addr_(ConvertToBthAddr(device_address
)),
129 device_address_(device_address
),
132 supports_rfcomm_(false),
133 rfcomm_channel_(0xFF) {
135 if (sdp_bytes
.size() > 0) {
136 LPBYTE blob_data
= const_cast<LPBYTE
>(&sdp_bytes
[0]);
137 ULONG blob_size
= static_cast<ULONG
>(sdp_bytes
.size());
138 SDP_ELEMENT_DATA protocol_descriptor_list_data
;
140 BluetoothSdpGetAttributeValue(blob_data
,
142 kProtocolDescriptorListId
,
143 &protocol_descriptor_list_data
)) {
145 protocol_descriptor_list_data
, &supports_rfcomm_
, &rfcomm_channel_
);
147 SDP_ELEMENT_DATA uuid_data
;
148 if (ERROR_SUCCESS
== BluetoothSdpGetAttributeValue(
149 blob_data
, blob_size
, kUuidId
, &uuid_data
)) {
150 ExtractUuid(uuid_data
, &uuid_
);
155 bool BluetoothServiceRecordWin::IsEqual(
156 const BluetoothServiceRecordWin
& other
) {
157 return device_address_
== other
.device_address_
&& name_
== other
.name_
&&
158 uuid_
== other
.uuid_
&& supports_rfcomm_
== other
.supports_rfcomm_
&&
159 rfcomm_channel_
== other
.rfcomm_channel_
;
162 } // namespace device