| // Copyright 2013 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 "device/bluetooth/bluetooth_service_record_mac.h" |
| |
| #import <IOBluetooth/objc/IOBluetoothSDPDataElement.h> |
| #import <IOBluetooth/objc/IOBluetoothSDPServiceRecord.h> |
| #import <IOBluetooth/objc/IOBluetoothSDPUUID.h> |
| |
| #include <string> |
| |
| #include "base/basictypes.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/sys_string_conversions.h" |
| #include "device/bluetooth/bluetooth_uuid.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace { |
| |
| const BluetoothSDPServiceAttributeID kServiceClassIDAttributeId = 0x0001; |
| const BluetoothSDPServiceAttributeID kProtocolDescriptorListAttributeId = |
| 0x0004; |
| const BluetoothSDPServiceAttributeID kServiceNameAttributeId = 0x0100; |
| |
| const uint8 kRfcommChannel = 0x0c; |
| const char kServiceName[] = "Headset Audio Gateway"; |
| |
| const device::BluetoothUUID kExpectedRfcommUuid( |
| "01234567-89ab-cdef-0123-456789abcdef"); |
| const device::BluetoothUUID kExpectedSerialUuid("1101"); |
| |
| const int kMaxUuidSize = 16; |
| |
| } // namespace |
| |
| namespace device { |
| |
| class BluetoothServiceRecordMacTest : public testing::Test { |
| public: |
| |
| IOBluetoothSDPUUID* ConvertUuid(const char* uuid_hex_char, size_t uuid_size) { |
| std::vector<uint8> uuid_bytes_vector; |
| uint8 uuid_buffer[kMaxUuidSize]; |
| base::HexStringToBytes(uuid_hex_char, &uuid_bytes_vector); |
| std::copy(uuid_bytes_vector.begin(), |
| uuid_bytes_vector.end(), |
| uuid_buffer); |
| return [IOBluetoothSDPUUID uuidWithBytes:uuid_buffer length:uuid_size]; |
| } |
| |
| IOBluetoothSDPDataElement* GetServiceClassId(IOBluetoothSDPUUID* uuid) { |
| IOBluetoothSDPDataElement* uuid_element = |
| [IOBluetoothSDPDataElement withElementValue:uuid]; |
| return [IOBluetoothSDPDataElement |
| withElementValue:[NSArray arrayWithObject:uuid_element]]; |
| } |
| |
| IOBluetoothSDPDataElement* GetProtocolDescriptorList(bool supports_rfcomm) { |
| NSMutableArray* protocol_descriptor_list_sequence = [NSMutableArray array]; |
| |
| const uint8 l2cap_uuid_bytes[] = { 0x01, 0x00 }; |
| |
| IOBluetoothSDPUUID* l2cap_uuid = |
| [IOBluetoothSDPUUID uuidWithBytes:l2cap_uuid_bytes length:2]; |
| [protocol_descriptor_list_sequence |
| addObject:[NSArray arrayWithObject:l2cap_uuid]]; |
| |
| if (supports_rfcomm) { |
| const uint8 rfcomm_uuid_bytes[] = { 0x00, 0x03 }; |
| IOBluetoothSDPUUID* rfcomm_uuid = |
| [IOBluetoothSDPUUID uuidWithBytes:rfcomm_uuid_bytes length:2]; |
| NSNumber* rfcomm_channel = |
| [NSNumber numberWithUnsignedChar:kRfcommChannel]; |
| [protocol_descriptor_list_sequence |
| addObject:[NSArray |
| arrayWithObjects:rfcomm_uuid, rfcomm_channel, nil]]; |
| } |
| |
| return [IOBluetoothSDPDataElement |
| withElementValue:protocol_descriptor_list_sequence]; |
| } |
| |
| IOBluetoothSDPDataElement* GetServiceName(const std::string& service_name) { |
| return [IOBluetoothSDPDataElement |
| withElementValue:base::SysUTF8ToNSString(service_name)]; |
| } |
| |
| IOBluetoothSDPServiceRecord* GetServiceRecord( |
| IOBluetoothSDPUUID* uuid, bool supports_rfcomm) { |
| NSMutableDictionary* service_attrs = [NSMutableDictionary dictionary]; |
| |
| if (uuid != nil) { |
| [service_attrs |
| setObject:GetServiceClassId(uuid) |
| forKey:[NSNumber numberWithInt:kServiceClassIDAttributeId]]; |
| } |
| [service_attrs |
| setObject:GetProtocolDescriptorList(supports_rfcomm) |
| forKey:[NSNumber numberWithInt:kProtocolDescriptorListAttributeId]]; |
| [service_attrs |
| setObject:GetServiceName(kServiceName) |
| forKey:[NSNumber numberWithInt:kServiceNameAttributeId]]; |
| |
| return [IOBluetoothSDPServiceRecord withServiceDictionary:service_attrs |
| device:nil]; |
| } |
| }; |
| |
| TEST_F(BluetoothServiceRecordMacTest, RfcommService) { |
| const char rfcomm_uuid_bytes[] = "0123456789abcdef0123456789abcdef"; |
| IOBluetoothSDPUUID* rfcomm_uuid = |
| ConvertUuid(rfcomm_uuid_bytes, sizeof(rfcomm_uuid_bytes) / 2); |
| |
| BluetoothServiceRecordMac record(GetServiceRecord(rfcomm_uuid, true)); |
| EXPECT_EQ(kServiceName, record.name()); |
| EXPECT_TRUE(record.SupportsRfcomm()); |
| EXPECT_EQ(kRfcommChannel, record.rfcomm_channel()); |
| EXPECT_EQ(kExpectedRfcommUuid, record.uuid()); |
| } |
| |
| TEST_F(BluetoothServiceRecordMacTest, ShortUuid) { |
| const char short_uuid_bytes[] = "1101"; |
| IOBluetoothSDPUUID* short_uuid = |
| ConvertUuid(short_uuid_bytes, sizeof(short_uuid_bytes) / 2); |
| |
| BluetoothServiceRecordMac record(GetServiceRecord(short_uuid, false)); |
| EXPECT_EQ(kExpectedSerialUuid, record.uuid()); |
| } |
| |
| TEST_F(BluetoothServiceRecordMacTest, MediumUuid) { |
| const char medium_uuid_bytes[] = "00001101"; |
| IOBluetoothSDPUUID* medium_uuid = |
| ConvertUuid(medium_uuid_bytes, sizeof(medium_uuid_bytes) / 2); |
| |
| BluetoothServiceRecordMac record(GetServiceRecord(medium_uuid, false)); |
| EXPECT_EQ(kExpectedSerialUuid, record.uuid()); |
| } |
| |
| TEST_F(BluetoothServiceRecordMacTest, UpperCaseUuid) { |
| const char upper_case_uuid_bytes[] = "0123456789ABCDEF0123456789ABCDEF"; |
| IOBluetoothSDPUUID* upper_case_uuid = |
| ConvertUuid(upper_case_uuid_bytes, sizeof(upper_case_uuid_bytes) / 2); |
| |
| BluetoothServiceRecordMac record(GetServiceRecord(upper_case_uuid, false)); |
| EXPECT_EQ(kExpectedRfcommUuid, record.uuid()); |
| } |
| |
| TEST_F(BluetoothServiceRecordMacTest, InvalidUuid) { |
| BluetoothServiceRecordMac record(GetServiceRecord(nil, false)); |
| EXPECT_FALSE(record.uuid().IsValid()); |
| } |
| |
| } // namespace device |