1 /** @file
2  *  @brief Internal APIs for Bluetooth SCO handling.
3  */
4 /*
5  * Copyright 2024 NXP
6  *
7  * SPDX-License-Identifier: Apache-2.0
8  */
9 
10 /** @brief Life-span states of SCO channel. Used only by internal APIs
11  *  dealing with setting channel to proper state depending on operational
12  *  context.
13  */
14 enum bt_sco_state {
15 	/** Channel disconnected */
16 	BT_SCO_STATE_DISCONNECTED,
17 	/** Channel is pending ACL encryption before connecting */
18 	BT_SCO_STATE_ENCRYPT_PENDING,
19 	/** Channel in connecting state */
20 	BT_SCO_STATE_CONNECTING,
21 	/** Channel ready for upper layer traffic on it */
22 	BT_SCO_STATE_CONNECTED,
23 	/** Channel in disconnecting state */
24 	BT_SCO_STATE_DISCONNECTING,
25 };
26 
27 struct bt_sco_chan;
28 struct bt_sco_chan_ops {
29 	/** @brief Channel connected callback
30 	 *
31 	 *  If this callback is provided it will be called whenever the
32 	 *  connection completes.
33 	 *
34 	 *  @param chan The channel that has been connected
35 	 */
36 	void (*connected)(struct bt_sco_chan *chan);
37 
38 	/** @brief Channel disconnected callback
39 	 *
40 	 *  If this callback is provided it will be called whenever the
41 	 *  channel is disconnected, including when a connection gets
42 	 *  rejected or when setting security fails.
43 	 *
44 	 *  @param chan   The channel that has been Disconnected
45 	 *  @param reason BT_HCI_ERR_* reason for the disconnection.
46 	 */
47 	void (*disconnected)(struct bt_sco_chan *chan, uint8_t reason);
48 };
49 
50 struct bt_sco_chan {
51 	struct bt_conn               *sco;
52 	/** Channel operations reference */
53 	const struct bt_sco_chan_ops *ops;
54 
55 	enum bt_sco_state            state;
56 };
57 
58 /** @brief Initiate an SCO connection to a remote device.
59  *
60  *  Allows initiate new SCO link to remote peer using its address.
61  *
62  *  The caller gets a new reference to the connection object which must be
63  *  released with bt_conn_unref() once done using the object.
64  *
65  *  @param peer  Remote address.
66  *  @param chan  sco chan object.
67  *
68  *  @return Valid connection object on success or NULL otherwise.
69  */
70 struct bt_conn *bt_conn_create_sco(const bt_addr_t *peer, struct bt_sco_chan *chan);
71 
72 /** @brief SCO Accept Info Structure */
73 struct bt_sco_accept_info {
74 	/** The ACL connection that is requesting authorization */
75 	struct bt_conn *acl;
76 
77 	/** class code of peer device */
78 	uint8_t   dev_class[3];
79 
80 	/** link type */
81 	uint8_t   link_type;
82 };
83 
84 /** @brief SCO Server structure. */
85 struct bt_sco_server {
86 	/** Required minimum security level.
87 	 * Only available when @kconfig{CONFIG_BT_SMP} is enabled.
88 	 */
89 	bt_security_t		sec_level;
90 	/** @brief Server accept callback
91 	 *
92 	 *  This callback is called whenever a new incoming connection requires
93 	 *  authorization.
94 	 *
95 	 *  @param info The SCO accept information structure
96 	 *  @param chan Pointer to receive the allocated channel
97 	 *
98 	 *  @return 0 in case of success or negative value in case of error.
99 	 */
100 	int (*accept)(const struct bt_sco_accept_info *info,
101 			  struct bt_sco_chan **chan);
102 };
103 
104 /** @brief Register SCO server.
105  *
106  *  Register SCO server, each new connection is authorized using the accept()
107  *  callback which in case of success shall allocate the channel structure
108  *  to be used by the new connection.
109  *
110  *  @param server Server structure.
111  *
112  *  @return 0 in case of success or negative value in case of error.
113  */
114 int bt_sco_server_register(struct bt_sco_server *server);
115 
116 /** @brief Unregister SCO server.
117  *
118  *  Unregister previously registered SCO server.
119  *
120  *  @param server Server structure.
121  *
122  *  @return 0 in case of success or negative value in case of error.
123  */
124 int bt_sco_server_unregister(struct bt_sco_server *server);
125 
126 /** @brief sco channel connected.
127  *
128  *  sco channel connected
129  *
130  *  @param sco SCO connection object.
131  */
132 void bt_sco_connected(struct bt_conn *sco);
133 
134 /** @brief sco channel disconnected.
135  *
136  *  sco channel disconnected
137  *
138  *  @param sco SCO connection object.
139  */
140 void bt_sco_disconnected(struct bt_conn *sco);
141 
142 uint8_t bt_esco_conn_req(struct bt_hci_evt_conn_request *evt);
143 
144 #if defined(CONFIG_BT_CONN_LOG_LEVEL_DBG)
145 void bt_sco_chan_set_state_debug(struct bt_sco_chan *chan,
146 				 enum bt_sco_state state,
147 				 const char *func, int line);
148 #define bt_sco_chan_set_state(_chan, _state) \
149 	bt_sco_chan_set_state_debug(_chan, _state, __func__, __LINE__)
150 #else
151 void bt_sco_chan_set_state(struct bt_sco_chan *chan, enum bt_sco_state state);
152 #endif /* CONFIG_BT_CONN_LOG_LEVEL_DBG */
153 
154 /** @brief SCO connection callback structure.
155  *
156  *  This structure is used for tracking the state of a SCO connection.
157  *  It is registered with the help of the bt_sco_conn_cb_register() API.
158  *  It's permissible to register multiple instances of this @ref bt_sco_conn_cb
159  *  type, in case different modules of an application are interested in
160  *  tracking the connection state. If a callback is not of interest for
161  *  an instance, it may be set to NULL and will as a consequence not be
162  *  used for that instance.
163  */
164 struct bt_sco_conn_cb {
165 	/** @brief A new SCO connection has been established.
166 	 *
167 	 *  This callback notifies the application of a new connection.
168 	 *  In case the err parameter is non-zero it means that the
169 	 *  connection establishment failed.
170 	 *
171 	 *  @param conn New SCO connection object.
172 	 *  @param err HCI error. Zero for success, non-zero otherwise.
173 	 */
174 	void (*connected)(struct bt_conn *conn, uint8_t err);
175 
176 	/** @brief A SCO connection has been disconnected.
177 	 *
178 	 *  This callback notifies the application that a SCO connection
179 	 *  has been disconnected.
180 	 *  When this callback is called the stack still has one reference to
181 	 *  the connection object.
182 	 *
183 	 *  @param conn SCO connection object.
184 	 *  @param reason BT_HCI_ERR_* reason for the disconnection.
185 	 */
186 	void (*disconnected)(struct bt_conn *conn, uint8_t reason);
187 
188 	/** @internal Internally used field for list handling */
189 	sys_snode_t _node;
190 };
191 
192 /** @brief Register SCO connection callbacks.
193  *
194  *  Register callbacks to monitor the state of SCO connections.
195  *
196  *  @param cb Callback struct. Must point to memory that remains valid.
197  *
198  * @retval 0 Success.
199  * @retval -EINVAL If @p cb is NULL.
200  * @retval -EEXIST if @p cb was already registered.
201  */
202 int bt_sco_conn_cb_register(struct bt_sco_conn_cb *cb);
203 
204 /**
205  * @brief Unregister SCO connection callbacks.
206  *
207  * Unregister the state of SCO connections callbacks.
208  *
209  * @param cb Callback struct point to memory that remains valid.
210  *
211  * @retval 0 Success.
212  * @retval -EINVAL If @p cb is NULL.
213  * @retval -ENOENT if @p cb was not registered.
214  */
215 int bt_sco_conn_cb_unregister(struct bt_sco_conn_cb *cb);
216 
217 /**
218  *  @brief Register a callback structure for connection events.
219  *
220  *  @param _name Name of callback structure.
221  */
222 #define BT_SCO_CONN_CB_DEFINE(_name)								\
223 	static const STRUCT_SECTION_ITERABLE(bt_sco_conn_cb, _CONCAT(bt_sco_conn_cb_, _name))
224