use super::VendorReturnParameters;
use crate::{BadStatusError, ConnectionHandle, Status};
use byteorder::{ByteOrder, LittleEndian};
use core::convert::{TryFrom, TryInto};
use core::fmt::{Debug, Formatter, Result as FmtResult};
use core::mem;
#[derive(Clone, Debug)]
pub struct CommandComplete<V>
where
V: super::VendorEvent,
{
pub num_hci_command_packets: u8,
pub return_params: ReturnParameters<V>,
}
impl<V> CommandComplete<V>
where
V: super::VendorEvent,
{
pub fn new(bytes: &[u8]) -> Result<CommandComplete<V>, crate::event::Error<V::Error>> {
require_len_at_least!(bytes, 3);
let params = match crate::opcode::Opcode(LittleEndian::read_u16(&bytes[1..])) {
crate::opcode::Opcode(0x0000) => ReturnParameters::Spontaneous,
crate::opcode::SET_EVENT_MASK => {
ReturnParameters::SetEventMask(to_status(&bytes[3..])?)
}
crate::opcode::RESET => ReturnParameters::Reset(to_status(&bytes[3..])?),
crate::opcode::READ_TX_POWER_LEVEL => {
ReturnParameters::ReadTxPowerLevel(to_tx_power_level(&bytes[3..])?)
}
crate::opcode::READ_LOCAL_VERSION_INFO => {
ReturnParameters::ReadLocalVersionInformation(to_local_version_info(&bytes[3..])?)
}
crate::opcode::READ_LOCAL_SUPPORTED_COMMANDS => {
ReturnParameters::ReadLocalSupportedCommands(to_supported_commands(&bytes[3..])?)
}
crate::opcode::READ_LOCAL_SUPPORTED_FEATURES => {
ReturnParameters::ReadLocalSupportedFeatures(to_supported_features(&bytes[3..])?)
}
crate::opcode::READ_BD_ADDR => ReturnParameters::ReadBdAddr(to_bd_addr(&bytes[3..])?),
crate::opcode::READ_RSSI => ReturnParameters::ReadRssi(to_read_rssi(&bytes[3..])?),
crate::opcode::LE_SET_EVENT_MASK => {
ReturnParameters::LeSetEventMask(to_status(&bytes[3..])?)
}
crate::opcode::LE_READ_BUFFER_SIZE => {
ReturnParameters::LeReadBufferSize(to_le_read_buffer_status(&bytes[3..])?)
}
crate::opcode::LE_READ_LOCAL_SUPPORTED_FEATURES => {
ReturnParameters::LeReadLocalSupportedFeatures(to_le_local_supported_features(
&bytes[3..],
)?)
}
crate::opcode::LE_SET_RANDOM_ADDRESS => {
ReturnParameters::LeSetRandomAddress(to_status(&bytes[3..])?)
}
crate::opcode::LE_SET_ADVERTISING_PARAMETERS => {
ReturnParameters::LeSetAdvertisingParameters(to_status(&bytes[3..])?)
}
crate::opcode::LE_READ_ADVERTISING_CHANNEL_TX_POWER => {
ReturnParameters::LeReadAdvertisingChannelTxPower(
to_le_advertising_channel_tx_power(&bytes[3..])?,
)
}
crate::opcode::LE_SET_ADVERTISING_DATA => {
ReturnParameters::LeSetAdvertisingData(to_status(&bytes[3..])?)
}
crate::opcode::LE_SET_SCAN_RESPONSE_DATA => {
ReturnParameters::LeSetScanResponseData(to_status(&bytes[3..])?)
}
crate::opcode::LE_SET_ADVERTISE_ENABLE => {
to_le_set_advertise_enable(to_status(&bytes[3..])?)
}
crate::opcode::LE_SET_SCAN_PARAMETERS => {
ReturnParameters::LeSetScanParameters(to_status(&bytes[3..])?)
}
crate::opcode::LE_SET_SCAN_ENABLE => {
ReturnParameters::LeSetScanEnable(to_status(&bytes[3..])?)
}
crate::opcode::LE_CREATE_CONNECTION_CANCEL => {
ReturnParameters::LeCreateConnectionCancel(to_status(&bytes[3..])?)
}
crate::opcode::LE_READ_WHITE_LIST_SIZE => {
ReturnParameters::LeReadWhiteListSize(to_status(&bytes[3..])?, bytes[4] as usize)
}
crate::opcode::LE_CLEAR_WHITE_LIST => {
ReturnParameters::LeClearWhiteList(to_status(&bytes[3..])?)
}
crate::opcode::LE_ADD_DEVICE_TO_WHITE_LIST => {
ReturnParameters::LeAddDeviceToWhiteList(to_status(&bytes[3..])?)
}
crate::opcode::LE_REMOVE_DEVICE_FROM_WHITE_LIST => {
ReturnParameters::LeRemoveDeviceFromWhiteList(to_status(&bytes[3..])?)
}
crate::opcode::LE_SET_HOST_CHANNEL_CLASSIFICATION => {
ReturnParameters::LeSetHostChannelClassification(to_status(&bytes[3..])?)
}
crate::opcode::LE_READ_CHANNEL_MAP => {
ReturnParameters::LeReadChannelMap(to_le_channel_map_parameters(&bytes[3..])?)
}
crate::opcode::LE_ENCRYPT => {
ReturnParameters::LeEncrypt(to_le_encrypted_data(&bytes[3..])?)
}
crate::opcode::LE_RAND => ReturnParameters::LeRand(to_random_number(&bytes[3..])?),
crate::opcode::LE_LTK_REQUEST_REPLY => {
ReturnParameters::LeLongTermKeyRequestReply(to_le_ltk_request_reply(&bytes[3..])?)
}
crate::opcode::LE_LTK_REQUEST_NEGATIVE_REPLY => {
ReturnParameters::LeLongTermKeyRequestNegativeReply(to_le_ltk_request_reply(
&bytes[3..],
)?)
}
crate::opcode::LE_READ_STATES => {
ReturnParameters::LeReadSupportedStates(to_le_read_states(&bytes[3..])?)
}
crate::opcode::LE_RECEIVER_TEST => {
ReturnParameters::LeReceiverTest(to_status(&bytes[3..])?)
}
crate::opcode::LE_TRANSMITTER_TEST => {
ReturnParameters::LeTransmitterTest(to_status(&bytes[3..])?)
}
crate::opcode::LE_TEST_END => ReturnParameters::LeTestEnd(to_le_test_end(&bytes[3..])?),
other => {
const VENDOR_OGF: u16 = 0x3F;
if other.ogf() != VENDOR_OGF {
return Err(crate::event::Error::UnknownOpcode(other));
}
ReturnParameters::Vendor(V::ReturnParameters::new(&bytes)?)
}
};
Ok(CommandComplete::<V> {
num_hci_command_packets: bytes[0],
return_params: params,
})
}
}
#[derive(Copy, Clone, Debug)]
pub enum ReturnParameters<V>
where
V: super::VendorEvent,
{
Spontaneous,
SetEventMask(Status<V::Status>),
Reset(Status<V::Status>),
ReadTxPowerLevel(TxPowerLevel<V::Status>),
ReadLocalVersionInformation(LocalVersionInfo<V::Status>),
ReadLocalSupportedCommands(LocalSupportedCommands<V::Status>),
ReadLocalSupportedFeatures(LocalSupportedFeatures<V::Status>),
ReadBdAddr(ReadBdAddr<V::Status>),
ReadRssi(ReadRssi<V::Status>),
LeSetEventMask(Status<V::Status>),
LeReadBufferSize(LeReadBufferSize<V::Status>),
LeReadLocalSupportedFeatures(LeSupportedFeatures<V::Status>),
LeSetRandomAddress(Status<V::Status>),
LeSetAdvertisingParameters(Status<V::Status>),
LeReadAdvertisingChannelTxPower(LeAdvertisingChannelTxPower<V::Status>),
LeSetAdvertisingData(Status<V::Status>),
LeSetScanResponseData(Status<V::Status>),
#[cfg(not(feature = "version-5-0"))]
LeSetAdvertiseEnable(Status<V::Status>),
#[cfg(feature = "version-5-0")]
LeSetAdvertisingEnable(Status<V::Status>),
LeSetScanParameters(Status<V::Status>),
LeSetScanEnable(Status<V::Status>),
LeCreateConnectionCancel(Status<V::Status>),
LeReadWhiteListSize(Status<V::Status>, usize),
LeClearWhiteList(Status<V::Status>),
LeAddDeviceToWhiteList(Status<V::Status>),
LeRemoveDeviceFromWhiteList(Status<V::Status>),
LeSetHostChannelClassification(Status<V::Status>),
LeReadChannelMap(ChannelMapParameters<V::Status>),
LeEncrypt(EncryptedReturnParameters<V::Status>),
LeRand(LeRandom<V::Status>),
LeLongTermKeyRequestReply(LeLongTermRequestReply<V::Status>),
LeLongTermKeyRequestNegativeReply(LeLongTermRequestReply<V::Status>),
LeReadSupportedStates(LeReadSupportedStates<V::Status>),
LeReceiverTest(Status<V::Status>),
LeTransmitterTest(Status<V::Status>),
LeTestEnd(LeTestEnd<V::Status>),
Vendor(V::ReturnParameters),
}
fn to_status<VE, VS>(bytes: &[u8]) -> Result<Status<VS>, crate::event::Error<VE>>
where
Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
bytes[0].try_into().map_err(super::rewrap_bad_status)
}
#[derive(Copy, Clone, Debug)]
pub struct TxPowerLevel<VS> {
pub status: Status<VS>,
pub conn_handle: ConnectionHandle,
pub tx_power_level_dbm: i8,
}
fn to_tx_power_level<VE, VS>(bytes: &[u8]) -> Result<TxPowerLevel<VS>, crate::event::Error<VE>>
where
Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
require_len!(bytes, 4);
Ok(TxPowerLevel {
status: to_status(bytes)?,
conn_handle: ConnectionHandle(LittleEndian::read_u16(&bytes[1..])),
tx_power_level_dbm: unsafe { mem::transmute::<u8, i8>(bytes[3]) },
})
}
#[derive(Copy, Clone, Debug)]
pub struct LocalVersionInfo<VS> {
pub status: Status<VS>,
pub hci_version: u8,
pub hci_revision: u16,
pub lmp_version: u8,
pub manufacturer_name: u16,
pub lmp_subversion: u16,
}
fn to_local_version_info<VE, VS>(
bytes: &[u8],
) -> Result<LocalVersionInfo<VS>, crate::event::Error<VE>>
where
Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
require_len!(bytes, 9);
Ok(LocalVersionInfo {
status: bytes[0].try_into().map_err(super::rewrap_bad_status)?,
hci_version: bytes[1],
hci_revision: LittleEndian::read_u16(&bytes[2..]),
lmp_version: bytes[4],
manufacturer_name: LittleEndian::read_u16(&bytes[5..]),
lmp_subversion: LittleEndian::read_u16(&bytes[7..]),
})
}
#[derive(Copy, Clone, Debug)]
pub struct LocalSupportedCommands<VS> {
pub status: Status<VS>,
pub supported_commands: CommandFlags,
}
const COMMAND_FLAGS_SIZE: usize = 64;
bitflag_array! {
#[derive(Copy, Clone)]
pub struct CommandFlags : COMMAND_FLAGS_SIZE;
pub struct CommandFlag;
const INQUIRY = 0, 1 << 0;
const INQUIRY_CANCEL = 0, 1 << 1;
const PERIODIC_INQUIRY_MODE = 0, 1 << 2;
const EXIT_PERIODIC_INQUIRY_MODE = 0, 1 << 3;
const CREATE_CONNECTION = 0, 1 << 4;
const DISCONNECT = 0, 1 << 5;
#[deprecated]
const ADD_SCO_CONNECTION = 0, 1 << 6;
const CREATE_CONNECTION_CANCEL = 0, 1 << 7;
const ACCEPT_CONNECTION_REQUEST = 1, 1 << 0;
const REJECT_CONNECTION_REQUEST = 1, 1 << 1;
const LINK_KEY_REQUEST_REPLY = 1, 1 << 2;
const LINK_KEY_REQUEST_NEGATIVE_REPLY = 1, 1 << 3;
const PIN_CODE_REQUEST_REPLY = 1, 1 << 4;
const PIN_CODE_REQUEST_NEGATIVE_REPLY = 1, 1 << 5;
const CHANGE_CONNECTION_PACKET_TYPE = 1, 1 << 6;
const AUTHENTICATION_REQUESTED = 1, 1 << 7;
const SET_CONNECTION_ENCRYPTION = 2, 1 << 0;
const CHANGE_CONNECTION_LINK_KEY = 2, 1 << 1;
const MASTER_LINK_KEY = 2, 1 << 2;
const REMOTE_NAME_REQUEST = 2, 1 << 3;
const REMOTE_NAME_REQUEST_CANCEL = 2, 1 << 4;
const READ_REMOTE_SUPPORTED_FEATURES = 2, 1 << 5;
const READ_REMOTE_EXTENDED_FEATURES = 2, 1 << 6;
const READ_REMOTE_VERSION_INFORMATION = 2, 1 << 7;
const READ_CLOCK_OFFSET = 3, 1 << 0;
const READ_LMP_HANDLE = 3, 1 << 1;
const HOLD_MODE = 4, 1 << 1;
const SNIFF_MODE = 4, 1 << 2;
const EXIT_SNIFF_MODE = 4, 1 << 3;
const PARK_STATE = 4, 1 << 4;
const EXIT_PARK_STATE = 4, 1 << 5;
const QOS_SETUP = 4, 1 << 6;
const ROLE_DISCOVERY = 4, 1 << 7;
const SWITCH_ROLE = 5, 1 << 0;
const READ_LINK_POLICY_SETTINGS = 5, 1 << 1;
const WRITE_LINK_POLICY_SETTINGS = 5, 1 << 2;
const READ_DEFAULT_LINK_POLICY_SETTINGS = 5, 1 << 3;
const WRITE_DEFAULT_LINK_POLICY_SETTINGS = 5, 1 << 4;
const FLOW_SPECIFICATION = 5, 1 << 5;
const SET_EVENT_MASK = 5, 1 << 6;
const RESET = 5, 1 << 7;
const SET_EVENT_FILTER = 6, 1 << 0;
const FLUSH = 6, 1 << 1;
const READ_PIN_TYPE = 6, 1 << 2;
const WRITE_PIN_TYPE = 6, 1 << 3;
const CREATE_NEW_UNIT_KEY = 6, 1 << 4;
const READ_STORED_LINK_KEY = 6, 1 << 5;
const WRITE_STORED_LINK_KEY = 6, 1 << 6;
const DELETE_STORED_LINK_KEY = 6, 1 << 7;
const WRITE_LOCAL_NAME = 7, 1 << 0;
const READ_LOCAL_NAME = 7, 1 << 1;
const READ_CONNECTION_ACCEPT_TIMEOUT = 7, 1 << 2;
const WRITE_CONNECTION_ACCEPT_TIMEOUT = 7, 1 << 3;
const READ_PAGE_TIMEOUT = 7, 1 << 4;
const WRITE_PAGE_TIMEOUT = 7, 1 << 5;
const READ_SCAN_ENABLE = 7, 1 << 6;
const WRITE_SCAN_ENABLE = 7, 1 << 7;
const READ_PAGE_SCAN_ACTIVITY = 8, 1 << 0;
const WRITE_PAGE_SCAN_ACTIVITY = 8, 1 << 1;
const READ_INQUIRY_SCAN_ACTIVITY = 8, 1 << 2;
const WRITE_INQUIRY_SCAN_ACTIVITY = 8, 1 << 3;
const READ_AUTHENTICATION_ENABLE = 8, 1 << 4;
const WRITE_AUTHENTICATION_ENABLE = 8, 1 << 5;
#[deprecated]
const READ_ENCRYPTION_MODE = 8, 1 << 6;
#[deprecated]
const WRITE_ENCRYPTION_MODE = 8, 1 << 7;
const READ_CLASS_OF_DEVICE = 9, 1 << 0;
const WRITE_CLASS_OF_DEVICE = 9, 1 << 1;
const READ_VOICE_SETTING = 9, 1 << 2;
const WRITE_VOICE_SETTING = 9, 1 << 3;
const READ_AUTOMATIC_FLUSH_TIMEOUT = 9, 1 << 4;
const WRITE_AUTOMATIC_FLUSH_TIMEOUT = 9, 1 << 5;
const READ_NUM_BROADCAST_RETRANSMISSIONS = 9, 1 << 6;
const WRITE_NUM_BROADCAST_RETRANSMISSIONS = 9, 1 << 7;
const READ_HOLD_MODE_ACTIVITY = 10, 1 << 0;
const WRITE_HOLD_MODE_ACTIVITY = 10, 1 << 1;
const READ_TRANSMIT_POWER_LEVEL = 10, 1 << 2;
const READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE = 10, 1 << 3;
const WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE = 10, 1 << 4;
const SET_CONTROLLER_TO_HOST_FLOW_CONTROL = 10, 1 << 5;
const HOST_BUFFER_SIZE = 10, 1 << 6;
const HOST_NUMBER_OF_COMPLETED_PACKETS = 10, 1 << 7;
const READ_LINK_SUPERVISION_TIMEOUT = 11, 1 << 0;
const WRITE_LINK_SUPERVISION_TIMEOUT = 11, 1 << 1;
const READ_NUMBER_OF_SUPPORTED_IAC = 11, 1 << 2;
const READ_CURRENT_IAC_LAP = 11, 1 << 3;
const WRITE_CURRENT_IAC_LAP = 11, 1 << 4;
#[deprecated]
const READ_PAGE_SCAN_MODE_PERIOD = 11, 1 << 5;
#[deprecated]
const WRITE_PAGE_SCAN_MODE_PERIOD = 11, 1 << 6;
#[deprecated]
const READ_PAGE_SCAN_MODE = 11, 1 << 7;
#[deprecated]
const WRITE_PAGE_SCAN_MODE = 12, 1 << 0;
const SET_AFH_HOST_CHANNEL_CLASSIFICATION = 12, 1 << 1;
const READ_INQUIRY_SCAN_TYPE = 12, 1 << 4;
const WRITE_INQUIRY_SCAN_TYPE = 12, 1 << 5;
const READ_INQUIRY_MODE = 12, 1 << 6;
const WRITE_INQUIRY_MODE = 12, 1 << 7;
const READ_PAGE_SCAN_TYPE = 13, 1 << 0;
const WRITE_PAGE_SCAN_TYPE = 13, 1 << 1;
const READ_AFH_CHANNEL_ASSESSMENT_MODE = 13, 1 << 2;
const WRITE_AFH_CHANNEL_ASSESSMENT_MODE = 13, 1 << 3;
const READ_LOCAL_VERSION_INFORMATION = 14, 1 << 3;
const READ_LOCAL_SUPPORTED_FEATURES = 14, 1 << 5;
const READ_LOCAL_EXTENDED_FEATURES = 14, 1 << 6;
const READ_BUFFER_SIZE = 14, 1 << 7;
#[deprecated]
const READ_COUNTRY_CODE = 15, 1 << 0;
const READ_BD_ADDR = 15, 1 << 1;
const READ_FAILED_CONTACT_COUNTER = 15, 1 << 2;
const RESET_FAILED_CONTACT_COUNTER = 15, 1 << 3;
const READ_LINK_QUALITY = 15, 1 << 4;
const READ_RSSI = 15, 1 << 5;
const READ_AFH_CHANNEL_MAP = 15, 1 << 6;
const READ_CLOCK = 15, 1 << 7;
const READ_LOOPBACK_MODE = 16, 1 << 0;
const WRITE_LOOPBACK_MODE = 16, 1 << 1;
const ENABLE_DEVICE_UNDER_TEST_MODE = 16, 1 << 2;
const SETUP_SYNCHRONOUS_CONNECTION_REQUEST = 16, 1 << 3;
const ACCEPT_SYNCHRONOUS_CONNECTION_REQUEST = 16, 1 << 4;
const REJECT_SYNCHRONOUS_CONNECTION_REQUEST = 16, 1 << 5;
const READ_EXTENDED_INQUIRY_RESPONSE = 17, 1 << 0;
const WRITE_EXTENDED_INQUIRY_RESPONSE = 17, 1 << 1;
const REFRESH_ENCRYPTION_KEY = 17, 1 << 2;
const SNIFF_SUBRATING = 17, 1 << 4;
const READ_SIMPLE_PAIRING_MODE = 17, 1 << 5;
const WRITE_SIMPLE_PAIRING_MODE = 17, 1 << 6;
const READ_LOCAL_OOB_DATA = 17, 1 << 7;
const READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL = 18, 1 << 0;
const WRITE_INQUIRY_TRANSMIT_POWER_LEVEL = 18, 1 << 1;
const READ_DEFAULT_ERRONEOUS_DATA_REPORTING = 18, 1 << 2;
const WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING = 18, 1 << 3;
const IO_CAPABILITY_REQUEST_REPLY = 18, 1 << 7;
const USER_CONFIRMATION_REQUEST_REPLY = 19, 1 << 0;
const USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY = 19, 1 << 1;
const USER_PASSKEY_REQUEST_REPLY = 19, 1 << 2;
const USER_PASSKEY_REQUEST_NEGATIVE_REPLY = 19, 1 << 3;
const REMOTE_OOB_DATA_REQUEST_REPLY = 19, 1 << 4;
const WRITE_SIMPLE_PAIRING_DEBUG_MODE = 19, 1 << 5;
const ENHANCED_FLUSH = 19, 1 << 6;
const REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY = 19, 1 << 7;
const SEND_KEYPRESS_NOTIFICATION = 20, 1 << 2;
const IO_CAPABILITY_REQUEST_NEGATIVE_REPLY = 20, 1 << 3;
const READ_ENCRYPTION_KEY_SIZE = 20, 1 << 4;
const CREATE_PHYSICAL_LINK = 21, 1 << 0;
const ACCEPT_PHYSICAL_LINK = 21, 1 << 1;
const DISCONNECT_PHYSICAL_LINK = 21, 1 << 2;
const CREATE_LOGICAL_LINK = 21, 1 << 3;
const ACCEPT_LOGICAL_LINK = 21, 1 << 4;
const DISCONNECT_LOGICAL_LINK = 21, 1 << 5;
const LOGICAL_LINK_CANCEL = 21, 1 << 6;
const FLOW_SPEC_MODIFY = 21, 1 << 7;
const READ_LOGICAL_LINK_ACCEPT_TIMEOUT = 22, 1 << 0;
const WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT = 22, 1 << 1;
const SET_EVENT_MASK_PAGE_2 = 22, 1 << 2;
const READ_LOCATION_DATA = 22, 1 << 3;
const WRITE_LOCATION_DATA = 22, 1 << 4;
const READ_LOCAL_AMP_INFO = 22, 1 << 5;
const READ_LOCAL_AMP_ASSOC = 22, 1 << 6;
const WRITE_REMOTE_AMP_ASSOC = 22, 1 << 7;
const READ_FLOW_CONTROL_MODE = 23, 1 << 0;
const WRITE_FLOW_CONTROL_MODE = 23, 1 << 1;
const READ_DATA_BLOCK_SIZE = 23, 1 << 2;
const ENABLE_AMP_RECEIVER_REPORTS = 23, 1 << 5;
const AMP_TEST_END = 23, 1 << 6;
const AMP_TEST = 23, 1 << 7;
const READ_ENHANCED_TRANSMIT_POWER_LEVEL = 24, 1 << 0;
const READ_BEST_EFFORT_FLUSH_TIMEOUT = 24, 1 << 2;
const WRITE_BEST_EFFORT_FLUSH_TIMEOUT = 24, 1 << 3;
const SHORT_RANGE_MODE = 24, 1 << 4;
const READ_LE_HOST_SUPPORT = 24, 1 << 5;
const WRITE_LE_HOST_SUPPORT = 24, 1 << 6;
const LE_SET_EVENT_MASK = 25, 1 << 0;
const LE_READ_BUFFER_SIZE = 25, 1 << 1;
const LE_READ_LOCAL_SUPPORTED_FEATURES = 25, 1 << 2;
const LE_SET_RANDOM_ADDRESS = 25, 1 << 4;
const LE_SET_ADVERTISING_PARAMETERS = 25, 1 << 5;
const LE_READ_ADVERTISING_CHANNEL_TX_POWER = 25, 1 << 6;
const LE_SET_ADVERTISING_DATA = 25, 1 << 7;
const LE_SET_SCAN_RESPONSE_DATA = 26, 1 << 0;
const LE_SET_ADVERTISE_ENABLE = 26, 1 << 1;
const LE_SET_SCAN_PARAMETERS = 26, 1 << 2;
const LE_SET_SCAN_ENABLE = 26, 1 << 3;
const LE_CREATE_CONNECTION = 26, 1 << 4;
const LE_CREATE_CONNECTION_CANCEL = 26, 1 << 5;
const LE_READ_WHITE_LIST_SIZE = 26, 1 << 6;
const LE_CLEAR_WHITE_LIST = 26, 1 << 7;
const LE_ADD_DEVICE_TO_WHITE_LIST = 27, 1 << 0;
const LE_REMOVE_DEVICE_FROM_WHITE_LIST = 27, 1 << 1;
const LE_CONNECTION_UPDATE = 27, 1 << 2;
const LE_SET_HOST_CHANNEL_CLASSIFICATION = 27, 1 << 3;
const LE_READ_CHANNEL_MAP = 27, 1 << 4;
const LE_READ_REMOTE_USED_FEATURES = 27, 1 << 5;
const LE_ENCRYPT = 27, 1 << 6;
const LE_RAND = 27, 1 << 7;
const LE_START_ENCRYPTION = 28, 1 << 0;
const LE_LONG_TERM_KEY_REQUEST_REPLY = 28, 1 << 1;
const LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY = 28, 1 << 2;
const LE_READ_SUPPORTED_STATES = 28, 1 << 3;
const LE_RECEIVER_TEST = 28, 1 << 4;
const LE_TRANSMITTER_TEST = 28, 1 << 5;
const LE_TEST_END = 28, 1 << 6;
const ENHANCED_SETUP_SYNCHRONOUS_CONNECTION = 29, 1 << 3;
const ENHANCED_ACCEPT_SYNCHRONOUS_CONNECTION = 29, 1 << 4;
const READ_LOCAL_SUPPORTED_CODECS = 29, 1 << 5;
const SET_MWS_CHANNEL_PARAMETERS_COMMAND = 29, 1 << 6;
const SET_EXTERNAL_FRAME_CONFIGURATION_COMMAND = 29, 1 << 7;
const SET_MWS_SIGNALING_COMMAND = 30, 1 << 0;
const SET_TRANSPORT_LAYER_COMMAND = 30, 1 << 1;
const SET_MWS_SCAN_FREQUENCY_TABLE_COMMAND = 30, 1 << 2;
const GET_TRANSPORT_LAYER_CONFIGURATION_COMMAND = 30, 1 << 3;
const SET_MWS_PATTERN_CONFIGURATION_COMMAND = 30, 1 << 4;
const SET_TRIGGERED_CLOCK_CAPTURE = 30, 1 << 5;
const TRUNCATED_PAGE = 30, 1 << 6;
const TRUNCATED_PAGE_CANCEL = 30, 1 << 7;
const SET_CONNECTIONLESS_PERIPHERAL_BROADCAST = 31, 1 << 0;
const SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_RECEIVE = 31, 1 << 1;
const START_SYNCHRONIZATION_TRAIN = 31, 1 << 2;
const RECEIVE_SYNCHRONIZATION_TRAIN = 31, 1 << 3;
const SET_CONNECTIONLESS_PERIPHERAL_BROADCAST_DATA = 31, 1 << 6;
const READ_SYNCHRONIZATION_TRAIN_PARAMETERS = 31, 1 << 7;
const WRITE_SYNCHRONIZATION_TRAIN_PARAMETERS = 32, 1 << 0;
const REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY = 32, 1 << 1;
const READ_SECURE_CONNECTIONS_HOST_SUPPORT = 32, 1 << 2;
const WRITE_SECURE_CONNECTIONS_HOST_SUPPORT = 32, 1 << 3;
const READ_AUTHENTICATED_PAYLOAD_TIMEOUT = 32, 1 << 4;
const WRITE_AUTHENTICATED_PAYLOAD_TIMEOUT = 32, 1 << 5;
const READ_LOCAL_OOB_EXTENDED_DATA = 32, 1 << 6;
const WRITE_SECURE_CONNECTIONS_TEST_MODE = 32, 1 << 7;
const READ_EXTENDED_PAGE_TIMEOUT = 33, 1 << 0;
const WRITE_EXTENDED_PAGE_TIMEOUT = 33, 1 << 1;
const READ_EXTENDED_INQUIRY_LENGTH = 33, 1 << 2;
const WRITE_EXTENDED_INQUIRY_LENGTH = 33, 1 << 3;
const LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY_COMMAND = 33, 1 << 4;
const LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY_COMMAND = 33, 1 << 5;
#[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
const LE_SET_DATA_LENGTH = 33, 1 << 6;
#[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
const LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH = 33, 1 << 7;
#[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
const LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH = 34, 1 << 0;
#[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
const LE_READ_LOCAL_P256_PUBLIC_KEY = 34, 1 << 1;
#[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
const LE_GENERATE_DH_KEY = 34, 1 << 2;
#[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
const LE_ADD_DEVICE_TO_RESOLVING_LIST = 34, 1 << 3;
#[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
const LE_REMOVE_DEVICE_FROM_RESOLVING_LIST = 34, 1 << 4;
#[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
const LE_CLEAR_RESOLVING_LIST = 34, 1 << 5;
#[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
const LE_READ_RESOLVING_LIST_SIZE = 34, 1 << 6;
#[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
const LE_READ_PEER_RESOLVABLE_ADDRESS = 34, 1 << 7;
#[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
const LE_READ_LOCAL_RESOLVABLE_ADDRESS = 35, 1 << 0;
#[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
const LE_SET_ADDRESS_RESOLUTION_ENABLE = 35, 1 << 1;
#[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
const LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT = 35, 1 << 2;
#[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
const LE_READ_MAXIMUM_DATA_LENGTH = 35, 1 << 3;
#[cfg(feature = "version-5-0")]
const LE_READ_PHY_COMMAND = 35, 1 << 4;
#[cfg(feature = "version-5-0")]
const LE_SET_DEFAULT_PHY_COMMAND = 35, 1 << 5;
#[cfg(feature = "version-5-0")]
const LE_SET_PHY_COMMAND = 35, 1 << 6;
#[cfg(feature = "version-5-0")]
const LE_ENHANCED_RECEIVER_TEST_COMMAND = 35, 1 << 7;
#[cfg(feature = "version-5-0")]
const LE_ENHANCED_TRANSMITTER_TEST_COMMAND = 36, 1 << 0;
#[cfg(feature = "version-5-0")]
const LE_SET_ADVERTISING_SET_RANDOM_ADDRESS_COMMAND = 36, 1 << 1;
#[cfg(feature = "version-5-0")]
const LE_SET_EXTENDED_ADVERTISING_PARAMETERS_COMMAND = 36, 1 << 2;
#[cfg(feature = "version-5-0")]
const LE_SET_EXTENDED_ADVERTISING_DATA_COMMAND = 36, 1 << 3;
#[cfg(feature = "version-5-0")]
const LE_SET_EXTENDED_SCAN_RESPONSE_DATA_COMMAND = 36, 1 << 4;
#[cfg(feature = "version-5-0")]
const LE_SET_EXTENDED_ADVERTISING_ENABLE_COMMAND = 36, 1 << 5;
#[cfg(feature = "version-5-0")]
const LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH_COMMAND = 36, 1 << 6;
#[cfg(feature = "version-5-0")]
const LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS_COMMAND = 36, 1 << 7;
#[cfg(feature = "version-5-0")]
const LE_REMOVE_ADVERTISING_SET_COMMAND = 37, 1 << 0;
#[cfg(feature = "version-5-0")]
const LE_CLEAR_ADVERTISING_SETS_COMMAND = 37, 1 << 1;
#[cfg(feature = "version-5-0")]
const LE_SET_PERIODIC_ADVERTISING_PARAMETERS_COMMAND = 37, 1 << 2;
#[cfg(feature = "version-5-0")]
const LE_SET_PERIODIC_ADVERTISING_DATA_COMMAND = 37, 1 << 3;
#[cfg(feature = "version-5-0")]
const LE_SET_PERIODIC_ADVERTISING_ENABLE_COMMAND = 37, 1 << 4;
#[cfg(feature = "version-5-0")]
const LE_SET_EXTENDED_SCAN_PARAMETERS_COMMAND = 37, 1 << 5;
#[cfg(feature = "version-5-0")]
const LE_SET_EXTENDED_SCAN_ENABLE_COMMAND = 37, 1 << 6;
#[cfg(feature = "version-5-0")]
const LE_EXTENDED_CREATE_CONNECTION_COMMAND = 37, 1 << 7;
#[cfg(feature = "version-5-0")]
const LE_PERIODIC_ADVERTISING_CREATE_SYNC_COMMAND = 38, 1 << 0;
#[cfg(feature = "version-5-0")]
const LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL_COMMAND = 38, 1 << 1;
#[cfg(feature = "version-5-0")]
const LE_PERIODIC_ADVERTISING_TERMINATE_SYNC_COMMAND = 38, 1 << 2;
#[cfg(feature = "version-5-0")]
const LE_ADD_DEVICE_TO_PERIODIC_ADVERTISER_LIST_COMMAND = 38, 1 << 3;
#[cfg(feature = "version-5-0")]
const LE_REMOVE_DEVICE_FROM_PERIODIC_ADVERTISER_LIST_COMMAND = 38, 1 << 4;
#[cfg(feature = "version-5-0")]
const LE_CLEAR_PERIODIC_ADVERTISER_LIST_COMMAND = 38, 1 << 5;
#[cfg(feature = "version-5-0")]
const LE_READ_PERIODIC_ADVERTISER_LIST_SIZE_COMMAND = 38, 1 << 6;
#[cfg(feature = "version-5-0")]
const LE_READ_TRANSMIT_POWER_COMMAND = 38, 1 << 7;
#[cfg(feature = "version-5-0")]
const LE_READ_RF_PATH_COMPENSATION_COMMAND = 39, 1 << 0;
#[cfg(feature = "version-5-0")]
const LE_WRITE_RF_PATH_COMPENSATION_COMMAND = 39, 1 << 1;
#[cfg(feature = "version-5-0")]
const LE_SET_PRIVACY_MODE = 39, 1 << 2;
}
impl Debug for CommandFlags {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
writeln!(f, "{:?}", &self.0[..16])?;
writeln!(f, "{:?}", &self.0[16..32])?;
writeln!(f, "{:?}", &self.0[32..39])
}
}
impl<'a> TryFrom<&'a [u8]> for CommandFlags {
type Error = crate::event::Error<crate::event::NeverError>;
fn try_from(value: &[u8]) -> Result<CommandFlags, Self::Error> {
require_len!(value, COMMAND_FLAGS_SIZE);
CommandFlags::from_bits(value).ok_or(crate::event::Error::BadCommandFlag)
}
}
fn to_supported_commands<VE, VS>(
bytes: &[u8],
) -> Result<LocalSupportedCommands<VS>, crate::event::Error<VE>>
where
Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
require_len!(bytes, 1 + COMMAND_FLAGS_SIZE);
Ok(LocalSupportedCommands {
status: bytes[0].try_into().map_err(super::rewrap_bad_status)?,
supported_commands: bytes[1..=COMMAND_FLAGS_SIZE]
.try_into()
.map_err(|e| match e {
crate::event::Error::BadLength(actual, expected) => {
crate::event::Error::BadLength(actual, expected)
}
crate::event::Error::BadCommandFlag => crate::event::Error::BadCommandFlag,
_ => unreachable!(),
})?,
})
}
#[derive(Copy, Clone, Debug)]
pub struct LocalSupportedFeatures<VS> {
pub status: Status<VS>,
pub supported_features: LmpFeatures,
}
bitflags! {
pub struct LmpFeatures : u64 {
const THREE_SLOT_PACKETS = 1 << 0;
const FIVE_SLOT_PACKETS = 1 << 1;
const ENCRYPTION = 1 << 2;
const SLOT_OFFSET = 1 << 3;
const TIMING_ACCURACY = 1 << 4;
const ROLE_SWITCH = 1 << 5;
const HOLD_MODE = 1 << 6;
const SNIFF_MODE = 1 << 7;
const POWER_CONTROL_REQUESTS = 1 << 9;
const CHANNEL_QUALITY_DRIVEN_DATA_RATE_CQDDR = 1 << 10;
const SCO_LINK = 1 << 11;
const HV2_PACKETS = 1 << 12;
const HV3_PACKETS = 1 << 13;
const MU_LAW_LOG_SYNCHRONOUS_DATA = 1 << 14;
const A_LAW_LOG_SYNCHRONOUS_DATA = 1 << 15;
const CVSD_SYNCHRONOUS_DATA = 1 << 16;
const PAGING_PARAMETER_NEGOTIATION = 1 << 17;
const POWER_CONTROL = 1 << 18;
const TRANSPARENT_SYNCHRONOUS_DATA = 1 << 19;
const FLOW_CONTROL_LAG_LSB = 1 << 20;
const FLOW_CONTROL_LAG_MID = 1 << 21;
const FLOW_CONTROL_LAG_MSB = 1 << 22;
const BROADCAST_ENCRYPTION = 1 << 23;
const ENHANCED_DATA_RATE_ACL_2_MB_PER_S_MODE = 1 << 25;
const ENHANCED_DATA_RATE_ACL_3_MB_PER_S_MODE = 1 << 26;
const ENHANCED_INQUIRY_SCAN = 1 << 27;
const INTERLACED_INQUIRY_SCAN = 1 << 28;
const INTERLACED_PAGE_SCAN = 1 << 29;
const RSSI_WITH_INQUIRY_RESULTS = 1 << 30;
const EXTENDED_SCO_LINK_EV3_PACKETS = 1 << 31;
const EV4_PACKETS = 1 << 32;
const EV5_PACKETS = 1 << 33;
const AFH_CAPABLE_PERIPHERAL = 1 << 35;
const AFH_CLASSIFICATION_PERIPHERAL = 1 << 36;
const BR_EDR_NOT_SUPPORTED = 1 << 37;
const LE_SUPPORTED_BY_CONTROLLER = 1 << 38;
const THREE_SLOT_ENHANCED_DATA_RATE_ACL_PACKETS = 1 << 39;
const FIVE_SLOT_ENHANCED_DATA_RATE_ACL_PACKETS = 1 << 40;
const SNIFF_SUBRATING = 1 << 41;
const PAUSE_ENCRYPTION = 1 << 42;
const AFH_CAPABLE_CENTRAL_DEVICE = 1 << 43;
const AFH_CLASSIFICATION_CENTRAL_DEVICE = 1 << 44;
const ENHANCED_DATA_RATE_ESCO_2_MB_PER_S_MODE = 1 << 45;
const ENHANCED_DATA_RATE_ESCO_3_MB_PER_S_MODE = 1 << 46;
const THREE_SLOT_ENHANCED_DATA_RATE_ESCO_PACKETS = 1 << 47;
const EXTENDED_INQUIRY_RESPONSE = 1 << 48;
const SIMULTANEOUS_LE_AND_BR_EDR_TO_SAME_DEVICE_CAPABLE = 1 << 49;
const SECURE_SIMPLE_PAIRING = 1 << 51;
const ENCAPSULATED_PDU = 1 << 52;
const ERRONEOUS_DATA_REPORTING = 1 << 53;
const NON_FLUSHABLE_PACKET_BOUNDARY_FLAG = 1 << 54;
const LINK_SUPERVISION_TIMEOUT_CHANGED_EVENT = 1 << 56;
const INQUIRY_TX_POWER_LEVEL = 1 << 57;
const ENHANCED_POWER_CONTROL = 1 << 58;
const EXTENDED_FEATURES = 1 << 63;
}
}
fn to_supported_features<VE, VS>(
bytes: &[u8],
) -> Result<LocalSupportedFeatures<VS>, crate::event::Error<VE>>
where
Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
require_len!(bytes, 9);
Ok(LocalSupportedFeatures {
status: to_status(bytes)?,
supported_features: LmpFeatures::from_bits_truncate(LittleEndian::read_u64(&bytes[1..])),
})
}
#[derive(Copy, Clone, Debug)]
pub struct ReadBdAddr<VS> {
pub status: Status<VS>,
pub bd_addr: crate::BdAddr,
}
fn to_bd_addr<VE, VS>(bytes: &[u8]) -> Result<ReadBdAddr<VS>, crate::event::Error<VE>>
where
Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
require_len!(bytes, 7);
let mut bd_addr = crate::BdAddr([0; 6]);
bd_addr.0.copy_from_slice(&bytes[1..]);
Ok(ReadBdAddr {
status: to_status(bytes)?,
bd_addr,
})
}
#[derive(Copy, Clone, Debug)]
pub struct ReadRssi<VS> {
pub status: Status<VS>,
pub conn_handle: ConnectionHandle,
pub rssi: i8,
}
fn to_read_rssi<VE, VS>(bytes: &[u8]) -> Result<ReadRssi<VS>, crate::event::Error<VE>>
where
Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
require_len!(bytes, 4);
Ok(ReadRssi {
status: to_status(bytes)?,
conn_handle: ConnectionHandle(LittleEndian::read_u16(&bytes[1..])),
rssi: unsafe { mem::transmute::<u8, i8>(bytes[3]) },
})
}
#[derive(Copy, Clone, Debug)]
pub struct LeReadBufferSize<VS> {
pub status: Status<VS>,
pub data_packet_length: u16,
pub data_packet_count: u8,
}
fn to_le_read_buffer_status<VE, VS>(
bytes: &[u8],
) -> Result<LeReadBufferSize<VS>, crate::event::Error<VE>>
where
Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
require_len!(bytes, 4);
Ok(LeReadBufferSize {
status: to_status(bytes)?,
data_packet_length: LittleEndian::read_u16(&bytes[1..]),
data_packet_count: bytes[3],
})
}
#[derive(Copy, Clone, Debug)]
pub struct LeSupportedFeatures<VS> {
pub status: Status<VS>,
pub supported_features: LeFeatures,
}
bitflags! {
pub struct LeFeatures : u64 {
const ENCRYPTION = 1 << 0;
const CONNECTION_PARAMETERS_REQUEST_PROCEDURE = 1 << 1;
const EXTENDED_REJECT_INDICATION = 1 << 2;
const PERIPHERALINITIATED_FEATURES_EXCHANGE = 1 << 3;
const PING = 1 << 4;
#[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
const DATA_PACKET_LENGTH_EXTENSION = 1 << 5;
#[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
const LL_PRIVACY = 1 << 6;
#[cfg(any(feature = "version-4-2", feature = "version-5-0"))]
const EXTENDED_SCANNER_FILTER_POLICIES = 1 << 7;
#[cfg(feature = "version-5-0")]
const PHY_2M = 1 << 8;
#[cfg(feature = "version-5-0")]
const STABLE_MODULATION_INDEX_TX = 1 << 9;
#[cfg(feature = "version-5-0")]
const STABLE_MODULATION_INDEX_RX = 1 << 10;
#[cfg(feature = "version-5-0")]
const CODED_PHY = 1 << 11;
#[cfg(feature = "version-5-0")]
const EXTENDED_ADVERTISING = 1 << 12;
#[cfg(feature = "version-5-0")]
const PERIODIC_ADVERTISING = 1 << 13;
#[cfg(feature = "version-5-0")]
const CHANNEL_SELECTION_ALGORITHM_2 = 1 << 14;
#[cfg(feature = "version-5-0")]
const POWER_CLASS_1 = 1 << 15;
#[cfg(feature = "version-5-0")]
const MINIMUM_NUMBER_OF_USED_CHANNELS_PROCEDURE = 1 << 16;
}
}
fn to_le_local_supported_features<VE, VS>(
bytes: &[u8],
) -> Result<LeSupportedFeatures<VS>, crate::event::Error<VE>>
where
Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
require_len!(bytes, 9);
Ok(LeSupportedFeatures {
status: to_status(bytes)?,
supported_features: LeFeatures::from_bits_truncate(LittleEndian::read_u64(&bytes[1..])),
})
}
#[derive(Copy, Clone, Debug)]
pub struct LeAdvertisingChannelTxPower<VS> {
pub status: Status<VS>,
pub power: i8,
}
fn to_le_advertising_channel_tx_power<VE, VS>(
bytes: &[u8],
) -> Result<LeAdvertisingChannelTxPower<VS>, crate::event::Error<VE>>
where
Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
require_len!(bytes, 2);
Ok(LeAdvertisingChannelTxPower {
status: to_status(bytes)?,
power: unsafe { mem::transmute::<u8, i8>(bytes[1]) },
})
}
#[cfg(not(feature = "version-5-0"))]
fn to_le_set_advertise_enable<V>(status: Status<V::Status>) -> ReturnParameters<V>
where
V: super::VendorEvent,
{
ReturnParameters::LeSetAdvertiseEnable(status)
}
#[cfg(feature = "version-5-0")]
fn to_le_set_advertise_enable<V>(status: Status<V::Status>) -> ReturnParameters<V>
where
V: super::VendorEvent,
{
ReturnParameters::LeSetAdvertisingEnable(status)
}
#[derive(Copy, Clone, Debug)]
pub struct ChannelMapParameters<VS> {
pub status: Status<VS>,
pub conn_handle: ConnectionHandle,
pub channel_map: crate::ChannelClassification,
}
fn to_le_channel_map_parameters<VE, VS>(
bytes: &[u8],
) -> Result<ChannelMapParameters<VS>, crate::event::Error<VE>>
where
Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
require_len!(bytes, 8);
let mut channel_bits = [0; 5];
channel_bits.copy_from_slice(&bytes[3..8]);
let channel_bits = channel_bits;
Ok(ChannelMapParameters {
status: to_status(&bytes[0..])?,
conn_handle: ConnectionHandle(LittleEndian::read_u16(&bytes[1..])),
channel_map: crate::ChannelClassification::from_bits(&bytes[3..])
.ok_or_else(|| crate::event::Error::InvalidChannelMap(channel_bits))?,
})
}
#[derive(Copy, Clone, Debug)]
pub struct EncryptedReturnParameters<VS> {
pub status: Status<VS>,
pub encrypted_data: EncryptedBlock,
}
#[derive(Copy, Clone)]
pub struct EncryptedBlock(pub [u8; 16]);
impl Debug for EncryptedBlock {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
writeln!(f, "AES-128 Encrypted Data ({:X?})", &self.0)
}
}
fn to_le_encrypted_data<VE, VS>(
bytes: &[u8],
) -> Result<EncryptedReturnParameters<VS>, crate::event::Error<VE>>
where
Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
require_len!(bytes, 17);
let mut block = [0; 16];
block.copy_from_slice(&bytes[1..]);
Ok(EncryptedReturnParameters {
status: to_status(&bytes)?,
encrypted_data: EncryptedBlock(block),
})
}
#[derive(Copy, Clone, Debug)]
pub struct LeRandom<VS> {
pub status: Status<VS>,
pub random_number: u64,
}
fn to_random_number<VE, VS>(bytes: &[u8]) -> Result<LeRandom<VS>, crate::event::Error<VE>>
where
Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
require_len!(bytes, 9);
Ok(LeRandom {
status: to_status(&bytes)?,
random_number: LittleEndian::read_u64(&bytes[1..]),
})
}
#[derive(Copy, Clone, Debug)]
pub struct LeLongTermRequestReply<VS> {
pub status: Status<VS>,
pub conn_handle: ConnectionHandle,
}
fn to_le_ltk_request_reply<VE, VS>(
bytes: &[u8],
) -> Result<LeLongTermRequestReply<VS>, crate::event::Error<VE>>
where
Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
require_len!(bytes, 3);
Ok(LeLongTermRequestReply {
status: to_status(&bytes)?,
conn_handle: ConnectionHandle(LittleEndian::read_u16(&bytes[1..])),
})
}
#[derive(Copy, Clone, Debug)]
pub struct LeReadSupportedStates<VS> {
pub status: Status<VS>,
pub supported_states: LeStates,
}
bitflags! {
pub struct LeStates : u64 {
const NON_CONNECTABLE_ADVERTISING = 1 << 0;
const SCANNABLE_ADVERTISING = 1 << 1;
const CONNECTABLE_ADVERTISING = 1 << 2;
const DIRECTED_ADVERTISING_HIGH_DUTY_CYCLE = 1 << 3;
const PASSIVE_SCANNING = 1 << 4;
const ACTIVE_SCANNING = 1 << 5;
const INITIATING = 1 << 6;
const PERIPHERAL_CONNECTION = 1 << 7;
const NONCONN_AD_AND_PASS_SCAN = 1 << 8;
const SCAN_AD_AND_PASS_SCAN = 1 << 9;
const CONN_AD_AND_PASS_SCAN = 1 << 10;
const DIR_AD_HDC_AND_PASS_SCAN = 1 << 11;
const NONCONN_AD_AND_ACT_SCAN = 1 << 12;
const SCAN_AD_AND_ACT_SCAN = 1 << 13;
const CONN_AD_AND_ACT_SCAN = 1 << 14;
const DIR_AD_HDC_AND_ACT_SCAN = 1 << 15;
const NONCONN_AD_AND_INITIATING = 1 << 16;
const SCAN_AD_AND_INITIATING = 1 << 17;
const NONCONN_AD_AND_CENTRAL_CONN = 1 << 18;
const SCAN_AD_AND_CENTRAL_CONN = 1 << 19;
const NONCONN_AD_AND_PERIPH_CONN = 1 << 20;
const SCAN_AD_AND_PERIPH_CONN = 1 << 21;
const PASS_SCAN_AND_INITIATING = 1 << 22;
const ACT_SCAN_AND_INITIATING = 1 << 23;
const PASS_SCAN_AND_CENTRAL_CONN = 1 << 24;
const ACT_SCAN_AND_CENTRAL_CONN = 1 << 25;
const PASS_SCAN_AND_PERIPH_CONN = 1 << 26;
const ACT_SCAN_AND_PERIPH_CONN = 1 << 27;
const INITIATING_AND_CENTRAL_CONN = 1 << 28;
const DIRECTED_ADVERTISING_LOW_DUTY_CYCLE = 1 << 29;
const DIR_AD_LDC_AND_PASS_SCAN = 1 << 30;
const DIR_AD_LDC_AND_ACT_SCAN = 1 << 31;
const CONN_AD_AND_INITIATING = 1 << 32;
const DIR_AD_HDC_AND_INITIATING = 1 << 33;
const DIR_AD_LDC_AND_INITIATING = 1 << 34;
const CONN_AD_AND_CENTRAL_CONN = 1 << 35;
const DIR_AD_HDC_AND_CENTRAL_CONN = 1 << 36;
const DIR_AD_LDC_AND_CENTRAL_CONN = 1 << 37;
const CONN_AD_AND_PERIPH_CONN = 1 << 38;
const DIR_AD_HDC_AND_PERIPH_CONN = 1 << 39;
const DIR_AD_LDC_AND_PERIPH_CONN = 1 << 40;
const INITIATING_AND_PERIPH_CONN = 1 << 41;
}
}
fn to_le_read_states<VE, VS>(
bytes: &[u8],
) -> Result<LeReadSupportedStates<VS>, crate::event::Error<VE>>
where
Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
require_len!(bytes, 9);
let bitfield = LittleEndian::read_u64(&bytes[1..]);
Ok(LeReadSupportedStates {
status: to_status(bytes)?,
supported_states: LeStates::from_bits(bitfield)
.ok_or_else(|| crate::event::Error::InvalidLeStates(bitfield))?,
})
}
#[derive(Copy, Clone, Debug)]
pub struct LeTestEnd<VS> {
pub status: Status<VS>,
pub number_of_packets: usize,
}
fn to_le_test_end<VE, VS>(bytes: &[u8]) -> Result<LeTestEnd<VS>, crate::event::Error<VE>>
where
Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
require_len!(bytes, 3);
Ok(LeTestEnd {
status: to_status(bytes)?,
number_of_packets: LittleEndian::read_u16(&bytes[1..]) as usize,
})
}