Line data Source code
1 1 : /**
2 : * @file
3 : * @brief Bluetooth Hearing Access Service (HAS) APIs.
4 : */
5 :
6 : /*
7 : * Copyright (c) 2022 Codecoup
8 : * Copyright (c) 2024 Nordic Semiconductor ASA
9 : *
10 : * SPDX-License-Identifier: Apache-2.0
11 : */
12 :
13 : #ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_HAS_H_
14 : #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_HAS_H_
15 :
16 : /**
17 : * @brief Hearing Access Service (HAS)
18 : *
19 : * @defgroup bt_has Hearing Access Service (HAS)
20 : *
21 : * @since 3.1
22 : * @version 0.8.0
23 : *
24 : * @ingroup bluetooth
25 : * @{
26 : *
27 : * The Hearing Access Service is used to identify a hearing aid and optionally
28 : * to control hearing aid presets.
29 : */
30 :
31 : #include <stdint.h>
32 : #include <stdbool.h>
33 :
34 : #include <zephyr/bluetooth/bluetooth.h>
35 : #include <zephyr/sys/util.h>
36 : #include <zephyr/sys/util_macro.h>
37 :
38 : #ifdef __cplusplus
39 : extern "C" {
40 : #endif
41 :
42 : /**
43 : * @name Preset index definitions
44 : * @{
45 : */
46 : /** No index */
47 1 : #define BT_HAS_PRESET_INDEX_NONE 0x00
48 : /** First preset index */
49 1 : #define BT_HAS_PRESET_INDEX_FIRST 0x01
50 : /** Last preset index */
51 1 : #define BT_HAS_PRESET_INDEX_LAST 0xFF
52 : /** @} */
53 :
54 : /** Preset name minimum length */
55 1 : #define BT_HAS_PRESET_NAME_MIN 1
56 : /** Preset name maximum length */
57 1 : #define BT_HAS_PRESET_NAME_MAX 40
58 :
59 : /** @brief Opaque Hearing Access Service object. */
60 : struct bt_has;
61 :
62 : /** Hearing Aid device type */
63 1 : enum bt_has_hearing_aid_type {
64 : /**
65 : * Two hearing aids that form a Coordinated Set, one for the right ear and one for the left
66 : * ear of the user. Typically used by a user with bilateral hearing loss.
67 : */
68 : BT_HAS_HEARING_AID_TYPE_BINAURAL = 0x00,
69 : /**
70 : * A single hearing aid for the left or the right ear. Typically used by a user with
71 : * unilateral hearing loss.
72 : */
73 : BT_HAS_HEARING_AID_TYPE_MONAURAL = 0x01,
74 : /**
75 : * Two hearing aids with a connection to one another that expose a single Bluetooth radio
76 : * interface.
77 : */
78 : BT_HAS_HEARING_AID_TYPE_BANDED = 0x02,
79 : };
80 :
81 : /** Preset Properties values */
82 1 : enum bt_has_properties {
83 : /** No properties set */
84 : BT_HAS_PROP_NONE = 0,
85 :
86 : /** Preset name can be written by the client */
87 : BT_HAS_PROP_WRITABLE = BIT(0),
88 :
89 : /** Preset availability */
90 : BT_HAS_PROP_AVAILABLE = BIT(1),
91 : };
92 :
93 : /** Hearing Aid device capabilities */
94 1 : enum bt_has_capabilities {
95 : /** Indicate support for presets */
96 : BT_HAS_PRESET_SUPPORT = BIT(0),
97 : };
98 :
99 : /** @brief Structure for registering features of a Hearing Access Service instance. */
100 1 : struct bt_has_features_param {
101 : /** Hearing Aid Type value */
102 1 : enum bt_has_hearing_aid_type type;
103 :
104 : /**
105 : * @brief Preset Synchronization Support.
106 : *
107 : * Only applicable if @p type is @ref BT_HAS_HEARING_AID_TYPE_BINAURAL
108 : * and @kconfig{CONFIG_BT_HAS_PRESET_COUNT} is non-zero.
109 : */
110 1 : bool preset_sync_support;
111 :
112 : /**
113 : * @brief Independent Presets.
114 : *
115 : * Only applicable if @p type is @ref BT_HAS_HEARING_AID_TYPE_BINAURAL
116 : * and @kconfig{CONFIG_BT_HAS_PRESET_COUNT} is non-zero.
117 : */
118 1 : bool independent_presets;
119 : };
120 :
121 : /** @brief Preset record definition */
122 1 : struct bt_has_preset_record {
123 : /** Unique preset index. */
124 1 : uint8_t index;
125 :
126 : /** Bitfield of preset properties. */
127 1 : enum bt_has_properties properties;
128 :
129 : /** Preset name. */
130 1 : const char *name;
131 : };
132 :
133 : /** @brief Hearing Access Service Client callback structure. */
134 1 : struct bt_has_client_cb {
135 : /**
136 : * @brief Callback function for bt_has_discover.
137 : *
138 : * This callback is called when discovery procedure is complete.
139 : *
140 : * @param conn Bluetooth connection object.
141 : * @param err 0 on success, ATT error or negative errno otherwise.
142 : * @param has Pointer to the Hearing Access Service object or NULL on errors.
143 : * @param type Hearing Aid type.
144 : * @param caps Hearing Aid capabilities.
145 : */
146 1 : void (*discover)(struct bt_conn *conn, int err, struct bt_has *has,
147 : enum bt_has_hearing_aid_type type, enum bt_has_capabilities caps);
148 :
149 : /**
150 : * @brief Callback function for Hearing Access Service active preset changes.
151 : *
152 : * Optional callback called when the active preset is changed by the remote server when the
153 : * preset switch procedure is complete. The callback must be set to receive active preset
154 : * changes and enable support for switching presets. If the callback is not set, the Active
155 : * Index and Control Point characteristics will not be discovered by
156 : * @ref bt_has_client_discover.
157 : *
158 : * @param has Pointer to the Hearing Access Service object.
159 : * @param err 0 on success, ATT error or negative errno otherwise.
160 : * @param index Active preset index.
161 : */
162 1 : void (*preset_switch)(struct bt_has *has, int err, uint8_t index);
163 :
164 : /**
165 : * @brief Callback function for presets read operation.
166 : *
167 : * The callback is called when the preset read response is sent by the remote server.
168 : * The record object as well as its members are temporary and must be copied to in order
169 : * to cache its information.
170 : *
171 : * @param has Pointer to the Hearing Access Service object.
172 : * @param err 0 on success, ATT error or negative errno otherwise.
173 : * @param record Preset record or NULL on errors.
174 : * @param is_last True if Read Presets operation can be considered concluded.
175 : */
176 1 : void (*preset_read_rsp)(struct bt_has *has, int err,
177 : const struct bt_has_preset_record *record, bool is_last);
178 :
179 : /**
180 : * @brief Callback function for preset update notifications.
181 : *
182 : * The callback is called when the preset record update is notified by the remote server.
183 : * The record object as well as its objects are temporary and must be copied to in order
184 : * to cache its information.
185 : *
186 : * @param has Pointer to the Hearing Access Service object.
187 : * @param index_prev Index of the previous preset in the list.
188 : * @param record Preset record.
189 : * @param is_last True if preset list update operation can be considered concluded.
190 : */
191 1 : void (*preset_update)(struct bt_has *has, uint8_t index_prev,
192 : const struct bt_has_preset_record *record, bool is_last);
193 :
194 : /**
195 : * @brief Callback function for preset deletion notifications.
196 : *
197 : * The callback is called when the preset has been deleted by the remote server.
198 : *
199 : * @param has Pointer to the Hearing Access Service object.
200 : * @param index Preset index.
201 : * @param is_last True if preset list update operation can be considered concluded.
202 : */
203 1 : void (*preset_deleted)(struct bt_has *has, uint8_t index, bool is_last);
204 :
205 : /**
206 : * @brief Callback function for preset availability notifications.
207 : *
208 : * The callback is called when the preset availability change is notified by the remote
209 : * server.
210 : *
211 : * @param has Pointer to the Hearing Access Service object.
212 : * @param index Preset index.
213 : * @param available True if available, false otherwise.
214 : * @param is_last True if preset list update operation can be considered concluded.
215 : */
216 1 : void (*preset_availability)(struct bt_has *has, uint8_t index, bool available,
217 : bool is_last);
218 : };
219 :
220 : /**
221 : * @brief Registers the callbacks used by the Hearing Access Service client.
222 : *
223 : * @param cb The callback structure.
224 : *
225 : * @return 0 in case of success or negative value in case of error.
226 : */
227 1 : int bt_has_client_cb_register(const struct bt_has_client_cb *cb);
228 :
229 : /**
230 : * @brief Discover Hearing Access Service on a remote device.
231 : *
232 : * Client method to find a Hearing Access Service on a server identified by @p conn.
233 : * The @ref bt_has_client_cb.discover callback will be called when the discovery procedure
234 : * is complete to provide user a @ref bt_has object.
235 : *
236 : * @param conn Bluetooth connection object.
237 : *
238 : * @return 0 if success, errno on failure.
239 : */
240 1 : int bt_has_client_discover(struct bt_conn *conn);
241 :
242 : /**
243 : * @brief Get the Bluetooth connection object of the service object.
244 : *
245 : * The caller gets a new reference to the connection object which must be
246 : * released with bt_conn_unref() once done using the object.
247 : *
248 : * @param[in] has Pointer to the Hearing Access Service object.
249 : * @param[out] conn Connection object.
250 : *
251 : * @return 0 in case of success or negative value in case of error.
252 : */
253 1 : int bt_has_client_conn_get(const struct bt_has *has, struct bt_conn **conn);
254 :
255 : /**
256 : * @brief Read Preset Records.
257 : *
258 : * Client method to read up to @p max_count presets starting from given @p index.
259 : * The preset records are returned in the @ref bt_has_client_cb.preset_read_rsp callback
260 : * (called once for each preset).
261 : *
262 : * @param has Pointer to the Hearing Access Service object.
263 : * @param index The index to start with.
264 : * @param max_count Maximum number of presets to read.
265 : *
266 : * @return 0 in case of success or negative value in case of error.
267 : */
268 1 : int bt_has_client_presets_read(struct bt_has *has, uint8_t index, uint8_t max_count);
269 :
270 : /**
271 : * @brief Set Active Preset.
272 : *
273 : * Client procedure to set preset identified by @p index as active.
274 : * The status is returned in the @ref bt_has_client_cb.preset_switch callback.
275 : *
276 : * @param has Pointer to the Hearing Access Service object.
277 : * @param index Preset index to activate.
278 : * @param sync Request active preset synchronization in set.
279 : *
280 : * @return 0 in case of success or negative value in case of error.
281 : */
282 1 : int bt_has_client_preset_set(struct bt_has *has, uint8_t index, bool sync);
283 :
284 : /**
285 : * @brief Activate Next Preset.
286 : *
287 : * Client procedure to set next available preset as active.
288 : * The status is returned in the @ref bt_has_client_cb.preset_switch callback.
289 : *
290 : * @param has Pointer to the Hearing Access Service object.
291 : * @param sync Request active preset synchronization in set.
292 : *
293 : * @return 0 in case of success or negative value in case of error.
294 : */
295 1 : int bt_has_client_preset_next(struct bt_has *has, bool sync);
296 :
297 : /**
298 : * @brief Activate Previous Preset.
299 : *
300 : * Client procedure to set previous available preset as active.
301 : * The status is returned in the @ref bt_has_client_cb.preset_switch callback.
302 : *
303 : * @param has Pointer to the Hearing Access Service object.
304 : * @param sync Request active preset synchronization in set.
305 : *
306 : * @return 0 in case of success or negative value in case of error.
307 : */
308 1 : int bt_has_client_preset_prev(struct bt_has *has, bool sync);
309 :
310 : /** @brief Preset operations structure. */
311 1 : struct bt_has_preset_ops {
312 : /**
313 : * @brief Preset select callback.
314 : *
315 : * This callback is called when the client requests to select preset identified by
316 : * @p index.
317 : *
318 : * @param index Preset index requested to activate.
319 : * @param sync Whether the server must relay this change to the other member of the
320 : * Binaural Hearing Aid Set.
321 : *
322 : * @return 0 in case of success or negative value in case of error.
323 : * @return -EBUSY if operation cannot be performed at the time.
324 : * @return -EINPROGRESS in case where user has to confirm once the requested preset
325 : * becomes active by calling @ref bt_has_preset_active_set.
326 : */
327 1 : int (*select)(uint8_t index, bool sync);
328 :
329 : /**
330 : * @brief Preset name changed callback
331 : *
332 : * This callback is called when the name of the preset identified by @p index has changed.
333 : *
334 : * @param index Preset index that name has been changed.
335 : * @param name Preset current name.
336 : */
337 1 : void (*name_changed)(uint8_t index, const char *name);
338 : };
339 :
340 : /** @brief Register structure for preset. */
341 1 : struct bt_has_preset_register_param {
342 : /**
343 : * @brief Preset index.
344 : *
345 : * Unique preset identifier. The value shall be other than @ref BT_HAS_PRESET_INDEX_NONE.
346 : */
347 1 : uint8_t index;
348 :
349 : /**
350 : * @brief Preset properties.
351 : *
352 : * Bitfield of preset properties.
353 : */
354 1 : enum bt_has_properties properties;
355 :
356 : /**
357 : * @brief Preset name.
358 : *
359 : * Preset name that further can be changed by either server or client if
360 : * @kconfig{CONFIG_BT_HAS_PRESET_NAME_DYNAMIC} configuration option has been enabled.
361 : * It's length shall be greater than @ref BT_HAS_PRESET_NAME_MIN. If the length exceeds
362 : * @ref BT_HAS_PRESET_NAME_MAX, the name will be truncated.
363 : */
364 1 : const char *name;
365 :
366 : /** Preset operations structure. */
367 1 : const struct bt_has_preset_ops *ops;
368 : };
369 :
370 : /**
371 : * @brief Register the Hearing Access Service instance.
372 : *
373 : * @param features Hearing Access Service register parameters.
374 : *
375 : * @return 0 if success, errno on failure.
376 : */
377 1 : int bt_has_register(const struct bt_has_features_param *features);
378 :
379 : /**
380 : * @brief Register preset.
381 : *
382 : * Register preset. The preset will be a added to the list of exposed preset records.
383 : * This symbol is linkable if @kconfig{CONFIG_BT_HAS_PRESET_COUNT} is non-zero.
384 : *
385 : * @param param Preset registration parameter.
386 : *
387 : * @return 0 if success, errno on failure.
388 : */
389 1 : int bt_has_preset_register(const struct bt_has_preset_register_param *param);
390 :
391 : /**
392 : * @brief Unregister Preset.
393 : *
394 : * Unregister preset. The preset will be removed from the list of preset records.
395 : *
396 : * @param index The index of preset that's being requested to unregister.
397 : *
398 : * @return 0 if success, errno on failure.
399 : */
400 1 : int bt_has_preset_unregister(uint8_t index);
401 :
402 : /**
403 : * @brief Set the preset as available.
404 : *
405 : * Set the @ref BT_HAS_PROP_AVAILABLE property bit. This will notify preset availability
406 : * to peer devices. Only available preset can be selected as active preset.
407 : *
408 : * @param index The index of preset that's became available.
409 : *
410 : * @return 0 in case of success or negative value in case of error.
411 : */
412 1 : int bt_has_preset_available(uint8_t index);
413 :
414 : /**
415 : * @brief Set the preset as unavailable.
416 : *
417 : * Clear the @ref BT_HAS_PROP_AVAILABLE property bit. This will notify preset availability
418 : * to peer devices. Unavailable preset cannot be selected as active preset.
419 : *
420 : * @param index The index of preset that's became unavailable.
421 : *
422 : * @return 0 in case of success or negative value in case of error.
423 : */
424 1 : int bt_has_preset_unavailable(uint8_t index);
425 :
426 : /** Enum for return values for @ref bt_has_preset_func_t functions */
427 1 : enum {
428 : /** Stop iterating */
429 : BT_HAS_PRESET_ITER_STOP = 0,
430 : /** Continue iterating */
431 : BT_HAS_PRESET_ITER_CONTINUE,
432 : };
433 :
434 : /**
435 : * @typedef bt_has_preset_func_t
436 : * @brief Preset iterator callback.
437 : *
438 : * @param index The index of preset found.
439 : * @param properties Preset properties.
440 : * @param name Preset name.
441 : * @param user_data Data given.
442 : *
443 : * @return BT_HAS_PRESET_ITER_CONTINUE if should continue to the next preset.
444 : * @return BT_HAS_PRESET_ITER_STOP to stop.
445 : */
446 1 : typedef uint8_t (*bt_has_preset_func_t)(uint8_t index, enum bt_has_properties properties,
447 : const char *name, void *user_data);
448 :
449 : /**
450 : * @brief Preset iterator.
451 : *
452 : * Iterate presets. Optionally, match non-zero index if given.
453 : *
454 : * @param index Preset index, passing @ref BT_HAS_PRESET_INDEX_NONE skips index matching.
455 : * @param func Callback function.
456 : * @param user_data Data to pass to the callback.
457 : */
458 1 : void bt_has_preset_foreach(uint8_t index, bt_has_preset_func_t func, void *user_data);
459 :
460 : /**
461 : * @brief Set active preset.
462 : *
463 : * Function used to set the preset identified by the @p index as the active preset.
464 : * The preset index will be notified to peer devices.
465 : *
466 : * @param index Preset index.
467 : *
468 : * @return 0 in case of success or negative value in case of error.
469 : */
470 1 : int bt_has_preset_active_set(uint8_t index);
471 :
472 : /**
473 : * @brief Get active preset.
474 : *
475 : * Function used to get the currently active preset index.
476 : *
477 : * @return Active preset index.
478 : */
479 1 : uint8_t bt_has_preset_active_get(void);
480 :
481 : /**
482 : * @brief Clear out active preset.
483 : *
484 : * Used by server to deactivate currently active preset.
485 : *
486 : * @return 0 in case of success or negative value in case of error.
487 : */
488 1 : static inline int bt_has_preset_active_clear(void)
489 : {
490 : return bt_has_preset_active_set(BT_HAS_PRESET_INDEX_NONE);
491 : }
492 :
493 : /**
494 : * @brief Change the Preset Name.
495 : *
496 : * Change the name of the preset identified by @p index.
497 : *
498 : * @param index The index of the preset to change the name of.
499 : * @param name Name to write.
500 : *
501 : * @return 0 in case of success or negative value in case of error.
502 : */
503 1 : int bt_has_preset_name_change(uint8_t index, const char *name);
504 :
505 : /**
506 : * @brief Change the Hearing Aid Features.
507 : *
508 : * Change the hearing aid features.
509 : *
510 : * @param features The features to be set.
511 : *
512 : * @return 0 in case of success or negative value in case of error.
513 : */
514 1 : int bt_has_features_set(const struct bt_has_features_param *features);
515 :
516 : #ifdef __cplusplus
517 : }
518 : #endif
519 :
520 : /**
521 : * @}
522 : */
523 :
524 : #endif /* ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_HAS_H_ */
|