| 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 void AddTo(device::BluetoothAdvertisement::Data* data) {} |
| 35 }; |
| 36 |
| 37 struct ServiceUUIDEntry : public AdvertisementEntry { |
| 38 std::vector<device::BluetoothUUID> service_uuids; |
| 39 |
| 40 void AddTo(device::BluetoothAdvertisement::Data* data) override { |
| 41 auto string_uuids = base::MakeUnique<std::vector<std::string>>(); |
| 42 for (const auto& uuid : service_uuids) { |
| 43 string_uuids->emplace_back(uuid.value()); |
| 44 } |
| 45 data->set_service_uuids(std::move(string_uuids)); |
| 46 } |
| 47 }; |
| 48 |
| 49 struct ServiceDataEntry : public AdvertisementEntry { |
| 50 uint16_t service_uuid; |
| 51 std::vector<uint8_t> service_data; |
| 52 |
| 53 void AddTo(device::BluetoothAdvertisement::Data* data) override { |
| 54 std::string string_uuid = base::StringPrintf("%04x", service_uuid); |
| 55 data->set_service_data( |
| 56 base::WrapUnique(new std::map<std::string, std::vector<uint8_t>>{ |
| 57 {string_uuid, service_data}})); |
| 58 } |
| 59 }; |
| 60 |
| 61 struct ManufacturerDataEntry : public AdvertisementEntry { |
| 62 uint16_t company_id_code; |
| 63 std::vector<uint8_t> blob; |
| 64 |
| 65 void AddTo(device::BluetoothAdvertisement::Data* data) override { |
| 66 data->set_manufacturer_data(base::WrapUnique( |
| 67 new std::map<uint16_t, std::vector<uint8_t>>{{company_id_code, blob}})); |
| 68 } |
| 69 }; |
| 70 |
| 71 uint16_t ExtractCompanyIdentifierCode(std::vector<uint8_t>* blob) { |
| 72 // The company identifier code is in little-endian. |
| 73 uint16_t company_id_code = (*blob)[1] << 8 | (*blob)[0]; |
| 74 blob->erase(blob->begin(), blob->begin() + sizeof(uint16_t)); |
| 75 return company_id_code; |
| 76 } |
| 77 |
| 29 } // namespace | 78 } // namespace |
| 30 | 79 |
| 31 namespace mojo { | 80 namespace mojo { |
| 32 | 81 |
| 33 // static | 82 // static |
| 34 std::vector<uint8_t> | 83 std::vector<uint8_t> |
| 35 StructTraits<arc::mojom::BluetoothUUIDDataView, device::BluetoothUUID>::uuid( | 84 StructTraits<arc::mojom::BluetoothUUIDDataView, device::BluetoothUUID>::uuid( |
| 36 const device::BluetoothUUID& input) { | 85 const device::BluetoothUUID& input) { |
| 37 // TODO(dcheng): Figure out what to do here, this is called twice on | 86 // TODO(dcheng): Figure out what to do here, this is called twice on |
| 38 // serialization. Building a vector is a little inefficient. | 87 // serialization. Building a vector is a little inefficient. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 63 for (auto pos : kUuidDashPos) | 112 for (auto pos : kUuidDashPos) |
| 64 uuid_str = uuid_str.insert(pos, "-"); | 113 uuid_str = uuid_str.insert(pos, "-"); |
| 65 | 114 |
| 66 device::BluetoothUUID result(uuid_str); | 115 device::BluetoothUUID result(uuid_str); |
| 67 | 116 |
| 68 DCHECK(result.IsValid()); | 117 DCHECK(result.IsValid()); |
| 69 *output = result; | 118 *output = result; |
| 70 return true; | 119 return true; |
| 71 } | 120 } |
| 72 | 121 |
| 122 template <> |
| 123 struct EnumTraits<arc::mojom::BluetoothAdvertisementType, |
| 124 device::BluetoothAdvertisement::AdvertisementType> { |
| 125 static bool FromMojom( |
| 126 arc::mojom::BluetoothAdvertisementType mojom_type, |
| 127 device::BluetoothAdvertisement::AdvertisementType* type) { |
| 128 switch (mojom_type) { |
| 129 case arc::mojom::BluetoothAdvertisementType::ADV_TYPE_CONNECTABLE: |
| 130 case arc::mojom::BluetoothAdvertisementType::ADV_TYPE_SCANNABLE: |
| 131 *type = device::BluetoothAdvertisement::ADVERTISEMENT_TYPE_PERIPHERAL; |
| 132 return true; |
| 133 case arc::mojom::BluetoothAdvertisementType::ADV_TYPE_NON_CONNECTABLE: |
| 134 *type = device::BluetoothAdvertisement::ADVERTISEMENT_TYPE_BROADCAST; |
| 135 return true; |
| 136 } |
| 137 NOTREACHED() << "Invalid type: " << static_cast<uint32_t>(mojom_type); |
| 138 return false; |
| 139 } |
| 140 }; |
| 141 |
| 142 template <> |
| 143 struct StructTraits<arc::mojom::BluetoothServiceDataDataView, |
| 144 ServiceDataEntry> { |
| 145 static bool Read(arc::mojom::BluetoothServiceDataDataView data, |
| 146 ServiceDataEntry* output) { |
| 147 output->service_uuid = data.uuid_16bit(); |
| 148 return data.ReadData(&output->service_data); |
| 149 } |
| 150 }; |
| 151 |
| 152 template <> |
| 153 struct UnionTraits<arc::mojom::BluetoothAdvertisingDataDataView, |
| 154 std::unique_ptr<AdvertisementEntry>> { |
| 155 static bool Read(arc::mojom::BluetoothAdvertisingDataDataView data, |
| 156 std::unique_ptr<AdvertisementEntry>* output) { |
| 157 switch (data.tag()) { |
| 158 case arc::mojom::BluetoothAdvertisingDataDataView::Tag::SERVICE_UUIDS: { |
| 159 std::unique_ptr<ServiceUUIDEntry> service_uuids = |
| 160 base::MakeUnique<ServiceUUIDEntry>(); |
| 161 if (!data.ReadServiceUuids(&service_uuids->service_uuids)) |
| 162 return false; |
| 163 *output = std::move(service_uuids); |
| 164 break; |
| 165 } |
| 166 case arc::mojom::BluetoothAdvertisingDataDataView::Tag::SERVICE_DATA: { |
| 167 std::unique_ptr<ServiceDataEntry> service_data = |
| 168 base::MakeUnique<ServiceDataEntry>(); |
| 169 if (!data.ReadServiceData(service_data.get())) |
| 170 return false; |
| 171 *output = std::move(service_data); |
| 172 break; |
| 173 } |
| 174 case arc::mojom::BluetoothAdvertisingDataDataView::Tag:: |
| 175 MANUFACTURER_DATA: { |
| 176 std::unique_ptr<ManufacturerDataEntry> manufacturer_data = |
| 177 base::MakeUnique<ManufacturerDataEntry>(); |
| 178 // We get manufacturer data as a big blob. The first two bytes |
| 179 // should be a company identifier code and the rest is manufacturer- |
| 180 // specific. |
| 181 std::vector<uint8_t> blob; |
| 182 if (!data.ReadManufacturerData(&blob)) |
| 183 return false; |
| 184 if (blob.size() < sizeof(uint16_t)) { |
| 185 LOG(WARNING) << "Advertisement had malformed manufacturer data"; |
| 186 return false; |
| 187 } |
| 188 |
| 189 manufacturer_data->company_id_code = |
| 190 ExtractCompanyIdentifierCode(&blob); |
| 191 manufacturer_data->blob = std::move(blob); |
| 192 *output = std::move(manufacturer_data); |
| 193 break; |
| 194 } |
| 195 default: { |
| 196 LOG(WARNING) << "Bluetooth advertising data case not implemented"; |
| 197 // Default AdvertisementEntry does nothing when added to the |
| 198 // device::BluetoothAdvertisement::AdvertisementData, so data we |
| 199 // don't know how to handle yet will be dropped but won't cause a |
| 200 // failure to deserialize. |
| 201 *output = base::MakeUnique<AdvertisementEntry>(); |
| 202 break; |
| 203 } |
| 204 } |
| 205 return true; |
| 206 } |
| 207 }; |
| 208 |
| 209 // static |
| 210 bool StructTraits<arc::mojom::BluetoothAdvertisementDataView, |
| 211 std::unique_ptr<device::BluetoothAdvertisement::Data>>:: |
| 212 Read(arc::mojom::BluetoothAdvertisementDataView advertisement, |
| 213 std::unique_ptr<device::BluetoothAdvertisement::Data>* output) { |
| 214 device::BluetoothAdvertisement::AdvertisementType adv_type; |
| 215 if (!advertisement.ReadType(&adv_type)) |
| 216 return false; |
| 217 auto data = base::MakeUnique<device::BluetoothAdvertisement::Data>(adv_type); |
| 218 |
| 219 std::vector<std::unique_ptr<AdvertisementEntry>> adv_entries; |
| 220 if (!advertisement.ReadData(&adv_entries)) |
| 221 return false; |
| 222 for (const auto& adv_entry : adv_entries) |
| 223 adv_entry->AddTo(data.get()); |
| 224 |
| 225 data->set_include_tx_power(advertisement.include_tx_power()); |
| 226 |
| 227 *output = std::move(data); |
| 228 return true; |
| 229 } |
| 230 |
| 73 } // namespace mojo | 231 } // namespace mojo |
| OLD | NEW |