chrome: Remove unneeded dependencies on libxml.
[chromium-blink-merge.git] / device / bluetooth / bluetooth_service_record_win.cc
blobc4fccde37137db8bfbe3a4a0593410ce6f8248a7
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"
7 #include <string>
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"
15 namespace {
17 const uint16 kProtocolDescriptorListId = 4;
18 const uint16 kRfcommUuid = 3;
19 const uint16 kUuidId = 1;
21 bool AdvanceToSdpType(const SDP_ELEMENT_DATA& sequence_data,
22 SDP_TYPE type,
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,
28 element,
29 sdp_data)) {
30 if (sdp_data->type == type) {
31 return true;
34 return false;
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,
43 SDP_TYPE_SEQUENCE,
44 &sequence_element,
45 &sequence_data)) {
46 HBLUETOOTH_CONTAINER_ELEMENT inner_sequence_element = NULL;
47 SDP_ELEMENT_DATA inner_sequence_data;
48 if (AdvanceToSdpType(sequence_data,
49 SDP_TYPE_UUID,
50 &inner_sequence_element,
51 &inner_sequence_data) &&
52 inner_sequence_data.data.uuid32 == kRfcommUuid &&
53 AdvanceToSdpType(sequence_data,
54 SDP_TYPE_UINT,
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,
69 SDP_TYPE_UUID,
70 &inner_uuid_element,
71 &inner_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]));
94 } else {
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();
112 ++iter) {
113 bth_addr += *iter * pow(256.0, byte_position);
114 byte_position++;
116 return bth_addr;
119 } // namespace
121 namespace device {
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),
130 name_(name),
131 uuid_(gatt_uuid),
132 supports_rfcomm_(false),
133 rfcomm_channel_(0xFF) {
134 // Bluetooth 2.0
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;
139 if (ERROR_SUCCESS ==
140 BluetoothSdpGetAttributeValue(blob_data,
141 blob_size,
142 kProtocolDescriptorListId,
143 &protocol_descriptor_list_data)) {
144 ExtractChannels(
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