// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. syntax = "proto3"; package pandora.l2cap; import "google/protobuf/any.proto"; import "google/protobuf/empty.proto"; import "pandora/host.proto"; option java_outer_classname = "L2CAPProto"; // L2CAP (Logical Link Control and Adaptation Protocol) services for managing channels // and data communication over ACL connections. This protocol is essential for // creating multiplexed data channels over the underlying ACL connections in Bluetooth. service L2CAP { // Establish an L2CAP channel on an ACL connection. rpc Connect(ConnectRequest) returns (ConnectResponse); // Await and accept an incoming L2CAP channel on an existing ACL connection. // Every incoming L2CAP channel connection request not handled by this // method should be rejected. rpc WaitConnection(WaitConnectionRequest) returns (WaitConnectionResponse); // Disconnect an established L2CAP channel. rpc Disconnect(DisconnectRequest) returns (DisconnectResponse); // Await an established L2CAP channel's termination. rpc WaitDisconnection(WaitDisconnectionRequest) returns (WaitDisconnectionResponse); // Fetch data received from an active L2CAP channel. // Packets are yielded until the stream is closed, packets are dropped otherwise. rpc Receive(ReceiveRequest) returns (stream ReceiveResponse); // Send data over an L2CAP channel to a connected device. rpc Send(SendRequest) returns (SendResponse); } // Potential reasons for command rejections in the L2CAP protocol. enum CommandRejectReason { // The command wasn't understood by the receiver. COMMAND_NOT_UNDERSTOOD = 0; // The received signal exceeds the allowed MTU (Maximum Transmission Unit). SIGNAL_MTU_EXCEEDED = 1; // The received command includes an invalid Channel Identifier (CID). INVALID_CID_IN_REQUEST = 2; } // A Token representing a unique L2CAP channel for data communication. message Channel { // Opaque value filled by the gRPC server, must not be modified nor crafted. google.protobuf.Any cookie = 1; } // Fixed channel, represented by a `Connection` and a Fixed Channel Identifier (CID). message FixedChannel { // Specifies the underlying ACL connection, either BR/EDR (Basic Rate/Enhanced Data Rate) or BLE. Connection connection = 1; // Fixed Channel Identifier (CID). Represents the unique identifier for the fixed channel. // Available CIDs are: // - 0x0001: L2CAP Signaling Channel // - 0x0002: Connectionless Channel // - 0x0003: AMP Manager Protocol // - 0x0004: Attribute Protocol (ATT) for BLE // - 0x0005: L2CAP Signaling Channel for BLE // - 0x0006: Security Manager Protocol for BLE // - 0x0007: Security Manager Protocol for BR/EDR // - CIDs in the range of 0x0007 to 0x003F are reserved for standardization purposes. uint32 cid = 2; } // Request for establishing an L2CAP connection-oriented channel, // where data is transmitted with acknowledgment. message ConnectionOrientedChannelRequest { // Protocol/Service Multiplexer (PSM) for identifying the upper-layer protocol. uint32 psm = 1; // Defines the maximum size of data payload (in bytes) that can be sent in a single packet. uint32 mtu = 2; } // Request for establishing a credit-based L2CAP channel, // typically used in BLE (Bluetooth Low Energy) when precise flow control is required. message CreditBasedChannelRequest { // Simplified Protocol/Service Multiplexer (sPSM) for identifying the upper-layer protocol in BLE. uint32 spsm = 1; // Defines the maximum size of data payload (in bytes) that can be sent in a single packet. uint32 mtu = 2; // Maximum size of the PDU (Protocol Data Unit) payload. uint32 mps = 3; // Initial credits given for flow control, defining the number of PDUs the sender can transmit. uint32 initial_credit = 4; } // Request of the `Connect` method. message ConnectRequest { // Specifies the underlying ACL connection, either BR/EDR (Basic Rate/Enhanced Data Rate) or BLE. Connection connection = 1; // Defines the type and specifics of the channel to establish. oneof type { // Request a connection-oriented channel. ConnectionOrientedChannelRequest basic = 2; // Request a BLE credit-based channel. CreditBasedChannelRequest le_credit_based = 3; // Request an enhanced credit-based channel. CreditBasedChannelRequest enhanced_credit_based = 4; } } // Response of the `Connect` method. message ConnectResponse { oneof result { // Error details if the connection failed. CommandRejectReason error = 1; // Details of the established channel on success. Channel channel = 2; } } // Request of the `WaitConnection` method. message WaitConnectionRequest { // Specifies the underlying ACL connection, either BR/EDR or BLE. Connection connection = 1; // Defines the type and specifics of the channel to wait and accept. oneof type { // Accept connection-oriented channels. ConnectionOrientedChannelRequest basic = 2; // Accept BLE credit-based channels. CreditBasedChannelRequest le_credit_based = 3; // Accept enhanced credit-based channels. CreditBasedChannelRequest enhanced_credit_based = 4; } } // Response of the `WaitConnection` method. message WaitConnectionResponse { oneof result { CommandRejectReason error = 1; Channel channel = 2; } } // Request of the `Disconnect` method. message DisconnectRequest { // Specifies the channel to disconnect. Channel channel = 1; } // Response of the `Disconnect` method. message DisconnectResponse { oneof result { CommandRejectReason error = 1; google.protobuf.Empty success = 2; } } // Request of the `WaitDisconnection` method. message WaitDisconnectionRequest { // Specifies the channel to await disconnection. Channel channel = 1; } // Response of the `WaitDisconnection` method. message WaitDisconnectionResponse { oneof result { CommandRejectReason error = 1; google.protobuf.Empty success = 2; } } // Request of the `Receive` method. message ReceiveRequest { // Specifies the channel to fetch data from. oneof source { // Fetch data from a dynamic channel. Channel channel = 1; // Fetch data from a fixed channel. FixedChannel fixed_channel = 2; } } // Response of the `Receive` method. message ReceiveResponse { // Contains the data received from the channel. bytes data = 1; } // Request of the `Send` method. message SendRequest { // Specifies the channel to send data over. oneof sink { // Send data over a dynamic channel. Channel channel = 1; // Send data over a fixed channel. FixedChannel fixed_channel = 2; } // Data to be sent over the specified channel. bytes data = 3; } // Response of the `Send` method. message SendResponse { oneof result { CommandRejectReason error = 1; google.protobuf.Empty success = 2; } }