1 /**
2  * @file
3  * @brief Bluetooth Volume Offset Control Service (VOCS) APIs.
4  */
5 
6 /*
7  * Copyright (c) 2020-2024 Nordic Semiconductor ASA
8  *
9  * SPDX-License-Identifier: Apache-2.0
10  */
11 
12 #ifndef ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_VOCS_H_
13 #define ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_VOCS_H_
14 
15 /**
16  * @brief Volume Offset Control Service (VOCS)
17  *
18  * @defgroup bt_vocs Volume Offset Control Service (VOCS)
19  *
20  * @since 2.6
21  * @version 0.8.0
22  *
23  * @ingroup bluetooth
24  * @{
25  *
26  * The Volume Offset Control Service is a secondary service, and as such should not be used own its
27  * own, but rather in the context of another (primary) service.
28  *
29  * This API implements both the server and client functionality.
30  * Note that the API abstracts away the change counter in the volume offset control state and will
31  * automatically handle any changes to that. If out of date, the client implementation will
32  * autonomously read the change counter value when executing a write request.
33  */
34 
35 #include <stdint.h>
36 #include <stdbool.h>
37 
38 #include <zephyr/bluetooth/conn.h>
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 /**
45  * @name Volume Offset Control Service Error codes
46  * @{
47  */
48 /**
49  * The Change_Counter operand value does not match the Change_Counter field value of the Volume
50  * Offset State characteristic.
51  */
52 #define BT_VOCS_ERR_INVALID_COUNTER                0x80
53 /** An invalid opcode has been used in a control point procedure. */
54 #define BT_VOCS_ERR_OP_NOT_SUPPORTED               0x81
55 /** An operand value used in a control point procedure is outside the permissible range. */
56 #define BT_VOCS_ERR_OUT_OF_RANGE                   0x82
57 /** @} */
58 
59 /**
60  * @name Volume Offset Control Service offset limits
61  * @{
62  */
63 /** Minimum offset value */
64 #define BT_VOCS_MIN_OFFSET                         -255
65 /** Maximum offset value */
66 #define BT_VOCS_MAX_OFFSET                         255
67 /** @} */
68 
69 /** @brief Opaque Volume Offset Control Service instance. */
70 struct bt_vocs;
71 
72 /** @brief Structure for registering a Volume Offset Control Service instance. */
73 struct bt_vocs_register_param {
74 	/** Audio Location bitmask */
75 	uint32_t location;
76 
77 	/** Boolean to set whether the location is writable by clients */
78 	bool location_writable;
79 
80 	/** Initial volume offset (-255 to 255) */
81 	int16_t offset;
82 
83 	/** Initial audio output description */
84 	char *output_desc;
85 
86 	/** Boolean to set whether the description is writable by clients */
87 	bool desc_writable;
88 
89 	/** Pointer to the callback structure. */
90 	struct bt_vocs_cb *cb;
91 };
92 
93 /** @brief Structure for discovering a Volume Offset Control Service instance. */
94 struct bt_vocs_discover_param {
95 	/**
96 	 * @brief The start handle of the discovering.
97 	 *
98 	 * Typically the @p start_handle of a @ref bt_gatt_include.
99 	 */
100 	uint16_t start_handle;
101 	/**
102 	 * @brief The end handle of the discovering.
103 	 *
104 	 * Typically the @p end_handle of a @ref bt_gatt_include.
105 	 */
106 	uint16_t end_handle;
107 };
108 
109 /**
110  * @brief Get a free service instance of Volume Offset Control Service from the pool.
111  *
112  * @return Volume Offset Control Service instance in case of success or NULL in case of error.
113  */
114 struct bt_vocs *bt_vocs_free_instance_get(void);
115 
116 /**
117  * @brief Get the service declaration attribute.
118  *
119  * The first service attribute returned can be included in any other GATT service.
120  *
121  * @param vocs Volume Offset Control Service instance.
122  *
123  * @return Pointer to the attributes of the service.
124  */
125 void *bt_vocs_svc_decl_get(struct bt_vocs *vocs);
126 
127 /**
128  * @brief Get the connection pointer of a client instance
129  *
130  * Get the Bluetooth connection pointer of a Audio Input Control Service
131  * client instance.
132  *
133  * @param vocs    Audio Input Control Service client instance pointer.
134  * @param conn    Connection pointer.
135  *
136  * @return 0 if success, errno on failure.
137  */
138 int bt_vocs_client_conn_get(const struct bt_vocs *vocs, struct bt_conn **conn);
139 
140 /**
141  * @brief Register the Volume Offset Control Service instance.
142  *
143  * @param vocs      Volume Offset Control Service instance.
144  * @param param     Volume Offset Control Service register parameters.
145  *
146  * @return 0 if success, errno on failure.
147  */
148 int bt_vocs_register(struct bt_vocs *vocs,
149 		     const struct bt_vocs_register_param *param);
150 
151 /**
152  * @brief Callback function for the offset state.
153  *
154  * Called when the value is read, or if the value is changed by either the server or client.
155  *
156  * @param inst        The instance pointer.
157  * @param err         Error value. 0 on success, GATT error on positive value
158  *                    or errno on negative value.
159  *                    For notifications, this will always be 0.
160  * @param offset      The offset value.
161  */
162 typedef void (*bt_vocs_state_cb)(struct bt_vocs *inst, int err, int16_t offset);
163 
164 /**
165  * @brief Callback function for setting offset.
166  *
167  * @param inst        The instance pointer.
168  * @param err         Error value. 0 on success, GATT error on positive value
169  *                    or errno on negative value.
170  */
171 typedef void (*bt_vocs_set_offset_cb)(struct bt_vocs *inst, int err);
172 
173 /**
174  * @brief Callback function for the location.
175  *
176  * Called when the value is read, or if the value is changed by either the server or client.
177  *
178  * @param inst         The instance pointer.
179  * @param err          Error value. 0 on success, GATT error on positive value
180  *                     or errno on negative value.
181  *                     For notifications, this will always be 0.
182  * @param location     The location value.
183  */
184 typedef void (*bt_vocs_location_cb)(struct bt_vocs *inst, int err,
185 				    uint32_t location);
186 
187 /**
188  * @brief Callback function for the description.
189  *
190  * Called when the value is read, or if the value is changed by either the server or client.
191  *
192  * @param inst         The instance pointer.
193  * @param err          Error value. 0 on success, GATT error on positive value
194  *                     or errno on negative value.
195  *                     For notifications, this will always be 0.
196  * @param description  The description as an UTF-8 encoded string.
197  */
198 typedef void (*bt_vocs_description_cb)(struct bt_vocs *inst, int err,
199 				       char *description);
200 
201 /**
202  * @brief Callback function for bt_vocs_discover.
203  *
204  * This callback should be overwritten by the primary service that
205  * includes the Volume Control Offset Service client, and should thus not be
206  * set by the application.
207  *
208  * @param inst         The instance pointer.
209  * @param err          Error value. 0 on success, GATT error on positive value
210  *                     or errno on negative value.
211  *                     For notifications, this will always be 0.
212  */
213 typedef void (*bt_vocs_discover_cb)(struct bt_vocs *inst, int err);
214 
215 /**
216  * @brief Struct to hold the Volume Offset Control Service callbacks
217  *
218  * These can be registered for usage with bt_vocs_client_cb_register() or bt_vocs_register()
219  * depending on the role.
220  */
221 struct bt_vocs_cb {
222 	/** The offset state has changed */
223 	bt_vocs_state_cb                state;
224 	/** The location has changed */
225 	bt_vocs_location_cb             location;
226 	/** The Description has changed */
227 	bt_vocs_description_cb          description;
228 
229 #if defined(CONFIG_BT_VOCS_CLIENT) || defined(__DOXYGEN__)
230 	/**
231 	 * The discovery procedure has completed
232 	 *
233 	 * Only settable for the client and requires enabling@kconfig{CONFIG_BT_VOCS_CLIENT}.
234 	 */
235 	bt_vocs_discover_cb             discover;
236 	/**
237 	 * The set offset procedure has completed
238 	 *
239 	 * Only settable for the client and requires enabling@kconfig{CONFIG_BT_VOCS_CLIENT}.
240 	 */
241 	bt_vocs_set_offset_cb           set_offset;
242 #endif /* CONFIG_BT_VOCS_CLIENT */
243 };
244 
245 /**
246  * @brief Read the Volume Offset Control Service offset state.
247  *
248  * The value is returned in the bt_vocs_cb.state callback.
249  *
250  * @param inst          Pointer to the Volume Offset Control Service instance.
251  *
252  * @return 0 on success, GATT error value on fail.
253  */
254 int bt_vocs_state_get(struct bt_vocs *inst);
255 
256 /**
257  * @brief Set the Volume Offset Control Service offset state.
258  *
259  * @param inst          Pointer to the Volume Offset Control Service instance.
260  * @param offset        The offset to set (-255 to 255).
261  *
262  * @return 0 on success, GATT error value on fail.
263  */
264 int bt_vocs_state_set(struct bt_vocs *inst, int16_t offset);
265 
266 /**
267  * @brief Read the Volume Offset Control Service location.
268  *
269  * The value is returned in the bt_vocs_cb.location callback.
270  *
271  * @param inst          Pointer to the Volume Offset Control Service instance.
272  *
273  * @return 0 on success, GATT error value on fail.
274  */
275 int bt_vocs_location_get(struct bt_vocs *inst);
276 
277 /**
278  * @brief Set the Volume Offset Control Service location.
279  *
280  * @param inst          Pointer to the Volume Offset Control Service instance.
281  * @param location      The location to set.
282  *
283  * @return 0 on success, GATT error value on fail.
284  */
285 int bt_vocs_location_set(struct bt_vocs *inst, uint32_t location);
286 
287 /**
288  * @brief Read the Volume Offset Control Service output description.
289  *
290  * The value is returned in the bt_vocs_cb.description callback.
291  *
292  * @param inst          Pointer to the Volume Offset Control Service instance.
293  *
294  * @return 0 on success, GATT error value on fail.
295  */
296 int bt_vocs_description_get(struct bt_vocs *inst);
297 
298 /**
299  * @brief Set the Volume Offset Control Service description.
300  *
301  * @param inst          Pointer to the Volume Offset Control Service instance.
302  * @param description   The UTF-8 encoded string description to set.
303  *
304  * @return 0 on success, GATT error value on fail.
305  */
306 int bt_vocs_description_set(struct bt_vocs *inst, const char *description);
307 
308 /**
309  * @brief Registers the callbacks for the Volume Offset Control Service client.
310  *
311  * @param inst  Pointer to the Volume Offset Control Service client instance.
312  * @param cb    Pointer to the callback structure.
313  */
314 void bt_vocs_client_cb_register(struct bt_vocs *inst, struct bt_vocs_cb *cb);
315 
316 /**
317  * @brief Returns a pointer to a Volume Offset Control Service client instance.
318  *
319  * @return Pointer to the instance, or NULL if no free instances are left.
320  */
321 struct bt_vocs *bt_vocs_client_free_instance_get(void);
322 
323 /**
324  * @brief Discover a Volume Offset Control Service.
325  *
326  * Attempts to discover a Volume Offset Control Service on a server given the @p param.
327  *
328  * @param conn  Connection to the peer with the Volume Offset Control Service.
329  * @param inst  Pointer to the Volume Offset Control Service client instance.
330  * @param param Pointer to the parameters.
331  *
332  * @return 0 on success, errno on fail.
333  */
334 int bt_vocs_discover(struct bt_conn *conn, struct bt_vocs *inst,
335 		     const struct bt_vocs_discover_param *param);
336 
337 #ifdef __cplusplus
338 }
339 #endif
340 
341 /**
342  * @}
343  */
344 
345 #endif /* ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_VOCS_H_ */
346