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