Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
307 changes: 307 additions & 0 deletions include/bluetooth/audio/vocs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,307 @@
/*
* 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't take this as a blocker/mandatory comment since it's completely subjective, but I wouldn't personally have taken the recent 80 -> 100 character limit change so that one must always strive for it. E.g. I find human readable text easier to read with shorter lines (less horizontal back-and-forth eye movement), so I'd still have formatted it to less than 80 characters. The main benefit of the 80 -> 100 chance (as I see it) is for code where forcing earlier line spits would actually hurt readability. Anyway, I realise this might also be tricky to configure in an editor so that it'd auto-split code and comments differently (that said, at least for code I write I always explicitly choose where to split the code, but let the editor do the splitting for any code comments or other documentation). (rant over :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually don't have any auto-split in my editor, so any such changes I've done has been intentional. Personally I don't find liken of length 100 to be any less readable, so it is, as you say, subjective :)

From: https://www.phoronix.com/scan.php?page=news_item&px=Linux-Kernel-Deprecates-80-Col

Yes, staying withing 80 columns is certainly still preferred. But it's not the hard limit that the checkpatch warnings imply, and other concerns can most certainly dominate

So from the Linux Kernel point of view, 80 should still be preferred. Going forwards I'll try to keep it at max 80, unless to avoid ugly breaks :)

* 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 changes: 46 additions & 0 deletions include/bluetooth/uuid.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -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
*/
Expand Down
1 change: 1 addition & 0 deletions subsys/bluetooth/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
9 changes: 9 additions & 0 deletions subsys/bluetooth/audio/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# 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 changes: 3 additions & 0 deletions subsys/bluetooth/audio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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