Line data Source code
1 0 : /* goep.h - Bluetooth Generic Object Exchange Profile handling */
2 :
3 : /*
4 : * Copyright 2024-2025 NXP
5 : *
6 : * SPDX-License-Identifier: Apache-2.0
7 : */
8 :
9 : #ifndef ZEPHYR_INCLUDE_BLUETOOTH_GOEP_H_
10 : #define ZEPHYR_INCLUDE_BLUETOOTH_GOEP_H_
11 :
12 : /**
13 : * @brief Generic Object Exchange Profile (GOEP)
14 : * @defgroup bt_goep Generic Object Exchange Profile (GOEP)
15 : * @ingroup bluetooth
16 : * @{
17 : */
18 :
19 : #include <zephyr/kernel.h>
20 : #include <string.h>
21 : #include <errno.h>
22 : #include <stdbool.h>
23 :
24 : #include <zephyr/bluetooth/bluetooth.h>
25 : #include <zephyr/bluetooth/conn.h>
26 : #include <zephyr/bluetooth/l2cap.h>
27 : #include <zephyr/bluetooth/classic/rfcomm.h>
28 : #include <zephyr/bluetooth/classic/obex.h>
29 :
30 : #ifdef __cplusplus
31 : extern "C" {
32 : #endif
33 :
34 : struct bt_goep;
35 :
36 : /** @brief GOEP transport operations structure.
37 : *
38 : * The object has to stay valid and constant for the lifetime of the GOEP server and client.
39 : */
40 1 : struct bt_goep_transport_ops {
41 : /** @brief GOEP transport connected callback
42 : *
43 : * If this callback is provided it will be called whenever the GOEP transport connection
44 : * completes.
45 : *
46 : * @param conn The ACL connection.
47 : * @param goep The GOEP object that has been connected.
48 : */
49 1 : void (*connected)(struct bt_conn *conn, struct bt_goep *goep);
50 :
51 : /** @brief GOEP transport disconnected callback
52 : *
53 : * If this callback is provided it will be called whenever the GOEP transport is
54 : * disconnected, including when a connection gets rejected.
55 : *
56 : * @param goep The GOEP object that has been disconnected.
57 : */
58 1 : void (*disconnected)(struct bt_goep *goep);
59 : };
60 :
61 : /** @brief Life-span states of GOEP transport.
62 : *
63 : * Used only by internal APIs dealing with setting GOEP to proper transport state depending on
64 : * operational context.
65 : *
66 : * GOEP transport enters the @ref BT_GOEP_TRANSPORT_CONNECTING state upon
67 : * @ref bt_goep_transport_l2cap_connect, @ref bt_goep_transport_rfcomm_connect or upon returning
68 : * from @ref bt_goep_transport_rfcomm_server::accept and bt_goep_transport_l2cap_server::accept.
69 : *
70 : * When GOEP transport leaves the @ref BT_GOEP_TRANSPORT_CONNECTING state and enters the @ref
71 : * BT_GOEP_TRANSPORT_CONNECTED, @ref bt_goep_transport_ops::connected is called.
72 : *
73 : * When GOEP transport enters the @ref BT_GOEP_TRANSPORT_DISCONNECTED from other states,
74 : * @ref bt_goep_transport_ops::disconnected is called.
75 : */
76 1 : enum __packed bt_goep_transport_state {
77 : /** GOEP disconnected */
78 : BT_GOEP_TRANSPORT_DISCONNECTED,
79 : /** GOEP in connecting state */
80 : BT_GOEP_TRANSPORT_CONNECTING,
81 : /** GOEP ready for upper layer traffic on it */
82 : BT_GOEP_TRANSPORT_CONNECTED,
83 : /** GOEP in disconnecting state */
84 : BT_GOEP_TRANSPORT_DISCONNECTING,
85 : };
86 :
87 0 : struct bt_goep {
88 : /** @internal To be used for transport */
89 : union {
90 0 : struct bt_rfcomm_dlc dlc;
91 0 : struct bt_l2cap_br_chan chan;
92 : } _transport;
93 :
94 : /** @internal Peer GOEP Version
95 : *
96 : * false - Peer supports GOEP v1.1. The GOEP transport is based on RFCOMM.
97 : * `dlc` is used as transport.
98 : *
99 : * true - peer supports GOEP v2.0 or later. The GOEP transport is based on L2CAP.
100 : * `chan` is used as transport.
101 : */
102 : bool _goep_v2;
103 :
104 : /** @internal connection handle */
105 : struct bt_conn *_acl;
106 :
107 : /** @internal Saves the current transport state, @ref bt_goep_transport_state */
108 : atomic_t _state;
109 :
110 : /** @brief GOEP transport operations
111 : *
112 : * The upper layer should pass the operations to `transport_ops` when
113 : * providing the GOEP structure.
114 : */
115 1 : const struct bt_goep_transport_ops *transport_ops;
116 :
117 : /** @brief OBEX object */
118 1 : struct bt_obex obex;
119 : };
120 :
121 : /**
122 : * @defgroup bt_goep_transport_rfcomm GOEP transport RFCOMM
123 : * @ingroup bt_goep
124 : * @{
125 : */
126 :
127 : /** @brief GOEP Server structure GOEP v1.1. */
128 1 : struct bt_goep_transport_rfcomm_server {
129 : /** @brief RFCOMM server for GOEP v1.1
130 : *
131 : * The @ref bt_goep_transport_rfcomm_server::rfcomm is used to register a rfcomm server.
132 : *
133 : * The @ref bt_rfcomm_server::channel needs to be passed with a pre-set channel (not
134 : * recommended however), Or give a value `0` to make the channel be auto-allocated when
135 : * @ref bt_goep_transport_rfcomm_server_register is called.
136 : * The @ref bt_rfcomm_server::accept should be not used by GOEP application, and instead
137 : * the @ref bt_goep_transport_rfcomm_server::accept should be used.
138 : */
139 1 : struct bt_rfcomm_server rfcomm;
140 :
141 : /** @brief Server accept callback
142 : *
143 : * This callback is called whenever a new incoming GOEP connection requires
144 : * authorization.
145 : *
146 : * Before returning the callback, @ref bt_goep::transport_ops should be initialized with
147 : * valid address of type @ref bt_goep_transport_ops object. The field `mtu` of
148 : * @ref bt_obex::rx could be passed with valid value. Or set it to zero, the mtu will be
149 : * calculated according to @kconfig{CONFIG_BT_GOEP_RFCOMM_MTU}.
150 : *
151 : * @warning It is the responsibility of the caller to zero out the parent of the GOEP
152 : * object.
153 : *
154 : * @param conn The connection that is requesting authorization.
155 : * @param server Pointer to the server structure this callback relates to.
156 : * @param goep Pointer to received the allocated GOEP object.
157 : *
158 : * @return 0 in case of success or negative value in case of error.
159 : * @return -ENOMEM if no available space for new object.
160 : * @return -EACCES if application did not authorize the connection.
161 : * @return -EPERM if encryption key size is too short.
162 : */
163 1 : int (*accept)(struct bt_conn *conn, struct bt_goep_transport_rfcomm_server *server,
164 : struct bt_goep **goep);
165 :
166 0 : sys_snode_t node;
167 : };
168 :
169 : /** @brief Register GOEP RFCOMM server.
170 : *
171 : * Register GOEP server for a RFCOMM channel @ref bt_rfcomm_server::channel, each new connection
172 : * is authorized using the @ref bt_goep_transport_rfcomm_server::accept callback which in case of
173 : * success shall allocate the GOEP structure @ref bt_goep to be used by the new GOEP connection.
174 : *
175 : * @ref bt_rfcomm_server::channel may be pre-set to a given value (not recommended however). Or be
176 : * left as 0, in which case the channel will be auto-allocated by RFCOMM.
177 : *
178 : * @param server Server structure.
179 : *
180 : * @return 0 in case of success or negative value in case of error.
181 : */
182 1 : int bt_goep_transport_rfcomm_server_register(struct bt_goep_transport_rfcomm_server *server);
183 :
184 : /** @brief Connect GOEP transport over RFCOMM
185 : *
186 : * Connect GOEP transport over RFCOMM, once the connection is completed, the callback
187 : * @ref bt_goep_transport_ops::connected is called. If the connection is rejected,
188 : * @ref bt_goep_transport_ops::disconnected callback is called instead.
189 : * The GOEP object is passed (over an address of it) as second parameter, application should
190 : * create transport dedicated GOEP object @ref bt_goep. Then pass to this API the location
191 : * (address).
192 : * Before calling the API, @ref bt_goep::transport_ops should be initialized with valid address
193 : * of type @ref bt_goep_transport_ops object. The field `mtu` of @ref bt_obex::rx could be passed
194 : * with valid value. Or set it to zero, the mtu will be calculated according to
195 : * @kconfig{CONFIG_BT_GOEP_RFCOMM_MTU}.
196 : * The RFCOMM channel is passed as third parameter. It is the RFCOMM channel of RFCOMM server of
197 : * peer device.
198 : *
199 : * @warning It is the responsibility of the caller to zero out the parent of the GOEP object.
200 : *
201 : * @param conn Connection object.
202 : * @param goep GOEP object.
203 : * @param channel RFCOMM channel to connect to.
204 : *
205 : * @return 0 in case of success or negative value in case of error.
206 : */
207 1 : int bt_goep_transport_rfcomm_connect(struct bt_conn *conn, struct bt_goep *goep, uint8_t channel);
208 :
209 : /** @brief Disconnect GOEP transport from RFCOMM
210 : *
211 : * Disconnect GOEP RFCOMM transport.
212 : *
213 : * @param goep GOEP object.
214 : *
215 : * @return 0 in case of success or negative value in case of error.
216 : */
217 1 : int bt_goep_transport_rfcomm_disconnect(struct bt_goep *goep);
218 :
219 : /** @} */
220 :
221 : /**
222 : * @defgroup bt_goep_transport_l2cap GOEP transport L2CAP
223 : * @ingroup bt_goep
224 : * @{
225 : */
226 :
227 : /** @brief GOEP Server structure for GOEP v2.0 and later. */
228 1 : struct bt_goep_transport_l2cap_server {
229 : /** @brief L2CAP PSM for GOEP v2.0 and later
230 : *
231 : * The @ref bt_goep_transport_l2cap_server::l2cap is used to register a l2cap server.
232 : *
233 : * The @ref bt_l2cap_server::psm needs to be passed with a pre-set psm (not recommended
234 : * however), Or give a value `0` to make the psm be auto-allocated when
235 : * @ref bt_goep_transport_l2cap_server_register is called.
236 : * The @ref bt_l2cap_server::sec_level is used to require minimum security level for l2cap
237 : * server.
238 : * The @ref bt_l2cap_server::accept should be not used by GOEP application, and instead
239 : * the @ref bt_goep_transport_l2cap_server::accept will be used.
240 : */
241 1 : struct bt_l2cap_server l2cap;
242 :
243 : /** @brief Server accept callback
244 : *
245 : * This callback is called whenever a new incoming GOEP connection requires
246 : * authorization.
247 : *
248 : * Before returning the callback, @ref bt_goep::transport_ops should be initialized with
249 : * valid address of type @ref bt_goep_transport_ops object. The field `mtu` of
250 : * @ref bt_obex::rx could be passed with valid value. Or set it to zero, the mtu will be
251 : * calculated according to @kconfig{CONFIG_BT_GOEP_L2CAP_MTU}.
252 : *
253 : * @warning It is the responsibility of the caller to zero out the parent of the GOEP
254 : * object.
255 : *
256 : * @param conn The connection that is requesting authorization.
257 : * @param server Pointer to the server structure this callback relates to.
258 : * @param goep Pointer to received the allocated GOEP object.
259 : *
260 : * @return 0 in case of success or negative value in case of error.
261 : * @return -ENOMEM if no available space for new object.
262 : * @return -EACCES if application did not authorize the connection.
263 : * @return -EPERM if encryption key size is too short.
264 : */
265 1 : int (*accept)(struct bt_conn *conn, struct bt_goep_transport_l2cap_server *server,
266 : struct bt_goep **goep);
267 :
268 0 : sys_snode_t node;
269 : };
270 :
271 : /** @brief Register GOEP L2CAP server.
272 : *
273 : * Register GOEP server for a L2CAP PSM @ref bt_l2cap_server::psm. each new connection is
274 : * authorized using the @ref bt_goep_transport_l2cap_server::accept callback which in case of
275 : * success shall allocate the GOEP structure @ref bt_goep to be used by the new GOEP connection.
276 : *
277 : * For L2CAP PSM, for fixed, SIG-assigned PSMs (in the range 0x0001-0x0eff) the PSM should not be
278 : * used. For dynamic PSMs (in the range 0x1000-0xffff),
279 : * @ref bt_l2cap_server::psm may be pre-set to a given value (not recommended however). And it
280 : * shall have the least significant bit of the most significant octet equal to 0 and the least
281 : * significant bit of all other octets equal to 1. Or be left as 0, in which case the channel
282 : * will be auto-allocated by L2CAP.
283 : *
284 : * @param server Server structure.
285 : *
286 : * @return 0 in case of success or negative value in case of error.
287 : */
288 1 : int bt_goep_transport_l2cap_server_register(struct bt_goep_transport_l2cap_server *server);
289 :
290 : /** @brief Connect GOEP transport over L2CAP
291 : *
292 : * Connect GOEP transport by L2CAP, once the connection is completed, the callback
293 : * @ref bt_goep_transport_ops::connected is called. If the connection is rejected,
294 : * @ref bt_goep_transport_ops::disconnected callback is called instead.
295 : * The GOEP object is passed (over an address of it) as second parameter, application should
296 : * create transport dedicated GOEP object @ref bt_goep. Then pass to this API the location
297 : * (address).
298 : * Before calling the API, @ref bt_goep::transport_ops should be initialized with valid address
299 : * of type @ref bt_goep_transport_ops object. The field `mtu` of @ref bt_obex::rx could be passed
300 : * with valid value. Or set it to zero, the mtu will be calculated according to
301 : * @kconfig{CONFIG_BT_GOEP_L2CAP_MTU}.
302 : * The L2CAP PSM is passed as third parameter. It is the RFCOMM channel of RFCOMM server of peer
303 : * device.
304 : *
305 : * @warning It is the responsibility of the caller to zero out the parent of the GOEP object.
306 : *
307 : * @param conn Connection object.
308 : * @param goep GOEP object.
309 : * @param psm L2CAP PSM to connect to.
310 : *
311 : * @return 0 in case of success or negative value in case of error.
312 : */
313 1 : int bt_goep_transport_l2cap_connect(struct bt_conn *conn, struct bt_goep *goep, uint16_t psm);
314 :
315 : /** @brief Disconnect GOEP transport from L2CAP channel
316 : *
317 : * Disconnect GOEP L2CAP transport.
318 : *
319 : * @param goep GOEP object.
320 : *
321 : * @return 0 in case of success or negative value in case of error.
322 : */
323 1 : int bt_goep_transport_l2cap_disconnect(struct bt_goep *goep);
324 :
325 : /** @} */
326 :
327 : /** @brief Allocate the buffer from given pool after reserving head room for GOEP
328 : *
329 : * For GOEP connection over RFCOMM, the reserved head room includes OBEX, RFCOMM, L2CAP and ACL
330 : * headers.
331 : * For GOEP connection over L2CAP, the reserved head room includes OBEX, L2CAP and ACL headers.
332 : *
333 : * @param goep GOEP object.
334 : * @param pool Which pool to take the buffer from.
335 : *
336 : * @return New buffer.
337 : */
338 1 : struct net_buf *bt_goep_create_pdu(struct bt_goep *goep, struct net_buf_pool *pool);
339 :
340 : #ifdef __cplusplus
341 : }
342 : #endif
343 :
344 : /**
345 : * @}
346 : */
347 :
348 : #endif /* ZEPHYR_INCLUDE_BLUETOOTH_GOEP_H_ */
|