OP_CODE_MAPPING(LE_READ_LOCAL_SUPPORTED_FEATURES)
OP_CODE_MAPPING(LE_SET_RANDOM_ADDRESS)
OP_CODE_MAPPING(LE_SET_ADVERTISING_PARAMETERS)
- OP_CODE_MAPPING(LE_READ_ADVERTISING_CHANNEL_TX_POWER)
+ OP_CODE_MAPPING(LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER)
OP_CODE_MAPPING(LE_SET_ADVERTISING_DATA)
OP_CODE_MAPPING(LE_SET_SCAN_RESPONSE_DATA)
OP_CODE_MAPPING(LE_SET_ADVERTISING_ENABLE)
LE_READ_LOCAL_SUPPORTED_FEATURES = 0x2003,
LE_SET_RANDOM_ADDRESS = 0x2005,
LE_SET_ADVERTISING_PARAMETERS = 0x2006,
- LE_READ_ADVERTISING_CHANNEL_TX_POWER = 0x2007,
+ LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER = 0x2007,
LE_SET_ADVERTISING_DATA = 0x2008,
LE_SET_SCAN_RESPONSE_DATA = 0x2009,
LE_SET_ADVERTISING_ENABLE = 0x200A,
LE_READ_LOCAL_SUPPORTED_FEATURES = 252,
LE_SET_RANDOM_ADDRESS = 254,
LE_SET_ADVERTISING_PARAMETERS = 255,
- LE_READ_ADVERTISING_CHANNEL_TX_POWER = 256,
+ LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER = 256,
LE_SET_ADVERTISING_DATA = 257,
LE_SET_SCAN_RESPONSE_DATA = 260,
LE_SET_ADVERTISING_ENABLE = 261,
status : ErrorCode,
}
-packet LeReadAdvertisingChannelTxPower : LeAdvertisingCommand (op_code = LE_READ_ADVERTISING_CHANNEL_TX_POWER) {
+packet LeReadAdvertisingPhysicalChannelTxPower : LeAdvertisingCommand (op_code = LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER) {
}
-packet LeReadAdvertisingChannelTxPowerComplete : CommandComplete (command_op_code = LE_READ_ADVERTISING_CHANNEL_TX_POWER) {
+packet LeReadAdvertisingPhysicalChannelTxPowerComplete : CommandComplete (command_op_code = LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER) {
status : ErrorCode,
- transmit_power_level : 8, // (-20dBm to 10dBm) Accuracy: +/-4dB
+ transmit_power_level : 8, // (-127dBm to 20dBm) Accuracy: +/-4dB
}
packet LeSetAdvertisingData : LeAdvertisingCommand (op_code = LE_SET_ADVERTISING_DATA) {
advertising_api_type_ = AdvertisingApiType::ANDROID_HCI;
} else {
advertising_api_type_ = AdvertisingApiType::LEGACY;
+ hci_layer_->EnqueueCommand(
+ LeReadAdvertisingPhysicalChannelTxPowerBuilder::Create(),
+ handler->BindOnceOn(this, &impl::on_read_advertising_physical_channel_tx_power));
}
}
hci::HciLayer* hci_layer_;
hci::Controller* controller_;
uint16_t le_maximum_advertising_data_length_;
+ int8_t le_physical_channel_tx_power_ = 0;
hci::LeAdvertisingInterface* le_advertising_interface_;
std::map<AdvertiserId, Advertiser> advertising_sets_;
hci::LeAddressManager* le_address_manager_;
AdvertisingApiType advertising_api_type_{0};
+ void on_read_advertising_physical_channel_tx_power(CommandCompleteView view) {
+ auto complete_view = LeReadAdvertisingPhysicalChannelTxPowerCompleteView::Create(view);
+ ASSERT(complete_view.IsValid());
+ if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
+ LOG_INFO("Got a command complete with status %s", ErrorCodeText(complete_view.GetStatus()).c_str());
+ return;
+ }
+ le_physical_channel_tx_power_ = complete_view.GetTransmitPowerLevel();
+ }
+
template <class View>
void on_set_advertising_enable_complete(bool enable, std::vector<EnabledSet> enabled_sets, CommandCompleteView view) {
ASSERT(view.IsValid());
} else {
int reg_id = id_map_[id];
advertising_sets_[enabled_set.advertising_handle_].started = true;
- // TODO read tx power
- advertising_callbacks_->OnAdvertisingSetStarted(reg_id, id, 0x00, advertising_status);
+ advertising_callbacks_->OnAdvertisingSetStarted(reg_id, id, le_physical_channel_tx_power_, advertising_status);
}
}
}
switch (opcode) {
case OpCode::LE_SET_ADVERTISING_PARAMETERS:
- // TODO read tx power
- advertising_callbacks_->OnAdvertisingParametersUpdated(id, 0x00, advertising_status);
+ advertising_callbacks_->OnAdvertisingParametersUpdated(id, le_physical_channel_tx_power_, advertising_status);
break;
case OpCode::LE_SET_ADVERTISING_DATA:
case OpCode::LE_SET_EXTENDED_ADVERTISING_DATA:
mock_advertising_callback_,
OnAdvertisingSetStarted(0x00, advertiser_id_, 0x00, AdvertisingCallback::AdvertisingStatus::SUCCESS));
std::vector<OpCode> adv_opcodes = {
+ OpCode::LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER,
OpCode::LE_SET_ADVERTISING_PARAMETERS,
OpCode::LE_SET_SCAN_RESPONSE_DATA,
OpCode::LE_SET_ADVERTISING_DATA,
for (size_t i = 0; i < adv_opcodes.size(); i++) {
auto packet_view = test_hci_layer_->GetCommandPacket(adv_opcodes[i]);
CommandPacketView command_packet_view = CommandPacketView::Create(packet_view);
- test_hci_layer_->IncomingEvent(
- CommandCompleteBuilder::Create(uint8_t{1}, adv_opcodes[i], std::make_unique<RawBuilder>(success_vector)));
+ if (adv_opcodes[i] == OpCode::LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER) {
+ test_hci_layer_->IncomingEvent(
+ LeReadAdvertisingPhysicalChannelTxPowerCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS, 0x00));
+ } else {
+ test_hci_layer_->IncomingEvent(
+ CommandCompleteBuilder::Create(uint8_t{1}, adv_opcodes[i], std::make_unique<RawBuilder>(success_vector)));
+ }
test_hci_layer_->SetCommandFuture();
}
sync_client_handler();
0x00, advertising_config, scan_callback, set_terminated_callback, client_handler_);
ASSERT_NE(LeAdvertisingManager::kInvalidId, id);
std::vector<OpCode> adv_opcodes = {
+ OpCode::LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER,
OpCode::LE_SET_ADVERTISING_PARAMETERS,
OpCode::LE_SET_SCAN_RESPONSE_DATA,
OpCode::LE_SET_ADVERTISING_DATA,
auto packet_view = test_hci_layer_->GetCommandPacket(adv_opcodes[i]);
CommandPacketView command_packet_view = CommandPacketView::Create(packet_view);
auto command = ConnectionManagementCommandView::Create(AclCommandView::Create(command_packet_view));
- test_hci_layer_->IncomingEvent(
- CommandCompleteBuilder::Create(uint8_t{1}, adv_opcodes[i], std::make_unique<RawBuilder>(success_vector)));
+ if (adv_opcodes[i] == OpCode::LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER) {
+ test_hci_layer_->IncomingEvent(
+ LeReadAdvertisingPhysicalChannelTxPowerCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS, 0x00));
+ } else {
+ test_hci_layer_->IncomingEvent(
+ CommandCompleteBuilder::Create(uint8_t{1}, adv_opcodes[i], std::make_unique<RawBuilder>(success_vector)));
+ }
test_hci_layer_->SetCommandFuture();
}
sync_client_handler();
SET_HANDLER(OpCode::LE_SET_RANDOM_ADDRESS, LeSetRandomAddress);
SET_HANDLER(OpCode::LE_SET_ADVERTISING_PARAMETERS,
LeSetAdvertisingParameters);
+ SET_HANDLER(OpCode::LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER,
+ LeReadAdvertisingPhysicalChannelTxPower);
SET_HANDLER(OpCode::LE_SET_ADVERTISING_DATA, LeSetAdvertisingData);
SET_HANDLER(OpCode::LE_SET_SCAN_RESPONSE_DATA, LeSetScanResponseData);
SET_HANDLER(OpCode::LE_SET_ADVERTISING_ENABLE, LeSetAdvertisingEnable);
send_event_(std::move(packet));
}
+void DualModeController::LeReadAdvertisingPhysicalChannelTxPower(
+ CommandPacketView command) {
+ auto command_view =
+ gd_hci::LeReadAdvertisingPhysicalChannelTxPowerView::Create(
+ gd_hci::LeAdvertisingCommandView::Create(command));
+ ASSERT(command_view.IsValid());
+ auto packet =
+ bluetooth::hci::LeReadAdvertisingPhysicalChannelTxPowerCompleteBuilder::
+ Create(kNumCommandPackets, ErrorCode::SUCCESS,
+ properties_.GetLeAdvertisingPhysicalChannelTxPower());
+ send_event_(std::move(packet));
+}
+
void DualModeController::LeSetAdvertisingData(CommandPacketView command) {
auto command_view = gd_hci::LeSetAdvertisingDataView::Create(
gd_hci::LeAdvertisingCommandView::Create(command));
// 7.8.5
void LeSetAdvertisingParameters(CommandPacketView args);
+ // 7.8.6
+ void LeReadAdvertisingPhysicalChannelTxPower(CommandPacketView args);
+
// 7.8.7
void LeSetAdvertisingData(CommandPacketView args);
return le_supported_features_;
}
+ // Specification Version 5.2, Volume 4, Part E, Section 7.8.6
+ int8_t GetLeAdvertisingPhysicalChannelTxPower() const {
+ return le_advertising_physical_channel_tx_power_;
+ }
+
void SetLeSupportedFeatures(uint64_t features) {
le_supported_features_ = features;
}
uint8_t le_connect_list_size_;
uint8_t le_resolving_list_size_;
uint64_t le_supported_features_{0x075b3fd8fe8ffeff};
+ int8_t le_advertising_physical_channel_tx_power_{0x00};
uint64_t le_supported_states_;
uint64_t le_event_mask_{0x01f};
std::vector<uint8_t> le_vendor_cap_;