OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/arc/bluetooth/bluetooth_struct_traits.h" | 5 #include "components/arc/bluetooth/bluetooth_struct_traits.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
11 #include "base/strings/stringprintf.h" | |
12 #include "device/bluetooth/bluetooth_advertisement.h" | |
11 #include "device/bluetooth/bluetooth_uuid.h" | 13 #include "device/bluetooth/bluetooth_uuid.h" |
12 | 14 |
13 namespace { | 15 namespace { |
14 | 16 |
17 // BluetoothUUID helpers. | |
15 constexpr size_t kUUIDSize = 16; | 18 constexpr size_t kUUIDSize = 16; |
16 | 19 |
17 bool IsNonHex(char c) { | 20 bool IsNonHex(char c) { |
18 return !isxdigit(c); | 21 return !isxdigit(c); |
19 } | 22 } |
20 | 23 |
21 std::string StripNonHex(const std::string& str) { | 24 std::string StripNonHex(const std::string& str) { |
22 std::string result = str; | 25 std::string result = str; |
23 result.erase(std::remove_if(result.begin(), result.end(), IsNonHex), | 26 result.erase(std::remove_if(result.begin(), result.end(), IsNonHex), |
24 result.end()); | 27 result.end()); |
25 | 28 |
26 return result; | 29 return result; |
27 } | 30 } |
28 | 31 |
32 // BluetoothAdvertisement helpers. | |
33 struct AdvertisementEntry { | |
34 virtual ~AdvertisementEntry() {} | |
Eric Caruso
2016/10/06 19:00:50
This line and the other virtual destructors are th
Luis Héctor Chávez
2016/10/06 19:23:53
The next time you reland something, can you please
| |
35 virtual void AddTo(device::BluetoothAdvertisement::Data* data) {} | |
36 }; | |
37 | |
38 struct ServiceUUIDEntry : public AdvertisementEntry { | |
39 std::vector<device::BluetoothUUID> service_uuids; | |
40 | |
41 ~ServiceUUIDEntry() override {} | |
42 | |
43 void AddTo(device::BluetoothAdvertisement::Data* data) override { | |
44 auto string_uuids = base::MakeUnique<std::vector<std::string>>(); | |
45 for (const auto& uuid : service_uuids) { | |
46 string_uuids->emplace_back(uuid.value()); | |
47 } | |
48 data->set_service_uuids(std::move(string_uuids)); | |
49 } | |
50 }; | |
51 | |
52 struct ServiceDataEntry : public AdvertisementEntry { | |
53 uint16_t service_uuid; | |
54 std::vector<uint8_t> service_data; | |
55 | |
56 ~ServiceDataEntry() override {} | |
57 | |
58 void AddTo(device::BluetoothAdvertisement::Data* data) override { | |
59 std::string string_uuid = base::StringPrintf("%04x", service_uuid); | |
60 data->set_service_data( | |
61 base::WrapUnique(new std::map<std::string, std::vector<uint8_t>>{ | |
62 {string_uuid, service_data}})); | |
63 } | |
64 }; | |
65 | |
66 struct ManufacturerDataEntry : public AdvertisementEntry { | |
67 uint16_t company_id_code; | |
68 std::vector<uint8_t> blob; | |
69 | |
70 ~ManufacturerDataEntry() override {} | |
71 | |
72 void AddTo(device::BluetoothAdvertisement::Data* data) override { | |
73 data->set_manufacturer_data(base::WrapUnique( | |
74 new std::map<uint16_t, std::vector<uint8_t>>{{company_id_code, blob}})); | |
75 } | |
76 }; | |
77 | |
78 uint16_t ExtractCompanyIdentifierCode(std::vector<uint8_t>* blob) { | |
79 // The company identifier code is in little-endian. | |
80 uint16_t company_id_code = (*blob)[1] << 8 | (*blob)[0]; | |
81 blob->erase(blob->begin(), blob->begin() + sizeof(uint16_t)); | |
82 return company_id_code; | |
83 } | |
84 | |
29 } // namespace | 85 } // namespace |
30 | 86 |
31 namespace mojo { | 87 namespace mojo { |
32 | 88 |
33 // static | 89 // static |
34 std::vector<uint8_t> | 90 std::vector<uint8_t> |
35 StructTraits<arc::mojom::BluetoothUUIDDataView, device::BluetoothUUID>::uuid( | 91 StructTraits<arc::mojom::BluetoothUUIDDataView, device::BluetoothUUID>::uuid( |
36 const device::BluetoothUUID& input) { | 92 const device::BluetoothUUID& input) { |
37 // TODO(dcheng): Figure out what to do here, this is called twice on | 93 // TODO(dcheng): Figure out what to do here, this is called twice on |
38 // serialization. Building a vector is a little inefficient. | 94 // serialization. Building a vector is a little inefficient. |
(...skipping 24 matching lines...) Expand all Loading... | |
63 for (auto pos : kUuidDashPos) | 119 for (auto pos : kUuidDashPos) |
64 uuid_str = uuid_str.insert(pos, "-"); | 120 uuid_str = uuid_str.insert(pos, "-"); |
65 | 121 |
66 device::BluetoothUUID result(uuid_str); | 122 device::BluetoothUUID result(uuid_str); |
67 | 123 |
68 DCHECK(result.IsValid()); | 124 DCHECK(result.IsValid()); |
69 *output = result; | 125 *output = result; |
70 return true; | 126 return true; |
71 } | 127 } |
72 | 128 |
129 template <> | |
130 struct EnumTraits<arc::mojom::BluetoothAdvertisementType, | |
131 device::BluetoothAdvertisement::AdvertisementType> { | |
132 static bool FromMojom( | |
133 arc::mojom::BluetoothAdvertisementType mojom_type, | |
134 device::BluetoothAdvertisement::AdvertisementType* type) { | |
135 switch (mojom_type) { | |
136 case arc::mojom::BluetoothAdvertisementType::ADV_TYPE_CONNECTABLE: | |
137 case arc::mojom::BluetoothAdvertisementType::ADV_TYPE_SCANNABLE: | |
138 *type = device::BluetoothAdvertisement::ADVERTISEMENT_TYPE_PERIPHERAL; | |
139 return true; | |
140 case arc::mojom::BluetoothAdvertisementType::ADV_TYPE_NON_CONNECTABLE: | |
141 *type = device::BluetoothAdvertisement::ADVERTISEMENT_TYPE_BROADCAST; | |
142 return true; | |
143 } | |
144 NOTREACHED() << "Invalid type: " << static_cast<uint32_t>(mojom_type); | |
145 return false; | |
146 } | |
147 }; | |
148 | |
149 template <> | |
150 struct StructTraits<arc::mojom::BluetoothServiceDataDataView, | |
151 ServiceDataEntry> { | |
152 static bool Read(arc::mojom::BluetoothServiceDataDataView data, | |
153 ServiceDataEntry* output) { | |
154 output->service_uuid = data.uuid_16bit(); | |
155 return data.ReadData(&output->service_data); | |
156 } | |
157 }; | |
158 | |
159 template <> | |
160 struct UnionTraits<arc::mojom::BluetoothAdvertisingDataDataView, | |
161 std::unique_ptr<AdvertisementEntry>> { | |
162 static bool Read(arc::mojom::BluetoothAdvertisingDataDataView data, | |
163 std::unique_ptr<AdvertisementEntry>* output) { | |
164 switch (data.tag()) { | |
165 case arc::mojom::BluetoothAdvertisingDataDataView::Tag::SERVICE_UUIDS: { | |
166 std::unique_ptr<ServiceUUIDEntry> service_uuids = | |
167 base::MakeUnique<ServiceUUIDEntry>(); | |
168 if (!data.ReadServiceUuids(&service_uuids->service_uuids)) | |
169 return false; | |
170 *output = std::move(service_uuids); | |
171 break; | |
172 } | |
173 case arc::mojom::BluetoothAdvertisingDataDataView::Tag::SERVICE_DATA: { | |
174 std::unique_ptr<ServiceDataEntry> service_data = | |
175 base::MakeUnique<ServiceDataEntry>(); | |
176 if (!data.ReadServiceData(service_data.get())) | |
177 return false; | |
178 *output = std::move(service_data); | |
179 break; | |
180 } | |
181 case arc::mojom::BluetoothAdvertisingDataDataView::Tag:: | |
182 MANUFACTURER_DATA: { | |
183 std::unique_ptr<ManufacturerDataEntry> manufacturer_data = | |
184 base::MakeUnique<ManufacturerDataEntry>(); | |
185 // We get manufacturer data as a big blob. The first two bytes | |
186 // should be a company identifier code and the rest is manufacturer- | |
187 // specific. | |
188 std::vector<uint8_t> blob; | |
189 if (!data.ReadManufacturerData(&blob)) | |
190 return false; | |
191 if (blob.size() < sizeof(uint16_t)) { | |
192 LOG(WARNING) << "Advertisement had malformed manufacturer data"; | |
193 return false; | |
194 } | |
195 | |
196 manufacturer_data->company_id_code = | |
197 ExtractCompanyIdentifierCode(&blob); | |
198 manufacturer_data->blob = std::move(blob); | |
199 *output = std::move(manufacturer_data); | |
200 break; | |
201 } | |
202 default: { | |
203 LOG(WARNING) << "Bluetooth advertising data case not implemented"; | |
204 // Default AdvertisementEntry does nothing when added to the | |
205 // device::BluetoothAdvertisement::AdvertisementData, so data we | |
206 // don't know how to handle yet will be dropped but won't cause a | |
207 // failure to deserialize. | |
208 *output = base::MakeUnique<AdvertisementEntry>(); | |
209 break; | |
210 } | |
211 } | |
212 return true; | |
213 } | |
214 }; | |
215 | |
216 // static | |
217 bool StructTraits<arc::mojom::BluetoothAdvertisementDataView, | |
218 std::unique_ptr<device::BluetoothAdvertisement::Data>>:: | |
219 Read(arc::mojom::BluetoothAdvertisementDataView advertisement, | |
220 std::unique_ptr<device::BluetoothAdvertisement::Data>* output) { | |
221 device::BluetoothAdvertisement::AdvertisementType adv_type; | |
222 if (!advertisement.ReadType(&adv_type)) | |
223 return false; | |
224 auto data = base::MakeUnique<device::BluetoothAdvertisement::Data>(adv_type); | |
225 | |
226 std::vector<std::unique_ptr<AdvertisementEntry>> adv_entries; | |
227 if (!advertisement.ReadData(&adv_entries)) | |
228 return false; | |
229 for (const auto& adv_entry : adv_entries) | |
230 adv_entry->AddTo(data.get()); | |
231 | |
232 data->set_include_tx_power(advertisement.include_tx_power()); | |
233 | |
234 *output = std::move(data); | |
235 return true; | |
236 } | |
237 | |
73 } // namespace mojo | 238 } // namespace mojo |
OLD | NEW |