mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-06-05 21:04:49 +00:00
nimble/services: add PACS
This commit adds Published Audio Capabilities Service/Prifile. In pair ble_audio_codec module is added, that supports registering supported codecs with their corresponding configurations.
This commit is contained in:
committed by
Krzysztof Kopyściński
parent
8debcf0c46
commit
e55baf9843
@@ -54,6 +54,7 @@ syscfg.vals:
|
||||
BLE_EATT_CHAN_NUM: 2
|
||||
BLE_PHY_2M: 1
|
||||
BLE_PHY_CODED: 1
|
||||
BLE_AUDIO_MAX_CODEC_RECORDS: 2
|
||||
|
||||
# controller
|
||||
BLE_LL_CFG_FEAT_LL_PRIVACY: 1
|
||||
|
||||
@@ -208,19 +208,184 @@
|
||||
*/
|
||||
|
||||
/** LE Audio Codec Config Type: Sampling Frequency. */
|
||||
#define BLE_AUDIO_CODEC_SAMPLING_FREQ_TYPE 0x01
|
||||
#define BLE_AUDIO_CODEC_CONF_SAMPLING_FREQ_TYPE 0x01
|
||||
|
||||
/** LE Audio Codec Config Type: Frame Duration. */
|
||||
#define BLE_AUDIO_CODEC_FRAME_DURATION_TYPE 0x02
|
||||
#define BLE_AUDIO_CODEC_CONF_FRAME_DURATION_TYPE 0x02
|
||||
|
||||
/** LE Audio Codec Config Type: Channel Allocation. */
|
||||
#define BLE_AUDIO_CODEC_AUDIO_CHANNEL_ALLOCATION_TYPE 0x03
|
||||
#define BLE_AUDIO_CODEC_CONF_AUDIO_CHANNEL_ALLOCATION_TYPE 0x03
|
||||
|
||||
/** LE Audio Codec Config Type: Octets Per Codec Frame. */
|
||||
#define BLE_AUDIO_CODEC_OCTETS_PER_CODEC_FRAME_TYPE 0x04
|
||||
#define BLE_AUDIO_CODEC_CONF_OCTETS_PER_CODEC_FRAME_TYPE 0x04
|
||||
|
||||
/** LE Audio Codec Config Type: Frame Blocks Per SDU. */
|
||||
#define BLE_AUDIO_CODEC_FRAME_BLOCKS_PER_SDU_TYPE 0x05
|
||||
#define BLE_AUDIO_CODEC_CONF_FRAME_BLOCKS_PER_SDU_TYPE 0x05
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @defgroup ble_audio_codec_config Bluetooth Low Energy Audio Codec Specific Capabilities
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** LE Audio Codec Specific Capability: Supported Sampling Frequencies. */
|
||||
#define BLE_AUDIO_CODEC_CAPS_SAMPLING_FREQ_TYPE 0x01
|
||||
|
||||
/** LE Audio Codec Specific Capability: Supported Frame Durations. */
|
||||
#define BLE_AUDIO_CODEC_CAPS_FRAME_DURATION_TYPE 0x02
|
||||
|
||||
/** LE Audio Codec Specific Capability: Supported Audio Channel Counts. */
|
||||
#define BLE_AUDIO_CODEC_CAPS_SUP_AUDIO_CHANNEL_COUNTS_TYPE 0x03
|
||||
|
||||
/** LE Audio Codec Specific Capability: Supported Octets Per Codec Frame. */
|
||||
#define BLE_AUDIO_CODEC_CAPS_OCTETS_PER_CODEC_FRAME_TYPE 0x04
|
||||
|
||||
/** LE Audio Codec Specific Capability: Supported Codec Frames Per SDU. */
|
||||
#define BLE_AUDIO_CODEC_CAPS_FRAMES_PER_SDU_TYPE 0x05
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @defgroup ble_audio_contexts Bluetooth Low Energy Audio Context Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** LE Audio Codec Context Type: Prohibited. */
|
||||
#define BLE_AUDIO_CONTEXT_TYPE_PROHIBITED 0x0000
|
||||
|
||||
/** LE Audio Codec Context Type: Unspecified. */
|
||||
#define BLE_AUDIO_CONTEXT_TYPE_UNSPECIFIED 0x0001
|
||||
|
||||
/** LE Audio Codec Context Type: Conversational. */
|
||||
#define BLE_AUDIO_CONTEXT_TYPE_CONVERSATIONAL 0x0002
|
||||
|
||||
/** LE Audio Codec Context Type: Media. */
|
||||
#define BLE_AUDIO_CONTEXT_TYPE_MEDIA 0x0004
|
||||
|
||||
/** LE Audio Codec Context Type: Game. */
|
||||
#define BLE_AUDIO_CONTEXT_TYPE_GAME 0x0008
|
||||
|
||||
/** LE Audio Codec Context Type: Instructional. */
|
||||
#define BLE_AUDIO_CONTEXT_TYPE_INSTRUCTIONAL 0x0010
|
||||
|
||||
/** LE Audio Codec Context Type: Voice Assistants. */
|
||||
#define BLE_AUDIO_CONTEXT_TYPE_VOICE_ASSISTANTS 0x0020
|
||||
|
||||
/** LE Audio Codec Context Type: Live. */
|
||||
#define BLE_AUDIO_CONTEXT_TYPE_LIVE 0x0040
|
||||
|
||||
/** LE Audio Codec Context Type: Sound Effects. */
|
||||
#define BLE_AUDIO_CONTEXT_TYPE_SOUND_EFFECTS 0x0080
|
||||
|
||||
/** LE Audio Codec Context Type: Notifications. */
|
||||
#define BLE_AUDIO_CONTEXT_TYPE_NOTIFICATIONS 0x0100
|
||||
|
||||
/** LE Audio Codec Context Type: Ringtone. */
|
||||
#define BLE_AUDIO_CONTEXT_TYPE_RINGTONE 0x0200
|
||||
|
||||
/** LE Audio Codec Context Type: Alerts. */
|
||||
#define BLE_AUDIO_CONTEXT_TYPE_ALERTS 0x0400
|
||||
|
||||
/** LE Audio Codec Context Type: EmergencyAlarm. */
|
||||
#define BLE_AUDIO_CONTEXT_TYPE_EMERGENCY_ALARM 0x0800
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @defgroup ble_audio_contexts Bluetooth Low Energy Audio Supported Frame Durations
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** LE Audio Codec Supported Frame Duration: 7.5 ms frame duration. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_FRAME_DURATION_7_5_MS 0x0001
|
||||
|
||||
/** LE Audio Codec Supported Frame Duration: 10 ms frame duration. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_FRAME_DURATION_10_MS 0x0002
|
||||
|
||||
/** LE Audio Codec Supported Frame Duration: 7.5 ms preferred. */
|
||||
#define BLE_AUDIO_CODEC_PREFERED_FRAME_DURATION_7_5_MS 0x0010
|
||||
|
||||
/** LE Audio Codec Supported Frame Duration: 10 ms preferred. */
|
||||
#define BLE_AUDIO_CODEC_PREFERED_FRAME_DURATION_10_MS 0x0020
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @defgroup ble_audio_contexts Bluetooth Low Energy Audio Supported Sampling Frequencies
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** LE Audio Codec Supported Sampling Frequency: 8000 Hz. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_SAMPLING_RATE_8000_HZ (1ULL << 0)
|
||||
|
||||
/** LE Audio Codec Supported Sampling Frequency: 11025 Hz. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_SAMPLING_RATE_11025_HZ (1ULL << 1)
|
||||
|
||||
/** LE Audio Codec Supported Sampling Frequency: 16000 Hz. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_SAMPLING_RATE_16000_HZ (1ULL << 2)
|
||||
|
||||
/** LE Audio Codec Supported Sampling Frequency: 22050 Hz. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_SAMPLING_RATE_22050_HZ (1ULL << 3)
|
||||
|
||||
/** LE Audio Codec Supported Sampling Frequency: 24000 Hz. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_SAMPLING_RATE_24000_HZ (1ULL << 4)
|
||||
|
||||
/** LE Audio Codec Supported Sampling Frequency: 32000 Hz. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_SAMPLING_RATE_32000_HZ (1ULL << 5)
|
||||
|
||||
/** LE Audio Codec Supported Sampling Frequency: 44100 Hz. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_SAMPLING_RATE_44100_HZ (1ULL << 6)
|
||||
|
||||
/** LE Audio Codec Supported Sampling Frequency: 48000 Hz. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_SAMPLING_RATE_48000_HZ (1ULL << 7)
|
||||
|
||||
/** LE Audio Codec Supported Sampling Frequency: 88200 Hz. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_SAMPLING_RATE_88200_HZ (1ULL << 8)
|
||||
|
||||
/** LE Audio Codec Supported Sampling Frequency: 96000 Hz. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_SAMPLING_RATE_96000_HZ (1ULL << 9)
|
||||
|
||||
/** LE Audio Codec Supported Sampling Frequency: 176400 Hz. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_SAMPLING_RATE_176400_HZ (1ULL << 10)
|
||||
|
||||
/** LE Audio Codec Supported Sampling Frequency: 192000 Hz. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_SAMPLING_RATE_192000_HZ (1ULL << 11)
|
||||
|
||||
/** LE Audio Codec Supported Sampling Frequency: 384000 Hz. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_SAMPLING_RATE_384000_HZ (1ULL << 12)
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @defgroup ble_audio_contexts Bluetooth Low Energy Audio Supported Channel Counts
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** LE Audio Codec Supported Channel Count: 1. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_CHANNEL_COUNT_1 0x0001
|
||||
|
||||
/** LE Audio Codec Supported Channel Count: 2. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_CHANNEL_COUNT_2 0x0002
|
||||
|
||||
/** LE Audio Codec Supported Channel Count: 3. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_CHANNEL_COUNT_3 0x0004
|
||||
|
||||
/** LE Audio Codec Supported Channel Count: 4. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_CHANNEL_COUNT_4 0x0008
|
||||
|
||||
/** LE Audio Codec Supported Channel Count: 5. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_CHANNEL_COUNT_5 0x0010
|
||||
|
||||
/** LE Audio Codec Supported Channel Count: 6. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_CHANNEL_COUNT_6 0x0020
|
||||
|
||||
/** LE Audio Codec Supported Channel Count: 7. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_CHANNEL_COUNT_7 0x0040
|
||||
|
||||
/** LE Audio Codec Supported Channel Count: 8. */
|
||||
#define BLE_AUDIO_CODEC_SUPPORTED_CHANNEL_COUNT_8 0x0080
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -244,16 +409,55 @@
|
||||
_octets_per_codec_frame, \
|
||||
_codec_frame_blocks_per_sdu) \
|
||||
{ \
|
||||
2, BLE_AUDIO_CODEC_SAMPLING_FREQ_TYPE, _sampling_freq, \
|
||||
2, BLE_AUDIO_CODEC_FRAME_DURATION_TYPE, _frame_duration, \
|
||||
OPTIONAL_FIELD(5, BLE_AUDIO_CODEC_AUDIO_CHANNEL_ALLOCATION_TYPE, \
|
||||
2, BLE_AUDIO_CODEC_CONF_SAMPLING_FREQ_TYPE, _sampling_freq, \
|
||||
2, BLE_AUDIO_CODEC_CONF_FRAME_DURATION_TYPE, _frame_duration, \
|
||||
OPTIONAL_FIELD(5, BLE_AUDIO_CODEC_CONF_AUDIO_CHANNEL_ALLOCATION_TYPE, \
|
||||
_audio_channel_alloc) \
|
||||
3, BLE_AUDIO_CODEC_OCTETS_PER_CODEC_FRAME_TYPE, \
|
||||
3, BLE_AUDIO_CODEC_CONF_OCTETS_PER_CODEC_FRAME_TYPE, \
|
||||
(_octets_per_codec_frame), ((_octets_per_codec_frame) >> 8), \
|
||||
OPTIONAL_FIELD(2, BLE_AUDIO_CODEC_FRAME_BLOCKS_PER_SDU_TYPE, \
|
||||
OPTIONAL_FIELD(2, BLE_AUDIO_CODEC_CONF_FRAME_BLOCKS_PER_SDU_TYPE, \
|
||||
_codec_frame_blocks_per_sdu) \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper macro used to build LTV array of Codec_Specific_Capabilities.
|
||||
*
|
||||
* @param _sampling_freq Supported_Sampling_Frequencies -
|
||||
* two octet value
|
||||
* @param _frame_duration Supported_Frame_Durations - single
|
||||
* octet value
|
||||
* @param _audio_channel_counts Supported_Audio_Channel_Counts -
|
||||
* single octet value
|
||||
* @param _min_octets_per_codec_frame minimum value of
|
||||
* Supported_Octets_Per_Codec_Frame -
|
||||
* two octet value
|
||||
* @param _max_octets_per_codec_frame maximum value of
|
||||
* Supported_Octets_Per_Codec_Frame -
|
||||
* two octet value
|
||||
* @param _codec_frames_per_sdu Supported_Max_Codec_Frames_Per_SDU -
|
||||
* single octet value
|
||||
*
|
||||
* @return Pointer to a `ble_uuid16_t` structure.
|
||||
*/
|
||||
#define BLE_AUDIO_BUILD_CODEC_CAPS(_sampling_freq, \
|
||||
_frame_duration, \
|
||||
_audio_channel_counts, \
|
||||
_min_octets_per_codec_frame, \
|
||||
_max_octets_per_codec_frame, \
|
||||
_codec_frames_per_sdu) \
|
||||
{ \
|
||||
3, BLE_AUDIO_CODEC_CAPS_SAMPLING_FREQ_TYPE, \
|
||||
(_sampling_freq), ((_sampling_freq) >> 8), \
|
||||
2, BLE_AUDIO_CODEC_CAPS_FRAME_DURATION_TYPE, _frame_duration, \
|
||||
OPTIONAL_FIELD(2, BLE_AUDIO_CODEC_CAPS_SUP_AUDIO_CHANNEL_COUNTS_TYPE, \
|
||||
_audio_channel_counts) \
|
||||
5, BLE_AUDIO_CODEC_CAPS_OCTETS_PER_CODEC_FRAME_TYPE, \
|
||||
(_min_octets_per_codec_frame), ((_min_octets_per_codec_frame) >> 8), \
|
||||
(_max_octets_per_codec_frame), ((_max_octets_per_codec_frame) >> 8), \
|
||||
OPTIONAL_FIELD(2, BLE_AUDIO_CODEC_CAPS_FRAMES_PER_SDU_TYPE, \
|
||||
_codec_frames_per_sdu) \
|
||||
}
|
||||
|
||||
/** Codec Information */
|
||||
struct ble_audio_codec_id {
|
||||
/** Coding Format */
|
||||
@@ -306,6 +510,12 @@ struct ble_audio_broadcast_name {
|
||||
/** BLE Audio event: Broadcast Announcement */
|
||||
#define BLE_AUDIO_EVENT_BROADCAST_ANNOUNCEMENT 0
|
||||
|
||||
/** BLE Audio event: Codec Registered */
|
||||
#define BLE_AUDIO_EVENT_CODEC_REGISTERED 1
|
||||
|
||||
/** BLE Audio event: Codec Unregistered */
|
||||
#define BLE_AUDIO_EVENT_CODEC_UNREGISTERED 2
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @brief Broadcast Announcement */
|
||||
@@ -329,6 +539,18 @@ struct ble_audio_event_broadcast_announcement {
|
||||
struct ble_audio_broadcast_name *name;
|
||||
};
|
||||
|
||||
/** @brief Codec Registered */
|
||||
struct ble_audio_event_codec_registered {
|
||||
/** Codec Record */
|
||||
const struct ble_audio_codec_record *record;
|
||||
};
|
||||
|
||||
/** @brief Codec Unregistered */
|
||||
struct ble_audio_event_codec_unregistered {
|
||||
/** Codec Record */
|
||||
const struct ble_audio_codec_record *record;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a BLE Audio related event. When such an event occurs, the host
|
||||
* notifies the application by passing an instance of this structure to an
|
||||
@@ -352,6 +574,20 @@ struct ble_audio_event {
|
||||
* Represents a received Broadcast Announcement.
|
||||
*/
|
||||
struct ble_audio_event_broadcast_announcement broadcast_announcement;
|
||||
|
||||
/**
|
||||
* @ref BLE_AUDIO_EVENT_CODEC_REGISTERED
|
||||
*
|
||||
* Represents a codec registration.
|
||||
*/
|
||||
struct ble_audio_event_codec_registered codec_registered;
|
||||
|
||||
/**
|
||||
* @ref BLE_AUDIO_EVENT_CODEC_UNREGISTERED
|
||||
*
|
||||
* Represents a codec registration.
|
||||
*/
|
||||
struct ble_audio_event_codec_unregistered codec_unregistered;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_AUDIO_CODEC_
|
||||
#define H_BLE_AUDIO_CODEC_
|
||||
|
||||
/**
|
||||
* @file ble_audio_codec.h
|
||||
*
|
||||
* @brief Bluetooth LE Audio Codec
|
||||
*
|
||||
* This header file provides the public API for managing LE Audio Codecs
|
||||
*
|
||||
* @defgroup ble_audio_codec Bluetooth LE Audio Codec
|
||||
* @ingroup bt_host
|
||||
* @{
|
||||
*
|
||||
* This API allows to create and manage list of LE Audio codecs with their capabilities and
|
||||
* metadata. This list can be used by higher level services, like PACS. Memory management of
|
||||
* codec entries is left to application and neither static nor dynamic allocation is enforced.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdint.h"
|
||||
#include "ble_audio.h"
|
||||
|
||||
/** Bit describing direction of codec configuration - source */
|
||||
#define BLE_AUDIO_CODEC_DIR_SOURCE_BIT (1 << 0)
|
||||
/** Bit describing direction of codec configuration - sink */
|
||||
#define BLE_AUDIO_CODEC_DIR_SINK_BIT (1 << 1)
|
||||
|
||||
/** Codec list entry */
|
||||
struct ble_audio_codec_record {
|
||||
/* Pointer to next codec list entry */
|
||||
STAILQ_ENTRY(ble_audio_codec_record) next;
|
||||
|
||||
/* Codec ID */
|
||||
struct ble_audio_codec_id codec_id;
|
||||
|
||||
/* Length of Codec Specific Capabilities */
|
||||
uint8_t codec_spec_caps_len;
|
||||
|
||||
/* Codec Specific Capabilities data */
|
||||
const uint8_t *codec_spec_caps;
|
||||
|
||||
/* Metadata length */
|
||||
uint8_t metadata_len;
|
||||
|
||||
/* Metadata */
|
||||
const uint8_t *metadata;
|
||||
|
||||
/* Bitfield describing direction that codec is acting on. It is a logical OR of:
|
||||
* - BLE_AUDIO_CODEC_DIR_SOURCE_BIT
|
||||
* - BLE_AUDIO_CODEC_DIR_SINK_BIT
|
||||
*/
|
||||
uint8_t direction;
|
||||
};
|
||||
|
||||
/** Type definition codec iteration callback function. */
|
||||
typedef int ble_audio_codec_foreach_fn(const struct ble_audio_codec_record *record, void *arg);
|
||||
|
||||
struct ble_audio_codec_register_params {
|
||||
/* Codec ID structure */
|
||||
struct ble_audio_codec_id codec_id;
|
||||
|
||||
/* Codec Specific Capabilities length */
|
||||
uint8_t codec_spec_caps_len;
|
||||
|
||||
/* Codec Specific Capabilities data */
|
||||
uint8_t *codec_spec_caps;
|
||||
|
||||
/* Metadata length */
|
||||
uint8_t metadata_len;
|
||||
|
||||
/* Metadata */
|
||||
uint8_t *metadata;
|
||||
|
||||
/* Bitfield describing direction that codec is acting on. It is a logical OR of:
|
||||
* - BLE_AUDIO_CODEC_DIR_SOURCE_BIT
|
||||
* - BLE_AUDIO_CODEC_DIR_SINK_BIT
|
||||
*/
|
||||
uint8_t direction;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Register codec entry
|
||||
*
|
||||
* @param[in] params Pointer to a `ble_audio_codec_register_params`
|
||||
* structure that defines Codec Specific Capabilities
|
||||
* @param[out] out_record Pointer to registered codec entry.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* A non-zero value on failure.
|
||||
*/
|
||||
int ble_audio_codec_register(const struct ble_audio_codec_register_params
|
||||
*params,
|
||||
struct ble_audio_codec_record *out_record);
|
||||
/**
|
||||
* @brief Remove codec entry from register
|
||||
*
|
||||
* @param[in] codec_record Pointer to registered codec entry.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* A non-zero value on failure.
|
||||
*/
|
||||
int ble_audio_codec_unregister(struct ble_audio_codec_record *codec_record);
|
||||
|
||||
/**
|
||||
* @brief Iterate through all registered codecs and call function on every
|
||||
* one of them.
|
||||
*
|
||||
* @param[in] direction Codec entry direction. It is any
|
||||
* combination of following bits:
|
||||
* - BLE_AUDIO_CODEC_DIR_SOURCE_BIT
|
||||
* - BLE_AUDIO_CODEC_DIR_SINK_BIT
|
||||
* This filters entries so the callback is called
|
||||
* only on these have matching direction bit set.
|
||||
* @param[in] cb Callback to be called on codec entries.
|
||||
* @param[in] arg Optional callback argument.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* A non-zero value on failure.
|
||||
*/
|
||||
int ble_audio_codec_foreach(uint8_t direction, ble_audio_codec_foreach_fn *cb, void *arg);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* H_BLE_AUDIO_CODEC_ */
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_AUDIO_SVC_PACS_
|
||||
#define H_BLE_AUDIO_SVC_PACS_
|
||||
|
||||
/**
|
||||
* @file ble_audio_svc_pacs.h
|
||||
*
|
||||
* @brief Bluetooth LE Audio PAC Service
|
||||
*
|
||||
* This header file provides the public API for interacting with the PACS package.
|
||||
*
|
||||
* @defgroup ble_audio_svc_pacs Bluetooth LE Audio PACS package
|
||||
* @ingroup bt_host
|
||||
* @{
|
||||
*
|
||||
* This package is used to setup PACS for codecs registered with @ref ble_audio_codec.
|
||||
* To register a codec create it's definition as `ble_audio_codec_record` structure and register it
|
||||
* using `ble_audio_codec_register()`. Up to BLE_AUDIO_MAX_CODEC_RECORDS entries may be registered.
|
||||
* Registering and unregistering codecs, as well as setting PACS parameters will trigger sending
|
||||
* notifications, if their support is enabled (see pacs/syscfg.yml).
|
||||
*
|
||||
*/
|
||||
|
||||
#define BLE_SVC_AUDIO_PACS_UUID16 0x1850
|
||||
#define BLE_SVC_AUDIO_PACS_CHR_UUID16_SINK_PAC 0x2BC9
|
||||
#define BLE_SVC_AUDIO_PACS_CHR_UUID16_SINK_AUDIO_LOCATIONS 0x2BCA
|
||||
#define BLE_SVC_AUDIO_PACS_CHR_UUID16_SOURCE_PAC 0x2BCB
|
||||
#define BLE_SVC_AUDIO_PACS_CHR_UUID16_SOURCE_AUDIO_LOCATIONS 0x2BCC
|
||||
#define BLE_SVC_AUDIO_PACS_CHR_UUID16_AVAILABLE_AUDIO_CONTEXTS 0x2BCD
|
||||
#define BLE_SVC_AUDIO_PACS_CHR_UUID16_SUPPORTED_AUDIO_CONTEXTS 0x2BCE
|
||||
|
||||
|
||||
struct ble_svc_audio_pacs_set_param {
|
||||
/* Supported Audio Locations */
|
||||
uint32_t audio_locations;
|
||||
|
||||
/* Supported Contexts */
|
||||
uint16_t supported_contexts;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Set PACS params.
|
||||
*
|
||||
* Set device capabilities reported in Published Audio Capabilities Service.
|
||||
*
|
||||
* @param[in] flags Flags that define if capabilities being set are for
|
||||
* Sink or Source. Valid values are either
|
||||
* `BLE_AUDIO_CODEC_FLAG_SOURCE` or `BLE_AUDIO_CODEC_FLAG_SINK`
|
||||
* @param[in] param Pointer to a `ble_svc_audio_pacs_set_param`
|
||||
* structure that defines capabilities supported by
|
||||
* device.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* A non-zero value on failure.
|
||||
*/
|
||||
int ble_svc_audio_pacs_set(uint8_t flags, struct ble_svc_audio_pacs_set_param *param);
|
||||
|
||||
/**
|
||||
* @brief Set available context types.
|
||||
*
|
||||
* @param[in] conn_handle Connection handle identifying connection for which contexts
|
||||
* being set
|
||||
* @param[in] sink_contexts Available Sink Contexts
|
||||
* @param[in] source_contexts Available Source Contexts
|
||||
*
|
||||
* @return 0 on success;
|
||||
* A non-zero value on failure.
|
||||
*/
|
||||
int ble_svc_audio_pacs_avail_contexts_set(uint16_t conn_handle,
|
||||
uint16_t sink_contexts,
|
||||
uint16_t source_contexts);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* H_BLE_AUDIO_SVC_PACS_ */
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_AUDIO_SVC_PACS_LC3_
|
||||
#define H_BLE_AUDIO_SVC_PACS_LC3_
|
||||
|
||||
|
||||
/**
|
||||
* @file ble_audio_svc_pacs_lc3.h
|
||||
*
|
||||
* @brief Bluetooth PAC Service for LC3 Codec
|
||||
*
|
||||
* This header file provides the public API for interacting with the PACS LC3 package, that
|
||||
* registers PAC entry for LC3 codec with configurations contained in system configuration file
|
||||
*
|
||||
* @defgroup ble_audio_svc_pacs_lc3 Bluetooth LE Audio PACS LC3 package
|
||||
* @ingroup ble_audio_svc_pacs
|
||||
* @{
|
||||
*
|
||||
* This package is an example how to register codec entry that PACS can use to construct its entries
|
||||
* for GATT database. This is high level package that can be used to construct basic PACS setup for
|
||||
* LC3 codec. This package creates only single PAC entry per source and sink. If more PAC entries
|
||||
* need to be created, with more advanced setup, @ref ble_audio_svc_pacs service shall be used in
|
||||
* combination with @ref ble_audio_codec API.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Set available context types.
|
||||
*
|
||||
* @param[in] conn_handle Connection handle identifying connection for which contexts
|
||||
* being set
|
||||
* @param[in] sink_contexts Available Sink Contexts
|
||||
* @param[in] source_contexts Available Source Contexts
|
||||
*
|
||||
* @return 0 on success;
|
||||
* A non-zero value on failure.
|
||||
*/
|
||||
int ble_svc_audio_pacs_lc3_set_avail_contexts(uint16_t conn_handle,
|
||||
uint16_t sink_contexts,
|
||||
uint16_t source_contexts);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* H_BLE_AUDIO_SVC_PACS_LC3_ */
|
||||
@@ -0,0 +1,34 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
pkg.name: nimble/host/audio/services/pacs/lc3
|
||||
pkg.description: LC3 codec entry for Published Audio Capabilities Service
|
||||
pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
|
||||
pkg.homepage: "https://mynewt.apache.org/"
|
||||
pkg.keywords:
|
||||
- ble
|
||||
- bluetooth
|
||||
- pacs
|
||||
- nimble
|
||||
|
||||
pkg.deps:
|
||||
- nimble/host/audio/services/pacs
|
||||
- nimble/host
|
||||
|
||||
pkg.init:
|
||||
ble_svc_audio_pacs_lc3_init:
|
||||
- $after:ble_svc_audio_pacs_init
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "audio/ble_audio_codec.h"
|
||||
#include "services/pacs/ble_audio_svc_pacs.h"
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "host/ble_hs.h"
|
||||
|
||||
/* Below is to unmangle comma separated Metadata octets from MYNEWT_VAL */
|
||||
#define _Args(...) __VA_ARGS__
|
||||
#define STRIP_PARENS(X) X
|
||||
#define UNMANGLE_MYNEWT_VAL(X) STRIP_PARENS(_Args X)
|
||||
|
||||
#define BLE_SVC_AUDIO_PACS_LC3_CODEC_ID 0x06
|
||||
|
||||
static uint8_t ble_svc_audio_pacs_lc3_src_codec_spec_caps[] = BLE_AUDIO_BUILD_CODEC_CAPS(
|
||||
MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_SAMPLING_FREQUENCIES),
|
||||
MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_FRAME_DURATIONS),
|
||||
#ifdef MYNEWT_VAL_BLE_SVC_AUDIO_PACS_LC3_SRC_AUDIO_CHANNEL_COUNTS
|
||||
MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_AUDIO_CHANNEL_COUNTS),
|
||||
#else
|
||||
,
|
||||
#endif
|
||||
MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_MIN_OCTETS_PER_CODEC_FRAME),
|
||||
MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_MAX_OCTETS_PER_CODEC_FRAME),
|
||||
#ifdef MYNEWT_VAL_BLE_SVC_AUDIO_PACS_LC3_SRC_MAX_CODEC_FRAMES_PER_SDU
|
||||
MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_MAX_CODEC_FRAMES_PER_SDU),
|
||||
#endif
|
||||
);
|
||||
|
||||
static uint8_t ble_svc_audio_pacs_lc3_snk_codec_spec_caps[] = BLE_AUDIO_BUILD_CODEC_CAPS(
|
||||
MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SNK_SAMPLING_FREQUENCIES),
|
||||
MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SNK_FRAME_DURATIONS),
|
||||
#ifdef MYNEWT_VAL_BLE_SVC_AUDIO_PACS_LC3_SRC_AUDIO_CHANNEL_COUNTS
|
||||
MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SNK_AUDIO_CHANNEL_COUNTS),
|
||||
#else
|
||||
,
|
||||
#endif
|
||||
MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SNK_MIN_OCTETS_PER_CODEC_FRAME),
|
||||
MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_MAX_OCTETS_PER_CODEC_FRAME),
|
||||
#ifdef MYNEWT_VAL_BLE_SVC_AUDIO_PACS_LC3_SRC_MAX_CODEC_FRAMES_PER_SDU
|
||||
MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SNK_MAX_CODEC_FRAMES_PER_SDU),
|
||||
#endif
|
||||
);
|
||||
|
||||
#ifdef MYNEWT_VAL_BLE_SVC_AUDIO_PACS_LC3_SRC_METADATA
|
||||
static uint8_t ble_svc_audio_pacs_lc3_src_metadata[] =
|
||||
{ UNMANGLE_MYNEWT_VAL(MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_METADATA)) };
|
||||
#endif
|
||||
|
||||
#ifdef MYNEWT_VAL_BLE_SVC_AUDIO_PACS_LC3_SNK_METADATA
|
||||
static uint8_t ble_svc_audio_pacs_lc3_snk_metadata[] =
|
||||
{ UNMANGLE_MYNEWT_VAL(MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SNK_METADATA)) };
|
||||
#endif
|
||||
|
||||
static struct ble_audio_codec_register_params src_codec_params = {
|
||||
.codec_id = {
|
||||
.format = BLE_SVC_AUDIO_PACS_LC3_CODEC_ID,
|
||||
.company_id = 0x00,
|
||||
.vendor_specific = 0x00
|
||||
},
|
||||
.codec_spec_caps_len = sizeof(ble_svc_audio_pacs_lc3_src_codec_spec_caps),
|
||||
.codec_spec_caps = ble_svc_audio_pacs_lc3_src_codec_spec_caps,
|
||||
#ifdef MYNEWT_VAL_BLE_SVC_AUDIO_PACS_LC3_SRC_METADATA
|
||||
.metadata_len = sizeof(ble_svc_audio_pacs_lc3_src_metadata),
|
||||
.metadata = ble_svc_audio_pacs_lc3_src_metadata,
|
||||
#else
|
||||
.metadata_len = 0,
|
||||
#endif
|
||||
.direction = BLE_AUDIO_CODEC_DIR_SOURCE_BIT
|
||||
};
|
||||
|
||||
static struct ble_audio_codec_register_params snk_codec_params = {
|
||||
.codec_id = {
|
||||
.format = BLE_SVC_AUDIO_PACS_LC3_CODEC_ID,
|
||||
.company_id = 0x00,
|
||||
.vendor_specific = 0x00
|
||||
},
|
||||
.codec_spec_caps_len = sizeof(ble_svc_audio_pacs_lc3_snk_codec_spec_caps),
|
||||
.codec_spec_caps = ble_svc_audio_pacs_lc3_snk_codec_spec_caps,
|
||||
#ifdef MYNEWT_VAL_BLE_SVC_AUDIO_PACS_LC3_SNK_METADATA
|
||||
.metadata_len = sizeof(ble_svc_audio_pacs_lc3_snk_metadata),
|
||||
.metadata = ble_svc_audio_pacs_lc3_snk_metadata,
|
||||
#else
|
||||
.metadata_len = 0,
|
||||
#endif
|
||||
|
||||
.direction = BLE_AUDIO_CODEC_DIR_SINK_BIT
|
||||
};
|
||||
|
||||
static int
|
||||
codec_register(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ble_audio_codec_register(&src_codec_params, NULL);
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
rc = ble_audio_codec_register(&snk_codec_params, NULL);
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ble_svc_audio_pacs_lc3_set_avail_contexts(uint16_t conn_handle,
|
||||
uint16_t sink_contexts,
|
||||
uint16_t source_contexts)
|
||||
{
|
||||
return ble_svc_audio_pacs_avail_contexts_set(conn_handle, sink_contexts,
|
||||
source_contexts);
|
||||
}
|
||||
|
||||
void
|
||||
ble_svc_audio_pacs_lc3_init(void)
|
||||
{
|
||||
struct ble_svc_audio_pacs_set_param src_params = {
|
||||
.audio_locations = MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_AUDIO_LOCATIONS),
|
||||
.supported_contexts = MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_SUP_CONTEXTS)
|
||||
};
|
||||
struct ble_svc_audio_pacs_set_param snk_params = {
|
||||
.audio_locations = MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SNK_SUP_AUDIO_LOCATIONS),
|
||||
.supported_contexts = MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SNK_SUP_CONTEXTS)
|
||||
};
|
||||
int rc;
|
||||
|
||||
rc = codec_register();
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
rc = ble_svc_audio_pacs_set(BLE_AUDIO_CODEC_DIR_SOURCE_BIT, &src_params);
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
rc = ble_svc_audio_pacs_set(BLE_AUDIO_CODEC_DIR_SINK_BIT, &snk_params);
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
(void)rc;
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
syscfg.defs:
|
||||
BLE_SVC_AUDIO_PACS_LC3_SRC_SAMPLING_FREQUENCIES:
|
||||
description: >
|
||||
Sampling frequencies supported by LC3 codec, as source. This setting is mandatory.
|
||||
Accepts any combination of values defined in Bluetooth Assigned Numbers 6.12.4.1.
|
||||
Default value: 48000Hz
|
||||
value: 0x80
|
||||
restrictions:
|
||||
- $notnull
|
||||
BLE_SVC_AUDIO_PACS_LC3_SRC_FRAME_DURATIONS:
|
||||
description: >
|
||||
Frame Durations supported by LC3 codec, as source. This setting is mandatory.
|
||||
Accepts any combination of values defined in Bluetooth Assigned Numbers 6.12.4.2.
|
||||
Default value: 7.5ms and 10ms supported, 10ms preferred.
|
||||
value: 0x23
|
||||
restrictions:
|
||||
- $notnull
|
||||
BLE_SVC_AUDIO_PACS_LC3_SRC_AUDIO_CHANNEL_COUNTS:
|
||||
description: >
|
||||
Audio Channel Counts supported by LC3 codec, as source. This setting is optional.
|
||||
Accepts any combination of values defined in Bluetooth Assigned Numbers 6.12.4.3.
|
||||
value:
|
||||
BLE_SVC_AUDIO_PACS_LC3_SRC_MIN_OCTETS_PER_CODEC_FRAME:
|
||||
description: >
|
||||
Minimum number of Octets Per Codec Frame supported by LC3 codec, as source.
|
||||
This setting is mandatory. Default value: 80
|
||||
value: 80
|
||||
restrictions:
|
||||
- $notnull
|
||||
BLE_SVC_AUDIO_PACS_LC3_SRC_MAX_OCTETS_PER_CODEC_FRAME:
|
||||
description: >
|
||||
Maximum number of Octets Per Codec Frame supported by LC3 codec, as source.
|
||||
This setting is mandatory. Default value: 120
|
||||
value: 120
|
||||
restrictions:
|
||||
- $notnull
|
||||
BLE_SVC_AUDIO_PACS_LC3_SRC_MAX_CODEC_FRAMES_PER_SDU:
|
||||
description: >
|
||||
Maximum number of Codec Frames Per SDU supported by LC3 codec, as source.
|
||||
This setting is optional.
|
||||
value:
|
||||
BLE_SVC_AUDIO_PACS_LC3_SRC_METADATA:
|
||||
description: >
|
||||
Optional Metadata to be attached to source codec capabilities. This value shall be in
|
||||
form of bytes forming LTVs of Metadata. Example: '0x03, 0x01, 0x00, 0x08'
|
||||
(lenght = 3, type = 0x01 (Preferred_Audio_Contexts), 0x00, 0x04 (Media))
|
||||
value:
|
||||
BLE_SVC_AUDIO_PACS_LC3_SRC_AUDIO_LOCATIONS:
|
||||
description: >
|
||||
Audio Locations supported by source codec. Value is an any combination of values defined
|
||||
in Bluetooth Assigned Numbers 6.12.1. Default: Front Left and Front Right
|
||||
value: 0x00000003
|
||||
BLE_SVC_AUDIO_PACS_LC3_SRC_SUP_CONTEXTS:
|
||||
description: >
|
||||
Audio Locations supported by source codec. Value is an any combination of values defined
|
||||
in Bluetooth Assigned Numbers 6.12.3. Default: Media
|
||||
value: 0x0004
|
||||
|
||||
BLE_SVC_AUDIO_PACS_LC3_SNK_SAMPLING_FREQUENCIES:
|
||||
description: >
|
||||
Sampling frequencies supported by LC3 codec, as sink. This setting is mandatory.
|
||||
Accepts any combination of values defined in Bluetooth Assigned Numbers 6.12.4.1.
|
||||
Default value: 48000Hz
|
||||
value: 0x80
|
||||
restrictions:
|
||||
- $notnull
|
||||
BLE_SVC_AUDIO_PACS_LC3_SNK_FRAME_DURATIONS:
|
||||
description: >
|
||||
Frame Durations supported by LC3 codec, as sink. This setting is mandatory.
|
||||
Accepts any combination of values defined in Bluetooth Assigned Numbers 6.12.4.2.
|
||||
Default value: 7.5ms and 10ms supported, 10ms preferred.
|
||||
value: 0x23
|
||||
restrictions:
|
||||
- $notnull
|
||||
BLE_SVC_AUDIO_PACS_LC3_SNK_AUDIO_CHANNEL_COUNTS:
|
||||
description: >
|
||||
Audio Channel Counts supported by LC3 codec, as sink. This setting is optional.
|
||||
Accepts any combination of values defined in Bluetooth Assigned Numbers 6.12.4.3.
|
||||
value:
|
||||
BLE_SVC_AUDIO_PACS_LC3_SNK_MIN_OCTETS_PER_CODEC_FRAME:
|
||||
description: >
|
||||
Minimum number of Octets Per Codec Frame supported by LC3 codec, as source.
|
||||
This setting is mandatory. Default value: 80
|
||||
value: 80
|
||||
restrictions:
|
||||
- $notnull
|
||||
BLE_SVC_AUDIO_PACS_LC3_SNK_MAX_OCTETS_PER_CODEC_FRAME:
|
||||
description: >
|
||||
Maximum number of Octets Per Codec Frame supported by LC3 codec, as sink.
|
||||
This setting is mandatory. Default value: 120
|
||||
value: 120
|
||||
restrictions:
|
||||
- $notnull
|
||||
BLE_SVC_AUDIO_PACS_LC3_SNK_MAX_CODEC_FRAMES_PER_SDU:
|
||||
description: >
|
||||
Maximum number of Codec Frames Per SDU supported by LC3 codec, as sink.
|
||||
This setting is optional.
|
||||
value:
|
||||
BLE_SVC_AUDIO_PACS_LC3_SNK_METADATA:
|
||||
description: >
|
||||
Optional Metadata to be attached to sink codec capabilities. This value shall be in
|
||||
form of bytes forming LTVs of Metadata. Example: '0x03, 0x01, 0x00, 0x08'
|
||||
(lenght = 3, type = 0x01 (Preferred_Audio_Contexts), 0x00, 0x04 (Media))
|
||||
value:
|
||||
BLE_SVC_AUDIO_PACS_LC3_SNK_SUP_AUDIO_LOCATIONS:
|
||||
description: >
|
||||
Audio Locations supported by sink codec. Value is an any combination of values defined
|
||||
in Bluetooth Assigned Numbers 6.12.1. Default: Front Left and Front Right
|
||||
value: 0x00000003
|
||||
BLE_SVC_AUDIO_PACS_LC3_SNK_SUP_CONTEXTS:
|
||||
description: >
|
||||
Audio Locations supported by sink codec. Value is an any combination of values defined
|
||||
in Bluetooth Assigned Numbers 6.12.3. Default: Media
|
||||
value: 0x0004
|
||||
@@ -0,0 +1,33 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
pkg.name: nimble/host/audio/services/pacs
|
||||
pkg.description: Published Audio Capabilities Service
|
||||
pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
|
||||
pkg.homepage: "https://mynewt.apache.org/"
|
||||
pkg.keywords:
|
||||
- ble
|
||||
- bluetooth
|
||||
- pacs
|
||||
- nimble
|
||||
|
||||
pkg.deps:
|
||||
- nimble/host
|
||||
- nimble/host/services/gatt
|
||||
|
||||
pkg.init:
|
||||
ble_svc_audio_pacs_init: 'MYNEWT_VAL(BLE_SVC_AUDIO_PACS_SYSINIT_STAGE)'
|
||||
@@ -0,0 +1,479 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "audio/ble_audio.h"
|
||||
#include "host/ble_hs.h"
|
||||
#include "host/ble_gatt.h"
|
||||
#include "audio/ble_audio_codec.h"
|
||||
#include "services/pacs/ble_audio_svc_pacs.h"
|
||||
|
||||
static uint32_t ble_svc_audio_pacs_sink_audio_locations;
|
||||
static uint32_t ble_svc_audio_pacs_source_audio_locations;
|
||||
static struct available_ctx {
|
||||
uint16_t conn_handle;
|
||||
uint16_t ble_svc_audio_pacs_avail_sink_contexts;
|
||||
uint16_t ble_svc_audio_pacs_avail_source_contexts;
|
||||
} ble_svc_audio_pacs_avail_contexts[MYNEWT_VAL(BLE_MAX_CONNECTIONS)] = {
|
||||
[0 ... MYNEWT_VAL(BLE_MAX_CONNECTIONS) - 1] = {
|
||||
.conn_handle = BLE_HS_CONN_HANDLE_NONE,
|
||||
.ble_svc_audio_pacs_avail_sink_contexts = 0,
|
||||
.ble_svc_audio_pacs_avail_source_contexts = 0
|
||||
}
|
||||
};
|
||||
static uint16_t ble_svc_audio_pacs_sup_sink_contexts;
|
||||
static uint16_t ble_svc_audio_pacs_sup_source_contexts;
|
||||
|
||||
static struct ble_gap_event_listener ble_pacs_listener;
|
||||
static struct ble_audio_event_listener ble_audio_listener;
|
||||
|
||||
struct pac_read_cb_arg {
|
||||
struct os_mbuf *om;
|
||||
uint8_t pac_count;
|
||||
};
|
||||
|
||||
static int
|
||||
ble_svc_audio_pacs_access(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
|
||||
static const struct ble_gatt_svc_def ble_svc_audio_pacs_defs[] = {
|
||||
{ /*** Service: Published Audio Capabilities Service (PACS) */
|
||||
.type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||
.uuid = BLE_UUID16_DECLARE(BLE_SVC_AUDIO_PACS_UUID16),
|
||||
.characteristics = (struct ble_gatt_chr_def[]) {
|
||||
#if MYNEWT_VAL(BLE_SVC_AUDIO_PACS_SINK_PAC)
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(BLE_SVC_AUDIO_PACS_CHR_UUID16_SINK_PAC),
|
||||
.access_cb = ble_svc_audio_pacs_access,
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC
|
||||
#if MYNEWT_VAL(BLE_SVC_AUDIO_PACS_SINK_PAC_NOTIFY)
|
||||
| BLE_GATT_CHR_F_NOTIFY
|
||||
#endif
|
||||
},
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_SVC_AUDIO_PACS_SINK_AUDIO_LOCATIONS)
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(
|
||||
BLE_SVC_AUDIO_PACS_CHR_UUID16_SINK_AUDIO_LOCATIONS),
|
||||
.access_cb = ble_svc_audio_pacs_access,
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC
|
||||
#if MYNEWT_VAL(BLE_SVC_AUDIO_PACS_SINK_AUDIO_LOCATIONS_NOTIFY)
|
||||
| BLE_GATT_CHR_F_NOTIFY
|
||||
#endif
|
||||
},
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_SVC_AUDIO_PACS_SOURCE_PAC)
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(
|
||||
BLE_SVC_AUDIO_PACS_CHR_UUID16_SOURCE_PAC),
|
||||
.access_cb = ble_svc_audio_pacs_access,
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC
|
||||
#if MYNEWT_VAL(BLE_SVC_AUDIO_PACS_SOURCE_PAC_NOTIFY)
|
||||
| BLE_GATT_CHR_F_NOTIFY
|
||||
#endif
|
||||
},
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_SVC_AUDIO_PACS_SOURCE_AUDIO_LOCATIONS)
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(
|
||||
BLE_SVC_AUDIO_PACS_CHR_UUID16_SOURCE_AUDIO_LOCATIONS),
|
||||
.access_cb = ble_svc_audio_pacs_access,
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC
|
||||
#if MYNEWT_VAL(BLE_SVC_AUDIO_PACS_SOURCE_AUDIO_LOCATIONS_NOTIFY)
|
||||
| BLE_GATT_CHR_F_NOTIFY
|
||||
#endif
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.uuid = BLE_UUID16_DECLARE(
|
||||
BLE_SVC_AUDIO_PACS_CHR_UUID16_AVAILABLE_AUDIO_CONTEXTS),
|
||||
.access_cb = ble_svc_audio_pacs_access,
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_NOTIFY,
|
||||
}, {
|
||||
.uuid = BLE_UUID16_DECLARE(
|
||||
BLE_SVC_AUDIO_PACS_CHR_UUID16_SUPPORTED_AUDIO_CONTEXTS),
|
||||
.access_cb = ble_svc_audio_pacs_access,
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC
|
||||
#if MYNEWT_VAL(BLE_SVC_AUDIO_PACS_SUP_AUDIO_CTX_NOTIFY)
|
||||
| BLE_GATT_CHR_F_NOTIFY
|
||||
#endif
|
||||
}, {
|
||||
0, /* No more characteristics in this service */
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
0, /* No more services. */
|
||||
},
|
||||
};
|
||||
|
||||
static int
|
||||
codec_record_to_pacs_entry(const struct ble_audio_codec_record *record, void *arg)
|
||||
{
|
||||
struct pac_read_cb_arg *cb_arg = (struct pac_read_cb_arg *)arg;
|
||||
uint8_t *buf;
|
||||
int rc;
|
||||
|
||||
rc = os_mbuf_append(cb_arg->om, &record->codec_id.format, sizeof(uint8_t));
|
||||
if (rc) {
|
||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
|
||||
buf = os_mbuf_extend(cb_arg->om, 4);
|
||||
if (buf == NULL) {
|
||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
put_le16(buf + 0, record->codec_id.company_id);
|
||||
put_le16(buf + 2, record->codec_id.vendor_specific);
|
||||
|
||||
rc = os_mbuf_append(cb_arg->om, &record->codec_spec_caps_len, sizeof(uint8_t));
|
||||
if (rc) {
|
||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
|
||||
rc = os_mbuf_append(cb_arg->om, record->codec_spec_caps, record->codec_spec_caps_len);
|
||||
if (rc) {
|
||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
|
||||
rc = os_mbuf_append(cb_arg->om, &record->metadata_len, sizeof(uint8_t));
|
||||
if (rc) {
|
||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
|
||||
rc = os_mbuf_append(cb_arg->om, record->metadata, record->metadata_len);
|
||||
if (rc) {
|
||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
|
||||
cb_arg->pac_count++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_svc_audio_pacs_sink_pac_read_access(struct ble_gatt_access_ctxt *ctxt)
|
||||
{
|
||||
struct pac_read_cb_arg cb_arg = {
|
||||
.om = ctxt->om,
|
||||
.pac_count = 0
|
||||
};
|
||||
int rc;
|
||||
uint8_t *pac_count;
|
||||
|
||||
pac_count = os_mbuf_extend(ctxt->om, sizeof(uint8_t));
|
||||
rc = ble_audio_codec_foreach(BLE_AUDIO_CODEC_DIR_SINK_BIT,
|
||||
codec_record_to_pacs_entry, (void *)&cb_arg);
|
||||
|
||||
*pac_count = cb_arg.pac_count;
|
||||
|
||||
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_svc_audio_pacs_source_pac_read_access(struct ble_gatt_access_ctxt *ctxt)
|
||||
{
|
||||
struct pac_read_cb_arg cb_arg = {
|
||||
.om = ctxt->om,
|
||||
.pac_count = 0
|
||||
};
|
||||
int rc;
|
||||
uint8_t *pac_count;
|
||||
|
||||
pac_count = os_mbuf_extend(ctxt->om, sizeof(uint8_t));
|
||||
rc = ble_audio_codec_foreach(BLE_AUDIO_CODEC_DIR_SOURCE_BIT,
|
||||
codec_record_to_pacs_entry, (void *)&cb_arg);
|
||||
|
||||
*pac_count = cb_arg.pac_count;
|
||||
|
||||
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_svc_audio_pacs_sink_audio_loc_read_access(struct ble_gatt_access_ctxt *
|
||||
ctxt)
|
||||
{
|
||||
uint8_t *buf;
|
||||
|
||||
buf = os_mbuf_extend(ctxt->om, 4);
|
||||
if (buf == NULL) {
|
||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
|
||||
put_le32(buf + 0, ble_svc_audio_pacs_sink_audio_locations);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_svc_audio_pacs_source_audio_loc_read_access(struct ble_gatt_access_ctxt *
|
||||
ctxt)
|
||||
{
|
||||
uint8_t *buf;
|
||||
|
||||
buf = os_mbuf_extend(ctxt->om, 4);
|
||||
if (buf == NULL) {
|
||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
|
||||
put_le32(buf + 0, ble_svc_audio_pacs_source_audio_locations);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct available_ctx *
|
||||
ble_svc_audio_pacs_find_avail_ctx(uint16_t conn_handle)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MYNEWT_VAL(BLE_MAX_CONNECTIONS); i++) {
|
||||
if (ble_svc_audio_pacs_avail_contexts[i].conn_handle == conn_handle) {
|
||||
return &ble_svc_audio_pacs_avail_contexts[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_svc_audio_pacs_avail_audio_ctx_read_access(uint16_t conn_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt)
|
||||
{
|
||||
struct available_ctx *avail_ctx;
|
||||
uint8_t *buf;
|
||||
|
||||
avail_ctx = ble_svc_audio_pacs_find_avail_ctx(conn_handle);
|
||||
|
||||
buf = os_mbuf_extend(ctxt->om, 4);
|
||||
if (buf == NULL) {
|
||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
|
||||
put_le16(buf + 0, avail_ctx->ble_svc_audio_pacs_avail_sink_contexts);
|
||||
put_le16(buf + 2, avail_ctx->ble_svc_audio_pacs_avail_source_contexts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_svc_audio_pacs_sup_audio_ctx_read_access(struct ble_gatt_access_ctxt
|
||||
*ctxt)
|
||||
{
|
||||
uint8_t *buf;
|
||||
|
||||
buf = os_mbuf_extend(ctxt->om, 4);
|
||||
if (buf == NULL) {
|
||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
|
||||
put_le16(buf + 0, ble_svc_audio_pacs_sup_sink_contexts);
|
||||
put_le16(buf + 2, ble_svc_audio_pacs_sup_source_contexts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_svc_audio_pacs_access(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg)
|
||||
{
|
||||
uint16_t uuid16 = ble_uuid_u16(ctxt->chr->uuid);
|
||||
int rc;
|
||||
|
||||
switch (uuid16) {
|
||||
case BLE_SVC_AUDIO_PACS_CHR_UUID16_SINK_PAC:
|
||||
if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
|
||||
rc = ble_svc_audio_pacs_sink_pac_read_access(ctxt);
|
||||
} else {
|
||||
assert(0);
|
||||
rc = BLE_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
return rc;
|
||||
case BLE_SVC_AUDIO_PACS_CHR_UUID16_SINK_AUDIO_LOCATIONS:
|
||||
if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
|
||||
rc = ble_svc_audio_pacs_sink_audio_loc_read_access(ctxt);
|
||||
} else {
|
||||
rc = BLE_ATT_ERR_REQ_NOT_SUPPORTED;
|
||||
}
|
||||
return rc;
|
||||
case BLE_SVC_AUDIO_PACS_CHR_UUID16_SOURCE_PAC:
|
||||
if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
|
||||
rc = ble_svc_audio_pacs_source_pac_read_access(ctxt);
|
||||
} else {
|
||||
assert(0);
|
||||
rc = BLE_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
return rc;
|
||||
case BLE_SVC_AUDIO_PACS_CHR_UUID16_SOURCE_AUDIO_LOCATIONS:
|
||||
if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
|
||||
rc = ble_svc_audio_pacs_source_audio_loc_read_access(ctxt);
|
||||
} else {
|
||||
rc = BLE_ATT_ERR_REQ_NOT_SUPPORTED;
|
||||
}
|
||||
return rc;
|
||||
case BLE_SVC_AUDIO_PACS_CHR_UUID16_AVAILABLE_AUDIO_CONTEXTS:
|
||||
if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
|
||||
rc = ble_svc_audio_pacs_avail_audio_ctx_read_access(conn_handle,
|
||||
ctxt);
|
||||
} else {
|
||||
assert(0);
|
||||
rc = BLE_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
return rc;
|
||||
case BLE_SVC_AUDIO_PACS_CHR_UUID16_SUPPORTED_AUDIO_CONTEXTS:
|
||||
if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
|
||||
rc = ble_svc_audio_pacs_sup_audio_ctx_read_access(ctxt);
|
||||
} else {
|
||||
assert(0);
|
||||
rc = BLE_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
return rc;
|
||||
default:
|
||||
assert(0);
|
||||
return BLE_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
pac_notify(uint16_t chrc_uuid)
|
||||
{
|
||||
uint16_t chr_val_handle;
|
||||
int rc;
|
||||
|
||||
if (!ble_hs_is_enabled()) {
|
||||
/* Do not notify if host has not started yet */
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BLE_SVC_AUDIO_PACS_UUID16),
|
||||
BLE_UUID16_DECLARE(chrc_uuid), NULL, &chr_val_handle);
|
||||
|
||||
if (!rc) {
|
||||
ble_gatts_chr_updated(chr_val_handle);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ble_svc_audio_pacs_set(uint8_t flags, struct ble_svc_audio_pacs_set_param *param)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (flags & BLE_AUDIO_CODEC_DIR_SOURCE_BIT) {
|
||||
ble_svc_audio_pacs_source_audio_locations = param->audio_locations;
|
||||
ble_svc_audio_pacs_sup_source_contexts = param->supported_contexts;
|
||||
rc = pac_notify(BLE_SVC_AUDIO_PACS_CHR_UUID16_SOURCE_AUDIO_LOCATIONS);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & BLE_AUDIO_CODEC_DIR_SINK_BIT) {
|
||||
ble_svc_audio_pacs_sink_audio_locations = param->audio_locations;
|
||||
ble_svc_audio_pacs_sup_sink_contexts = param->supported_contexts;
|
||||
rc = pac_notify(BLE_SVC_AUDIO_PACS_CHR_UUID16_SOURCE_AUDIO_LOCATIONS);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return pac_notify(BLE_SVC_AUDIO_PACS_CHR_UUID16_SUPPORTED_AUDIO_CONTEXTS);
|
||||
}
|
||||
|
||||
int
|
||||
ble_svc_audio_pacs_avail_contexts_set(uint16_t conn_handle,
|
||||
uint16_t sink_contexts,
|
||||
uint16_t source_contexts)
|
||||
{
|
||||
struct available_ctx *avail_ctx = ble_svc_audio_pacs_find_avail_ctx(conn_handle);
|
||||
|
||||
avail_ctx->ble_svc_audio_pacs_avail_sink_contexts = sink_contexts;
|
||||
avail_ctx->ble_svc_audio_pacs_avail_source_contexts = source_contexts;
|
||||
|
||||
return pac_notify(BLE_SVC_AUDIO_PACS_CHR_UUID16_AVAILABLE_AUDIO_CONTEXTS);
|
||||
}
|
||||
|
||||
static int
|
||||
ble_pacs_audio_event(struct ble_audio_event *event, void *arg)
|
||||
{
|
||||
uint8_t codec_dir;
|
||||
|
||||
if (event->type == BLE_AUDIO_EVENT_CODEC_REGISTERED ||
|
||||
event->type == BLE_AUDIO_EVENT_CODEC_UNREGISTERED) {
|
||||
codec_dir = event->type == BLE_AUDIO_EVENT_CODEC_REGISTERED ?
|
||||
event->codec_registered.record->direction :
|
||||
event->codec_unregistered.record->direction;
|
||||
|
||||
if (codec_dir & BLE_AUDIO_CODEC_DIR_SOURCE_BIT) {
|
||||
pac_notify(BLE_SVC_AUDIO_PACS_CHR_UUID16_SOURCE_PAC);
|
||||
}
|
||||
|
||||
if (codec_dir & BLE_AUDIO_CODEC_DIR_SINK_BIT) {
|
||||
pac_notify(BLE_SVC_AUDIO_PACS_CHR_UUID16_SINK_PAC);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_pacs_gap_event(struct ble_gap_event *event, void *arg)
|
||||
{
|
||||
struct available_ctx *avail_ctx;
|
||||
|
||||
switch (event->type) {
|
||||
case BLE_GAP_EVENT_CONNECT:
|
||||
if (event->connect.status != 0) {
|
||||
break;
|
||||
}
|
||||
avail_ctx = ble_svc_audio_pacs_find_avail_ctx(BLE_HS_CONN_HANDLE_NONE);
|
||||
avail_ctx->conn_handle = event->connect.conn_handle;
|
||||
break;
|
||||
case BLE_GAP_EVENT_DISCONNECT:
|
||||
avail_ctx = ble_svc_audio_pacs_find_avail_ctx(event->disconnect.conn.conn_handle);
|
||||
if (avail_ctx >= 0) {
|
||||
avail_ctx->conn_handle = BLE_HS_CONN_HANDLE_NONE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ble_svc_audio_pacs_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* Ensure this function only gets called by sysinit. */
|
||||
SYSINIT_ASSERT_ACTIVE();
|
||||
|
||||
rc = ble_gatts_count_cfg(ble_svc_audio_pacs_defs);
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
rc = ble_gatts_add_svcs(ble_svc_audio_pacs_defs);
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
rc = ble_gap_event_listener_register(&ble_pacs_listener,
|
||||
ble_pacs_gap_event, NULL);
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
rc = ble_audio_event_listener_register(&ble_audio_listener, ble_pacs_audio_event, NULL);
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
(void)rc;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
syscfg.defs:
|
||||
BLE_SVC_AUDIO_PACS_SYSINIT_STAGE:
|
||||
description: >
|
||||
Sysinit stage for Published Audio Capabilities Service.
|
||||
value: 303
|
||||
BLE_SVC_AUDIO_PACS_SINK_PAC:
|
||||
description: >
|
||||
Enable Sink PAC characteristic.
|
||||
If disabled, BLE_SVC_AUDIO_PACS_SOURCE_PAC must be enabled.
|
||||
value: 1
|
||||
BLE_SVC_AUDIO_PACS_SINK_PAC_NOTIFY:
|
||||
description: >
|
||||
Enable Sink PAC characteristic notifications.
|
||||
value: 1
|
||||
restrictions: BLE_SVC_AUDIO_PACS_SINK_PAC
|
||||
BLE_SVC_AUDIO_PACS_SINK_AUDIO_LOCATIONS:
|
||||
description: >
|
||||
Enable SOURCE Sink Audio Locations characteristic.
|
||||
value: 1
|
||||
restrictions: BLE_SVC_AUDIO_PACS_SINK_PAC
|
||||
BLE_SVC_AUDIO_PACS_SINK_AUDIO_LOCATIONS_NOTIFY:
|
||||
description: >
|
||||
Enable SOURCE Sink Audio Locations characteristic notifications.
|
||||
value: 1
|
||||
restrictions: BLE_SVC_AUDIO_PACS_SINK_AUDIO_LOCATIONS
|
||||
BLE_SVC_AUDIO_PACS_SOURCE_PAC:
|
||||
description: >
|
||||
Enable Source PAC characteristic.
|
||||
If disabled, BLE_SVC_AUDIO_PACS_SINK_PAC must be enabled.
|
||||
value: 1
|
||||
BLE_SVC_AUDIO_PACS_SOURCE_PAC_NOTIFY:
|
||||
description: >
|
||||
Enable Source PAC characteristic notifications.
|
||||
value: 1
|
||||
restrictions: BLE_SVC_AUDIO_PACS_SOURCE_PAC
|
||||
BLE_SVC_AUDIO_PACS_SOURCE_AUDIO_LOCATIONS:
|
||||
description: >
|
||||
Enable Source Audio Locations characteristic.
|
||||
value: 1
|
||||
restrictions: BLE_SVC_AUDIO_PACS_SOURCE_PAC
|
||||
BLE_SVC_AUDIO_PACS_SOURCE_AUDIO_LOCATIONS_NOTIFY:
|
||||
description: >
|
||||
Enable Source Audio Locations characteristic notifications.
|
||||
value: 1
|
||||
restrictions: BLE_SVC_AUDIO_PACS_SOURCE_AUDIO_LOCATIONS
|
||||
BLE_SVC_AUDIO_PACS_SUP_AUDIO_CTX_NOTIFY:
|
||||
description: >
|
||||
Enable Supported Audio Contexts characteristic notifications.
|
||||
value: 1
|
||||
|
||||
syscfg.restrictions:
|
||||
- 'BLE_SVC_AUDIO_PACS_SINK_PAC == 1 || BLE_SVC_AUDIO_PACS_SOURCE_PAC == 1'
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
|
||||
#if MYNEWT_VAL(BLE_AUDIO_MAX_CODEC_RECORDS)
|
||||
#include "os/os.h"
|
||||
#include "audio/ble_audio.h"
|
||||
#include "audio/ble_audio_codec.h"
|
||||
#include "ble_audio_priv.h"
|
||||
#include "host/ble_hs.h"
|
||||
#include "sysinit/sysinit.h"
|
||||
|
||||
static STAILQ_HEAD(, ble_audio_codec_record) ble_audio_codec_records;
|
||||
static struct os_mempool ble_audio_codec_pool;
|
||||
|
||||
static os_membuf_t ble_audio_svc_pacs_pac_elem_mem[
|
||||
OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_AUDIO_MAX_CODEC_RECORDS),
|
||||
sizeof (struct ble_audio_codec_record))
|
||||
];
|
||||
|
||||
int
|
||||
ble_audio_codec_register(const struct ble_audio_codec_register_params *params,
|
||||
struct ble_audio_codec_record *out_record)
|
||||
{
|
||||
struct ble_audio_event codec_event = {
|
||||
.type = BLE_AUDIO_EVENT_CODEC_REGISTERED
|
||||
};
|
||||
|
||||
struct ble_audio_codec_record *record =
|
||||
os_memblock_get(&ble_audio_codec_pool);
|
||||
if (!record) {
|
||||
return BLE_HS_ENOMEM;
|
||||
}
|
||||
|
||||
record->codec_id = params->codec_id;
|
||||
record->codec_spec_caps_len = params->codec_spec_caps_len;
|
||||
record->codec_spec_caps = params->codec_spec_caps;
|
||||
record->metadata_len = params->metadata_len;
|
||||
record->metadata = params->metadata;
|
||||
record->direction = params->direction;
|
||||
|
||||
if (STAILQ_EMPTY(&ble_audio_codec_records)) {
|
||||
STAILQ_INSERT_HEAD(&ble_audio_codec_records, record, next);
|
||||
} else {
|
||||
STAILQ_INSERT_TAIL(&ble_audio_codec_records, record, next);
|
||||
}
|
||||
|
||||
out_record = record;
|
||||
|
||||
codec_event.codec_registered.record = record;
|
||||
(void)ble_audio_event_listener_call(&codec_event);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ble_audio_codec_unregister(struct ble_audio_codec_record *codec_record)
|
||||
{
|
||||
struct ble_audio_event codec_event = {
|
||||
.type = BLE_AUDIO_EVENT_CODEC_UNREGISTERED
|
||||
};
|
||||
|
||||
STAILQ_REMOVE(&ble_audio_codec_records, codec_record,
|
||||
ble_audio_codec_record, next);
|
||||
|
||||
codec_event.codec_unregistered.record = codec_record;
|
||||
(void)ble_audio_event_listener_call(&codec_event);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ble_audio_codec_foreach(uint8_t flags, ble_audio_codec_foreach_fn *cb, void *arg)
|
||||
{
|
||||
struct ble_audio_codec_record *record;
|
||||
int rc;
|
||||
|
||||
STAILQ_FOREACH(record, &ble_audio_codec_records, next) {
|
||||
if (record->direction & flags) {
|
||||
rc = cb(record, arg);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ble_audio_codec_record *
|
||||
ble_audio_codec_find(struct ble_audio_codec_id codec_id, uint8_t flag)
|
||||
{
|
||||
struct ble_audio_codec_record *record;
|
||||
|
||||
STAILQ_FOREACH(record, &ble_audio_codec_records, next) {
|
||||
if (!memcmp(&record->codec_id, &codec_id,
|
||||
sizeof(struct ble_audio_codec_id)) &&
|
||||
(flag ? (record->direction & flag) : 1)) {
|
||||
return record;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
ble_audio_codec_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
STAILQ_INIT(&ble_audio_codec_records);
|
||||
|
||||
rc = os_mempool_init(&ble_audio_codec_pool,
|
||||
MYNEWT_VAL(BLE_AUDIO_MAX_CODEC_RECORDS),
|
||||
sizeof(struct ble_audio_codec_record),
|
||||
ble_audio_svc_pacs_pac_elem_mem,
|
||||
"ble_audio_codec_pool");
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -17,5 +17,9 @@
|
||||
#
|
||||
|
||||
syscfg.defs:
|
||||
BLE_AUDIO_MAX_CODEC_RECORDS:
|
||||
description: >
|
||||
Maximum number of registered audio codecs.
|
||||
value: 0
|
||||
|
||||
syscfg.logs:
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_AUDIO_CODEC_PRIV_
|
||||
#define H_BLE_AUDIO_CODEC_PRIV_
|
||||
|
||||
int ble_audio_codec_init(void);
|
||||
|
||||
#endif /* H_BLE_AUDIO_CODEC_PRIV_ */
|
||||
@@ -765,6 +765,11 @@ ble_hs_init(void)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_AUDIO_MAX_CODEC_RECORDS)
|
||||
rc = ble_audio_codec_init();
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
#endif
|
||||
|
||||
ble_hs_stop_init();
|
||||
|
||||
ble_mqueue_init(&ble_hs_rx_q, ble_hs_event_rx_data, NULL);
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "ble_att_priv.h"
|
||||
#include "ble_eatt_priv.h"
|
||||
#include "ble_gap_priv.h"
|
||||
#include "ble_audio_codec_priv.h"
|
||||
#include "ble_gatt_priv.h"
|
||||
#include "ble_hs_hci_priv.h"
|
||||
#include "ble_hs_atomic_priv.h"
|
||||
|
||||
@@ -599,6 +599,10 @@
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_AUDIO_MAX_CODEC_RECORDS
|
||||
#define MYNEWT_VAL_BLE_AUDIO_MAX_CODEC_RECORDS (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_EATT_CHAN_NUM
|
||||
#define MYNEWT_VAL_BLE_EATT_CHAN_NUM (0)
|
||||
#endif
|
||||
|
||||
@@ -600,6 +600,10 @@
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_AUDIO_MAX_CODEC_RECORDS
|
||||
#define MYNEWT_VAL_BLE_AUDIO_MAX_CODEC_RECORDS (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_EATT_CHAN_NUM
|
||||
#define MYNEWT_VAL_BLE_EATT_CHAN_NUM (0)
|
||||
#endif
|
||||
|
||||
@@ -599,6 +599,10 @@
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_AUDIO_MAX_CODEC_RECORDS
|
||||
#define MYNEWT_VAL_BLE_AUDIO_MAX_CODEC_RECORDS (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_EATT_CHAN_NUM
|
||||
#define MYNEWT_VAL_BLE_EATT_CHAN_NUM (0)
|
||||
#endif
|
||||
|
||||
@@ -598,6 +598,10 @@
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_AUDIO_MAX_CODEC_RECORDS
|
||||
#define MYNEWT_VAL_BLE_AUDIO_MAX_CODEC_RECORDS (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_EATT_CHAN_NUM
|
||||
#define MYNEWT_VAL_BLE_EATT_CHAN_NUM (0)
|
||||
#endif
|
||||
|
||||
@@ -1515,6 +1515,10 @@
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_AUDIO_MAX_CODEC_RECORDS
|
||||
#define MYNEWT_VAL_BLE_AUDIO_MAX_CODEC_RECORDS (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_EATT_CHAN_NUM
|
||||
#define MYNEWT_VAL_BLE_EATT_CHAN_NUM (0)
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user