1// Copyright 2023 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// https://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15syntax = "proto3"; 16 17package pandora.l2cap; 18 19import "google/protobuf/any.proto"; 20import "google/protobuf/empty.proto"; 21import "pandora/host.proto"; 22 23option java_outer_classname = "L2CAPProto"; 24 25// L2CAP (Logical Link Control and Adaptation Protocol) services for managing channels 26// and data communication over ACL connections. This protocol is essential for 27// creating multiplexed data channels over the underlying ACL connections in Bluetooth. 28service L2CAP { 29 // Establish an L2CAP channel on an ACL connection. 30 rpc Connect(ConnectRequest) returns (ConnectResponse); 31 // Await and accept an incoming L2CAP channel on an existing ACL connection. 32 // Every incoming L2CAP channel connection request not handled by this 33 // method should be rejected. 34 rpc WaitConnection(WaitConnectionRequest) returns (WaitConnectionResponse); 35 // Disconnect an established L2CAP channel. 36 rpc Disconnect(DisconnectRequest) returns (DisconnectResponse); 37 // Await an established L2CAP channel's termination. 38 rpc WaitDisconnection(WaitDisconnectionRequest) returns (WaitDisconnectionResponse); 39 // Fetch data received from an active L2CAP channel. 40 // Packets are yielded until the stream is closed, packets are dropped otherwise. 41 rpc Receive(ReceiveRequest) returns (stream ReceiveResponse); 42 // Send data over an L2CAP channel to a connected device. 43 rpc Send(SendRequest) returns (SendResponse); 44} 45 46// Potential reasons for command rejections in the L2CAP protocol. 47enum CommandRejectReason { 48 // The command wasn't understood by the receiver. 49 COMMAND_NOT_UNDERSTOOD = 0; 50 // The received signal exceeds the allowed MTU (Maximum Transmission Unit). 51 SIGNAL_MTU_EXCEEDED = 1; 52 // The received command includes an invalid Channel Identifier (CID). 53 INVALID_CID_IN_REQUEST = 2; 54} 55 56// A Token representing a unique L2CAP channel for data communication. 57message Channel { 58 // Opaque value filled by the gRPC server, must not be modified nor crafted. 59 google.protobuf.Any cookie = 1; 60} 61 62// Fixed channel, represented by a `Connection` and a Fixed Channel Identifier (CID). 63message FixedChannel { 64 // Specifies the underlying ACL connection, either BR/EDR (Basic Rate/Enhanced Data Rate) or BLE. 65 Connection connection = 1; 66 // Fixed Channel Identifier (CID). Represents the unique identifier for the fixed channel. 67 // Available CIDs are: 68 // - 0x0001: L2CAP Signaling Channel 69 // - 0x0002: Connectionless Channel 70 // - 0x0003: AMP Manager Protocol 71 // - 0x0004: Attribute Protocol (ATT) for BLE 72 // - 0x0005: L2CAP Signaling Channel for BLE 73 // - 0x0006: Security Manager Protocol for BLE 74 // - 0x0007: Security Manager Protocol for BR/EDR 75 // - CIDs in the range of 0x0007 to 0x003F are reserved for standardization purposes. 76 uint32 cid = 2; 77} 78 79// Request for establishing an L2CAP connection-oriented channel, 80// where data is transmitted with acknowledgment. 81message ConnectionOrientedChannelRequest { 82 // Protocol/Service Multiplexer (PSM) for identifying the upper-layer protocol. 83 uint32 psm = 1; 84 // Defines the maximum size of data payload (in bytes) that can be sent in a single packet. 85 uint32 mtu = 2; 86} 87 88// Request for establishing a credit-based L2CAP channel, 89// typically used in BLE (Bluetooth Low Energy) when precise flow control is required. 90message CreditBasedChannelRequest { 91 // Simplified Protocol/Service Multiplexer (sPSM) for identifying the upper-layer protocol in BLE. 92 uint32 spsm = 1; 93 // Defines the maximum size of data payload (in bytes) that can be sent in a single packet. 94 uint32 mtu = 2; 95 // Maximum size of the PDU (Protocol Data Unit) payload. 96 uint32 mps = 3; 97 // Initial credits given for flow control, defining the number of PDUs the sender can transmit. 98 uint32 initial_credit = 4; 99} 100 101// Request of the `Connect` method. 102message ConnectRequest { 103 // Specifies the underlying ACL connection, either BR/EDR (Basic Rate/Enhanced Data Rate) or BLE. 104 Connection connection = 1; 105 // Defines the type and specifics of the channel to establish. 106 oneof type { 107 // Request a connection-oriented channel. 108 ConnectionOrientedChannelRequest basic = 2; 109 // Request a BLE credit-based channel. 110 CreditBasedChannelRequest le_credit_based = 3; 111 // Request an enhanced credit-based channel. 112 CreditBasedChannelRequest enhanced_credit_based = 4; 113 } 114} 115 116// Response of the `Connect` method. 117message ConnectResponse { 118 oneof result { 119 // Error details if the connection failed. 120 CommandRejectReason error = 1; 121 // Details of the established channel on success. 122 Channel channel = 2; 123 } 124} 125 126// Request of the `WaitConnection` method. 127message WaitConnectionRequest { 128 // Specifies the underlying ACL connection, either BR/EDR or BLE. 129 Connection connection = 1; 130 // Defines the type and specifics of the channel to wait and accept. 131 oneof type { 132 // Accept connection-oriented channels. 133 ConnectionOrientedChannelRequest basic = 2; 134 // Accept BLE credit-based channels. 135 CreditBasedChannelRequest le_credit_based = 3; 136 // Accept enhanced credit-based channels. 137 CreditBasedChannelRequest enhanced_credit_based = 4; 138 } 139} 140 141// Response of the `WaitConnection` method. 142message WaitConnectionResponse { 143 oneof result { 144 CommandRejectReason error = 1; 145 Channel channel = 2; 146 } 147} 148 149// Request of the `Disconnect` method. 150message DisconnectRequest { 151 // Specifies the channel to disconnect. 152 Channel channel = 1; 153} 154 155// Response of the `Disconnect` method. 156message DisconnectResponse { 157 oneof result { 158 CommandRejectReason error = 1; 159 google.protobuf.Empty success = 2; 160 } 161} 162 163// Request of the `WaitDisconnection` method. 164message WaitDisconnectionRequest { 165 // Specifies the channel to await disconnection. 166 Channel channel = 1; 167} 168 169// Response of the `WaitDisconnection` method. 170message WaitDisconnectionResponse { 171 oneof result { 172 CommandRejectReason error = 1; 173 google.protobuf.Empty success = 2; 174 } 175} 176 177// Request of the `Receive` method. 178message ReceiveRequest { 179 // Specifies the channel to fetch data from. 180 oneof source { 181 // Fetch data from a dynamic channel. 182 Channel channel = 1; 183 // Fetch data from a fixed channel. 184 FixedChannel fixed_channel = 2; 185 } 186} 187 188// Response of the `Receive` method. 189message ReceiveResponse { 190 // Contains the data received from the channel. 191 bytes data = 1; 192} 193 194// Request of the `Send` method. 195message SendRequest { 196 // Specifies the channel to send data over. 197 oneof sink { 198 // Send data over a dynamic channel. 199 Channel channel = 1; 200 // Send data over a fixed channel. 201 FixedChannel fixed_channel = 2; 202 } 203 // Data to be sent over the specified channel. 204 bytes data = 3; 205} 206 207// Response of the `Send` method. 208message SendResponse { 209 oneof result { 210 CommandRejectReason error = 1; 211 google.protobuf.Empty success = 2; 212 } 213} 214