[go: nahoru, domu]

blob: 03cbd21ffb94f05fb826ef395c7c95aa9e3ea2c1 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <algorithm>
#include <cctype>
#include <iomanip>
#include <ios>
#include <memory>
#include <sstream>
#include <string>
#include <vector>
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "components/arc/bluetooth/bluetooth_type_converters.h"
#include "device/bluetooth/bluetooth_gatt_service.h"
#include "device/bluetooth/bluetooth_uuid.h"
namespace {
constexpr size_t kAddressSize = 6;
constexpr char kInvalidAddress[] = "00:00:00:00:00:00";
// SDP Service attribute IDs.
constexpr uint16_t kServiceClassIDList = 0x0001;
constexpr uint16_t kProtocolDescriptorList = 0x0004;
constexpr uint16_t kBrowseGroupList = 0x0005;
constexpr uint16_t kBluetoothProfileDescriptorList = 0x0009;
constexpr uint16_t kServiceName = 0x0100;
bool IsNonHex(char c) {
return !isxdigit(c);
}
std::string StripNonHex(const std::string& str) {
std::string result = str;
result.erase(std::remove_if(result.begin(), result.end(), IsNonHex),
result.end());
return result;
}
} // namespace
namespace mojo {
// static
arc::mojom::BluetoothAddressPtr
TypeConverter<arc::mojom::BluetoothAddressPtr, std::string>::Convert(
const std::string& address) {
arc::mojom::BluetoothAddressPtr mojo_addr =
arc::mojom::BluetoothAddress::New();
base::HexStringToBytes(StripNonHex(address), &mojo_addr->address);
return mojo_addr;
}
// static
std::string TypeConverter<std::string, arc::mojom::BluetoothAddress>::Convert(
const arc::mojom::BluetoothAddress& address) {
std::ostringstream addr_stream;
addr_stream << std::setfill('0') << std::hex << std::uppercase;
const std::vector<uint8_t>& bytes = address.address;
if (address.address.size() != kAddressSize)
return std::string(kInvalidAddress);
for (size_t k = 0; k < bytes.size(); k++) {
addr_stream << std::setw(2) << (unsigned int)bytes[k];
addr_stream << ((k == bytes.size() - 1) ? "" : ":");
}
return addr_stream.str();
}
// static
arc::mojom::BluetoothGattStatus
TypeConverter<arc::mojom::BluetoothGattStatus,
device::BluetoothGattService::GattErrorCode>::
Convert(const device::BluetoothGattService::GattErrorCode& error_code) {
arc::mojom::BluetoothGattStatus ret;
switch (error_code) {
case device::BluetoothGattService::GattErrorCode::GATT_ERROR_INVALID_LENGTH:
ret = arc::mojom::BluetoothGattStatus::GATT_INVALID_ATTRIBUTE_LENGTH;
break;
case device::BluetoothGattService::GattErrorCode::GATT_ERROR_NOT_PERMITTED:
ret = arc::mojom::BluetoothGattStatus::GATT_READ_NOT_PERMITTED;
break;
case device::BluetoothGattService::GattErrorCode::GATT_ERROR_NOT_AUTHORIZED:
ret = arc::mojom::BluetoothGattStatus::GATT_INSUFFICIENT_AUTHENTICATION;
break;
case device::BluetoothGattService::GattErrorCode::GATT_ERROR_NOT_SUPPORTED:
ret = arc::mojom::BluetoothGattStatus::GATT_REQUEST_NOT_SUPPORTED;
break;
case device::BluetoothGattService::GattErrorCode::GATT_ERROR_UNKNOWN:
case device::BluetoothGattService::GattErrorCode::GATT_ERROR_FAILED:
case device::BluetoothGattService::GattErrorCode::GATT_ERROR_IN_PROGRESS:
case device::BluetoothGattService::GattErrorCode::GATT_ERROR_NOT_PAIRED:
ret = arc::mojom::BluetoothGattStatus::GATT_FAILURE;
break;
default:
ret = arc::mojom::BluetoothGattStatus::GATT_FAILURE;
break;
}
return ret;
}
// static
arc::mojom::BluetoothSdpAttributePtr
TypeConverter<arc::mojom::BluetoothSdpAttributePtr,
bluez::BluetoothServiceAttributeValueBlueZ>::
Convert(const bluez::BluetoothServiceAttributeValueBlueZ& attr_bluez,
size_t depth) {
auto result = arc::mojom::BluetoothSdpAttribute::New();
result->type = attr_bluez.type();
result->type_size = 0;
switch (result->type) {
case bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE:
result->value.Append(base::MakeUnique<base::Value>());
break;
case bluez::BluetoothServiceAttributeValueBlueZ::UINT:
case bluez::BluetoothServiceAttributeValueBlueZ::INT:
case bluez::BluetoothServiceAttributeValueBlueZ::UUID:
case bluez::BluetoothServiceAttributeValueBlueZ::STRING:
case bluez::BluetoothServiceAttributeValueBlueZ::URL:
case bluez::BluetoothServiceAttributeValueBlueZ::BOOL:
result->type_size = attr_bluez.size();
result->value.Append(attr_bluez.value().CreateDeepCopy());
break;
case bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE:
if (depth + 1 >= arc::kBluetoothSDPMaxDepth) {
result->type = bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE;
result->type_size = 0;
result->value.Append(base::MakeUnique<base::Value>());
return result;
}
for (const auto& child : attr_bluez.sequence()) {
result->sequence.push_back(Convert(child, depth + 1));
}
result->type_size = result->sequence.size();
result->value.Clear();
break;
default:
NOTREACHED();
}
return result;
}
// static
bluez::BluetoothServiceAttributeValueBlueZ
TypeConverter<bluez::BluetoothServiceAttributeValueBlueZ,
arc::mojom::BluetoothSdpAttributePtr>::
Convert(const arc::mojom::BluetoothSdpAttributePtr& attr, size_t depth) {
bluez::BluetoothServiceAttributeValueBlueZ::Type type = attr->type;
switch (type) {
case bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE:
return bluez::BluetoothServiceAttributeValueBlueZ();
case bluez::BluetoothServiceAttributeValueBlueZ::UINT:
case bluez::BluetoothServiceAttributeValueBlueZ::INT:
case bluez::BluetoothServiceAttributeValueBlueZ::UUID:
case bluez::BluetoothServiceAttributeValueBlueZ::STRING:
case bluez::BluetoothServiceAttributeValueBlueZ::URL:
case bluez::BluetoothServiceAttributeValueBlueZ::BOOL: {
if (attr->value.GetSize() != 1) {
return bluez::BluetoothServiceAttributeValueBlueZ(
bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE, 0,
base::MakeUnique<base::Value>());
}
std::unique_ptr<base::Value> value;
attr->value.Remove(0, &value);
return bluez::BluetoothServiceAttributeValueBlueZ(
type, static_cast<size_t>(attr->type_size), std::move(value));
}
case bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE: {
if (depth + 1 >= arc::kBluetoothSDPMaxDepth || attr->sequence.empty()) {
return bluez::BluetoothServiceAttributeValueBlueZ(
bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE, 0,
base::MakeUnique<base::Value>());
}
auto bluez_sequence = base::MakeUnique<
bluez::BluetoothServiceAttributeValueBlueZ::Sequence>();
for (const auto& child : attr->sequence) {
bluez_sequence->push_back(Convert(child, depth + 1));
}
return bluez::BluetoothServiceAttributeValueBlueZ(
std::move(bluez_sequence));
break;
}
default:
NOTREACHED();
}
return bluez::BluetoothServiceAttributeValueBlueZ(
bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE, 0,
base::MakeUnique<base::Value>());
}
// static
arc::mojom::BluetoothSdpRecordPtr
TypeConverter<arc::mojom::BluetoothSdpRecordPtr,
bluez::BluetoothServiceRecordBlueZ>::
Convert(const bluez::BluetoothServiceRecordBlueZ& record_bluez) {
arc::mojom::BluetoothSdpRecordPtr result =
arc::mojom::BluetoothSdpRecord::New();
for (auto id : record_bluez.GetAttributeIds()) {
switch (id) {
case kServiceClassIDList:
case kProtocolDescriptorList:
case kBrowseGroupList:
case kBluetoothProfileDescriptorList:
case kServiceName:
result->attrs[id] = arc::mojom::BluetoothSdpAttribute::From(
record_bluez.GetAttributeValue(id));
break;
default:
// Android does not support this.
break;
}
}
return result;
}
// static
bluez::BluetoothServiceRecordBlueZ
TypeConverter<bluez::BluetoothServiceRecordBlueZ,
arc::mojom::BluetoothSdpRecordPtr>::
Convert(const arc::mojom::BluetoothSdpRecordPtr& record) {
bluez::BluetoothServiceRecordBlueZ record_bluez;
for (const auto& pair : record->attrs) {
switch (pair.first) {
case kServiceClassIDList:
case kProtocolDescriptorList:
case kBrowseGroupList:
case kBluetoothProfileDescriptorList:
case kServiceName:
record_bluez.AddRecordEntry(
pair.first,
pair.second.To<bluez::BluetoothServiceAttributeValueBlueZ>());
break;
default:
NOTREACHED();
break;
}
}
return record_bluez;
}
} // namespace mojo