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 : * @warning It is the responsibility of the caller to zero out the parent of the GOEP
147 : * object.
148 : *
149 : * @param conn The connection that is requesting authorization.
150 : * @param server Pointer to the server structure this callback relates to.
151 : * @param goep Pointer to received the allocated GOEP object.
152 : *
153 : * @return 0 in case of success or negative value in case of error.
154 : * @return -ENOMEM if no available space for new object.
155 : * @return -EACCES if application did not authorize the connection.
156 : * @return -EPERM if encryption key size is too short.
157 : */
158 1 : int (*accept)(struct bt_conn *conn, struct bt_goep_transport_rfcomm_server *server,
159 : struct bt_goep **goep);
160 :
161 0 : sys_snode_t node;
162 : };
163 :
164 : /** @brief Register GOEP RFCOMM server.
165 : *
166 : * Register GOEP server for a RFCOMM channel @ref bt_rfcomm_server::channel, each new connection
167 : * is authorized using the @ref bt_goep_transport_rfcomm_server::accept callback which in case of
168 : * success shall allocate the GOEP structure @ref bt_goep to be used by the new GOEP connection.
169 : *
170 : * @ref bt_rfcomm_server::channel may be pre-set to a given value (not recommended however). Or be
171 : * left as 0, in which case the channel will be auto-allocated by RFCOMM.
172 : *
173 : * @param server Server structure.
174 : *
175 : * @return 0 in case of success or negative value in case of error.
176 : */
177 1 : int bt_goep_transport_rfcomm_server_register(struct bt_goep_transport_rfcomm_server *server);
178 :
179 : /** @brief Connect GOEP transport over RFCOMM
180 : *
181 : * Connect GOEP transport over RFCOMM, once the connection is completed, the callback
182 : * @ref bt_goep_transport_ops::connected is called. If the connection is rejected,
183 : * @ref bt_goep_transport_ops::disconnected callback is called instead.
184 : * The GOEP object is passed (over an address of it) as second parameter, application should
185 : * create transport dedicated GOEP object @ref bt_goep. Then pass to this API the location
186 : * (address).
187 : * Before calling the API, @ref bt_obex::client_ops and @ref bt_goep::transport_ops should
188 : * be initialized with valid address of type @ref bt_obex_client_ops object and
189 : * @ref bt_goep_transport_ops object. The field `mtu` of @ref bt_obex::rx could be passed with
190 : * valid value. Or set it to zero, the mtu will be calculated according to
191 : * @kconfig{CONFIG_BT_GOEP_RFCOMM_MTU}.
192 : * The RFCOMM channel is passed as third parameter. It is the RFCOMM channel of RFCOMM server of
193 : * peer device.
194 : *
195 : * @warning It is the responsibility of the caller to zero out the parent of the GOEP object.
196 : *
197 : * @param conn Connection object.
198 : * @param goep GOEP object.
199 : * @param channel RFCOMM channel to connect to.
200 : *
201 : * @return 0 in case of success or negative value in case of error.
202 : */
203 1 : int bt_goep_transport_rfcomm_connect(struct bt_conn *conn, struct bt_goep *goep, uint8_t channel);
204 :
205 : /** @brief Disconnect GOEP transport from RFCOMM
206 : *
207 : * Disconnect GOEP RFCOMM transport.
208 : *
209 : * @param goep GOEP object.
210 : *
211 : * @return 0 in case of success or negative value in case of error.
212 : */
213 1 : int bt_goep_transport_rfcomm_disconnect(struct bt_goep *goep);
214 :
215 : /** @} */
216 :
217 : /**
218 : * @defgroup bt_goep_transport_l2cap GOEP transport L2CAP
219 : * @ingroup bt_goep
220 : * @{
221 : */
222 :
223 : /** @brief GOEP Server structure for GOEP v2.0 and later. */
224 1 : struct bt_goep_transport_l2cap_server {
225 : /** @brief L2CAP PSM for GOEP v2.0 and later
226 : *
227 : * The @ref bt_goep_transport_l2cap_server::l2cap is used to register a l2cap server.
228 : *
229 : * The @ref bt_l2cap_server::psm needs to be passed with a pre-set psm (not recommended
230 : * however), Or give a value `0` to make the psm be auto-allocated when
231 : * @ref bt_goep_transport_l2cap_server_register is called.
232 : * The @ref bt_l2cap_server::sec_level is used to require minimum security level for l2cap
233 : * server.
234 : * The @ref bt_l2cap_server::accept should be not used by GOEP application, and instead
235 : * the @ref bt_goep_transport_l2cap_server::accept will be used.
236 : */
237 1 : struct bt_l2cap_server l2cap;
238 :
239 : /** @brief Server accept callback
240 : *
241 : * This callback is called whenever a new incoming GOEP connection requires
242 : * authorization.
243 : *
244 : * @warning It is the responsibility of the caller to zero out the parent of the GOEP
245 : * object.
246 : *
247 : * @param conn The connection that is requesting authorization.
248 : * @param server Pointer to the server structure this callback relates to.
249 : * @param goep Pointer to received the allocated GOEP object.
250 : *
251 : * @return 0 in case of success or negative value in case of error.
252 : * @return -ENOMEM if no available space for new object.
253 : * @return -EACCES if application did not authorize the connection.
254 : * @return -EPERM if encryption key size is too short.
255 : */
256 1 : int (*accept)(struct bt_conn *conn, struct bt_goep_transport_l2cap_server *server,
257 : struct bt_goep **goep);
258 :
259 0 : sys_snode_t node;
260 : };
261 :
262 : /** @brief Register GOEP L2CAP server.
263 : *
264 : * Register GOEP server for a L2CAP PSM @ref bt_l2cap_server::psm. each new connection is
265 : * authorized using the @ref bt_goep_transport_l2cap_server::accept callback which in case of
266 : * success shall allocate the GOEP structure @ref bt_goep to be used by the new GOEP connection.
267 : *
268 : * For L2CAP PSM, for fixed, SIG-assigned PSMs (in the range 0x0001-0x0eff) the PSM should not be
269 : * used. For dynamic PSMs (in the range 0x1000-0xffff),
270 : * @ref bt_l2cap_server::psm may be pre-set to a given value (not recommended however). And it
271 : * shall have the least significant bit of the most significant octet equal to 0 and the least
272 : * significant bit of all other octets equal to 1. Or be left as 0, in which case the channel
273 : * will be auto-allocated by L2CAP.
274 : *
275 : * @param server Server structure.
276 : *
277 : * @return 0 in case of success or negative value in case of error.
278 : */
279 1 : int bt_goep_transport_l2cap_server_register(struct bt_goep_transport_l2cap_server *server);
280 :
281 : /** @brief Connect GOEP transport over L2CAP
282 : *
283 : * Connect GOEP transport by L2CAP, once the connection is completed, the callback
284 : * @ref bt_goep_transport_ops::connected is called. If the connection is rejected,
285 : * @ref bt_goep_transport_ops::disconnected callback is called instead.
286 : * The GOEP object is passed (over an address of it) as second parameter, application should
287 : * create transport dedicated GOEP object @ref bt_goep. Then pass to this API the location
288 : * (address).
289 : * Before calling the API, @ref bt_obex::client_ops and @ref bt_goep::transport_ops should
290 : * be initialized with valid address of type @ref bt_obex_client_ops object and
291 : * @ref bt_goep_transport_ops object. The field `mtu` of @ref bt_obex::rx could be passed with
292 : * valid value. Or set it to zero, the mtu will be calculated according to
293 : * @kconfig{CONFIG_BT_GOEP_L2CAP_MTU}.
294 : * The L2CAP PSM is passed as third parameter. It is the RFCOMM channel of RFCOMM server of peer
295 : * device.
296 : *
297 : * @warning It is the responsibility of the caller to zero out the parent of the GOEP object.
298 : *
299 : * @param conn Connection object.
300 : * @param goep GOEP object.
301 : * @param psm L2CAP PSM to connect to.
302 : *
303 : * @return 0 in case of success or negative value in case of error.
304 : */
305 1 : int bt_goep_transport_l2cap_connect(struct bt_conn *conn, struct bt_goep *goep, uint16_t psm);
306 :
307 : /** @brief Disconnect GOEP transport from L2CAP channel
308 : *
309 : * Disconnect GOEP L2CAP transport.
310 : *
311 : * @param goep GOEP object.
312 : *
313 : * @return 0 in case of success or negative value in case of error.
314 : */
315 1 : int bt_goep_transport_l2cap_disconnect(struct bt_goep *goep);
316 :
317 : /** @} */
318 :
319 : /** @brief Allocate the buffer from given pool after reserving head room for GOEP
320 : *
321 : * For GOEP connection over RFCOMM, the reserved head room includes OBEX, RFCOMM, L2CAP and ACL
322 : * headers.
323 : * For GOEP connection over L2CAP, the reserved head room includes OBEX, L2CAP and ACL headers.
324 : *
325 : * @param goep GOEP object.
326 : * @param pool Which pool to take the buffer from.
327 : *
328 : * @return New buffer.
329 : */
330 1 : struct net_buf *bt_goep_create_pdu(struct bt_goep *goep, struct net_buf_pool *pool);
331 :
332 : #ifdef __cplusplus
333 : }
334 : #endif
335 :
336 : /**
337 : * @}
338 : */
339 :
340 : #endif /* ZEPHYR_INCLUDE_BLUETOOTH_GOEP_H_ */
|