blob: ae44cb1b899dba5478d761ba8deed2c1e40dc7d3 [file] [log] [blame]
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,
}