1 // 2 // Copyright 2015 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #define LOG_TAG "dual_mode_controller" 18 19 #include "vendor_libs/test_vendor_lib/include/dual_mode_controller.h" 20 21 #include "base/logging.h" 22 #include "base/files/file_util.h" 23 #include "base/json/json_reader.h" 24 #include "base/values.h" 25 #include "vendor_libs/test_vendor_lib/include/event_packet.h" 26 #include "vendor_libs/test_vendor_lib/include/hci_transport.h" 27 28 extern "C" { 29 #include "stack/include/hcidefs.h" 30 #include "osi/include/log.h" 31 } // extern "C" 32 33 namespace { 34 35 // Included in certain events to indicate success (specific to the event 36 // context). 37 const uint8_t kSuccessStatus = 0; 38 39 // The default number encoded in event packets to indicate to the HCI how many 40 // command packets it can send to the controller. 41 const uint8_t kNumHciCommandPackets = 1; 42 43 // The location of the config file loaded to populate controller attributes. 44 const std::string kControllerPropertiesFile = 45 "/etc/bluetooth/controller_properties.json"; 46 47 // Inquiry modes for specifiying inquiry result formats. 48 const uint8_t kStandardInquiry = 0x00; 49 const uint8_t kRssiInquiry = 0x01; 50 const uint8_t kExtendedOrRssiInquiry = 0x02; 51 52 // The bd address of another (fake) device. 53 const std::vector<uint8_t> kOtherDeviceBdAddress = {6, 5, 4, 3, 2, 1}; 54 55 // Fake inquiry response for a fake device. 56 const std::vector<uint8_t> kPageScanRepetitionMode = {0}; 57 const std::vector<uint8_t> kPageScanPeriodMode = {0}; 58 const std::vector<uint8_t> kPageScanMode = {0}; 59 const std::vector<uint8_t> kClassOfDevice = {1, 2, 3}; 60 const std::vector<uint8_t> kClockOffset = {1, 2}; 61 62 void LogCommand(const char* command) { 63 LOG_INFO(LOG_TAG, "Controller performing command: %s", command); 64 } 65 66 // Functions used by JSONValueConverter to read stringified JSON into Properties 67 // object. 68 bool ParseUint8t(const base::StringPiece& value, uint8_t* field) { 69 *field = std::stoi(value.as_string()); 70 return true; 71 } 72 73 bool ParseUint16t(const base::StringPiece& value, uint16_t* field) { 74 *field = std::stoi(value.as_string()); 75 return true; 76 } 77 78 bool ParseUint8tVector(const base::StringPiece& value, 79 std::vector<uint8_t>* field) { 80 for (char& c : value.as_string()) 81 field->push_back(c - '0'); 82 return true; 83 } 84 85 } // namespace 86 87 namespace test_vendor_lib { 88 89 void DualModeController::SendCommandComplete( 90 uint16_t command_opcode, 91 const std::vector<uint8_t>& return_parameters) const { 92 std::unique_ptr<EventPacket> command_complete = 93 EventPacket::CreateCommandCompleteEvent( 94 kNumHciCommandPackets, command_opcode, return_parameters); 95 send_event_(std::move(command_complete)); 96 } 97 98 void DualModeController::SendCommandCompleteSuccess( 99 uint16_t command_opcode) const { 100 SendCommandComplete(command_opcode, {kSuccessStatus}); 101 } 102 103 void DualModeController::SendCommandStatus(uint8_t status, 104 uint16_t command_opcode) const { 105 std::unique_ptr<EventPacket> command_status = 106 EventPacket::CreateCommandStatusEvent(status, kNumHciCommandPackets, 107 command_opcode); 108 send_event_(std::move(command_status)); 109 } 110 111 void DualModeController::SendCommandStatusSuccess( 112 uint16_t command_opcode) const { 113 SendCommandStatus(kSuccessStatus, command_opcode); 114 } 115 116 void DualModeController::SendInquiryResult() const { 117 std::unique_ptr<EventPacket> inquiry_result = 118 EventPacket::CreateInquiryResultEvent( 119 1, kOtherDeviceBdAddress, kPageScanRepetitionMode, 120 kPageScanPeriodMode, kPageScanMode, kClassOfDevice, kClockOffset); 121 send_event_(std::move(inquiry_result)); 122 } 123 124 void DualModeController::SendExtendedInquiryResult( 125 const std::string& name, const std::string& address) const { 126 std::vector<uint8_t> rssi = {0}; 127 std::vector<uint8_t> extended_inquiry_data = {name.length() + 1, 0x09}; 128 std::copy(name.begin(), name.end(), 129 std::back_inserter(extended_inquiry_data)); 130 std::vector<uint8_t> bd_address(address.begin(), address.end()); 131 // TODO(dennischeng): Use constants for parameter sizes, here and elsewhere. 132 while (extended_inquiry_data.size() < 240) { 133 extended_inquiry_data.push_back(0); 134 } 135 std::unique_ptr<EventPacket> extended_inquiry_result = 136 EventPacket::CreateExtendedInquiryResultEvent( 137 bd_address, kPageScanRepetitionMode, kPageScanPeriodMode, 138 kClassOfDevice, kClockOffset, rssi, extended_inquiry_data); 139 send_event_(std::move(extended_inquiry_result)); 140 } 141 142 DualModeController::DualModeController() 143 : state_(kStandby), 144 test_channel_state_(kNone), 145 properties_(kControllerPropertiesFile) { 146 #define SET_HANDLER(opcode, method) \ 147 active_hci_commands_[opcode] = \ 148 std::bind(&DualModeController::method, this, std::placeholders::_1); 149 SET_HANDLER(HCI_RESET, HciReset); 150 SET_HANDLER(HCI_READ_BUFFER_SIZE, HciReadBufferSize); 151 SET_HANDLER(HCI_HOST_BUFFER_SIZE, HciHostBufferSize); 152 SET_HANDLER(HCI_READ_LOCAL_VERSION_INFO, HciReadLocalVersionInformation); 153 SET_HANDLER(HCI_READ_BD_ADDR, HciReadBdAddr); 154 SET_HANDLER(HCI_READ_LOCAL_SUPPORTED_CMDS, HciReadLocalSupportedCommands); 155 SET_HANDLER(HCI_READ_LOCAL_EXT_FEATURES, HciReadLocalExtendedFeatures); 156 SET_HANDLER(HCI_WRITE_SIMPLE_PAIRING_MODE, HciWriteSimplePairingMode); 157 SET_HANDLER(HCI_WRITE_LE_HOST_SUPPORT, HciWriteLeHostSupport); 158 SET_HANDLER(HCI_SET_EVENT_MASK, HciSetEventMask); 159 SET_HANDLER(HCI_WRITE_INQUIRY_MODE, HciWriteInquiryMode); 160 SET_HANDLER(HCI_WRITE_PAGESCAN_TYPE, HciWritePageScanType); 161 SET_HANDLER(HCI_WRITE_INQSCAN_TYPE, HciWriteInquiryScanType); 162 SET_HANDLER(HCI_WRITE_CLASS_OF_DEVICE, HciWriteClassOfDevice); 163 SET_HANDLER(HCI_WRITE_PAGE_TOUT, HciWritePageTimeout); 164 SET_HANDLER(HCI_WRITE_DEF_POLICY_SETTINGS, HciWriteDefaultLinkPolicySettings); 165 SET_HANDLER(HCI_READ_LOCAL_NAME, HciReadLocalName); 166 SET_HANDLER(HCI_CHANGE_LOCAL_NAME, HciWriteLocalName); 167 SET_HANDLER(HCI_WRITE_EXT_INQ_RESPONSE, HciWriteExtendedInquiryResponse); 168 SET_HANDLER(HCI_WRITE_VOICE_SETTINGS, HciWriteVoiceSetting); 169 SET_HANDLER(HCI_WRITE_CURRENT_IAC_LAP, HciWriteCurrentIacLap); 170 SET_HANDLER(HCI_WRITE_INQUIRYSCAN_CFG, HciWriteInquiryScanActivity); 171 SET_HANDLER(HCI_WRITE_SCAN_ENABLE, HciWriteScanEnable); 172 SET_HANDLER(HCI_SET_EVENT_FILTER, HciSetEventFilter); 173 SET_HANDLER(HCI_INQUIRY, HciInquiry); 174 SET_HANDLER(HCI_INQUIRY_CANCEL, HciInquiryCancel); 175 SET_HANDLER(HCI_DELETE_STORED_LINK_KEY, HciDeleteStoredLinkKey); 176 SET_HANDLER(HCI_RMT_NAME_REQUEST, HciRemoteNameRequest); 177 #undef SET_HANDLER 178 179 #define SET_TEST_HANDLER(command_name, method) \ 180 active_test_channel_commands_[command_name] = \ 181 std::bind(&DualModeController::method, this, std::placeholders::_1); 182 SET_TEST_HANDLER("CLEAR", TestChannelClear); 183 SET_TEST_HANDLER("CLEAR_EVENT_DELAY", TestChannelClearEventDelay); 184 SET_TEST_HANDLER("DISCOVER", TestChannelDiscover); 185 SET_TEST_HANDLER("SET_EVENT_DELAY", TestChannelSetEventDelay); 186 SET_TEST_HANDLER("TIMEOUT_ALL", TestChannelTimeoutAll); 187 #undef SET_TEST_HANDLER 188 } 189 190 void DualModeController::RegisterHandlersWithHciTransport( 191 HciTransport& transport) { 192 transport.RegisterCommandHandler(std::bind(&DualModeController::HandleCommand, 193 this, std::placeholders::_1)); 194 } 195 196 void DualModeController::RegisterHandlersWithTestChannelTransport( 197 TestChannelTransport& transport) { 198 transport.RegisterCommandHandler( 199 std::bind(&DualModeController::HandleTestChannelCommand, this, 200 std::placeholders::_1, std::placeholders::_2)); 201 } 202 203 void DualModeController::HandleTestChannelCommand( 204 const std::string& name, const std::vector<std::string>& args) { 205 if (active_test_channel_commands_.count(name) == 0) 206 return; 207 active_test_channel_commands_[name](args); 208 } 209 210 void DualModeController::HandleCommand( 211 std::unique_ptr<CommandPacket> command_packet) { 212 uint16_t opcode = command_packet->GetOpcode(); 213 LOG_INFO(LOG_TAG, "Command opcode: 0x%04X, OGF: 0x%04X, OCF: 0x%04X", opcode, 214 command_packet->GetOGF(), command_packet->GetOCF()); 215 216 // The command hasn't been registered with the handler yet. There is nothing 217 // to do. 218 if (active_hci_commands_.count(opcode) == 0) 219 return; 220 else if (test_channel_state_ == kTimeoutAll) 221 return; 222 active_hci_commands_[opcode](command_packet->GetPayload()); 223 } 224 225 void DualModeController::RegisterEventChannel( 226 std::function<void(std::unique_ptr<EventPacket>)> callback) { 227 send_event_ = callback; 228 } 229 230 void DualModeController::RegisterDelayedEventChannel( 231 std::function<void(std::unique_ptr<EventPacket>, base::TimeDelta)> 232 callback) { 233 send_delayed_event_ = callback; 234 SetEventDelay(0); 235 } 236 237 void DualModeController::SetEventDelay(int64_t delay) { 238 if (delay < 0) 239 delay = 0; 240 send_event_ = std::bind(send_delayed_event_, std::placeholders::_1, 241 base::TimeDelta::FromMilliseconds(delay)); 242 } 243 244 void DualModeController::TestChannelClear( 245 const std::vector<std::string>& args) { 246 LogCommand("TestChannel Clear"); 247 test_channel_state_ = kNone; 248 SetEventDelay(0); 249 } 250 251 void DualModeController::TestChannelDiscover( 252 const std::vector<std::string>& args) { 253 LogCommand("TestChannel Discover"); 254 for (size_t i = 0; i < args.size()-1; i+=2) 255 SendExtendedInquiryResult(args[i], args[i+1]); 256 } 257 258 void DualModeController::TestChannelTimeoutAll( 259 const std::vector<std::string>& args) { 260 LogCommand("TestChannel Timeout All"); 261 test_channel_state_ = kTimeoutAll; 262 } 263 264 void DualModeController::TestChannelSetEventDelay( 265 const std::vector<std::string>& args) { 266 LogCommand("TestChannel Set Event Delay"); 267 test_channel_state_ = kDelayedResponse; 268 SetEventDelay(std::stoi(args[0])); 269 } 270 271 void DualModeController::TestChannelClearEventDelay( 272 const std::vector<std::string>& args) { 273 LogCommand("TestChannel Clear Event Delay"); 274 test_channel_state_ = kNone; 275 SetEventDelay(0); 276 } 277 278 void DualModeController::HciReset(const std::vector<uint8_t>& /* args */) { 279 LogCommand("Reset"); 280 state_ = kStandby; 281 SendCommandCompleteSuccess(HCI_RESET); 282 } 283 284 void DualModeController::HciReadBufferSize( 285 const std::vector<uint8_t>& /* args */) { 286 LogCommand("Read Buffer Size"); 287 SendCommandComplete(HCI_READ_BUFFER_SIZE, properties_.GetBufferSize()); 288 } 289 290 void DualModeController::HciHostBufferSize( 291 const std::vector<uint8_t>& /* args */) { 292 LogCommand("Host Buffer Size"); 293 SendCommandCompleteSuccess(HCI_HOST_BUFFER_SIZE); 294 } 295 296 void DualModeController::HciReadLocalVersionInformation( 297 const std::vector<uint8_t>& /* args */) { 298 LogCommand("Read Local Version Information"); 299 SendCommandComplete(HCI_READ_LOCAL_VERSION_INFO, 300 properties_.GetLocalVersionInformation()); 301 } 302 303 void DualModeController::HciReadBdAddr(const std::vector<uint8_t>& /* args */) { 304 LogCommand("Read Bd Addr"); 305 std::vector<uint8_t> bd_address_with_status = properties_.GetBdAddress(); 306 bd_address_with_status.insert(bd_address_with_status.begin(), 307 kSuccessStatus); 308 SendCommandComplete(HCI_READ_BD_ADDR, bd_address_with_status); 309 } 310 311 void DualModeController::HciReadLocalSupportedCommands( 312 const std::vector<uint8_t>& /* args */) { 313 LogCommand("Read Local Supported Commands"); 314 SendCommandComplete(HCI_READ_LOCAL_SUPPORTED_CMDS, 315 properties_.GetLocalSupportedCommands()); 316 } 317 318 void DualModeController::HciReadLocalExtendedFeatures( 319 const std::vector<uint8_t>& args) { 320 LogCommand("Read Local Extended Features"); 321 SendCommandComplete(HCI_READ_LOCAL_EXT_FEATURES, 322 properties_.GetLocalExtendedFeatures(args[0])); 323 } 324 325 void DualModeController::HciWriteSimplePairingMode( 326 const std::vector<uint8_t>& /* args */) { 327 LogCommand("Write Simple Pairing Mode"); 328 SendCommandCompleteSuccess(HCI_WRITE_SIMPLE_PAIRING_MODE); 329 } 330 331 void DualModeController::HciWriteLeHostSupport( 332 const std::vector<uint8_t>& /* args */) { 333 LogCommand("Write Le Host Support"); 334 SendCommandCompleteSuccess(HCI_WRITE_LE_HOST_SUPPORT); 335 } 336 337 void DualModeController::HciSetEventMask( 338 const std::vector<uint8_t>& /* args */) { 339 LogCommand("Set Event Mask"); 340 SendCommandCompleteSuccess(HCI_SET_EVENT_MASK); 341 } 342 343 void DualModeController::HciWriteInquiryMode(const std::vector<uint8_t>& args) { 344 LogCommand("Write Inquiry Mode"); 345 CHECK(args.size() == 1); 346 inquiry_mode_ = args[0]; 347 SendCommandCompleteSuccess(HCI_WRITE_INQUIRY_MODE); 348 } 349 350 void DualModeController::HciWritePageScanType( 351 const std::vector<uint8_t>& /* args */) { 352 LogCommand("Write Page Scan Type"); 353 SendCommandCompleteSuccess(HCI_WRITE_PAGESCAN_TYPE); 354 } 355 356 void DualModeController::HciWriteInquiryScanType( 357 const std::vector<uint8_t>& /* args */) { 358 LogCommand("Write Inquiry Scan Type"); 359 SendCommandCompleteSuccess(HCI_WRITE_INQSCAN_TYPE); 360 } 361 362 void DualModeController::HciWriteClassOfDevice( 363 const std::vector<uint8_t>& /* args */) { 364 LogCommand("Write Class Of Device"); 365 SendCommandCompleteSuccess(HCI_WRITE_CLASS_OF_DEVICE); 366 } 367 368 void DualModeController::HciWritePageTimeout( 369 const std::vector<uint8_t>& /* args */) { 370 LogCommand("Write Page Timeout"); 371 SendCommandCompleteSuccess(HCI_WRITE_PAGE_TOUT); 372 } 373 374 void DualModeController::HciWriteDefaultLinkPolicySettings( 375 const std::vector<uint8_t>& /* args */) { 376 LogCommand("Write Default Link Policy Settings"); 377 SendCommandCompleteSuccess(HCI_WRITE_DEF_POLICY_SETTINGS); 378 } 379 380 void DualModeController::HciReadLocalName( 381 const std::vector<uint8_t>& /* args */) { 382 LogCommand("Get Local Name"); 383 SendCommandComplete(HCI_READ_LOCAL_NAME, properties_.GetLocalName()); 384 } 385 386 void DualModeController::HciWriteLocalName( 387 const std::vector<uint8_t>& /* args */) { 388 LogCommand("Write Local Name"); 389 SendCommandCompleteSuccess(HCI_CHANGE_LOCAL_NAME); 390 } 391 392 void DualModeController::HciWriteExtendedInquiryResponse( 393 const std::vector<uint8_t>& /* args */) { 394 LogCommand("Write Extended Inquiry Response"); 395 SendCommandCompleteSuccess(HCI_WRITE_EXT_INQ_RESPONSE); 396 } 397 398 void DualModeController::HciWriteVoiceSetting( 399 const std::vector<uint8_t>& /* args */) { 400 LogCommand("Write Voice Setting"); 401 SendCommandCompleteSuccess(HCI_WRITE_VOICE_SETTINGS); 402 } 403 404 void DualModeController::HciWriteCurrentIacLap( 405 const std::vector<uint8_t>& /* args */) { 406 LogCommand("Write Current IAC LAP"); 407 SendCommandCompleteSuccess(HCI_WRITE_CURRENT_IAC_LAP); 408 } 409 410 void DualModeController::HciWriteInquiryScanActivity( 411 const std::vector<uint8_t>& /* args */) { 412 LogCommand("Write Inquiry Scan Activity"); 413 SendCommandCompleteSuccess(HCI_WRITE_INQUIRYSCAN_CFG); 414 } 415 416 void DualModeController::HciWriteScanEnable( 417 const std::vector<uint8_t>& /* args */) { 418 LogCommand("Write Scan Enable"); 419 SendCommandCompleteSuccess(HCI_WRITE_SCAN_ENABLE); 420 } 421 422 void DualModeController::HciSetEventFilter( 423 const std::vector<uint8_t>& /* args */) { 424 LogCommand("Set Event Filter"); 425 SendCommandCompleteSuccess(HCI_SET_EVENT_FILTER); 426 } 427 428 void DualModeController::HciInquiry(const std::vector<uint8_t>& /* args */) { 429 LogCommand("Inquiry"); 430 state_ = kInquiry; 431 SendCommandStatusSuccess(HCI_INQUIRY); 432 switch (inquiry_mode_) { 433 case (kStandardInquiry): 434 SendInquiryResult(); 435 break; 436 437 case (kRssiInquiry): 438 LOG_INFO(LOG_TAG, "RSSI Inquiry Mode currently not supported."); 439 break; 440 441 case (kExtendedOrRssiInquiry): 442 SendExtendedInquiryResult("FooBar", "123456"); 443 break; 444 } 445 } 446 447 void DualModeController::HciInquiryCancel( 448 const std::vector<uint8_t>& /* args */) { 449 LogCommand("Inquiry Cancel"); 450 CHECK(state_ == kInquiry); 451 state_ = kStandby; 452 SendCommandCompleteSuccess(HCI_INQUIRY_CANCEL); 453 } 454 455 void DualModeController::HciDeleteStoredLinkKey( 456 const std::vector<uint8_t>& args) { 457 LogCommand("Delete Stored Link Key"); 458 /* Check the last octect in |args|. If it is 0, delete only the link key for 459 * the given BD_ADDR. If is is 1, delete all stored link keys. */ 460 SendCommandComplete(HCI_DELETE_STORED_LINK_KEY, {1}); 461 } 462 463 void DualModeController::HciRemoteNameRequest( 464 const std::vector<uint8_t>& args) { 465 LogCommand("Remote Name Request"); 466 SendCommandStatusSuccess(HCI_RMT_NAME_REQUEST); 467 } 468 469 DualModeController::Properties::Properties(const std::string& file_name) 470 : local_supported_commands_size_(64), local_name_size_(248) { 471 std::string properties_raw; 472 if (!base::ReadFileToString(base::FilePath(file_name), &properties_raw)) 473 LOG_INFO(LOG_TAG, "Error reading controller properties from file."); 474 475 scoped_ptr<base::Value> properties_value_ptr = 476 base::JSONReader::Read(properties_raw); 477 if (properties_value_ptr.get() == nullptr) 478 LOG_INFO(LOG_TAG, 479 "Error controller properties may consist of ill-formed JSON."); 480 481 // Get the underlying base::Value object, which is of type 482 // base::Value::TYPE_DICTIONARY, and read it into member variables. 483 base::Value& properties_dictionary = *(properties_value_ptr.get()); 484 base::JSONValueConverter<DualModeController::Properties> converter; 485 486 if (!converter.Convert(properties_dictionary, this)) 487 LOG_INFO(LOG_TAG, 488 "Error converting JSON properties into Properties object."); 489 } 490 491 const std::vector<uint8_t> DualModeController::Properties::GetBufferSize() { 492 return std::vector<uint8_t>( 493 {kSuccessStatus, acl_data_packet_size_, acl_data_packet_size_ >> 8, 494 sco_data_packet_size_, num_acl_data_packets_, num_acl_data_packets_ >> 8, 495 num_sco_data_packets_, num_sco_data_packets_ >> 8}); 496 } 497 498 const std::vector<uint8_t> 499 DualModeController::Properties::GetLocalVersionInformation() { 500 return std::vector<uint8_t>({kSuccessStatus, version_, revision_, 501 revision_ >> 8, lmp_pal_version_, 502 manufacturer_name_, manufacturer_name_ >> 8, 503 lmp_pal_subversion_, lmp_pal_subversion_ >> 8}); 504 } 505 506 const std::vector<uint8_t> DualModeController::Properties::GetBdAddress() { 507 return bd_address_; 508 } 509 510 const std::vector<uint8_t> 511 DualModeController::Properties::GetLocalExtendedFeatures(uint8_t page_number) { 512 return std::vector<uint8_t>({kSuccessStatus, page_number, 513 maximum_page_number_, 0xFF, 0xFF, 0xFF, 0xFF, 514 0xFF, 0xFF, 0xFF, 0xFF}); 515 } 516 517 const std::vector<uint8_t> 518 DualModeController::Properties::GetLocalSupportedCommands() { 519 std::vector<uint8_t> local_supported_commands; 520 local_supported_commands.push_back(kSuccessStatus); 521 for (uint8_t i = 0; i < local_supported_commands_size_; ++i) 522 local_supported_commands.push_back(0xFF); 523 return local_supported_commands; 524 } 525 526 const std::vector<uint8_t> DualModeController::Properties::GetLocalName() { 527 std::vector<uint8_t> local_name; 528 local_name.push_back(kSuccessStatus); 529 for (uint8_t i = 0; i < local_name_size_; ++i) 530 local_name.push_back(0xFF); 531 return local_name; 532 } 533 534 // static 535 void DualModeController::Properties::RegisterJSONConverter( 536 base::JSONValueConverter<DualModeController::Properties>* converter) { 537 // TODO(dennischeng): Use RegisterIntField() here? 538 #define REGISTER_UINT8_T(field_name, field) \ 539 converter->RegisterCustomField<uint8_t>( \ 540 field_name, &DualModeController::Properties::field, &ParseUint8t); 541 #define REGISTER_UINT16_T(field_name, field) \ 542 converter->RegisterCustomField<uint16_t>( \ 543 field_name, &DualModeController::Properties::field, &ParseUint16t); 544 REGISTER_UINT16_T("AclDataPacketSize", acl_data_packet_size_); 545 REGISTER_UINT8_T("ScoDataPacketSize", sco_data_packet_size_); 546 REGISTER_UINT16_T("NumAclDataPackets", num_acl_data_packets_); 547 REGISTER_UINT16_T("NumScoDataPackets", num_sco_data_packets_); 548 REGISTER_UINT8_T("Version", version_); 549 REGISTER_UINT16_T("Revision", revision_); 550 REGISTER_UINT8_T("LmpPalVersion", lmp_pal_version_); 551 REGISTER_UINT16_T("ManufacturerName", manufacturer_name_); 552 REGISTER_UINT16_T("LmpPalSubversion", lmp_pal_subversion_); 553 REGISTER_UINT8_T("MaximumPageNumber", maximum_page_number_); 554 converter->RegisterCustomField<std::vector<uint8_t>>( 555 "BdAddress", &DualModeController::Properties::bd_address_, 556 &ParseUint8tVector); 557 #undef REGISTER_UINT8_T 558 #undef REGISTER_UINT16_T 559 } 560 561 } // namespace test_vendor_lib 562