xref: /haiku/headers/private/bluetooth/l2cap.h (revision 7eab6b486ebadb54ca3c306601f4b04dd92359fa)
1 /*
2  * Copyright 2024, Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 #ifndef _L2CAP_H_
6 #define _L2CAP_H_
7 
8 #include <bluetooth/bluetooth.h>
9 
10 
11 /* Channel IDs */
12 /*! These are unique for a unit. Thus the total number of channels that a unit
13  * can have open simultaneously is (L2CAP_LAST_CID - L2CAP_FIRST_CID) = 65471.
14  * (This does not depend on the number of connections.) */
15 #define L2CAP_NULL_CID		0x0000
16 #define L2CAP_SIGNALING_CID	0x0001
17 #define L2CAP_CONNECTIONLESS_CID 0x0002
18 	/* 0x0003-0x003f: reserved */
19 #define L2CAP_FIRST_CID		0x0040
20 #define L2CAP_LAST_CID		0xffff
21 
22 
23 /* Idents */
24 /*! Command idents are unique within a connection, since there is only one
25  * L2CAP_SIGNALING_CID. Thus only (L2CAP_LAST_IDENT - L2CAP_FIRST_IDENT),
26  * i.e. 254, commands can be pending simultaneously for a connection. */
27 #define L2CAP_NULL_IDENT		0x00
28 #define L2CAP_FIRST_IDENT		0x01
29 #define L2CAP_LAST_IDENT		0xff
30 
31 
32 /* MTU */
33 #define L2CAP_MTU_MINIMUM		48
34 #define L2CAP_MTU_DEFAULT		672
35 #define L2CAP_MTU_MAXIMUM		0xffff
36 
37 
38 /* Timeouts */
39 #define L2CAP_FLUSH_TIMEOUT_DEFAULT	0xffff /* always retransmit */
40 #define L2CAP_LINK_TIMEOUT_DEFAULT	0xffff
41 
42 
43 /* Protocol/Service Multiplexer (PSM) values */
44 #define L2CAP_PSM_ANY		0x0000	/* Any/Invalid PSM */
45 #define L2CAP_PSM_SDP		0x0001	/* Service Discovery Protocol */
46 #define L2CAP_PSM_RFCOMM	0x0003	/* RFCOMM protocol */
47 #define L2CAP_PSM_TCS_BIN	0x0005	/* Telephony Control Protocol */
48 #define L2CAP_PSM_TCS_BIN_CORDLESS 0x0007 /* TCS cordless */
49 #define L2CAP_PSM_BNEP		0x000F	/* BNEP */
50 #define L2CAP_PSM_HID_CTRL	0x0011	/* HID control */
51 #define L2CAP_PSM_HID_INT	0x0013	/* HID interrupt */
52 #define L2CAP_PSM_UPnP		0x0015	/* UPnP (ESDP) */
53 #define L2CAP_PSM_AVCTP		0x0017	/* AVCTP */
54 #define L2CAP_PSM_AVDTP		0x0019	/* AVDTP */
55 	/* < 0x1000: reserved */
56 	/* >= 0x1000: dynamically assigned */
57 
58 
59 typedef struct {
60 	uint16	length;	/* payload size */
61 	uint16	dcid;	/* destination channel ID */
62 } _PACKED l2cap_basic_header;
63 
64 
65 /* Connectionless traffic ("CLT") */
66 typedef struct {
67 	/* dcid == L2CAP_CONNECTIONLESS_CID (0x2) */
68 	uint16	psm;
69 } _PACKED l2cap_connectionless_header;
70 #define L2CAP_CONNECTIONLESS_MTU_MAXIMUM (L2CAP_MTU_MAXIMUM - sizeof(l2cap_connectionless_header))
71 
72 
73 typedef struct {
74 	uint8	code;   /* command opcode */
75 #define L2CAP_IS_SIGNAL_REQ(code) (((code) & 1) == 0)
76 #define L2CAP_IS_SIGNAL_RSP(code) (((code) & 1) == 1)
77 	uint8	ident;  /* identifier to match request and response */
78 	uint16	length; /* command parameters length */
79 } _PACKED l2cap_command_header;
80 
81 #define L2CAP_COMMAND_REJECT_RSP	0x01
82 typedef struct {
83 	enum : uint16 {
84 		REJECTED_NOT_UNDERSTOOD	= 0x0000,
85 		REJECTED_MTU_EXCEEDED	= 0x0001,
86 		REJECTED_INVALID_CID	= 0x0002,
87 		/* 0x0003-0xffff: reserved */
88 	}; uint16 reason;
89 	/* data may follow */
90 } _PACKED l2cap_command_reject;
91 
92 typedef union {
93 	struct {
94 		uint16	mtu; /* actual signaling MTU */
95 	} _PACKED mtu_exceeded;
96 	struct {
97 		uint16	scid; /* source (local) CID */
98 		uint16	dcid; /* destination (remote) CID */
99 	} _PACKED invalid_cid;
100 } l2cap_command_reject_data;
101 
102 
103 #define L2CAP_CONNECTION_REQ	0x02
104 typedef struct {
105 	uint16	psm;
106 	uint16	scid; /* source channel ID */
107 } _PACKED l2cap_connection_req;
108 
109 #define L2CAP_CONNECTION_RSP	0x03
110 typedef struct {
111 	uint16	dcid;   /* destination channel ID */
112 	uint16	scid;   /* source channel ID */
113 	enum : uint16 {
114 		RESULT_SUCCESS					= 0x0000,
115 		RESULT_PENDING					= 0x0001,
116 		RESULT_PSM_NOT_SUPPORTED		= 0x0002,
117 		RESULT_SECURITY_BLOCK			= 0x0003,
118 		RESULT_NO_RESOURCES				= 0x0004,
119 		RESULT_INVALID_SCID				= 0x0005,
120 		RESULT_SCID_ALREADY_ALLOCATED	= 0x0006,
121 		/* 0x0007-0xffff: reserved */
122 	}; uint16 result;
123 	enum : uint16 {
124 		NO_STATUS_INFO					= 0x0000,
125 		STATUS_AUTHENTICATION_PENDING	= 0x0001,
126 		STATUS_AUTHORIZATION_PENDING	= 0x0002,
127 		/* 0x0003-0xffff: reserved */
128 	}; uint16 status; /* only defined if result = pending */
129 } _PACKED l2cap_connection_rsp;
130 
131 
132 #define L2CAP_CONFIGURATION_REQ	0x04
133 typedef struct {
134 	uint16	dcid;  /* destination channel ID */
135 	uint16	flags;
136 	/* options may follow */
137 } _PACKED l2cap_configuration_req;
138 
139 #define L2CAP_CONFIGURATION_RSP	0x05
140 typedef struct {
141 	uint16	scid;   /* source channel ID */
142 	uint16	flags;
143 #define L2CAP_CFG_FLAG_CONTINUATION		0x0001
144 	enum : uint16 {
145 		RESULT_SUCCESS				= 0x0000,
146 		RESULT_UNACCEPTABLE_PARAMS	= 0x0001,
147 		RESULT_REJECTED				= 0x0002,
148 		RESULT_UNKNOWN_OPTION		= 0x0003,
149 		RESULT_PENDING				= 0x0004,
150 		RESULT_FLOW_SPEC_REJECTED	= 0x0005,
151 		/* 0x0006-0xffff: reserved */
152 	}; uint16 result;
153 	/* options may follow */
154 } _PACKED l2cap_configuration_rsp;
155 
156 typedef struct {
157 	enum : uint8 {
158 		OPTION_MTU				= 0x01,
159 		OPTION_FLUSH_TIMEOUT	= 0x02,
160 		OPTION_QOS				= 0x03,
161 
162 		OPTION_HINT_BIT			= 0x80,
163 	}; uint8 type;
164 	uint8 length;
165 	/* value follows */
166 } _PACKED l2cap_configuration_option;
167 
168 typedef struct {
169 	uint8 flags;				/* reserved for future use */
170 	uint8 service_type;			/* 1 = best effort */
171 	uint32 token_rate;			/* average bytes per second */
172 	uint32 token_bucket_size;	/* max burst bytes */
173 	uint32 peak_bandwidth;		/* bytes per second */
174 	uint32 access_latency;		/* microseconds */
175 	uint32 delay_variation;		/* microseconds */
176 } _PACKED l2cap_qos;
177 
178 typedef union {
179 	uint16		mtu;
180 	uint16		flush_timeout;
181 	l2cap_qos	qos;
182 } l2cap_configuration_option_value;
183 
184 
185 #define L2CAP_DISCONNECTION_REQ	0x06
186 typedef struct {
187 	uint16	dcid; /* destination channel ID */
188 	uint16	scid; /* source channel ID */
189 } _PACKED l2cap_disconnection_req;
190 
191 #define L2CAP_DISCONNECTION_RSP	0x07
192 typedef l2cap_disconnection_req l2cap_disconnection_rsp;
193 
194 
195 #define L2CAP_ECHO_REQ	0x08
196 #define L2CAP_ECHO_RSP	0x09
197 
198 #define L2CAP_MAX_ECHO_SIZE \
199 	(L2CAP_MTU_MAXIMUM - sizeof(l2cap_command_header))
200 
201 
202 #define L2CAP_INFORMATION_REQ	0x0a
203 typedef struct {
204 	enum : uint16 {
205 		TYPE_CONNECTIONLESS_MTU	= 0x0001,
206 		TYPE_EXTENDED_FEATURES	= 0x0002,
207 		TYPE_FIXED_CHANNELS		= 0x0003,
208 			/* 0x0004-0xffff: reserved */
209 	}; uint16 type;
210 } _PACKED l2cap_information_req;
211 
212 #define L2CAP_INFORMATION_RSP	0x0b
213 typedef struct {
214 	uint16	type;
215 	enum : uint16 {
216 		RESULT_SUCCESS			= 0x0000,
217 		RESULT_NOT_SUPPORTED	= 0x0001,
218 	}; uint16 result;
219 	/* data may follow */
220 } _PACKED l2cap_information_rsp;
221 
222 typedef union {
223 	uint16 mtu;
224 	uint32 extended_features;
225 } _PACKED l2cap_information_rsp_data;
226 
227 
228 #endif /* _L2CAP_H_ */
229