/* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #define PACKET_TESTING // Instantiate the tests in the packet files #include "hci/hci_packets.h" #include "os/log.h" #include "packet/bit_inserter.h" #include "packet/raw_builder.h" using bluetooth::packet::BitInserter; using std::vector; namespace bluetooth { namespace hci { std::vector pixel_3_xl_write_extended_inquiry_response{ 0x52, 0x0c, 0xf1, 0x01, 0x0b, 0x09, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x20, 0x33, 0x20, 0x58, 0x4c, 0x19, 0x03, 0x05, 0x11, 0x0a, 0x11, 0x0c, 0x11, 0x0e, 0x11, 0x12, 0x11, 0x15, 0x11, 0x16, 0x11, 0x1f, 0x11, 0x2d, 0x11, 0x2f, 0x11, 0x00, 0x12, 0x32, 0x11, 0x01, 0x05, 0x81, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; std::vector pixel_3_xl_write_extended_inquiry_response_no_uuids{ 0x52, 0x0c, 0xf1, 0x01, 0x0b, 0x09, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x20, 0x33, 0x20, 0x58, 0x4c, 0x01, 0x03, 0x01, 0x05, 0x81, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; std::vector pixel_3_xl_write_extended_inquiry_response_no_uuids_just_eir{ pixel_3_xl_write_extended_inquiry_response_no_uuids.begin() + 4, // skip command, size, and fec_required pixel_3_xl_write_extended_inquiry_response_no_uuids.end()}; TEST(HciPacketsTest, testWriteExtendedInquiryResponse) { std::shared_ptr> view_bytes = std::make_shared>(pixel_3_xl_write_extended_inquiry_response); PacketView packet_bytes_view(view_bytes); auto view = WriteExtendedInquiryResponseView::Create(CommandView::Create(packet_bytes_view)); ASSERT_TRUE(view.IsValid()); auto gap_data = view.GetExtendedInquiryResponse(); ASSERT_GE(gap_data.size(), 4ul); ASSERT_EQ(gap_data[0].data_type_, GapDataType::COMPLETE_LOCAL_NAME); ASSERT_EQ(gap_data[0].data_.size(), 10ul); ASSERT_EQ(gap_data[1].data_type_, GapDataType::COMPLETE_LIST_16_BIT_UUIDS); ASSERT_EQ(gap_data[1].data_.size(), 24ul); ASSERT_EQ(gap_data[2].data_type_, GapDataType::COMPLETE_LIST_32_BIT_UUIDS); ASSERT_EQ(gap_data[2].data_.size(), 0ul); ASSERT_EQ(gap_data[3].data_type_, GapDataType::COMPLETE_LIST_128_BIT_UUIDS); ASSERT_EQ(gap_data[3].data_.size(), 128ul); std::vector no_padding{gap_data.begin(), gap_data.begin() + 4}; auto builder = WriteExtendedInquiryResponseBuilder::Create(view.GetFecRequired(), no_padding); std::shared_ptr> packet_bytes = std::make_shared>(); BitInserter it(*packet_bytes); builder->Serialize(it); EXPECT_EQ(packet_bytes->size(), view_bytes->size()); for (size_t i = 0; i < view_bytes->size(); i++) { ASSERT_EQ(packet_bytes->at(i), view_bytes->at(i)); } } // TODO: Revisit reflection tests for EIR // DEFINE_AND_INSTANTIATE_WriteExtendedInquiryResponseReflectionTest(pixel_3_xl_write_extended_inquiry_response, // pixel_3_xl_write_extended_inquiry_response_no_uuids); std::vector le_set_scan_parameters{ 0x0b, 0x20, 0x07, 0x01, 0x12, 0x00, 0x12, 0x00, 0x01, 0x00, }; TEST(HciPacketsTest, testLeSetScanParameters) { PacketView packet_bytes_view(std::make_shared>(le_set_scan_parameters)); auto view = LeSetScanParametersView::Create(LeScanningCommandView::Create(CommandView::Create(packet_bytes_view))); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(LeScanType::ACTIVE, view.GetLeScanType()); ASSERT_EQ(0x12, view.GetLeScanInterval()); ASSERT_EQ(0x12, view.GetLeScanWindow()); ASSERT_EQ(OwnAddressType::RANDOM_DEVICE_ADDRESS, view.GetOwnAddressType()); ASSERT_EQ(LeScanningFilterPolicy::ACCEPT_ALL, view.GetScanningFilterPolicy()); } std::vector le_set_scan_enable{ 0x0c, 0x20, 0x02, 0x01, 0x00, }; TEST(HciPacketsTest, testLeSetScanEnable) { PacketView packet_bytes_view(std::make_shared>(le_set_scan_enable)); auto view = LeSetScanEnableView::Create(LeScanningCommandView::Create(CommandView::Create(packet_bytes_view))); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(Enable::ENABLED, view.GetLeScanEnable()); ASSERT_EQ(Enable::DISABLED, view.GetFilterDuplicates()); } std::vector le_get_vendor_capabilities{ 0x53, 0xfd, 0x00, }; TEST(HciPacketsTest, testLeGetVendorCapabilities) { PacketView packet_bytes_view(std::make_shared>(le_get_vendor_capabilities)); auto view = LeGetVendorCapabilitiesView::Create(VendorCommandView::Create(CommandView::Create(packet_bytes_view))); ASSERT_TRUE(view.IsValid()); } std::vector le_get_vendor_capabilities_complete{ 0x0e, 0x0c, 0x01, 0x53, 0xfd, 0x00, 0x05, 0x01, 0x00, 0x04, 0x80, 0x01, 0x10, 0x01, }; TEST(HciPacketsTest, testLeGetVendorCapabilitiesComplete) { PacketView packet_bytes_view( std::make_shared>(le_get_vendor_capabilities_complete)); auto view = LeGetVendorCapabilitiesCompleteView::Create(CommandCompleteView::Create(EventView::Create(packet_bytes_view))); ASSERT_TRUE(view.IsValid()); auto base_capabilities = view.GetBaseVendorCapabilities(); ASSERT_EQ(5, base_capabilities.max_advt_instances_); ASSERT_EQ(1, base_capabilities.offloaded_resolution_of_private_address_); ASSERT_EQ(1024, base_capabilities.total_scan_results_storage_); ASSERT_EQ(128, base_capabilities.max_irk_list_sz_); ASSERT_EQ(1, base_capabilities.filtering_support_); ASSERT_EQ(16, base_capabilities.max_filter_); ASSERT_EQ(1, base_capabilities.activity_energy_info_support_); } std::vector le_set_extended_scan_parameters{ 0x41, 0x20, 0x08, 0x01, 0x00, 0x01, 0x01, 0x12, 0x00, 0x12, 0x00, }; TEST(HciPacketsTest, testLeSetExtendedScanParameters) { PacketView packet_bytes_view(std::make_shared>(le_set_extended_scan_parameters)); auto view = LeSetExtendedScanParametersView::Create(LeScanningCommandView::Create(CommandView::Create(packet_bytes_view))); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(1, view.GetScanningPhys()); auto params = view.GetParameters(); ASSERT_EQ(1ul, params.size()); ASSERT_EQ(LeScanType::ACTIVE, params[0].le_scan_type_); ASSERT_EQ(18, params[0].le_scan_interval_); ASSERT_EQ(18, params[0].le_scan_window_); } std::vector le_set_extended_scan_parameters_6553{ 0x41, 0x20, 0x08, 0x01, 0x00, 0x01, 0x01, 0x99, 0x19, 0x99, 0x19, }; TEST(HciPacketsTest, testLeSetExtendedScanParameters_6553) { PacketView packet_bytes_view( std::make_shared>(le_set_extended_scan_parameters_6553)); auto view = LeSetExtendedScanParametersView::Create(LeScanningCommandView::Create(CommandView::Create(packet_bytes_view))); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(1, view.GetScanningPhys()); auto params = view.GetParameters(); ASSERT_EQ(1ul, params.size()); ASSERT_EQ(LeScanType::ACTIVE, params[0].le_scan_type_); ASSERT_EQ(6553, params[0].le_scan_interval_); ASSERT_EQ(6553, params[0].le_scan_window_); } std::vector le_set_extended_scan_enable{ 0x42, 0x20, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, }; TEST(HciPacketsTest, testLeSetExtendedScanEnable) { PacketView packet_bytes_view(std::make_shared>(le_set_extended_scan_enable)); auto view = LeSetExtendedScanEnableView::Create(LeScanningCommandView::Create(CommandView::Create(packet_bytes_view))); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(FilterDuplicates::DISABLED, view.GetFilterDuplicates()); ASSERT_EQ(Enable::ENABLED, view.GetEnable()); ASSERT_EQ(0, view.GetDuration()); ASSERT_EQ(0, view.GetPeriod()); } std::vector le_set_extended_scan_enable_disable{ 0x42, 0x20, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, }; TEST(HciPacketsTest, testLeSetExtendedScanEnableDisable) { PacketView packet_bytes_view( std::make_shared>(le_set_extended_scan_enable_disable)); auto view = LeSetExtendedScanEnableView::Create(LeScanningCommandView::Create(CommandView::Create(packet_bytes_view))); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(FilterDuplicates::ENABLED, view.GetFilterDuplicates()); ASSERT_EQ(Enable::DISABLED, view.GetEnable()); ASSERT_EQ(0, view.GetDuration()); ASSERT_EQ(0, view.GetPeriod()); } std::vector le_extended_create_connection = { 0x43, 0x20, 0x2a, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x30, 0x00, 0x18, 0x00, 0x28, 0x00, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x30, 0x00, 0x18, 0x00, 0x28, 0x00, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00}; TEST(HciPacketsTest, testLeExtendedCreateConnection) { std::shared_ptr> packet_bytes = std::make_shared>(le_extended_create_connection); PacketView packet_bytes_view(packet_bytes); auto view = LeExtendedCreateConnectionView::Create( LeConnectionManagementCommandView::Create(AclCommandView::Create(CommandView::Create(packet_bytes_view)))); ASSERT_TRUE(view.IsValid()); } std::vector le_set_extended_advertising_random_address = { 0x35, 0x20, 0x07, 0x00, 0x77, 0x58, 0xeb, 0xd3, 0x1c, 0x6e, }; TEST(HciPacketsTest, testLeSetAdvertisingSetRandomAddress) { std::shared_ptr> packet_bytes = std::make_shared>(le_set_extended_advertising_random_address); PacketView packet_bytes_view(packet_bytes); auto view = LeSetAdvertisingSetRandomAddressView::Create( LeAdvertisingCommandView::Create(CommandView::Create(packet_bytes_view))); ASSERT_TRUE(view.IsValid()); uint8_t random_address_bytes[] = {0x77, 0x58, 0xeb, 0xd3, 0x1c, 0x6e}; ASSERT_EQ(0, view.GetAdvertisingHandle()); ASSERT_EQ(Address(random_address_bytes), view.GetRandomAddress()); } std::vector le_set_extended_advertising_data{ 0x37, 0x20, 0x12, 0x00, 0x03, 0x01, 0x0e, 0x02, 0x01, 0x02, 0x0a, 0x09, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x20, 0x33, 0x20, 0x58, }; TEST(HciPacketsTest, testLeSetExtendedAdvertisingData) { std::shared_ptr> packet_bytes = std::make_shared>(le_set_extended_advertising_data); PacketView packet_bytes_view(packet_bytes); auto view = LeSetExtendedAdvertisingDataRawView::Create( LeAdvertisingCommandView::Create(CommandView::Create(packet_bytes_view))); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(0, view.GetAdvertisingHandle()); ASSERT_EQ(Operation::COMPLETE_ADVERTISEMENT, view.GetOperation()); ASSERT_EQ(FragmentPreference::CONTROLLER_SHOULD_NOT, view.GetFragmentPreference()); std::vector advertising_data{ 0x02, 0x01, 0x02, 0x0a, 0x09, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x20, 0x33, 0x20, 0x58, }; auto payload = view.GetPayload(); std::vector payload_data(payload.begin(), payload.end()); ASSERT_EQ(advertising_data, payload_data); } std::vector le_set_extended_advertising_parameters_set_0{ 0x36, 0x20, 0x19, 0x00, 0x13, 0x00, 0x90, 0x01, 0x00, 0xc2, 0x01, 0x00, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x01, 0x00, 0x01, 0x01, 0x00, }; TEST(HciPacketsTest, testLeSetExtendedAdvertisingParametersLegacySet0) { std::shared_ptr> packet_bytes = std::make_shared>(le_set_extended_advertising_parameters_set_0); PacketView packet_bytes_view(packet_bytes); auto view = LeSetExtendedAdvertisingParametersLegacyView::Create( LeAdvertisingCommandView::Create(CommandView::Create(packet_bytes_view))); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(0, view.GetAdvertisingHandle()); ASSERT_EQ(400ul, view.GetPrimaryAdvertisingIntervalMin()); ASSERT_EQ(450ul, view.GetPrimaryAdvertisingIntervalMax()); ASSERT_EQ(0x7, view.GetPrimaryAdvertisingChannelMap()); ASSERT_EQ(OwnAddressType::RANDOM_DEVICE_ADDRESS, view.GetOwnAddressType()); ASSERT_EQ(PeerAddressType::PUBLIC_DEVICE_OR_IDENTITY_ADDRESS, view.GetPeerAddressType()); ASSERT_EQ(Address::kEmpty, view.GetPeerAddress()); ASSERT_EQ(AdvertisingFilterPolicy::ALL_DEVICES, view.GetAdvertisingFilterPolicy()); ASSERT_EQ(1, view.GetAdvertisingSid()); ASSERT_EQ(Enable::DISABLED, view.GetScanRequestNotificationEnable()); } std::vector le_set_extended_advertising_parameters_set_1{ 0x36, 0x20, 0x19, 0x01, 0x13, 0x00, 0x90, 0x01, 0x00, 0xc2, 0x01, 0x00, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x01, 0x00, 0x01, 0x01, 0x00, }; TEST(HciPacketsTest, testLeSetExtendedAdvertisingParametersSet1) { std::shared_ptr> packet_bytes = std::make_shared>(le_set_extended_advertising_parameters_set_1); PacketView packet_bytes_view(packet_bytes); auto view = LeSetExtendedAdvertisingParametersLegacyView::Create( LeAdvertisingCommandView::Create(CommandView::Create(packet_bytes_view))); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(1, view.GetAdvertisingHandle()); ASSERT_EQ(400ul, view.GetPrimaryAdvertisingIntervalMin()); ASSERT_EQ(450ul, view.GetPrimaryAdvertisingIntervalMax()); ASSERT_EQ(0x7, view.GetPrimaryAdvertisingChannelMap()); ASSERT_EQ(OwnAddressType::RANDOM_DEVICE_ADDRESS, view.GetOwnAddressType()); ASSERT_EQ(PeerAddressType::PUBLIC_DEVICE_OR_IDENTITY_ADDRESS, view.GetPeerAddressType()); ASSERT_EQ(Address::kEmpty, view.GetPeerAddress()); ASSERT_EQ(AdvertisingFilterPolicy::ALL_DEVICES, view.GetAdvertisingFilterPolicy()); ASSERT_EQ(1, view.GetAdvertisingSid()); ASSERT_EQ(Enable::DISABLED, view.GetScanRequestNotificationEnable()); } std::vector le_set_extended_advertising_parameters_complete{0x0e, 0x05, 0x01, 0x36, 0x20, 0x00, 0xf5}; TEST(HciPacketsTest, testLeSetExtendedAdvertisingParametersComplete) { std::shared_ptr> packet_bytes = std::make_shared>(le_set_extended_advertising_parameters_complete); PacketView packet_bytes_view(packet_bytes); auto view = LeSetExtendedAdvertisingParametersCompleteView::Create( CommandCompleteView::Create(EventView::Create(packet_bytes_view))); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(static_cast(-11), view.GetSelectedTxPower()); } std::vector le_remove_advertising_set_1{ 0x3c, 0x20, 0x01, 0x01, }; TEST(HciPacketsTest, testLeRemoveAdvertisingSet1) { std::shared_ptr> packet_bytes = std::make_shared>(le_remove_advertising_set_1); PacketView packet_bytes_view(packet_bytes); auto view = LeRemoveAdvertisingSetView::Create(LeAdvertisingCommandView::Create(CommandView::Create(packet_bytes_view))); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(1, view.GetAdvertisingHandle()); } std::vector le_set_extended_advertising_disable_1{ 0x39, 0x20, 0x06, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, }; TEST(HciPacketsTest, testLeSetExtendedAdvertisingDisable1) { std::shared_ptr> packet_bytes = std::make_shared>(le_set_extended_advertising_disable_1); PacketView packet_bytes_view(packet_bytes); auto view = LeSetExtendedAdvertisingDisableView::Create( LeAdvertisingCommandView::Create(CommandView::Create(packet_bytes_view))); ASSERT_TRUE(view.IsValid()); auto disabled_set = view.GetDisabledSets(); ASSERT_EQ(1ul, disabled_set.size()); ASSERT_EQ(1, disabled_set[0].advertising_handle_); } TEST(HciPacketsTest, testLeSetAdvertisingDataBuilderLength) { GapData gap_data; gap_data.data_type_ = GapDataType::COMPLETE_LOCAL_NAME; gap_data.data_ = std::vector({'A', ' ', 'g', 'o', 'o', 'd', ' ', 'n', 'a', 'm', 'e'}); auto builder = LeSetAdvertisingDataBuilder::Create({gap_data}); ASSERT_EQ(2ul /*opcode*/ + 1ul /* parameter size */ + 1ul /* data_length */ + 31ul /* data */, builder->size()); auto packet_bytes = std::make_shared>(); packet_bytes->reserve(builder->size()); BitInserter bit_inserter(*packet_bytes); builder->Serialize(bit_inserter); auto command_view = LeAdvertisingCommandView::Create(CommandView::Create(PacketView(packet_bytes))); ASSERT_TRUE(command_view.IsValid()); ASSERT_EQ(1ul /* data_length */ + 31ul /* data */, command_view.GetPayload().size()); auto view = LeSetAdvertisingDataView::Create(command_view); ASSERT_TRUE(view.IsValid()); } TEST(HciPacketsTest, testLeSetScanResponseDataBuilderLength) { GapData gap_data; gap_data.data_type_ = GapDataType::COMPLETE_LOCAL_NAME; gap_data.data_ = std::vector({'A', ' ', 'g', 'o', 'o', 'd', ' ', 'n', 'a', 'm', 'e'}); auto builder = LeSetScanResponseDataBuilder::Create({gap_data}); ASSERT_EQ(2ul /*opcode*/ + 1ul /* parameter size */ + 1ul /*data_length */ + 31ul /* data */, builder->size()); auto packet_bytes = std::make_shared>(); packet_bytes->reserve(builder->size()); BitInserter bit_inserter(*packet_bytes); builder->Serialize(bit_inserter); auto command_view = LeAdvertisingCommandView::Create(CommandView::Create(PacketView(packet_bytes))); ASSERT_TRUE(command_view.IsValid()); ASSERT_EQ(1ul /* data_length */ + 31ul /* data */, command_view.GetPayload().size()); auto view = LeSetScanResponseDataView::Create(command_view); ASSERT_TRUE(view.IsValid()); } TEST(HciPacketsTest, testLeMultiAdvSetAdvertisingDataBuilderLength) { GapData gap_data; gap_data.data_type_ = GapDataType::COMPLETE_LOCAL_NAME; gap_data.data_ = std::vector({'A', ' ', 'g', 'o', 'o', 'd', ' ', 'n', 'a', 'm', 'e'}); uint8_t set = 3; auto builder = LeMultiAdvtSetDataBuilder::Create({gap_data}, set); auto packet_bytes = std::make_shared>(); packet_bytes->reserve(builder->size()); BitInserter bit_inserter(*packet_bytes); builder->Serialize(bit_inserter); auto command_view = LeMultiAdvtSetDataView::Create(LeMultiAdvtView::Create( LeAdvertisingCommandView::Create(CommandView::Create(PacketView(packet_bytes))))); ASSERT_TRUE(command_view.IsValid()); auto view = LeMultiAdvtSetDataView::Create(command_view); ASSERT_TRUE(view.IsValid()); ASSERT_TRUE(view.GetAdvertisingData().size() > 0ul); ASSERT_EQ(view.GetAdvertisingData()[0].data_, gap_data.data_); ASSERT_EQ(view.GetAdvertisingInstance(), 3); } TEST(HciPacketsTest, testLeMultiAdvSetScanResponseDataBuilderLength) { GapData gap_data; gap_data.data_type_ = GapDataType::COMPLETE_LOCAL_NAME; gap_data.data_ = std::vector({'A', ' ', 'g', 'o', 'o', 'd', ' ', 'n', 'a', 'm', 'e'}); uint8_t set = 3; auto builder = LeMultiAdvtSetScanRespBuilder::Create({gap_data}, set); auto packet_bytes = std::make_shared>(); packet_bytes->reserve(builder->size()); BitInserter bit_inserter(*packet_bytes); builder->Serialize(bit_inserter); auto command_view = LeMultiAdvtSetScanRespView::Create(LeMultiAdvtView::Create( LeAdvertisingCommandView::Create(CommandView::Create(PacketView(packet_bytes))))); ASSERT_TRUE(command_view.IsValid()); auto view = LeMultiAdvtSetScanRespView::Create(command_view); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(view.GetAdvertisingData()[0].data_, gap_data.data_); ASSERT_EQ(view.GetAdvertisingInstance(), 3); } TEST(HciPacketsTest, testMsftReadSupportedFeatures) { // MSFT opcode is not defined in PDL. auto msft_opcode = static_cast(0xfc01); auto builder = MsftReadSupportedFeaturesBuilder::Create(msft_opcode); auto packet_bytes = std::make_shared>(); packet_bytes->reserve(builder->size()); BitInserter bit_inserter(*packet_bytes); builder->Serialize(bit_inserter); std::vector expected_bytes{ 0x01, // Vendor command opcode and MSFT base code. 0xfc, 0x01, // Packet length 0x00, // Subcommand Opcode for Read Supported Features }; ASSERT_EQ(expected_bytes, *packet_bytes); } TEST(HciPacketsTest, testMsftLeMonitorAdvUuid) { // MSFT opcode is not defined in PDL. auto msft_opcode = static_cast(0xfc01); auto builder = MsftLeMonitorAdvConditionUuid2Builder::Create( msft_opcode, 0x10 /* RSSI threshold high */, 0x11 /* RSSI threshold low */, 0x12 /* RSSI threshold low timeout */, 0x13 /* RSSI sampling period */, std::array{0x71, 0x72} /* 16-bit UUID */); auto packet_bytes = std::make_shared>(); packet_bytes->reserve(builder->size()); BitInserter bit_inserter(*packet_bytes); builder->Serialize(bit_inserter); std::vector expected_bytes{ 0x01, // Vendor command opcode and MSFT base code. 0xfc, 0x09, // Packet length 0x03, // Subcommand Opcode for LE Monitor Adv 0x10, // RSSI threshold high 0x11, // RSSI threshold low 0x12, // RSSI threshold low timeout 0x13, // RSSI sampling period 0x02, // Condition type = UUID 0x01, // UUID type = 16-bit UUID 0x71, // UUID content 0x72, }; ASSERT_EQ(expected_bytes, *packet_bytes); } TEST(HciPacketsTest, testMsftLeMonitorAdvPatternsEmpty) { // MSFT opcode is not defined in PDL. auto msft_opcode = static_cast(0xfc01); std::vector patterns; auto builder = MsftLeMonitorAdvConditionPatternsBuilder::Create( msft_opcode, 0x10 /* RSSI threshold high */, 0x11 /* RSSI threshold low */, 0x12 /* RSSI threshold low timeout */, 0x13 /* RSSI sampling period */, patterns); auto packet_bytes = std::make_shared>(); packet_bytes->reserve(builder->size()); BitInserter bit_inserter(*packet_bytes); builder->Serialize(bit_inserter); std::vector expected_bytes{ 0x01, // Vendor command opcode and MSFT base code. 0xfc, 0x07, // Packet length 0x03, // Subcommand Opcode for LE Monitor Adv 0x10, // RSSI threshold high 0x11, // RSSI threshold low 0x12, // RSSI threshold low timeout 0x13, // RSSI sampling period 0x01, // Condition type = Patterns 0x00, // Number of patterns }; ASSERT_EQ(expected_bytes, *packet_bytes); } TEST(HciPacketsTest, testMsftLeMonitorAdvPatterns) { // MSFT opcode is not defined in PDL. auto msft_opcode = static_cast(0xfc01); MsftLeMonitorAdvConditionPattern pattern1; pattern1.ad_type_ = 0x03; pattern1.start_of_pattern_ = 0x00; pattern1.pattern_ = {1, 2, 3}; MsftLeMonitorAdvConditionPattern pattern2; pattern2.ad_type_ = 0x0f; pattern2.start_of_pattern_ = 0x10; pattern2.pattern_ = {0xa1, 0xa2}; std::vector patterns{pattern1, pattern2}; auto builder = MsftLeMonitorAdvConditionPatternsBuilder::Create( msft_opcode, 0x10 /* RSSI threshold high */, 0x11 /* RSSI threshold low */, 0x12 /* RSSI threshold low timeout */, 0x13 /* RSSI sampling period */, patterns); auto packet_bytes = std::make_shared>(); packet_bytes->reserve(builder->size()); BitInserter bit_inserter(*packet_bytes); builder->Serialize(bit_inserter); std::vector expected_bytes{ 0x01, // Vendor command opcode and MSFT base code. 0xfc, 0x12, // Packet length 0x03, // Subcommand Opcode for LE Monitor Adv 0x10, // RSSI threshold high 0x11, // RSSI threshold low 0x12, // RSSI threshold low timeout 0x13, // RSSI sampling period 0x01, // Condition type = Patterns 0x02, // Number of patterns // Pattern 1 0x05, // Length 0x03, // AD Type 0x00, // Start of pattern 0x01, // Pattern 0x02, 0x03, // Pattern 2 0x04, // Length 0x0f, // AD Type 0x10, // Start of pattern 0xa1, // Pattern 0xa2, }; ASSERT_EQ(expected_bytes, *packet_bytes); } std::vector msft_read_supported_features_complete{ 0x0e, // command complete event code 0x10, // event size 0x01, // num_hci_command_packets 0x1e, 0xfc, // vendor specific MSFT opcode assigned by Intel 0x00, // status 0x00, // MSFT subcommand opcode 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // supported features 0x02, // MSFT event prefix length 0x87, 0x80, // prefix: MSFT event prefix provided by Intel }; TEST(HciPacketsTest, testMsftReadSupportedFeaturesComplete) { PacketView packet_bytes_view( std::make_shared>(msft_read_supported_features_complete)); auto view = MsftReadSupportedFeaturesCommandCompleteView::Create( MsftCommandCompleteView::Create(CommandCompleteView::Create(EventView::Create(packet_bytes_view)))); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(ErrorCode::SUCCESS, view.GetStatus()); ASSERT_EQ((uint8_t)0x00, (uint8_t)view.GetSubcommandOpcode()); ASSERT_EQ((uint64_t)0x000000000000007f, view.GetSupportedFeatures()); ASSERT_EQ(2ul, view.GetPrefix().size()); uint16_t prefix = 0; for (auto p : view.GetPrefix()) prefix = (prefix << 8) + p; ASSERT_EQ((uint16_t)0x8780, prefix); } } // namespace hci } // namespace bluetooth