Commit ed2162c7 authored by Emil Gydesen's avatar Emil Gydesen Committed by Anas Nashif
Browse files

Bluetooth: Audio: Volume Offset Control Service and Client



This commit implements the secondary service
Volume Offset Control Service (VOCS) server and client.

Signed-off-by: default avatarEmil Gydesen <emil.gydesen@nordicsemi.no>
parent cdd02a99
Loading
Loading
Loading
Loading
+307 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2020 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#ifndef ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_VOCS_H_
#define ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_VOCS_H_

/**
 * @brief Volume Offset Control Service (VOCS)
 *
 * @defgroup bt_gatt_vocs Volume Offset Control Service (VOCS)
 *
 * @ingroup bluetooth
 * @{
 *
 * The Volume Offset Control Service is a secondary service, and as such should not be used own its
 * own, but rather in the context of another (primary) service.
 *
 * This API implements both the server and client functionality.
 * Note that the API abstracts away the change counter in the volume offset control state and will
 * automatically handle any changes to that. If out of date, the client implementation will
 * autonomously read the change counter value when executing a write request.
 *
 * [Experimental] Users should note that the APIs can change as a part of ongoing development.
 */

#include <zephyr/types.h>

#ifdef __cplusplus
extern "C" {
#endif

/** Volume Offset Control Service Error codes */
#define BT_VOCS_ERR_INVALID_COUNTER                0x80
#define BT_VOCS_ERR_OP_NOT_SUPPORTED               0x81
#define BT_VOCS_ERR_OUT_OF_RANGE                   0x82

#define BT_VOCS_MIN_OFFSET                         -255
#define BT_VOCS_MAX_OFFSET                         255

/** @brief Opaque Volume Offset Control Service instance. */
struct bt_vocs;

/** @brief Structure for initializing a Volume Offset Control Service instance. */
struct bt_vocs_init_param {
	/** Audio Location bitmask */
	uint32_t location;

	/** Boolean to set whether the location is writable by clients */
	bool location_writable;

	/** Initial volume offset (-255 to 255) */
	int16_t offset;

	/** Initial audio output description */
	char *output_desc;

	/** Boolean to set whether the description is writable by clients */
	bool desc_writable;
};

/** @brief Structure for discovering a Volume Offset Control Service instance. */
struct bt_vocs_discover_param {
	/**
	 * @brief The start handle of the discovering.
	 *
	 * Typically the @p start_handle of a @ref bt_gatt_include.
	 */
	uint16_t start_handle;
	/**
	 * @brief The end handle of the discovering.
	 *
	 * Typically the @p end_handle of a @ref bt_gatt_include.
	 */
	uint16_t end_handle;
};

/**
 * @brief Get a free service instance of Volume Offset Control Service from the pool.
 *
 * @return Volume Offset Control Service instance in case of success or NULL in case of error.
 */
struct bt_vocs *bt_vocs_free_instance_get(void);

/**
 * @brief Get the service declaration attribute.
 *
 * The first service attribute returned can be included in any other GATT service.
 *
 * @param vocs Volume Offset Control Service instance.
 *
 * @return Pointer to the attributes of the service.
 */
void *bt_vocs_svc_decl_get(struct bt_vocs *vocs);

/**
 * @brief Initialize the Volume Offset Control Service instance.
 *
 * @param vocs      Volume Offset Control Service instance.
 * @param init      Volume Offset Control Service initialization structure.
 *                  May be NULL to use default values.
 *
 * @return 0 if success, errno on failure.
 */
int bt_vocs_init(struct bt_vocs *vocs, const struct bt_vocs_init_param *init);

/**
 * @brief Callback function for the offset state.
 *
 * Called when the value is read, or if the value is changed by either the server or client.
 *
 * @param conn        Connection to peer device, or NULL if local server read.
 * @param inst        The instance pointer.
 * @param err         Error value. 0 on success, GATT error on positive value
 *                    or errno on negative value.
 *                    For notifications, this will always be 0.
 * @param offset      The offset value.
 */
typedef void (*bt_vocs_state_cb_t)(struct bt_conn *conn, struct bt_vocs *inst,
				   int err, int16_t offset);

/**
 * @brief Callback function for setting offset.
 *
 * @param conn        Connection to peer device, or NULL if local server write.
 * @param inst        The instance pointer.
 * @param err         Error value. 0 on success, GATT error on positive value
 *                    or errno on negative value.
 */
typedef void (*bt_vocs_set_offset_cb_t)(struct bt_conn *conn, struct bt_vocs *inst, int err);

/**
 * @brief Callback function for the location.
 *
 * Called when the value is read, or if the value is changed by either the server or client.
 *
 * @param conn         Connection to peer device, or NULL if local server read.
 * @param inst         The instance pointer.
 * @param err          Error value. 0 on success, GATT error on positive value
 *                     or errno on negative value.
 *                     For notifications, this will always be 0.
 * @param location     The location value.
 */
typedef void (*bt_vocs_location_cb_t)(struct bt_conn *conn, struct bt_vocs *inst, int err,
				      uint32_t location);

/**
 * @brief Callback function for the description.
 *
 * Called when the value is read, or if the value is changed by either the server or client.
 *
 * @param conn         Connection to peer device, or NULL if local server read.
 * @param inst         The instance pointer.
 * @param err          Error value. 0 on success, GATT error on positive value
 *                     or errno on negative value.
 *                     For notifications, this will always be 0.
 * @param description  The description as an UTF-8 encoded string.
 */
typedef void (*bt_vocs_description_cb_t)(struct bt_conn *conn, struct bt_vocs *inst, int err,
					 char *description);

/**
 * @brief Callback function for bt_vocs_discover.
 *
 * This callback will usually be overwritten by the primary service that
 * includes the Volume Control Offset Service client.
 *
 * @param conn         Connection to peer device, or NULL if local server read.
 * @param inst         The instance pointer.
 * @param err          Error value. 0 on success, GATT error on positive value
 *                     or errno on negative value.
 *                     For notifications, this will always be 0.
 */
typedef void (*bt_vocs_discover_cb_t)(struct bt_conn *conn, struct bt_vocs *inst, int err);

struct bt_vocs_cb {
	bt_vocs_state_cb_t              state;
	bt_vocs_location_cb_t           location;
	bt_vocs_description_cb_t        description;

#if defined(CONFIG_BT_VOCS_CLIENT)
	/* Client only */
	bt_vocs_discover_cb_t           discover;
	bt_vocs_set_offset_cb_t         set_offset;
#endif /* CONFIG_BT_VOCS_CLIENT */
};

/**
 * @brief Read the Volume Offset Control Service offset state.
 *
 * The value is returned in the bt_vocs_cb.state callback.
 *
 * @param conn          Connection to peer device, or NULL to read local server value.
 * @param inst          Pointer to the Volume Offset Control Service instance.
 *
 * @return 0 on success, GATT error value on fail.
 */
int bt_vocs_state_get(struct bt_conn *conn, struct bt_vocs *inst);

/**
 * @brief Set the Volume Offset Control Service offset state.
 *
 * @param conn          Connection to peer device, or NULL to set local server value.
 * @param inst          Pointer to the Volume Offset Control Service instance.
 * @param offset        The offset to set (-255 to 255).
 *
 * @return 0 on success, GATT error value on fail.
 */
int bt_vocs_state_set(struct bt_conn *conn, struct bt_vocs *inst, int16_t offset);

/**
 * @brief Read the Volume Offset Control Service location.
 *
 * The value is returned in the bt_vocs_cb.location callback.
 *
 * @param conn          Connection to peer device, or NULL to read local server value.
 * @param inst          Pointer to the Volume Offset Control Service instance.
 *
 * @return 0 on success, GATT error value on fail.
 */
int bt_vocs_location_get(struct bt_conn *conn, struct bt_vocs *inst);

/**
 * @brief Set the Volume Offset Control Service location.
 *
 * @param conn          Connection to peer device, or NULL to read local server value.
 * @param inst          Pointer to the Volume Offset Control Service instance.
 * @param location      The location to set.
 *
 * @return 0 on success, GATT error value on fail.
 */
int bt_vocs_location_set(struct bt_conn *conn, struct bt_vocs *inst, uint32_t location);

/**
 * @brief Read the Volume Offset Control Service output description.
 *
 * The value is returned in the bt_vocs_cb.description callback.
 *
 * @param conn          Connection to peer device, or NULL to read local server value.
 * @param inst          Pointer to the Volume Offset Control Service instance.
 *
 * @return 0 on success, GATT error value on fail.
 */
int bt_vocs_description_get(struct bt_conn *conn, struct bt_vocs *inst);

/**
 * @brief Set the Volume Offset Control Service description.
 *
 * @param conn          Connection to peer device, or NULL to set local server value.
 * @param inst          Pointer to the Volume Offset Control Service instance.
 * @param description   The UTF-8 encoded string description to set.
 *
 * @return 0 on success, GATT error value on fail.
 */
int bt_vocs_description_set(struct bt_conn *conn, struct bt_vocs *inst,
			    const char *description);

/**
 * @brief Register callbacks for the Volume Offset Control Service.
 *
 * @param inst          Pointer to the Volume Offset Control Service instance.
 * @param cb            Pointer to the callback structure.
 *
 * @return 0 on success, GATT error value on fail.
 */
int bt_vocs_cb_register(struct bt_vocs *inst, struct bt_vocs_cb *cb);

/**
 * @brief Registers the callbacks for the Volume Offset Control Service client.
 *
 * @param inst  Pointer to the Volume Offset Control Service client instance.
 * @param cb    Pointer to the callback structure.
 */
void bt_vocs_client_cb_register(struct bt_vocs *inst, struct bt_vocs_cb *cb);

/**
 * @brief Returns a pointer to a Volume Offset Control Service client instance.
 *
 * @return Pointer to the instance, or NULL if no free instances are left.
 */
struct bt_vocs *bt_vocs_client_free_instance_get(void);

/**
 * @brief Discover a Volume Offset Control Service.
 *
 * Attempts to discover a Volume Offset Control Service on a server given the @p param.
 *
 * @param conn  Connection to the peer with the Volume Offset Control Service.
 * @param inst  Pointer to the Volume Offset Control Service client instance.
 * @param param Pointer to the parameters.
 *
 * @return 0 on success, errno on fail.
 */
int bt_vocs_discover(struct bt_conn *conn, struct bt_vocs *inst,
		     const struct bt_vocs_discover_param *param);

#ifdef __cplusplus
}
#endif

/**
 * @}
 */

#endif /* ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_VOCS_H_ */
+46 −0
Original line number Diff line number Diff line
@@ -383,6 +383,15 @@ struct bt_uuid_128 {
 */
#define BT_UUID_MESH_PROXY \
	BT_UUID_DECLARE_16(BT_UUID_MESH_PROXY_VAL)
/** @def BT_UUID_VOCS_VAL
 *  @brief Volume Offset Control Service value
 */
#define BT_UUID_VOCS_VAL 0x1845
/** @def BT_UUID_VOCS
 *  @brief Volume Offset Control Service
 */
#define BT_UUID_VOCS \
	BT_UUID_DECLARE_16(BT_UUID_VOCS_VAL)
/** @def BT_UUID_GATT_PRIMARY_VAL
 *  @brief GATT Primary Service UUID value
 */
@@ -1214,6 +1223,43 @@ struct bt_uuid_128 {
#define BT_UUID_GATT_SERVER_FEATURES      \
	BT_UUID_DECLARE_16(BT_UUID_GATT_SERVER_FEATURES_VAL)

/** @def BT_UUID_VOCS_STATE_VAL
 *  @brief Volume Offset State value
 */
#define BT_UUID_VOCS_STATE_VAL 0x2B80
/** @def BT_UUID_VOCS_STATE
 *  @brief Volume Offset State
 */
#define BT_UUID_VOCS_STATE \
	BT_UUID_DECLARE_16(BT_UUID_VOCS_STATE_VAL)
/** @def BT_UUID_VOCS_LOCATION_VAL
 *  @brief Audio Location value
 */
#define BT_UUID_VOCS_LOCATION_VAL 0x2B81
/** @def BT_UUID_VOCS_LOCATION
 *  @brief Audio Location
 */
#define BT_UUID_VOCS_LOCATION \
	BT_UUID_DECLARE_16(BT_UUID_VOCS_LOCATION_VAL)
/** @def BT_UUID_VOCS_CONTROL_VAL
 *  @brief Volume Offset Control Point value
 */
#define BT_UUID_VOCS_CONTROL_VAL 0x2B82
/** @def BT_UUID_VOCS_CONTROL
 *  @brief Volume Offset Control Point
 */
#define BT_UUID_VOCS_CONTROL \
	BT_UUID_DECLARE_16(BT_UUID_VOCS_CONTROL_VAL)
/** @def BT_UUID_VOCS_DESCRIPTION_VAL
 *  @brief Volume Offset Audio Output Description value
 */
#define BT_UUID_VOCS_DESCRIPTION_VAL 0x2B83
/** @def BT_UUID_VOCS_DESCRIPTION
 *  @brief Volume Offset Audio Output Description
 */
#define BT_UUID_VOCS_DESCRIPTION \
	BT_UUID_DECLARE_16(BT_UUID_VOCS_DESCRIPTION_VAL)

/*
 * Protocol UUIDs
 */
+1 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ add_subdirectory_ifdef(CONFIG_BT_HCI host)
add_subdirectory_ifdef(CONFIG_BT_SHELL shell)
add_subdirectory_ifdef(CONFIG_BT_CONN services)
add_subdirectory_ifdef(CONFIG_BT_MESH mesh)
add_subdirectory_ifdef(CONFIG_BT_AUDIO audio)

if(CONFIG_BT_CTLR AND CONFIG_BT_LL_SW_SPLIT)
  add_subdirectory(controller)
+9 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: Apache-2.0

zephyr_library()
zephyr_library_link_libraries(subsys__bluetooth)

if (CONFIG_BT_VOCS OR CONFIG_BT_VOCS_CLIENT)
	zephyr_library_sources(vocs.c)
endif()
zephyr_library_sources_ifdef(CONFIG_BT_VOCS_CLIENT vocs_client.c)
+3 −0
Original line number Diff line number Diff line
@@ -50,4 +50,7 @@ config BT_AUDIO_DEBUG
	  Use this option to enable debug logs for the Bluetooth
	  Audio functionality.


source "subsys/bluetooth/audio/Kconfig.vocs"

endif # BT_AUDIO
Loading