1 // Copyright (c) 2012 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.h"
10 #include "base/logging.h"
11 #include "base/string_number_conversions.h"
12 #include "device/bluetooth/bluetooth_utils.h"
13 #include "third_party/libxml/chromium/libxml_utils.h"
17 static const char* kAttributeNode
= "attribute";
18 static const char* kIdAttribute
= "id";
19 static const char* kProtocolDescriptorListId
= "0x0004";
20 static const char* kRfcommUuid
= "0x0003";
21 static const char* kSdpNameId
= "0x0100";
22 static const char* kSequenceNode
= "sequence";
23 static const char* kTextNode
= "text";
24 static const char* kUint8Node
= "uint8";
25 static const char* kUuidId
= "0x0001";
26 static const char* kUuidNode
= "uuid";
27 static const char* kValueAttribute
= "value";
29 bool AdvanceToTag(XmlReader
* reader
, const char* node_type
) {
33 } while (reader
->NodeName() != node_type
);
37 bool ExtractTextValue(XmlReader
* reader
, std::string
* value_out
) {
38 if (AdvanceToTag(reader
, kTextNode
)) {
39 reader
->NodeAttribute(kValueAttribute
, value_out
);
49 BluetoothServiceRecord::BluetoothServiceRecord(
50 const std::string
& address
,
51 const std::string
& xml_data
)
53 supports_rfcomm_(false) {
56 if (!reader
.Load(xml_data
))
59 while (AdvanceToTag(&reader
, kAttributeNode
)) {
61 if (reader
.NodeAttribute(kIdAttribute
, &id
)) {
62 if (id
== kSdpNameId
) {
63 ExtractTextValue(&reader
, &name_
);
64 } else if (id
== kProtocolDescriptorListId
) {
65 if (AdvanceToTag(&reader
, kSequenceNode
)) {
66 ExtractChannels(&reader
);
68 } else if (id
== kUuidId
) {
69 if (AdvanceToTag(&reader
, kSequenceNode
)) {
74 // We don't care about anything else here, so find the closing tag
75 AdvanceToTag(&reader
, kAttributeNode
);
79 void BluetoothServiceRecord::ExtractChannels(XmlReader
* reader
) {
80 const int start_depth
= reader
->Depth();
82 if (reader
->NodeName() == kSequenceNode
) {
83 if (AdvanceToTag(reader
, kUuidNode
)) {
85 if (reader
->NodeAttribute(kValueAttribute
, &type
) &&
86 type
== kRfcommUuid
) {
87 if (AdvanceToTag(reader
, kUint8Node
)) {
88 std::string channel_string
;
89 if (reader
->NodeAttribute(kValueAttribute
, &channel_string
)) {
90 std::vector
<uint8
> channel_bytes
;
91 if (base::HexStringToBytes(channel_string
.substr(2),
93 if (channel_bytes
.size() == 1) {
94 rfcomm_channel_
= channel_bytes
[0];
95 supports_rfcomm_
= true;
103 } while (AdvanceToTag(reader
, kSequenceNode
) &&
104 reader
->Depth() != start_depth
);
107 void BluetoothServiceRecord::ExtractUuid(XmlReader
* reader
) {
108 const int start_depth
= reader
->Depth();
110 if (reader
->NodeName() == kSequenceNode
) {
111 if (AdvanceToTag(reader
, kUuidNode
)) {
112 if (!reader
->NodeAttribute(kValueAttribute
, &uuid_
))
116 } while (AdvanceToTag(reader
, kSequenceNode
) &&
117 reader
->Depth() != start_depth
);
119 uuid_
= device::bluetooth_utils::CanonicalUuid(uuid_
);
122 } // namespace device