little_endian_packets checksum Fcs : 16 "l2cap/" packet BasicFrame { _size_(_payload_) : 16, channel_id : 16, _payload_, } packet BasicFrameWithFcs { _checksum_start_(fcs), _size_(_payload_) : 16, channel_id : 16, _payload_ : [+2*8], // Include Fcs in the _size_ fcs : Fcs, } enum Continuation : 1 { END = 0, CONTINUE = 1, } // ChannelId 2 is connectionless packet GroupFrame : BasicFrame (channel_id = 0x02) { psm : 16, _payload_, } enum FrameType : 1 { I_FRAME = 0, S_FRAME = 1, } enum SupervisoryFunction : 2 { RECEIVER_READY = 0, REJECT = 1, RECEIVER_NOT_READY = 2, SELECT_REJECT = 3, } enum RetransmissionDisable : 1 { NORMAL = 0, DISABLE = 1, } enum SegmentationAndReassembly : 2 { UNSEGMENTED = 0, START = 1, END = 2, CONTINUATION = 3, } packet StandardFrame : BasicFrame { frame_type : FrameType, _body_, } packet StandardFrameWithFcs : BasicFrameWithFcs { frame_type : FrameType, _body_, } group StandardSupervisoryControl { _fixed_ = 0 : 1, s : SupervisoryFunction, _reserved_ : 3, r : RetransmissionDisable, req_seq : 6, _reserved_ : 2, } group StandardInformationControl { tx_seq : 6, r : RetransmissionDisable, req_seq : 6, sar : SegmentationAndReassembly, } packet StandardSupervisoryFrame : StandardFrame (frame_type = S_FRAME) { StandardSupervisoryControl, } packet StandardSupervisoryFrameWithFcs : StandardFrameWithFcs (frame_type = S_FRAME) { StandardSupervisoryControl, } packet StandardInformationFrame : StandardFrame (frame_type = I_FRAME) { StandardInformationControl, _payload_, } packet StandardInformationFrameWithFcs : StandardFrameWithFcs (frame_type = I_FRAME) { StandardInformationControl, _payload_, } packet StandardInformationStartFrame : StandardInformationFrame (sar = START) { l2cap_sdu_length : 16, _payload_, } packet StandardInformationStartFrameWithFcs : StandardInformationFrameWithFcs (sar = START) { l2cap_sdu_length : 16, _payload_, } enum Poll : 1 { NOT_SET = 0, POLL = 1, } enum Final : 1 { NOT_SET = 0, POLL_RESPONSE = 1, } group EnhancedSupervisoryControl { _fixed_ = 0 : 1, s : SupervisoryFunction, p : Poll, _reserved_ : 2, f : Final, req_seq : 6, _reserved_ : 2, } group EnhancedInformationControl { tx_seq : 6, f : Final, req_seq : 6, sar : SegmentationAndReassembly, } packet EnhancedSupervisoryFrame : StandardFrame (frame_type = S_FRAME) { EnhancedSupervisoryControl, } packet EnhancedSupervisoryFrameWithFcs : StandardFrameWithFcs (frame_type = S_FRAME) { EnhancedSupervisoryControl, } packet EnhancedInformationFrame : StandardFrame (frame_type = I_FRAME) { EnhancedInformationControl, _payload_, } packet EnhancedInformationFrameWithFcs : StandardFrameWithFcs (frame_type = I_FRAME) { EnhancedInformationControl, _payload_, } packet EnhancedInformationStartFrame : EnhancedInformationFrame (sar = START) { l2cap_sdu_length : 16, _payload_, } packet EnhancedInformationStartFrameWithFcs : EnhancedInformationFrameWithFcs (sar = START) { l2cap_sdu_length : 16, _payload_, } group ExtendedSupervisoryControl { f : Final, req_seq : 14, s : SupervisoryFunction, p : Poll, _reserved_ : 5, _reserved_ : 8, } group ExtendedInformationControl { f : Final, req_seq : 14, sar : SegmentationAndReassembly, tx_seq : 14, } packet ExtendedSupervisoryFrame : StandardFrame (frame_type = S_FRAME) { ExtendedSupervisoryControl, } packet ExtendedSupervisoryFrameWithFcs : StandardFrameWithFcs (frame_type = S_FRAME) { ExtendedSupervisoryControl, } packet ExtendedInformationFrame : StandardFrame (frame_type = I_FRAME) { ExtendedInformationControl, _payload_, } packet ExtendedInformationFrameWithFcs : StandardFrameWithFcs (frame_type = I_FRAME) { ExtendedInformationControl, _payload_, } packet ExtendedInformationStartFrame : ExtendedInformationFrame (sar = START) { l2cap_sdu_length : 16, _payload_, } packet ExtendedInformationStartFrameWithFcs : ExtendedInformationFrameWithFcs (sar = START) { l2cap_sdu_length : 16, _payload_, } packet FirstLeInformationFrame : BasicFrame { l2cap_sdu_length : 16, _payload_, } enum CommandCode : 8 { COMMAND_REJECT = 0x01, CONNECTION_REQUEST = 0x02, CONNECTION_RESPONSE = 0x03, CONFIGURATION_REQUEST = 0x04, CONFIGURATION_RESPONSE = 0x05, DISCONNECTION_REQUEST = 0x06, DISCONNECTION_RESPONSE = 0x07, ECHO_REQUEST = 0x08, ECHO_RESPONSE = 0x09, INFORMATION_REQUEST = 0x0A, INFORMATION_RESPONSE = 0x0B, CREATE_CHANNEL_REQUEST = 0x0C, CREATE_CHANNEL_RESPONSE = 0x0D, MOVE_CHANNEL_REQUEST = 0x0E, MOVE_CHANNEL_RESPONSE = 0x0F, MOVE_CHANNEL_CONFIRMATION_REQUEST = 0x10, MOVE_CHANNEL_CONFIRMATION_RESPONSE = 0x11, } packet ControlFrame : BasicFrame (channel_id = 0x0001) { _payload_, } packet Control { code : CommandCode, identifier : 8, _size_(_payload_) : 16, _payload_, } enum CommandRejectReason : 16 { COMMAND_NOT_UNDERSTOOD = 0x0000, SIGNALING_MTU_EXCEEDED = 0x0001, INVALID_CID_IN_REQUEST = 0x0002, } packet CommandReject : Control (code = COMMAND_REJECT) { reason : CommandRejectReason, _body_, } packet CommandRejectNotUnderstood : CommandReject (reason = COMMAND_NOT_UNDERSTOOD) { } packet CommandRejectMtuExceeded : CommandReject (reason = SIGNALING_MTU_EXCEEDED) { actual_mtu : 16, } packet CommandRejectInvalidCid : CommandReject (reason = INVALID_CID_IN_REQUEST) { local_channel : 16, // Relative to the sender of the CommandReject remote_channel : 16, } packet ConnectionRequest : Control (code = CONNECTION_REQUEST) { psm : 16, source_cid : 16, } enum ConnectionResponseResult : 16 { SUCCESS = 0x0000, PENDING = 0x0001, PSM_NOT_SUPPORTED = 0x0002, SECURITY_BLOCK = 0x0003, NO_RESOURCES_AVAILABLE = 0x0004, INVALID_CID = 0x0006, SOURCE_CID_ALREADY_ALLOCATED = 0x0007, } enum ConnectionResponseStatus : 16 { NO_FURTHER_INFORMATION_AVAILABLE = 0x0000, AUTHENTICATION_PENDING = 0x0001, AUTHORIZATION_PENDING = 0x0002, } packet ConnectionResponse : Control (code = CONNECTION_RESPONSE) { destination_cid : 16, source_cid : 16, result : ConnectionResponseResult, status : ConnectionResponseStatus, } enum ConfigurationOptionType : 7 { MTU = 0x01, FLUSH_TIMEOUT = 0x02, QUALITY_OF_SERVICE = 0x03, RETRANSMISSION_AND_FLOW_CONTROL = 0x04, FRAME_CHECK_SEQUENCE = 0x05, EXTENDED_FLOW_SPECIFICATION = 0x06, EXTENDED_WINDOW_SIZE = 0x07, } enum ConfigurationOptionIsHint : 1 { OPTION_MUST_BE_RECOGNIZED = 0, OPTION_IS_A_HINT = 1, } struct ConfigurationOption { type : ConfigurationOptionType, is_hint : ConfigurationOptionIsHint, length : 8, _body_, } struct MtuConfigurationOption : ConfigurationOption (type = MTU, length = 2) { mtu : 16, } struct FlushTimeoutConfigurationOption : ConfigurationOption (type = FLUSH_TIMEOUT, length = 2) { flush_timeout : 16, } enum QosServiceType : 8 { NO_TRAFFIC = 0x00, BEST_EFFORT = 0x01, // Default GUARANTEED = 0x02, } struct QualityOfServiceConfigurationOption : ConfigurationOption (type = QUALITY_OF_SERVICE, length = 22) { _reserved_ : 8, // Flags service_type : QosServiceType, token_rate : 32, // 0 = ignore, 0xffffffff = max available token_bucket_size : 32, // 0 = ignore, 0xffffffff = max available peak_bandwidth : 32, // Octets/second 0 = ignore latency : 32, // microseconds 0xffffffff = ignore delay_variation : 32, // microseconds 0xffffffff = ignore } enum RetransmissionAndFlowControlModeOption : 8 { L2CAP_BASIC = 0x00, RETRANSMISSION = 0x01, FLOW_CONTROL = 0x02, ENHANCED_RETRANSMISSION = 0x03, STREAMING = 0x04, } struct RetransmissionAndFlowControlConfigurationOption : ConfigurationOption (type = RETRANSMISSION_AND_FLOW_CONTROL, length = 9) { mode : RetransmissionAndFlowControlModeOption, tx_window_size : 8, // 1-32 for Flow Control and Retransmission, 1-63 for Enhanced max_transmit : 8, retransmission_time_out : 16, monitor_time_out : 16, maximum_pdu_size : 16, } enum FcsType : 8 { NO_FCS = 0, DEFAULT = 1, // 16-bit FCS } struct FrameCheckSequenceOption : ConfigurationOption (type = FRAME_CHECK_SEQUENCE, length = 1) { fcs_type : FcsType, } struct ExtendedFlowSpecificationOption : ConfigurationOption (type = EXTENDED_FLOW_SPECIFICATION, length = 16) { identifier : 8, // Default 0x01, must be 0x01 for Extended Flow-Best-Effort service_type : QosServiceType, maximum_sdu_size : 16, // Octets sdu_interarrival_time : 32, // in microseconds access_latency : 32, // in microseconds, without HCI and stack overheads flush_timeout : 32, // in microseconds 0x0 = no retransmissions 0xFFFFFFFF = never flushed } struct ExtendedWindowSizeOption : ConfigurationOption (type = EXTENDED_WINDOW_SIZE, length = 2) { max_window_size : 16, // 0x0000 = Valid for streaming, 0x0001-0x3FFF Valid for Enhanced Retransmission } packet ConfigurationRequest : Control (code = CONFIGURATION_REQUEST) { destination_cid : 16, continuation : Continuation, _reserved_ : 15, config : ConfigurationOption[], } enum ConfigurationResponseResult : 16 { SUCCESS = 0x0000, UNACCEPTABLE_PARAMETERS = 0x0001, REJECTED = 0x0002, UNKNOWN_OPTIONS = 0x0003, PENDING = 0x0004, FLOW_SPEC_REJECTED = 0x0005, } packet ConfigurationResponse : Control (code = CONFIGURATION_RESPONSE) { source_cid : 16, continuation : Continuation, _reserved_ : 15, result : ConfigurationResponseResult, config : ConfigurationOption[], } packet DisconnectionRequest : Control (code = DISCONNECTION_REQUEST) { destination_cid : 16, source_cid : 16, } packet DisconnectionResponse : Control (code = DISCONNECTION_RESPONSE) { destination_cid : 16, source_cid : 16, } packet EchoRequest : Control (code = ECHO_REQUEST) { _payload_, // Optional and implementation specific } packet EchoResponse : Control (code = ECHO_RESPONSE) { _payload_, // Optional and implementation specific } enum InformationRequestInfoType : 16 { CONNECTIONLESS_MTU = 0x0001, EXTENDED_FEATURES_SUPPORTED = 0x0002, FIXED_CHANNELS_SUPPORTED = 0x0003, } packet InformationRequest : Control (code = INFORMATION_REQUEST) { info_type : InformationRequestInfoType, } enum InformationRequestResult : 16 { SUCCESS = 0x0000, NOT_SUPPORTED = 0x0001, } packet InformationResponse : Control (code = INFORMATION_RESPONSE) { info_type : InformationRequestInfoType, result : InformationRequestResult, _body_, } packet InformationResponseConnectionlessMtu : InformationResponse (info_type = CONNECTIONLESS_MTU) { connectionless_mtu : 16, } packet InformationResponseExtendedFeatures : InformationResponse (info_type = EXTENDED_FEATURES_SUPPORTED) { // ExtendedFeatureMask : 32, flow_control_mode : 1, retransmission_mode : 1, bi_directional_qoS : 1, enhanced_retransmission_mode : 1, streaming_mode : 1, fcs_option : 1, extended_flow_specification_for_br_edr : 1, fixed_channels : 1, extended_window_size : 1, unicast_connectionless_data_reception : 1, _reserved_ : 22, } packet InformationResponseFixedChannels : InformationResponse (info_type = FIXED_CHANNELS_SUPPORTED) { fixed_channels : 64, // bit 0 must be 0, bit 1 must be 1, all others 1 = supported } packet CreateChannelRequest : Control (code = CREATE_CHANNEL_REQUEST) { psm : 16, source_cid : 16, controller_id : 8, } enum CreateChannelResponseResult : 16 { SUCCESS = 0x0000, PENDING = 0x0001, PSM_NOT_SUPPORTED = 0x0002, SECURITY_BLOCK = 0x0003, NO_RESOURCES_AVAILABLE = 0x0004, CONTROLLER_ID_NOT_SUPPORTED = 0x0005, INVALID_CID = 0x0006, SOURCE_CID_ALREADY_ALLOCATED = 0x0007, } enum CreateChannelResponseStatus : 16 { NO_FURTHER_INFORMATION_AVAILABLE = 0x0000, AUTHENTICATION_PENDING = 0x0001, AUTHORIZATION_PENDING = 0x0002, } packet CreateChannelResponse : Control (code = CREATE_CHANNEL_RESPONSE) { destination_cid : 16, source_cid : 16, result : CreateChannelResponseResult, status : CreateChannelResponseStatus, } // AMP Only ? packet MoveChannelRequest : Control (code = MOVE_CHANNEL_REQUEST) { initiator_cid : 16, dest_controller_id : 8, } enum MoveChannelResponseResult : 16 { SUCCESS = 0x0000, PENDING = 0x0001, CONTROLLER_ID_NOT_SUPPORTED = 0x0002, NEW_CONTROLLER_ID_IS_SAME = 0x0003, CONFIGURATION_NOT_SUPPORTED = 0x0004, CHANNEL_COLLISION = 0x0005, CHANNEL_NOT_ALLOWED_TO_BE_MOVED = 0x0006, } packet MoveChannelResponse : Control (code = MOVE_CHANNEL_RESPONSE) { initiator_cid : 16, result : MoveChannelResponseResult, } enum MoveChannelConfirmationResult : 16 { SUCCESS = 0x0000, FAILURE = 0x0001, } packet MoveChannelConfirmationRequest : Control (code = MOVE_CHANNEL_CONFIRMATION_REQUEST) { initiator_cid : 16, result : MoveChannelConfirmationResult, } packet MoveChannelConfirmationResponse : Control (code = MOVE_CHANNEL_CONFIRMATION_RESPONSE) { initiator_cid : 16, } enum LeCommandCode : 8 { COMMAND_REJECT = 0x01, DISCONNECTION_REQUEST = 0x06, DISCONNECTION_RESPONSE = 0x07, CONNECTION_PARAMETER_UPDATE_REQUEST = 0x12, CONNECTION_PARAMETER_UPDATE_RESPONSE = 0x13, LE_CREDIT_BASED_CONNECTION_REQUEST = 0x14, LE_CREDIT_BASED_CONNECTION_RESPONSE = 0x15, LE_FLOW_CONTROL_CREDIT = 0x16, } packet LeControlFrame : BasicFrame (channel_id = 0x0005) { _payload_, } packet LeControl { code : LeCommandCode, identifier : 8, // Must be non-zero _size_(_payload_) : 16, _payload_, } packet LeCommandReject : LeControl (code = COMMAND_REJECT) { reason : CommandRejectReason, _payload_, } packet LeCommandRejectNotUnderstood : LeCommandReject (reason = COMMAND_NOT_UNDERSTOOD) { } packet LeCommandRejectMtuExceeded : LeCommandReject (reason = SIGNALING_MTU_EXCEEDED) { actual_mtu : 16, } packet LeCommandRejectInvalidCid : LeCommandReject (reason = INVALID_CID_IN_REQUEST) { local_channel : 16, // Relative to the sender of the CommandReject remote_channel : 16, } packet LeDisconnectionRequest : LeControl (code = DISCONNECTION_REQUEST) { destination_cid : 16, source_cid : 16, } packet LeDisconnectionResponse : LeControl (code = DISCONNECTION_RESPONSE) { destination_cid : 16, source_cid : 16, } packet ConnectionParameterUpdateRequest : LeControl (code = CONNECTION_PARAMETER_UPDATE_REQUEST) { interval_min : 16, interval_max : 16, slave_latency : 16, timeout_multiplier : 16, } enum ConnectionParameterUpdateResponseResult : 16 { ACCEPTED = 0, REJECTED = 1, } packet ConnectionParameterUpdateResponse : LeControl (code = CONNECTION_PARAMETER_UPDATE_RESPONSE) { result : ConnectionParameterUpdateResponseResult, } packet LeCreditBasedConnectionRequest : LeControl (code = LE_CREDIT_BASED_CONNECTION_REQUEST) { le_psm : 16, // 0x0001-0x007F Fixed, 0x0080-0x00FF Dynamic source_cid : 16, mtu : 16, mps : 16, initial_credits : 16, } enum LeCreditBasedConnectionResponseResult : 16 { SUCCESS = 0x0000, LE_PSM_NOT_SUPPORTED = 0x0002, NO_RESOURCES_AVAILABLE = 0x0004, INSUFFICIENT_AUTHENTICATION = 0x0005, INSUFFICIENT_AUTHORIZATION = 0x0006, INSUFFICIENT_ENCRYPTION_KEY_SIZE = 0x0007, INSUFFICIENT_ENCRYPTION = 0x0008, INVALID_SOURCE_CID = 0x0009, SOURCE_CID_ALREADY_ALLOCATED = 0x000A, UNACCEPTABLE_PARAMETERS = 0x000B, } packet LeCreditBasedConnectionResponse : LeControl (code = LE_CREDIT_BASED_CONNECTION_RESPONSE) { destination_cid : 16, mtu : 16, mps : 16, initial_credits : 16, result : LeCreditBasedConnectionResponseResult, } packet LeFlowControlCredit : LeControl (code = LE_FLOW_CONTROL_CREDIT) { cid : 16, // Receiver's destination CID credits : 16, }