Fix build break
[chromium-blink-merge.git] / device / bluetooth / bluetooth_service_record_chromeos.cc
blobb7ab878b1015602e68dcbad50878e74be7ceb240
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_chromeos.h"
7 #include <bluetooth/bluetooth.h>
9 #include <string>
10 #include <vector>
12 #include "base/logging.h"
13 #include "base/string_number_conversions.h"
14 #include "device/bluetooth/bluetooth_utils.h"
15 #include "third_party/libxml/chromium/libxml_utils.h"
17 namespace {
19 static const char* kAttributeNode = "attribute";
20 static const char* kBooleanNode = "boolean";
21 static const char* kSequenceNode = "sequence";
22 static const char* kTextNode = "text";
23 static const char* kUint8Node = "uint8";
24 static const char* kUuidNode = "uuid";
26 static const char* kIdAttribute = "id";
27 static const char* kValueAttribute = "value";
28 static const char* kValueTrue = "true";
30 static const char* kHidNormallyConnectableId = "0x020d";
31 static const char* kHidReconnectInitiateId = "0x0205";
32 static const char* kProtocolDescriptorListId = "0x0004";
33 static const char* kSdpNameId = "0x0100";
34 static const char* kServiceClassUuidId = "0x0001";
36 static const char* kProtocolRfcommUuid = "0x0003";
37 static const char* kProtocolHidpUuid = "0x0011";
39 bool AdvanceToTag(XmlReader* reader, const char* node_type) {
40 do {
41 if (!reader->Read())
42 return false;
43 } while (reader->NodeName() != node_type);
44 return true;
47 bool ExtractTextValue(XmlReader* reader, std::string* value_out) {
48 if (AdvanceToTag(reader, kTextNode)) {
49 reader->NodeAttribute(kValueAttribute, value_out);
50 return true;
52 return false;
55 bool ExtractBooleanValue(XmlReader* reader, bool* value_out) {
56 if (AdvanceToTag(reader, kBooleanNode)) {
57 std::string str_value;
58 if (!reader->NodeAttribute(kValueAttribute, &str_value))
59 return false;
60 *value_out = str_value == kValueTrue;
61 return true;
63 return false;
66 } // namespace
68 namespace chromeos {
70 BluetoothServiceRecordChromeOS::BluetoothServiceRecordChromeOS(
71 const std::string& address,
72 const std::string& xml_data) {
73 address_ = address;
74 supports_rfcomm_ = false;
75 supports_hid_ = false;
77 // For HID services the default is false when the attribute is not present.
78 hid_reconnect_initiate_ = false;
79 hid_normally_connectable_ = false;
81 XmlReader reader;
82 if (!reader.Load(xml_data))
83 return;
85 while (AdvanceToTag(&reader, kAttributeNode)) {
86 std::string id;
87 if (reader.NodeAttribute(kIdAttribute, &id)) {
88 if (id == kSdpNameId) {
89 ExtractTextValue(&reader, &name_);
90 } else if (id == kProtocolDescriptorListId) {
91 if (AdvanceToTag(&reader, kSequenceNode)) {
92 ExtractProtocolDescriptors(&reader);
94 } else if (id == kServiceClassUuidId) {
95 if (AdvanceToTag(&reader, kSequenceNode)) {
96 ExtractServiceClassUuid(&reader);
98 } else if (id == kHidNormallyConnectableId) {
99 ExtractBooleanValue(&reader, &hid_normally_connectable_);
100 } else if (id == kHidReconnectInitiateId) {
101 ExtractBooleanValue(&reader, &hid_reconnect_initiate_);
104 // We don't care about anything else here, so find the closing tag
105 AdvanceToTag(&reader, kAttributeNode);
107 if (!supports_hid_) {
108 // For non-HID services the default is true.
109 hid_normally_connectable_ = true;
110 hid_reconnect_initiate_ = true;
114 void BluetoothServiceRecordChromeOS::GetBluetoothAddress(
115 bdaddr_t* out_address) const {
116 std::string numbers_only;
117 for (int i = 0; i < 6; ++i)
118 numbers_only += address_.substr(i * 3, 2);
120 std::vector<uint8> address_bytes;
121 base::HexStringToBytes(numbers_only, &address_bytes);
122 for (int i = 0; i < 6; ++i)
123 out_address->b[5 - i] = address_bytes[i];
126 void BluetoothServiceRecordChromeOS::ExtractProtocolDescriptors(
127 XmlReader* reader) {
128 const int start_depth = reader->Depth();
129 // The ProtocolDescriptorList can have one or more sequence of sequence of
130 // stack, where each stack starts with an UUID and the remaining tags (if
131 // present) are protocol-specific.
132 do {
133 if (reader->NodeName() == kSequenceNode) {
134 if (AdvanceToTag(reader, kUuidNode)) {
135 std::string protocolUuid;
136 if (reader->NodeAttribute(kValueAttribute, &protocolUuid)) {
137 // Per protocol parameters parsing.
138 if (protocolUuid == kProtocolRfcommUuid) {
139 if (AdvanceToTag(reader, kUint8Node)) {
140 std::string channel_string;
141 if (reader->NodeAttribute(kValueAttribute, &channel_string)) {
142 std::vector<uint8> channel_bytes;
143 if (base::HexStringToBytes(channel_string.substr(2),
144 &channel_bytes)) {
145 if (channel_bytes.size() == 1) {
146 rfcomm_channel_ = channel_bytes[0];
147 supports_rfcomm_ = true;
152 } else if (protocolUuid == kProtocolHidpUuid) {
153 supports_hid_ = true;
158 } while (AdvanceToTag(reader, kSequenceNode) &&
159 reader->Depth() != start_depth);
162 void BluetoothServiceRecordChromeOS::ExtractServiceClassUuid(
163 XmlReader* reader) {
164 const int start_depth = reader->Depth();
165 do {
166 if (reader->NodeName() == kSequenceNode) {
167 if (AdvanceToTag(reader, kUuidNode)) {
168 if (!reader->NodeAttribute(kValueAttribute, &uuid_))
169 uuid_.clear();
172 } while (AdvanceToTag(reader, kSequenceNode) &&
173 reader->Depth() != start_depth);
175 uuid_ = device::bluetooth_utils::CanonicalUuid(uuid_);
178 } // namespace chromeos