diff --git a/model/controller/dual_mode_controller.cc b/model/controller/dual_mode_controller.cc index 298a5ed..4642840 100644 --- a/model/controller/dual_mode_controller.cc +++ b/model/controller/dual_mode_controller.cc @@ -16,11 +16,11 @@ #include "model/controller/dual_mode_controller.h" -#include -#include #include +#include #include #include +#include #include #include @@ -178,8 +178,8 @@ void DualModeController::HandleCommand(std::shared_ptr> pac OpCode op_code = command_packet.GetOpCode(); const bool is_vendor_command = (static_cast(op_code) >> 10) == 0x3f; - const bool is_known_command = hci_command_op_code_to_index_.count(op_code) > 0; - const bool is_implemented_command = hci_command_handlers_.count(op_code) > 0; + const bool is_known_command = GetOpCodeToIndex().count(op_code) > 0; + const bool is_implemented_command = GetHciCommandHandlers().count(op_code) > 0; // HCI Read Local Supported Commands is supported by default. // Vendor commands are supported when implemented. @@ -189,7 +189,7 @@ void DualModeController::HandleCommand(std::shared_ptr> pac // For other commands, query the Support Commands bit mask in // the controller properties. if (!is_supported_command && is_known_command) { - int index = static_cast(hci_command_op_code_to_index_.at(op_code)); + int index = static_cast(GetOpCodeToIndex().at(op_code)); is_supported_command = (properties_.supported_commands[index / 10] & (1U << (index % 10))) != 0; } @@ -215,7 +215,7 @@ void DualModeController::HandleCommand(std::shared_ptr> pac // Command is both supported and implemented. // Invoke the registered handler. else if (is_supported_command && is_implemented_command) { - hci_command_handlers_.at(op_code)(this, command_packet); + GetHciCommandHandlers().at(op_code)(this, command_packet); } // Command is supported but not implemented: // the command needs to be implemented to fix this. @@ -2243,66 +2243,66 @@ void DualModeController::LeWriteSuggestedDefaultDataLength(CommandView command) static ErrorCode generateP256Key(std::array& key_x_coordinate, std::array& key_y_coordinate) { - // Clear any previous OpenSSL errors. - ERR_clear_error(); - - // Use unique_ptr with custom deleters for automatic memory management - // This ensures resources are freed even if an early return occurs due - // to an error. - auto ec_key_deleter = [](EC_KEY* ptr) { EC_KEY_free(ptr); }; - std::unique_ptr ec_key( - EC_KEY_new_by_curve_name(NID_X9_62_prime256v1), ec_key_deleter); - - if (!ec_key) { - WARNING("Failed to create EC_KEY for prime256v1 curve."); - return ErrorCode::UNSPECIFIED_ERROR; - } + // Clear any previous OpenSSL errors. + ERR_clear_error(); + + // Use unique_ptr with custom deleters for automatic memory management + // This ensures resources are freed even if an early return occurs due + // to an error. + auto ec_key_deleter = [](EC_KEY* ptr) { EC_KEY_free(ptr); }; + std::unique_ptr ec_key( + EC_KEY_new_by_curve_name(NID_X9_62_prime256v1), ec_key_deleter); + + if (!ec_key) { + WARNING("Failed to create EC_KEY for prime256v1 curve."); + return ErrorCode::UNSPECIFIED_ERROR; + } - // Generate the key pair. - if (!EC_KEY_generate_key(ec_key.get())) { - WARNING("Failed to generate EC key pair."); - return ErrorCode::UNSPECIFIED_ERROR; - } + // Generate the key pair. + if (!EC_KEY_generate_key(ec_key.get())) { + WARNING("Failed to generate EC key pair."); + return ErrorCode::UNSPECIFIED_ERROR; + } - // Get the public key point and group. - const EC_POINT* pub_key_point = EC_KEY_get0_public_key(ec_key.get()); - const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key.get()); + // Get the public key point and group. + const EC_POINT* pub_key_point = EC_KEY_get0_public_key(ec_key.get()); + const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key.get()); - if (!pub_key_point || !ec_group) { - WARNING("Failed to get public key point or EC group."); - return ErrorCode::UNSPECIFIED_ERROR; - } + if (!pub_key_point || !ec_group) { + WARNING("Failed to get public key point or EC group."); + return ErrorCode::UNSPECIFIED_ERROR; + } - // BIGNUM objects to hold the x and y coordinates - auto bn_deleter = [](BIGNUM* ptr) { BN_free(ptr); }; - std::unique_ptr x_bn(BN_new(), bn_deleter); - std::unique_ptr y_bn(BN_new(), bn_deleter); + // BIGNUM objects to hold the x and y coordinates + auto bn_deleter = [](BIGNUM* ptr) { BN_free(ptr); }; + std::unique_ptr x_bn(BN_new(), bn_deleter); + std::unique_ptr y_bn(BN_new(), bn_deleter); - if (!x_bn || !y_bn) { - WARNING("Failed to allocate BIGNUMs for coordinates."); - return ErrorCode::UNSPECIFIED_ERROR; - } + if (!x_bn || !y_bn) { + WARNING("Failed to allocate BIGNUMs for coordinates."); + return ErrorCode::UNSPECIFIED_ERROR; + } - // Extract affine coordinates (x, y) from the public key point - if (!EC_POINT_get_affine_coordinates(ec_group, pub_key_point, x_bn.get(), y_bn.get(), NULL)) { - WARNING("Failed to get affine coordinates from public key."); - return ErrorCode::UNSPECIFIED_ERROR; - } + // Extract affine coordinates (x, y) from the public key point + if (!EC_POINT_get_affine_coordinates(ec_group, pub_key_point, x_bn.get(), y_bn.get(), NULL)) { + WARNING("Failed to get affine coordinates from public key."); + return ErrorCode::UNSPECIFIED_ERROR; + } - // Convert BIGNUMs to fixed-size byte arrays (32 bytes for P-256) - // BN_bn2binpad pads with zeros if the BIGNUM is smaller than 'len'. - // It returns the number of bytes written, or -1 on error. - if (BN_bn2binpad(x_bn.get(), key_x_coordinate.data(), key_x_coordinate.size()) == -1) { - WARNING("Failed to convert X coordinate BIGNUM to binary."); - return ErrorCode::UNSPECIFIED_ERROR; - } + // Convert BIGNUMs to fixed-size byte arrays (32 bytes for P-256) + // BN_bn2binpad pads with zeros if the BIGNUM is smaller than 'len'. + // It returns the number of bytes written, or -1 on error. + if (BN_bn2binpad(x_bn.get(), key_x_coordinate.data(), key_x_coordinate.size()) == -1) { + WARNING("Failed to convert X coordinate BIGNUM to binary."); + return ErrorCode::UNSPECIFIED_ERROR; + } - if (BN_bn2binpad(y_bn.get(), key_y_coordinate.data(), key_y_coordinate.size()) == -1) { - WARNING("Failed to convert Y coordinate BIGNUM to binary."); - return ErrorCode::UNSPECIFIED_ERROR; - } + if (BN_bn2binpad(y_bn.get(), key_y_coordinate.data(), key_y_coordinate.size()) == -1) { + WARNING("Failed to convert Y coordinate BIGNUM to binary."); + return ErrorCode::UNSPECIFIED_ERROR; + } - return ErrorCode::SUCCESS; + return ErrorCode::SUCCESS; } void DualModeController::LeReadLocalP256PublicKey(CommandView command) { @@ -3400,988 +3400,987 @@ void DualModeController::IntelDdcConfigWrite(CommandView command) { // Notable exceptions: // - Vendor commands // - Read Local Supported Commands command -const std::unordered_map DualModeController::hci_command_op_code_to_index_{ - // LINK_CONTROL - {OpCode::INQUIRY, OpCodeIndex::INQUIRY}, - {OpCode::INQUIRY_CANCEL, OpCodeIndex::INQUIRY_CANCEL}, - {OpCode::PERIODIC_INQUIRY_MODE, OpCodeIndex::PERIODIC_INQUIRY_MODE}, - {OpCode::EXIT_PERIODIC_INQUIRY_MODE, OpCodeIndex::EXIT_PERIODIC_INQUIRY_MODE}, - {OpCode::CREATE_CONNECTION, OpCodeIndex::CREATE_CONNECTION}, - {OpCode::DISCONNECT, OpCodeIndex::DISCONNECT}, - {OpCode::ADD_SCO_CONNECTION, OpCodeIndex::ADD_SCO_CONNECTION}, - {OpCode::CREATE_CONNECTION_CANCEL, OpCodeIndex::CREATE_CONNECTION_CANCEL}, - {OpCode::ACCEPT_CONNECTION_REQUEST, OpCodeIndex::ACCEPT_CONNECTION_REQUEST}, - {OpCode::REJECT_CONNECTION_REQUEST, OpCodeIndex::REJECT_CONNECTION_REQUEST}, - {OpCode::LINK_KEY_REQUEST_REPLY, OpCodeIndex::LINK_KEY_REQUEST_REPLY}, - {OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, OpCodeIndex::LINK_KEY_REQUEST_NEGATIVE_REPLY}, - {OpCode::PIN_CODE_REQUEST_REPLY, OpCodeIndex::PIN_CODE_REQUEST_REPLY}, - {OpCode::PIN_CODE_REQUEST_NEGATIVE_REPLY, OpCodeIndex::PIN_CODE_REQUEST_NEGATIVE_REPLY}, - {OpCode::CHANGE_CONNECTION_PACKET_TYPE, OpCodeIndex::CHANGE_CONNECTION_PACKET_TYPE}, - {OpCode::AUTHENTICATION_REQUESTED, OpCodeIndex::AUTHENTICATION_REQUESTED}, - {OpCode::SET_CONNECTION_ENCRYPTION, OpCodeIndex::SET_CONNECTION_ENCRYPTION}, - {OpCode::CHANGE_CONNECTION_LINK_KEY, OpCodeIndex::CHANGE_CONNECTION_LINK_KEY}, - {OpCode::CENTRAL_LINK_KEY, OpCodeIndex::CENTRAL_LINK_KEY}, - {OpCode::REMOTE_NAME_REQUEST, OpCodeIndex::REMOTE_NAME_REQUEST}, - {OpCode::REMOTE_NAME_REQUEST_CANCEL, OpCodeIndex::REMOTE_NAME_REQUEST_CANCEL}, - {OpCode::READ_REMOTE_SUPPORTED_FEATURES, OpCodeIndex::READ_REMOTE_SUPPORTED_FEATURES}, - {OpCode::READ_REMOTE_EXTENDED_FEATURES, OpCodeIndex::READ_REMOTE_EXTENDED_FEATURES}, - {OpCode::READ_REMOTE_VERSION_INFORMATION, OpCodeIndex::READ_REMOTE_VERSION_INFORMATION}, - {OpCode::READ_CLOCK_OFFSET, OpCodeIndex::READ_CLOCK_OFFSET}, - {OpCode::READ_LMP_HANDLE, OpCodeIndex::READ_LMP_HANDLE}, - {OpCode::SETUP_SYNCHRONOUS_CONNECTION, OpCodeIndex::SETUP_SYNCHRONOUS_CONNECTION}, - {OpCode::ACCEPT_SYNCHRONOUS_CONNECTION, OpCodeIndex::ACCEPT_SYNCHRONOUS_CONNECTION}, - {OpCode::REJECT_SYNCHRONOUS_CONNECTION, OpCodeIndex::REJECT_SYNCHRONOUS_CONNECTION}, - {OpCode::IO_CAPABILITY_REQUEST_REPLY, OpCodeIndex::IO_CAPABILITY_REQUEST_REPLY}, - {OpCode::USER_CONFIRMATION_REQUEST_REPLY, OpCodeIndex::USER_CONFIRMATION_REQUEST_REPLY}, - {OpCode::USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY, - OpCodeIndex::USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY}, - {OpCode::USER_PASSKEY_REQUEST_REPLY, OpCodeIndex::USER_PASSKEY_REQUEST_REPLY}, - {OpCode::USER_PASSKEY_REQUEST_NEGATIVE_REPLY, - OpCodeIndex::USER_PASSKEY_REQUEST_NEGATIVE_REPLY}, - {OpCode::REMOTE_OOB_DATA_REQUEST_REPLY, OpCodeIndex::REMOTE_OOB_DATA_REQUEST_REPLY}, - {OpCode::REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY, - OpCodeIndex::REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY}, - {OpCode::IO_CAPABILITY_REQUEST_NEGATIVE_REPLY, - OpCodeIndex::IO_CAPABILITY_REQUEST_NEGATIVE_REPLY}, - {OpCode::ENHANCED_SETUP_SYNCHRONOUS_CONNECTION, - OpCodeIndex::ENHANCED_SETUP_SYNCHRONOUS_CONNECTION}, - {OpCode::ENHANCED_ACCEPT_SYNCHRONOUS_CONNECTION, - OpCodeIndex::ENHANCED_ACCEPT_SYNCHRONOUS_CONNECTION}, - {OpCode::TRUNCATED_PAGE, OpCodeIndex::TRUNCATED_PAGE}, - {OpCode::TRUNCATED_PAGE_CANCEL, OpCodeIndex::TRUNCATED_PAGE_CANCEL}, - {OpCode::SET_CONNECTIONLESS_PERIPHERAL_BROADCAST, - OpCodeIndex::SET_CONNECTIONLESS_PERIPHERAL_BROADCAST}, - {OpCode::SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_RECEIVE, - OpCodeIndex::SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_RECEIVE}, - {OpCode::START_SYNCHRONIZATION_TRAIN, OpCodeIndex::START_SYNCHRONIZATION_TRAIN}, - {OpCode::RECEIVE_SYNCHRONIZATION_TRAIN, OpCodeIndex::RECEIVE_SYNCHRONIZATION_TRAIN}, - {OpCode::REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY, - OpCodeIndex::REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY}, - - // LINK_POLICY - {OpCode::HOLD_MODE, OpCodeIndex::HOLD_MODE}, - {OpCode::SNIFF_MODE, OpCodeIndex::SNIFF_MODE}, - {OpCode::EXIT_SNIFF_MODE, OpCodeIndex::EXIT_SNIFF_MODE}, - {OpCode::QOS_SETUP, OpCodeIndex::QOS_SETUP}, - {OpCode::ROLE_DISCOVERY, OpCodeIndex::ROLE_DISCOVERY}, - {OpCode::SWITCH_ROLE, OpCodeIndex::SWITCH_ROLE}, - {OpCode::READ_LINK_POLICY_SETTINGS, OpCodeIndex::READ_LINK_POLICY_SETTINGS}, - {OpCode::WRITE_LINK_POLICY_SETTINGS, OpCodeIndex::WRITE_LINK_POLICY_SETTINGS}, - {OpCode::READ_DEFAULT_LINK_POLICY_SETTINGS, OpCodeIndex::READ_DEFAULT_LINK_POLICY_SETTINGS}, - {OpCode::WRITE_DEFAULT_LINK_POLICY_SETTINGS, - OpCodeIndex::WRITE_DEFAULT_LINK_POLICY_SETTINGS}, - {OpCode::FLOW_SPECIFICATION, OpCodeIndex::FLOW_SPECIFICATION}, - {OpCode::SNIFF_SUBRATING, OpCodeIndex::SNIFF_SUBRATING}, - - // CONTROLLER_AND_BASEBAND - {OpCode::SET_EVENT_MASK, OpCodeIndex::SET_EVENT_MASK}, - {OpCode::RESET, OpCodeIndex::RESET}, - {OpCode::SET_EVENT_FILTER, OpCodeIndex::SET_EVENT_FILTER}, - {OpCode::FLUSH, OpCodeIndex::FLUSH}, - {OpCode::READ_PIN_TYPE, OpCodeIndex::READ_PIN_TYPE}, - {OpCode::WRITE_PIN_TYPE, OpCodeIndex::WRITE_PIN_TYPE}, - {OpCode::READ_STORED_LINK_KEY, OpCodeIndex::READ_STORED_LINK_KEY}, - {OpCode::WRITE_STORED_LINK_KEY, OpCodeIndex::WRITE_STORED_LINK_KEY}, - {OpCode::DELETE_STORED_LINK_KEY, OpCodeIndex::DELETE_STORED_LINK_KEY}, - {OpCode::WRITE_LOCAL_NAME, OpCodeIndex::WRITE_LOCAL_NAME}, - {OpCode::READ_LOCAL_NAME, OpCodeIndex::READ_LOCAL_NAME}, - {OpCode::READ_CONNECTION_ACCEPT_TIMEOUT, OpCodeIndex::READ_CONNECTION_ACCEPT_TIMEOUT}, - {OpCode::WRITE_CONNECTION_ACCEPT_TIMEOUT, OpCodeIndex::WRITE_CONNECTION_ACCEPT_TIMEOUT}, - {OpCode::READ_PAGE_TIMEOUT, OpCodeIndex::READ_PAGE_TIMEOUT}, - {OpCode::WRITE_PAGE_TIMEOUT, OpCodeIndex::WRITE_PAGE_TIMEOUT}, - {OpCode::READ_SCAN_ENABLE, OpCodeIndex::READ_SCAN_ENABLE}, - {OpCode::WRITE_SCAN_ENABLE, OpCodeIndex::WRITE_SCAN_ENABLE}, - {OpCode::READ_PAGE_SCAN_ACTIVITY, OpCodeIndex::READ_PAGE_SCAN_ACTIVITY}, - {OpCode::WRITE_PAGE_SCAN_ACTIVITY, OpCodeIndex::WRITE_PAGE_SCAN_ACTIVITY}, - {OpCode::READ_INQUIRY_SCAN_ACTIVITY, OpCodeIndex::READ_INQUIRY_SCAN_ACTIVITY}, - {OpCode::WRITE_INQUIRY_SCAN_ACTIVITY, OpCodeIndex::WRITE_INQUIRY_SCAN_ACTIVITY}, - {OpCode::READ_AUTHENTICATION_ENABLE, OpCodeIndex::READ_AUTHENTICATION_ENABLE}, - {OpCode::WRITE_AUTHENTICATION_ENABLE, OpCodeIndex::WRITE_AUTHENTICATION_ENABLE}, - {OpCode::READ_CLASS_OF_DEVICE, OpCodeIndex::READ_CLASS_OF_DEVICE}, - {OpCode::WRITE_CLASS_OF_DEVICE, OpCodeIndex::WRITE_CLASS_OF_DEVICE}, - {OpCode::READ_VOICE_SETTING, OpCodeIndex::READ_VOICE_SETTING}, - {OpCode::WRITE_VOICE_SETTING, OpCodeIndex::WRITE_VOICE_SETTING}, - {OpCode::READ_AUTOMATIC_FLUSH_TIMEOUT, OpCodeIndex::READ_AUTOMATIC_FLUSH_TIMEOUT}, - {OpCode::WRITE_AUTOMATIC_FLUSH_TIMEOUT, OpCodeIndex::WRITE_AUTOMATIC_FLUSH_TIMEOUT}, - {OpCode::READ_NUM_BROADCAST_RETRANSMITS, OpCodeIndex::READ_NUM_BROADCAST_RETRANSMITS}, - {OpCode::WRITE_NUM_BROADCAST_RETRANSMITS, OpCodeIndex::WRITE_NUM_BROADCAST_RETRANSMITS}, - {OpCode::READ_HOLD_MODE_ACTIVITY, OpCodeIndex::READ_HOLD_MODE_ACTIVITY}, - {OpCode::WRITE_HOLD_MODE_ACTIVITY, OpCodeIndex::WRITE_HOLD_MODE_ACTIVITY}, - {OpCode::READ_TRANSMIT_POWER_LEVEL, OpCodeIndex::READ_TRANSMIT_POWER_LEVEL}, - {OpCode::READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE, - OpCodeIndex::READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE}, - {OpCode::WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE, - OpCodeIndex::WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE}, - {OpCode::SET_CONTROLLER_TO_HOST_FLOW_CONTROL, - OpCodeIndex::SET_CONTROLLER_TO_HOST_FLOW_CONTROL}, - {OpCode::HOST_BUFFER_SIZE, OpCodeIndex::HOST_BUFFER_SIZE}, - {OpCode::HOST_NUMBER_OF_COMPLETED_PACKETS, OpCodeIndex::HOST_NUMBER_OF_COMPLETED_PACKETS}, - {OpCode::READ_LINK_SUPERVISION_TIMEOUT, OpCodeIndex::READ_LINK_SUPERVISION_TIMEOUT}, - {OpCode::WRITE_LINK_SUPERVISION_TIMEOUT, OpCodeIndex::WRITE_LINK_SUPERVISION_TIMEOUT}, - {OpCode::READ_NUMBER_OF_SUPPORTED_IAC, OpCodeIndex::READ_NUMBER_OF_SUPPORTED_IAC}, - {OpCode::READ_CURRENT_IAC_LAP, OpCodeIndex::READ_CURRENT_IAC_LAP}, - {OpCode::WRITE_CURRENT_IAC_LAP, OpCodeIndex::WRITE_CURRENT_IAC_LAP}, - {OpCode::SET_AFH_HOST_CHANNEL_CLASSIFICATION, - OpCodeIndex::SET_AFH_HOST_CHANNEL_CLASSIFICATION}, - {OpCode::READ_INQUIRY_SCAN_TYPE, OpCodeIndex::READ_INQUIRY_SCAN_TYPE}, - {OpCode::WRITE_INQUIRY_SCAN_TYPE, OpCodeIndex::WRITE_INQUIRY_SCAN_TYPE}, - {OpCode::READ_INQUIRY_MODE, OpCodeIndex::READ_INQUIRY_MODE}, - {OpCode::WRITE_INQUIRY_MODE, OpCodeIndex::WRITE_INQUIRY_MODE}, - {OpCode::READ_PAGE_SCAN_TYPE, OpCodeIndex::READ_PAGE_SCAN_TYPE}, - {OpCode::WRITE_PAGE_SCAN_TYPE, OpCodeIndex::WRITE_PAGE_SCAN_TYPE}, - {OpCode::READ_AFH_CHANNEL_ASSESSMENT_MODE, OpCodeIndex::READ_AFH_CHANNEL_ASSESSMENT_MODE}, - {OpCode::WRITE_AFH_CHANNEL_ASSESSMENT_MODE, OpCodeIndex::WRITE_AFH_CHANNEL_ASSESSMENT_MODE}, - {OpCode::READ_EXTENDED_INQUIRY_RESPONSE, OpCodeIndex::READ_EXTENDED_INQUIRY_RESPONSE}, - {OpCode::WRITE_EXTENDED_INQUIRY_RESPONSE, OpCodeIndex::WRITE_EXTENDED_INQUIRY_RESPONSE}, - {OpCode::REFRESH_ENCRYPTION_KEY, OpCodeIndex::REFRESH_ENCRYPTION_KEY}, - {OpCode::READ_SIMPLE_PAIRING_MODE, OpCodeIndex::READ_SIMPLE_PAIRING_MODE}, - {OpCode::WRITE_SIMPLE_PAIRING_MODE, OpCodeIndex::WRITE_SIMPLE_PAIRING_MODE}, - {OpCode::READ_LOCAL_OOB_DATA, OpCodeIndex::READ_LOCAL_OOB_DATA}, - {OpCode::READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL, - OpCodeIndex::READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL}, - {OpCode::WRITE_INQUIRY_TRANSMIT_POWER_LEVEL, - OpCodeIndex::WRITE_INQUIRY_TRANSMIT_POWER_LEVEL}, - {OpCode::READ_DEFAULT_ERRONEOUS_DATA_REPORTING, - OpCodeIndex::READ_DEFAULT_ERRONEOUS_DATA_REPORTING}, - {OpCode::WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING, - OpCodeIndex::WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING}, - {OpCode::ENHANCED_FLUSH, OpCodeIndex::ENHANCED_FLUSH}, - {OpCode::SEND_KEYPRESS_NOTIFICATION, OpCodeIndex::SEND_KEYPRESS_NOTIFICATION}, - {OpCode::SET_EVENT_MASK_PAGE_2, OpCodeIndex::SET_EVENT_MASK_PAGE_2}, - {OpCode::READ_FLOW_CONTROL_MODE, OpCodeIndex::READ_FLOW_CONTROL_MODE}, - {OpCode::WRITE_FLOW_CONTROL_MODE, OpCodeIndex::WRITE_FLOW_CONTROL_MODE}, - {OpCode::READ_ENHANCED_TRANSMIT_POWER_LEVEL, - OpCodeIndex::READ_ENHANCED_TRANSMIT_POWER_LEVEL}, - {OpCode::READ_LE_HOST_SUPPORT, OpCodeIndex::READ_LE_HOST_SUPPORT}, - {OpCode::WRITE_LE_HOST_SUPPORT, OpCodeIndex::WRITE_LE_HOST_SUPPORT}, - {OpCode::SET_MWS_CHANNEL_PARAMETERS, OpCodeIndex::SET_MWS_CHANNEL_PARAMETERS}, - {OpCode::SET_EXTERNAL_FRAME_CONFIGURATION, OpCodeIndex::SET_EXTERNAL_FRAME_CONFIGURATION}, - {OpCode::SET_MWS_SIGNALING, OpCodeIndex::SET_MWS_SIGNALING}, - {OpCode::SET_MWS_TRANSPORT_LAYER, OpCodeIndex::SET_MWS_TRANSPORT_LAYER}, - {OpCode::SET_MWS_SCAN_FREQUENCY_TABLE, OpCodeIndex::SET_MWS_SCAN_FREQUENCY_TABLE}, - {OpCode::SET_MWS_PATTERN_CONFIGURATION, OpCodeIndex::SET_MWS_PATTERN_CONFIGURATION}, - {OpCode::SET_RESERVED_LT_ADDR, OpCodeIndex::SET_RESERVED_LT_ADDR}, - {OpCode::DELETE_RESERVED_LT_ADDR, OpCodeIndex::DELETE_RESERVED_LT_ADDR}, - {OpCode::SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_DATA, - OpCodeIndex::SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_DATA}, - {OpCode::READ_SYNCHRONIZATION_TRAIN_PARAMETERS, - OpCodeIndex::READ_SYNCHRONIZATION_TRAIN_PARAMETERS}, - {OpCode::WRITE_SYNCHRONIZATION_TRAIN_PARAMETERS, - OpCodeIndex::WRITE_SYNCHRONIZATION_TRAIN_PARAMETERS}, - {OpCode::READ_SECURE_CONNECTIONS_HOST_SUPPORT, - OpCodeIndex::READ_SECURE_CONNECTIONS_HOST_SUPPORT}, - {OpCode::WRITE_SECURE_CONNECTIONS_HOST_SUPPORT, - OpCodeIndex::WRITE_SECURE_CONNECTIONS_HOST_SUPPORT}, - {OpCode::READ_AUTHENTICATED_PAYLOAD_TIMEOUT, - OpCodeIndex::READ_AUTHENTICATED_PAYLOAD_TIMEOUT}, - {OpCode::WRITE_AUTHENTICATED_PAYLOAD_TIMEOUT, - OpCodeIndex::WRITE_AUTHENTICATED_PAYLOAD_TIMEOUT}, - {OpCode::READ_LOCAL_OOB_EXTENDED_DATA, OpCodeIndex::READ_LOCAL_OOB_EXTENDED_DATA}, - {OpCode::READ_EXTENDED_PAGE_TIMEOUT, OpCodeIndex::READ_EXTENDED_PAGE_TIMEOUT}, - {OpCode::WRITE_EXTENDED_PAGE_TIMEOUT, OpCodeIndex::WRITE_EXTENDED_PAGE_TIMEOUT}, - {OpCode::READ_EXTENDED_INQUIRY_LENGTH, OpCodeIndex::READ_EXTENDED_INQUIRY_LENGTH}, - {OpCode::WRITE_EXTENDED_INQUIRY_LENGTH, OpCodeIndex::WRITE_EXTENDED_INQUIRY_LENGTH}, - {OpCode::SET_ECOSYSTEM_BASE_INTERVAL, OpCodeIndex::SET_ECOSYSTEM_BASE_INTERVAL}, - {OpCode::CONFIGURE_DATA_PATH, OpCodeIndex::CONFIGURE_DATA_PATH}, - {OpCode::SET_MIN_ENCRYPTION_KEY_SIZE, OpCodeIndex::SET_MIN_ENCRYPTION_KEY_SIZE}, - - // INFORMATIONAL_PARAMETERS - {OpCode::READ_LOCAL_VERSION_INFORMATION, OpCodeIndex::READ_LOCAL_VERSION_INFORMATION}, - {OpCode::READ_LOCAL_SUPPORTED_FEATURES, OpCodeIndex::READ_LOCAL_SUPPORTED_FEATURES}, - {OpCode::READ_LOCAL_EXTENDED_FEATURES, OpCodeIndex::READ_LOCAL_EXTENDED_FEATURES}, - {OpCode::READ_BUFFER_SIZE, OpCodeIndex::READ_BUFFER_SIZE}, - {OpCode::READ_BD_ADDR, OpCodeIndex::READ_BD_ADDR}, - {OpCode::READ_DATA_BLOCK_SIZE, OpCodeIndex::READ_DATA_BLOCK_SIZE}, - {OpCode::READ_LOCAL_SUPPORTED_CODECS_V1, OpCodeIndex::READ_LOCAL_SUPPORTED_CODECS_V1}, - {OpCode::READ_LOCAL_SIMPLE_PAIRING_OPTIONS, OpCodeIndex::READ_LOCAL_SIMPLE_PAIRING_OPTIONS}, - {OpCode::READ_LOCAL_SUPPORTED_CODECS_V2, OpCodeIndex::READ_LOCAL_SUPPORTED_CODECS_V2}, - {OpCode::READ_LOCAL_SUPPORTED_CODEC_CAPABILITIES, - OpCodeIndex::READ_LOCAL_SUPPORTED_CODEC_CAPABILITIES}, - {OpCode::READ_LOCAL_SUPPORTED_CONTROLLER_DELAY, - OpCodeIndex::READ_LOCAL_SUPPORTED_CONTROLLER_DELAY}, - - // STATUS_PARAMETERS - {OpCode::READ_FAILED_CONTACT_COUNTER, OpCodeIndex::READ_FAILED_CONTACT_COUNTER}, - {OpCode::RESET_FAILED_CONTACT_COUNTER, OpCodeIndex::RESET_FAILED_CONTACT_COUNTER}, - {OpCode::READ_LINK_QUALITY, OpCodeIndex::READ_LINK_QUALITY}, - {OpCode::READ_RSSI, OpCodeIndex::READ_RSSI}, - {OpCode::READ_AFH_CHANNEL_MAP, OpCodeIndex::READ_AFH_CHANNEL_MAP}, - {OpCode::READ_CLOCK, OpCodeIndex::READ_CLOCK}, - {OpCode::READ_ENCRYPTION_KEY_SIZE, OpCodeIndex::READ_ENCRYPTION_KEY_SIZE}, - {OpCode::GET_MWS_TRANSPORT_LAYER_CONFIGURATION, - OpCodeIndex::GET_MWS_TRANSPORT_LAYER_CONFIGURATION}, - {OpCode::SET_TRIGGERED_CLOCK_CAPTURE, OpCodeIndex::SET_TRIGGERED_CLOCK_CAPTURE}, - - // TESTING - {OpCode::READ_LOOPBACK_MODE, OpCodeIndex::READ_LOOPBACK_MODE}, - {OpCode::WRITE_LOOPBACK_MODE, OpCodeIndex::WRITE_LOOPBACK_MODE}, - {OpCode::ENABLE_IMPLEMENTATION_UNDER_TEST_MODE, - OpCodeIndex::ENABLE_IMPLEMENTATION_UNDER_TEST_MODE}, - {OpCode::WRITE_SIMPLE_PAIRING_DEBUG_MODE, OpCodeIndex::WRITE_SIMPLE_PAIRING_DEBUG_MODE}, - {OpCode::WRITE_SECURE_CONNECTIONS_TEST_MODE, - OpCodeIndex::WRITE_SECURE_CONNECTIONS_TEST_MODE}, - - // LE_CONTROLLER - {OpCode::LE_SET_EVENT_MASK, OpCodeIndex::LE_SET_EVENT_MASK}, - {OpCode::LE_READ_BUFFER_SIZE_V1, OpCodeIndex::LE_READ_BUFFER_SIZE_V1}, - {OpCode::LE_READ_LOCAL_SUPPORTED_FEATURES_PAGE_0, - OpCodeIndex::LE_READ_LOCAL_SUPPORTED_FEATURES_PAGE_0}, - {OpCode::LE_SET_RANDOM_ADDRESS, OpCodeIndex::LE_SET_RANDOM_ADDRESS}, - {OpCode::LE_SET_ADVERTISING_PARAMETERS, OpCodeIndex::LE_SET_ADVERTISING_PARAMETERS}, - {OpCode::LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER, - OpCodeIndex::LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER}, - {OpCode::LE_SET_ADVERTISING_DATA, OpCodeIndex::LE_SET_ADVERTISING_DATA}, - {OpCode::LE_SET_SCAN_RESPONSE_DATA, OpCodeIndex::LE_SET_SCAN_RESPONSE_DATA}, - {OpCode::LE_SET_ADVERTISING_ENABLE, OpCodeIndex::LE_SET_ADVERTISING_ENABLE}, - {OpCode::LE_SET_SCAN_PARAMETERS, OpCodeIndex::LE_SET_SCAN_PARAMETERS}, - {OpCode::LE_SET_SCAN_ENABLE, OpCodeIndex::LE_SET_SCAN_ENABLE}, - {OpCode::LE_CREATE_CONNECTION, OpCodeIndex::LE_CREATE_CONNECTION}, - {OpCode::LE_CREATE_CONNECTION_CANCEL, OpCodeIndex::LE_CREATE_CONNECTION_CANCEL}, - {OpCode::LE_READ_FILTER_ACCEPT_LIST_SIZE, OpCodeIndex::LE_READ_FILTER_ACCEPT_LIST_SIZE}, - {OpCode::LE_CLEAR_FILTER_ACCEPT_LIST, OpCodeIndex::LE_CLEAR_FILTER_ACCEPT_LIST}, - {OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST, - OpCodeIndex::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST}, - {OpCode::LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST, - OpCodeIndex::LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST}, - {OpCode::LE_CONNECTION_UPDATE, OpCodeIndex::LE_CONNECTION_UPDATE}, - {OpCode::LE_SET_HOST_CHANNEL_CLASSIFICATION, - OpCodeIndex::LE_SET_HOST_CHANNEL_CLASSIFICATION}, - {OpCode::LE_READ_CHANNEL_MAP, OpCodeIndex::LE_READ_CHANNEL_MAP}, - {OpCode::LE_READ_REMOTE_FEATURES_PAGE_0, OpCodeIndex::LE_READ_REMOTE_FEATURES_PAGE_0}, - {OpCode::LE_ENCRYPT, OpCodeIndex::LE_ENCRYPT}, - {OpCode::LE_RAND, OpCodeIndex::LE_RAND}, - {OpCode::LE_START_ENCRYPTION, OpCodeIndex::LE_START_ENCRYPTION}, - {OpCode::LE_LONG_TERM_KEY_REQUEST_REPLY, OpCodeIndex::LE_LONG_TERM_KEY_REQUEST_REPLY}, - {OpCode::LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY, - OpCodeIndex::LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY}, - {OpCode::LE_READ_SUPPORTED_STATES, OpCodeIndex::LE_READ_SUPPORTED_STATES}, - {OpCode::LE_RECEIVER_TEST_V1, OpCodeIndex::LE_RECEIVER_TEST_V1}, - {OpCode::LE_TRANSMITTER_TEST_V1, OpCodeIndex::LE_TRANSMITTER_TEST_V1}, - {OpCode::LE_TEST_END, OpCodeIndex::LE_TEST_END}, - {OpCode::LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY, - OpCodeIndex::LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY}, - {OpCode::LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY, - OpCodeIndex::LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY}, - {OpCode::LE_SET_DATA_LENGTH, OpCodeIndex::LE_SET_DATA_LENGTH}, - {OpCode::LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH, - OpCodeIndex::LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH}, - {OpCode::LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH, - OpCodeIndex::LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH}, - {OpCode::LE_READ_LOCAL_P_256_PUBLIC_KEY, OpCodeIndex::LE_READ_LOCAL_P_256_PUBLIC_KEY}, - {OpCode::LE_GENERATE_DHKEY_V1, OpCodeIndex::LE_GENERATE_DHKEY_V1}, - {OpCode::LE_ADD_DEVICE_TO_RESOLVING_LIST, OpCodeIndex::LE_ADD_DEVICE_TO_RESOLVING_LIST}, - {OpCode::LE_REMOVE_DEVICE_FROM_RESOLVING_LIST, - OpCodeIndex::LE_REMOVE_DEVICE_FROM_RESOLVING_LIST}, - {OpCode::LE_CLEAR_RESOLVING_LIST, OpCodeIndex::LE_CLEAR_RESOLVING_LIST}, - {OpCode::LE_READ_RESOLVING_LIST_SIZE, OpCodeIndex::LE_READ_RESOLVING_LIST_SIZE}, - {OpCode::LE_READ_PEER_RESOLVABLE_ADDRESS, OpCodeIndex::LE_READ_PEER_RESOLVABLE_ADDRESS}, - {OpCode::LE_READ_LOCAL_RESOLVABLE_ADDRESS, OpCodeIndex::LE_READ_LOCAL_RESOLVABLE_ADDRESS}, - {OpCode::LE_SET_ADDRESS_RESOLUTION_ENABLE, OpCodeIndex::LE_SET_ADDRESS_RESOLUTION_ENABLE}, - {OpCode::LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT, - OpCodeIndex::LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT}, - {OpCode::LE_READ_MAXIMUM_DATA_LENGTH, OpCodeIndex::LE_READ_MAXIMUM_DATA_LENGTH}, - {OpCode::LE_READ_PHY, OpCodeIndex::LE_READ_PHY}, - {OpCode::LE_SET_DEFAULT_PHY, OpCodeIndex::LE_SET_DEFAULT_PHY}, - {OpCode::LE_SET_PHY, OpCodeIndex::LE_SET_PHY}, - {OpCode::LE_RECEIVER_TEST_V2, OpCodeIndex::LE_RECEIVER_TEST_V2}, - {OpCode::LE_TRANSMITTER_TEST_V2, OpCodeIndex::LE_TRANSMITTER_TEST_V2}, - {OpCode::LE_SET_ADVERTISING_SET_RANDOM_ADDRESS, - OpCodeIndex::LE_SET_ADVERTISING_SET_RANDOM_ADDRESS}, - {OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1, - OpCodeIndex::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1}, - {OpCode::LE_SET_EXTENDED_ADVERTISING_DATA, OpCodeIndex::LE_SET_EXTENDED_ADVERTISING_DATA}, - {OpCode::LE_SET_EXTENDED_SCAN_RESPONSE_DATA, - OpCodeIndex::LE_SET_EXTENDED_SCAN_RESPONSE_DATA}, - {OpCode::LE_SET_EXTENDED_ADVERTISING_ENABLE, - OpCodeIndex::LE_SET_EXTENDED_ADVERTISING_ENABLE}, - {OpCode::LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH, - OpCodeIndex::LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH}, - {OpCode::LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS, - OpCodeIndex::LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS}, - {OpCode::LE_REMOVE_ADVERTISING_SET, OpCodeIndex::LE_REMOVE_ADVERTISING_SET}, - {OpCode::LE_CLEAR_ADVERTISING_SETS, OpCodeIndex::LE_CLEAR_ADVERTISING_SETS}, - {OpCode::LE_SET_PERIODIC_ADVERTISING_PARAMETERS_V1, - OpCodeIndex::LE_SET_PERIODIC_ADVERTISING_PARAMETERS_V1}, - {OpCode::LE_SET_PERIODIC_ADVERTISING_DATA, OpCodeIndex::LE_SET_PERIODIC_ADVERTISING_DATA}, - {OpCode::LE_SET_PERIODIC_ADVERTISING_ENABLE, - OpCodeIndex::LE_SET_PERIODIC_ADVERTISING_ENABLE}, - {OpCode::LE_SET_EXTENDED_SCAN_PARAMETERS, OpCodeIndex::LE_SET_EXTENDED_SCAN_PARAMETERS}, - {OpCode::LE_SET_EXTENDED_SCAN_ENABLE, OpCodeIndex::LE_SET_EXTENDED_SCAN_ENABLE}, - {OpCode::LE_EXTENDED_CREATE_CONNECTION_V1, OpCodeIndex::LE_EXTENDED_CREATE_CONNECTION_V1}, - {OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC, - OpCodeIndex::LE_PERIODIC_ADVERTISING_CREATE_SYNC}, - {OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL, - OpCodeIndex::LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL}, - {OpCode::LE_PERIODIC_ADVERTISING_TERMINATE_SYNC, - OpCodeIndex::LE_PERIODIC_ADVERTISING_TERMINATE_SYNC}, - {OpCode::LE_ADD_DEVICE_TO_PERIODIC_ADVERTISER_LIST, - OpCodeIndex::LE_ADD_DEVICE_TO_PERIODIC_ADVERTISER_LIST}, - {OpCode::LE_REMOVE_DEVICE_FROM_PERIODIC_ADVERTISER_LIST, - OpCodeIndex::LE_REMOVE_DEVICE_FROM_PERIODIC_ADVERTISER_LIST}, - {OpCode::LE_CLEAR_PERIODIC_ADVERTISER_LIST, OpCodeIndex::LE_CLEAR_PERIODIC_ADVERTISER_LIST}, - {OpCode::LE_READ_PERIODIC_ADVERTISER_LIST_SIZE, - OpCodeIndex::LE_READ_PERIODIC_ADVERTISER_LIST_SIZE}, - {OpCode::LE_READ_TRANSMIT_POWER, OpCodeIndex::LE_READ_TRANSMIT_POWER}, - {OpCode::LE_READ_RF_PATH_COMPENSATION_POWER, - OpCodeIndex::LE_READ_RF_PATH_COMPENSATION_POWER}, - {OpCode::LE_WRITE_RF_PATH_COMPENSATION_POWER, - OpCodeIndex::LE_WRITE_RF_PATH_COMPENSATION_POWER}, - {OpCode::LE_SET_PRIVACY_MODE, OpCodeIndex::LE_SET_PRIVACY_MODE}, - {OpCode::LE_RECEIVER_TEST_V3, OpCodeIndex::LE_RECEIVER_TEST_V3}, - {OpCode::LE_TRANSMITTER_TEST_V3, OpCodeIndex::LE_TRANSMITTER_TEST_V3}, - {OpCode::LE_SET_CONNECTIONLESS_CTE_TRANSMIT_PARAMETERS, - OpCodeIndex::LE_SET_CONNECTIONLESS_CTE_TRANSMIT_PARAMETERS}, - {OpCode::LE_SET_CONNECTIONLESS_CTE_TRANSMIT_ENABLE, - OpCodeIndex::LE_SET_CONNECTIONLESS_CTE_TRANSMIT_ENABLE}, - {OpCode::LE_SET_CONNECTIONLESS_IQ_SAMPLING_ENABLE, - OpCodeIndex::LE_SET_CONNECTIONLESS_IQ_SAMPLING_ENABLE}, - {OpCode::LE_SET_CONNECTION_CTE_RECEIVE_PARAMETERS, - OpCodeIndex::LE_SET_CONNECTION_CTE_RECEIVE_PARAMETERS}, - {OpCode::LE_SET_CONNECTION_CTE_TRANSMIT_PARAMETERS, - OpCodeIndex::LE_SET_CONNECTION_CTE_TRANSMIT_PARAMETERS}, - {OpCode::LE_CONNECTION_CTE_REQUEST_ENABLE, OpCodeIndex::LE_CONNECTION_CTE_REQUEST_ENABLE}, - {OpCode::LE_CONNECTION_CTE_RESPONSE_ENABLE, OpCodeIndex::LE_CONNECTION_CTE_RESPONSE_ENABLE}, - {OpCode::LE_READ_ANTENNA_INFORMATION, OpCodeIndex::LE_READ_ANTENNA_INFORMATION}, - {OpCode::LE_SET_PERIODIC_ADVERTISING_RECEIVE_ENABLE, - OpCodeIndex::LE_SET_PERIODIC_ADVERTISING_RECEIVE_ENABLE}, - {OpCode::LE_PERIODIC_ADVERTISING_SYNC_TRANSFER, - OpCodeIndex::LE_PERIODIC_ADVERTISING_SYNC_TRANSFER}, - {OpCode::LE_PERIODIC_ADVERTISING_SET_INFO_TRANSFER, - OpCodeIndex::LE_PERIODIC_ADVERTISING_SET_INFO_TRANSFER}, - {OpCode::LE_SET_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS, - OpCodeIndex::LE_SET_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS}, - {OpCode::LE_SET_DEFAULT_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS, - OpCodeIndex::LE_SET_DEFAULT_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS}, - {OpCode::LE_GENERATE_DHKEY_V2, OpCodeIndex::LE_GENERATE_DHKEY_V2}, - {OpCode::LE_MODIFY_SLEEP_CLOCK_ACCURACY, OpCodeIndex::LE_MODIFY_SLEEP_CLOCK_ACCURACY}, - {OpCode::LE_READ_BUFFER_SIZE_V2, OpCodeIndex::LE_READ_BUFFER_SIZE_V2}, - {OpCode::LE_READ_ISO_TX_SYNC, OpCodeIndex::LE_READ_ISO_TX_SYNC}, - {OpCode::LE_SET_CIG_PARAMETERS, OpCodeIndex::LE_SET_CIG_PARAMETERS}, - {OpCode::LE_SET_CIG_PARAMETERS_TEST, OpCodeIndex::LE_SET_CIG_PARAMETERS_TEST}, - {OpCode::LE_CREATE_CIS, OpCodeIndex::LE_CREATE_CIS}, - {OpCode::LE_REMOVE_CIG, OpCodeIndex::LE_REMOVE_CIG}, - {OpCode::LE_ACCEPT_CIS_REQUEST, OpCodeIndex::LE_ACCEPT_CIS_REQUEST}, - {OpCode::LE_REJECT_CIS_REQUEST, OpCodeIndex::LE_REJECT_CIS_REQUEST}, - {OpCode::LE_CREATE_BIG, OpCodeIndex::LE_CREATE_BIG}, - {OpCode::LE_CREATE_BIG_TEST, OpCodeIndex::LE_CREATE_BIG_TEST}, - {OpCode::LE_TERMINATE_BIG, OpCodeIndex::LE_TERMINATE_BIG}, - {OpCode::LE_BIG_CREATE_SYNC, OpCodeIndex::LE_BIG_CREATE_SYNC}, - {OpCode::LE_BIG_TERMINATE_SYNC, OpCodeIndex::LE_BIG_TERMINATE_SYNC}, - {OpCode::LE_REQUEST_PEER_SCA, OpCodeIndex::LE_REQUEST_PEER_SCA}, - {OpCode::LE_SETUP_ISO_DATA_PATH, OpCodeIndex::LE_SETUP_ISO_DATA_PATH}, - {OpCode::LE_REMOVE_ISO_DATA_PATH, OpCodeIndex::LE_REMOVE_ISO_DATA_PATH}, - {OpCode::LE_ISO_TRANSMIT_TEST, OpCodeIndex::LE_ISO_TRANSMIT_TEST}, - {OpCode::LE_ISO_RECEIVE_TEST, OpCodeIndex::LE_ISO_RECEIVE_TEST}, - {OpCode::LE_ISO_READ_TEST_COUNTERS, OpCodeIndex::LE_ISO_READ_TEST_COUNTERS}, - {OpCode::LE_ISO_TEST_END, OpCodeIndex::LE_ISO_TEST_END}, - {OpCode::LE_SET_HOST_FEATURE_V1, OpCodeIndex::LE_SET_HOST_FEATURE_V1}, - {OpCode::LE_READ_ISO_LINK_QUALITY, OpCodeIndex::LE_READ_ISO_LINK_QUALITY}, - {OpCode::LE_ENHANCED_READ_TRANSMIT_POWER_LEVEL, - OpCodeIndex::LE_ENHANCED_READ_TRANSMIT_POWER_LEVEL}, - {OpCode::LE_READ_REMOTE_TRANSMIT_POWER_LEVEL, - OpCodeIndex::LE_READ_REMOTE_TRANSMIT_POWER_LEVEL}, - {OpCode::LE_SET_PATH_LOSS_REPORTING_PARAMETERS, - OpCodeIndex::LE_SET_PATH_LOSS_REPORTING_PARAMETERS}, - {OpCode::LE_SET_PATH_LOSS_REPORTING_ENABLE, OpCodeIndex::LE_SET_PATH_LOSS_REPORTING_ENABLE}, - {OpCode::LE_SET_TRANSMIT_POWER_REPORTING_ENABLE, - OpCodeIndex::LE_SET_TRANSMIT_POWER_REPORTING_ENABLE}, - {OpCode::LE_TRANSMITTER_TEST_V4, OpCodeIndex::LE_TRANSMITTER_TEST_V4}, - {OpCode::LE_SET_DATA_RELATED_ADDRESS_CHANGES, - OpCodeIndex::LE_SET_DATA_RELATED_ADDRESS_CHANGES}, - {OpCode::LE_SET_DEFAULT_SUBRATE, OpCodeIndex::LE_SET_DEFAULT_SUBRATE}, - {OpCode::LE_SUBRATE_REQUEST, OpCodeIndex::LE_SUBRATE_REQUEST}, - {OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V2, - OpCodeIndex::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V2}, - {OpCode::LE_SET_DECISION_DATA, OpCodeIndex::LE_SET_DECISION_DATA}, - {OpCode::LE_SET_DECISION_INSTRUCTIONS, OpCodeIndex::LE_SET_DECISION_INSTRUCTIONS}, - {OpCode::LE_SET_PERIODIC_ADVERTISING_SUBEVENT_DATA, - OpCodeIndex::LE_SET_PERIODIC_ADVERTISING_SUBEVENT_DATA}, - {OpCode::LE_SET_PERIODIC_ADVERTISING_RESPONSE_DATA, - OpCodeIndex::LE_SET_PERIODIC_ADVERTISING_RESPONSE_DATA}, - {OpCode::LE_SET_PERIODIC_SYNC_SUBEVENT, OpCodeIndex::LE_SET_PERIODIC_SYNC_SUBEVENT}, - {OpCode::LE_EXTENDED_CREATE_CONNECTION_V2, OpCodeIndex::LE_EXTENDED_CREATE_CONNECTION_V2}, - {OpCode::LE_SET_PERIODIC_ADVERTISING_PARAMETERS_V2, - OpCodeIndex::LE_SET_PERIODIC_ADVERTISING_PARAMETERS_V2}, - {OpCode::LE_READ_ALL_LOCAL_SUPPORTED_FEATURES, - OpCodeIndex::LE_READ_ALL_LOCAL_SUPPORTED_FEATURES}, - {OpCode::LE_READ_ALL_REMOTE_FEATURES, OpCodeIndex::LE_READ_ALL_REMOTE_FEATURES}, - {OpCode::LE_CS_READ_LOCAL_SUPPORTED_CAPABILITIES, - OpCodeIndex::LE_CS_READ_LOCAL_SUPPORTED_CAPABILITIES}, - {OpCode::LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES, - OpCodeIndex::LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES}, - {OpCode::LE_CS_WRITE_CACHED_REMOTE_SUPPORTED_CAPABILITIES, - OpCodeIndex::LE_CS_WRITE_CACHED_REMOTE_SUPPORTED_CAPABILITIES}, - {OpCode::LE_CS_SECURITY_ENABLE, OpCodeIndex::LE_CS_SECURITY_ENABLE}, - {OpCode::LE_CS_SET_DEFAULT_SETTINGS, OpCodeIndex::LE_CS_SET_DEFAULT_SETTINGS}, - {OpCode::LE_CS_READ_REMOTE_FAE_TABLE, OpCodeIndex::LE_CS_READ_REMOTE_FAE_TABLE}, - {OpCode::LE_CS_WRITE_CACHED_REMOTE_FAE_TABLE, - OpCodeIndex::LE_CS_WRITE_CACHED_REMOTE_FAE_TABLE}, - {OpCode::LE_CS_CREATE_CONFIG, OpCodeIndex::LE_CS_CREATE_CONFIG}, - {OpCode::LE_CS_REMOVE_CONFIG, OpCodeIndex::LE_CS_REMOVE_CONFIG}, - {OpCode::LE_CS_SET_CHANNEL_CLASSIFICATION, OpCodeIndex::LE_CS_SET_CHANNEL_CLASSIFICATION}, - {OpCode::LE_CS_SET_PROCEDURE_PARAMETERS, OpCodeIndex::LE_CS_SET_PROCEDURE_PARAMETERS}, - {OpCode::LE_CS_PROCEDURE_ENABLE, OpCodeIndex::LE_CS_PROCEDURE_ENABLE}, - {OpCode::LE_CS_TEST, OpCodeIndex::LE_CS_TEST}, - {OpCode::LE_CS_TEST_END, OpCodeIndex::LE_CS_TEST_END}, - {OpCode::LE_ADD_DEVICE_TO_MONITORED_ADVERTISERS_LIST, - OpCodeIndex::LE_ADD_DEVICE_TO_MONITORED_ADVERTISERS_LIST}, - {OpCode::LE_REMOVE_DEVICE_FROM_MONITORED_ADVERTISERS_LIST, - OpCodeIndex::LE_REMOVE_DEVICE_FROM_MONITORED_ADVERTISERS_LIST}, - {OpCode::LE_CLEAR_MONITORED_ADVERTISERS_LIST, - OpCodeIndex::LE_CLEAR_MONITORED_ADVERTISERS_LIST}, - {OpCode::LE_READ_MONITORED_ADVERTISERS_LIST_SIZE, - OpCodeIndex::LE_READ_MONITORED_ADVERTISERS_LIST_SIZE}, - {OpCode::LE_ENABLE_MONITORING_ADVERTISERS, OpCodeIndex::LE_ENABLE_MONITORING_ADVERTISERS}, - {OpCode::LE_FRAME_SPACE_UPDATE, OpCodeIndex::LE_FRAME_SPACE_UPDATE}, -}; - -const std::unordered_map - DualModeController::hci_command_handlers_{ - // LINK_CONTROL - {OpCode::INQUIRY, &DualModeController::Inquiry}, - {OpCode::INQUIRY_CANCEL, &DualModeController::InquiryCancel}, - //{OpCode::PERIODIC_INQUIRY_MODE, - //&DualModeController::PeriodicInquiryMode}, - //{OpCode::EXIT_PERIODIC_INQUIRY_MODE, - //&DualModeController::ExitPeriodicInquiryMode}, - {OpCode::CREATE_CONNECTION, &DualModeController::CreateConnection}, - {OpCode::DISCONNECT, &DualModeController::Disconnect}, - {OpCode::ADD_SCO_CONNECTION, &DualModeController::AddScoConnection}, - {OpCode::CREATE_CONNECTION_CANCEL, &DualModeController::CreateConnectionCancel}, - {OpCode::ACCEPT_CONNECTION_REQUEST, &DualModeController::AcceptConnectionRequest}, - {OpCode::REJECT_CONNECTION_REQUEST, &DualModeController::RejectConnectionRequest}, - {OpCode::LINK_KEY_REQUEST_REPLY, &DualModeController::ForwardToLm}, - {OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, &DualModeController::ForwardToLm}, - {OpCode::PIN_CODE_REQUEST_REPLY, &DualModeController::ForwardToLm}, - {OpCode::PIN_CODE_REQUEST_NEGATIVE_REPLY, &DualModeController::ForwardToLm}, - {OpCode::CHANGE_CONNECTION_PACKET_TYPE, - &DualModeController::ChangeConnectionPacketType}, - {OpCode::AUTHENTICATION_REQUESTED, &DualModeController::ForwardToLm}, - {OpCode::SET_CONNECTION_ENCRYPTION, &DualModeController::ForwardToLm}, - {OpCode::CHANGE_CONNECTION_LINK_KEY, &DualModeController::ChangeConnectionLinkKey}, - {OpCode::CENTRAL_LINK_KEY, &DualModeController::CentralLinkKey}, - {OpCode::REMOTE_NAME_REQUEST, &DualModeController::RemoteNameRequest}, - //{OpCode::REMOTE_NAME_REQUEST_CANCEL, - //&DualModeController::RemoteNameRequestCancel}, - {OpCode::READ_REMOTE_SUPPORTED_FEATURES, - &DualModeController::ReadRemoteSupportedFeatures}, - {OpCode::READ_REMOTE_EXTENDED_FEATURES, - &DualModeController::ReadRemoteExtendedFeatures}, - {OpCode::READ_REMOTE_VERSION_INFORMATION, - &DualModeController::ReadRemoteVersionInformation}, - {OpCode::READ_CLOCK_OFFSET, &DualModeController::ReadClockOffset}, - //{OpCode::READ_LMP_HANDLE, &DualModeController::ReadLmpHandle}, - {OpCode::SETUP_SYNCHRONOUS_CONNECTION, - &DualModeController::SetupSynchronousConnection}, - {OpCode::ACCEPT_SYNCHRONOUS_CONNECTION, - &DualModeController::AcceptSynchronousConnection}, - {OpCode::REJECT_SYNCHRONOUS_CONNECTION, - &DualModeController::RejectSynchronousConnection}, - {OpCode::IO_CAPABILITY_REQUEST_REPLY, &DualModeController::ForwardToLm}, - {OpCode::USER_CONFIRMATION_REQUEST_REPLY, &DualModeController::ForwardToLm}, - {OpCode::USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY, - &DualModeController::ForwardToLm}, - {OpCode::USER_PASSKEY_REQUEST_REPLY, &DualModeController::ForwardToLm}, - {OpCode::USER_PASSKEY_REQUEST_NEGATIVE_REPLY, &DualModeController::ForwardToLm}, - {OpCode::REMOTE_OOB_DATA_REQUEST_REPLY, &DualModeController::ForwardToLm}, - {OpCode::REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY, &DualModeController::ForwardToLm}, - {OpCode::IO_CAPABILITY_REQUEST_NEGATIVE_REPLY, &DualModeController::ForwardToLm}, - {OpCode::ENHANCED_SETUP_SYNCHRONOUS_CONNECTION, - &DualModeController::EnhancedSetupSynchronousConnection}, - {OpCode::ENHANCED_ACCEPT_SYNCHRONOUS_CONNECTION, - &DualModeController::EnhancedAcceptSynchronousConnection}, - //{OpCode::TRUNCATED_PAGE, &DualModeController::TruncatedPage}, - //{OpCode::TRUNCATED_PAGE_CANCEL, - //&DualModeController::TruncatedPageCancel}, - //{OpCode::SET_CONNECTIONLESS_PERIPHERAL_BROADCAST, - //&DualModeController::SetConnectionlessPeripheralBroadcast}, - //{OpCode::SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_RECEIVE, - //&DualModeController::SetConnectionlessPeripheralBroadcastReceive}, - //{OpCode::START_SYNCHRONIZATION_TRAIN, - //&DualModeController::StartSynchronizationTrain}, - //{OpCode::RECEIVE_SYNCHRONIZATION_TRAIN, - //&DualModeController::ReceiveSynchronizationTrain}, - {OpCode::REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY, &DualModeController::ForwardToLm}, - - // LINK_POLICY - {OpCode::HOLD_MODE, &DualModeController::HoldMode}, - {OpCode::SNIFF_MODE, &DualModeController::SniffMode}, - {OpCode::EXIT_SNIFF_MODE, &DualModeController::ExitSniffMode}, - {OpCode::QOS_SETUP, &DualModeController::QosSetup}, - {OpCode::ROLE_DISCOVERY, &DualModeController::RoleDiscovery}, - {OpCode::SWITCH_ROLE, &DualModeController::SwitchRole}, - {OpCode::READ_LINK_POLICY_SETTINGS, &DualModeController::ReadLinkPolicySettings}, - {OpCode::WRITE_LINK_POLICY_SETTINGS, &DualModeController::WriteLinkPolicySettings}, - {OpCode::READ_DEFAULT_LINK_POLICY_SETTINGS, - &DualModeController::ReadDefaultLinkPolicySettings}, - {OpCode::WRITE_DEFAULT_LINK_POLICY_SETTINGS, - &DualModeController::WriteDefaultLinkPolicySettings}, - {OpCode::FLOW_SPECIFICATION, &DualModeController::FlowSpecification}, - {OpCode::SNIFF_SUBRATING, &DualModeController::SniffSubrating}, - - // CONTROLLER_AND_BASEBAND - {OpCode::SET_EVENT_MASK, &DualModeController::SetEventMask}, - {OpCode::RESET, &DualModeController::Reset}, - {OpCode::SET_EVENT_FILTER, &DualModeController::SetEventFilter}, - //{OpCode::FLUSH, &DualModeController::Flush}, - //{OpCode::READ_PIN_TYPE, &DualModeController::ReadPinType}, - //{OpCode::WRITE_PIN_TYPE, &DualModeController::WritePinType}, - //{OpCode::READ_STORED_LINK_KEY, - //&DualModeController::ReadStoredLinkKey}, - //{OpCode::WRITE_STORED_LINK_KEY, - //&DualModeController::WriteStoredLinkKey}, - {OpCode::DELETE_STORED_LINK_KEY, &DualModeController::DeleteStoredLinkKey}, - {OpCode::WRITE_LOCAL_NAME, &DualModeController::WriteLocalName}, - {OpCode::READ_LOCAL_NAME, &DualModeController::ReadLocalName}, - {OpCode::READ_CONNECTION_ACCEPT_TIMEOUT, - &DualModeController::ReadConnectionAcceptTimeout}, - {OpCode::WRITE_CONNECTION_ACCEPT_TIMEOUT, - &DualModeController::WriteConnectionAcceptTimeout}, - {OpCode::READ_PAGE_TIMEOUT, &DualModeController::ReadPageTimeout}, - {OpCode::WRITE_PAGE_TIMEOUT, &DualModeController::WritePageTimeout}, - {OpCode::READ_SCAN_ENABLE, &DualModeController::ReadScanEnable}, - {OpCode::WRITE_SCAN_ENABLE, &DualModeController::WriteScanEnable}, - {OpCode::READ_PAGE_SCAN_ACTIVITY, &DualModeController::ReadPageScanActivity}, - {OpCode::WRITE_PAGE_SCAN_ACTIVITY, &DualModeController::WritePageScanActivity}, - {OpCode::READ_INQUIRY_SCAN_ACTIVITY, &DualModeController::ReadInquiryScanActivity}, - {OpCode::WRITE_INQUIRY_SCAN_ACTIVITY, - &DualModeController::WriteInquiryScanActivity}, - {OpCode::READ_AUTHENTICATION_ENABLE, &DualModeController::ReadAuthenticationEnable}, - {OpCode::WRITE_AUTHENTICATION_ENABLE, - &DualModeController::WriteAuthenticationEnable}, - {OpCode::READ_CLASS_OF_DEVICE, &DualModeController::ReadClassOfDevice}, - {OpCode::WRITE_CLASS_OF_DEVICE, &DualModeController::WriteClassOfDevice}, - {OpCode::READ_VOICE_SETTING, &DualModeController::ReadVoiceSetting}, - {OpCode::WRITE_VOICE_SETTING, &DualModeController::WriteVoiceSetting}, - //{OpCode::READ_AUTOMATIC_FLUSH_TIMEOUT, - //&DualModeController::ReadAutomaticFlushTimeout}, - //{OpCode::WRITE_AUTOMATIC_FLUSH_TIMEOUT, - //&DualModeController::WriteAutomaticFlushTimeout}, - //{OpCode::READ_NUM_BROADCAST_RETRANSMITS, - //&DualModeController::ReadNumBroadcastRetransmits}, - //{OpCode::WRITE_NUM_BROADCAST_RETRANSMITS, - //&DualModeController::WriteNumBroadcastRetransmits}, - //{OpCode::READ_HOLD_MODE_ACTIVITY, - //&DualModeController::ReadHoldModeActivity}, - //{OpCode::WRITE_HOLD_MODE_ACTIVITY, - //&DualModeController::WriteHoldModeActivity}, - {OpCode::READ_TRANSMIT_POWER_LEVEL, &DualModeController::ReadTransmitPowerLevel}, - {OpCode::READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE, - &DualModeController::ReadSynchronousFlowControlEnable}, - {OpCode::WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE, - &DualModeController::WriteSynchronousFlowControlEnable}, - //{OpCode::SET_CONTROLLER_TO_HOST_FLOW_CONTROL, - //&DualModeController::SetControllerToHostFlowControl}, - {OpCode::HOST_BUFFER_SIZE, &DualModeController::HostBufferSize}, - //{OpCode::HOST_NUMBER_OF_COMPLETED_PACKETS, - //&DualModeController::HostNumberOfCompletedPackets}, - //{OpCode::READ_LINK_SUPERVISION_TIMEOUT, - //&DualModeController::ReadLinkSupervisionTimeout}, - {OpCode::WRITE_LINK_SUPERVISION_TIMEOUT, - &DualModeController::WriteLinkSupervisionTimeout}, - {OpCode::READ_NUMBER_OF_SUPPORTED_IAC, - &DualModeController::ReadNumberOfSupportedIac}, - {OpCode::READ_CURRENT_IAC_LAP, &DualModeController::ReadCurrentIacLap}, - {OpCode::WRITE_CURRENT_IAC_LAP, &DualModeController::WriteCurrentIacLap}, - //{OpCode::SET_AFH_HOST_CHANNEL_CLASSIFICATION, - //&DualModeController::SetAfhHostChannelClassification}, - {OpCode::READ_INQUIRY_SCAN_TYPE, &DualModeController::ReadInquiryScanType}, - {OpCode::WRITE_INQUIRY_SCAN_TYPE, &DualModeController::WriteInquiryScanType}, - {OpCode::READ_INQUIRY_MODE, &DualModeController::ReadInquiryMode}, - {OpCode::WRITE_INQUIRY_MODE, &DualModeController::WriteInquiryMode}, - {OpCode::READ_PAGE_SCAN_TYPE, &DualModeController::ReadPageScanType}, - {OpCode::WRITE_PAGE_SCAN_TYPE, &DualModeController::WritePageScanType}, - //{OpCode::READ_AFH_CHANNEL_ASSESSMENT_MODE, - //&DualModeController::ReadAfhChannelAssessmentMode}, - //{OpCode::WRITE_AFH_CHANNEL_ASSESSMENT_MODE, - //&DualModeController::WriteAfhChannelAssessmentMode}, - //{OpCode::READ_EXTENDED_INQUIRY_RESPONSE, - //&DualModeController::ReadExtendedInquiryResponse}, - {OpCode::WRITE_EXTENDED_INQUIRY_RESPONSE, - &DualModeController::WriteExtendedInquiryResponse}, - {OpCode::REFRESH_ENCRYPTION_KEY, &DualModeController::RefreshEncryptionKey}, - //{OpCode::READ_SIMPLE_PAIRING_MODE, - //&DualModeController::ReadSimplePairingMode}, - {OpCode::WRITE_SIMPLE_PAIRING_MODE, &DualModeController::WriteSimplePairingMode}, - {OpCode::READ_LOCAL_OOB_DATA, &DualModeController::ReadLocalOobData}, - {OpCode::READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL, - &DualModeController::ReadInquiryResponseTransmitPowerLevel}, - //{OpCode::WRITE_INQUIRY_TRANSMIT_POWER_LEVEL, - //&DualModeController::WriteInquiryTransmitPowerLevel}, - //{OpCode::READ_DEFAULT_ERRONEOUS_DATA_REPORTING, - //&DualModeController::ReadDefaultErroneousDataReporting}, - //{OpCode::WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING, - //&DualModeController::WriteDefaultErroneousDataReporting}, - {OpCode::ENHANCED_FLUSH, &DualModeController::EnhancedFlush}, - {OpCode::SEND_KEYPRESS_NOTIFICATION, &DualModeController::ForwardToLm}, - {OpCode::SET_EVENT_MASK_PAGE_2, &DualModeController::SetEventMaskPage2}, - //{OpCode::READ_FLOW_CONTROL_MODE, - //&DualModeController::ReadFlowControlMode}, - //{OpCode::WRITE_FLOW_CONTROL_MODE, - //&DualModeController::WriteFlowControlMode}, - {OpCode::READ_ENHANCED_TRANSMIT_POWER_LEVEL, - &DualModeController::ReadEnhancedTransmitPowerLevel}, - //{OpCode::READ_LE_HOST_SUPPORT, - //&DualModeController::ReadLeHostSupport}, - {OpCode::WRITE_LE_HOST_SUPPORT, &DualModeController::WriteLeHostSupport}, - //{OpCode::SET_MWS_CHANNEL_PARAMETERS, - //&DualModeController::SetMwsChannelParameters}, - //{OpCode::SET_EXTERNAL_FRAME_CONFIGURATION, - //&DualModeController::SetExternalFrameConfiguration}, - //{OpCode::SET_MWS_SIGNALING, &DualModeController::SetMwsSignaling}, - //{OpCode::SET_MWS_TRANSPORT_LAYER, - //&DualModeController::SetMwsTransportLayer}, - //{OpCode::SET_MWS_SCAN_FREQUENCY_TABLE, - //&DualModeController::SetMwsScanFrequencyTable}, - //{OpCode::SET_MWS_PATTERN_CONFIGURATION, - //&DualModeController::SetMwsPatternConfiguration}, - //{OpCode::SET_RESERVED_LT_ADDR, - //&DualModeController::SetReservedLtAddr}, - //{OpCode::DELETE_RESERVED_LT_ADDR, - //&DualModeController::DeleteReservedLtAddr}, - //{OpCode::SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_DATA, - //&DualModeController::SetConnectionlessPeripheralBroadcastData}, - //{OpCode::READ_SYNCHRONIZATION_TRAIN_PARAMETERS, - //&DualModeController::ReadSynchronizationTrainParameters}, - //{OpCode::WRITE_SYNCHRONIZATION_TRAIN_PARAMETERS, - //&DualModeController::WriteSynchronizationTrainParameters}, - //{OpCode::READ_SECURE_CONNECTIONS_HOST_SUPPORT, - //&DualModeController::ReadSecureConnectionsHostSupport}, - {OpCode::WRITE_SECURE_CONNECTIONS_HOST_SUPPORT, - &DualModeController::WriteSecureConnectionsHostSupport}, - //{OpCode::READ_AUTHENTICATED_PAYLOAD_TIMEOUT, - //&DualModeController::ReadAuthenticatedPayloadTimeout}, - //{OpCode::WRITE_AUTHENTICATED_PAYLOAD_TIMEOUT, - //&DualModeController::WriteAuthenticatedPayloadTimeout}, - {OpCode::READ_LOCAL_OOB_EXTENDED_DATA, - &DualModeController::ReadLocalOobExtendedData}, - //{OpCode::READ_EXTENDED_PAGE_TIMEOUT, - //&DualModeController::ReadExtendedPageTimeout}, - //{OpCode::WRITE_EXTENDED_PAGE_TIMEOUT, - //&DualModeController::WriteExtendedPageTimeout}, - //{OpCode::READ_EXTENDED_INQUIRY_LENGTH, - //&DualModeController::ReadExtendedInquiryLength}, - //{OpCode::WRITE_EXTENDED_INQUIRY_LENGTH, - //&DualModeController::WriteExtendedInquiryLength}, - //{OpCode::SET_ECOSYSTEM_BASE_INTERVAL, - //&DualModeController::SetEcosystemBaseInterval}, - //{OpCode::CONFIGURE_DATA_PATH, &DualModeController::ConfigureDataPath}, - {OpCode::SET_MIN_ENCRYPTION_KEY_SIZE, &DualModeController::SetMinEncryptionKeySize}, - - // INFORMATIONAL_PARAMETERS - {OpCode::READ_LOCAL_VERSION_INFORMATION, - &DualModeController::ReadLocalVersionInformation}, - {OpCode::READ_LOCAL_SUPPORTED_COMMANDS, - &DualModeController::ReadLocalSupportedCommands}, - {OpCode::READ_LOCAL_SUPPORTED_FEATURES, - &DualModeController::ReadLocalSupportedFeatures}, - {OpCode::READ_LOCAL_EXTENDED_FEATURES, - &DualModeController::ReadLocalExtendedFeatures}, - {OpCode::READ_BUFFER_SIZE, &DualModeController::ReadBufferSize}, - {OpCode::READ_BD_ADDR, &DualModeController::ReadBdAddr}, - //{OpCode::READ_DATA_BLOCK_SIZE, - //&DualModeController::ReadDataBlockSize}, - {OpCode::READ_LOCAL_SUPPORTED_CODECS_V1, - &DualModeController::ReadLocalSupportedCodecsV1}, - //{OpCode::READ_LOCAL_SIMPLE_PAIRING_OPTIONS, - //&DualModeController::ReadLocalSimplePairingOptions}, - //{OpCode::READ_LOCAL_SUPPORTED_CODECS_V2, - //&DualModeController::ReadLocalSupportedCodecsV2}, - //{OpCode::READ_LOCAL_SUPPORTED_CODEC_CAPABILITIES, - //&DualModeController::ReadLocalSupportedCodecCapabilities}, - //{OpCode::READ_LOCAL_SUPPORTED_CONTROLLER_DELAY, - //&DualModeController::ReadLocalSupportedControllerDelay}, - - // STATUS_PARAMETERS - {OpCode::READ_FAILED_CONTACT_COUNTER, - &DualModeController::ReadFailedContactCounter}, - {OpCode::RESET_FAILED_CONTACT_COUNTER, - &DualModeController::ResetFailedContactCounter}, - //{OpCode::READ_LINK_QUALITY, &DualModeController::ReadLinkQuality}, - {OpCode::READ_RSSI, &DualModeController::ReadRssi}, - //{OpCode::READ_AFH_CHANNEL_MAP, - //&DualModeController::ReadAfhChannelMap}, - //{OpCode::READ_CLOCK, &DualModeController::ReadClock}, - {OpCode::READ_ENCRYPTION_KEY_SIZE, &DualModeController::ReadEncryptionKeySize}, - //{OpCode::GET_MWS_TRANSPORT_LAYER_CONFIGURATION, - //&DualModeController::GetMwsTransportLayerConfiguration}, - //{OpCode::SET_TRIGGERED_CLOCK_CAPTURE, - //&DualModeController::SetTriggeredClockCapture}, - - // TESTING - {OpCode::READ_LOOPBACK_MODE, &DualModeController::ReadLoopbackMode}, - {OpCode::WRITE_LOOPBACK_MODE, &DualModeController::WriteLoopbackMode}, - //{OpCode::ENABLE_DEVICE_UNDER_TEST_MODE, - //&DualModeController::EnableDeviceUnderTestMode}, - //{OpCode::WRITE_SIMPLE_PAIRING_DEBUG_MODE, - //&DualModeController::WriteSimplePairingDebugMode}, - //{OpCode::WRITE_SECURE_CONNECTIONS_TEST_MODE, - //&DualModeController::WriteSecureConnectionsTestMode}, - - // LE_CONTROLLER - {OpCode::LE_SET_EVENT_MASK, &DualModeController::LeSetEventMask}, - {OpCode::LE_READ_BUFFER_SIZE_V1, &DualModeController::LeReadBufferSizeV1}, - {OpCode::LE_READ_LOCAL_SUPPORTED_FEATURES_PAGE_0, - &DualModeController::LeReadLocalSupportedFeaturesPage0}, - {OpCode::LE_SET_RANDOM_ADDRESS, &DualModeController::LeSetRandomAddress}, - {OpCode::LE_SET_ADVERTISING_PARAMETERS, - &DualModeController::LeSetAdvertisingParameters}, - {OpCode::LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER, - &DualModeController::LeReadAdvertisingPhysicalChannelTxPower}, - {OpCode::LE_SET_ADVERTISING_DATA, &DualModeController::LeSetAdvertisingData}, - {OpCode::LE_SET_SCAN_RESPONSE_DATA, &DualModeController::LeSetScanResponseData}, - {OpCode::LE_SET_ADVERTISING_ENABLE, &DualModeController::LeSetAdvertisingEnable}, - {OpCode::LE_SET_SCAN_PARAMETERS, &DualModeController::LeSetScanParameters}, - {OpCode::LE_SET_SCAN_ENABLE, &DualModeController::LeSetScanEnable}, - {OpCode::LE_CREATE_CONNECTION, &DualModeController::LeCreateConnection}, - {OpCode::LE_CREATE_CONNECTION_CANCEL, - &DualModeController::LeCreateConnectionCancel}, - {OpCode::LE_READ_FILTER_ACCEPT_LIST_SIZE, - &DualModeController::LeReadFilterAcceptListSize}, - {OpCode::LE_CLEAR_FILTER_ACCEPT_LIST, &DualModeController::LeClearFilterAcceptList}, - {OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST, - &DualModeController::LeAddDeviceToFilterAcceptList}, - {OpCode::LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST, - &DualModeController::LeRemoveDeviceFromFilterAcceptList}, - {OpCode::LE_CONNECTION_UPDATE, &DualModeController::LeConnectionUpdate}, - //{OpCode::LE_SET_HOST_CHANNEL_CLASSIFICATION, - //&DualModeController::LeSetHostChannelClassification}, - //{OpCode::LE_READ_CHANNEL_MAP, &DualModeController::LeReadChannelMap}, - {OpCode::LE_READ_REMOTE_FEATURES_PAGE_0, - &DualModeController::LeReadRemoteFeaturesPage0}, - {OpCode::LE_ENCRYPT, &DualModeController::LeEncrypt}, - {OpCode::LE_RAND, &DualModeController::LeRand}, - {OpCode::LE_START_ENCRYPTION, &DualModeController::LeStartEncryption}, - {OpCode::LE_LONG_TERM_KEY_REQUEST_REPLY, - &DualModeController::LeLongTermKeyRequestReply}, - {OpCode::LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY, - &DualModeController::LeLongTermKeyRequestNegativeReply}, - {OpCode::LE_READ_SUPPORTED_STATES, &DualModeController::LeReadSupportedStates}, - //{OpCode::LE_RECEIVER_TEST_V1, &DualModeController::LeReceiverTestV1}, - //{OpCode::LE_TRANSMITTER_TEST_V1, - //&DualModeController::LeTransmitterTestV1}, - //{OpCode::LE_TEST_END, &DualModeController::LeTestEnd}, - {OpCode::LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY, - &DualModeController::LeRemoteConnectionParameterRequestReply}, - {OpCode::LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY, - &DualModeController::LeRemoteConnectionParameterRequestNegativeReply}, - {OpCode::LE_SET_DATA_LENGTH, &DualModeController::LeSetDataLength}, - {OpCode::LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH, - &DualModeController::LeReadSuggestedDefaultDataLength}, - {OpCode::LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH, - &DualModeController::LeWriteSuggestedDefaultDataLength}, - {OpCode::LE_READ_LOCAL_P_256_PUBLIC_KEY, - &DualModeController::LeReadLocalP256PublicKey}, - //{OpCode::LE_GENERATE_DHKEY_V1, - //&DualModeController::LeGenerateDhkeyV1}, - {OpCode::LE_ADD_DEVICE_TO_RESOLVING_LIST, - &DualModeController::LeAddDeviceToResolvingList}, - {OpCode::LE_REMOVE_DEVICE_FROM_RESOLVING_LIST, - &DualModeController::LeRemoveDeviceFromResolvingList}, - {OpCode::LE_CLEAR_RESOLVING_LIST, &DualModeController::LeClearResolvingList}, - {OpCode::LE_READ_RESOLVING_LIST_SIZE, &DualModeController::LeReadResolvingListSize}, - {OpCode::LE_READ_PEER_RESOLVABLE_ADDRESS, - &DualModeController::LeReadPeerResolvableAddress}, - {OpCode::LE_READ_LOCAL_RESOLVABLE_ADDRESS, - &DualModeController::LeReadLocalResolvableAddress}, - {OpCode::LE_SET_ADDRESS_RESOLUTION_ENABLE, - &DualModeController::LeSetAddressResolutionEnable}, - {OpCode::LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT, - &DualModeController::LeSetResolvablePrivateAddressTimeout}, - {OpCode::LE_READ_MAXIMUM_DATA_LENGTH, &DualModeController::LeReadMaximumDataLength}, - {OpCode::LE_READ_PHY, &DualModeController::LeReadPhy}, - {OpCode::LE_SET_DEFAULT_PHY, &DualModeController::LeSetDefaultPhy}, - {OpCode::LE_SET_PHY, &DualModeController::LeSetPhy}, - //{OpCode::LE_RECEIVER_TEST_V2, &DualModeController::LeReceiverTestV2}, - //{OpCode::LE_TRANSMITTER_TEST_V2, - //&DualModeController::LeTransmitterTestV2}, - {OpCode::LE_SET_ADVERTISING_SET_RANDOM_ADDRESS, - &DualModeController::LeSetAdvertisingSetRandomAddress}, - {OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1, - &DualModeController::LeSetExtendedAdvertisingParametersV1}, - {OpCode::LE_SET_EXTENDED_ADVERTISING_DATA, - &DualModeController::LeSetExtendedAdvertisingData}, - {OpCode::LE_SET_EXTENDED_SCAN_RESPONSE_DATA, - &DualModeController::LeSetExtendedScanResponseData}, - {OpCode::LE_SET_EXTENDED_ADVERTISING_ENABLE, - &DualModeController::LeSetExtendedAdvertisingEnable}, - {OpCode::LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH, - &DualModeController::LeReadMaximumAdvertisingDataLength}, - {OpCode::LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS, - &DualModeController::LeReadNumberOfSupportedAdvertisingSets}, - {OpCode::LE_REMOVE_ADVERTISING_SET, &DualModeController::LeRemoveAdvertisingSet}, - {OpCode::LE_CLEAR_ADVERTISING_SETS, &DualModeController::LeClearAdvertisingSets}, - {OpCode::LE_SET_PERIODIC_ADVERTISING_PARAMETERS_V1, - &DualModeController::LeSetPeriodicAdvertisingParametersV1}, - {OpCode::LE_SET_PERIODIC_ADVERTISING_DATA, - &DualModeController::LeSetPeriodicAdvertisingData}, - {OpCode::LE_SET_PERIODIC_ADVERTISING_ENABLE, - &DualModeController::LeSetPeriodicAdvertisingEnable}, - {OpCode::LE_SET_EXTENDED_SCAN_PARAMETERS, - &DualModeController::LeSetExtendedScanParameters}, - {OpCode::LE_SET_EXTENDED_SCAN_ENABLE, &DualModeController::LeSetExtendedScanEnable}, - {OpCode::LE_EXTENDED_CREATE_CONNECTION_V1, - &DualModeController::LeExtendedCreateConnectionV1}, - {OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC, - &DualModeController::LePeriodicAdvertisingCreateSync}, - {OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL, - &DualModeController::LePeriodicAdvertisingCreateSyncCancel}, - {OpCode::LE_PERIODIC_ADVERTISING_TERMINATE_SYNC, - &DualModeController::LePeriodicAdvertisingTerminateSync}, - {OpCode::LE_ADD_DEVICE_TO_PERIODIC_ADVERTISER_LIST, - &DualModeController::LeAddDeviceToPeriodicAdvertiserList}, - {OpCode::LE_REMOVE_DEVICE_FROM_PERIODIC_ADVERTISER_LIST, - &DualModeController::LeRemoveDeviceFromPeriodicAdvertiserList}, - {OpCode::LE_CLEAR_PERIODIC_ADVERTISER_LIST, - &DualModeController::LeClearPeriodicAdvertiserList}, - {OpCode::LE_READ_PERIODIC_ADVERTISER_LIST_SIZE, - &DualModeController::LeReadPeriodicAdvertiserListSize}, - //{OpCode::LE_READ_TRANSMIT_POWER, - //&DualModeController::LeReadTransmitPower}, - //{OpCode::LE_READ_RF_PATH_COMPENSATION_POWER, - //&DualModeController::LeReadRfPathCompensationPower}, - //{OpCode::LE_WRITE_RF_PATH_COMPENSATION_POWER, - //&DualModeController::LeWriteRfPathCompensationPower}, - {OpCode::LE_SET_PRIVACY_MODE, &DualModeController::LeSetPrivacyMode}, - //{OpCode::LE_RECEIVER_TEST_V3, &DualModeController::LeReceiverTestV3}, - //{OpCode::LE_TRANSMITTER_TEST_V3, - //&DualModeController::LeTransmitterTestV3}, - //{OpCode::LE_SET_CONNECTIONLESS_CTE_TRANSMIT_PARAMETERS, - //&DualModeController::LeSetConnectionlessCteTransmitParameters}, - //{OpCode::LE_SET_CONNECTIONLESS_CTE_TRANSMIT_ENABLE, - //&DualModeController::LeSetConnectionlessCteTransmitEnable}, - //{OpCode::LE_SET_CONNECTIONLESS_IQ_SAMPLING_ENABLE, - //&DualModeController::LeSetConnectionlessIqSamplingEnable}, - //{OpCode::LE_SET_CONNECTION_CTE_RECEIVE_PARAMETERS, - //&DualModeController::LeSetConnectionCteReceiveParameters}, - //{OpCode::LE_SET_CONNECTION_CTE_TRANSMIT_PARAMETERS, - //&DualModeController::LeSetConnectionCteTransmitParameters}, - //{OpCode::LE_CONNECTION_CTE_REQUEST_ENABLE, - //&DualModeController::LeConnectionCteRequestEnable}, - //{OpCode::LE_CONNECTION_CTE_RESPONSE_ENABLE, - //&DualModeController::LeConnectionCteResponseEnable}, - //{OpCode::LE_READ_ANTENNA_INFORMATION, - //&DualModeController::LeReadAntennaInformation}, - //{OpCode::LE_SET_PERIODIC_ADVERTISING_RECEIVE_ENABLE, - //&DualModeController::LeSetPeriodicAdvertisingReceiveEnable}, - //{OpCode::LE_PERIODIC_ADVERTISING_SYNC_TRANSFER, - //&DualModeController::LePeriodicAdvertisingSyncTransfer}, - //{OpCode::LE_PERIODIC_ADVERTISING_SET_INFO_TRANSFER, - //&DualModeController::LePeriodicAdvertisingSetInfoTransfer}, - //{OpCode::LE_SET_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS, - //&DualModeController::LeSetPeriodicAdvertisingSyncTransferParameters}, - //{OpCode::LE_SET_DEFAULT_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS, - //&DualModeController::LeSetDefaultPeriodicAdvertisingSyncTransferParameters}, - //{OpCode::LE_GENERATE_DHKEY_V2, - //&DualModeController::LeGenerateDhkeyV2}, - //{OpCode::LE_MODIFY_SLEEP_CLOCK_ACCURACY, - //&DualModeController::LeModifySleepClockAccuracy}, - {OpCode::LE_READ_BUFFER_SIZE_V2, &DualModeController::LeReadBufferSizeV2}, - //{OpCode::LE_READ_ISO_TX_SYNC, &DualModeController::LeReadIsoTxSync}, - {OpCode::LE_SET_CIG_PARAMETERS, &DualModeController::ForwardToLl}, - {OpCode::LE_SET_CIG_PARAMETERS_TEST, &DualModeController::ForwardToLl}, - {OpCode::LE_CREATE_CIS, &DualModeController::ForwardToLl}, - {OpCode::LE_REMOVE_CIG, &DualModeController::ForwardToLl}, - {OpCode::LE_ACCEPT_CIS_REQUEST, &DualModeController::ForwardToLl}, - {OpCode::LE_REJECT_CIS_REQUEST, &DualModeController::ForwardToLl}, - //{OpCode::LE_CREATE_BIG, &DualModeController::LeCreateBig}, - //{OpCode::LE_CREATE_BIG_TEST, &DualModeController::LeCreateBigTest}, - //{OpCode::LE_TERMINATE_BIG, &DualModeController::LeTerminateBig}, - //{OpCode::LE_BIG_CREATE_SYNC, &DualModeController::LeBigCreateSync}, - //{OpCode::LE_BIG_TERMINATE_SYNC, - //&DualModeController::LeBigTerminateSync}, - {OpCode::LE_REQUEST_PEER_SCA, &DualModeController::LeRequestPeerSca}, - {OpCode::LE_SETUP_ISO_DATA_PATH, &DualModeController::ForwardToLl}, - {OpCode::LE_REMOVE_ISO_DATA_PATH, &DualModeController::ForwardToLl}, - //{OpCode::LE_ISO_TRANSMIT_TEST, - //&DualModeController::LeIsoTransmitTest}, - //{OpCode::LE_ISO_RECEIVE_TEST, &DualModeController::LeIsoReceiveTest}, - //{OpCode::LE_ISO_READ_TEST_COUNTERS, - //&DualModeController::LeIsoReadTestCounters}, - //{OpCode::LE_ISO_TEST_END, &DualModeController::LeIsoTestEnd}, - {OpCode::LE_SET_HOST_FEATURE_V1, &DualModeController::LeSetHostFeatureV1}, - //{OpCode::LE_READ_ISO_LINK_QUALITY, - //&DualModeController::LeReadIsoLinkQuality}, - //{OpCode::LE_ENHANCED_READ_TRANSMIT_POWER_LEVEL, - //&DualModeController::LeEnhancedReadTransmitPowerLevel}, - //{OpCode::LE_READ_REMOTE_TRANSMIT_POWER_LEVEL, - //&DualModeController::LeReadRemoteTransmitPowerLevel}, - //{OpCode::LE_SET_PATH_LOSS_REPORTING_PARAMETERS, - //&DualModeController::LeSetPathLossReportingParameters}, - //{OpCode::LE_SET_PATH_LOSS_REPORTING_ENABLE, - //&DualModeController::LeSetPathLossReportingEnable}, - //{OpCode::LE_SET_TRANSMIT_POWER_REPORTING_ENABLE, - //&DualModeController::LeSetTransmitPowerReportingEnable}, - //{OpCode::LE_TRANSMITTER_TEST_V4, - //&DualModeController::LeTransmitterTestV4}, - //{OpCode::LE_SET_DATA_RELATED_ADDRESS_CHANGES, - //&DualModeController::LeSetDataRelatedAddressChanges}, - //{OpCode::LE_SET_DEFAULT_SUBRATE, - //&DualModeController::LeSetDefaultSubrate}, - //{OpCode::LE_SUBRATE_REQUEST, &DualModeController::LeSubrateRequest}, - //{OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V2, - //&DualModeController::LeSetExtendedAdvertisingParametersV2}, - //{OpCode::LE_SET_DECISION_DATA, &DualModeController::LeSetDecisionData}, - //{OpCode::LE_SET_DECISION_INSTRUCTIONS, - //&DualModeController::LeSetDecisionInstructions}, - //{OpCode::LE_SET_PERIODIC_ADVERTISING_SUBEVENT_DATA, - //&DualModeController::LeSetPeriodicAdvertisingSubeventData}, - //{OpCode::LE_SET_PERIODIC_ADVERTISING_RESPONSE_DATA, - //&DualModeController::LeSetPeriodicAdvertisingResponseData}, - //{OpCode::LE_SET_PERIODIC_SYNC_SUBEVENT, - //&DualModeController::LeSetPeriodicSyncSubevent}, - //{OpCode::LE_EXTENDED_CREATE_CONNECTION_V2, - //&DualModeController::LeExtendedCreateConnectionV2}, - //{OpCode::LE_SET_PERIODIC_ADVERTISING_PARAMETERS_V2, - //&DualModeController::LeSetPeriodicAdvertisingParametersV2}, - //{OpCode::LE_READ_ALL_LOCAL_SUPPORTED_FEATURES, - //&DualModeController::LeReadAllLocalSupportedFeatures}, - //{OpCode::LE_READ_ALL_REMOTE_FEATURES, - //&DualModeController::LeReadAllRemoteFeatures}, - //{OpCode::LE_CS_READ_LOCAL_SUPPORTED_CAPABILITIES, - //&DualModeController::LeCsReadLocalSupportedCapabilities}, - //{OpCode::LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES, - //&DualModeController::LeCsReadRemoteSupportedCapabilities}, - //{OpCode::LE_CS_WRITE_CACHED_REMOTE_SUPPORTED_CAPABILITIES, - //&DualModeController::LeCsWriteCachedRemoteSupportedCapabilities}, - //{OpCode::LE_CS_SECURITY_ENABLE, &DualModeController::LeCsSecurityEnable}, - //{OpCode::LE_CS_SET_DEFAULT_SETTINGS, &DualModeController::LeCsSetDefaultSettings}, - //{OpCode::LE_CS_READ_REMOTE_FAE_TABLE, - //&DualModeController::LeCsReadRemoteFaeTable}, - //{OpCode::LE_CS_WRITE_CACHED_REMOTE_FAE_TABLE, - //&DualModeController::LeCsWriteCachedRemoteFaeTable}, - //{OpCode::LE_CS_CREATE_CONFIG, &DualModeController::LeCsCreateConfig}, - //{OpCode::LE_CS_REMOVE_CONFIG, &DualModeController::LeCsRemoveConfig}, - //{OpCode::LE_CS_SET_CHANNEL_CLASSIFICATION, - //&DualModeController::LeCsSetChannelClassification}, - //{OpCode::LE_CS_SET_PROCEDURE_PARAMETERS, - //&DualModeController::LeCsSetProcedureParameters}, - //{OpCode::LE_CS_PROCEDURE_ENABLE, &DualModeController::LeCsProcedureEnable}, - //{OpCode::LE_CS_TEST, &DualModeController::LeCsTest}, - //{OpCode::LE_CS_TEST_END, &DualModeController::LeCsTestEnd}, - //{OpCode::LE_ADD_DEVICE_TO_MONITORED_ADVERTISERS_LIST, - //&DualModeController::LeAddDeviceToMonitoredAdvertisersList}, - //{OpCode::LE_REMOVE_DEVICE_FROM_MONITORED_ADVERTISERS_LIST, - //&DualModeController::LeRemoveDeviceFromMonitoredAdvertisersList}, - //{OpCode::LE_CLEAR_MONITORED_ADVERTISERS_LIST, - //&DualModeController::LeClearMonitoredAdvertisersList}, - //{OpCode::LE_READ_MONITORED_ADVERTISERS_LIST_SIZE, - //&DualModeController::LeReadMonitoredAdvertisersListSize}, - //{OpCode::LE_ENABLE_MONITORED_ADVERTISERS, - //&DualModeController::LeEnableMonitoredAdvertisers}, - //{OpCode::LE_FRAME_SPACE_UPDATE, &DualModeController::LeFrameSpaceUpdate}, - - // VENDOR - {OpCode(CSR_VENDOR), &DualModeController::CsrVendorCommand}, - {OpCode::LE_GET_VENDOR_CAPABILITIES, &DualModeController::LeGetVendorCapabilities}, - {OpCode::LE_BATCH_SCAN, &DualModeController::LeBatchScan}, - {OpCode::LE_APCF, &DualModeController::LeApcf}, - {OpCode::LE_GET_CONTROLLER_ACTIVITY_ENERGY_INFO, - &DualModeController::LeGetControllerActivityEnergyInfo}, - {OpCode::LE_EX_SET_SCAN_PARAMETERS, &DualModeController::LeExSetScanParameters}, - {OpCode::GET_CONTROLLER_DEBUG_INFO, &DualModeController::GetControllerDebugInfo}, - {OpCode::INTEL_DDC_CONFIG_READ, &DualModeController::IntelDdcConfigRead}, - {OpCode::INTEL_DDC_CONFIG_WRITE, &DualModeController::IntelDdcConfigWrite}, - }; +const std::unordered_map& DualModeController::GetOpCodeToIndex() { + // This local static map will be constructed on the first call to GetOpCodeToIndex() + // and correctly destructed when the program exits (after all other static objects + // that depend on it are conceptually gone, because it's only destroyed when it goes + // out of scope at program termination). + static const std::unordered_map op_code_to_index = { + // LINK_CONTROL + {OpCode::INQUIRY, OpCodeIndex::INQUIRY}, + {OpCode::INQUIRY_CANCEL, OpCodeIndex::INQUIRY_CANCEL}, + {OpCode::PERIODIC_INQUIRY_MODE, OpCodeIndex::PERIODIC_INQUIRY_MODE}, + {OpCode::EXIT_PERIODIC_INQUIRY_MODE, OpCodeIndex::EXIT_PERIODIC_INQUIRY_MODE}, + {OpCode::CREATE_CONNECTION, OpCodeIndex::CREATE_CONNECTION}, + {OpCode::DISCONNECT, OpCodeIndex::DISCONNECT}, + {OpCode::ADD_SCO_CONNECTION, OpCodeIndex::ADD_SCO_CONNECTION}, + {OpCode::CREATE_CONNECTION_CANCEL, OpCodeIndex::CREATE_CONNECTION_CANCEL}, + {OpCode::ACCEPT_CONNECTION_REQUEST, OpCodeIndex::ACCEPT_CONNECTION_REQUEST}, + {OpCode::REJECT_CONNECTION_REQUEST, OpCodeIndex::REJECT_CONNECTION_REQUEST}, + {OpCode::LINK_KEY_REQUEST_REPLY, OpCodeIndex::LINK_KEY_REQUEST_REPLY}, + {OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, OpCodeIndex::LINK_KEY_REQUEST_NEGATIVE_REPLY}, + {OpCode::PIN_CODE_REQUEST_REPLY, OpCodeIndex::PIN_CODE_REQUEST_REPLY}, + {OpCode::PIN_CODE_REQUEST_NEGATIVE_REPLY, OpCodeIndex::PIN_CODE_REQUEST_NEGATIVE_REPLY}, + {OpCode::CHANGE_CONNECTION_PACKET_TYPE, OpCodeIndex::CHANGE_CONNECTION_PACKET_TYPE}, + {OpCode::AUTHENTICATION_REQUESTED, OpCodeIndex::AUTHENTICATION_REQUESTED}, + {OpCode::SET_CONNECTION_ENCRYPTION, OpCodeIndex::SET_CONNECTION_ENCRYPTION}, + {OpCode::CHANGE_CONNECTION_LINK_KEY, OpCodeIndex::CHANGE_CONNECTION_LINK_KEY}, + {OpCode::CENTRAL_LINK_KEY, OpCodeIndex::CENTRAL_LINK_KEY}, + {OpCode::REMOTE_NAME_REQUEST, OpCodeIndex::REMOTE_NAME_REQUEST}, + {OpCode::REMOTE_NAME_REQUEST_CANCEL, OpCodeIndex::REMOTE_NAME_REQUEST_CANCEL}, + {OpCode::READ_REMOTE_SUPPORTED_FEATURES, OpCodeIndex::READ_REMOTE_SUPPORTED_FEATURES}, + {OpCode::READ_REMOTE_EXTENDED_FEATURES, OpCodeIndex::READ_REMOTE_EXTENDED_FEATURES}, + {OpCode::READ_REMOTE_VERSION_INFORMATION, OpCodeIndex::READ_REMOTE_VERSION_INFORMATION}, + {OpCode::READ_CLOCK_OFFSET, OpCodeIndex::READ_CLOCK_OFFSET}, + {OpCode::READ_LMP_HANDLE, OpCodeIndex::READ_LMP_HANDLE}, + {OpCode::SETUP_SYNCHRONOUS_CONNECTION, OpCodeIndex::SETUP_SYNCHRONOUS_CONNECTION}, + {OpCode::ACCEPT_SYNCHRONOUS_CONNECTION, OpCodeIndex::ACCEPT_SYNCHRONOUS_CONNECTION}, + {OpCode::REJECT_SYNCHRONOUS_CONNECTION, OpCodeIndex::REJECT_SYNCHRONOUS_CONNECTION}, + {OpCode::IO_CAPABILITY_REQUEST_REPLY, OpCodeIndex::IO_CAPABILITY_REQUEST_REPLY}, + {OpCode::USER_CONFIRMATION_REQUEST_REPLY, OpCodeIndex::USER_CONFIRMATION_REQUEST_REPLY}, + {OpCode::USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY, + OpCodeIndex::USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY}, + {OpCode::USER_PASSKEY_REQUEST_REPLY, OpCodeIndex::USER_PASSKEY_REQUEST_REPLY}, + {OpCode::USER_PASSKEY_REQUEST_NEGATIVE_REPLY, + OpCodeIndex::USER_PASSKEY_REQUEST_NEGATIVE_REPLY}, + {OpCode::REMOTE_OOB_DATA_REQUEST_REPLY, OpCodeIndex::REMOTE_OOB_DATA_REQUEST_REPLY}, + {OpCode::REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY, + OpCodeIndex::REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY}, + {OpCode::IO_CAPABILITY_REQUEST_NEGATIVE_REPLY, + OpCodeIndex::IO_CAPABILITY_REQUEST_NEGATIVE_REPLY}, + {OpCode::ENHANCED_SETUP_SYNCHRONOUS_CONNECTION, + OpCodeIndex::ENHANCED_SETUP_SYNCHRONOUS_CONNECTION}, + {OpCode::ENHANCED_ACCEPT_SYNCHRONOUS_CONNECTION, + OpCodeIndex::ENHANCED_ACCEPT_SYNCHRONOUS_CONNECTION}, + {OpCode::TRUNCATED_PAGE, OpCodeIndex::TRUNCATED_PAGE}, + {OpCode::TRUNCATED_PAGE_CANCEL, OpCodeIndex::TRUNCATED_PAGE_CANCEL}, + {OpCode::SET_CONNECTIONLESS_PERIPHERAL_BROADCAST, + OpCodeIndex::SET_CONNECTIONLESS_PERIPHERAL_BROADCAST}, + {OpCode::SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_RECEIVE, + OpCodeIndex::SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_RECEIVE}, + {OpCode::START_SYNCHRONIZATION_TRAIN, OpCodeIndex::START_SYNCHRONIZATION_TRAIN}, + {OpCode::RECEIVE_SYNCHRONIZATION_TRAIN, OpCodeIndex::RECEIVE_SYNCHRONIZATION_TRAIN}, + {OpCode::REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY, + OpCodeIndex::REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY}, + + // LINK_POLICY + {OpCode::HOLD_MODE, OpCodeIndex::HOLD_MODE}, + {OpCode::SNIFF_MODE, OpCodeIndex::SNIFF_MODE}, + {OpCode::EXIT_SNIFF_MODE, OpCodeIndex::EXIT_SNIFF_MODE}, + {OpCode::QOS_SETUP, OpCodeIndex::QOS_SETUP}, + {OpCode::ROLE_DISCOVERY, OpCodeIndex::ROLE_DISCOVERY}, + {OpCode::SWITCH_ROLE, OpCodeIndex::SWITCH_ROLE}, + {OpCode::READ_LINK_POLICY_SETTINGS, OpCodeIndex::READ_LINK_POLICY_SETTINGS}, + {OpCode::WRITE_LINK_POLICY_SETTINGS, OpCodeIndex::WRITE_LINK_POLICY_SETTINGS}, + {OpCode::READ_DEFAULT_LINK_POLICY_SETTINGS, + OpCodeIndex::READ_DEFAULT_LINK_POLICY_SETTINGS}, + {OpCode::WRITE_DEFAULT_LINK_POLICY_SETTINGS, + OpCodeIndex::WRITE_DEFAULT_LINK_POLICY_SETTINGS}, + {OpCode::FLOW_SPECIFICATION, OpCodeIndex::FLOW_SPECIFICATION}, + {OpCode::SNIFF_SUBRATING, OpCodeIndex::SNIFF_SUBRATING}, + + // CONTROLLER_AND_BASEBAND + {OpCode::SET_EVENT_MASK, OpCodeIndex::SET_EVENT_MASK}, + {OpCode::RESET, OpCodeIndex::RESET}, + {OpCode::SET_EVENT_FILTER, OpCodeIndex::SET_EVENT_FILTER}, + {OpCode::FLUSH, OpCodeIndex::FLUSH}, + {OpCode::READ_PIN_TYPE, OpCodeIndex::READ_PIN_TYPE}, + {OpCode::WRITE_PIN_TYPE, OpCodeIndex::WRITE_PIN_TYPE}, + {OpCode::READ_STORED_LINK_KEY, OpCodeIndex::READ_STORED_LINK_KEY}, + {OpCode::WRITE_STORED_LINK_KEY, OpCodeIndex::WRITE_STORED_LINK_KEY}, + {OpCode::DELETE_STORED_LINK_KEY, OpCodeIndex::DELETE_STORED_LINK_KEY}, + {OpCode::WRITE_LOCAL_NAME, OpCodeIndex::WRITE_LOCAL_NAME}, + {OpCode::READ_LOCAL_NAME, OpCodeIndex::READ_LOCAL_NAME}, + {OpCode::READ_CONNECTION_ACCEPT_TIMEOUT, OpCodeIndex::READ_CONNECTION_ACCEPT_TIMEOUT}, + {OpCode::WRITE_CONNECTION_ACCEPT_TIMEOUT, OpCodeIndex::WRITE_CONNECTION_ACCEPT_TIMEOUT}, + {OpCode::READ_PAGE_TIMEOUT, OpCodeIndex::READ_PAGE_TIMEOUT}, + {OpCode::WRITE_PAGE_TIMEOUT, OpCodeIndex::WRITE_PAGE_TIMEOUT}, + {OpCode::READ_SCAN_ENABLE, OpCodeIndex::READ_SCAN_ENABLE}, + {OpCode::WRITE_SCAN_ENABLE, OpCodeIndex::WRITE_SCAN_ENABLE}, + {OpCode::READ_PAGE_SCAN_ACTIVITY, OpCodeIndex::READ_PAGE_SCAN_ACTIVITY}, + {OpCode::WRITE_PAGE_SCAN_ACTIVITY, OpCodeIndex::WRITE_PAGE_SCAN_ACTIVITY}, + {OpCode::READ_INQUIRY_SCAN_ACTIVITY, OpCodeIndex::READ_INQUIRY_SCAN_ACTIVITY}, + {OpCode::WRITE_INQUIRY_SCAN_ACTIVITY, OpCodeIndex::WRITE_INQUIRY_SCAN_ACTIVITY}, + {OpCode::READ_AUTHENTICATION_ENABLE, OpCodeIndex::READ_AUTHENTICATION_ENABLE}, + {OpCode::WRITE_AUTHENTICATION_ENABLE, OpCodeIndex::WRITE_AUTHENTICATION_ENABLE}, + {OpCode::READ_CLASS_OF_DEVICE, OpCodeIndex::READ_CLASS_OF_DEVICE}, + {OpCode::WRITE_CLASS_OF_DEVICE, OpCodeIndex::WRITE_CLASS_OF_DEVICE}, + {OpCode::READ_VOICE_SETTING, OpCodeIndex::READ_VOICE_SETTING}, + {OpCode::WRITE_VOICE_SETTING, OpCodeIndex::WRITE_VOICE_SETTING}, + {OpCode::READ_AUTOMATIC_FLUSH_TIMEOUT, OpCodeIndex::READ_AUTOMATIC_FLUSH_TIMEOUT}, + {OpCode::WRITE_AUTOMATIC_FLUSH_TIMEOUT, OpCodeIndex::WRITE_AUTOMATIC_FLUSH_TIMEOUT}, + {OpCode::READ_NUM_BROADCAST_RETRANSMITS, OpCodeIndex::READ_NUM_BROADCAST_RETRANSMITS}, + {OpCode::WRITE_NUM_BROADCAST_RETRANSMITS, OpCodeIndex::WRITE_NUM_BROADCAST_RETRANSMITS}, + {OpCode::READ_HOLD_MODE_ACTIVITY, OpCodeIndex::READ_HOLD_MODE_ACTIVITY}, + {OpCode::WRITE_HOLD_MODE_ACTIVITY, OpCodeIndex::WRITE_HOLD_MODE_ACTIVITY}, + {OpCode::READ_TRANSMIT_POWER_LEVEL, OpCodeIndex::READ_TRANSMIT_POWER_LEVEL}, + {OpCode::READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE, + OpCodeIndex::READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE}, + {OpCode::WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE, + OpCodeIndex::WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE}, + {OpCode::SET_CONTROLLER_TO_HOST_FLOW_CONTROL, + OpCodeIndex::SET_CONTROLLER_TO_HOST_FLOW_CONTROL}, + {OpCode::HOST_BUFFER_SIZE, OpCodeIndex::HOST_BUFFER_SIZE}, + {OpCode::HOST_NUMBER_OF_COMPLETED_PACKETS, OpCodeIndex::HOST_NUMBER_OF_COMPLETED_PACKETS}, + {OpCode::READ_LINK_SUPERVISION_TIMEOUT, OpCodeIndex::READ_LINK_SUPERVISION_TIMEOUT}, + {OpCode::WRITE_LINK_SUPERVISION_TIMEOUT, OpCodeIndex::WRITE_LINK_SUPERVISION_TIMEOUT}, + {OpCode::READ_NUMBER_OF_SUPPORTED_IAC, OpCodeIndex::READ_NUMBER_OF_SUPPORTED_IAC}, + {OpCode::READ_CURRENT_IAC_LAP, OpCodeIndex::READ_CURRENT_IAC_LAP}, + {OpCode::WRITE_CURRENT_IAC_LAP, OpCodeIndex::WRITE_CURRENT_IAC_LAP}, + {OpCode::SET_AFH_HOST_CHANNEL_CLASSIFICATION, + OpCodeIndex::SET_AFH_HOST_CHANNEL_CLASSIFICATION}, + {OpCode::READ_INQUIRY_SCAN_TYPE, OpCodeIndex::READ_INQUIRY_SCAN_TYPE}, + {OpCode::WRITE_INQUIRY_SCAN_TYPE, OpCodeIndex::WRITE_INQUIRY_SCAN_TYPE}, + {OpCode::READ_INQUIRY_MODE, OpCodeIndex::READ_INQUIRY_MODE}, + {OpCode::WRITE_INQUIRY_MODE, OpCodeIndex::WRITE_INQUIRY_MODE}, + {OpCode::READ_PAGE_SCAN_TYPE, OpCodeIndex::READ_PAGE_SCAN_TYPE}, + {OpCode::WRITE_PAGE_SCAN_TYPE, OpCodeIndex::WRITE_PAGE_SCAN_TYPE}, + {OpCode::READ_AFH_CHANNEL_ASSESSMENT_MODE, OpCodeIndex::READ_AFH_CHANNEL_ASSESSMENT_MODE}, + {OpCode::WRITE_AFH_CHANNEL_ASSESSMENT_MODE, + OpCodeIndex::WRITE_AFH_CHANNEL_ASSESSMENT_MODE}, + {OpCode::READ_EXTENDED_INQUIRY_RESPONSE, OpCodeIndex::READ_EXTENDED_INQUIRY_RESPONSE}, + {OpCode::WRITE_EXTENDED_INQUIRY_RESPONSE, OpCodeIndex::WRITE_EXTENDED_INQUIRY_RESPONSE}, + {OpCode::REFRESH_ENCRYPTION_KEY, OpCodeIndex::REFRESH_ENCRYPTION_KEY}, + {OpCode::READ_SIMPLE_PAIRING_MODE, OpCodeIndex::READ_SIMPLE_PAIRING_MODE}, + {OpCode::WRITE_SIMPLE_PAIRING_MODE, OpCodeIndex::WRITE_SIMPLE_PAIRING_MODE}, + {OpCode::READ_LOCAL_OOB_DATA, OpCodeIndex::READ_LOCAL_OOB_DATA}, + {OpCode::READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL, + OpCodeIndex::READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL}, + {OpCode::WRITE_INQUIRY_TRANSMIT_POWER_LEVEL, + OpCodeIndex::WRITE_INQUIRY_TRANSMIT_POWER_LEVEL}, + {OpCode::READ_DEFAULT_ERRONEOUS_DATA_REPORTING, + OpCodeIndex::READ_DEFAULT_ERRONEOUS_DATA_REPORTING}, + {OpCode::WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING, + OpCodeIndex::WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING}, + {OpCode::ENHANCED_FLUSH, OpCodeIndex::ENHANCED_FLUSH}, + {OpCode::SEND_KEYPRESS_NOTIFICATION, OpCodeIndex::SEND_KEYPRESS_NOTIFICATION}, + {OpCode::SET_EVENT_MASK_PAGE_2, OpCodeIndex::SET_EVENT_MASK_PAGE_2}, + {OpCode::READ_FLOW_CONTROL_MODE, OpCodeIndex::READ_FLOW_CONTROL_MODE}, + {OpCode::WRITE_FLOW_CONTROL_MODE, OpCodeIndex::WRITE_FLOW_CONTROL_MODE}, + {OpCode::READ_ENHANCED_TRANSMIT_POWER_LEVEL, + OpCodeIndex::READ_ENHANCED_TRANSMIT_POWER_LEVEL}, + {OpCode::READ_LE_HOST_SUPPORT, OpCodeIndex::READ_LE_HOST_SUPPORT}, + {OpCode::WRITE_LE_HOST_SUPPORT, OpCodeIndex::WRITE_LE_HOST_SUPPORT}, + {OpCode::SET_MWS_CHANNEL_PARAMETERS, OpCodeIndex::SET_MWS_CHANNEL_PARAMETERS}, + {OpCode::SET_EXTERNAL_FRAME_CONFIGURATION, OpCodeIndex::SET_EXTERNAL_FRAME_CONFIGURATION}, + {OpCode::SET_MWS_SIGNALING, OpCodeIndex::SET_MWS_SIGNALING}, + {OpCode::SET_MWS_TRANSPORT_LAYER, OpCodeIndex::SET_MWS_TRANSPORT_LAYER}, + {OpCode::SET_MWS_SCAN_FREQUENCY_TABLE, OpCodeIndex::SET_MWS_SCAN_FREQUENCY_TABLE}, + {OpCode::SET_MWS_PATTERN_CONFIGURATION, OpCodeIndex::SET_MWS_PATTERN_CONFIGURATION}, + {OpCode::SET_RESERVED_LT_ADDR, OpCodeIndex::SET_RESERVED_LT_ADDR}, + {OpCode::DELETE_RESERVED_LT_ADDR, OpCodeIndex::DELETE_RESERVED_LT_ADDR}, + {OpCode::SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_DATA, + OpCodeIndex::SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_DATA}, + {OpCode::READ_SYNCHRONIZATION_TRAIN_PARAMETERS, + OpCodeIndex::READ_SYNCHRONIZATION_TRAIN_PARAMETERS}, + {OpCode::WRITE_SYNCHRONIZATION_TRAIN_PARAMETERS, + OpCodeIndex::WRITE_SYNCHRONIZATION_TRAIN_PARAMETERS}, + {OpCode::READ_SECURE_CONNECTIONS_HOST_SUPPORT, + OpCodeIndex::READ_SECURE_CONNECTIONS_HOST_SUPPORT}, + {OpCode::WRITE_SECURE_CONNECTIONS_HOST_SUPPORT, + OpCodeIndex::WRITE_SECURE_CONNECTIONS_HOST_SUPPORT}, + {OpCode::READ_AUTHENTICATED_PAYLOAD_TIMEOUT, + OpCodeIndex::READ_AUTHENTICATED_PAYLOAD_TIMEOUT}, + {OpCode::WRITE_AUTHENTICATED_PAYLOAD_TIMEOUT, + OpCodeIndex::WRITE_AUTHENTICATED_PAYLOAD_TIMEOUT}, + {OpCode::READ_LOCAL_OOB_EXTENDED_DATA, OpCodeIndex::READ_LOCAL_OOB_EXTENDED_DATA}, + {OpCode::READ_EXTENDED_PAGE_TIMEOUT, OpCodeIndex::READ_EXTENDED_PAGE_TIMEOUT}, + {OpCode::WRITE_EXTENDED_PAGE_TIMEOUT, OpCodeIndex::WRITE_EXTENDED_PAGE_TIMEOUT}, + {OpCode::READ_EXTENDED_INQUIRY_LENGTH, OpCodeIndex::READ_EXTENDED_INQUIRY_LENGTH}, + {OpCode::WRITE_EXTENDED_INQUIRY_LENGTH, OpCodeIndex::WRITE_EXTENDED_INQUIRY_LENGTH}, + {OpCode::SET_ECOSYSTEM_BASE_INTERVAL, OpCodeIndex::SET_ECOSYSTEM_BASE_INTERVAL}, + {OpCode::CONFIGURE_DATA_PATH, OpCodeIndex::CONFIGURE_DATA_PATH}, + {OpCode::SET_MIN_ENCRYPTION_KEY_SIZE, OpCodeIndex::SET_MIN_ENCRYPTION_KEY_SIZE}, + + // INFORMATIONAL_PARAMETERS + {OpCode::READ_LOCAL_VERSION_INFORMATION, OpCodeIndex::READ_LOCAL_VERSION_INFORMATION}, + {OpCode::READ_LOCAL_SUPPORTED_FEATURES, OpCodeIndex::READ_LOCAL_SUPPORTED_FEATURES}, + {OpCode::READ_LOCAL_EXTENDED_FEATURES, OpCodeIndex::READ_LOCAL_EXTENDED_FEATURES}, + {OpCode::READ_BUFFER_SIZE, OpCodeIndex::READ_BUFFER_SIZE}, + {OpCode::READ_BD_ADDR, OpCodeIndex::READ_BD_ADDR}, + {OpCode::READ_DATA_BLOCK_SIZE, OpCodeIndex::READ_DATA_BLOCK_SIZE}, + {OpCode::READ_LOCAL_SUPPORTED_CODECS_V1, OpCodeIndex::READ_LOCAL_SUPPORTED_CODECS_V1}, + {OpCode::READ_LOCAL_SIMPLE_PAIRING_OPTIONS, + OpCodeIndex::READ_LOCAL_SIMPLE_PAIRING_OPTIONS}, + {OpCode::READ_LOCAL_SUPPORTED_CODECS_V2, OpCodeIndex::READ_LOCAL_SUPPORTED_CODECS_V2}, + {OpCode::READ_LOCAL_SUPPORTED_CODEC_CAPABILITIES, + OpCodeIndex::READ_LOCAL_SUPPORTED_CODEC_CAPABILITIES}, + {OpCode::READ_LOCAL_SUPPORTED_CONTROLLER_DELAY, + OpCodeIndex::READ_LOCAL_SUPPORTED_CONTROLLER_DELAY}, + + // STATUS_PARAMETERS + {OpCode::READ_FAILED_CONTACT_COUNTER, OpCodeIndex::READ_FAILED_CONTACT_COUNTER}, + {OpCode::RESET_FAILED_CONTACT_COUNTER, OpCodeIndex::RESET_FAILED_CONTACT_COUNTER}, + {OpCode::READ_LINK_QUALITY, OpCodeIndex::READ_LINK_QUALITY}, + {OpCode::READ_RSSI, OpCodeIndex::READ_RSSI}, + {OpCode::READ_AFH_CHANNEL_MAP, OpCodeIndex::READ_AFH_CHANNEL_MAP}, + {OpCode::READ_CLOCK, OpCodeIndex::READ_CLOCK}, + {OpCode::READ_ENCRYPTION_KEY_SIZE, OpCodeIndex::READ_ENCRYPTION_KEY_SIZE}, + {OpCode::GET_MWS_TRANSPORT_LAYER_CONFIGURATION, + OpCodeIndex::GET_MWS_TRANSPORT_LAYER_CONFIGURATION}, + {OpCode::SET_TRIGGERED_CLOCK_CAPTURE, OpCodeIndex::SET_TRIGGERED_CLOCK_CAPTURE}, + + // TESTING + {OpCode::READ_LOOPBACK_MODE, OpCodeIndex::READ_LOOPBACK_MODE}, + {OpCode::WRITE_LOOPBACK_MODE, OpCodeIndex::WRITE_LOOPBACK_MODE}, + {OpCode::ENABLE_IMPLEMENTATION_UNDER_TEST_MODE, + OpCodeIndex::ENABLE_IMPLEMENTATION_UNDER_TEST_MODE}, + {OpCode::WRITE_SIMPLE_PAIRING_DEBUG_MODE, OpCodeIndex::WRITE_SIMPLE_PAIRING_DEBUG_MODE}, + {OpCode::WRITE_SECURE_CONNECTIONS_TEST_MODE, + OpCodeIndex::WRITE_SECURE_CONNECTIONS_TEST_MODE}, + + // LE_CONTROLLER + {OpCode::LE_SET_EVENT_MASK, OpCodeIndex::LE_SET_EVENT_MASK}, + {OpCode::LE_READ_BUFFER_SIZE_V1, OpCodeIndex::LE_READ_BUFFER_SIZE_V1}, + {OpCode::LE_READ_LOCAL_SUPPORTED_FEATURES_PAGE_0, + OpCodeIndex::LE_READ_LOCAL_SUPPORTED_FEATURES_PAGE_0}, + {OpCode::LE_SET_RANDOM_ADDRESS, OpCodeIndex::LE_SET_RANDOM_ADDRESS}, + {OpCode::LE_SET_ADVERTISING_PARAMETERS, OpCodeIndex::LE_SET_ADVERTISING_PARAMETERS}, + {OpCode::LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER, + OpCodeIndex::LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER}, + {OpCode::LE_SET_ADVERTISING_DATA, OpCodeIndex::LE_SET_ADVERTISING_DATA}, + {OpCode::LE_SET_SCAN_RESPONSE_DATA, OpCodeIndex::LE_SET_SCAN_RESPONSE_DATA}, + {OpCode::LE_SET_ADVERTISING_ENABLE, OpCodeIndex::LE_SET_ADVERTISING_ENABLE}, + {OpCode::LE_SET_SCAN_PARAMETERS, OpCodeIndex::LE_SET_SCAN_PARAMETERS}, + {OpCode::LE_SET_SCAN_ENABLE, OpCodeIndex::LE_SET_SCAN_ENABLE}, + {OpCode::LE_CREATE_CONNECTION, OpCodeIndex::LE_CREATE_CONNECTION}, + {OpCode::LE_CREATE_CONNECTION_CANCEL, OpCodeIndex::LE_CREATE_CONNECTION_CANCEL}, + {OpCode::LE_READ_FILTER_ACCEPT_LIST_SIZE, OpCodeIndex::LE_READ_FILTER_ACCEPT_LIST_SIZE}, + {OpCode::LE_CLEAR_FILTER_ACCEPT_LIST, OpCodeIndex::LE_CLEAR_FILTER_ACCEPT_LIST}, + {OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST, + OpCodeIndex::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST}, + {OpCode::LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST, + OpCodeIndex::LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST}, + {OpCode::LE_CONNECTION_UPDATE, OpCodeIndex::LE_CONNECTION_UPDATE}, + {OpCode::LE_SET_HOST_CHANNEL_CLASSIFICATION, + OpCodeIndex::LE_SET_HOST_CHANNEL_CLASSIFICATION}, + {OpCode::LE_READ_CHANNEL_MAP, OpCodeIndex::LE_READ_CHANNEL_MAP}, + {OpCode::LE_READ_REMOTE_FEATURES_PAGE_0, OpCodeIndex::LE_READ_REMOTE_FEATURES_PAGE_0}, + {OpCode::LE_ENCRYPT, OpCodeIndex::LE_ENCRYPT}, + {OpCode::LE_RAND, OpCodeIndex::LE_RAND}, + {OpCode::LE_START_ENCRYPTION, OpCodeIndex::LE_START_ENCRYPTION}, + {OpCode::LE_LONG_TERM_KEY_REQUEST_REPLY, OpCodeIndex::LE_LONG_TERM_KEY_REQUEST_REPLY}, + {OpCode::LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY, + OpCodeIndex::LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY}, + {OpCode::LE_READ_SUPPORTED_STATES, OpCodeIndex::LE_READ_SUPPORTED_STATES}, + {OpCode::LE_RECEIVER_TEST_V1, OpCodeIndex::LE_RECEIVER_TEST_V1}, + {OpCode::LE_TRANSMITTER_TEST_V1, OpCodeIndex::LE_TRANSMITTER_TEST_V1}, + {OpCode::LE_TEST_END, OpCodeIndex::LE_TEST_END}, + {OpCode::LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY, + OpCodeIndex::LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY}, + {OpCode::LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY, + OpCodeIndex::LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY}, + {OpCode::LE_SET_DATA_LENGTH, OpCodeIndex::LE_SET_DATA_LENGTH}, + {OpCode::LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH, + OpCodeIndex::LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH}, + {OpCode::LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH, + OpCodeIndex::LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH}, + {OpCode::LE_READ_LOCAL_P_256_PUBLIC_KEY, OpCodeIndex::LE_READ_LOCAL_P_256_PUBLIC_KEY}, + {OpCode::LE_GENERATE_DHKEY_V1, OpCodeIndex::LE_GENERATE_DHKEY_V1}, + {OpCode::LE_ADD_DEVICE_TO_RESOLVING_LIST, OpCodeIndex::LE_ADD_DEVICE_TO_RESOLVING_LIST}, + {OpCode::LE_REMOVE_DEVICE_FROM_RESOLVING_LIST, + OpCodeIndex::LE_REMOVE_DEVICE_FROM_RESOLVING_LIST}, + {OpCode::LE_CLEAR_RESOLVING_LIST, OpCodeIndex::LE_CLEAR_RESOLVING_LIST}, + {OpCode::LE_READ_RESOLVING_LIST_SIZE, OpCodeIndex::LE_READ_RESOLVING_LIST_SIZE}, + {OpCode::LE_READ_PEER_RESOLVABLE_ADDRESS, OpCodeIndex::LE_READ_PEER_RESOLVABLE_ADDRESS}, + {OpCode::LE_READ_LOCAL_RESOLVABLE_ADDRESS, OpCodeIndex::LE_READ_LOCAL_RESOLVABLE_ADDRESS}, + {OpCode::LE_SET_ADDRESS_RESOLUTION_ENABLE, OpCodeIndex::LE_SET_ADDRESS_RESOLUTION_ENABLE}, + {OpCode::LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT, + OpCodeIndex::LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT}, + {OpCode::LE_READ_MAXIMUM_DATA_LENGTH, OpCodeIndex::LE_READ_MAXIMUM_DATA_LENGTH}, + {OpCode::LE_READ_PHY, OpCodeIndex::LE_READ_PHY}, + {OpCode::LE_SET_DEFAULT_PHY, OpCodeIndex::LE_SET_DEFAULT_PHY}, + {OpCode::LE_SET_PHY, OpCodeIndex::LE_SET_PHY}, + {OpCode::LE_RECEIVER_TEST_V2, OpCodeIndex::LE_RECEIVER_TEST_V2}, + {OpCode::LE_TRANSMITTER_TEST_V2, OpCodeIndex::LE_TRANSMITTER_TEST_V2}, + {OpCode::LE_SET_ADVERTISING_SET_RANDOM_ADDRESS, + OpCodeIndex::LE_SET_ADVERTISING_SET_RANDOM_ADDRESS}, + {OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1, + OpCodeIndex::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1}, + {OpCode::LE_SET_EXTENDED_ADVERTISING_DATA, OpCodeIndex::LE_SET_EXTENDED_ADVERTISING_DATA}, + {OpCode::LE_SET_EXTENDED_SCAN_RESPONSE_DATA, + OpCodeIndex::LE_SET_EXTENDED_SCAN_RESPONSE_DATA}, + {OpCode::LE_SET_EXTENDED_ADVERTISING_ENABLE, + OpCodeIndex::LE_SET_EXTENDED_ADVERTISING_ENABLE}, + {OpCode::LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH, + OpCodeIndex::LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH}, + {OpCode::LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS, + OpCodeIndex::LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS}, + {OpCode::LE_REMOVE_ADVERTISING_SET, OpCodeIndex::LE_REMOVE_ADVERTISING_SET}, + {OpCode::LE_CLEAR_ADVERTISING_SETS, OpCodeIndex::LE_CLEAR_ADVERTISING_SETS}, + {OpCode::LE_SET_PERIODIC_ADVERTISING_PARAMETERS_V1, + OpCodeIndex::LE_SET_PERIODIC_ADVERTISING_PARAMETERS_V1}, + {OpCode::LE_SET_PERIODIC_ADVERTISING_DATA, OpCodeIndex::LE_SET_PERIODIC_ADVERTISING_DATA}, + {OpCode::LE_SET_PERIODIC_ADVERTISING_ENABLE, + OpCodeIndex::LE_SET_PERIODIC_ADVERTISING_ENABLE}, + {OpCode::LE_SET_EXTENDED_SCAN_PARAMETERS, OpCodeIndex::LE_SET_EXTENDED_SCAN_PARAMETERS}, + {OpCode::LE_SET_EXTENDED_SCAN_ENABLE, OpCodeIndex::LE_SET_EXTENDED_SCAN_ENABLE}, + {OpCode::LE_EXTENDED_CREATE_CONNECTION_V1, OpCodeIndex::LE_EXTENDED_CREATE_CONNECTION_V1}, + {OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC, + OpCodeIndex::LE_PERIODIC_ADVERTISING_CREATE_SYNC}, + {OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL, + OpCodeIndex::LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL}, + {OpCode::LE_PERIODIC_ADVERTISING_TERMINATE_SYNC, + OpCodeIndex::LE_PERIODIC_ADVERTISING_TERMINATE_SYNC}, + {OpCode::LE_ADD_DEVICE_TO_PERIODIC_ADVERTISER_LIST, + OpCodeIndex::LE_ADD_DEVICE_TO_PERIODIC_ADVERTISER_LIST}, + {OpCode::LE_REMOVE_DEVICE_FROM_PERIODIC_ADVERTISER_LIST, + OpCodeIndex::LE_REMOVE_DEVICE_FROM_PERIODIC_ADVERTISER_LIST}, + {OpCode::LE_CLEAR_PERIODIC_ADVERTISER_LIST, + OpCodeIndex::LE_CLEAR_PERIODIC_ADVERTISER_LIST}, + {OpCode::LE_READ_PERIODIC_ADVERTISER_LIST_SIZE, + OpCodeIndex::LE_READ_PERIODIC_ADVERTISER_LIST_SIZE}, + {OpCode::LE_READ_TRANSMIT_POWER, OpCodeIndex::LE_READ_TRANSMIT_POWER}, + {OpCode::LE_READ_RF_PATH_COMPENSATION_POWER, + OpCodeIndex::LE_READ_RF_PATH_COMPENSATION_POWER}, + {OpCode::LE_WRITE_RF_PATH_COMPENSATION_POWER, + OpCodeIndex::LE_WRITE_RF_PATH_COMPENSATION_POWER}, + {OpCode::LE_SET_PRIVACY_MODE, OpCodeIndex::LE_SET_PRIVACY_MODE}, + {OpCode::LE_RECEIVER_TEST_V3, OpCodeIndex::LE_RECEIVER_TEST_V3}, + {OpCode::LE_TRANSMITTER_TEST_V3, OpCodeIndex::LE_TRANSMITTER_TEST_V3}, + {OpCode::LE_SET_CONNECTIONLESS_CTE_TRANSMIT_PARAMETERS, + OpCodeIndex::LE_SET_CONNECTIONLESS_CTE_TRANSMIT_PARAMETERS}, + {OpCode::LE_SET_CONNECTIONLESS_CTE_TRANSMIT_ENABLE, + OpCodeIndex::LE_SET_CONNECTIONLESS_CTE_TRANSMIT_ENABLE}, + {OpCode::LE_SET_CONNECTIONLESS_IQ_SAMPLING_ENABLE, + OpCodeIndex::LE_SET_CONNECTIONLESS_IQ_SAMPLING_ENABLE}, + {OpCode::LE_SET_CONNECTION_CTE_RECEIVE_PARAMETERS, + OpCodeIndex::LE_SET_CONNECTION_CTE_RECEIVE_PARAMETERS}, + {OpCode::LE_SET_CONNECTION_CTE_TRANSMIT_PARAMETERS, + OpCodeIndex::LE_SET_CONNECTION_CTE_TRANSMIT_PARAMETERS}, + {OpCode::LE_CONNECTION_CTE_REQUEST_ENABLE, OpCodeIndex::LE_CONNECTION_CTE_REQUEST_ENABLE}, + {OpCode::LE_CONNECTION_CTE_RESPONSE_ENABLE, + OpCodeIndex::LE_CONNECTION_CTE_RESPONSE_ENABLE}, + {OpCode::LE_READ_ANTENNA_INFORMATION, OpCodeIndex::LE_READ_ANTENNA_INFORMATION}, + {OpCode::LE_SET_PERIODIC_ADVERTISING_RECEIVE_ENABLE, + OpCodeIndex::LE_SET_PERIODIC_ADVERTISING_RECEIVE_ENABLE}, + {OpCode::LE_PERIODIC_ADVERTISING_SYNC_TRANSFER, + OpCodeIndex::LE_PERIODIC_ADVERTISING_SYNC_TRANSFER}, + {OpCode::LE_PERIODIC_ADVERTISING_SET_INFO_TRANSFER, + OpCodeIndex::LE_PERIODIC_ADVERTISING_SET_INFO_TRANSFER}, + {OpCode::LE_SET_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS, + OpCodeIndex::LE_SET_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS}, + {OpCode::LE_SET_DEFAULT_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS, + OpCodeIndex::LE_SET_DEFAULT_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS}, + {OpCode::LE_GENERATE_DHKEY_V2, OpCodeIndex::LE_GENERATE_DHKEY_V2}, + {OpCode::LE_MODIFY_SLEEP_CLOCK_ACCURACY, OpCodeIndex::LE_MODIFY_SLEEP_CLOCK_ACCURACY}, + {OpCode::LE_READ_BUFFER_SIZE_V2, OpCodeIndex::LE_READ_BUFFER_SIZE_V2}, + {OpCode::LE_READ_ISO_TX_SYNC, OpCodeIndex::LE_READ_ISO_TX_SYNC}, + {OpCode::LE_SET_CIG_PARAMETERS, OpCodeIndex::LE_SET_CIG_PARAMETERS}, + {OpCode::LE_SET_CIG_PARAMETERS_TEST, OpCodeIndex::LE_SET_CIG_PARAMETERS_TEST}, + {OpCode::LE_CREATE_CIS, OpCodeIndex::LE_CREATE_CIS}, + {OpCode::LE_REMOVE_CIG, OpCodeIndex::LE_REMOVE_CIG}, + {OpCode::LE_ACCEPT_CIS_REQUEST, OpCodeIndex::LE_ACCEPT_CIS_REQUEST}, + {OpCode::LE_REJECT_CIS_REQUEST, OpCodeIndex::LE_REJECT_CIS_REQUEST}, + {OpCode::LE_CREATE_BIG, OpCodeIndex::LE_CREATE_BIG}, + {OpCode::LE_CREATE_BIG_TEST, OpCodeIndex::LE_CREATE_BIG_TEST}, + {OpCode::LE_TERMINATE_BIG, OpCodeIndex::LE_TERMINATE_BIG}, + {OpCode::LE_BIG_CREATE_SYNC, OpCodeIndex::LE_BIG_CREATE_SYNC}, + {OpCode::LE_BIG_TERMINATE_SYNC, OpCodeIndex::LE_BIG_TERMINATE_SYNC}, + {OpCode::LE_REQUEST_PEER_SCA, OpCodeIndex::LE_REQUEST_PEER_SCA}, + {OpCode::LE_SETUP_ISO_DATA_PATH, OpCodeIndex::LE_SETUP_ISO_DATA_PATH}, + {OpCode::LE_REMOVE_ISO_DATA_PATH, OpCodeIndex::LE_REMOVE_ISO_DATA_PATH}, + {OpCode::LE_ISO_TRANSMIT_TEST, OpCodeIndex::LE_ISO_TRANSMIT_TEST}, + {OpCode::LE_ISO_RECEIVE_TEST, OpCodeIndex::LE_ISO_RECEIVE_TEST}, + {OpCode::LE_ISO_READ_TEST_COUNTERS, OpCodeIndex::LE_ISO_READ_TEST_COUNTERS}, + {OpCode::LE_ISO_TEST_END, OpCodeIndex::LE_ISO_TEST_END}, + {OpCode::LE_SET_HOST_FEATURE_V1, OpCodeIndex::LE_SET_HOST_FEATURE_V1}, + {OpCode::LE_READ_ISO_LINK_QUALITY, OpCodeIndex::LE_READ_ISO_LINK_QUALITY}, + {OpCode::LE_ENHANCED_READ_TRANSMIT_POWER_LEVEL, + OpCodeIndex::LE_ENHANCED_READ_TRANSMIT_POWER_LEVEL}, + {OpCode::LE_READ_REMOTE_TRANSMIT_POWER_LEVEL, + OpCodeIndex::LE_READ_REMOTE_TRANSMIT_POWER_LEVEL}, + {OpCode::LE_SET_PATH_LOSS_REPORTING_PARAMETERS, + OpCodeIndex::LE_SET_PATH_LOSS_REPORTING_PARAMETERS}, + {OpCode::LE_SET_PATH_LOSS_REPORTING_ENABLE, + OpCodeIndex::LE_SET_PATH_LOSS_REPORTING_ENABLE}, + {OpCode::LE_SET_TRANSMIT_POWER_REPORTING_ENABLE, + OpCodeIndex::LE_SET_TRANSMIT_POWER_REPORTING_ENABLE}, + {OpCode::LE_TRANSMITTER_TEST_V4, OpCodeIndex::LE_TRANSMITTER_TEST_V4}, + {OpCode::LE_SET_DATA_RELATED_ADDRESS_CHANGES, + OpCodeIndex::LE_SET_DATA_RELATED_ADDRESS_CHANGES}, + {OpCode::LE_SET_DEFAULT_SUBRATE, OpCodeIndex::LE_SET_DEFAULT_SUBRATE}, + {OpCode::LE_SUBRATE_REQUEST, OpCodeIndex::LE_SUBRATE_REQUEST}, + {OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V2, + OpCodeIndex::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V2}, + {OpCode::LE_SET_DECISION_DATA, OpCodeIndex::LE_SET_DECISION_DATA}, + {OpCode::LE_SET_DECISION_INSTRUCTIONS, OpCodeIndex::LE_SET_DECISION_INSTRUCTIONS}, + {OpCode::LE_SET_PERIODIC_ADVERTISING_SUBEVENT_DATA, + OpCodeIndex::LE_SET_PERIODIC_ADVERTISING_SUBEVENT_DATA}, + {OpCode::LE_SET_PERIODIC_ADVERTISING_RESPONSE_DATA, + OpCodeIndex::LE_SET_PERIODIC_ADVERTISING_RESPONSE_DATA}, + {OpCode::LE_SET_PERIODIC_SYNC_SUBEVENT, OpCodeIndex::LE_SET_PERIODIC_SYNC_SUBEVENT}, + {OpCode::LE_EXTENDED_CREATE_CONNECTION_V2, OpCodeIndex::LE_EXTENDED_CREATE_CONNECTION_V2}, + {OpCode::LE_SET_PERIODIC_ADVERTISING_PARAMETERS_V2, + OpCodeIndex::LE_SET_PERIODIC_ADVERTISING_PARAMETERS_V2}, + {OpCode::LE_READ_ALL_LOCAL_SUPPORTED_FEATURES, + OpCodeIndex::LE_READ_ALL_LOCAL_SUPPORTED_FEATURES}, + {OpCode::LE_READ_ALL_REMOTE_FEATURES, OpCodeIndex::LE_READ_ALL_REMOTE_FEATURES}, + {OpCode::LE_CS_READ_LOCAL_SUPPORTED_CAPABILITIES, + OpCodeIndex::LE_CS_READ_LOCAL_SUPPORTED_CAPABILITIES}, + {OpCode::LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES, + OpCodeIndex::LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES}, + {OpCode::LE_CS_WRITE_CACHED_REMOTE_SUPPORTED_CAPABILITIES, + OpCodeIndex::LE_CS_WRITE_CACHED_REMOTE_SUPPORTED_CAPABILITIES}, + {OpCode::LE_CS_SECURITY_ENABLE, OpCodeIndex::LE_CS_SECURITY_ENABLE}, + {OpCode::LE_CS_SET_DEFAULT_SETTINGS, OpCodeIndex::LE_CS_SET_DEFAULT_SETTINGS}, + {OpCode::LE_CS_READ_REMOTE_FAE_TABLE, OpCodeIndex::LE_CS_READ_REMOTE_FAE_TABLE}, + {OpCode::LE_CS_WRITE_CACHED_REMOTE_FAE_TABLE, + OpCodeIndex::LE_CS_WRITE_CACHED_REMOTE_FAE_TABLE}, + {OpCode::LE_CS_CREATE_CONFIG, OpCodeIndex::LE_CS_CREATE_CONFIG}, + {OpCode::LE_CS_REMOVE_CONFIG, OpCodeIndex::LE_CS_REMOVE_CONFIG}, + {OpCode::LE_CS_SET_CHANNEL_CLASSIFICATION, OpCodeIndex::LE_CS_SET_CHANNEL_CLASSIFICATION}, + {OpCode::LE_CS_SET_PROCEDURE_PARAMETERS, OpCodeIndex::LE_CS_SET_PROCEDURE_PARAMETERS}, + {OpCode::LE_CS_PROCEDURE_ENABLE, OpCodeIndex::LE_CS_PROCEDURE_ENABLE}, + {OpCode::LE_CS_TEST, OpCodeIndex::LE_CS_TEST}, + {OpCode::LE_CS_TEST_END, OpCodeIndex::LE_CS_TEST_END}, + {OpCode::LE_ADD_DEVICE_TO_MONITORED_ADVERTISERS_LIST, + OpCodeIndex::LE_ADD_DEVICE_TO_MONITORED_ADVERTISERS_LIST}, + {OpCode::LE_REMOVE_DEVICE_FROM_MONITORED_ADVERTISERS_LIST, + OpCodeIndex::LE_REMOVE_DEVICE_FROM_MONITORED_ADVERTISERS_LIST}, + {OpCode::LE_CLEAR_MONITORED_ADVERTISERS_LIST, + OpCodeIndex::LE_CLEAR_MONITORED_ADVERTISERS_LIST}, + {OpCode::LE_READ_MONITORED_ADVERTISERS_LIST_SIZE, + OpCodeIndex::LE_READ_MONITORED_ADVERTISERS_LIST_SIZE}, + {OpCode::LE_ENABLE_MONITORING_ADVERTISERS, OpCodeIndex::LE_ENABLE_MONITORING_ADVERTISERS}, + {OpCode::LE_FRAME_SPACE_UPDATE, OpCodeIndex::LE_FRAME_SPACE_UPDATE}, + }; + return op_code_to_index; +} + +const std::unordered_map& +DualModeController::GetHciCommandHandlers() { + // This local static map will be constructed on the first call to GetHciCommandHandlers() + // and correctly destructed when the program exits (after all other static objects + // that depend on it are conceptually gone, because it's only destroyed when it goes + // out of scope at program termination). + static const std::unordered_map handlers = { + // LINK_CONTROL + {OpCode::INQUIRY, &DualModeController::Inquiry}, + {OpCode::INQUIRY_CANCEL, &DualModeController::InquiryCancel}, + //{OpCode::PERIODIC_INQUIRY_MODE, + //&DualModeController::PeriodicInquiryMode}, + //{OpCode::EXIT_PERIODIC_INQUIRY_MODE, + //&DualModeController::ExitPeriodicInquiryMode}, + {OpCode::CREATE_CONNECTION, &DualModeController::CreateConnection}, + {OpCode::DISCONNECT, &DualModeController::Disconnect}, + {OpCode::ADD_SCO_CONNECTION, &DualModeController::AddScoConnection}, + {OpCode::CREATE_CONNECTION_CANCEL, &DualModeController::CreateConnectionCancel}, + {OpCode::ACCEPT_CONNECTION_REQUEST, &DualModeController::AcceptConnectionRequest}, + {OpCode::REJECT_CONNECTION_REQUEST, &DualModeController::RejectConnectionRequest}, + {OpCode::LINK_KEY_REQUEST_REPLY, &DualModeController::ForwardToLm}, + {OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, &DualModeController::ForwardToLm}, + {OpCode::PIN_CODE_REQUEST_REPLY, &DualModeController::ForwardToLm}, + {OpCode::PIN_CODE_REQUEST_NEGATIVE_REPLY, &DualModeController::ForwardToLm}, + {OpCode::CHANGE_CONNECTION_PACKET_TYPE, &DualModeController::ChangeConnectionPacketType}, + {OpCode::AUTHENTICATION_REQUESTED, &DualModeController::ForwardToLm}, + {OpCode::SET_CONNECTION_ENCRYPTION, &DualModeController::ForwardToLm}, + {OpCode::CHANGE_CONNECTION_LINK_KEY, &DualModeController::ChangeConnectionLinkKey}, + {OpCode::CENTRAL_LINK_KEY, &DualModeController::CentralLinkKey}, + {OpCode::REMOTE_NAME_REQUEST, &DualModeController::RemoteNameRequest}, + //{OpCode::REMOTE_NAME_REQUEST_CANCEL, + //&DualModeController::RemoteNameRequestCancel}, + {OpCode::READ_REMOTE_SUPPORTED_FEATURES, + &DualModeController::ReadRemoteSupportedFeatures}, + {OpCode::READ_REMOTE_EXTENDED_FEATURES, &DualModeController::ReadRemoteExtendedFeatures}, + {OpCode::READ_REMOTE_VERSION_INFORMATION, + &DualModeController::ReadRemoteVersionInformation}, + {OpCode::READ_CLOCK_OFFSET, &DualModeController::ReadClockOffset}, + //{OpCode::READ_LMP_HANDLE, &DualModeController::ReadLmpHandle}, + {OpCode::SETUP_SYNCHRONOUS_CONNECTION, &DualModeController::SetupSynchronousConnection}, + {OpCode::ACCEPT_SYNCHRONOUS_CONNECTION, &DualModeController::AcceptSynchronousConnection}, + {OpCode::REJECT_SYNCHRONOUS_CONNECTION, &DualModeController::RejectSynchronousConnection}, + {OpCode::IO_CAPABILITY_REQUEST_REPLY, &DualModeController::ForwardToLm}, + {OpCode::USER_CONFIRMATION_REQUEST_REPLY, &DualModeController::ForwardToLm}, + {OpCode::USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY, &DualModeController::ForwardToLm}, + {OpCode::USER_PASSKEY_REQUEST_REPLY, &DualModeController::ForwardToLm}, + {OpCode::USER_PASSKEY_REQUEST_NEGATIVE_REPLY, &DualModeController::ForwardToLm}, + {OpCode::REMOTE_OOB_DATA_REQUEST_REPLY, &DualModeController::ForwardToLm}, + {OpCode::REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY, &DualModeController::ForwardToLm}, + {OpCode::IO_CAPABILITY_REQUEST_NEGATIVE_REPLY, &DualModeController::ForwardToLm}, + {OpCode::ENHANCED_SETUP_SYNCHRONOUS_CONNECTION, + &DualModeController::EnhancedSetupSynchronousConnection}, + {OpCode::ENHANCED_ACCEPT_SYNCHRONOUS_CONNECTION, + &DualModeController::EnhancedAcceptSynchronousConnection}, + //{OpCode::TRUNCATED_PAGE, &DualModeController::TruncatedPage}, + //{OpCode::TRUNCATED_PAGE_CANCEL, + //&DualModeController::TruncatedPageCancel}, + //{OpCode::SET_CONNECTIONLESS_PERIPHERAL_BROADCAST, + //&DualModeController::SetConnectionlessPeripheralBroadcast}, + //{OpCode::SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_RECEIVE, + //&DualModeController::SetConnectionlessPeripheralBroadcastReceive}, + //{OpCode::START_SYNCHRONIZATION_TRAIN, + //&DualModeController::StartSynchronizationTrain}, + //{OpCode::RECEIVE_SYNCHRONIZATION_TRAIN, + //&DualModeController::ReceiveSynchronizationTrain}, + {OpCode::REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY, &DualModeController::ForwardToLm}, + + // LINK_POLICY + {OpCode::HOLD_MODE, &DualModeController::HoldMode}, + {OpCode::SNIFF_MODE, &DualModeController::SniffMode}, + {OpCode::EXIT_SNIFF_MODE, &DualModeController::ExitSniffMode}, + {OpCode::QOS_SETUP, &DualModeController::QosSetup}, + {OpCode::ROLE_DISCOVERY, &DualModeController::RoleDiscovery}, + {OpCode::SWITCH_ROLE, &DualModeController::SwitchRole}, + {OpCode::READ_LINK_POLICY_SETTINGS, &DualModeController::ReadLinkPolicySettings}, + {OpCode::WRITE_LINK_POLICY_SETTINGS, &DualModeController::WriteLinkPolicySettings}, + {OpCode::READ_DEFAULT_LINK_POLICY_SETTINGS, + &DualModeController::ReadDefaultLinkPolicySettings}, + {OpCode::WRITE_DEFAULT_LINK_POLICY_SETTINGS, + &DualModeController::WriteDefaultLinkPolicySettings}, + {OpCode::FLOW_SPECIFICATION, &DualModeController::FlowSpecification}, + {OpCode::SNIFF_SUBRATING, &DualModeController::SniffSubrating}, + + // CONTROLLER_AND_BASEBAND + {OpCode::SET_EVENT_MASK, &DualModeController::SetEventMask}, + {OpCode::RESET, &DualModeController::Reset}, + {OpCode::SET_EVENT_FILTER, &DualModeController::SetEventFilter}, + //{OpCode::FLUSH, &DualModeController::Flush}, + //{OpCode::READ_PIN_TYPE, &DualModeController::ReadPinType}, + //{OpCode::WRITE_PIN_TYPE, &DualModeController::WritePinType}, + //{OpCode::READ_STORED_LINK_KEY, + //&DualModeController::ReadStoredLinkKey}, + //{OpCode::WRITE_STORED_LINK_KEY, + //&DualModeController::WriteStoredLinkKey}, + {OpCode::DELETE_STORED_LINK_KEY, &DualModeController::DeleteStoredLinkKey}, + {OpCode::WRITE_LOCAL_NAME, &DualModeController::WriteLocalName}, + {OpCode::READ_LOCAL_NAME, &DualModeController::ReadLocalName}, + {OpCode::READ_CONNECTION_ACCEPT_TIMEOUT, + &DualModeController::ReadConnectionAcceptTimeout}, + {OpCode::WRITE_CONNECTION_ACCEPT_TIMEOUT, + &DualModeController::WriteConnectionAcceptTimeout}, + {OpCode::READ_PAGE_TIMEOUT, &DualModeController::ReadPageTimeout}, + {OpCode::WRITE_PAGE_TIMEOUT, &DualModeController::WritePageTimeout}, + {OpCode::READ_SCAN_ENABLE, &DualModeController::ReadScanEnable}, + {OpCode::WRITE_SCAN_ENABLE, &DualModeController::WriteScanEnable}, + {OpCode::READ_PAGE_SCAN_ACTIVITY, &DualModeController::ReadPageScanActivity}, + {OpCode::WRITE_PAGE_SCAN_ACTIVITY, &DualModeController::WritePageScanActivity}, + {OpCode::READ_INQUIRY_SCAN_ACTIVITY, &DualModeController::ReadInquiryScanActivity}, + {OpCode::WRITE_INQUIRY_SCAN_ACTIVITY, &DualModeController::WriteInquiryScanActivity}, + {OpCode::READ_AUTHENTICATION_ENABLE, &DualModeController::ReadAuthenticationEnable}, + {OpCode::WRITE_AUTHENTICATION_ENABLE, &DualModeController::WriteAuthenticationEnable}, + {OpCode::READ_CLASS_OF_DEVICE, &DualModeController::ReadClassOfDevice}, + {OpCode::WRITE_CLASS_OF_DEVICE, &DualModeController::WriteClassOfDevice}, + {OpCode::READ_VOICE_SETTING, &DualModeController::ReadVoiceSetting}, + {OpCode::WRITE_VOICE_SETTING, &DualModeController::WriteVoiceSetting}, + //{OpCode::READ_AUTOMATIC_FLUSH_TIMEOUT, + //&DualModeController::ReadAutomaticFlushTimeout}, + //{OpCode::WRITE_AUTOMATIC_FLUSH_TIMEOUT, + //&DualModeController::WriteAutomaticFlushTimeout}, + //{OpCode::READ_NUM_BROADCAST_RETRANSMITS, + //&DualModeController::ReadNumBroadcastRetransmits}, + //{OpCode::WRITE_NUM_BROADCAST_RETRANSMITS, + //&DualModeController::WriteNumBroadcastRetransmits}, + //{OpCode::READ_HOLD_MODE_ACTIVITY, + //&DualModeController::ReadHoldModeActivity}, + //{OpCode::WRITE_HOLD_MODE_ACTIVITY, + //&DualModeController::WriteHoldModeActivity}, + {OpCode::READ_TRANSMIT_POWER_LEVEL, &DualModeController::ReadTransmitPowerLevel}, + {OpCode::READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE, + &DualModeController::ReadSynchronousFlowControlEnable}, + {OpCode::WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE, + &DualModeController::WriteSynchronousFlowControlEnable}, + //{OpCode::SET_CONTROLLER_TO_HOST_FLOW_CONTROL, + //&DualModeController::SetControllerToHostFlowControl}, + {OpCode::HOST_BUFFER_SIZE, &DualModeController::HostBufferSize}, + //{OpCode::HOST_NUMBER_OF_COMPLETED_PACKETS, + //&DualModeController::HostNumberOfCompletedPackets}, + //{OpCode::READ_LINK_SUPERVISION_TIMEOUT, + //&DualModeController::ReadLinkSupervisionTimeout}, + {OpCode::WRITE_LINK_SUPERVISION_TIMEOUT, + &DualModeController::WriteLinkSupervisionTimeout}, + {OpCode::READ_NUMBER_OF_SUPPORTED_IAC, &DualModeController::ReadNumberOfSupportedIac}, + {OpCode::READ_CURRENT_IAC_LAP, &DualModeController::ReadCurrentIacLap}, + {OpCode::WRITE_CURRENT_IAC_LAP, &DualModeController::WriteCurrentIacLap}, + //{OpCode::SET_AFH_HOST_CHANNEL_CLASSIFICATION, + //&DualModeController::SetAfhHostChannelClassification}, + {OpCode::READ_INQUIRY_SCAN_TYPE, &DualModeController::ReadInquiryScanType}, + {OpCode::WRITE_INQUIRY_SCAN_TYPE, &DualModeController::WriteInquiryScanType}, + {OpCode::READ_INQUIRY_MODE, &DualModeController::ReadInquiryMode}, + {OpCode::WRITE_INQUIRY_MODE, &DualModeController::WriteInquiryMode}, + {OpCode::READ_PAGE_SCAN_TYPE, &DualModeController::ReadPageScanType}, + {OpCode::WRITE_PAGE_SCAN_TYPE, &DualModeController::WritePageScanType}, + //{OpCode::READ_AFH_CHANNEL_ASSESSMENT_MODE, + //&DualModeController::ReadAfhChannelAssessmentMode}, + //{OpCode::WRITE_AFH_CHANNEL_ASSESSMENT_MODE, + //&DualModeController::WriteAfhChannelAssessmentMode}, + //{OpCode::READ_EXTENDED_INQUIRY_RESPONSE, + //&DualModeController::ReadExtendedInquiryResponse}, + {OpCode::WRITE_EXTENDED_INQUIRY_RESPONSE, + &DualModeController::WriteExtendedInquiryResponse}, + {OpCode::REFRESH_ENCRYPTION_KEY, &DualModeController::RefreshEncryptionKey}, + //{OpCode::READ_SIMPLE_PAIRING_MODE, + //&DualModeController::ReadSimplePairingMode}, + {OpCode::WRITE_SIMPLE_PAIRING_MODE, &DualModeController::WriteSimplePairingMode}, + {OpCode::READ_LOCAL_OOB_DATA, &DualModeController::ReadLocalOobData}, + {OpCode::READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL, + &DualModeController::ReadInquiryResponseTransmitPowerLevel}, + //{OpCode::WRITE_INQUIRY_TRANSMIT_POWER_LEVEL, + //&DualModeController::WriteInquiryTransmitPowerLevel}, + //{OpCode::READ_DEFAULT_ERRONEOUS_DATA_REPORTING, + //&DualModeController::ReadDefaultErroneousDataReporting}, + //{OpCode::WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING, + //&DualModeController::WriteDefaultErroneousDataReporting}, + {OpCode::ENHANCED_FLUSH, &DualModeController::EnhancedFlush}, + {OpCode::SEND_KEYPRESS_NOTIFICATION, &DualModeController::ForwardToLm}, + {OpCode::SET_EVENT_MASK_PAGE_2, &DualModeController::SetEventMaskPage2}, + //{OpCode::READ_FLOW_CONTROL_MODE, + //&DualModeController::ReadFlowControlMode}, + //{OpCode::WRITE_FLOW_CONTROL_MODE, + //&DualModeController::WriteFlowControlMode}, + {OpCode::READ_ENHANCED_TRANSMIT_POWER_LEVEL, + &DualModeController::ReadEnhancedTransmitPowerLevel}, + //{OpCode::READ_LE_HOST_SUPPORT, + //&DualModeController::ReadLeHostSupport}, + {OpCode::WRITE_LE_HOST_SUPPORT, &DualModeController::WriteLeHostSupport}, + //{OpCode::SET_MWS_CHANNEL_PARAMETERS, + //&DualModeController::SetMwsChannelParameters}, + //{OpCode::SET_EXTERNAL_FRAME_CONFIGURATION, + //&DualModeController::SetExternalFrameConfiguration}, + //{OpCode::SET_MWS_SIGNALING, &DualModeController::SetMwsSignaling}, + //{OpCode::SET_MWS_TRANSPORT_LAYER, + //&DualModeController::SetMwsTransportLayer}, + //{OpCode::SET_MWS_SCAN_FREQUENCY_TABLE, + //&DualModeController::SetMwsScanFrequencyTable}, + //{OpCode::SET_MWS_PATTERN_CONFIGURATION, + //&DualModeController::SetMwsPatternConfiguration}, + //{OpCode::SET_RESERVED_LT_ADDR, + //&DualModeController::SetReservedLtAddr}, + //{OpCode::DELETE_RESERVED_LT_ADDR, + //&DualModeController::DeleteReservedLtAddr}, + //{OpCode::SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_DATA, + //&DualModeController::SetConnectionlessPeripheralBroadcastData}, + //{OpCode::READ_SYNCHRONIZATION_TRAIN_PARAMETERS, + //&DualModeController::ReadSynchronizationTrainParameters}, + //{OpCode::WRITE_SYNCHRONIZATION_TRAIN_PARAMETERS, + //&DualModeController::WriteSynchronizationTrainParameters}, + //{OpCode::READ_SECURE_CONNECTIONS_HOST_SUPPORT, + //&DualModeController::ReadSecureConnectionsHostSupport}, + {OpCode::WRITE_SECURE_CONNECTIONS_HOST_SUPPORT, + &DualModeController::WriteSecureConnectionsHostSupport}, + //{OpCode::READ_AUTHENTICATED_PAYLOAD_TIMEOUT, + //&DualModeController::ReadAuthenticatedPayloadTimeout}, + //{OpCode::WRITE_AUTHENTICATED_PAYLOAD_TIMEOUT, + //&DualModeController::WriteAuthenticatedPayloadTimeout}, + {OpCode::READ_LOCAL_OOB_EXTENDED_DATA, &DualModeController::ReadLocalOobExtendedData}, + //{OpCode::READ_EXTENDED_PAGE_TIMEOUT, + //&DualModeController::ReadExtendedPageTimeout}, + //{OpCode::WRITE_EXTENDED_PAGE_TIMEOUT, + //&DualModeController::WriteExtendedPageTimeout}, + //{OpCode::READ_EXTENDED_INQUIRY_LENGTH, + //&DualModeController::ReadExtendedInquiryLength}, + //{OpCode::WRITE_EXTENDED_INQUIRY_LENGTH, + //&DualModeController::WriteExtendedInquiryLength}, + //{OpCode::SET_ECOSYSTEM_BASE_INTERVAL, + //&DualModeController::SetEcosystemBaseInterval}, + //{OpCode::CONFIGURE_DATA_PATH, &DualModeController::ConfigureDataPath}, + {OpCode::SET_MIN_ENCRYPTION_KEY_SIZE, &DualModeController::SetMinEncryptionKeySize}, + + // INFORMATIONAL_PARAMETERS + {OpCode::READ_LOCAL_VERSION_INFORMATION, + &DualModeController::ReadLocalVersionInformation}, + {OpCode::READ_LOCAL_SUPPORTED_COMMANDS, &DualModeController::ReadLocalSupportedCommands}, + {OpCode::READ_LOCAL_SUPPORTED_FEATURES, &DualModeController::ReadLocalSupportedFeatures}, + {OpCode::READ_LOCAL_EXTENDED_FEATURES, &DualModeController::ReadLocalExtendedFeatures}, + {OpCode::READ_BUFFER_SIZE, &DualModeController::ReadBufferSize}, + {OpCode::READ_BD_ADDR, &DualModeController::ReadBdAddr}, + //{OpCode::READ_DATA_BLOCK_SIZE, + //&DualModeController::ReadDataBlockSize}, + {OpCode::READ_LOCAL_SUPPORTED_CODECS_V1, &DualModeController::ReadLocalSupportedCodecsV1}, + //{OpCode::READ_LOCAL_SIMPLE_PAIRING_OPTIONS, + //&DualModeController::ReadLocalSimplePairingOptions}, + //{OpCode::READ_LOCAL_SUPPORTED_CODECS_V2, + //&DualModeController::ReadLocalSupportedCodecsV2}, + //{OpCode::READ_LOCAL_SUPPORTED_CODEC_CAPABILITIES, + //&DualModeController::ReadLocalSupportedCodecCapabilities}, + //{OpCode::READ_LOCAL_SUPPORTED_CONTROLLER_DELAY, + //&DualModeController::ReadLocalSupportedControllerDelay}, + + // STATUS_PARAMETERS + {OpCode::READ_FAILED_CONTACT_COUNTER, &DualModeController::ReadFailedContactCounter}, + {OpCode::RESET_FAILED_CONTACT_COUNTER, &DualModeController::ResetFailedContactCounter}, + //{OpCode::READ_LINK_QUALITY, &DualModeController::ReadLinkQuality}, + {OpCode::READ_RSSI, &DualModeController::ReadRssi}, + //{OpCode::READ_AFH_CHANNEL_MAP, + //&DualModeController::ReadAfhChannelMap}, + //{OpCode::READ_CLOCK, &DualModeController::ReadClock}, + {OpCode::READ_ENCRYPTION_KEY_SIZE, &DualModeController::ReadEncryptionKeySize}, + //{OpCode::GET_MWS_TRANSPORT_LAYER_CONFIGURATION, + //&DualModeController::GetMwsTransportLayerConfiguration}, + //{OpCode::SET_TRIGGERED_CLOCK_CAPTURE, + //&DualModeController::SetTriggeredClockCapture}, + + // TESTING + {OpCode::READ_LOOPBACK_MODE, &DualModeController::ReadLoopbackMode}, + {OpCode::WRITE_LOOPBACK_MODE, &DualModeController::WriteLoopbackMode}, + //{OpCode::ENABLE_DEVICE_UNDER_TEST_MODE, + //&DualModeController::EnableDeviceUnderTestMode}, + //{OpCode::WRITE_SIMPLE_PAIRING_DEBUG_MODE, + //&DualModeController::WriteSimplePairingDebugMode}, + //{OpCode::WRITE_SECURE_CONNECTIONS_TEST_MODE, + //&DualModeController::WriteSecureConnectionsTestMode}, + + // LE_CONTROLLER + {OpCode::LE_SET_EVENT_MASK, &DualModeController::LeSetEventMask}, + {OpCode::LE_READ_BUFFER_SIZE_V1, &DualModeController::LeReadBufferSizeV1}, + {OpCode::LE_READ_LOCAL_SUPPORTED_FEATURES_PAGE_0, + &DualModeController::LeReadLocalSupportedFeaturesPage0}, + {OpCode::LE_SET_RANDOM_ADDRESS, &DualModeController::LeSetRandomAddress}, + {OpCode::LE_SET_ADVERTISING_PARAMETERS, &DualModeController::LeSetAdvertisingParameters}, + {OpCode::LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER, + &DualModeController::LeReadAdvertisingPhysicalChannelTxPower}, + {OpCode::LE_SET_ADVERTISING_DATA, &DualModeController::LeSetAdvertisingData}, + {OpCode::LE_SET_SCAN_RESPONSE_DATA, &DualModeController::LeSetScanResponseData}, + {OpCode::LE_SET_ADVERTISING_ENABLE, &DualModeController::LeSetAdvertisingEnable}, + {OpCode::LE_SET_SCAN_PARAMETERS, &DualModeController::LeSetScanParameters}, + {OpCode::LE_SET_SCAN_ENABLE, &DualModeController::LeSetScanEnable}, + {OpCode::LE_CREATE_CONNECTION, &DualModeController::LeCreateConnection}, + {OpCode::LE_CREATE_CONNECTION_CANCEL, &DualModeController::LeCreateConnectionCancel}, + {OpCode::LE_READ_FILTER_ACCEPT_LIST_SIZE, + &DualModeController::LeReadFilterAcceptListSize}, + {OpCode::LE_CLEAR_FILTER_ACCEPT_LIST, &DualModeController::LeClearFilterAcceptList}, + {OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST, + &DualModeController::LeAddDeviceToFilterAcceptList}, + {OpCode::LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST, + &DualModeController::LeRemoveDeviceFromFilterAcceptList}, + {OpCode::LE_CONNECTION_UPDATE, &DualModeController::LeConnectionUpdate}, + //{OpCode::LE_SET_HOST_CHANNEL_CLASSIFICATION, + //&DualModeController::LeSetHostChannelClassification}, + //{OpCode::LE_READ_CHANNEL_MAP, &DualModeController::LeReadChannelMap}, + {OpCode::LE_READ_REMOTE_FEATURES_PAGE_0, &DualModeController::LeReadRemoteFeaturesPage0}, + {OpCode::LE_ENCRYPT, &DualModeController::LeEncrypt}, + {OpCode::LE_RAND, &DualModeController::LeRand}, + {OpCode::LE_START_ENCRYPTION, &DualModeController::LeStartEncryption}, + {OpCode::LE_LONG_TERM_KEY_REQUEST_REPLY, &DualModeController::LeLongTermKeyRequestReply}, + {OpCode::LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY, + &DualModeController::LeLongTermKeyRequestNegativeReply}, + {OpCode::LE_READ_SUPPORTED_STATES, &DualModeController::LeReadSupportedStates}, + //{OpCode::LE_RECEIVER_TEST_V1, &DualModeController::LeReceiverTestV1}, + //{OpCode::LE_TRANSMITTER_TEST_V1, + //&DualModeController::LeTransmitterTestV1}, + //{OpCode::LE_TEST_END, &DualModeController::LeTestEnd}, + {OpCode::LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY, + &DualModeController::LeRemoteConnectionParameterRequestReply}, + {OpCode::LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY, + &DualModeController::LeRemoteConnectionParameterRequestNegativeReply}, + {OpCode::LE_SET_DATA_LENGTH, &DualModeController::LeSetDataLength}, + {OpCode::LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH, + &DualModeController::LeReadSuggestedDefaultDataLength}, + {OpCode::LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH, + &DualModeController::LeWriteSuggestedDefaultDataLength}, + {OpCode::LE_READ_LOCAL_P_256_PUBLIC_KEY, &DualModeController::LeReadLocalP256PublicKey}, + //{OpCode::LE_GENERATE_DHKEY_V1, + //&DualModeController::LeGenerateDhkeyV1}, + {OpCode::LE_ADD_DEVICE_TO_RESOLVING_LIST, + &DualModeController::LeAddDeviceToResolvingList}, + {OpCode::LE_REMOVE_DEVICE_FROM_RESOLVING_LIST, + &DualModeController::LeRemoveDeviceFromResolvingList}, + {OpCode::LE_CLEAR_RESOLVING_LIST, &DualModeController::LeClearResolvingList}, + {OpCode::LE_READ_RESOLVING_LIST_SIZE, &DualModeController::LeReadResolvingListSize}, + {OpCode::LE_READ_PEER_RESOLVABLE_ADDRESS, + &DualModeController::LeReadPeerResolvableAddress}, + {OpCode::LE_READ_LOCAL_RESOLVABLE_ADDRESS, + &DualModeController::LeReadLocalResolvableAddress}, + {OpCode::LE_SET_ADDRESS_RESOLUTION_ENABLE, + &DualModeController::LeSetAddressResolutionEnable}, + {OpCode::LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT, + &DualModeController::LeSetResolvablePrivateAddressTimeout}, + {OpCode::LE_READ_MAXIMUM_DATA_LENGTH, &DualModeController::LeReadMaximumDataLength}, + {OpCode::LE_READ_PHY, &DualModeController::LeReadPhy}, + {OpCode::LE_SET_DEFAULT_PHY, &DualModeController::LeSetDefaultPhy}, + {OpCode::LE_SET_PHY, &DualModeController::LeSetPhy}, + //{OpCode::LE_RECEIVER_TEST_V2, &DualModeController::LeReceiverTestV2}, + //{OpCode::LE_TRANSMITTER_TEST_V2, + //&DualModeController::LeTransmitterTestV2}, + {OpCode::LE_SET_ADVERTISING_SET_RANDOM_ADDRESS, + &DualModeController::LeSetAdvertisingSetRandomAddress}, + {OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1, + &DualModeController::LeSetExtendedAdvertisingParametersV1}, + {OpCode::LE_SET_EXTENDED_ADVERTISING_DATA, + &DualModeController::LeSetExtendedAdvertisingData}, + {OpCode::LE_SET_EXTENDED_SCAN_RESPONSE_DATA, + &DualModeController::LeSetExtendedScanResponseData}, + {OpCode::LE_SET_EXTENDED_ADVERTISING_ENABLE, + &DualModeController::LeSetExtendedAdvertisingEnable}, + {OpCode::LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH, + &DualModeController::LeReadMaximumAdvertisingDataLength}, + {OpCode::LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS, + &DualModeController::LeReadNumberOfSupportedAdvertisingSets}, + {OpCode::LE_REMOVE_ADVERTISING_SET, &DualModeController::LeRemoveAdvertisingSet}, + {OpCode::LE_CLEAR_ADVERTISING_SETS, &DualModeController::LeClearAdvertisingSets}, + {OpCode::LE_SET_PERIODIC_ADVERTISING_PARAMETERS_V1, + &DualModeController::LeSetPeriodicAdvertisingParametersV1}, + {OpCode::LE_SET_PERIODIC_ADVERTISING_DATA, + &DualModeController::LeSetPeriodicAdvertisingData}, + {OpCode::LE_SET_PERIODIC_ADVERTISING_ENABLE, + &DualModeController::LeSetPeriodicAdvertisingEnable}, + {OpCode::LE_SET_EXTENDED_SCAN_PARAMETERS, + &DualModeController::LeSetExtendedScanParameters}, + {OpCode::LE_SET_EXTENDED_SCAN_ENABLE, &DualModeController::LeSetExtendedScanEnable}, + {OpCode::LE_EXTENDED_CREATE_CONNECTION_V1, + &DualModeController::LeExtendedCreateConnectionV1}, + {OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC, + &DualModeController::LePeriodicAdvertisingCreateSync}, + {OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL, + &DualModeController::LePeriodicAdvertisingCreateSyncCancel}, + {OpCode::LE_PERIODIC_ADVERTISING_TERMINATE_SYNC, + &DualModeController::LePeriodicAdvertisingTerminateSync}, + {OpCode::LE_ADD_DEVICE_TO_PERIODIC_ADVERTISER_LIST, + &DualModeController::LeAddDeviceToPeriodicAdvertiserList}, + {OpCode::LE_REMOVE_DEVICE_FROM_PERIODIC_ADVERTISER_LIST, + &DualModeController::LeRemoveDeviceFromPeriodicAdvertiserList}, + {OpCode::LE_CLEAR_PERIODIC_ADVERTISER_LIST, + &DualModeController::LeClearPeriodicAdvertiserList}, + {OpCode::LE_READ_PERIODIC_ADVERTISER_LIST_SIZE, + &DualModeController::LeReadPeriodicAdvertiserListSize}, + //{OpCode::LE_READ_TRANSMIT_POWER, + //&DualModeController::LeReadTransmitPower}, + //{OpCode::LE_READ_RF_PATH_COMPENSATION_POWER, + //&DualModeController::LeReadRfPathCompensationPower}, + //{OpCode::LE_WRITE_RF_PATH_COMPENSATION_POWER, + //&DualModeController::LeWriteRfPathCompensationPower}, + {OpCode::LE_SET_PRIVACY_MODE, &DualModeController::LeSetPrivacyMode}, + //{OpCode::LE_RECEIVER_TEST_V3, &DualModeController::LeReceiverTestV3}, + //{OpCode::LE_TRANSMITTER_TEST_V3, + //&DualModeController::LeTransmitterTestV3}, + //{OpCode::LE_SET_CONNECTIONLESS_CTE_TRANSMIT_PARAMETERS, + //&DualModeController::LeSetConnectionlessCteTransmitParameters}, + //{OpCode::LE_SET_CONNECTIONLESS_CTE_TRANSMIT_ENABLE, + //&DualModeController::LeSetConnectionlessCteTransmitEnable}, + //{OpCode::LE_SET_CONNECTIONLESS_IQ_SAMPLING_ENABLE, + //&DualModeController::LeSetConnectionlessIqSamplingEnable}, + //{OpCode::LE_SET_CONNECTION_CTE_RECEIVE_PARAMETERS, + //&DualModeController::LeSetConnectionCteReceiveParameters}, + //{OpCode::LE_SET_CONNECTION_CTE_TRANSMIT_PARAMETERS, + //&DualModeController::LeSetConnectionCteTransmitParameters}, + //{OpCode::LE_CONNECTION_CTE_REQUEST_ENABLE, + //&DualModeController::LeConnectionCteRequestEnable}, + //{OpCode::LE_CONNECTION_CTE_RESPONSE_ENABLE, + //&DualModeController::LeConnectionCteResponseEnable}, + //{OpCode::LE_READ_ANTENNA_INFORMATION, + //&DualModeController::LeReadAntennaInformation}, + //{OpCode::LE_SET_PERIODIC_ADVERTISING_RECEIVE_ENABLE, + //&DualModeController::LeSetPeriodicAdvertisingReceiveEnable}, + //{OpCode::LE_PERIODIC_ADVERTISING_SYNC_TRANSFER, + //&DualModeController::LePeriodicAdvertisingSyncTransfer}, + //{OpCode::LE_PERIODIC_ADVERTISING_SET_INFO_TRANSFER, + //&DualModeController::LePeriodicAdvertisingSetInfoTransfer}, + //{OpCode::LE_SET_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS, + //&DualModeController::LeSetPeriodicAdvertisingSyncTransferParameters}, + //{OpCode::LE_SET_DEFAULT_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS, + //&DualModeController::LeSetDefaultPeriodicAdvertisingSyncTransferParameters}, + //{OpCode::LE_GENERATE_DHKEY_V2, + //&DualModeController::LeGenerateDhkeyV2}, + //{OpCode::LE_MODIFY_SLEEP_CLOCK_ACCURACY, + //&DualModeController::LeModifySleepClockAccuracy}, + {OpCode::LE_READ_BUFFER_SIZE_V2, &DualModeController::LeReadBufferSizeV2}, + //{OpCode::LE_READ_ISO_TX_SYNC, &DualModeController::LeReadIsoTxSync}, + {OpCode::LE_SET_CIG_PARAMETERS, &DualModeController::ForwardToLl}, + {OpCode::LE_SET_CIG_PARAMETERS_TEST, &DualModeController::ForwardToLl}, + {OpCode::LE_CREATE_CIS, &DualModeController::ForwardToLl}, + {OpCode::LE_REMOVE_CIG, &DualModeController::ForwardToLl}, + {OpCode::LE_ACCEPT_CIS_REQUEST, &DualModeController::ForwardToLl}, + {OpCode::LE_REJECT_CIS_REQUEST, &DualModeController::ForwardToLl}, + //{OpCode::LE_CREATE_BIG, &DualModeController::LeCreateBig}, + //{OpCode::LE_CREATE_BIG_TEST, &DualModeController::LeCreateBigTest}, + //{OpCode::LE_TERMINATE_BIG, &DualModeController::LeTerminateBig}, + //{OpCode::LE_BIG_CREATE_SYNC, &DualModeController::LeBigCreateSync}, + //{OpCode::LE_BIG_TERMINATE_SYNC, + //&DualModeController::LeBigTerminateSync}, + {OpCode::LE_REQUEST_PEER_SCA, &DualModeController::LeRequestPeerSca}, + {OpCode::LE_SETUP_ISO_DATA_PATH, &DualModeController::ForwardToLl}, + {OpCode::LE_REMOVE_ISO_DATA_PATH, &DualModeController::ForwardToLl}, + //{OpCode::LE_ISO_TRANSMIT_TEST, + //&DualModeController::LeIsoTransmitTest}, + //{OpCode::LE_ISO_RECEIVE_TEST, &DualModeController::LeIsoReceiveTest}, + //{OpCode::LE_ISO_READ_TEST_COUNTERS, + //&DualModeController::LeIsoReadTestCounters}, + //{OpCode::LE_ISO_TEST_END, &DualModeController::LeIsoTestEnd}, + {OpCode::LE_SET_HOST_FEATURE_V1, &DualModeController::LeSetHostFeatureV1}, + //{OpCode::LE_READ_ISO_LINK_QUALITY, + //&DualModeController::LeReadIsoLinkQuality}, + //{OpCode::LE_ENHANCED_READ_TRANSMIT_POWER_LEVEL, + //&DualModeController::LeEnhancedReadTransmitPowerLevel}, + //{OpCode::LE_READ_REMOTE_TRANSMIT_POWER_LEVEL, + //&DualModeController::LeReadRemoteTransmitPowerLevel}, + //{OpCode::LE_SET_PATH_LOSS_REPORTING_PARAMETERS, + //&DualModeController::LeSetPathLossReportingParameters}, + //{OpCode::LE_SET_PATH_LOSS_REPORTING_ENABLE, + //&DualModeController::LeSetPathLossReportingEnable}, + //{OpCode::LE_SET_TRANSMIT_POWER_REPORTING_ENABLE, + //&DualModeController::LeSetTransmitPowerReportingEnable}, + //{OpCode::LE_TRANSMITTER_TEST_V4, + //&DualModeController::LeTransmitterTestV4}, + //{OpCode::LE_SET_DATA_RELATED_ADDRESS_CHANGES, + //&DualModeController::LeSetDataRelatedAddressChanges}, + //{OpCode::LE_SET_DEFAULT_SUBRATE, + //&DualModeController::LeSetDefaultSubrate}, + //{OpCode::LE_SUBRATE_REQUEST, &DualModeController::LeSubrateRequest}, + //{OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V2, + //&DualModeController::LeSetExtendedAdvertisingParametersV2}, + //{OpCode::LE_SET_DECISION_DATA, &DualModeController::LeSetDecisionData}, + //{OpCode::LE_SET_DECISION_INSTRUCTIONS, + //&DualModeController::LeSetDecisionInstructions}, + //{OpCode::LE_SET_PERIODIC_ADVERTISING_SUBEVENT_DATA, + //&DualModeController::LeSetPeriodicAdvertisingSubeventData}, + //{OpCode::LE_SET_PERIODIC_ADVERTISING_RESPONSE_DATA, + //&DualModeController::LeSetPeriodicAdvertisingResponseData}, + //{OpCode::LE_SET_PERIODIC_SYNC_SUBEVENT, + //&DualModeController::LeSetPeriodicSyncSubevent}, + //{OpCode::LE_EXTENDED_CREATE_CONNECTION_V2, + //&DualModeController::LeExtendedCreateConnectionV2}, + //{OpCode::LE_SET_PERIODIC_ADVERTISING_PARAMETERS_V2, + //&DualModeController::LeSetPeriodicAdvertisingParametersV2}, + //{OpCode::LE_READ_ALL_LOCAL_SUPPORTED_FEATURES, + //&DualModeController::LeReadAllLocalSupportedFeatures}, + //{OpCode::LE_READ_ALL_REMOTE_FEATURES, + //&DualModeController::LeReadAllRemoteFeatures}, + //{OpCode::LE_CS_READ_LOCAL_SUPPORTED_CAPABILITIES, + //&DualModeController::LeCsReadLocalSupportedCapabilities}, + //{OpCode::LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES, + //&DualModeController::LeCsReadRemoteSupportedCapabilities}, + //{OpCode::LE_CS_WRITE_CACHED_REMOTE_SUPPORTED_CAPABILITIES, + //&DualModeController::LeCsWriteCachedRemoteSupportedCapabilities}, + //{OpCode::LE_CS_SECURITY_ENABLE, &DualModeController::LeCsSecurityEnable}, + //{OpCode::LE_CS_SET_DEFAULT_SETTINGS, &DualModeController::LeCsSetDefaultSettings}, + //{OpCode::LE_CS_READ_REMOTE_FAE_TABLE, + //&DualModeController::LeCsReadRemoteFaeTable}, + //{OpCode::LE_CS_WRITE_CACHED_REMOTE_FAE_TABLE, + //&DualModeController::LeCsWriteCachedRemoteFaeTable}, + //{OpCode::LE_CS_CREATE_CONFIG, &DualModeController::LeCsCreateConfig}, + //{OpCode::LE_CS_REMOVE_CONFIG, &DualModeController::LeCsRemoveConfig}, + //{OpCode::LE_CS_SET_CHANNEL_CLASSIFICATION, + //&DualModeController::LeCsSetChannelClassification}, + //{OpCode::LE_CS_SET_PROCEDURE_PARAMETERS, + //&DualModeController::LeCsSetProcedureParameters}, + //{OpCode::LE_CS_PROCEDURE_ENABLE, &DualModeController::LeCsProcedureEnable}, + //{OpCode::LE_CS_TEST, &DualModeController::LeCsTest}, + //{OpCode::LE_CS_TEST_END, &DualModeController::LeCsTestEnd}, + //{OpCode::LE_ADD_DEVICE_TO_MONITORED_ADVERTISERS_LIST, + //&DualModeController::LeAddDeviceToMonitoredAdvertisersList}, + //{OpCode::LE_REMOVE_DEVICE_FROM_MONITORED_ADVERTISERS_LIST, + //&DualModeController::LeRemoveDeviceFromMonitoredAdvertisersList}, + //{OpCode::LE_CLEAR_MONITORED_ADVERTISERS_LIST, + //&DualModeController::LeClearMonitoredAdvertisersList}, + //{OpCode::LE_READ_MONITORED_ADVERTISERS_LIST_SIZE, + //&DualModeController::LeReadMonitoredAdvertisersListSize}, + //{OpCode::LE_ENABLE_MONITORED_ADVERTISERS, + //&DualModeController::LeEnableMonitoredAdvertisers}, + //{OpCode::LE_FRAME_SPACE_UPDATE, &DualModeController::LeFrameSpaceUpdate}, + + // VENDOR + {OpCode(CSR_VENDOR), &DualModeController::CsrVendorCommand}, + {OpCode::LE_GET_VENDOR_CAPABILITIES, &DualModeController::LeGetVendorCapabilities}, + {OpCode::LE_BATCH_SCAN, &DualModeController::LeBatchScan}, + {OpCode::LE_APCF, &DualModeController::LeApcf}, + {OpCode::LE_GET_CONTROLLER_ACTIVITY_ENERGY_INFO, + &DualModeController::LeGetControllerActivityEnergyInfo}, + {OpCode::LE_EX_SET_SCAN_PARAMETERS, &DualModeController::LeExSetScanParameters}, + {OpCode::GET_CONTROLLER_DEBUG_INFO, &DualModeController::GetControllerDebugInfo}, + {OpCode::INTEL_DDC_CONFIG_READ, &DualModeController::IntelDdcConfigRead}, + {OpCode::INTEL_DDC_CONFIG_WRITE, &DualModeController::IntelDdcConfigWrite}, + }; + return handlers; +} } // namespace rootcanal diff --git a/model/controller/dual_mode_controller.h b/model/controller/dual_mode_controller.h index 996afb6..d56273b 100644 --- a/model/controller/dual_mode_controller.h +++ b/model/controller/dual_mode_controller.h @@ -598,14 +598,16 @@ class DualModeController : public Device { // Map command opcodes to the corresponding bit index in the // supported command mask. - static const std::unordered_map hci_command_op_code_to_index_; + static const std::unordered_map& GetOpCodeToIndex(); // Map all implemented opcodes to the function implementing the handler // for the associated command. The map should be a subset of the // supported_command field in the properties_ object. Commands // that are supported but not implemented will raise a fatal assert. using CommandHandler = std::function; - static const std::unordered_map hci_command_handlers_; + + // Getter for the command handlers map + static const std::unordered_map& GetHciCommandHandlers(); }; } // namespace rootcanal diff --git a/model/controller/ffi.cc b/model/controller/ffi.cc index 6d8fd1c..d9b1325 100644 --- a/model/controller/ffi.cc +++ b/model/controller/ffi.cc @@ -38,28 +38,41 @@ enum Idc { extern "C" { __attribute__((visibility("default"))) void* ffi_controller_new( - uint8_t const address[6], void (*send_hci)(int idc, uint8_t const* data, size_t data_len), - void (*send_ll)(uint8_t const* data, size_t data_len, int phy, int tx_power)) { + uint8_t const address[6], + void (*send_hci)(void* cookie, int idc, uint8_t const* data, size_t data_len), + void (*send_ll)(void* cookie, uint8_t const* data, size_t data_len, int phy, int tx_power), + void (*invalid_packet_handler)(void* cookie, int reason, char const* message, + uint8_t const* data, size_t data_len), + void* cookie) { DualModeController* controller = new DualModeController(); controller->SetAddress( Address({address[0], address[1], address[2], address[3], address[4], address[5]})); controller->RegisterEventChannel([=](std::shared_ptr> data) { - send_hci(hci::Idc::EVT, data->data(), data->size()); + send_hci(cookie, hci::Idc::EVT, data->data(), data->size()); }); controller->RegisterAclChannel([=](std::shared_ptr> data) { - send_hci(hci::Idc::ACL, data->data(), data->size()); + send_hci(cookie, hci::Idc::ACL, data->data(), data->size()); }); controller->RegisterScoChannel([=](std::shared_ptr> data) { - send_hci(hci::Idc::SCO, data->data(), data->size()); + send_hci(cookie, hci::Idc::SCO, data->data(), data->size()); }); controller->RegisterIsoChannel([=](std::shared_ptr> data) { - send_hci(hci::Idc::ISO, data->data(), data->size()); + send_hci(cookie, hci::Idc::ISO, data->data(), data->size()); }); controller->RegisterLinkLayerChannel( [=](std::vector const& data, Phy::Type phy, int8_t tx_power) { - send_ll(data.data(), data.size(), static_cast(phy), tx_power); + send_ll(cookie, data.data(), data.size(), static_cast(phy), tx_power); }); + if (invalid_packet_handler) { + controller->RegisterInvalidPacketHandler([=](uint32_t /*id*/, InvalidPacketReason reason, + std::string message, + std::vector const& packet) { + invalid_packet_handler(cookie, static_cast(reason), message.c_str(), packet.data(), + packet.size()); + }); + } + return controller; } diff --git a/model/controller/ffi.h b/model/controller/ffi.h index 8b1d9d2..e3fb52f 100644 --- a/model/controller/ffi.h +++ b/model/controller/ffi.h @@ -19,10 +19,13 @@ extern "C" { -void* ffi_controller_new(uint8_t const address[6], - void (*send_hci)(int idc, uint8_t const* data, size_t data_len), - void (*send_ll)(uint8_t const* data, size_t data_len, int phy, - int tx_power)); +void* ffi_controller_new( + uint8_t const address[6], + void (*send_hci)(void* cookie, int idc, uint8_t const* data, size_t data_len), + void (*send_ll)(void* cookie, uint8_t const* data, size_t data_len, int phy, int tx_power), + void (*invalid_packet_handler)(void* cookie, int reason, char const* message, + uint8_t const* data, size_t data_len), + void* cookie); void ffi_controller_delete(void* controller); void ffi_controller_receive_hci(void* controller, int idc, uint8_t const* data, size_t data_len); void ffi_controller_receive_ll(void* controller, uint8_t const* data, size_t data_len, int phy, diff --git a/model/controller/le_advertiser.cc b/model/controller/le_advertiser.cc index cd9ae56..bb2ba4b 100644 --- a/model/controller/le_advertiser.cc +++ b/model/controller/le_advertiser.cc @@ -40,7 +40,7 @@ using duration = std::chrono::steady_clock::duration; using time_point = std::chrono::steady_clock::time_point; }; // namespace chrono -slots operator"" _slots(unsigned long long count) { return slots(count); } +slots operator""_slots(unsigned long long count) { return slots(count); } // ============================================================================= // Constants diff --git a/model/controller/le_advertiser.h b/model/controller/le_advertiser.h index f365370..6795eb1 100644 --- a/model/controller/le_advertiser.h +++ b/model/controller/le_advertiser.h @@ -32,7 +32,7 @@ namespace rootcanal { using slots = std::chrono::duration>; // User defined literal for slots, e.g. `0x800_slots` -slots operator"" _slots(unsigned long long count); +slots operator""_slots(unsigned long long count); using namespace bluetooth::hci; diff --git a/packets/hci_packets.pdl b/packets/hci_packets.pdl index 444c621..4656e82 100644 --- a/packets/hci_packets.pdl +++ b/packets/hci_packets.pdl @@ -384,12 +384,13 @@ enum OpCode : 16 { LE_CS_READ_REMOTE_FAE_TABLE = 0x208E, LE_CS_WRITE_CACHED_REMOTE_FAE_TABLE = 0x208F, LE_CS_CREATE_CONFIG = 0x2090, - LE_CS_REMOVE_CONFIG = 0x0291, + LE_CS_REMOVE_CONFIG = 0x2091, LE_CS_SET_CHANNEL_CLASSIFICATION = 0x2092, LE_CS_SET_PROCEDURE_PARAMETERS = 0x2093, LE_CS_PROCEDURE_ENABLE = 0x2094, LE_CS_TEST = 0x2095, LE_CS_TEST_END = 0x2096, + LE_SET_HOST_FEATURE_V2 = 0x2097, LE_ADD_DEVICE_TO_MONITORED_ADVERTISERS_LIST = 0x2098, LE_REMOVE_DEVICE_FROM_MONITORED_ADVERTISERS_LIST = 0x2099, LE_CLEAR_MONITORED_ADVERTISERS_LIST = 0x209A, @@ -4029,18 +4030,6 @@ struct EnabledSet { max_extended_advertising_events : 8, } -struct DisabledSet { - advertising_handle : 8, - _fixed_ = 0x00 : 16, // duration - _fixed_ = 0x00 : 8, // max_extended_advertising_events -} - -packet LeSetExtendedAdvertisingDisable : Command (op_code = LE_SET_EXTENDED_ADVERTISING_ENABLE) { - _fixed_ = 0x00 : 8, // Enable::DISABLED - _count_(disabled_sets) : 8, - disabled_sets : DisabledSet[], -} - packet LeSetExtendedAdvertisingEnable : Command (op_code = LE_SET_EXTENDED_ADVERTISING_ENABLE) { enable : Enable, _count_(enabled_sets) : 8, @@ -4051,7 +4040,7 @@ test LeSetExtendedAdvertisingEnable { "\x39\x20\x06\x01\x01\x01\x00\x00\x00", } -test LeSetExtendedAdvertisingDisable { +test LeSetExtendedAdvertisingEnable { "\x39\x20\x06\x00\x01\x01\x00\x00\x00", } @@ -6530,12 +6519,6 @@ packet LeBatchScanReadResultParameters : LeBatchScan (batch_scan_opcode = READ_R batch_scan_data_read : BatchScanDataRead, } -packet LeBatchScanReadResultParametersCompleteRaw : LeBatchScanComplete (batch_scan_opcode = READ_RESULT_PARAMETERS) { - batch_scan_data_read : BatchScanDataRead, - num_of_records : 8, - raw_data : 8[], -} - packet LeBatchScanReadResultParametersComplete : LeBatchScanComplete (batch_scan_opcode = READ_RESULT_PARAMETERS) { batch_scan_data_read : BatchScanDataRead, _body_, @@ -6888,186 +6871,3 @@ packet ControllerDebugInfoEvent : VendorSpecificEvent (subevent_code = CONTROLLE _size_(debug_data) : 16, debug_data : 8[], } - -// ----------------------------------------------------------------------------- -// Microsoft Commands -// https://learn.microsoft.com/en-us/windows-hardware/drivers/bluetooth/microsoft-defined-bluetooth-hci-commands-and-events -// ----------------------------------------------------------------------------- - -enum MsftSubcommandOpcode : 8 { - MSFT_READ_SUPPORTED_FEATURES = 0x00, - MSFT_MONITOR_RSSI = 0x01, - MSFT_CANCEL_MONITOR_RSSI = 0x02, - MSFT_LE_MONITOR_ADV = 0x03, - MSFT_LE_CANCEL_MONITOR_ADV = 0x04, - MSFT_LE_SET_ADV_FILTER_ENABLE = 0x05, - MSFT_READ_ABSOLUTE_RSSI = 0x06, -} - -// MSFT Commands do not have a constant opcode, so leave `op_code` undefined. -packet MsftCommand : Command { - subcommand_opcode: MsftSubcommandOpcode, - _payload_, -} - -packet MsftReadSupportedFeatures : MsftCommand (subcommand_opcode = MSFT_READ_SUPPORTED_FEATURES) {} - -enum MsftLeMonitorAdvConditionType : 8 { - MSFT_CONDITION_TYPE_PATTERNS = 0x01, - MSFT_CONDITION_TYPE_UUID = 0x02, - MSFT_CONDITION_TYPE_IRK_RESOLUTION = 0x03, - MSFT_CONDITION_TYPE_ADDRESS = 0x04, -} - -enum MsftLeMonitorAdvConditionUuidType : 8 { - MSFT_CONDITION_UUID_TYPE_16_BIT = 0x01, - MSFT_CONDITION_UUID_TYPE_32_BIT = 0x02, - MSFT_CONDITION_UUID_TYPE_128_BIT = 0x03, -} - -packet MsftLeMonitorAdv : MsftCommand (subcommand_opcode = MSFT_LE_MONITOR_ADV) { - rssi_threshold_high : 8, - rssi_threshold_low : 8, - rssi_threshold_low_time_interval : 8, - rssi_sampling_period : 8, - condition_type: MsftLeMonitorAdvConditionType, - _payload_, -} - -struct MsftLeMonitorAdvConditionPattern { - _size_(pattern) : 8, // including one byte for ad_type and one byte for start_of_pattern - ad_type: 8, - start_of_pattern: 8, - pattern: 8[+2], -} - -packet MsftLeMonitorAdvConditionPatterns : MsftLeMonitorAdv (condition_type = MSFT_CONDITION_TYPE_PATTERNS) { - _count_(patterns): 8, - patterns: MsftLeMonitorAdvConditionPattern[], -} - -test MsftLeMonitorAdvConditionPatterns { - "\x1e\xfc\x0e\x03\x10\x05\x04\xaa\x01\x01\x06\x03\x00\x80\x81\x82\x83", // 1 pattern - "\x70\xfd\x13\x03\x15\x04\x02\xbb\x01\x02\x04\x03\x00\x80\x81\x06\x0f\x00\x90\x91\x92\x93", // 2 patterns -} - -packet MsftLeMonitorAdvConditionUuid : MsftLeMonitorAdv (condition_type = MSFT_CONDITION_TYPE_UUID) { - uuid_type: MsftLeMonitorAdvConditionUuidType, - _payload_, -} - -packet MsftLeMonitorAdvConditionUuid2 : MsftLeMonitorAdvConditionUuid (uuid_type = MSFT_CONDITION_UUID_TYPE_16_BIT) { - uuid2: 8[2], -} - -test MsftLeMonitorAdvConditionUuid2 { - "\x1e\xfc\x09\x03\x10\x11\x12\x13\x02\x01\x70\x71", // opcode = fc1e for Intel - "\x70\xfd\x09\x03\x10\x11\x12\x13\x02\x01\x70\x71", // opcode = fd70 for Qualcomm -} - -packet MsftLeMonitorAdvConditionUuid4 : MsftLeMonitorAdvConditionUuid (uuid_type = MSFT_CONDITION_UUID_TYPE_32_BIT) { - uuid4: 8[4], -} - -test MsftLeMonitorAdvConditionUuid4 { - "\x1e\xfc\x0b\x03\x10\x11\x12\x13\x02\x02\x70\x71\x72\x73", - "\x70\xfd\x0b\x03\x10\x11\x12\x13\x02\x02\x70\x71\x72\x73", -} - -packet MsftLeMonitorAdvConditionUuid16 : MsftLeMonitorAdvConditionUuid (uuid_type = MSFT_CONDITION_UUID_TYPE_128_BIT) { - uuid16: 8[16], -} - -test MsftLeMonitorAdvConditionUuid16 { - "\x1e\xfc\x17\x03\x10\x11\x12\x13\x02\x03\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f", - "\x70\xfd\x17\x03\x10\x11\x12\x13\x02\x03\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f", -} - -packet MsftLeCancelMonitorAdv: MsftCommand (subcommand_opcode = MSFT_LE_CANCEL_MONITOR_ADV) { - monitor_handle: 8, -} - -test MsftLeCancelMonitorAdv { - "\x1e\xfc\x02\x04\x01", // cancel handle 0x01 -} - -packet MsftLeSetAdvFilterEnable : MsftCommand (subcommand_opcode = MSFT_LE_SET_ADV_FILTER_ENABLE) { - enable: 8, -} - -test MsftLeSetAdvFilterEnable { - "\x1e\xfc\x02\x05\x01", // disable - "\x70\xfd\x02\x05\x01", // enable -} - -packet MsftCommandComplete : CommandComplete { - status: ErrorCode, - subcommand_opcode: MsftSubcommandOpcode, - _payload_, -} - -packet MsftReadSupportedFeaturesCommandComplete : MsftCommandComplete (subcommand_opcode = MSFT_READ_SUPPORTED_FEATURES) { - supported_features: 64, - _size_(prefix) : 8, - prefix: 8[], -} - -test MsftReadSupportedFeaturesCommandComplete { - "\x0e\x10\x01\x1e\xfc\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x02\x87\x80", // Msft opcode by Intel - "\x0e\x12\x01\x70\xfd\x00\x00\x1f\x00\x00\x00\x00\x00\x00\x00\x04\x4d\x53\x46\x54", // Msft opcode by Qualcomm -} - -packet MsftLeMonitorAdvCommandComplete : MsftCommandComplete (subcommand_opcode = MSFT_LE_MONITOR_ADV) { - monitor_handle: 8, -} - -test MsftLeMonitorAdvCommandComplete { - "\x0e\x06\x01\x1e\xfc\x00\x03\x05", // succeeded - "\x0e\x06\x01\x70\xfd\x01\x03\x06", // failed -} - -packet MsftLeCancelMonitorAdvCommandComplete : MsftCommandComplete (subcommand_opcode = MSFT_LE_CANCEL_MONITOR_ADV) {} - -packet MsftLeSetAdvFilterEnableCommandComplete : MsftCommandComplete (subcommand_opcode = MSFT_LE_SET_ADV_FILTER_ENABLE) {} - -enum MsftEventCode : 8 { - MSFT_RSSI_EVENT = 0x01, - MSFT_LE_MONITOR_DEVICE_EVENT = 0x02, -} - -enum MsftEventStatus : 8 { - MSFT_EVENT_STATUS_SUCCESS = 0x00, - MSFT_EVENT_STATUS_FAILURE = 0x01, -} - -// It is not possible to define MSFT Event packet by deriving `Event` packet -// because it starts with variable-length event prefix which can only be determined -// at run-time (after receiving return of MSFT Read Supported Features). -// Therefore we only define the payload which is located after the event prefix. -packet MsftEventPayload { - msft_event_code : MsftEventCode, - _payload_, -} - -packet MsftRssiEventPayload : MsftEventPayload (msft_event_code = MSFT_RSSI_EVENT) { - status: MsftEventStatus, - connection_handle: 16, - rssi: 8, -} - -test MsftRssiEventPayload { - "\x01\x00\x01\x10\xf0", // MSFT_RSSI_EVENT succeeded - "\x01\x01\x02\x02\x08", // MSFT_RSSI_EVENT failed -} - -packet MsftLeMonitorDeviceEventPayload : MsftEventPayload (msft_event_code = MSFT_LE_MONITOR_DEVICE_EVENT) { - address_type: 8, - bd_addr: Address, - monitor_handle: 8, - monitor_state: 8, -} - -test MsftLeMonitorDeviceEventPayload { - "\x02\x01\x00\x01\x02\x03\x04\x05\x10\x00", - "\x02\x02\xf0\xf1\xf2\xf3\xf4\xf5\xaa\x02", -} diff --git a/rust/Cargo.toml b/rust/Cargo.toml index c072576..2acf506 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -19,6 +19,9 @@ version = "0.1.0" edition = "2018" build="build.rs" +[features] +serde = [] + [dependencies] bytes = "1.0.1" num-bigint = "0.4.3" @@ -26,13 +29,14 @@ num-derive = "0.3.3" num-integer = "0.1.45" num-traits = "0.2.14" paste = "1.0.4" -pdl-runtime = "0.3.0" +pdl-derive = "0.4.2" +pdl-runtime = "0.4.2" pin-utils = "0.1.0" -rand = "0.9.1" +rand = "0.8.3" thiserror = "1.0.23" [build-dependencies] -pdl-compiler = "0.3.2" +pdl-compiler = "0.4.2" [lib] path="src/lib.rs" diff --git a/rust/build.rs b/rust/build.rs index 923b0aa..72236db 100644 --- a/rust/build.rs +++ b/rust/build.rs @@ -41,8 +41,6 @@ fn generate_module(in_file: &Path) { ) .expect("PDL parse failed"); let analyzed_file = pdl_compiler::analyzer::analyze(&parsed_file).expect("PDL analysis failed"); - let rust_source = pdl_compiler::backends::rust_legacy::generate(&sources, &analyzed_file); - out_file - .write_all(rust_source.as_bytes()) - .expect("Could not write to output file"); + let rust_source = pdl_compiler::backends::rust::generate(&sources, &analyzed_file, &[]); + out_file.write_all(rust_source.as_bytes()).expect("Could not write to output file"); } diff --git a/rust/src/ffi.rs b/rust/src/ffi.rs index a8fae1a..8c9eb0c 100644 --- a/rust/src/ffi.rs +++ b/rust/src/ffi.rs @@ -15,6 +15,7 @@ // TODO(b/290018030): Remove this and add proper safety comments. #![allow(clippy::undocumented_unsafe_blocks)] +use pdl_runtime::Packet; use std::convert::TryFrom; use std::mem::ManuallyDrop; use std::rc::Rc; @@ -161,7 +162,7 @@ pub unsafe extern "C" fn link_manager_ingest_hci( let lm = ManuallyDrop::new(unsafe { Rc::from_raw(lm) }); let data = unsafe { slice::from_raw_parts(data, len) }; - if let Ok(packet) = hci::Command::parse(data) { + if let Ok(packet) = hci::Command::decode_full(data) { lm.ingest_hci(packet).is_ok() } else { false @@ -190,7 +191,7 @@ pub unsafe extern "C" fn link_manager_ingest_lmp( let lm = ManuallyDrop::new(unsafe { Rc::from_raw(lm) }); let data = unsafe { slice::from_raw_parts(data, len) }; - if let Ok(packet) = lmp::LmpPacket::parse(data) { + if let Ok(packet) = lmp::LmpPacket::decode_full(data) { unsafe { lm.ingest_lmp(hci::Address::from(&*from), packet).is_ok() } } else { false @@ -295,7 +296,7 @@ pub unsafe extern "C" fn link_layer_ingest_hci( let ll = Rc::get_mut(&mut ll).unwrap(); let data = unsafe { slice::from_raw_parts(data, len) }; - if let Ok(packet) = hci::Command::parse(data) { + if let Ok(packet) = hci::Command::decode_full(data) { ll.ingest_hci(packet).is_ok() } else { false @@ -324,7 +325,7 @@ pub unsafe extern "C" fn link_layer_ingest_llcp( let ll = Rc::get_mut(&mut ll).unwrap(); let data = unsafe { slice::from_raw_parts(data, len) }; - if let Ok(packet) = llcp::LlcpPacket::parse(data) { + if let Ok(packet) = llcp::LlcpPacket::decode_full(data) { ll.ingest_llcp(handle, packet).is_ok() } else { false diff --git a/rust/src/llcp/iso.rs b/rust/src/llcp/iso.rs index 70c9a8f..db440f0 100644 --- a/rust/src/llcp/iso.rs +++ b/rust/src/llcp/iso.rs @@ -14,7 +14,6 @@ use crate::ffi; use crate::packets::{hci, llcp}; -use pdl_runtime::Packet as _; use std::collections::HashMap; use std::convert::{TryFrom, TryInto}; @@ -141,10 +140,10 @@ impl CisParameters { fn new(cig_config: &CigConfig, cis_config: &CisConfig) -> CisParameters { let bn_c_to_p: u8 = cis_config .bn_c_to_p - .unwrap_or_else(|| ((cis_config.max_sdu_c_to_p + 250) / 251).try_into().unwrap()); + .unwrap_or_else(|| cis_config.max_sdu_c_to_p.div_ceil(251).try_into().unwrap()); let bn_p_to_c: u8 = cis_config .bn_p_to_c - .unwrap_or_else(|| ((cis_config.max_sdu_p_to_c + 250) / 251).try_into().unwrap()); + .unwrap_or_else(|| cis_config.max_sdu_p_to_c.div_ceil(251).try_into().unwrap()); let nse = cis_config.nse.unwrap_or(std::cmp::max(bn_c_to_p, bn_p_to_c)); let max_pdu_c_to_p = cis_config.max_pdu_c_to_p.unwrap_or(251); let max_pdu_p_to_c = cis_config.max_pdu_p_to_c.unwrap_or(251); @@ -299,7 +298,7 @@ impl IsoManager { match cis.state { // When the CIS is fully connected, disconnection is notified // with Disconnection Complete event. - CisState::Connected => self.send_hci_event(hci::DisconnectionCompleteBuilder { + CisState::Connected => self.send_hci_event(hci::DisconnectionComplete { status: hci::ErrorCode::Success, connection_handle: cis.cis_connection_handle, reason, @@ -310,7 +309,7 @@ impl IsoManager { // Similarly, when a remote CIS connection request has been accepted // by the Host, the status must be notified with LE Cis Established. CisState::PendingRsp | CisState::PendingInd => { - self.send_hci_event(hci::LeCisEstablishedV1Builder { + self.send_hci_event(hci::LeCisEstablishedV1 { status: reason, connection_handle: cis.cis_connection_handle, cig_sync_delay: 0, @@ -341,7 +340,7 @@ impl IsoManager { continue; } - self.send_hci_event(hci::LeCisEstablishedV1Builder { + self.send_hci_event(hci::LeCisEstablishedV1 { status: reason, connection_handle: cis.cis_connection_handle, cig_sync_delay: 0, @@ -416,12 +415,16 @@ impl IsoManager { }) } - fn send_hci_event>(&self, event: E) { - self.ops.send_hci_event(&event.into().encode_to_vec().unwrap()) + fn send_hci_event + pdl_runtime::Packet>(&self, event: E) { + self.ops.send_hci_event(&event.encode_to_vec().unwrap()) } - fn send_llcp_packet>(&self, acl_connection_handle: u16, packet: P) { - self.ops.send_llcp_packet(acl_connection_handle, &packet.into().encode_to_vec().unwrap()) + fn send_llcp_packet + pdl_runtime::Packet>( + &self, + acl_connection_handle: u16, + packet: P, + ) { + self.ops.send_llcp_packet(acl_connection_handle, &packet.encode_to_vec().unwrap()) } fn get_le_features(&self) -> u64 { @@ -470,7 +473,7 @@ impl IsoManager { self.send_llcp_packet( request.acl_connection_handle, - llcp::CisReqBuilder { + llcp::CisReq { cig_id: request.cig_id, cis_id: request.cis_id, phy_c_to_p: parameters.phy_c_to_p, @@ -503,15 +506,15 @@ impl IsoManager { } pub fn hci_le_set_cig_parameters(&mut self, packet: hci::LeSetCigParameters) { - let cig_id: u8 = packet.get_cig_id(); - let sdu_interval_c_to_p: u32 = packet.get_sdu_interval_c_to_p(); - let sdu_interval_p_to_c: u32 = packet.get_sdu_interval_p_to_c(); - let framed: bool = packet.get_framing() == hci::Enable::Enabled; - let max_transport_latency_c_to_p: u16 = packet.get_max_transport_latency_c_to_p(); - let max_transport_latency_p_to_c: u16 = packet.get_max_transport_latency_p_to_c(); - let cis_config: &[hci::CisParametersConfig] = packet.get_cis_config(); - - let command_complete = |status| hci::LeSetCigParametersCompleteBuilder { + let cig_id: u8 = packet.cig_id(); + let sdu_interval_c_to_p: u32 = packet.sdu_interval_c_to_p(); + let sdu_interval_p_to_c: u32 = packet.sdu_interval_p_to_c(); + let framed: bool = packet.framing() == hci::Enable::Enabled; + let max_transport_latency_c_to_p: u16 = packet.max_transport_latency_c_to_p(); + let max_transport_latency_p_to_c: u16 = packet.max_transport_latency_p_to_c(); + let cis_config: &[hci::CisParametersConfig] = packet.cis_config(); + + let command_complete = |status| hci::LeSetCigParametersComplete { status, cig_id, connection_handle: vec![], @@ -682,7 +685,7 @@ impl IsoManager { cis_connection_handles.push(cis_connection_handle); } - self.send_hci_event(hci::LeSetCigParametersCompleteBuilder { + self.send_hci_event(hci::LeSetCigParametersComplete { status: hci::ErrorCode::Success, cig_id, connection_handle: cis_connection_handles, @@ -691,16 +694,16 @@ impl IsoManager { } pub fn hci_le_set_cig_parameters_test(&mut self, packet: hci::LeSetCigParametersTest) { - let cig_id: u8 = packet.get_cig_id(); - let sdu_interval_c_to_p: u32 = packet.get_sdu_interval_c_to_p(); - let sdu_interval_p_to_c: u32 = packet.get_sdu_interval_p_to_c(); - let ft_c_to_p: u8 = packet.get_ft_c_to_p(); - let ft_p_to_c: u8 = packet.get_ft_p_to_c(); - let iso_interval: u16 = packet.get_iso_interval(); - let framed: bool = packet.get_framing() == hci::Enable::Enabled; - let cis_config: &[hci::LeCisParametersTestConfig] = packet.get_cis_config(); - - let command_complete = |status| hci::LeSetCigParametersTestCompleteBuilder { + let cig_id: u8 = packet.cig_id(); + let sdu_interval_c_to_p: u32 = packet.sdu_interval_c_to_p(); + let sdu_interval_p_to_c: u32 = packet.sdu_interval_p_to_c(); + let ft_c_to_p: u8 = packet.ft_c_to_p(); + let ft_p_to_c: u8 = packet.ft_p_to_c(); + let iso_interval: u16 = packet.iso_interval(); + let framed: bool = packet.framing() == hci::Enable::Enabled; + let cis_config: &[hci::LeCisParametersTestConfig] = packet.cis_config(); + + let command_complete = |status| hci::LeSetCigParametersTestComplete { status, cig_id, connection_handle: vec![], @@ -847,7 +850,7 @@ impl IsoManager { cis_connection_handles.push(cis_connection_handle); } - self.send_hci_event(hci::LeSetCigParametersTestCompleteBuilder { + self.send_hci_event(hci::LeSetCigParametersTestComplete { status: hci::ErrorCode::Success, cig_id, connection_handle: cis_connection_handles, @@ -856,10 +859,10 @@ impl IsoManager { } pub fn hci_le_remove_cig(&mut self, packet: hci::LeRemoveCig) { - let cig_id: u8 = packet.get_cig_id(); + let cig_id: u8 = packet.cig_id(); let command_complete = - |status| hci::LeRemoveCigCompleteBuilder { status, cig_id, num_hci_command_packets: 1 }; + |status| hci::LeRemoveCigComplete { status, cig_id, num_hci_command_packets: 1 }; // If the Host issues this command with a CIG_ID that does not exist, the // Controller shall return the error code Unknown Connection Identifier (0x02). @@ -892,11 +895,10 @@ impl IsoManager { } pub fn hci_le_create_cis(&mut self, packet: hci::LeCreateCis) { - let cis_config: &[hci::LeCreateCisConfig] = packet.get_cis_config(); + let cis_config: &[hci::LeCreateCisConfig] = packet.cis_config(); let mut cis_connection_requests: Vec = vec![]; - let command_status = - |status| hci::LeCreateCisStatusBuilder { status, num_hci_command_packets: 1 }; + let command_status = |status| hci::LeCreateCisStatus { status, num_hci_command_packets: 1 }; for cis_config in cis_config { match self.acl_connections.get(&cis_config.acl_connection_handle) { @@ -996,10 +998,10 @@ impl IsoManager { } pub fn hci_le_accept_cis_request(&mut self, packet: hci::LeAcceptCisRequest) { - let connection_handle: u16 = packet.get_connection_handle(); + let connection_handle: u16 = packet.connection_handle(); let command_status = - |status| hci::LeAcceptCisRequestStatusBuilder { status, num_hci_command_packets: 1 }; + |status| hci::LeAcceptCisRequestStatus { status, num_hci_command_packets: 1 }; // If the Peripheral’s Host issues this command with a // Connection_Handle that does not exist, or the Connection_Handle @@ -1044,20 +1046,16 @@ impl IsoManager { let acl_connection_handle = cis.acl_connection_handle.unwrap(); self.send_llcp_packet( acl_connection_handle, - llcp::CisRspBuilder { - cis_offset_min: 0, - cis_offset_max: 0xffffff, - conn_event_count: 0, - }, + llcp::CisRsp { cis_offset_min: 0, cis_offset_max: 0xffffff, conn_event_count: 0 }, ); self.send_hci_event(command_status(hci::ErrorCode::Success)) } pub fn hci_le_reject_cis_request(&mut self, packet: hci::LeRejectCisRequest) { - let connection_handle: u16 = packet.get_connection_handle(); + let connection_handle: u16 = packet.connection_handle(); - let command_complete = |status| hci::LeRejectCisRequestCompleteBuilder { + let command_complete = |status| hci::LeRejectCisRequestComplete { status, connection_handle, num_hci_command_packets: 1, @@ -1104,14 +1102,14 @@ impl IsoManager { self.cis_connections.remove(&connection_handle); // Send back LL_CIS_RSP to reject the request. - let error_code = if packet.get_reason() == hci::ErrorCode::Success { + let error_code = if packet.reason() == hci::ErrorCode::Success { hci::ErrorCode::RemoteUserTerminatedConnection } else { - packet.get_reason() + packet.reason() }; self.send_llcp_packet( acl_connection_handle, - llcp::RejectExtIndBuilder { + llcp::RejectExtInd { reject_opcode: llcp::Opcode::LlCisReq as u8, error_code: error_code as u8, }, @@ -1121,10 +1119,10 @@ impl IsoManager { } pub fn hci_le_setup_iso_data_path(&mut self, packet: hci::LeSetupIsoDataPath) { - let connection_handle: u16 = packet.get_connection_handle(); - let codec_configuration = packet.get_codec_configuration(); + let connection_handle: u16 = packet.connection_handle(); + let codec_configuration = packet.codec_configuration(); - let command_complete = |status| hci::LeSetupIsoDataPathCompleteBuilder { + let command_complete = |status| hci::LeSetupIsoDataPathComplete { status, connection_handle, num_hci_command_packets: 1, @@ -1148,15 +1146,11 @@ impl IsoManager { // Connection_Handle and direction before issuing the HCI_LE_Remove_ISO_Data_- // Path command for that Connection_Handle and direction, the Controller shall // return the error code Command Disallowed (0x0C). - if cis.iso_data_path_c_to_p.is_some() - && packet.get_data_path_direction() == c_to_p_direction - { + if cis.iso_data_path_c_to_p.is_some() && packet.data_path_direction() == c_to_p_direction { println!("C->P ISO data path already configured for ({}, {})", cis.cig_id, cis.cis_id); return self.send_hci_event(command_complete(hci::ErrorCode::CommandDisallowed)); } - if cis.iso_data_path_p_to_c.is_some() - && packet.get_data_path_direction() == p_to_c_direction - { + if cis.iso_data_path_p_to_c.is_some() && packet.data_path_direction() == p_to_c_direction { println!("P->C ISO data path already configured for ({}, {})", cis.cig_id, cis.cis_id); return self.send_hci_event(command_complete(hci::ErrorCode::CommandDisallowed)); } @@ -1182,7 +1176,7 @@ impl IsoManager { // If the Host issues this command with Codec_Configuration_Length non-zero // and Codec_ID set to transparent air mode, the Controller shall return the error // code Invalid HCI Command Parameters (0x12). - if !codec_configuration.is_empty() && packet.get_codec_id() == 0x3 { + if !codec_configuration.is_empty() && packet.codec_id() == 0x3 { println!("Codec Configuration is not empty and Codec ID is for transparent air mode"); return self .send_hci_event(command_complete(hci::ErrorCode::InvalidHciCommandParameters)); @@ -1193,7 +1187,7 @@ impl IsoManager { // Connection_Handle parameter, the Controller shall return the error code // Invalid HCI Command Parameters (0x12). - if packet.get_data_path_direction() == c_to_p_direction { + if packet.data_path_direction() == c_to_p_direction { cis.iso_data_path_c_to_p = Some(IsoDataPath::Hci); } else { cis.iso_data_path_p_to_c = Some(IsoDataPath::Hci); @@ -1203,11 +1197,11 @@ impl IsoManager { } pub fn hci_le_remove_iso_data_path(&mut self, packet: hci::LeRemoveIsoDataPath) { - let connection_handle: u16 = packet.get_connection_handle(); - let remove_input_data_path = packet.get_remove_input_data_path() != 0; - let remove_output_data_path = packet.get_remove_output_data_path() != 0; + let connection_handle: u16 = packet.connection_handle(); + let remove_input_data_path = packet.remove_input_data_path() != 0; + let remove_output_data_path = packet.remove_output_data_path() != 0; - let command_complete = |status| hci::LeRemoveIsoDataPathCompleteBuilder { + let command_complete = |status| hci::LeRemoveIsoDataPathComplete { status, connection_handle, num_hci_command_packets: 1, @@ -1250,9 +1244,8 @@ impl IsoManager { } pub fn hci_disconnect(&mut self, packet: hci::Disconnect) { - let connection_handle: u16 = packet.get_connection_handle(); - let command_status = - |status| hci::DisconnectStatusBuilder { status, num_hci_command_packets: 1 }; + let connection_handle: u16 = packet.connection_handle(); + let command_status = |status| hci::DisconnectStatus { status, num_hci_command_packets: 1 }; let Some(cis) = self.cis_connections.get(&connection_handle).cloned() else { return self.send_hci_event(command_status(hci::ErrorCode::UnknownConnection)); @@ -1282,15 +1275,15 @@ impl IsoManager { self.send_llcp_packet( cis.acl_connection_handle.unwrap(), - llcp::CisTerminateIndBuilder { + llcp::CisTerminateInd { cig_id: cis.cig_id, cis_id: cis.cis_id, - error_code: packet.get_reason().into(), + error_code: packet.reason().into(), }, ); self.send_hci_event(command_status(hci::ErrorCode::Success)); - self.send_hci_event(hci::DisconnectionCompleteBuilder { + self.send_hci_event(hci::DisconnectionComplete { status: hci::ErrorCode::Success, connection_handle, reason: hci::ErrorCode::ConnectionTerminatedByLocalHost, @@ -1302,8 +1295,8 @@ impl IsoManager { self.cis_connections.insert( cis_connection_handle, Cis { - cig_id: packet.get_cig_id(), - cis_id: packet.get_cis_id(), + cig_id: packet.cig_id(), + cis_id: packet.cis_id(), role: hci::Role::Peripheral, acl_connection_handle: Some(acl_connection_handle), cis_connection_handle, @@ -1313,31 +1306,31 @@ impl IsoManager { parameters: Some(CisParameters { cig_sync_delay: 0, cis_sync_delay: 0, - phy_c_to_p: packet.get_phy_c_to_p(), - phy_p_to_c: packet.get_phy_p_to_c(), - nse: packet.get_nse(), - bn_c_to_p: packet.get_bn_c_to_p(), - bn_p_to_c: packet.get_bn_p_to_c(), - ft_c_to_p: packet.get_ft_c_to_p(), - ft_p_to_c: packet.get_ft_p_to_c(), - max_pdu_c_to_p: packet.get_max_pdu_c_to_p(), - max_pdu_p_to_c: packet.get_max_pdu_p_to_c(), - max_sdu_c_to_p: packet.get_max_sdu_c_to_p(), - max_sdu_p_to_c: packet.get_max_sdu_p_to_c(), - sdu_interval_c_to_p: packet.get_sdu_interval_c_to_p(), - sdu_interval_p_to_c: packet.get_sdu_interval_p_to_c(), - iso_interval: packet.get_iso_interval(), - sub_interval: packet.get_sub_interval(), - framed: packet.get_framed() != 0, + phy_c_to_p: packet.phy_c_to_p(), + phy_p_to_c: packet.phy_p_to_c(), + nse: packet.nse(), + bn_c_to_p: packet.bn_c_to_p(), + bn_p_to_c: packet.bn_p_to_c(), + ft_c_to_p: packet.ft_c_to_p(), + ft_p_to_c: packet.ft_p_to_c(), + max_pdu_c_to_p: packet.max_pdu_c_to_p(), + max_pdu_p_to_c: packet.max_pdu_p_to_c(), + max_sdu_c_to_p: packet.max_sdu_c_to_p(), + max_sdu_p_to_c: packet.max_sdu_p_to_c(), + sdu_interval_c_to_p: packet.sdu_interval_c_to_p(), + sdu_interval_p_to_c: packet.sdu_interval_p_to_c(), + iso_interval: packet.iso_interval(), + sub_interval: packet.sub_interval(), + framed: packet.framed() != 0, }), }, ); - self.send_hci_event(hci::LeCisRequestBuilder { + self.send_hci_event(hci::LeCisRequest { acl_connection_handle, cis_connection_handle, - cig_id: packet.get_cig_id(), - cis_id: packet.get_cis_id(), + cig_id: packet.cig_id(), + cis_id: packet.cis_id(), }) } @@ -1356,7 +1349,7 @@ impl IsoManager { let parameters = cis.parameters.as_ref().unwrap(); self.send_llcp_packet( acl_connection_handle, - llcp::CisIndBuilder { + llcp::CisInd { aa: 0, cis_offset: 0, cig_sync_delay: parameters.cig_sync_delay, @@ -1364,7 +1357,7 @@ impl IsoManager { conn_event_count: 0, }, ); - self.send_hci_event(hci::LeCisEstablishedV1Builder { + self.send_hci_event(hci::LeCisEstablishedV1 { status: hci::ErrorCode::Success, connection_handle: cis_connection_handle, cig_sync_delay: parameters.cig_sync_delay, @@ -1390,7 +1383,7 @@ impl IsoManager { } pub fn ll_reject_ext_ind(&mut self, acl_connection_handle: u16, packet: llcp::RejectExtInd) { - if packet.get_reject_opcode() != llcp::Opcode::LlCisReq as u8 { + if packet.reject_opcode() != llcp::Opcode::LlCisReq as u8 { return; } @@ -1404,7 +1397,7 @@ impl IsoManager { let cis = self.cis_connections.get_mut(&cis_connection_handle).unwrap(); cis.state = CisState::Configuration; cis.parameters = None; - self.send_hci_event(hci::LeCisEstablishedV1Builder { + self.send_hci_event(hci::LeCisEstablishedV1 { status: hci::ErrorCode::RemoteUserTerminatedConnection, connection_handle: cis_connection_handle, cig_sync_delay: 0, @@ -1440,12 +1433,12 @@ impl IsoManager { self.cis_connections.entry(cis_connection_handle).and_modify(|cis| { cis.state = CisState::Connected; let parameters = cis.parameters.as_mut().unwrap(); - parameters.cig_sync_delay = packet.get_cig_sync_delay(); - parameters.cis_sync_delay = packet.get_cis_sync_delay(); + parameters.cig_sync_delay = packet.cig_sync_delay(); + parameters.cis_sync_delay = packet.cis_sync_delay(); }); let cis = self.cis_connections.get(&cis_connection_handle).unwrap(); let parameters = cis.parameters.as_ref().unwrap(); - self.send_hci_event(hci::LeCisEstablishedV1Builder { + self.send_hci_event(hci::LeCisEstablishedV1 { status: hci::ErrorCode::Success, connection_handle: cis_connection_handle, cig_sync_delay: parameters.cig_sync_delay, @@ -1475,15 +1468,15 @@ impl IsoManager { ) { let cis_connection_handle = self.get_cis_connection_handle(|cis| { cis.acl_connection_handle == Some(acl_connection_handle) - && cis.cig_id == packet.get_cig_id() - && cis.cis_id == packet.get_cis_id() + && cis.cig_id == packet.cig_id() + && cis.cis_id == packet.cis_id() }); if let Some(cis_connection_handle) = cis_connection_handle { - self.send_hci_event(hci::DisconnectionCompleteBuilder { + self.send_hci_event(hci::DisconnectionComplete { status: hci::ErrorCode::Success, connection_handle: cis_connection_handle, - reason: hci::ErrorCode::try_from(packet.get_error_code()).unwrap(), + reason: hci::ErrorCode::try_from(packet.error_code()).unwrap(), }); self.cis_connections.remove(&cis_connection_handle); } else { @@ -1504,7 +1497,7 @@ fn iso_interval( ) -> Option { if framed { let iso_interval = std::cmp::max(sdu_interval_c_to_p, sdu_interval_p_to_c); - Some(((iso_interval + 1249) / 1250) as u16) + Some(iso_interval.div_ceil(1250) as u16) } else { // Unframed PDUs shall only be used when the ISO_Interval is equal to // or an integer multiple of the SDU_Interval and a constant time offset diff --git a/rust/src/llcp/manager.rs b/rust/src/llcp/manager.rs index 4291ec0..5d78a03 100644 --- a/rust/src/llcp/manager.rs +++ b/rust/src/llcp/manager.rs @@ -85,15 +85,15 @@ impl LinkLayer { pub fn ingest_hci(&mut self, packet: hci::Command) -> Result<(), LinkLayerError> { use hci::CommandChild::*; match packet.specialize() { - Disconnect(packet) => self.iso.hci_disconnect(packet), - LeSetCigParameters(packet) => self.iso.hci_le_set_cig_parameters(packet), - LeSetCigParametersTest(packet) => self.iso.hci_le_set_cig_parameters_test(packet), - LeCreateCis(packet) => self.iso.hci_le_create_cis(packet), - LeRemoveCig(packet) => self.iso.hci_le_remove_cig(packet), - LeAcceptCisRequest(packet) => self.iso.hci_le_accept_cis_request(packet), - LeRejectCisRequest(packet) => self.iso.hci_le_reject_cis_request(packet), - LeSetupIsoDataPath(packet) => self.iso.hci_le_setup_iso_data_path(packet), - LeRemoveIsoDataPath(packet) => self.iso.hci_le_remove_iso_data_path(packet), + Ok(Disconnect(packet)) => self.iso.hci_disconnect(packet), + Ok(LeSetCigParameters(packet)) => self.iso.hci_le_set_cig_parameters(packet), + Ok(LeSetCigParametersTest(packet)) => self.iso.hci_le_set_cig_parameters_test(packet), + Ok(LeCreateCis(packet)) => self.iso.hci_le_create_cis(packet), + Ok(LeRemoveCig(packet)) => self.iso.hci_le_remove_cig(packet), + Ok(LeAcceptCisRequest(packet)) => self.iso.hci_le_accept_cis_request(packet), + Ok(LeRejectCisRequest(packet)) => self.iso.hci_le_reject_cis_request(packet), + Ok(LeSetupIsoDataPath(packet)) => self.iso.hci_le_setup_iso_data_path(packet), + Ok(LeRemoveIsoDataPath(packet)) => self.iso.hci_le_remove_iso_data_path(packet), _ => Err(LinkLayerError::UnhandledHciPacket)?, }; Ok(()) @@ -106,16 +106,18 @@ impl LinkLayer { ) -> Result<(), LinkLayerError> { use llcp::LlcpPacketChild::*; match packet.specialize() { - RejectExtInd(packet) => match llcp::Opcode::try_from(packet.get_reject_opcode()) { + Ok(RejectExtInd(packet)) => match llcp::Opcode::try_from(packet.reject_opcode()) { Ok(llcp::Opcode::LlCisReq) => { self.iso.ll_reject_ext_ind(acl_connection_handle, packet) } _ => unreachable!(), }, - CisReq(packet) => self.iso.ll_cis_req(acl_connection_handle, packet), - CisRsp(packet) => self.iso.ll_cis_rsp(acl_connection_handle, packet), - CisInd(packet) => self.iso.ll_cis_ind(acl_connection_handle, packet), - CisTerminateInd(packet) => self.iso.ll_cis_terminate_ind(acl_connection_handle, packet), + Ok(CisReq(packet)) => self.iso.ll_cis_req(acl_connection_handle, packet), + Ok(CisRsp(packet)) => self.iso.ll_cis_rsp(acl_connection_handle, packet), + Ok(CisInd(packet)) => self.iso.ll_cis_ind(acl_connection_handle, packet), + Ok(CisTerminateInd(packet)) => { + self.iso.ll_cis_terminate_ind(acl_connection_handle, packet) + } _ => unimplemented!(), } Ok(()) diff --git a/rust/src/lmp/manager.rs b/rust/src/lmp/manager.rs index c6dc39c..d1d4bdc 100644 --- a/rust/src/lmp/manager.rs +++ b/rust/src/lmp/manager.rs @@ -133,110 +133,103 @@ impl LinkManager { status: hci::ErrorCode, ) -> Result<(), LinkManagerError> { use hci::CommandChild::*; - #[allow(unused_imports)] - use Option::None; // Overwrite `None` variant of `Child` enum let event: hci::Event = match command.specialize() { - LinkKeyRequestReply(packet) => hci::LinkKeyRequestReplyCompleteBuilder { + Ok(LinkKeyRequestReply(packet)) => hci::LinkKeyRequestReplyComplete { status, - bd_addr: packet.get_bd_addr(), + bd_addr: packet.bd_addr(), num_hci_command_packets, } - .into(), - LinkKeyRequestNegativeReply(packet) => { - hci::LinkKeyRequestNegativeReplyCompleteBuilder { - status, - bd_addr: packet.get_bd_addr(), - num_hci_command_packets, - } - .into() + .try_into(), + Ok(LinkKeyRequestNegativeReply(packet)) => hci::LinkKeyRequestNegativeReplyComplete { + status, + bd_addr: packet.bd_addr(), + num_hci_command_packets, } - PinCodeRequestReply(packet) => hci::PinCodeRequestReplyCompleteBuilder { + .try_into(), + Ok(PinCodeRequestReply(packet)) => hci::PinCodeRequestReplyComplete { status, - bd_addr: packet.get_bd_addr(), + bd_addr: packet.bd_addr(), num_hci_command_packets, } - .into(), - PinCodeRequestNegativeReply(packet) => { - hci::PinCodeRequestNegativeReplyCompleteBuilder { - status, - bd_addr: packet.get_bd_addr(), - num_hci_command_packets, - } - .into() + .try_into(), + Ok(PinCodeRequestNegativeReply(packet)) => hci::PinCodeRequestNegativeReplyComplete { + status, + bd_addr: packet.bd_addr(), + num_hci_command_packets, } - IoCapabilityRequestReply(packet) => hci::IoCapabilityRequestReplyCompleteBuilder { + .try_into(), + Ok(IoCapabilityRequestReply(packet)) => hci::IoCapabilityRequestReplyComplete { status, - bd_addr: packet.get_bd_addr(), + bd_addr: packet.bd_addr(), num_hci_command_packets, } - .into(), - IoCapabilityRequestNegativeReply(packet) => { - hci::IoCapabilityRequestNegativeReplyCompleteBuilder { + .try_into(), + Ok(IoCapabilityRequestNegativeReply(packet)) => { + hci::IoCapabilityRequestNegativeReplyComplete { status, - bd_addr: packet.get_bd_addr(), + bd_addr: packet.bd_addr(), num_hci_command_packets, } - .into() + .try_into() } - UserConfirmationRequestReply(packet) => { - hci::UserConfirmationRequestReplyCompleteBuilder { - status, - bd_addr: packet.get_bd_addr(), - num_hci_command_packets, - } - .into() + Ok(UserConfirmationRequestReply(packet)) => hci::UserConfirmationRequestReplyComplete { + status, + bd_addr: packet.bd_addr(), + num_hci_command_packets, } - UserConfirmationRequestNegativeReply(packet) => { - hci::UserConfirmationRequestNegativeReplyCompleteBuilder { + .try_into(), + Ok(UserConfirmationRequestNegativeReply(packet)) => { + hci::UserConfirmationRequestNegativeReplyComplete { status, - bd_addr: packet.get_bd_addr(), + bd_addr: packet.bd_addr(), num_hci_command_packets, } - .into() + .try_into() } - UserPasskeyRequestReply(packet) => hci::UserPasskeyRequestReplyCompleteBuilder { + Ok(UserPasskeyRequestReply(packet)) => hci::UserPasskeyRequestReplyComplete { status, - bd_addr: packet.get_bd_addr(), + bd_addr: packet.bd_addr(), num_hci_command_packets, } - .into(), - UserPasskeyRequestNegativeReply(packet) => { - hci::UserPasskeyRequestNegativeReplyCompleteBuilder { + .try_into(), + Ok(UserPasskeyRequestNegativeReply(packet)) => { + hci::UserPasskeyRequestNegativeReplyComplete { status, - bd_addr: packet.get_bd_addr(), + bd_addr: packet.bd_addr(), num_hci_command_packets, } - .into() + .try_into() } - RemoteOobDataRequestReply(packet) => hci::RemoteOobDataRequestReplyCompleteBuilder { + Ok(RemoteOobDataRequestReply(packet)) => hci::RemoteOobDataRequestReplyComplete { status, - bd_addr: packet.get_bd_addr(), + bd_addr: packet.bd_addr(), num_hci_command_packets, } - .into(), - RemoteOobDataRequestNegativeReply(packet) => { - hci::RemoteOobDataRequestNegativeReplyCompleteBuilder { + .try_into(), + Ok(RemoteOobDataRequestNegativeReply(packet)) => { + hci::RemoteOobDataRequestNegativeReplyComplete { status, - bd_addr: packet.get_bd_addr(), + bd_addr: packet.bd_addr(), num_hci_command_packets, } - .into() + .try_into() } - SendKeypressNotification(packet) => hci::SendKeypressNotificationCompleteBuilder { + Ok(SendKeypressNotification(packet)) => hci::SendKeypressNotificationComplete { status, - bd_addr: packet.get_bd_addr(), + bd_addr: packet.bd_addr(), num_hci_command_packets, } - .into(), - AuthenticationRequested(_) => { - hci::AuthenticationRequestedStatusBuilder { status, num_hci_command_packets }.into() + .try_into(), + Ok(AuthenticationRequested(_)) => { + hci::AuthenticationRequestedStatus { status, num_hci_command_packets }.try_into() } - SetConnectionEncryption(_) => { - hci::SetConnectionEncryptionStatusBuilder { status, num_hci_command_packets }.into() + Ok(SetConnectionEncryption(_)) => { + hci::SetConnectionEncryptionStatus { status, num_hci_command_packets }.try_into() } _ => return Err(LinkManagerError::UnhandledHciPacket), - }; + } + .expect("failed to serialize response event"); self.ops.send_hci_event(&event.encode_to_vec().unwrap()); Ok(()) } @@ -322,17 +315,15 @@ impl procedure::Context for LinkContext { } } - fn send_hci_event>(&self, event: E) { + fn send_hci_event + pdl_runtime::Packet>(&self, event: E) { if let Some(manager) = self.manager.upgrade() { - manager.ops.send_hci_event(&event.into().encode_to_vec().unwrap()) + manager.ops.send_hci_event(&event.encode_to_vec().unwrap()) } } - fn send_lmp_packet>(&self, packet: P) { + fn send_lmp_packet + pdl_runtime::Packet>(&self, packet: P) { if let Some(manager) = self.manager.upgrade() { - manager - .ops - .send_lmp_packet(self.peer_address(), &packet.into().encode_to_vec().unwrap()) + manager.ops.send_lmp_packet(self.peer_address(), &packet.encode_to_vec().unwrap()) } } diff --git a/rust/src/lmp/procedure/authentication.rs b/rust/src/lmp/procedure/authentication.rs index 6ed07d2..25a92bb 100644 --- a/rust/src/lmp/procedure/authentication.rs +++ b/rust/src/lmp/procedure/authentication.rs @@ -25,7 +25,7 @@ pub async fn send_challenge( _link_key: [u8; 16], ) -> Result<(), ()> { let random_number = [0; 16]; - ctx.send_lmp_packet(lmp::AuRandBuilder { transaction_id, random_number }.build()); + ctx.send_lmp_packet(lmp::AuRand { transaction_id, random_number }); match ctx.receive_lmp_packet::>().await { Either::Left(_response) => Ok(()), @@ -34,53 +34,44 @@ pub async fn send_challenge( } pub async fn receive_challenge(ctx: &impl Context, _link_key: [u8; 16]) { - let _random_number = *ctx.receive_lmp_packet::().await.get_random_number(); - ctx.send_lmp_packet(lmp::SresBuilder { transaction_id: 0, authentication_rsp: [0; 4] }.build()); + let _random_number = *ctx.receive_lmp_packet::().await.random_number(); + ctx.send_lmp_packet(lmp::Sres { transaction_id: 0, authentication_rsp: [0; 4] }); } pub async fn initiate(ctx: &impl Context) { let _ = ctx.receive_hci_command::().await; - ctx.send_hci_event( - hci::AuthenticationRequestedStatusBuilder { - num_hci_command_packets, - status: hci::ErrorCode::Success, - } - .build(), - ); + ctx.send_hci_event(hci::AuthenticationRequestedStatus { + num_hci_command_packets, + status: hci::ErrorCode::Success, + }); - ctx.send_hci_event(hci::LinkKeyRequestBuilder { bd_addr: ctx.peer_address() }.build()); + ctx.send_hci_event(hci::LinkKeyRequest { bd_addr: ctx.peer_address() }); let status = match ctx .receive_hci_command::>() .await { Either::Left(_reply) => { - ctx.send_hci_event( - hci::LinkKeyRequestReplyCompleteBuilder { - num_hci_command_packets, - status: hci::ErrorCode::Success, - bd_addr: ctx.peer_address(), - } - .build(), - ); + ctx.send_hci_event(hci::LinkKeyRequestReplyComplete { + num_hci_command_packets, + status: hci::ErrorCode::Success, + bd_addr: ctx.peer_address(), + }); // Send the initial challenge to determine if the remote device has saved the link key, // or deleted the bond. The authentication request fails with error PIN_OR_KEY_MISSING // if the remote rejects the challenge. - match send_challenge(ctx, 0, *_reply.get_link_key()).await { + match send_challenge(ctx, 0, *_reply.link_key()).await { Err(_) => hci::ErrorCode::PinOrKeyMissing, Ok(_) => hci::ErrorCode::Success, } } Either::Right(_) => { - ctx.send_hci_event( - hci::LinkKeyRequestNegativeReplyCompleteBuilder { - num_hci_command_packets, - status: hci::ErrorCode::Success, - bd_addr: ctx.peer_address(), - } - .build(), - ); + ctx.send_hci_event(hci::LinkKeyRequestNegativeReplyComplete { + num_hci_command_packets, + status: hci::ErrorCode::Success, + bd_addr: ctx.peer_address(), + }); let result = if features::supported_on_both_page1( ctx, @@ -100,9 +91,10 @@ pub async fn initiate(ctx: &impl Context) { } }; - ctx.send_hci_event( - hci::AuthenticationCompleteBuilder { status, connection_handle: ctx.peer_handle() }.build(), - ); + ctx.send_hci_event(hci::AuthenticationComplete { + status, + connection_handle: ctx.peer_handle(), + }); } pub async fn respond(ctx: &impl Context) { @@ -112,7 +104,7 @@ pub async fn respond(ctx: &impl Context) { { Either::Left(_random_number) => { // Request the Link Key from the host stack. - ctx.send_hci_event(hci::LinkKeyRequestBuilder { bd_addr: ctx.peer_address() }.build()); + ctx.send_hci_event(hci::LinkKeyRequest { bd_addr: ctx.peer_address() }); match ctx .receive_hci_command::>() @@ -120,44 +112,41 @@ pub async fn respond(ctx: &impl Context) { { Either::Left(_reply) => { ctx.send_hci_event( - hci::LinkKeyRequestReplyCompleteBuilder { + hci::LinkKeyRequestReplyComplete { num_hci_command_packets, status: hci::ErrorCode::Success, bd_addr: ctx.peer_address(), } - .build(), ); // TODO: Resolve authentication challenge // Currently the Link Key is always considered valid. // Send the expected LMP_SRES response. ctx.send_lmp_packet( - lmp::SresBuilder { + lmp::Sres { transaction_id: 0, authentication_rsp: [0; 4] } - .build() ); // Authentication is successul at this point. } Either::Right(_) => { ctx.send_hci_event( - hci::LinkKeyRequestNegativeReplyCompleteBuilder { + hci::LinkKeyRequestNegativeReplyComplete { num_hci_command_packets, status: hci::ErrorCode::Success, bd_addr: ctx.peer_address(), } - .build(), ); // Respond with LMP_NOT_ACCEPTED to indicate that the // Link Key is missing. - ctx.send_lmp_packet(lmp::NotAcceptedBuilder { + ctx.send_lmp_packet(lmp::NotAccepted { not_accepted_opcode: lmp::Opcode::AuRand, error_code: hci::ErrorCode::PinOrKeyMissing as u8, transaction_id: 0 - }.build()) + }) } } } diff --git a/rust/src/lmp/procedure/encryption.rs b/rust/src/lmp/procedure/encryption.rs index 573ef35..7be8d0b 100644 --- a/rust/src/lmp/procedure/encryption.rs +++ b/rust/src/lmp/procedure/encryption.rs @@ -25,99 +25,83 @@ use hci::LMPFeaturesPage2Bits::SecureConnectionsControllerSupport; pub async fn initiate(ctx: &impl Context) { // TODO: handle turn off let _ = ctx.receive_hci_command::().await; - ctx.send_hci_event( - hci::SetConnectionEncryptionStatusBuilder { - num_hci_command_packets, - status: hci::ErrorCode::Success, - } - .build(), - ); + ctx.send_hci_event(hci::SetConnectionEncryptionStatus { + num_hci_command_packets, + status: hci::ErrorCode::Success, + }); // TODO: handle failure let _ = ctx - .send_accepted_lmp_packet( - lmp::EncryptionModeReqBuilder { transaction_id: 0, encryption_mode: 0x1 }.build(), - ) + .send_accepted_lmp_packet(lmp::EncryptionModeReq { + transaction_id: 0, + encryption_mode: 0x1, + }) .await; // TODO: handle failure let _ = ctx - .send_accepted_lmp_packet( - lmp::EncryptionKeySizeReqBuilder { transaction_id: 0, key_size: 16 }.build(), - ) + .send_accepted_lmp_packet(lmp::EncryptionKeySizeReq { transaction_id: 0, key_size: 16 }) .await; // TODO: handle failure let _ = ctx - .send_accepted_lmp_packet( - lmp::StartEncryptionReqBuilder { transaction_id: 0, random_number: [0; 16] }.build(), - ) + .send_accepted_lmp_packet(lmp::StartEncryptionReq { + transaction_id: 0, + random_number: [0; 16], + }) .await; let aes_ccm = features::supported_on_both_page1(ctx, SecureConnectionsHostSupport).await && features::supported_on_both_page2(ctx, SecureConnectionsControllerSupport).await; - ctx.send_hci_event( - hci::EncryptionChangeBuilder { - status: hci::ErrorCode::Success, - connection_handle: ctx.peer_handle(), - encryption_enabled: if aes_ccm { - hci::EncryptionEnabled::BrEdrAesCcm - } else { - hci::EncryptionEnabled::On - }, - } - .build(), - ); + ctx.send_hci_event(hci::EncryptionChange { + status: hci::ErrorCode::Success, + connection_handle: ctx.peer_handle(), + encryption_enabled: if aes_ccm { + hci::EncryptionEnabled::BrEdrAesCcm + } else { + hci::EncryptionEnabled::On + }, + }); } pub async fn respond(ctx: &impl Context) { // TODO: handle let _ = ctx.receive_lmp_packet::().await; - ctx.send_lmp_packet( - lmp::AcceptedBuilder { transaction_id: 0, accepted_opcode: lmp::Opcode::EncryptionModeReq } - .build(), - ); + ctx.send_lmp_packet(lmp::Accepted { + transaction_id: 0, + accepted_opcode: lmp::Opcode::EncryptionModeReq, + }); let _ = ctx.receive_lmp_packet::().await; - ctx.send_lmp_packet( - lmp::AcceptedBuilder { - transaction_id: 0, - accepted_opcode: lmp::Opcode::EncryptionKeySizeReq, - } - .build(), - ); + ctx.send_lmp_packet(lmp::Accepted { + transaction_id: 0, + accepted_opcode: lmp::Opcode::EncryptionKeySizeReq, + }); let _ = ctx.receive_lmp_packet::().await; - ctx.send_lmp_packet( - lmp::AcceptedBuilder { - transaction_id: 0, - accepted_opcode: lmp::Opcode::StartEncryptionReq, - } - .build(), - ); + ctx.send_lmp_packet(lmp::Accepted { + transaction_id: 0, + accepted_opcode: lmp::Opcode::StartEncryptionReq, + }); let aes_ccm = features::supported_on_both_page1(ctx, SecureConnectionsHostSupport).await && features::supported_on_both_page2(ctx, SecureConnectionsControllerSupport).await; - ctx.send_hci_event( - hci::EncryptionChangeBuilder { - status: hci::ErrorCode::Success, - connection_handle: ctx.peer_handle(), - encryption_enabled: if aes_ccm { - hci::EncryptionEnabled::BrEdrAesCcm - } else { - hci::EncryptionEnabled::On - }, - } - .build(), - ); + ctx.send_hci_event(hci::EncryptionChange { + status: hci::ErrorCode::Success, + connection_handle: ctx.peer_handle(), + encryption_enabled: if aes_ccm { + hci::EncryptionEnabled::BrEdrAesCcm + } else { + hci::EncryptionEnabled::On + }, + }); } #[cfg(test)] mod tests { - use super::initiate; - use super::respond; + use super::{initiate, respond}; use crate::lmp::procedure::Context; use crate::lmp::test::{sequence, TestContext}; diff --git a/rust/src/lmp/procedure/features.rs b/rust/src/lmp/procedure/features.rs index 6499313..8468bea 100644 --- a/rust/src/lmp/procedure/features.rs +++ b/rust/src/lmp/procedure/features.rs @@ -18,34 +18,26 @@ use crate::lmp::procedure::Context; use crate::packets::lmp; pub async fn initiate(ctx: &impl Context, features_page: u8) -> u64 { - ctx.send_lmp_packet( - lmp::FeaturesReqExtBuilder { - transaction_id: 0, - features_page, - max_supported_page: 1, - extended_features: ctx.extended_features(features_page).to_le_bytes(), - } - .build(), - ); + ctx.send_lmp_packet(lmp::FeaturesReqExt { + transaction_id: 0, + features_page, + max_supported_page: 1, + extended_features: ctx.extended_features(features_page).to_le_bytes(), + }); - u64::from_le_bytes( - *ctx.receive_lmp_packet::().await.get_extended_features(), - ) + u64::from_le_bytes(*ctx.receive_lmp_packet::().await.extended_features()) } pub async fn respond(ctx: &impl Context) { let req = ctx.receive_lmp_packet::().await; - let features_page = req.get_features_page(); + let features_page = req.features_page(); - ctx.send_lmp_packet( - lmp::FeaturesResExtBuilder { - transaction_id: 0, - features_page, - max_supported_page: 1, - extended_features: ctx.extended_features(features_page).to_le_bytes(), - } - .build(), - ); + ctx.send_lmp_packet(lmp::FeaturesResExt { + transaction_id: 0, + features_page, + max_supported_page: 1, + extended_features: ctx.extended_features(features_page).to_le_bytes(), + }); } async fn supported_on_both_page(ctx: &impl Context, page_number: u8, feature_mask: u64) -> bool { diff --git a/rust/src/lmp/procedure/legacy_pairing.rs b/rust/src/lmp/procedure/legacy_pairing.rs index bb30c3f..4f7e87f 100644 --- a/rust/src/lmp/procedure/legacy_pairing.rs +++ b/rust/src/lmp/procedure/legacy_pairing.rs @@ -20,27 +20,22 @@ use crate::packets::{hci, lmp}; use crate::num_hci_command_packets; pub async fn initiate(ctx: &impl Context) -> Result<(), ()> { - ctx.send_hci_event(hci::PinCodeRequestBuilder { bd_addr: ctx.peer_address() }.build()); + ctx.send_hci_event(hci::PinCodeRequest { bd_addr: ctx.peer_address() }); let _pin_code = ctx.receive_hci_command::().await; - ctx.send_hci_event( - hci::PinCodeRequestReplyCompleteBuilder { - num_hci_command_packets: 1, - status: hci::ErrorCode::Success, - bd_addr: ctx.peer_address(), - } - .build(), - ); + ctx.send_hci_event(hci::PinCodeRequestReplyComplete { + num_hci_command_packets: 1, + status: hci::ErrorCode::Success, + bd_addr: ctx.peer_address(), + }); // TODO: handle result let _ = ctx - .send_accepted_lmp_packet( - lmp::InRandBuilder { transaction_id: 0, random_number: [0; 16] }.build(), - ) + .send_accepted_lmp_packet(lmp::InRand { transaction_id: 0, random_number: [0; 16] }) .await; - ctx.send_lmp_packet(lmp::CombKeyBuilder { transaction_id: 0, random_number: [0; 16] }.build()); + ctx.send_lmp_packet(lmp::CombKey { transaction_id: 0, random_number: [0; 16] }); let _ = ctx.receive_lmp_packet::().await; @@ -52,39 +47,31 @@ pub async fn initiate(ctx: &impl Context) -> Result<(), ()> { if auth_result.is_err() { return Err(()); } - ctx.send_hci_event( - hci::LinkKeyNotificationBuilder { - bd_addr: ctx.peer_address(), - key_type: hci::KeyType::Combination, - link_key, - } - .build(), - ); + ctx.send_hci_event(hci::LinkKeyNotification { + bd_addr: ctx.peer_address(), + key_type: hci::KeyType::Combination, + link_key, + }); Ok(()) } pub async fn respond(ctx: &impl Context, _request: lmp::InRand) -> Result<(), ()> { - ctx.send_hci_event(hci::PinCodeRequestBuilder { bd_addr: ctx.peer_address() }.build()); + ctx.send_hci_event(hci::PinCodeRequest { bd_addr: ctx.peer_address() }); let _pin_code = ctx.receive_hci_command::().await; - ctx.send_hci_event( - hci::PinCodeRequestReplyCompleteBuilder { - num_hci_command_packets, - status: hci::ErrorCode::Success, - bd_addr: ctx.peer_address(), - } - .build(), - ); + ctx.send_hci_event(hci::PinCodeRequestReplyComplete { + num_hci_command_packets, + status: hci::ErrorCode::Success, + bd_addr: ctx.peer_address(), + }); - ctx.send_lmp_packet( - lmp::AcceptedBuilder { transaction_id: 0, accepted_opcode: lmp::Opcode::InRand }.build(), - ); + ctx.send_lmp_packet(lmp::Accepted { transaction_id: 0, accepted_opcode: lmp::Opcode::InRand }); let _ = ctx.receive_lmp_packet::().await; - ctx.send_lmp_packet(lmp::CombKeyBuilder { transaction_id: 0, random_number: [0; 16] }.build()); + ctx.send_lmp_packet(lmp::CombKey { transaction_id: 0, random_number: [0; 16] }); // Post pairing authentication let link_key = [0; 16]; @@ -94,14 +81,11 @@ pub async fn respond(ctx: &impl Context, _request: lmp::InRand) -> Result<(), () if auth_result.is_err() { return Err(()); } - ctx.send_hci_event( - hci::LinkKeyNotificationBuilder { - bd_addr: ctx.peer_address(), - key_type: hci::KeyType::Combination, - link_key, - } - .build(), - ); + ctx.send_hci_event(hci::LinkKeyNotification { + bd_addr: ctx.peer_address(), + key_type: hci::KeyType::Combination, + link_key, + }); Ok(()) } diff --git a/rust/src/lmp/procedure/mod.rs b/rust/src/lmp/procedure/mod.rs index d73c5d3..f4fb7e6 100644 --- a/rust/src/lmp/procedure/mod.rs +++ b/rust/src/lmp/procedure/mod.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::convert::TryFrom; +use std::convert::{TryFrom, TryInto}; use std::future::Future; use std::pin::Pin; use std::task::{self, Poll}; @@ -24,8 +24,8 @@ pub trait Context { fn poll_hci_command>(&self) -> Poll; fn poll_lmp_packet>(&self) -> Poll

; - fn send_hci_event>(&self, event: E); - fn send_lmp_packet>(&self, packet: P); + fn send_hci_event + pdl_runtime::Packet>(&self, event: E); + fn send_lmp_packet + pdl_runtime::Packet>(&self, packet: P); fn peer_address(&self) -> hci::Address; fn peer_handle(&self) -> u16; @@ -44,12 +44,15 @@ pub trait Context { ReceiveFuture(Self::poll_lmp_packet, self) } - fn send_accepted_lmp_packet>( + fn send_accepted_lmp_packet + pdl_runtime::Packet>( &self, packet: P, - ) -> SendAcceptedLmpPacketFuture<'_, Self> { - let packet = packet.into(); - let opcode = packet.get_opcode(); + ) -> SendAcceptedLmpPacketFuture<'_, Self> + where +

>::Error: std::fmt::Debug, + { + let packet = packet.try_into().unwrap(); + let opcode = packet.opcode(); self.send_lmp_packet(packet); SendAcceptedLmpPacketFuture(self, opcode) @@ -89,15 +92,15 @@ where fn poll(self: Pin<&mut Self>, _cx: &mut task::Context<'_>) -> Poll { let accepted = self.0.poll_lmp_packet::(); if let Poll::Ready(accepted) = accepted { - if accepted.get_accepted_opcode() == self.1 { + if accepted.accepted_opcode() == self.1 { return Poll::Ready(Ok(())); } } let not_accepted = self.0.poll_lmp_packet::(); if let Poll::Ready(not_accepted) = not_accepted { - if not_accepted.get_not_accepted_opcode() == self.1 { - return Poll::Ready(Err(not_accepted.get_error_code())); + if not_accepted.not_accepted_opcode() == self.1 { + return Poll::Ready(Err(not_accepted.error_code())); } } diff --git a/rust/src/lmp/procedure/secure_simple_pairing.rs b/rust/src/lmp/procedure/secure_simple_pairing.rs index 5432196..1b66d39 100644 --- a/rust/src/lmp/procedure/secure_simple_pairing.rs +++ b/rust/src/lmp/procedure/secure_simple_pairing.rs @@ -94,47 +94,41 @@ fn link_key_type(auth_method: AuthenticationMethod, dh_key: DhKey) -> hci::KeyTy async fn send_public_key(ctx: &impl Context, transaction_id: u8, public_key: PublicKey) { // TODO: handle error let _ = ctx - .send_accepted_lmp_packet( - lmp::EncapsulatedHeaderBuilder { - transaction_id, - major_type: 1, - minor_type: 1, - payload_length: public_key.size() as u8, - } - .build(), - ) + .send_accepted_lmp_packet(lmp::EncapsulatedHeader { + transaction_id, + major_type: 1, + minor_type: 1, + payload_length: public_key.size() as u8, + }) .await; for chunk in public_key.as_slice().chunks(16) { // TODO: handle error let _ = ctx - .send_accepted_lmp_packet( - lmp::EncapsulatedPayloadBuilder { transaction_id, data: chunk.try_into().unwrap() } - .build(), - ) + .send_accepted_lmp_packet(lmp::EncapsulatedPayload { + transaction_id, + data: chunk.try_into().unwrap(), + }) .await; } } async fn receive_public_key(ctx: &impl Context, transaction_id: u8) -> PublicKey { let key_size: usize = - ctx.receive_lmp_packet::().await.get_payload_length().into(); + ctx.receive_lmp_packet::().await.payload_length().into(); let mut key = PublicKey::new(key_size).unwrap(); - ctx.send_lmp_packet( - lmp::AcceptedBuilder { transaction_id, accepted_opcode: lmp::Opcode::EncapsulatedHeader } - .build(), - ); + ctx.send_lmp_packet(lmp::Accepted { + transaction_id, + accepted_opcode: lmp::Opcode::EncapsulatedHeader, + }); for chunk in key.as_mut_slice().chunks_mut(16) { let payload = ctx.receive_lmp_packet::().await; - chunk.copy_from_slice(payload.get_data().as_slice()); - ctx.send_lmp_packet( - lmp::AcceptedBuilder { - transaction_id, - accepted_opcode: lmp::Opcode::EncapsulatedPayload, - } - .build(), - ); + chunk.copy_from_slice(payload.data().as_slice()); + ctx.send_lmp_packet(lmp::Accepted { + transaction_id, + accepted_opcode: lmp::Opcode::EncapsulatedPayload, + }); } key @@ -151,66 +145,52 @@ async fn receive_commitment(ctx: &impl Context, confirm: Option().await; // TODO: check pairing number - ctx.send_lmp_packet( - lmp::AcceptedBuilder { - transaction_id: 0, - accepted_opcode: lmp::Opcode::SimplePairingNumber, - } - .build(), - ); + ctx.send_lmp_packet(lmp::Accepted { + transaction_id: 0, + accepted_opcode: lmp::Opcode::SimplePairingNumber, + }); let nonce = [0; NONCE_SIZE]; // TODO: handle error - let _ = ctx - .send_accepted_lmp_packet( - lmp::SimplePairingNumberBuilder { transaction_id: 0, nonce }.build(), - ) - .await; + let _ = + ctx.send_accepted_lmp_packet(lmp::SimplePairingNumber { transaction_id: 0, nonce }).await; } async fn send_commitment(ctx: &impl Context, confirm: lmp::SimplePairingConfirm) { let commitment_value = build_commitment(ctx); - if confirm.get_commitment_value() != &commitment_value { + if confirm.commitment_value() != &commitment_value { todo!(); } let nonce = [0; NONCE_SIZE]; // TODO: handle error - let _ = ctx - .send_accepted_lmp_packet( - lmp::SimplePairingNumberBuilder { transaction_id: 0, nonce }.build(), - ) - .await; + let _ = + ctx.send_accepted_lmp_packet(lmp::SimplePairingNumber { transaction_id: 0, nonce }).await; let _pairing_number = ctx.receive_lmp_packet::().await; // TODO: check pairing number - ctx.send_lmp_packet( - lmp::AcceptedBuilder { - transaction_id: 0, - accepted_opcode: lmp::Opcode::SimplePairingNumber, - } - .build(), - ); + ctx.send_lmp_packet(lmp::Accepted { + transaction_id: 0, + accepted_opcode: lmp::Opcode::SimplePairingNumber, + }); } async fn user_confirmation_request(ctx: &impl Context) -> Result<(), ()> { - ctx.send_hci_event( - hci::UserConfirmationRequestBuilder { bd_addr: ctx.peer_address(), numeric_value: 0 } - .build(), - ); + ctx.send_hci_event(hci::UserConfirmationRequest { + bd_addr: ctx.peer_address(), + numeric_value: 0, + }); match ctx .receive_hci_command:: Result<(), ()> { { Either::Left(_) => { ctx.send_hci_event( - hci::UserConfirmationRequestReplyCompleteBuilder { + hci::UserConfirmationRequestReplyComplete { num_hci_command_packets, status: hci::ErrorCode::Success, bd_addr: ctx.peer_address(), } - .build(), ); Ok(()) } Either::Right(_) => { ctx.send_hci_event( - hci::UserConfirmationRequestNegativeReplyCompleteBuilder { + hci::UserConfirmationRequestNegativeReplyComplete { num_hci_command_packets, status: hci::ErrorCode::Success, bd_addr: ctx.peer_address(), } - .build(), ); Err(()) } @@ -245,7 +223,7 @@ async fn user_confirmation_request(ctx: &impl Context) -> Result<(), ()> { } async fn user_passkey_request(ctx: &impl Context) -> Result<(), ()> { - ctx.send_hci_event(hci::UserPasskeyRequestBuilder { bd_addr: ctx.peer_address() }.build()); + ctx.send_hci_event(hci::UserPasskeyRequest { bd_addr: ctx.peer_address() }); loop { match ctx @@ -256,36 +234,27 @@ async fn user_passkey_request(ctx: &impl Context) -> Result<(), ()> { .await { Either::Left(Either::Left(_)) => { - ctx.send_hci_event( - hci::UserPasskeyRequestReplyCompleteBuilder { - num_hci_command_packets, - status: hci::ErrorCode::Success, - bd_addr: ctx.peer_address(), - } - .build(), - ); + ctx.send_hci_event(hci::UserPasskeyRequestReplyComplete { + num_hci_command_packets, + status: hci::ErrorCode::Success, + bd_addr: ctx.peer_address(), + }); return Ok(()); } Either::Left(Either::Right(_)) => { - ctx.send_hci_event( - hci::UserPasskeyRequestNegativeReplyCompleteBuilder { - num_hci_command_packets, - status: hci::ErrorCode::Success, - bd_addr: ctx.peer_address(), - } - .build(), - ); + ctx.send_hci_event(hci::UserPasskeyRequestNegativeReplyComplete { + num_hci_command_packets, + status: hci::ErrorCode::Success, + bd_addr: ctx.peer_address(), + }); return Err(()); } Either::Right(_) => { - ctx.send_hci_event( - hci::SendKeypressNotificationCompleteBuilder { - num_hci_command_packets, - status: hci::ErrorCode::Success, - bd_addr: ctx.peer_address(), - } - .build(), - ); + ctx.send_hci_event(hci::SendKeypressNotificationComplete { + num_hci_command_packets, + status: hci::ErrorCode::Success, + bd_addr: ctx.peer_address(), + }); // TODO: send LmpKeypressNotification } } @@ -293,7 +262,7 @@ async fn user_passkey_request(ctx: &impl Context) -> Result<(), ()> { } async fn remote_oob_data_request(ctx: &impl Context) -> Result<(), ()> { - ctx.send_hci_event(hci::RemoteOobDataRequestBuilder { bd_addr: ctx.peer_address() }.build()); + ctx.send_hci_event(hci::RemoteOobDataRequest { bd_addr: ctx.peer_address() }); match ctx .receive_hci_command:: Result<(), ()> { { Either::Left(_) => { ctx.send_hci_event( - hci::RemoteOobDataRequestReplyCompleteBuilder { + hci::RemoteOobDataRequestReplyComplete { num_hci_command_packets, status: hci::ErrorCode::Success, bd_addr: ctx.peer_address(), } - .build(), ); Ok(()) } Either::Right(_) => { ctx.send_hci_event( - hci::RemoteOobDataRequestNegativeReplyCompleteBuilder { + hci::RemoteOobDataRequestNegativeReplyComplete { num_hci_command_packets, status: hci::ErrorCode::Success, bd_addr: ctx.peer_address(), } - .build(), ); Err(()) } @@ -332,7 +299,7 @@ const PASSKEY_ENTRY_REPEAT_NUMBER: usize = 20; pub async fn initiate(ctx: &impl Context) -> Result<(), ()> { let initiator = { - ctx.send_hci_event(hci::IoCapabilityRequestBuilder { bd_addr: ctx.peer_address() }.build()); + ctx.send_hci_event(hci::IoCapabilityRequest { bd_addr: ctx.peer_address() }); match ctx .receive_hci_command:: Result<(), ()> { { Either::Left(reply) => { ctx.send_hci_event( - hci::IoCapabilityRequestReplyCompleteBuilder { + hci::IoCapabilityRequestReplyComplete { num_hci_command_packets, status : hci::ErrorCode::Success, bd_addr: ctx.peer_address(), } - .build(), ); ctx.send_lmp_packet( - lmp::IoCapabilityReqBuilder { + lmp::IoCapabilityReq { transaction_id: 0, - io_capabilities: reply.get_io_capability().into(), - oob_authentication_data: reply.get_oob_present().into(), + io_capabilities: reply.io_capability().into(), + oob_authentication_data: reply.oob_present().into(), authentication_requirement: reply - .get_authentication_requirements() + .authentication_requirements() .into(), } - .build(), ); AuthenticationParams { - io_capability: reply.get_io_capability(), - oob_data_present: reply.get_oob_present(), - authentication_requirements: reply.get_authentication_requirements(), + io_capability: reply.io_capability(), + oob_data_present: reply.oob_present(), + authentication_requirements: reply.authentication_requirements(), } } Either::Right(_) => { ctx.send_hci_event( - hci::IoCapabilityRequestNegativeReplyCompleteBuilder { + hci::IoCapabilityRequestNegativeReplyComplete { num_hci_command_packets, status : hci::ErrorCode::Success, bd_addr: ctx.peer_address(), } - .build(), ); ctx.send_hci_event( - hci::SimplePairingCompleteBuilder { + hci::SimplePairingComplete { status : hci::ErrorCode::AuthenticationFailure, bd_addr: ctx.peer_address(), } - .build(), ); return Err(()); } @@ -389,22 +352,19 @@ pub async fn initiate(ctx: &impl Context) -> Result<(), ()> { let responder = { let response = ctx.receive_lmp_packet::().await; - let io_capability = hci::IoCapability::try_from(response.get_io_capabilities()).unwrap(); + let io_capability = hci::IoCapability::try_from(response.io_capabilities()).unwrap(); let oob_data_present = - hci::OobDataPresent::try_from(response.get_oob_authentication_data()).unwrap(); + hci::OobDataPresent::try_from(response.oob_authentication_data()).unwrap(); let authentication_requirements = - hci::AuthenticationRequirements::try_from(response.get_authentication_requirement()) + hci::AuthenticationRequirements::try_from(response.authentication_requirement()) .unwrap(); - ctx.send_hci_event( - hci::IoCapabilityResponseBuilder { - bd_addr: ctx.peer_address(), - io_capability, - oob_data_present, - authentication_requirements, - } - .build(), - ); + ctx.send_hci_event(hci::IoCapabilityResponse { + bd_addr: ctx.peer_address(), + io_capability, + oob_data_present, + authentication_requirements, + }); AuthenticationParams { io_capability, oob_data_present, authentication_requirements } }; @@ -436,9 +396,7 @@ pub async fn initiate(ctx: &impl Context) -> Result<(), ()> { send_commitment(ctx, confirm).await; if user_confirmation_request(ctx).await.is_err() { - ctx.send_lmp_packet( - lmp::NumericComparisonFailedBuilder { transaction_id: 0 }.build(), - ); + ctx.send_lmp_packet(lmp::NumericComparisonFailed { transaction_id: 0 }); Err(())?; } Ok(()) @@ -446,34 +404,23 @@ pub async fn initiate(ctx: &impl Context) -> Result<(), ()> { AuthenticationMethod::PasskeyEntry => { let confirm = if initiator.io_capability == hci::IoCapability::KeyboardOnly { if user_passkey_request(ctx).await.is_err() { - ctx.send_lmp_packet( - lmp::PasskeyFailedBuilder { transaction_id: 0 }.build(), - ); + ctx.send_lmp_packet(lmp::PasskeyFailed { transaction_id: 0 }); Err(())?; } - ctx.send_lmp_packet( - lmp::SimplePairingConfirmBuilder { - transaction_id: 0, - commitment_value: build_commitment(ctx), - } - .build(), - ); + ctx.send_lmp_packet(lmp::SimplePairingConfirm { + transaction_id: 0, + commitment_value: build_commitment(ctx), + }); ctx.receive_lmp_packet::().await } else { - ctx.send_hci_event( - hci::UserPasskeyNotificationBuilder { - bd_addr: ctx.peer_address(), - passkey: 0, - } - .build(), - ); - ctx.send_lmp_packet( - lmp::SimplePairingConfirmBuilder { - transaction_id: 0, - commitment_value: build_commitment(ctx), - } - .build(), - ); + ctx.send_hci_event(hci::UserPasskeyNotification { + bd_addr: ctx.peer_address(), + passkey: 0, + }); + ctx.send_lmp_packet(lmp::SimplePairingConfirm { + transaction_id: 0, + commitment_value: build_commitment(ctx), + }); match ctx .receive_lmp_packet::>() .await @@ -484,13 +431,10 @@ pub async fn initiate(ctx: &impl Context) -> Result<(), ()> { }; send_commitment(ctx, confirm).await; for _ in 1..PASSKEY_ENTRY_REPEAT_NUMBER { - ctx.send_lmp_packet( - lmp::SimplePairingConfirmBuilder { - transaction_id: 0, - commitment_value: build_commitment(ctx), - } - .build(), - ); + ctx.send_lmp_packet(lmp::SimplePairingConfirm { + transaction_id: 0, + commitment_value: build_commitment(ctx), + }); let confirm = ctx.receive_lmp_packet::().await; send_commitment(ctx, confirm).await; } @@ -501,13 +445,10 @@ pub async fn initiate(ctx: &impl Context) -> Result<(), ()> { remote_oob_data_request(ctx).await?; } - ctx.send_lmp_packet( - lmp::SimplePairingConfirmBuilder { - transaction_id: 0, - commitment_value: build_commitment(ctx), - } - .build(), - ); + ctx.send_lmp_packet(lmp::SimplePairingConfirm { + transaction_id: 0, + commitment_value: build_commitment(ctx), + }); let confirm = ctx.receive_lmp_packet::().await; send_commitment(ctx, confirm).await; Ok(()) @@ -517,13 +458,10 @@ pub async fn initiate(ctx: &impl Context) -> Result<(), ()> { .await; if result.is_err() { - ctx.send_hci_event( - hci::SimplePairingCompleteBuilder { - status: hci::ErrorCode::AuthenticationFailure, - bd_addr: ctx.peer_address(), - } - .build(), - ); + ctx.send_hci_event(hci::SimplePairingComplete { + status: hci::ErrorCode::AuthenticationFailure, + bd_addr: ctx.peer_address(), + }); return Err(()); } @@ -532,19 +470,14 @@ pub async fn initiate(ctx: &impl Context) -> Result<(), ()> { let confirmation_value = [0; CONFIRMATION_VALUE_SIZE]; let result = ctx - .send_accepted_lmp_packet( - lmp::DhkeyCheckBuilder { transaction_id: 0, confirmation_value }.build(), - ) + .send_accepted_lmp_packet(lmp::DhkeyCheck { transaction_id: 0, confirmation_value }) .await; if result.is_err() { - ctx.send_hci_event( - hci::SimplePairingCompleteBuilder { - status: hci::ErrorCode::AuthenticationFailure, - bd_addr: ctx.peer_address(), - } - .build(), - ); + ctx.send_hci_event(hci::SimplePairingComplete { + status: hci::ErrorCode::AuthenticationFailure, + bd_addr: ctx.peer_address(), + }); return Err(()); } } @@ -552,19 +485,16 @@ pub async fn initiate(ctx: &impl Context) -> Result<(), ()> { { // TODO: check dhkey let _dhkey = ctx.receive_lmp_packet::().await; - ctx.send_lmp_packet( - lmp::AcceptedBuilder { transaction_id: 0, accepted_opcode: lmp::Opcode::DhkeyCheck } - .build(), - ); + ctx.send_lmp_packet(lmp::Accepted { + transaction_id: 0, + accepted_opcode: lmp::Opcode::DhkeyCheck, + }); } - ctx.send_hci_event( - hci::SimplePairingCompleteBuilder { - status: hci::ErrorCode::Success, - bd_addr: ctx.peer_address(), - } - .build(), - ); + ctx.send_hci_event(hci::SimplePairingComplete { + status: hci::ErrorCode::Success, + bd_addr: ctx.peer_address(), + }); // Link Key Calculation let link_key = [0; 16]; @@ -575,42 +505,36 @@ pub async fn initiate(ctx: &impl Context) -> Result<(), ()> { return Err(()); } - ctx.send_hci_event( - hci::LinkKeyNotificationBuilder { - bd_addr: ctx.peer_address(), - key_type: link_key_type(auth_method, dh_key), - link_key, - } - .build(), - ); + ctx.send_hci_event(hci::LinkKeyNotification { + bd_addr: ctx.peer_address(), + key_type: link_key_type(auth_method, dh_key), + link_key, + }); Ok(()) } pub async fn respond(ctx: &impl Context, request: lmp::IoCapabilityReq) -> Result<(), ()> { let initiator = { - let io_capability = hci::IoCapability::try_from(request.get_io_capabilities()).unwrap(); + let io_capability = hci::IoCapability::try_from(request.io_capabilities()).unwrap(); let oob_data_present = - hci::OobDataPresent::try_from(request.get_oob_authentication_data()).unwrap(); + hci::OobDataPresent::try_from(request.oob_authentication_data()).unwrap(); let authentication_requirements = - hci::AuthenticationRequirements::try_from(request.get_authentication_requirement()) + hci::AuthenticationRequirements::try_from(request.authentication_requirement()) .unwrap(); - ctx.send_hci_event( - hci::IoCapabilityResponseBuilder { - bd_addr: ctx.peer_address(), - io_capability, - oob_data_present, - authentication_requirements, - } - .build(), - ); + ctx.send_hci_event(hci::IoCapabilityResponse { + bd_addr: ctx.peer_address(), + io_capability, + oob_data_present, + authentication_requirements, + }); AuthenticationParams { io_capability, oob_data_present, authentication_requirements } }; let responder = { - ctx.send_hci_event(hci::IoCapabilityRequestBuilder { bd_addr: ctx.peer_address() }.build()); + ctx.send_hci_event(hci::IoCapabilityRequest { bd_addr: ctx.peer_address() }); match ctx .receive_hci_command:: Resul { Either::Left(reply) => { ctx.send_hci_event( - hci::IoCapabilityRequestReplyCompleteBuilder { + hci::IoCapabilityRequestReplyComplete { num_hci_command_packets, status: hci::ErrorCode::Success, bd_addr: ctx.peer_address(), } - .build(), ); ctx.send_lmp_packet( - lmp::IoCapabilityResBuilder { + lmp::IoCapabilityRes { transaction_id: 0, - io_capabilities: reply.get_io_capability().into(), - oob_authentication_data: reply.get_oob_present().into(), + io_capabilities: reply.io_capability().into(), + oob_authentication_data: reply.oob_present().into(), authentication_requirement: reply - .get_authentication_requirements() + .authentication_requirements() .into(), } - .build(), ); AuthenticationParams { - io_capability: reply.get_io_capability(), - oob_data_present: reply.get_oob_present(), - authentication_requirements: reply.get_authentication_requirements(), + io_capability: reply.io_capability(), + oob_data_present: reply.oob_present(), + authentication_requirements: reply.authentication_requirements(), } } Either::Right(reply) => { ctx.send_hci_event( - hci::IoCapabilityRequestNegativeReplyCompleteBuilder { + hci::IoCapabilityRequestNegativeReplyComplete { num_hci_command_packets, status: hci::ErrorCode::Success, bd_addr: ctx.peer_address(), } - .build(), ); ctx.send_lmp_packet( - lmp::NotAcceptedExtBuilder { + lmp::NotAcceptedExt { transaction_id: 0, - error_code: reply.get_reason().into(), + error_code: reply.reason().into(), not_accepted_opcode: lmp::ExtendedOpcode::IoCapabilityReq, } - .build(), ); ctx.send_hci_event( - hci::SimplePairingCompleteBuilder { + hci::SimplePairingComplete { status: hci::ErrorCode::AuthenticationFailure, - bd_addr: reply.get_bd_addr(), + bd_addr: reply.bd_addr(), } - .build(), ); return Err(()); } @@ -703,22 +622,21 @@ pub async fn respond(ctx: &impl Context, request: lmp::IoCapabilityReq) -> Resul let confirm = ctx.receive_lmp_packet::().await; if user_passkey.is_err() { ctx.send_lmp_packet( - lmp::NotAcceptedBuilder { + lmp::NotAccepted { transaction_id: 0, not_accepted_opcode: lmp::Opcode::SimplePairingConfirm, error_code: hci::ErrorCode::AuthenticationFailure.into(), - }.build(), + }, ); return Err(()); } confirm } else { ctx.send_hci_event( - hci::UserPasskeyNotificationBuilder { + hci::UserPasskeyNotification { bd_addr: ctx.peer_address(), passkey: 0, } - .build(), ); match ctx .receive_lmp_packet::>() @@ -752,13 +670,10 @@ pub async fn respond(ctx: &impl Context, request: lmp::IoCapabilityReq) -> Resul let negative_user_confirmation = match result { Ok(negative_user_confirmation) => negative_user_confirmation, Err(_) => { - ctx.send_hci_event( - hci::SimplePairingCompleteBuilder { - status: hci::ErrorCode::AuthenticationFailure, - bd_addr: ctx.peer_address(), - } - .build(), - ); + ctx.send_hci_event(hci::SimplePairingComplete { + status: hci::ErrorCode::AuthenticationFailure, + bd_addr: ctx.peer_address(), + }); return Err(()); } }; @@ -769,59 +684,45 @@ pub async fn respond(ctx: &impl Context, request: lmp::IoCapabilityReq) -> Resul { Either::Left(_) => { // Numeric comparison failed - ctx.send_hci_event( - hci::SimplePairingCompleteBuilder { - status: hci::ErrorCode::AuthenticationFailure, - bd_addr: ctx.peer_address(), - } - .build(), - ); + ctx.send_hci_event(hci::SimplePairingComplete { + status: hci::ErrorCode::AuthenticationFailure, + bd_addr: ctx.peer_address(), + }); return Err(()); } Either::Right(dhkey) => dhkey, }; if negative_user_confirmation { - ctx.send_lmp_packet( - lmp::NotAcceptedBuilder { - transaction_id: 0, - not_accepted_opcode: lmp::Opcode::DhkeyCheck, - error_code: hci::ErrorCode::AuthenticationFailure.into(), - } - .build(), - ); - ctx.send_hci_event( - hci::SimplePairingCompleteBuilder { - status: hci::ErrorCode::AuthenticationFailure, - bd_addr: ctx.peer_address(), - } - .build(), - ); + ctx.send_lmp_packet(lmp::NotAccepted { + transaction_id: 0, + not_accepted_opcode: lmp::Opcode::DhkeyCheck, + error_code: hci::ErrorCode::AuthenticationFailure.into(), + }); + ctx.send_hci_event(hci::SimplePairingComplete { + status: hci::ErrorCode::AuthenticationFailure, + bd_addr: ctx.peer_address(), + }); return Err(()); } // Authentication Stage 2 let confirmation_value = [0; CONFIRMATION_VALUE_SIZE]; - ctx.send_lmp_packet( - lmp::AcceptedBuilder { transaction_id: 0, accepted_opcode: lmp::Opcode::DhkeyCheck } - .build(), - ); + ctx.send_lmp_packet(lmp::Accepted { + transaction_id: 0, + accepted_opcode: lmp::Opcode::DhkeyCheck, + }); // TODO: handle error let _ = ctx - .send_accepted_lmp_packet( - lmp::DhkeyCheckBuilder { transaction_id: 0, confirmation_value }.build(), - ) + .send_accepted_lmp_packet(lmp::DhkeyCheck { transaction_id: 0, confirmation_value }) .await; - ctx.send_hci_event( - hci::SimplePairingCompleteBuilder { - status: hci::ErrorCode::Success, - bd_addr: ctx.peer_address(), - } - .build(), - ); + ctx.send_hci_event(hci::SimplePairingComplete { + status: hci::ErrorCode::Success, + bd_addr: ctx.peer_address(), + }); // Link Key Calculation let link_key = [0; 16]; @@ -832,14 +733,11 @@ pub async fn respond(ctx: &impl Context, request: lmp::IoCapabilityReq) -> Resul return Err(()); } - ctx.send_hci_event( - hci::LinkKeyNotificationBuilder { - bd_addr: ctx.peer_address(), - key_type: link_key_type(auth_method, dh_key), - link_key, - } - .build(), - ); + ctx.send_hci_event(hci::LinkKeyNotification { + bd_addr: ctx.peer_address(), + key_type: link_key_type(auth_method, dh_key), + link_key, + }); Ok(()) } @@ -850,8 +748,7 @@ mod tests { use crate::lmp::procedure::Context; use crate::lmp::test::{sequence, TestContext}; // simple pairing is part of authentication procedure - use super::super::authentication::initiate; - use super::super::authentication::respond; + use super::super::authentication::{initiate, respond}; fn local_p192_public_key(context: &crate::lmp::test::TestContext) -> [[u8; 16]; 3] { let mut buf = [[0; 16], [0; 16], [0; 16]]; diff --git a/rust/src/lmp/test/context.rs b/rust/src/lmp/test/context.rs index f0eb783..44e2a72 100644 --- a/rust/src/lmp/test/context.rs +++ b/rust/src/lmp/test/context.rs @@ -88,12 +88,18 @@ impl Context for TestContext { } } - fn send_hci_event>(&self, event: E) { - self.hci_events.borrow_mut().push_back(event.into()); + fn send_hci_event + pdl_runtime::Packet>(&self, event: E) { + let Ok(event) = event.try_into() else { + panic!("failed to convert to Event"); + }; + self.hci_events.borrow_mut().push_back(event); } - fn send_lmp_packet>(&self, packet: P) { - self.out_lmp_packets.borrow_mut().push_back(packet.into()); + fn send_lmp_packet + pdl_runtime::Packet>(&self, packet: P) { + let Ok(packet) = packet.try_into() else { + panic!("failed to convert to LmpPacket"); + }; + self.out_lmp_packets.borrow_mut().push_back(packet); } fn peer_address(&self) -> hci::Address { diff --git a/rust/src/lmp/test/sequence.rs b/rust/src/lmp/test/sequence.rs index 9735b1a..a9dd3ba 100644 --- a/rust/src/lmp/test/sequence.rs +++ b/rust/src/lmp/test/sequence.rs @@ -20,11 +20,11 @@ macro_rules! sequence_body { use crate::packets::lmp::*; let builder = paste! { - [<$packet Builder>] { + $packet { $($name: $value),* } }; - $ctx.0.in_lmp_packets.borrow_mut().push_back(builder.build().into()); + $ctx.0.in_lmp_packets.borrow_mut().push_back(builder.try_into().unwrap()); let poll = crate::lmp::test::poll($ctx.1.as_mut()); @@ -40,11 +40,11 @@ macro_rules! sequence_body { use crate::packets::hci::*; let builder = paste! { - [<$packet Builder>] { + $packet { $($name: $value),* } }; - $ctx.0.hci_commands.borrow_mut().push_back(builder.build().into()); + $ctx.0.hci_commands.borrow_mut().push_back(builder.try_into().unwrap()); let poll = crate::lmp::test::poll($ctx.1.as_mut()); @@ -64,7 +64,7 @@ macro_rules! sequence_body { } $( - let value = paste! { packet.[]() }; + let value = paste! { packet.$name() }; assert_eq!(value.clone(), $expected_value); )* @@ -82,7 +82,7 @@ macro_rules! sequence_body { } $( - let value = paste! { packet.[]() }; + let value = paste! { packet.$name() }; assert_eq!(value.clone(), $expected_value); )* @@ -136,5 +136,4 @@ macro_rules! sequence { }); } -pub(crate) use sequence; -pub(crate) use sequence_body; +pub(crate) use {sequence, sequence_body}; diff --git a/rust/src/packets.rs b/rust/src/packets.rs index a64a22a..3af19f4 100644 --- a/rust/src/packets.rs +++ b/rust/src/packets.rs @@ -57,36 +57,32 @@ pub mod hci { pub fn command_remote_device_address(command: &Command) -> Option

{ use CommandChild::*; - #[allow(unused_imports)] - use Option::None; // Overwrite `None` variant of `Child` enum match command.specialize() { - LinkKeyRequestReply(packet) => Some(packet.get_bd_addr()), - LinkKeyRequestNegativeReply(packet) => Some(packet.get_bd_addr()), - PinCodeRequestReply(packet) => Some(packet.get_bd_addr()), - PinCodeRequestNegativeReply(packet) => Some(packet.get_bd_addr()), - IoCapabilityRequestReply(packet) => Some(packet.get_bd_addr()), - IoCapabilityRequestNegativeReply(packet) => Some(packet.get_bd_addr()), - UserConfirmationRequestReply(packet) => Some(packet.get_bd_addr()), - UserConfirmationRequestNegativeReply(packet) => Some(packet.get_bd_addr()), - UserPasskeyRequestReply(packet) => Some(packet.get_bd_addr()), - UserPasskeyRequestNegativeReply(packet) => Some(packet.get_bd_addr()), - RemoteOobDataRequestReply(packet) => Some(packet.get_bd_addr()), - RemoteOobDataRequestNegativeReply(packet) => Some(packet.get_bd_addr()), - SendKeypressNotification(packet) => Some(packet.get_bd_addr()), - _ => None, + Ok(LinkKeyRequestReply(packet)) => Some(packet.bd_addr()), + Ok(LinkKeyRequestNegativeReply(packet)) => Some(packet.bd_addr()), + Ok(PinCodeRequestReply(packet)) => Some(packet.bd_addr()), + Ok(PinCodeRequestNegativeReply(packet)) => Some(packet.bd_addr()), + Ok(IoCapabilityRequestReply(packet)) => Some(packet.bd_addr()), + Ok(IoCapabilityRequestNegativeReply(packet)) => Some(packet.bd_addr()), + Ok(UserConfirmationRequestReply(packet)) => Some(packet.bd_addr()), + Ok(UserConfirmationRequestNegativeReply(packet)) => Some(packet.bd_addr()), + Ok(UserPasskeyRequestReply(packet)) => Some(packet.bd_addr()), + Ok(UserPasskeyRequestNegativeReply(packet)) => Some(packet.bd_addr()), + Ok(RemoteOobDataRequestReply(packet)) => Some(packet.bd_addr()), + Ok(RemoteOobDataRequestNegativeReply(packet)) => Some(packet.bd_addr()), + Ok(SendKeypressNotification(packet)) => Some(packet.bd_addr()), + _ => Option::None, } } pub fn command_connection_handle(command: &Command) -> Option { use CommandChild::*; - #[allow(unused_imports)] - use Option::None; // Overwrite `None` variant of `Child` enum match command.specialize() { - AuthenticationRequested(packet) => Some(packet.get_connection_handle()), - SetConnectionEncryption(packet) => Some(packet.get_connection_handle()), - _ => None, + Ok(AuthenticationRequested(packet)) => Some(packet.connection_handle()), + Ok(SetConnectionEncryption(packet)) => Some(packet.connection_handle()), + _ => Option::None, } } } diff --git a/third_party/pdl b/third_party/pdl index b2cfaca..b193b66 160000 --- a/third_party/pdl +++ b/third_party/pdl @@ -1 +1 @@ -Subproject commit b2cfaca987fff89caf6b632f20b5d57d78be72df +Subproject commit b193b6671f6e06873576b02e6902b861b6275d4e