MariuszSkamra commented on code in PR #1691:
URL: https://github.com/apache/mynewt-nimble/pull/1691#discussion_r1580576584


##########
nimble/host/audio/services/bass/include/services/bass/ble_audio_svc_bass.h:
##########
@@ -0,0 +1,455 @@
+/**
+ * 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_BASS_
+#define H_BLE_AUDIO_SVC_BASS_
+
+#include <stdint.h>
+#include "audio/ble_audio.h"
+#include "syscfg/syscfg.h"
+
+/**
+ * @file ble_audio_svc_bass.h
+ *
+ * @brief Bluetooth LE Audio BAS Service
+ *
+ * This header file provides the public API for interacting with the BASS 
package.
+ *
+ * @defgroup ble_audio_svc_bass Bluetooth LE Audio BASS package
+ * @ingroup bt_host
+ * @{
+ *
+ * This package implements BASS service. Receiver states can be modified with 
setter functions
+ * or GATT writes to Control Point characteristic. Operations on Control Point 
like Add Source or
+ * Modify Source can be accepted or rejected by application by registering 
accept function callback.
+ * Accessing Control Point characteristic, or Successful modification or 
Receiver State will lead to
+ * emission of one of BLE_SVC_AUDIO_BASS events.
+ *
+ */
+
+/** BLE AUDIO BASS Maximum Subgroup Number */
+#define BLE_SVC_AUDIO_BASS_SUB_NUM_MAX \
+    MYNEWT_VAL(BLE_SVC_AUDIO_BASS_SUB_NUM_MAX)
+
+/** BLE AUDIO BASS characteristic UUID */
+#define BLE_SVC_AUDIO_BASS_UUID16                                        0x184F
+
+/** BLE AUDIO BASS Control Point characteristic UUID */
+#define BLE_SVC_AUDIO_BASS_CHR_UUID16_BASS_CP                            0x2BC7
+
+/** BLE AUDIO BASS Broadcast Receiver State characteristic UUID */
+#define BLE_SVC_AUDIO_BASS_CHR_UUID16_BROADCAST_RECEIVE_STATE            0x2BC8
+
+/** Value of not assigned Source ID of Receiver State */
+#define BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE                     0xFF
+
+/** BLE AUDIO BASS Add Source operation OP code */
+#define BLE_SVC_AUDIO_BASS_OPERATION_ADD_SOURCE                          0x01
+
+/** BLE AUDIO BASS Modify Source operation OP code */
+#define BLE_SVC_AUDIO_BASS_OPERATION_MODIFY_SOURCE                       0x02
+
+/** BLE AUDIO BASS Remove Source operation OP code */
+#define BLE_SVC_AUDIO_BASS_OPERATION_REMOVE_SOURCE                       0x03
+
+/** BLE AUDIO BASS Error: OP Code not supported */
+#define BLE_SVC_AUDIO_BASS_ERR_OPCODE_NOT_SUPPORTED                      0x80
+
+/** BLE AUDIO BASS Error: Invalid Source ID */
+#define BLE_SVC_AUDIO_BASS_ERR_INVALID_SOURCE_ID                         0x81
+
+/** BLE AUDIO BASS Encryption States */
+enum ble_svc_audio_bass_big_enc {
+    /** BLE AUDIO BASS BIG Encryption: Not Encrypted */
+    BLE_SVC_AUDIO_BASS_BIG_ENC_NOT_ENCRYPTED,
+
+    /** BLE AUDIO BASS BIG Encryption: Broadcast Code Required */
+    BLE_SVC_AUDIO_BASS_BIG_ENC_BROADCAST_CODE_REQ,
+
+    /** BLE AUDIO BASS BIG Encryption: Decrypting */
+    BLE_SVC_AUDIO_BASS_BIG_ENC_DECRYPTING,
+
+    /** BLE AUDIO BASS BIG Encryption: Bad Code */
+    BLE_SVC_AUDIO_BASS_BIG_ENC_BAD_CODE
+};
+
+/** BLE AUDIO BASS PA Sync parameters, valid fo Modify Source operation */
+enum ble_svc_audio_bass_pa_sync {
+    /** BLE AUDIO BASS PA Sync: Do not synchronize to PA */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_DO_NOT_SYNC,
+
+    /** BLE AUDIO BASS PA Sync: Synchronize to PA – PAST available */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_SYNC_PAST_AVAILABLE,
+
+    /** BLE AUDIO BASS PA Sync: Synchronize to PA – PAST not available */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_SYNC_PAST_NOT_AVAILABLE,
+
+    /**
+     * BLE AUDIO BASS PA Sync: reserved for future use.
+     * This shall be always last value in this enum
+     */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_RFU
+};
+
+/** BLE AUDIO BASS Broadcast Receiver: PA Sync States */
+enum ble_svc_audio_bass_pa_sync_state {
+    /** BLE AUDIO BASS PA Sync State: Not synchronized to PA */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_NOT_SYNCED,
+
+    /** BLE AUDIO BASS PA Sync State: SyncInfo Request */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_SYNC_INFO_REQ,
+
+    /** BLE AUDIO BASS PA Sync State: Synchronized to PA */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_SYNCED,
+
+    /** BLE AUDIO BASS PA Sync State: Failed to synchronize to PAA */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_SYNCED_FAILED,
+
+    /** BLE AUDIO BASS PA Sync State: No PAST */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_NO_PAST
+};
+
+/** BLE AUDIO BASS Broadcast Receiver State: Subgroup entry */
+struct ble_svc_audio_bass_subgroup {
+    /** BLE AUDIO BASS Subgroup entry: Bis Synchronization State */
+    uint32_t bis_sync_state;
+
+    /** BLE AUDIO BASS Subgroup entry: Metadata length */
+    uint8_t metadata_length;
+
+    /** BLE AUDIO BASS Subgroup entry: Metadata */
+    uint8_t *metadata;
+};
+
+/** BLE AUDIO BASS Broadcast Receiver State */
+struct ble_svc_audio_bass_receiver_state {
+    /** BLE AUDIO BASS Broadcast Receiver State: Source ID */
+    uint8_t source_id;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Source BLE Address */
+    ble_addr_t source_addr;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Source Advertising SID */
+    uint8_t source_adv_sid;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Broadcast ID */
+    uint32_t broadcast_id;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: PA Sync state */
+    enum ble_svc_audio_bass_pa_sync_state pa_sync_state;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: BIG Encryption */
+    enum ble_svc_audio_bass_big_enc big_encryption;
+
+    /**
+     * BLE AUDIO BASS Broadcast Receiver State: Bad Code.
+     * On GATT Read access, this value is ignored if big_encryption
+     * is not set to BLE_SVC_AUDIO_BASS_BIG_ENC_BAD_CODE
+     */
+    uint8_t bad_code[BLE_AUDIO_BROADCAST_CODE_SIZE];
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Number of subgroups */
+    uint8_t num_subgroups;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: subgroup entries */
+    struct ble_svc_audio_bass_subgroup
+        subgroups[BLE_SVC_AUDIO_BASS_SUB_NUM_MAX];
+};
+
+/** BLE AUDIO BASS Broadcast Receiver State add parameters */
+struct ble_svc_audio_bass_receiver_state_add_params {
+    /** BLE AUDIO BASS Broadcast Receiver State: Source BLE Address */
+    ble_addr_t source_addr;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Source Advertising SID */
+    uint8_t source_adv_sid;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Broadcast ID */
+    uint32_t broadcast_id;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: PA Sync state */
+    enum ble_svc_audio_bass_pa_sync_state pa_sync_state;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: BIG Encryption */
+    enum ble_svc_audio_bass_big_enc big_encryption;
+
+    /**
+     * BLE AUDIO BASS Broadcast Receiver State: Bad Code.
+     * On GATT Read access, this value is ignored if big_encryption
+     * is not set to BLE_SVC_AUDIO_BASS_BIG_ENC_BAD_CODE
+     */
+    const uint8_t bad_code[BLE_AUDIO_BROADCAST_CODE_SIZE];

Review Comment:
   I apologize as I was wrong regarding this one. Looks like this one cannot be 
const, because the use won't be able to initialize it.



##########
nimble/host/audio/services/bass/include/services/bass/ble_audio_svc_bass.h:
##########
@@ -0,0 +1,455 @@
+/**
+ * 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_BASS_
+#define H_BLE_AUDIO_SVC_BASS_
+
+#include <stdint.h>
+#include "audio/ble_audio.h"
+#include "syscfg/syscfg.h"
+
+/**
+ * @file ble_audio_svc_bass.h
+ *
+ * @brief Bluetooth LE Audio BAS Service
+ *
+ * This header file provides the public API for interacting with the BASS 
package.
+ *
+ * @defgroup ble_audio_svc_bass Bluetooth LE Audio BASS package
+ * @ingroup bt_host
+ * @{
+ *
+ * This package implements BASS service. Receiver states can be modified with 
setter functions
+ * or GATT writes to Control Point characteristic. Operations on Control Point 
like Add Source or
+ * Modify Source can be accepted or rejected by application by registering 
accept function callback.
+ * Accessing Control Point characteristic, or Successful modification or 
Receiver State will lead to
+ * emission of one of BLE_SVC_AUDIO_BASS events.
+ *
+ */
+
+/** BLE AUDIO BASS Maximum Subgroup Number */
+#define BLE_SVC_AUDIO_BASS_SUB_NUM_MAX \
+    MYNEWT_VAL(BLE_SVC_AUDIO_BASS_SUB_NUM_MAX)
+
+/** BLE AUDIO BASS characteristic UUID */
+#define BLE_SVC_AUDIO_BASS_UUID16                                        0x184F
+
+/** BLE AUDIO BASS Control Point characteristic UUID */
+#define BLE_SVC_AUDIO_BASS_CHR_UUID16_BASS_CP                            0x2BC7
+
+/** BLE AUDIO BASS Broadcast Receiver State characteristic UUID */
+#define BLE_SVC_AUDIO_BASS_CHR_UUID16_BROADCAST_RECEIVE_STATE            0x2BC8
+
+/** Value of not assigned Source ID of Receiver State */
+#define BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE                     0xFF
+
+/** BLE AUDIO BASS Add Source operation OP code */
+#define BLE_SVC_AUDIO_BASS_OPERATION_ADD_SOURCE                          0x01
+
+/** BLE AUDIO BASS Modify Source operation OP code */
+#define BLE_SVC_AUDIO_BASS_OPERATION_MODIFY_SOURCE                       0x02
+
+/** BLE AUDIO BASS Remove Source operation OP code */
+#define BLE_SVC_AUDIO_BASS_OPERATION_REMOVE_SOURCE                       0x03
+
+/** BLE AUDIO BASS Error: OP Code not supported */
+#define BLE_SVC_AUDIO_BASS_ERR_OPCODE_NOT_SUPPORTED                      0x80
+
+/** BLE AUDIO BASS Error: Invalid Source ID */
+#define BLE_SVC_AUDIO_BASS_ERR_INVALID_SOURCE_ID                         0x81
+
+/** BLE AUDIO BASS Encryption States */
+enum ble_svc_audio_bass_big_enc {
+    /** BLE AUDIO BASS BIG Encryption: Not Encrypted */
+    BLE_SVC_AUDIO_BASS_BIG_ENC_NOT_ENCRYPTED,
+
+    /** BLE AUDIO BASS BIG Encryption: Broadcast Code Required */
+    BLE_SVC_AUDIO_BASS_BIG_ENC_BROADCAST_CODE_REQ,
+
+    /** BLE AUDIO BASS BIG Encryption: Decrypting */
+    BLE_SVC_AUDIO_BASS_BIG_ENC_DECRYPTING,
+
+    /** BLE AUDIO BASS BIG Encryption: Bad Code */
+    BLE_SVC_AUDIO_BASS_BIG_ENC_BAD_CODE
+};
+
+/** BLE AUDIO BASS PA Sync parameters, valid fo Modify Source operation */
+enum ble_svc_audio_bass_pa_sync {
+    /** BLE AUDIO BASS PA Sync: Do not synchronize to PA */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_DO_NOT_SYNC,
+
+    /** BLE AUDIO BASS PA Sync: Synchronize to PA – PAST available */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_SYNC_PAST_AVAILABLE,
+
+    /** BLE AUDIO BASS PA Sync: Synchronize to PA – PAST not available */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_SYNC_PAST_NOT_AVAILABLE,
+
+    /**
+     * BLE AUDIO BASS PA Sync: reserved for future use.
+     * This shall be always last value in this enum
+     */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_RFU
+};
+
+/** BLE AUDIO BASS Broadcast Receiver: PA Sync States */
+enum ble_svc_audio_bass_pa_sync_state {
+    /** BLE AUDIO BASS PA Sync State: Not synchronized to PA */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_NOT_SYNCED,
+
+    /** BLE AUDIO BASS PA Sync State: SyncInfo Request */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_SYNC_INFO_REQ,
+
+    /** BLE AUDIO BASS PA Sync State: Synchronized to PA */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_SYNCED,
+
+    /** BLE AUDIO BASS PA Sync State: Failed to synchronize to PAA */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_SYNCED_FAILED,
+
+    /** BLE AUDIO BASS PA Sync State: No PAST */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_NO_PAST
+};
+
+/** BLE AUDIO BASS Broadcast Receiver State: Subgroup entry */
+struct ble_svc_audio_bass_subgroup {
+    /** BLE AUDIO BASS Subgroup entry: Bis Synchronization State */
+    uint32_t bis_sync_state;
+
+    /** BLE AUDIO BASS Subgroup entry: Metadata length */
+    uint8_t metadata_length;
+
+    /** BLE AUDIO BASS Subgroup entry: Metadata */
+    uint8_t *metadata;
+};
+
+/** BLE AUDIO BASS Broadcast Receiver State */
+struct ble_svc_audio_bass_receiver_state {
+    /** BLE AUDIO BASS Broadcast Receiver State: Source ID */
+    uint8_t source_id;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Source BLE Address */
+    ble_addr_t source_addr;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Source Advertising SID */
+    uint8_t source_adv_sid;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Broadcast ID */
+    uint32_t broadcast_id;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: PA Sync state */
+    enum ble_svc_audio_bass_pa_sync_state pa_sync_state;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: BIG Encryption */
+    enum ble_svc_audio_bass_big_enc big_encryption;
+
+    /**
+     * BLE AUDIO BASS Broadcast Receiver State: Bad Code.
+     * On GATT Read access, this value is ignored if big_encryption
+     * is not set to BLE_SVC_AUDIO_BASS_BIG_ENC_BAD_CODE
+     */
+    uint8_t bad_code[BLE_AUDIO_BROADCAST_CODE_SIZE];
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Number of subgroups */
+    uint8_t num_subgroups;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: subgroup entries */
+    struct ble_svc_audio_bass_subgroup
+        subgroups[BLE_SVC_AUDIO_BASS_SUB_NUM_MAX];
+};
+
+/** BLE AUDIO BASS Broadcast Receiver State add parameters */
+struct ble_svc_audio_bass_receiver_state_add_params {
+    /** BLE AUDIO BASS Broadcast Receiver State: Source BLE Address */
+    ble_addr_t source_addr;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Source Advertising SID */
+    uint8_t source_adv_sid;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Broadcast ID */
+    uint32_t broadcast_id;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: PA Sync state */
+    enum ble_svc_audio_bass_pa_sync_state pa_sync_state;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: BIG Encryption */
+    enum ble_svc_audio_bass_big_enc big_encryption;
+
+    /**
+     * BLE AUDIO BASS Broadcast Receiver State: Bad Code.
+     * On GATT Read access, this value is ignored if big_encryption
+     * is not set to BLE_SVC_AUDIO_BASS_BIG_ENC_BAD_CODE
+     */
+    const uint8_t bad_code[BLE_AUDIO_BROADCAST_CODE_SIZE];
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Number of subgroups */
+    uint8_t num_subgroups;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: subgroup entries */
+    const struct ble_svc_audio_bass_subgroup
+        subgroups[BLE_SVC_AUDIO_BASS_SUB_NUM_MAX];

Review Comment:
   ditto



##########
nimble/host/audio/services/bass/include/services/bass/ble_audio_svc_bass.h:
##########
@@ -0,0 +1,455 @@
+/**
+ * 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_BASS_
+#define H_BLE_AUDIO_SVC_BASS_
+
+#include <stdint.h>
+#include "audio/ble_audio.h"
+#include "syscfg/syscfg.h"
+
+/**
+ * @file ble_audio_svc_bass.h
+ *
+ * @brief Bluetooth LE Audio BAS Service
+ *
+ * This header file provides the public API for interacting with the BASS 
package.
+ *
+ * @defgroup ble_audio_svc_bass Bluetooth LE Audio BASS package
+ * @ingroup bt_host
+ * @{
+ *
+ * This package implements BASS service. Receiver states can be modified with 
setter functions
+ * or GATT writes to Control Point characteristic. Operations on Control Point 
like Add Source or
+ * Modify Source can be accepted or rejected by application by registering 
accept function callback.
+ * Accessing Control Point characteristic, or Successful modification or 
Receiver State will lead to
+ * emission of one of BLE_SVC_AUDIO_BASS events.
+ *
+ */
+
+/** BLE AUDIO BASS Maximum Subgroup Number */
+#define BLE_SVC_AUDIO_BASS_SUB_NUM_MAX \
+    MYNEWT_VAL(BLE_SVC_AUDIO_BASS_SUB_NUM_MAX)
+
+/** BLE AUDIO BASS characteristic UUID */
+#define BLE_SVC_AUDIO_BASS_UUID16                                        0x184F
+
+/** BLE AUDIO BASS Control Point characteristic UUID */
+#define BLE_SVC_AUDIO_BASS_CHR_UUID16_BASS_CP                            0x2BC7
+
+/** BLE AUDIO BASS Broadcast Receiver State characteristic UUID */
+#define BLE_SVC_AUDIO_BASS_CHR_UUID16_BROADCAST_RECEIVE_STATE            0x2BC8
+
+/** Value of not assigned Source ID of Receiver State */
+#define BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE                     0xFF

Review Comment:
   It looks like this one is private API, thus can be moved to `.c`



##########
nimble/host/audio/services/bass/src/ble_audio_svc_bass.c:
##########
@@ -0,0 +1,854 @@
+/*
+ * 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 "host/ble_hs.h"
+#include "host/ble_gatt.h"
+#include "../../host/src/ble_gatt_priv.h"
+#include "../../host/src/ble_att_priv.h"
+#include "services/bass/ble_audio_svc_bass.h"
+#include "../../../src/ble_audio_priv.h"
+
+#define BLE_SVC_AUDIO_BASS_CHR_LEN_UNLIMITED                    (-1)
+#define BLE_SVC_AUDIO_BASS_RECEIVE_BIS_SYNC_STATE_ANY           0xFFFFFFFF
+
+ble_uuid_t * bass_receive_state_uuid =
+    BLE_UUID16_DECLARE(BLE_SVC_AUDIO_BASS_CHR_UUID16_BROADCAST_RECEIVE_STATE);
+ble_uuid_t * bass_cp_uuid =
+    BLE_UUID16_DECLARE(BLE_SVC_AUDIO_BASS_CHR_UUID16_BASS_CP);
+
+enum ble_svc_audio_bass_ctrl_point_op_code {
+    BLE_AUDIO_SVC_BASS_REMOTE_SCAN_STOPPED,
+    BLE_AUDIO_SVC_BASS_REMOTE_SCAN_STARTED,
+    BLE_AUDIO_SVC_BASS_ADD_SOURCE,
+    BLE_AUDIO_SVC_BASS_MODIFY_SOURCE,
+    BLE_AUDIO_SVC_BASS_SET_BROADCAST_CODE,
+    BLE_AUDIO_SVC_BASS_REMOVE_SOURCE
+};
+
+typedef int ble_svc_audio_bass_ctrl_point_handler_cb(uint8_t *data,
+                                                     uint16_t data_len,
+                                                     uint16_t conn_handle);
+
+static struct ble_svc_audio_bass_ctrl_point_ev {
+    ble_svc_audio_bass_accept_fn *ctrl_point_ev_fn;
+    void *arg;
+} accept_fn;
+
+struct ble_svc_audio_bass_rcv_state_entry {
+    uint8_t source_id;
+    uint16_t chr_val;
+    struct ble_svc_audio_bass_receiver_state state;
+};
+
+static struct ble_svc_audio_bass_rcv_state_entry
+    receiver_states[MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX)] = {
+    [0 ... MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX) - 1] = {
+        .source_id = BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE
+    }
+};
+
+static struct os_mempool ble_audio_svc_bass_metadata_pool;
+static os_membuf_t ble_audio_svc_bass_metadata_mem[
+    OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX) *
+                    BLE_SVC_AUDIO_BASS_SUB_NUM_MAX,
+                    MYNEWT_VAL(BLE_SVC_AUDIO_BASS_METADATA_MAX_SZ))];
+
+static int
+ble_svc_audio_bass_remote_scan_stopped(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle);
+static int
+ble_svc_audio_bass_remote_scan_started(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle);
+static int
+ble_svc_audio_bass_add_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle);
+static int
+ble_svc_audio_bass_modify_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle);
+static int
+ble_svc_audio_bass_set_broadcast_code(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle);
+static int
+ble_svc_audio_bass_remove_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle);
+
+static int
+ble_svc_audio_bass_ctrl_point_write_access(struct ble_gatt_access_ctxt *ctxt, 
uint16_t conn_handle);
+static int
+ble_svc_audio_bass_rcv_state_read_access(struct ble_gatt_access_ctxt *ctxt, 
void *arg);
+
+static struct ble_svc_audio_bass_ctrl_point_handler {
+    uint8_t op_code;
+    uint8_t length_min;
+    uint8_t length_max;
+    ble_svc_audio_bass_ctrl_point_handler_cb *handler_cb;
+} ble_svc_audio_bass_ctrl_point_handlers[] = {
+    {
+        .op_code = BLE_AUDIO_SVC_BASS_REMOTE_SCAN_STOPPED,
+        .length_min = 0,
+        .length_max = 0,
+        .handler_cb = ble_svc_audio_bass_remote_scan_stopped
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_REMOTE_SCAN_STARTED,
+        .length_min = 0,
+        .length_max = 0,
+        .handler_cb = ble_svc_audio_bass_remote_scan_started
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_ADD_SOURCE,
+        .length_min = 15,
+        .length_max = BLE_SVC_AUDIO_BASS_CHR_LEN_UNLIMITED,
+        .handler_cb = ble_svc_audio_bass_add_source
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_MODIFY_SOURCE,
+        .length_min = 5,
+        .length_max = BLE_SVC_AUDIO_BASS_CHR_LEN_UNLIMITED,
+        .handler_cb = ble_svc_audio_bass_modify_source
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_SET_BROADCAST_CODE,
+        .length_min = 17,
+        .length_max = 17,
+        .handler_cb = ble_svc_audio_bass_set_broadcast_code
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_REMOVE_SOURCE,
+        .length_min = 1,
+        .length_max = 1,
+        .handler_cb = ble_svc_audio_bass_remove_source
+    }
+};
+
+static struct ble_gatt_chr_def 
ble_svc_audio_bass_chrs[MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX) + 2];
+
+static const struct ble_gatt_svc_def 
ble_svc_audio_bass_defs[MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX) + 2] = 
{
+    { /*** Service: Published Audio Capabilities Service (bass) */
+        .type = BLE_GATT_SVC_TYPE_PRIMARY,
+        .uuid = BLE_UUID16_DECLARE(BLE_SVC_AUDIO_BASS_UUID16),
+        .characteristics = ble_svc_audio_bass_chrs,
+    },
+    {
+        0, /* No more services. */
+    },
+};
+
+static uint8_t free_source_id = 0;
+
+static int
+ble_svc_audio_bass_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_BASS_CHR_UUID16_BASS_CP:
+        if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
+            rc = ble_svc_audio_bass_ctrl_point_write_access(ctxt, conn_handle);
+        } else {
+            assert(0);
+        }
+        return rc;
+    case BLE_SVC_AUDIO_BASS_CHR_UUID16_BROADCAST_RECEIVE_STATE:
+        if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
+            rc = ble_svc_audio_bass_rcv_state_read_access(ctxt, arg);
+        } else {
+            assert(0);
+        }
+        return rc;
+    default:
+        assert(0);
+    }
+}
+
+static uint8_t
+ble_svc_audio_bass_get_new_source_id(void)
+{
+    /** Wrap around after all Source IDs were used */
+    if (free_source_id == BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE) {
+        free_source_id = 0;
+    }
+
+    return free_source_id++;
+}

Review Comment:
   How do you know the source ID is not in use? You should iterate the receive 
states to check



##########
nimble/host/audio/services/bass/include/services/bass/ble_audio_svc_bass.h:
##########
@@ -0,0 +1,455 @@
+/**
+ * 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_BASS_
+#define H_BLE_AUDIO_SVC_BASS_
+
+#include <stdint.h>
+#include "audio/ble_audio.h"
+#include "syscfg/syscfg.h"
+
+/**
+ * @file ble_audio_svc_bass.h
+ *
+ * @brief Bluetooth LE Audio BAS Service
+ *
+ * This header file provides the public API for interacting with the BASS 
package.
+ *
+ * @defgroup ble_audio_svc_bass Bluetooth LE Audio BASS package
+ * @ingroup bt_host
+ * @{
+ *
+ * This package implements BASS service. Receiver states can be modified with 
setter functions
+ * or GATT writes to Control Point characteristic. Operations on Control Point 
like Add Source or
+ * Modify Source can be accepted or rejected by application by registering 
accept function callback.
+ * Accessing Control Point characteristic, or Successful modification or 
Receiver State will lead to
+ * emission of one of BLE_SVC_AUDIO_BASS events.
+ *
+ */
+
+/** BLE AUDIO BASS Maximum Subgroup Number */
+#define BLE_SVC_AUDIO_BASS_SUB_NUM_MAX \
+    MYNEWT_VAL(BLE_SVC_AUDIO_BASS_SUB_NUM_MAX)
+
+/** BLE AUDIO BASS characteristic UUID */
+#define BLE_SVC_AUDIO_BASS_UUID16                                        0x184F
+
+/** BLE AUDIO BASS Control Point characteristic UUID */
+#define BLE_SVC_AUDIO_BASS_CHR_UUID16_BASS_CP                            0x2BC7
+
+/** BLE AUDIO BASS Broadcast Receiver State characteristic UUID */
+#define BLE_SVC_AUDIO_BASS_CHR_UUID16_BROADCAST_RECEIVE_STATE            0x2BC8
+
+/** Value of not assigned Source ID of Receiver State */
+#define BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE                     0xFF
+
+/** BLE AUDIO BASS Add Source operation OP code */
+#define BLE_SVC_AUDIO_BASS_OPERATION_ADD_SOURCE                          0x01
+
+/** BLE AUDIO BASS Modify Source operation OP code */
+#define BLE_SVC_AUDIO_BASS_OPERATION_MODIFY_SOURCE                       0x02
+
+/** BLE AUDIO BASS Remove Source operation OP code */
+#define BLE_SVC_AUDIO_BASS_OPERATION_REMOVE_SOURCE                       0x03
+
+/** BLE AUDIO BASS Error: OP Code not supported */
+#define BLE_SVC_AUDIO_BASS_ERR_OPCODE_NOT_SUPPORTED                      0x80
+
+/** BLE AUDIO BASS Error: Invalid Source ID */
+#define BLE_SVC_AUDIO_BASS_ERR_INVALID_SOURCE_ID                         0x81
+
+/** BLE AUDIO BASS Encryption States */
+enum ble_svc_audio_bass_big_enc {
+    /** BLE AUDIO BASS BIG Encryption: Not Encrypted */
+    BLE_SVC_AUDIO_BASS_BIG_ENC_NOT_ENCRYPTED,
+
+    /** BLE AUDIO BASS BIG Encryption: Broadcast Code Required */
+    BLE_SVC_AUDIO_BASS_BIG_ENC_BROADCAST_CODE_REQ,
+
+    /** BLE AUDIO BASS BIG Encryption: Decrypting */
+    BLE_SVC_AUDIO_BASS_BIG_ENC_DECRYPTING,
+
+    /** BLE AUDIO BASS BIG Encryption: Bad Code */
+    BLE_SVC_AUDIO_BASS_BIG_ENC_BAD_CODE
+};
+
+/** BLE AUDIO BASS PA Sync parameters, valid fo Modify Source operation */
+enum ble_svc_audio_bass_pa_sync {
+    /** BLE AUDIO BASS PA Sync: Do not synchronize to PA */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_DO_NOT_SYNC,
+
+    /** BLE AUDIO BASS PA Sync: Synchronize to PA – PAST available */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_SYNC_PAST_AVAILABLE,
+
+    /** BLE AUDIO BASS PA Sync: Synchronize to PA – PAST not available */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_SYNC_PAST_NOT_AVAILABLE,
+
+    /**
+     * BLE AUDIO BASS PA Sync: reserved for future use.
+     * This shall be always last value in this enum
+     */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_RFU
+};
+
+/** BLE AUDIO BASS Broadcast Receiver: PA Sync States */
+enum ble_svc_audio_bass_pa_sync_state {
+    /** BLE AUDIO BASS PA Sync State: Not synchronized to PA */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_NOT_SYNCED,
+
+    /** BLE AUDIO BASS PA Sync State: SyncInfo Request */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_SYNC_INFO_REQ,
+
+    /** BLE AUDIO BASS PA Sync State: Synchronized to PA */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_SYNCED,
+
+    /** BLE AUDIO BASS PA Sync State: Failed to synchronize to PAA */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_SYNCED_FAILED,
+
+    /** BLE AUDIO BASS PA Sync State: No PAST */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_NO_PAST
+};
+
+/** BLE AUDIO BASS Broadcast Receiver State: Subgroup entry */
+struct ble_svc_audio_bass_subgroup {
+    /** BLE AUDIO BASS Subgroup entry: Bis Synchronization State */
+    uint32_t bis_sync_state;
+
+    /** BLE AUDIO BASS Subgroup entry: Metadata length */
+    uint8_t metadata_length;
+
+    /** BLE AUDIO BASS Subgroup entry: Metadata */
+    uint8_t *metadata;
+};
+
+/** BLE AUDIO BASS Broadcast Receiver State */
+struct ble_svc_audio_bass_receiver_state {
+    /** BLE AUDIO BASS Broadcast Receiver State: Source ID */
+    uint8_t source_id;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Source BLE Address */
+    ble_addr_t source_addr;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Source Advertising SID */
+    uint8_t source_adv_sid;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Broadcast ID */
+    uint32_t broadcast_id;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: PA Sync state */
+    enum ble_svc_audio_bass_pa_sync_state pa_sync_state;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: BIG Encryption */
+    enum ble_svc_audio_bass_big_enc big_encryption;
+
+    /**
+     * BLE AUDIO BASS Broadcast Receiver State: Bad Code.
+     * On GATT Read access, this value is ignored if big_encryption
+     * is not set to BLE_SVC_AUDIO_BASS_BIG_ENC_BAD_CODE
+     */
+    uint8_t bad_code[BLE_AUDIO_BROADCAST_CODE_SIZE];
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Number of subgroups */
+    uint8_t num_subgroups;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: subgroup entries */
+    struct ble_svc_audio_bass_subgroup
+        subgroups[BLE_SVC_AUDIO_BASS_SUB_NUM_MAX];
+};
+
+/** BLE AUDIO BASS Broadcast Receiver State add parameters */
+struct ble_svc_audio_bass_receiver_state_add_params {
+    /** BLE AUDIO BASS Broadcast Receiver State: Source BLE Address */
+    ble_addr_t source_addr;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Source Advertising SID */
+    uint8_t source_adv_sid;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Broadcast ID */
+    uint32_t broadcast_id;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: PA Sync state */
+    enum ble_svc_audio_bass_pa_sync_state pa_sync_state;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: BIG Encryption */
+    enum ble_svc_audio_bass_big_enc big_encryption;
+
+    /**
+     * BLE AUDIO BASS Broadcast Receiver State: Bad Code.
+     * On GATT Read access, this value is ignored if big_encryption
+     * is not set to BLE_SVC_AUDIO_BASS_BIG_ENC_BAD_CODE
+     */
+    const uint8_t bad_code[BLE_AUDIO_BROADCAST_CODE_SIZE];
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Number of subgroups */
+    uint8_t num_subgroups;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: subgroup entries */
+    const struct ble_svc_audio_bass_subgroup
+        subgroups[BLE_SVC_AUDIO_BASS_SUB_NUM_MAX];
+};
+
+/** Parameters used for updating Metadata in Receiver State. */
+struct ble_svc_audio_bass_metadata_params {
+    /** Subgroup index */
+    uint8_t subgroup_idx;
+
+    /** Metadata length */
+    uint8_t metadata_length;
+
+    /** Metadata */
+    const uint8_t *metadata;
+};
+
+/** Parameters used for updating Receiver State. */
+struct ble_svc_audio_bass_update_params {
+    /** PA Sync state */
+    enum ble_svc_audio_bass_pa_sync_state pa_sync_state;
+
+    /** BIG encryption state */
+    enum ble_svc_audio_bass_big_enc big_encryption;
+
+    /** Incorrect Bad Broadcast Code. Valid for 
BLE_SVC_AUDIO_BASS_BIG_ENC_BAD_CODE */
+    const uint8_t *bad_code;
+
+    /** Subgroup index of BIS Sync State to be updated */
+    uint8_t subgroup_idx;
+
+    /** BIS Sync State */
+    uint32_t bis_sync_state;

Review Comment:
   I'm certain the user should provide here all subgroups.
   It's because the rest of the parameters are common for all subgroups 
(pa_sync_state etc), so the function is not for updating a state of specific 
subgroup, but rather for updating total receive state
   
   e.g.
   ```
       /** Number of subgroups */
       uint8_t num_subgroups;
   
       /** Scan Delegator Receive State: subgroup entries */
       struct ble_svc_audio_bass_subgroup_params subgroups[
               MYNEWT_VAL(BLE_SVC_AUDIO_BASS_SUB_NUM_MAX)];
   ```
   
   where 
   ```
   /** Subgroup parameters used for updating Receiver State */
   struct ble_svc_audio_bass_subgroup_params {
       /** BIS Synchronization */
       uint32_t bis_sync;
   
       /** Metadata length */
       uint8_t metadata_length;
   
       /** Metadata */
       const uint8_t *metadata;
   };
   ```



##########
nimble/host/audio/services/bass/include/services/bass/ble_audio_svc_bass.h:
##########
@@ -0,0 +1,455 @@
+/**
+ * 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_BASS_
+#define H_BLE_AUDIO_SVC_BASS_
+
+#include <stdint.h>
+#include "audio/ble_audio.h"
+#include "syscfg/syscfg.h"
+
+/**
+ * @file ble_audio_svc_bass.h
+ *
+ * @brief Bluetooth LE Audio BAS Service
+ *
+ * This header file provides the public API for interacting with the BASS 
package.
+ *
+ * @defgroup ble_audio_svc_bass Bluetooth LE Audio BASS package
+ * @ingroup bt_host
+ * @{
+ *
+ * This package implements BASS service. Receiver states can be modified with 
setter functions
+ * or GATT writes to Control Point characteristic. Operations on Control Point 
like Add Source or
+ * Modify Source can be accepted or rejected by application by registering 
accept function callback.
+ * Accessing Control Point characteristic, or Successful modification or 
Receiver State will lead to
+ * emission of one of BLE_SVC_AUDIO_BASS events.
+ *
+ */
+
+/** BLE AUDIO BASS Maximum Subgroup Number */
+#define BLE_SVC_AUDIO_BASS_SUB_NUM_MAX \
+    MYNEWT_VAL(BLE_SVC_AUDIO_BASS_SUB_NUM_MAX)
+
+/** BLE AUDIO BASS characteristic UUID */
+#define BLE_SVC_AUDIO_BASS_UUID16                                        0x184F
+
+/** BLE AUDIO BASS Control Point characteristic UUID */
+#define BLE_SVC_AUDIO_BASS_CHR_UUID16_BASS_CP                            0x2BC7
+
+/** BLE AUDIO BASS Broadcast Receiver State characteristic UUID */
+#define BLE_SVC_AUDIO_BASS_CHR_UUID16_BROADCAST_RECEIVE_STATE            0x2BC8
+
+/** Value of not assigned Source ID of Receiver State */
+#define BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE                     0xFF
+
+/** BLE AUDIO BASS Add Source operation OP code */
+#define BLE_SVC_AUDIO_BASS_OPERATION_ADD_SOURCE                          0x01
+
+/** BLE AUDIO BASS Modify Source operation OP code */
+#define BLE_SVC_AUDIO_BASS_OPERATION_MODIFY_SOURCE                       0x02
+
+/** BLE AUDIO BASS Remove Source operation OP code */
+#define BLE_SVC_AUDIO_BASS_OPERATION_REMOVE_SOURCE                       0x03
+
+/** BLE AUDIO BASS Error: OP Code not supported */
+#define BLE_SVC_AUDIO_BASS_ERR_OPCODE_NOT_SUPPORTED                      0x80
+
+/** BLE AUDIO BASS Error: Invalid Source ID */
+#define BLE_SVC_AUDIO_BASS_ERR_INVALID_SOURCE_ID                         0x81
+
+/** BLE AUDIO BASS Encryption States */
+enum ble_svc_audio_bass_big_enc {
+    /** BLE AUDIO BASS BIG Encryption: Not Encrypted */
+    BLE_SVC_AUDIO_BASS_BIG_ENC_NOT_ENCRYPTED,
+
+    /** BLE AUDIO BASS BIG Encryption: Broadcast Code Required */
+    BLE_SVC_AUDIO_BASS_BIG_ENC_BROADCAST_CODE_REQ,
+
+    /** BLE AUDIO BASS BIG Encryption: Decrypting */
+    BLE_SVC_AUDIO_BASS_BIG_ENC_DECRYPTING,
+
+    /** BLE AUDIO BASS BIG Encryption: Bad Code */
+    BLE_SVC_AUDIO_BASS_BIG_ENC_BAD_CODE
+};
+
+/** BLE AUDIO BASS PA Sync parameters, valid fo Modify Source operation */
+enum ble_svc_audio_bass_pa_sync {
+    /** BLE AUDIO BASS PA Sync: Do not synchronize to PA */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_DO_NOT_SYNC,
+
+    /** BLE AUDIO BASS PA Sync: Synchronize to PA – PAST available */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_SYNC_PAST_AVAILABLE,
+
+    /** BLE AUDIO BASS PA Sync: Synchronize to PA – PAST not available */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_SYNC_PAST_NOT_AVAILABLE,
+
+    /**
+     * BLE AUDIO BASS PA Sync: reserved for future use.
+     * This shall be always last value in this enum
+     */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_RFU
+};
+
+/** BLE AUDIO BASS Broadcast Receiver: PA Sync States */
+enum ble_svc_audio_bass_pa_sync_state {
+    /** BLE AUDIO BASS PA Sync State: Not synchronized to PA */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_NOT_SYNCED,
+
+    /** BLE AUDIO BASS PA Sync State: SyncInfo Request */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_SYNC_INFO_REQ,
+
+    /** BLE AUDIO BASS PA Sync State: Synchronized to PA */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_SYNCED,
+
+    /** BLE AUDIO BASS PA Sync State: Failed to synchronize to PAA */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_SYNCED_FAILED,
+
+    /** BLE AUDIO BASS PA Sync State: No PAST */
+    BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_NO_PAST
+};
+
+/** BLE AUDIO BASS Broadcast Receiver State: Subgroup entry */
+struct ble_svc_audio_bass_subgroup {
+    /** BLE AUDIO BASS Subgroup entry: Bis Synchronization State */
+    uint32_t bis_sync_state;
+
+    /** BLE AUDIO BASS Subgroup entry: Metadata length */
+    uint8_t metadata_length;
+
+    /** BLE AUDIO BASS Subgroup entry: Metadata */
+    uint8_t *metadata;
+};
+
+/** BLE AUDIO BASS Broadcast Receiver State */
+struct ble_svc_audio_bass_receiver_state {
+    /** BLE AUDIO BASS Broadcast Receiver State: Source ID */
+    uint8_t source_id;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Source BLE Address */
+    ble_addr_t source_addr;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Source Advertising SID */
+    uint8_t source_adv_sid;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Broadcast ID */
+    uint32_t broadcast_id;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: PA Sync state */
+    enum ble_svc_audio_bass_pa_sync_state pa_sync_state;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: BIG Encryption */
+    enum ble_svc_audio_bass_big_enc big_encryption;
+
+    /**
+     * BLE AUDIO BASS Broadcast Receiver State: Bad Code.
+     * On GATT Read access, this value is ignored if big_encryption
+     * is not set to BLE_SVC_AUDIO_BASS_BIG_ENC_BAD_CODE
+     */
+    uint8_t bad_code[BLE_AUDIO_BROADCAST_CODE_SIZE];
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Number of subgroups */
+    uint8_t num_subgroups;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: subgroup entries */
+    struct ble_svc_audio_bass_subgroup
+        subgroups[BLE_SVC_AUDIO_BASS_SUB_NUM_MAX];
+};
+
+/** BLE AUDIO BASS Broadcast Receiver State add parameters */
+struct ble_svc_audio_bass_receiver_state_add_params {
+    /** BLE AUDIO BASS Broadcast Receiver State: Source BLE Address */
+    ble_addr_t source_addr;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Source Advertising SID */
+    uint8_t source_adv_sid;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Broadcast ID */
+    uint32_t broadcast_id;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: PA Sync state */
+    enum ble_svc_audio_bass_pa_sync_state pa_sync_state;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: BIG Encryption */
+    enum ble_svc_audio_bass_big_enc big_encryption;
+
+    /**
+     * BLE AUDIO BASS Broadcast Receiver State: Bad Code.
+     * On GATT Read access, this value is ignored if big_encryption
+     * is not set to BLE_SVC_AUDIO_BASS_BIG_ENC_BAD_CODE
+     */
+    const uint8_t bad_code[BLE_AUDIO_BROADCAST_CODE_SIZE];
+
+    /** BLE AUDIO BASS Broadcast Receiver State: Number of subgroups */
+    uint8_t num_subgroups;
+
+    /** BLE AUDIO BASS Broadcast Receiver State: subgroup entries */
+    const struct ble_svc_audio_bass_subgroup
+        subgroups[BLE_SVC_AUDIO_BASS_SUB_NUM_MAX];
+};
+
+/** Parameters used for updating Metadata in Receiver State. */
+struct ble_svc_audio_bass_metadata_params {
+    /** Subgroup index */
+    uint8_t subgroup_idx;
+
+    /** Metadata length */
+    uint8_t metadata_length;
+
+    /** Metadata */
+    const uint8_t *metadata;
+};
+
+/** Parameters used for updating Receiver State. */
+struct ble_svc_audio_bass_update_params {
+    /** PA Sync state */
+    enum ble_svc_audio_bass_pa_sync_state pa_sync_state;
+
+    /** BIG encryption state */
+    enum ble_svc_audio_bass_big_enc big_encryption;
+
+    /** Incorrect Bad Broadcast Code. Valid for 
BLE_SVC_AUDIO_BASS_BIG_ENC_BAD_CODE */
+    const uint8_t *bad_code;
+
+    /** Subgroup index of BIS Sync State to be updated */
+    uint8_t subgroup_idx;
+
+    /** BIS Sync State */
+    uint32_t bis_sync_state;
+};
+
+/**
+ *  Structure describing operation attempted by write on
+ *  BASS Control Point characteristic
+ */
+struct ble_svc_audio_bass_operation {
+    /**
+     * Indicates the type of BASS operation that occurred.  This is one of the
+     * ble_svc_audio_bass_operation codes.
+     */
+    uint8_t op;
+
+    /** Connection handle for which the operation was performed */
+    uint16_t conn_handle;
+
+    /**
+     * A discriminated union containing additional details concerning the BASS 
Control Point
+     * event.  The 'type' field indicates which member of the union is valid.
+     */
+    union {
+        /**
+         * Represents Add Source operation.  Valid for the following event
+         * types:
+         *     o BLE_SVC_AUDIO_BASS_OPERATION_ADD_SOURCE
+         * Application can accept or reject Add Source operation. If no 
application callback is set
+         * and free Receive State characteristic exists operation is 
automatically accepted.
+         * If application callback exists and returns 0 operation is accepted.
+         * Otherwise, operation is rejected.
+         * If operation is accepted by application, it may select receiver 
state to be filled.
+         * If application doesnt select characteristic, BASS Server falls back
+         * to searching free one. If none is found, operation is rejected.

Review Comment:
   If the stack behaves as described here, it's not compliant with BASS 3.1.1.4 
Add Source operation:
   ```
   If the server accepts the Add Source operation, the server shall select an 
empty Broadcast Receive State
   characteristic to update, or if the server has no empty Broadcast Receive 
State characteristics, the server
   shall first delete all fields in a selected Broadcast Receive State 
characteristic.
   ```
   
   I think you need to update description only, as the `out_source_id_swap` 
pointer is valid only when there is not space to allocate another receive state 
(so it's as per spec).



##########
nimble/host/audio/services/bass/src/ble_audio_svc_bass.c:
##########
@@ -0,0 +1,854 @@
+/*
+ * 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 "host/ble_hs.h"
+#include "host/ble_gatt.h"
+#include "../../host/src/ble_gatt_priv.h"
+#include "../../host/src/ble_att_priv.h"
+#include "services/bass/ble_audio_svc_bass.h"
+#include "../../../src/ble_audio_priv.h"
+
+#define BLE_SVC_AUDIO_BASS_CHR_LEN_UNLIMITED                    (-1)
+#define BLE_SVC_AUDIO_BASS_RECEIVE_BIS_SYNC_STATE_ANY           0xFFFFFFFF
+
+ble_uuid_t * bass_receive_state_uuid =
+    BLE_UUID16_DECLARE(BLE_SVC_AUDIO_BASS_CHR_UUID16_BROADCAST_RECEIVE_STATE);
+ble_uuid_t * bass_cp_uuid =
+    BLE_UUID16_DECLARE(BLE_SVC_AUDIO_BASS_CHR_UUID16_BASS_CP);

Review Comment:
   Can be const



##########
nimble/host/audio/services/bass/src/ble_audio_svc_bass.c:
##########
@@ -0,0 +1,854 @@
+/*
+ * 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 "host/ble_hs.h"
+#include "host/ble_gatt.h"
+#include "../../host/src/ble_gatt_priv.h"
+#include "../../host/src/ble_att_priv.h"
+#include "services/bass/ble_audio_svc_bass.h"
+#include "../../../src/ble_audio_priv.h"
+
+#define BLE_SVC_AUDIO_BASS_CHR_LEN_UNLIMITED                    (-1)
+#define BLE_SVC_AUDIO_BASS_RECEIVE_BIS_SYNC_STATE_ANY           0xFFFFFFFF
+
+ble_uuid_t * bass_receive_state_uuid =
+    BLE_UUID16_DECLARE(BLE_SVC_AUDIO_BASS_CHR_UUID16_BROADCAST_RECEIVE_STATE);
+ble_uuid_t * bass_cp_uuid =
+    BLE_UUID16_DECLARE(BLE_SVC_AUDIO_BASS_CHR_UUID16_BASS_CP);
+
+enum ble_svc_audio_bass_ctrl_point_op_code {
+    BLE_AUDIO_SVC_BASS_REMOTE_SCAN_STOPPED,
+    BLE_AUDIO_SVC_BASS_REMOTE_SCAN_STARTED,
+    BLE_AUDIO_SVC_BASS_ADD_SOURCE,
+    BLE_AUDIO_SVC_BASS_MODIFY_SOURCE,
+    BLE_AUDIO_SVC_BASS_SET_BROADCAST_CODE,
+    BLE_AUDIO_SVC_BASS_REMOVE_SOURCE
+};
+
+typedef int ble_svc_audio_bass_ctrl_point_handler_cb(uint8_t *data,
+                                                     uint16_t data_len,
+                                                     uint16_t conn_handle);
+
+static struct ble_svc_audio_bass_ctrl_point_ev {
+    ble_svc_audio_bass_accept_fn *ctrl_point_ev_fn;
+    void *arg;
+} accept_fn;
+
+struct ble_svc_audio_bass_rcv_state_entry {
+    uint8_t source_id;
+    uint16_t chr_val;
+    struct ble_svc_audio_bass_receiver_state state;
+};
+
+static struct ble_svc_audio_bass_rcv_state_entry
+    receiver_states[MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX)] = {
+    [0 ... MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX) - 1] = {
+        .source_id = BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE
+    }
+};
+
+static struct os_mempool ble_audio_svc_bass_metadata_pool;
+static os_membuf_t ble_audio_svc_bass_metadata_mem[
+    OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX) *
+                    BLE_SVC_AUDIO_BASS_SUB_NUM_MAX,
+                    MYNEWT_VAL(BLE_SVC_AUDIO_BASS_METADATA_MAX_SZ))];
+
+static int
+ble_svc_audio_bass_remote_scan_stopped(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle);
+static int
+ble_svc_audio_bass_remote_scan_started(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle);
+static int
+ble_svc_audio_bass_add_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle);
+static int
+ble_svc_audio_bass_modify_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle);
+static int
+ble_svc_audio_bass_set_broadcast_code(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle);
+static int
+ble_svc_audio_bass_remove_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle);
+
+static int
+ble_svc_audio_bass_ctrl_point_write_access(struct ble_gatt_access_ctxt *ctxt, 
uint16_t conn_handle);
+static int
+ble_svc_audio_bass_rcv_state_read_access(struct ble_gatt_access_ctxt *ctxt, 
void *arg);
+
+static struct ble_svc_audio_bass_ctrl_point_handler {
+    uint8_t op_code;
+    uint8_t length_min;
+    uint8_t length_max;
+    ble_svc_audio_bass_ctrl_point_handler_cb *handler_cb;
+} ble_svc_audio_bass_ctrl_point_handlers[] = {
+    {
+        .op_code = BLE_AUDIO_SVC_BASS_REMOTE_SCAN_STOPPED,
+        .length_min = 0,
+        .length_max = 0,
+        .handler_cb = ble_svc_audio_bass_remote_scan_stopped
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_REMOTE_SCAN_STARTED,
+        .length_min = 0,
+        .length_max = 0,
+        .handler_cb = ble_svc_audio_bass_remote_scan_started
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_ADD_SOURCE,
+        .length_min = 15,
+        .length_max = BLE_SVC_AUDIO_BASS_CHR_LEN_UNLIMITED,
+        .handler_cb = ble_svc_audio_bass_add_source
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_MODIFY_SOURCE,
+        .length_min = 5,
+        .length_max = BLE_SVC_AUDIO_BASS_CHR_LEN_UNLIMITED,
+        .handler_cb = ble_svc_audio_bass_modify_source
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_SET_BROADCAST_CODE,
+        .length_min = 17,
+        .length_max = 17,
+        .handler_cb = ble_svc_audio_bass_set_broadcast_code
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_REMOVE_SOURCE,
+        .length_min = 1,
+        .length_max = 1,
+        .handler_cb = ble_svc_audio_bass_remove_source
+    }
+};
+
+static struct ble_gatt_chr_def 
ble_svc_audio_bass_chrs[MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX) + 2];
+
+static const struct ble_gatt_svc_def 
ble_svc_audio_bass_defs[MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX) + 2] = 
{
+    { /*** Service: Published Audio Capabilities Service (bass) */
+        .type = BLE_GATT_SVC_TYPE_PRIMARY,
+        .uuid = BLE_UUID16_DECLARE(BLE_SVC_AUDIO_BASS_UUID16),
+        .characteristics = ble_svc_audio_bass_chrs,
+    },
+    {
+        0, /* No more services. */
+    },
+};
+
+static uint8_t free_source_id = 0;
+
+static int
+ble_svc_audio_bass_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_BASS_CHR_UUID16_BASS_CP:
+        if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
+            rc = ble_svc_audio_bass_ctrl_point_write_access(ctxt, conn_handle);
+        } else {
+            assert(0);
+        }
+        return rc;
+    case BLE_SVC_AUDIO_BASS_CHR_UUID16_BROADCAST_RECEIVE_STATE:
+        if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
+            rc = ble_svc_audio_bass_rcv_state_read_access(ctxt, arg);
+        } else {
+            assert(0);
+        }
+        return rc;
+    default:
+        assert(0);
+    }
+}
+
+static uint8_t
+ble_svc_audio_bass_get_new_source_id(void)
+{
+    /** Wrap around after all Source IDs were used */
+    if (free_source_id == BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE) {
+        free_source_id = 0;
+    }
+
+    return free_source_id++;
+}
+
+static int
+ble_svc_audio_bass_receive_state_notify(struct 
ble_svc_audio_bass_rcv_state_entry *state)
+{
+    int i;
+
+    for (i = 0; i < sizeof(ble_svc_audio_bass_chrs); i++) {
+        if (ble_svc_audio_bass_chrs[i].arg == state) {
+            ble_gatts_chr_updated(*ble_svc_audio_bass_chrs[i].val_handle);
+            return 0;
+        }
+    }
+
+    return BLE_HS_ENOENT;
+}
+
+static int
+ble_svc_audio_bass_receive_state_find_by_source_id(struct 
ble_svc_audio_bass_rcv_state_entry **out_state,
+                                                   uint8_t source_id)
+{
+    int i;
+
+    for (i = 0; i < sizeof(receiver_states); i++) {
+        if (receiver_states[i].source_id == source_id) {
+            *out_state = &receiver_states[i];
+            return 0;
+        }
+    }
+
+    return BLE_HS_ENOMEM;
+}
+
+int
+ble_svc_audio_bass_receive_state_find_free(struct 
ble_svc_audio_bass_rcv_state_entry **out_state)
+{
+    int i;
+
+    for (i = 0; i < sizeof(receiver_states); i++) {
+        if (receiver_states[i].source_id == 
BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE) {
+            *out_state = &receiver_states[i];
+            return 0;
+        }
+    }
+
+    return BLE_HS_ENOMEM;
+}
+
+static void
+ble_svc_audio_bass_receive_state_free(struct 
ble_svc_audio_bass_rcv_state_entry *state)
+{
+    state->source_id = BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE;
+}
+
+static int
+ble_svc_audio_bass_remote_scan_stopped(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle)
+{
+    struct ble_audio_event ev = {
+        .type = BLE_AUDIO_EVENT_BASS_REMOTE_SCAN_STOPPED
+    };
+
+    ev.remote_scan_stopped.conn_handle = conn_handle;
+    ble_audio_event_listener_call(&ev);
+
+    return 0;
+}
+
+static int
+ble_svc_audio_bass_remote_scan_started(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle)
+{
+    struct ble_audio_event ev = {
+        .type = BLE_AUDIO_EVENT_BASS_REMOTE_SCAN_STARTED
+    };
+
+    ev.remote_scan_started.conn_handle = conn_handle;
+    ble_audio_event_listener_call(&ev);
+
+    return 0;
+}
+
+static int
+ble_svc_audio_bass_add_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle)
+{
+    struct ble_audio_event ev = {
+        .type = BLE_AUDIO_EVENT_BASS_OPERATION_STATUS,
+        .bass_operation_status = {
+            .op = BLE_AUDIO_EVENT_BASS_SOURCE_ADDED,
+            .status = 0
+        }
+    };
+    struct ble_svc_audio_bass_operation operation;
+    struct ble_svc_audio_bass_rcv_state_entry *rcv_state = NULL;
+    uint8_t offset = 0;
+    uint8_t *metadata_ptr;
+    uint8_t source_id_new;
+    uint8_t source_id_to_remove = BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE;
+    int rc = 0;
+    int i;
+
+    memset(&operation, 0, sizeof(operation));
+
+    operation.op = BLE_SVC_AUDIO_BASS_OPERATION_ADD_SOURCE;
+    operation.conn_handle = conn_handle;
+
+    operation.add_source.adv_addr.type = data[offset++];
+    memcpy(operation.add_source.adv_addr.val, &data[offset], 6);
+    offset += 6;
+    operation.add_source.adv_sid = data[offset++];
+    operation.add_source.broadcast_id = get_le24(&data[offset]);
+    offset += 3;
+    operation.add_source.pa_sync = data[offset++];
+    if (operation.add_source.pa_sync >= BLE_SVC_AUDIO_BASS_PA_SYNC_RFU) {
+        rc = BLE_HS_EINVAL;
+        ev.bass_operation_status.status = BLE_HS_EINVAL;
+        goto done;
+    }
+
+    operation.add_source.pa_interval = get_le16(&data[offset]);
+    offset += 2;
+    operation.add_source.num_subgroups = data[offset++];
+
+    /**
+     * Previous data was checked for it's size in 
`ble_svc_audio_bass_ctrl_point_write_access`.
+     * As bis_sync_state array may be of variable length, we need to check it 
separately
+     */
+    data_len -= offset;
+    for (i = 0; i < operation.add_source.num_subgroups; i++) {
+        if (data_len < sizeof(uint32_t)) {
+            rc = BLE_ATT_ERR_WRITE_REQ_REJECTED;
+            ev.bass_operation_status.status = BLE_HS_EREJECT;
+            goto done;
+        }
+        operation.add_source.subgroups[i].bis_sync_state = 
get_le32(&data[offset]);
+        offset += 4;
+        operation.add_source.subgroups[i].metadata_length = data[offset++];
+        data_len -= 5;
+        if (data_len < operation.add_source.subgroups[i].metadata_length) {
+            rc = BLE_ATT_ERR_WRITE_REQ_REJECTED;
+            ev.bass_operation_status.status = BLE_HS_EREJECT;
+            goto done;
+        }
+        operation.add_source.subgroups[i].metadata = &data[offset];
+        offset += operation.add_source.subgroups[i].metadata_length;
+        data_len -= operation.add_source.subgroups[i].metadata_length;
+    }
+
+    source_id_new = ble_svc_audio_bass_get_new_source_id();
+    operation.add_source.source_id = source_id_new;
+
+    ble_svc_audio_bass_receive_state_find_free(&rcv_state);
+    if (rcv_state == NULL) {
+        operation.add_source.out_source_id_to_swap = &source_id_to_remove;
+    } else {
+        operation.add_source.out_source_id_to_swap = NULL;
+        rcv_state->source_id = operation.add_source.source_id;
+    }
+
+    if (accept_fn.ctrl_point_ev_fn) {
+        rc = accept_fn.ctrl_point_ev_fn(&operation, accept_fn.arg);
+        if (rc != 0) {
+            if (rcv_state != NULL) {
+                ble_svc_audio_bass_receive_state_free(rcv_state);
+            }
+            rc = BLE_ATT_ERR_WRITE_REQ_REJECTED;
+            ev.bass_operation_status.status = BLE_HS_EREJECT;
+            goto done;
+        }
+    }
+
+    if (rcv_state == NULL) {
+        if (source_id_to_remove != 
BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE) {
+            ble_svc_audio_bass_receive_state_find_by_source_id(&rcv_state, 
source_id_to_remove);
+            if (rcv_state == NULL) {
+                rc = BLE_HS_EAPP;
+                ev.bass_operation_status.status = BLE_HS_EAPP;
+                goto done;
+            }
+
+            /* Swap Source ID */
+            rcv_state->source_id = operation.add_source.source_id;
+        } else {
+            rc = BLE_HS_ENOMEM;
+            ev.bass_operation_status.status = BLE_HS_ENOMEM;
+            goto done;
+        }
+    } else {
+        rcv_state->source_id = operation.add_source.source_id;
+    }
+
+    ev.bass_operation_status.source_id = rcv_state->source_id;
+    rcv_state->state.source_addr.type = operation.add_source.adv_addr.type;
+    memcpy(&rcv_state->state.source_addr.type, 
operation.add_source.adv_addr.val, 6);
+    rcv_state->state.source_adv_sid = operation.add_source.adv_sid;
+    rcv_state->state.broadcast_id = operation.add_source.broadcast_id;
+
+    for (i = 0; i < operation.add_source.num_subgroups; i++) {
+        metadata_ptr = os_memblock_get(&ble_audio_svc_bass_metadata_pool);
+        if (!metadata_ptr) {
+            rc = BLE_HS_ENOMEM;
+            ev.bass_operation_status.status = BLE_HS_ENOMEM;
+            goto done;
+        }
+        rcv_state->state.subgroups[i].metadata_length = 
operation.add_source.subgroups[i].metadata_length;
+        memcpy(metadata_ptr, operation.add_source.subgroups[i].metadata,
+               min(operation.add_source.subgroups[i].metadata_length,
+                   MYNEWT_VAL(BLE_SVC_AUDIO_BASS_METADATA_MAX_SZ)));
+
+        rcv_state->state.subgroups[i].metadata = metadata_ptr;
+    }
+
+done:
+    if (!rc) {
+        rc = ble_svc_audio_bass_receive_state_notify(rcv_state);
+        ev.bass_operation_status.status = rc;
+        goto done;
+    }
+
+    ble_audio_event_listener_call(&ev);
+
+    return rc;
+}
+
+static int
+check_bis_sync(uint16_t num_subgroups, const uint32_t *bis_sync_list)
+{
+    uint32_t bis_sync_mask = 0;
+    int i;
+    int j;
+
+    for (i = 0; i < num_subgroups; i++) {
+        if (bis_sync_list[i] != 0xFFFFFFFF) {
+            for (j = 0; j < num_subgroups; j++) {
+                if (bis_sync_list[i] & bis_sync_mask) {
+                    return BLE_HS_EINVAL;
+                }
+
+                bis_sync_mask |= bis_sync_list[i];
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int
+ble_svc_audio_bass_modify_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle)
+{
+    struct ble_svc_audio_bass_operation operation;
+    struct ble_svc_audio_bass_rcv_state_entry *rcv_state = NULL;
+    struct ble_audio_event ev = {
+        .type = BLE_AUDIO_EVENT_BASS_OPERATION_STATUS,
+        .bass_operation_status = {
+            .op = BLE_AUDIO_EVENT_BASS_SOURCE_MODIFIED,
+            .status = 0
+        }
+    };
+    uint8_t offset = 0;
+    int rc = 0;
+    int i;
+
+    memset(&operation, 0, sizeof(operation));
+
+    operation.op = BLE_SVC_AUDIO_BASS_OPERATION_MODIFY_SOURCE;
+    operation.conn_handle = conn_handle;
+
+    operation.modify_source.source_id = data[offset++];
+
+    ble_svc_audio_bass_receive_state_find_by_source_id(&rcv_state,
+                                                       
operation.modify_source.source_id);
+    if (rcv_state == NULL) {
+        rc = BLE_SVC_AUDIO_BASS_ERR_INVALID_SOURCE_ID;
+        ev.bass_operation_status.status = BLE_HS_EINVAL;
+        goto done;
+    }
+
+    operation.modify_source.pa_sync = data[offset++];
+    if (operation.modify_source.pa_sync >= BLE_SVC_AUDIO_BASS_PA_SYNC_RFU) {
+        return BLE_HS_EINVAL;
+    }
+
+    operation.modify_source.pa_interval = get_le16(&data[offset]);
+    offset += 2;
+    operation.modify_source.num_subgroups = get_le16(&data[offset]);
+    offset += 2;
+
+    data_len -= offset;
+    if (data_len < operation.modify_source.num_subgroups * sizeof(uint32_t)) {
+        rc = BLE_ATT_ERR_WRITE_REQ_REJECTED;
+        ev.bass_operation_status.status = BLE_HS_EREJECT;
+        goto done;
+    }
+
+    for (i = 0; i < operation.modify_source.num_subgroups; i++) {
+        operation.modify_source.bis_sync[i] = get_le32(&data[offset]);
+        offset += 4;
+    }
+
+    if (check_bis_sync(operation.modify_source.num_subgroups,
+                       operation.modify_source.bis_sync)) {
+        return 0;
+    }
+
+    if (accept_fn.ctrl_point_ev_fn) {
+        rc = accept_fn.ctrl_point_ev_fn(&operation, accept_fn.arg);
+        if (rc != 0) {
+            rc = BLE_ATT_ERR_WRITE_REQ_REJECTED;
+            ev.bass_operation_status.status = BLE_HS_EREJECT;
+            goto done;
+        }
+    }
+
+    ev.bass_operation_status.source_id = operation.modify_source.source_id;
+
+done:
+    if (!rc) {
+        rc = ble_svc_audio_bass_receive_state_notify(rcv_state);
+        ev.bass_operation_status.status = rc;
+        goto done;
+    }
+
+    ble_audio_event_listener_call(&ev);
+
+    return rc;
+}
+
+static int
+ble_svc_audio_bass_set_broadcast_code(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle)
+{
+    struct ble_svc_audio_bass_rcv_state_entry *rcv_state = NULL;
+    struct ble_audio_event ev = {
+        .type = BLE_AUDIO_EVENT_BASS_BROADCAST_CODE_SET,
+    };
+
+    ev.bass_set_broadcast_code.source_id = data[0];
+
+    ble_svc_audio_bass_receive_state_find_by_source_id(&rcv_state,
+                                                       
ev.bass_set_broadcast_code.source_id);
+    if (rcv_state == NULL) {
+        return BLE_SVC_AUDIO_BASS_ERR_INVALID_SOURCE_ID;
+    }
+
+    memcpy(ev.bass_set_broadcast_code.broadcast_code, &data[1], 
BLE_AUDIO_BROADCAST_CODE_SIZE);
+
+    ble_audio_event_listener_call(&ev);
+
+    return 0;
+}
+
+static int
+ble_svc_audio_bass_remove_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle)
+{
+    struct ble_audio_event ev = {
+        .type = BLE_AUDIO_EVENT_BASS_BROADCAST_CODE_SET,
+        .bass_operation_status = {
+            .op = BLE_AUDIO_EVENT_BASS_SOURCE_REMOVED,
+            .status = 0
+        }
+    };
+    struct ble_svc_audio_bass_rcv_state_entry *rcv_state = NULL;
+    struct ble_svc_audio_bass_operation operation;
+    int rc = 0;
+    int i;
+
+    ev.bass_set_broadcast_code.source_id = data[0];
+
+    ble_svc_audio_bass_receive_state_find_by_source_id(&rcv_state,
+                                                       
ev.bass_operation_status.source_id);
+    if (rcv_state == NULL) {
+        rc = BLE_SVC_AUDIO_BASS_ERR_INVALID_SOURCE_ID;
+        ev.bass_operation_status.status = BLE_HS_ENOENT;
+        goto done;
+    }
+
+    operation.remove_source.source_id = ev.bass_operation_status.source_id;
+    operation.conn_handle = conn_handle;
+    if (accept_fn.ctrl_point_ev_fn) {
+        rc = accept_fn.ctrl_point_ev_fn(&operation, accept_fn.arg);
+        if (rc != 0) {
+            rc = BLE_HS_EREJECT;
+            ev.bass_operation_status.status = BLE_HS_EREJECT;
+            goto done;
+        }
+    }
+
+    for (i = 0; i < rcv_state->state.num_subgroups; i++) {
+        os_memblock_put(&ble_audio_svc_bass_metadata_pool, 
rcv_state->state.subgroups[i].metadata);
+    }
+
+    memset(rcv_state, 0, sizeof(*rcv_state));
+    rcv_state->source_id = BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE;
+
+done:
+    if (!rc) {
+        rc = ble_svc_audio_bass_receive_state_notify(rcv_state);
+        ev.bass_operation_status.status = rc;
+        goto done;
+    }
+
+    ble_audio_event_listener_call(&ev);
+
+    return rc;
+}
+
+static struct ble_svc_audio_bass_ctrl_point_handler *
+ble_svc_audio_bass_find_handler(uint8_t opcode)
+{
+    int i;
+
+    for (i = 0; i < sizeof(ble_svc_audio_bass_ctrl_point_handlers); i++) {
+        if (ble_svc_audio_bass_ctrl_point_handlers[i].op_code == opcode) {
+            return &ble_svc_audio_bass_ctrl_point_handlers[i];
+        }
+    }
+
+    return NULL;
+}
+
+static int
+ble_svc_audio_bass_ctrl_point_write_access(struct ble_gatt_access_ctxt *ctxt, 
uint16_t conn_handle)
+{
+    struct ble_svc_audio_bass_ctrl_point_handler *handler;
+
+    uint8_t opcode = ctxt->om->om_data[0];
+
+    handler = ble_svc_audio_bass_find_handler(opcode);
+
+    if (!handler) {
+        return BLE_SVC_AUDIO_BASS_ERR_OPCODE_NOT_SUPPORTED;
+    }
+
+    if (ctxt->om->om_len - 1 < handler->length_min &&
+        handler->length_max >= 0 ?
+        ctxt->om->om_len > handler->length_max : 0) {
+        return BLE_ATT_ERR_WRITE_REQ_REJECTED;
+    }
+
+    return handler->handler_cb(&ctxt->om->om_data[1], ctxt->om->om_len - 1, 
conn_handle);
+}
+
+static int
+ble_svc_audio_bass_rcv_state_read_access(struct ble_gatt_access_ctxt *ctxt, 
void *arg)
+{
+    struct ble_svc_audio_bass_rcv_state_entry *state = arg;
+    uint8_t *buf;
+    int i;
+
+    /* Nothing set, return empty buffer */
+    if (state->source_id == BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE) {
+        return 0;
+    }
+
+    os_mbuf_append(ctxt->om, &state->source_id, 1);
+    os_mbuf_append(ctxt->om, &state->state.source_addr.type, 1);
+    os_mbuf_append(ctxt->om, &state->state.source_addr.val, 6);
+    os_mbuf_append(ctxt->om, &state->state.source_adv_sid, 1);
+    buf = os_mbuf_extend(ctxt->om, 3);
+    if (buf == NULL) {
+        return BLE_ATT_ERR_INSUFFICIENT_RES;
+    }
+
+    put_le24(buf, state->state.broadcast_id);
+    os_mbuf_append(ctxt->om, &state->state.pa_sync_state, 1);
+    os_mbuf_append(ctxt->om, &state->state.big_encryption, 1);
+
+    if (state->state.big_encryption == BLE_SVC_AUDIO_BASS_BIG_ENC_BAD_CODE) {
+        os_mbuf_append(ctxt->om, &state->state.bad_code, 
BLE_AUDIO_BROADCAST_CODE_SIZE);
+    }
+
+    os_mbuf_append(ctxt->om, &state->state.num_subgroups, 1);
+
+    for (i = 0; i < state->state.num_subgroups; i++) {
+        buf = os_mbuf_extend(ctxt->om, 4);
+        if (buf == NULL) {
+            return BLE_ATT_ERR_INSUFFICIENT_RES;
+        }
+
+        put_le32(buf, state->state.subgroups[i].bis_sync_state);
+        os_mbuf_append(ctxt->om, &state->state.subgroups[i].metadata_length, 
1);
+        os_mbuf_append(ctxt->om, state->state.subgroups[i].metadata,
+                       state->state.subgroups[i].metadata_length);
+    }
+
+    return 0;
+}
+
+int
+ble_svc_audio_bass_accept_fn_set(ble_svc_audio_bass_accept_fn *fn, void *arg)
+{
+    if (accept_fn.ctrl_point_ev_fn) {
+        return BLE_HS_EALREADY;
+    }
+
+    accept_fn.ctrl_point_ev_fn = fn;
+    accept_fn.arg = arg;
+    return 0;
+}
+
+int
+ble_svc_audio_bass_receive_state_add(const struct 
ble_svc_audio_bass_receiver_state_add_params *params,
+                                     uint8_t *source_id)
+{
+    struct ble_svc_audio_bass_rcv_state_entry *rcv_state;
+    int i;
+    int rc;
+
+    rc = ble_svc_audio_bass_receive_state_find_free(&rcv_state);
+    if (rc) {
+        return rc;
+    }
+
+    rcv_state->source_id = ble_svc_audio_bass_get_new_source_id();
+    rcv_state->state.source_addr = params->source_addr;
+    rcv_state->state.source_adv_sid = params->source_adv_sid;
+    rcv_state->state.broadcast_id = params->broadcast_id;
+    rcv_state->state.pa_sync_state = params->pa_sync_state;
+    rcv_state->state.big_encryption = params->big_encryption;
+    memcpy(&rcv_state->state.bad_code, params->bad_code, 
BLE_AUDIO_BROADCAST_CODE_SIZE);

Review Comment:
   ```
       if (rcv_state->state.big_encryption == 
BLE_SVC_AUDIO_BASS_BIG_ENC_BAD_CODE) {
           memcpy(&rcv_state->state.bad_code, params->bad_code, 
sizeof(rcv_state->state.bad_code));
       }
   ```



##########
nimble/host/audio/services/bass/src/ble_audio_svc_bass.c:
##########
@@ -0,0 +1,854 @@
+/*
+ * 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 "host/ble_hs.h"
+#include "host/ble_gatt.h"
+#include "../../host/src/ble_gatt_priv.h"
+#include "../../host/src/ble_att_priv.h"
+#include "services/bass/ble_audio_svc_bass.h"
+#include "../../../src/ble_audio_priv.h"
+
+#define BLE_SVC_AUDIO_BASS_CHR_LEN_UNLIMITED                    (-1)
+#define BLE_SVC_AUDIO_BASS_RECEIVE_BIS_SYNC_STATE_ANY           0xFFFFFFFF
+
+ble_uuid_t * bass_receive_state_uuid =
+    BLE_UUID16_DECLARE(BLE_SVC_AUDIO_BASS_CHR_UUID16_BROADCAST_RECEIVE_STATE);
+ble_uuid_t * bass_cp_uuid =
+    BLE_UUID16_DECLARE(BLE_SVC_AUDIO_BASS_CHR_UUID16_BASS_CP);
+
+enum ble_svc_audio_bass_ctrl_point_op_code {
+    BLE_AUDIO_SVC_BASS_REMOTE_SCAN_STOPPED,
+    BLE_AUDIO_SVC_BASS_REMOTE_SCAN_STARTED,
+    BLE_AUDIO_SVC_BASS_ADD_SOURCE,
+    BLE_AUDIO_SVC_BASS_MODIFY_SOURCE,
+    BLE_AUDIO_SVC_BASS_SET_BROADCAST_CODE,
+    BLE_AUDIO_SVC_BASS_REMOVE_SOURCE
+};
+
+typedef int ble_svc_audio_bass_ctrl_point_handler_cb(uint8_t *data,
+                                                     uint16_t data_len,
+                                                     uint16_t conn_handle);
+
+static struct ble_svc_audio_bass_ctrl_point_ev {
+    ble_svc_audio_bass_accept_fn *ctrl_point_ev_fn;
+    void *arg;
+} accept_fn;
+
+struct ble_svc_audio_bass_rcv_state_entry {
+    uint8_t source_id;
+    uint16_t chr_val;
+    struct ble_svc_audio_bass_receiver_state state;
+};
+
+static struct ble_svc_audio_bass_rcv_state_entry
+    receiver_states[MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX)] = {
+    [0 ... MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX) - 1] = {
+        .source_id = BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE
+    }
+};
+
+static struct os_mempool ble_audio_svc_bass_metadata_pool;
+static os_membuf_t ble_audio_svc_bass_metadata_mem[
+    OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX) *
+                    BLE_SVC_AUDIO_BASS_SUB_NUM_MAX,
+                    MYNEWT_VAL(BLE_SVC_AUDIO_BASS_METADATA_MAX_SZ))];
+
+static int
+ble_svc_audio_bass_remote_scan_stopped(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle);
+static int
+ble_svc_audio_bass_remote_scan_started(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle);
+static int
+ble_svc_audio_bass_add_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle);
+static int
+ble_svc_audio_bass_modify_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle);
+static int
+ble_svc_audio_bass_set_broadcast_code(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle);
+static int
+ble_svc_audio_bass_remove_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle);
+
+static int
+ble_svc_audio_bass_ctrl_point_write_access(struct ble_gatt_access_ctxt *ctxt, 
uint16_t conn_handle);
+static int
+ble_svc_audio_bass_rcv_state_read_access(struct ble_gatt_access_ctxt *ctxt, 
void *arg);
+
+static struct ble_svc_audio_bass_ctrl_point_handler {
+    uint8_t op_code;
+    uint8_t length_min;
+    uint8_t length_max;
+    ble_svc_audio_bass_ctrl_point_handler_cb *handler_cb;
+} ble_svc_audio_bass_ctrl_point_handlers[] = {
+    {
+        .op_code = BLE_AUDIO_SVC_BASS_REMOTE_SCAN_STOPPED,
+        .length_min = 0,
+        .length_max = 0,
+        .handler_cb = ble_svc_audio_bass_remote_scan_stopped
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_REMOTE_SCAN_STARTED,
+        .length_min = 0,
+        .length_max = 0,
+        .handler_cb = ble_svc_audio_bass_remote_scan_started
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_ADD_SOURCE,
+        .length_min = 15,
+        .length_max = BLE_SVC_AUDIO_BASS_CHR_LEN_UNLIMITED,
+        .handler_cb = ble_svc_audio_bass_add_source
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_MODIFY_SOURCE,
+        .length_min = 5,
+        .length_max = BLE_SVC_AUDIO_BASS_CHR_LEN_UNLIMITED,
+        .handler_cb = ble_svc_audio_bass_modify_source
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_SET_BROADCAST_CODE,
+        .length_min = 17,
+        .length_max = 17,
+        .handler_cb = ble_svc_audio_bass_set_broadcast_code
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_REMOVE_SOURCE,
+        .length_min = 1,
+        .length_max = 1,
+        .handler_cb = ble_svc_audio_bass_remove_source
+    }
+};
+
+static struct ble_gatt_chr_def 
ble_svc_audio_bass_chrs[MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX) + 2];
+
+static const struct ble_gatt_svc_def 
ble_svc_audio_bass_defs[MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX) + 2] = 
{
+    { /*** Service: Published Audio Capabilities Service (bass) */
+        .type = BLE_GATT_SVC_TYPE_PRIMARY,
+        .uuid = BLE_UUID16_DECLARE(BLE_SVC_AUDIO_BASS_UUID16),
+        .characteristics = ble_svc_audio_bass_chrs,
+    },
+    {
+        0, /* No more services. */
+    },
+};
+
+static uint8_t free_source_id = 0;
+
+static int
+ble_svc_audio_bass_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_BASS_CHR_UUID16_BASS_CP:
+        if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
+            rc = ble_svc_audio_bass_ctrl_point_write_access(ctxt, conn_handle);
+        } else {
+            assert(0);
+        }
+        return rc;
+    case BLE_SVC_AUDIO_BASS_CHR_UUID16_BROADCAST_RECEIVE_STATE:
+        if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
+            rc = ble_svc_audio_bass_rcv_state_read_access(ctxt, arg);
+        } else {
+            assert(0);
+        }
+        return rc;
+    default:
+        assert(0);
+    }
+}
+
+static uint8_t
+ble_svc_audio_bass_get_new_source_id(void)
+{
+    /** Wrap around after all Source IDs were used */
+    if (free_source_id == BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE) {
+        free_source_id = 0;
+    }
+
+    return free_source_id++;
+}
+
+static int
+ble_svc_audio_bass_receive_state_notify(struct 
ble_svc_audio_bass_rcv_state_entry *state)
+{
+    int i;
+
+    for (i = 0; i < sizeof(ble_svc_audio_bass_chrs); i++) {
+        if (ble_svc_audio_bass_chrs[i].arg == state) {
+            ble_gatts_chr_updated(*ble_svc_audio_bass_chrs[i].val_handle);
+            return 0;
+        }
+    }
+
+    return BLE_HS_ENOENT;
+}
+
+static int
+ble_svc_audio_bass_receive_state_find_by_source_id(struct 
ble_svc_audio_bass_rcv_state_entry **out_state,
+                                                   uint8_t source_id)
+{
+    int i;
+
+    for (i = 0; i < sizeof(receiver_states); i++) {
+        if (receiver_states[i].source_id == source_id) {
+            *out_state = &receiver_states[i];
+            return 0;
+        }
+    }
+
+    return BLE_HS_ENOMEM;
+}
+
+int
+ble_svc_audio_bass_receive_state_find_free(struct 
ble_svc_audio_bass_rcv_state_entry **out_state)
+{
+    int i;
+
+    for (i = 0; i < sizeof(receiver_states); i++) {
+        if (receiver_states[i].source_id == 
BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE) {
+            *out_state = &receiver_states[i];
+            return 0;
+        }
+    }
+
+    return BLE_HS_ENOMEM;
+}
+
+static void
+ble_svc_audio_bass_receive_state_free(struct 
ble_svc_audio_bass_rcv_state_entry *state)
+{
+    state->source_id = BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE;
+}
+
+static int
+ble_svc_audio_bass_remote_scan_stopped(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle)
+{
+    struct ble_audio_event ev = {
+        .type = BLE_AUDIO_EVENT_BASS_REMOTE_SCAN_STOPPED
+    };
+
+    ev.remote_scan_stopped.conn_handle = conn_handle;
+    ble_audio_event_listener_call(&ev);
+
+    return 0;
+}
+
+static int
+ble_svc_audio_bass_remote_scan_started(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle)
+{
+    struct ble_audio_event ev = {
+        .type = BLE_AUDIO_EVENT_BASS_REMOTE_SCAN_STARTED
+    };
+
+    ev.remote_scan_started.conn_handle = conn_handle;
+    ble_audio_event_listener_call(&ev);
+
+    return 0;
+}
+
+static int
+ble_svc_audio_bass_add_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle)
+{
+    struct ble_audio_event ev = {
+        .type = BLE_AUDIO_EVENT_BASS_OPERATION_STATUS,
+        .bass_operation_status = {
+            .op = BLE_AUDIO_EVENT_BASS_SOURCE_ADDED,
+            .status = 0
+        }
+    };
+    struct ble_svc_audio_bass_operation operation;
+    struct ble_svc_audio_bass_rcv_state_entry *rcv_state = NULL;
+    uint8_t offset = 0;
+    uint8_t *metadata_ptr;
+    uint8_t source_id_new;
+    uint8_t source_id_to_remove = BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE;
+    int rc = 0;
+    int i;
+
+    memset(&operation, 0, sizeof(operation));
+
+    operation.op = BLE_SVC_AUDIO_BASS_OPERATION_ADD_SOURCE;
+    operation.conn_handle = conn_handle;
+
+    operation.add_source.adv_addr.type = data[offset++];
+    memcpy(operation.add_source.adv_addr.val, &data[offset], 6);
+    offset += 6;
+    operation.add_source.adv_sid = data[offset++];
+    operation.add_source.broadcast_id = get_le24(&data[offset]);
+    offset += 3;
+    operation.add_source.pa_sync = data[offset++];
+    if (operation.add_source.pa_sync >= BLE_SVC_AUDIO_BASS_PA_SYNC_RFU) {
+        rc = BLE_HS_EINVAL;
+        ev.bass_operation_status.status = BLE_HS_EINVAL;
+        goto done;
+    }
+
+    operation.add_source.pa_interval = get_le16(&data[offset]);
+    offset += 2;
+    operation.add_source.num_subgroups = data[offset++];
+
+    /**
+     * Previous data was checked for it's size in 
`ble_svc_audio_bass_ctrl_point_write_access`.
+     * As bis_sync_state array may be of variable length, we need to check it 
separately
+     */
+    data_len -= offset;
+    for (i = 0; i < operation.add_source.num_subgroups; i++) {
+        if (data_len < sizeof(uint32_t)) {
+            rc = BLE_ATT_ERR_WRITE_REQ_REJECTED;
+            ev.bass_operation_status.status = BLE_HS_EREJECT;
+            goto done;
+        }
+        operation.add_source.subgroups[i].bis_sync_state = 
get_le32(&data[offset]);
+        offset += 4;
+        operation.add_source.subgroups[i].metadata_length = data[offset++];
+        data_len -= 5;
+        if (data_len < operation.add_source.subgroups[i].metadata_length) {
+            rc = BLE_ATT_ERR_WRITE_REQ_REJECTED;
+            ev.bass_operation_status.status = BLE_HS_EREJECT;
+            goto done;
+        }
+        operation.add_source.subgroups[i].metadata = &data[offset];
+        offset += operation.add_source.subgroups[i].metadata_length;
+        data_len -= operation.add_source.subgroups[i].metadata_length;
+    }
+
+    source_id_new = ble_svc_audio_bass_get_new_source_id();
+    operation.add_source.source_id = source_id_new;
+
+    ble_svc_audio_bass_receive_state_find_free(&rcv_state);
+    if (rcv_state == NULL) {
+        operation.add_source.out_source_id_to_swap = &source_id_to_remove;
+    } else {
+        operation.add_source.out_source_id_to_swap = NULL;
+        rcv_state->source_id = operation.add_source.source_id;
+    }
+
+    if (accept_fn.ctrl_point_ev_fn) {
+        rc = accept_fn.ctrl_point_ev_fn(&operation, accept_fn.arg);
+        if (rc != 0) {
+            if (rcv_state != NULL) {
+                ble_svc_audio_bass_receive_state_free(rcv_state);
+            }
+            rc = BLE_ATT_ERR_WRITE_REQ_REJECTED;
+            ev.bass_operation_status.status = BLE_HS_EREJECT;
+            goto done;
+        }
+    }
+
+    if (rcv_state == NULL) {
+        if (source_id_to_remove != 
BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE) {
+            ble_svc_audio_bass_receive_state_find_by_source_id(&rcv_state, 
source_id_to_remove);
+            if (rcv_state == NULL) {
+                rc = BLE_HS_EAPP;
+                ev.bass_operation_status.status = BLE_HS_EAPP;
+                goto done;
+            }
+
+            /* Swap Source ID */
+            rcv_state->source_id = operation.add_source.source_id;
+        } else {
+            rc = BLE_HS_ENOMEM;
+            ev.bass_operation_status.status = BLE_HS_ENOMEM;
+            goto done;
+        }
+    } else {
+        rcv_state->source_id = operation.add_source.source_id;
+    }
+
+    ev.bass_operation_status.source_id = rcv_state->source_id;
+    rcv_state->state.source_addr.type = operation.add_source.adv_addr.type;
+    memcpy(&rcv_state->state.source_addr.type, 
operation.add_source.adv_addr.val, 6);
+    rcv_state->state.source_adv_sid = operation.add_source.adv_sid;
+    rcv_state->state.broadcast_id = operation.add_source.broadcast_id;
+
+    for (i = 0; i < operation.add_source.num_subgroups; i++) {
+        metadata_ptr = os_memblock_get(&ble_audio_svc_bass_metadata_pool);
+        if (!metadata_ptr) {
+            rc = BLE_HS_ENOMEM;
+            ev.bass_operation_status.status = BLE_HS_ENOMEM;
+            goto done;
+        }
+        rcv_state->state.subgroups[i].metadata_length = 
operation.add_source.subgroups[i].metadata_length;
+        memcpy(metadata_ptr, operation.add_source.subgroups[i].metadata,
+               min(operation.add_source.subgroups[i].metadata_length,
+                   MYNEWT_VAL(BLE_SVC_AUDIO_BASS_METADATA_MAX_SZ)));
+
+        rcv_state->state.subgroups[i].metadata = metadata_ptr;
+    }
+
+done:
+    if (!rc) {
+        rc = ble_svc_audio_bass_receive_state_notify(rcv_state);
+        ev.bass_operation_status.status = rc;
+        goto done;
+    }
+
+    ble_audio_event_listener_call(&ev);
+
+    return rc;
+}
+
+static int
+check_bis_sync(uint16_t num_subgroups, const uint32_t *bis_sync_list)
+{
+    uint32_t bis_sync_mask = 0;
+    int i;
+    int j;
+
+    for (i = 0; i < num_subgroups; i++) {
+        if (bis_sync_list[i] != 0xFFFFFFFF) {
+            for (j = 0; j < num_subgroups; j++) {
+                if (bis_sync_list[i] & bis_sync_mask) {
+                    return BLE_HS_EINVAL;
+                }
+
+                bis_sync_mask |= bis_sync_list[i];
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int
+ble_svc_audio_bass_modify_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle)
+{
+    struct ble_svc_audio_bass_operation operation;
+    struct ble_svc_audio_bass_rcv_state_entry *rcv_state = NULL;
+    struct ble_audio_event ev = {
+        .type = BLE_AUDIO_EVENT_BASS_OPERATION_STATUS,
+        .bass_operation_status = {
+            .op = BLE_AUDIO_EVENT_BASS_SOURCE_MODIFIED,
+            .status = 0
+        }
+    };
+    uint8_t offset = 0;
+    int rc = 0;
+    int i;
+
+    memset(&operation, 0, sizeof(operation));
+
+    operation.op = BLE_SVC_AUDIO_BASS_OPERATION_MODIFY_SOURCE;
+    operation.conn_handle = conn_handle;
+
+    operation.modify_source.source_id = data[offset++];
+
+    ble_svc_audio_bass_receive_state_find_by_source_id(&rcv_state,
+                                                       
operation.modify_source.source_id);
+    if (rcv_state == NULL) {
+        rc = BLE_SVC_AUDIO_BASS_ERR_INVALID_SOURCE_ID;
+        ev.bass_operation_status.status = BLE_HS_EINVAL;
+        goto done;
+    }
+
+    operation.modify_source.pa_sync = data[offset++];
+    if (operation.modify_source.pa_sync >= BLE_SVC_AUDIO_BASS_PA_SYNC_RFU) {
+        return BLE_HS_EINVAL;
+    }
+
+    operation.modify_source.pa_interval = get_le16(&data[offset]);
+    offset += 2;
+    operation.modify_source.num_subgroups = get_le16(&data[offset]);
+    offset += 2;
+
+    data_len -= offset;
+    if (data_len < operation.modify_source.num_subgroups * sizeof(uint32_t)) {
+        rc = BLE_ATT_ERR_WRITE_REQ_REJECTED;
+        ev.bass_operation_status.status = BLE_HS_EREJECT;
+        goto done;
+    }
+
+    for (i = 0; i < operation.modify_source.num_subgroups; i++) {
+        operation.modify_source.bis_sync[i] = get_le32(&data[offset]);
+        offset += 4;
+    }
+
+    if (check_bis_sync(operation.modify_source.num_subgroups,
+                       operation.modify_source.bis_sync)) {
+        return 0;
+    }
+
+    if (accept_fn.ctrl_point_ev_fn) {
+        rc = accept_fn.ctrl_point_ev_fn(&operation, accept_fn.arg);
+        if (rc != 0) {
+            rc = BLE_ATT_ERR_WRITE_REQ_REJECTED;
+            ev.bass_operation_status.status = BLE_HS_EREJECT;
+            goto done;
+        }
+    }
+
+    ev.bass_operation_status.source_id = operation.modify_source.source_id;
+
+done:
+    if (!rc) {
+        rc = ble_svc_audio_bass_receive_state_notify(rcv_state);
+        ev.bass_operation_status.status = rc;
+        goto done;
+    }
+
+    ble_audio_event_listener_call(&ev);
+
+    return rc;
+}
+
+static int
+ble_svc_audio_bass_set_broadcast_code(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle)
+{
+    struct ble_svc_audio_bass_rcv_state_entry *rcv_state = NULL;
+    struct ble_audio_event ev = {
+        .type = BLE_AUDIO_EVENT_BASS_BROADCAST_CODE_SET,
+    };
+
+    ev.bass_set_broadcast_code.source_id = data[0];
+
+    ble_svc_audio_bass_receive_state_find_by_source_id(&rcv_state,
+                                                       
ev.bass_set_broadcast_code.source_id);
+    if (rcv_state == NULL) {
+        return BLE_SVC_AUDIO_BASS_ERR_INVALID_SOURCE_ID;
+    }
+
+    memcpy(ev.bass_set_broadcast_code.broadcast_code, &data[1], 
BLE_AUDIO_BROADCAST_CODE_SIZE);
+
+    ble_audio_event_listener_call(&ev);
+
+    return 0;
+}
+
+static int
+ble_svc_audio_bass_remove_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle)
+{
+    struct ble_audio_event ev = {
+        .type = BLE_AUDIO_EVENT_BASS_BROADCAST_CODE_SET,
+        .bass_operation_status = {
+            .op = BLE_AUDIO_EVENT_BASS_SOURCE_REMOVED,
+            .status = 0
+        }
+    };
+    struct ble_svc_audio_bass_rcv_state_entry *rcv_state = NULL;
+    struct ble_svc_audio_bass_operation operation;
+    int rc = 0;
+    int i;
+
+    ev.bass_set_broadcast_code.source_id = data[0];
+
+    ble_svc_audio_bass_receive_state_find_by_source_id(&rcv_state,
+                                                       
ev.bass_operation_status.source_id);
+    if (rcv_state == NULL) {
+        rc = BLE_SVC_AUDIO_BASS_ERR_INVALID_SOURCE_ID;
+        ev.bass_operation_status.status = BLE_HS_ENOENT;
+        goto done;
+    }
+
+    operation.remove_source.source_id = ev.bass_operation_status.source_id;
+    operation.conn_handle = conn_handle;
+    if (accept_fn.ctrl_point_ev_fn) {
+        rc = accept_fn.ctrl_point_ev_fn(&operation, accept_fn.arg);
+        if (rc != 0) {
+            rc = BLE_HS_EREJECT;
+            ev.bass_operation_status.status = BLE_HS_EREJECT;
+            goto done;
+        }
+    }
+
+    for (i = 0; i < rcv_state->state.num_subgroups; i++) {
+        os_memblock_put(&ble_audio_svc_bass_metadata_pool, 
rcv_state->state.subgroups[i].metadata);
+    }
+
+    memset(rcv_state, 0, sizeof(*rcv_state));
+    rcv_state->source_id = BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE;
+
+done:
+    if (!rc) {
+        rc = ble_svc_audio_bass_receive_state_notify(rcv_state);
+        ev.bass_operation_status.status = rc;
+        goto done;
+    }
+
+    ble_audio_event_listener_call(&ev);
+
+    return rc;
+}
+
+static struct ble_svc_audio_bass_ctrl_point_handler *
+ble_svc_audio_bass_find_handler(uint8_t opcode)
+{
+    int i;
+
+    for (i = 0; i < sizeof(ble_svc_audio_bass_ctrl_point_handlers); i++) {
+        if (ble_svc_audio_bass_ctrl_point_handlers[i].op_code == opcode) {
+            return &ble_svc_audio_bass_ctrl_point_handlers[i];
+        }
+    }
+
+    return NULL;
+}
+
+static int
+ble_svc_audio_bass_ctrl_point_write_access(struct ble_gatt_access_ctxt *ctxt, 
uint16_t conn_handle)
+{
+    struct ble_svc_audio_bass_ctrl_point_handler *handler;
+
+    uint8_t opcode = ctxt->om->om_data[0];
+
+    handler = ble_svc_audio_bass_find_handler(opcode);
+
+    if (!handler) {
+        return BLE_SVC_AUDIO_BASS_ERR_OPCODE_NOT_SUPPORTED;
+    }
+
+    if (ctxt->om->om_len - 1 < handler->length_min &&
+        handler->length_max >= 0 ?
+        ctxt->om->om_len > handler->length_max : 0) {
+        return BLE_ATT_ERR_WRITE_REQ_REJECTED;
+    }
+
+    return handler->handler_cb(&ctxt->om->om_data[1], ctxt->om->om_len - 1, 
conn_handle);
+}
+
+static int
+ble_svc_audio_bass_rcv_state_read_access(struct ble_gatt_access_ctxt *ctxt, 
void *arg)
+{
+    struct ble_svc_audio_bass_rcv_state_entry *state = arg;
+    uint8_t *buf;
+    int i;
+
+    /* Nothing set, return empty buffer */
+    if (state->source_id == BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE) {
+        return 0;
+    }
+
+    os_mbuf_append(ctxt->om, &state->source_id, 1);
+    os_mbuf_append(ctxt->om, &state->state.source_addr.type, 1);
+    os_mbuf_append(ctxt->om, &state->state.source_addr.val, 6);
+    os_mbuf_append(ctxt->om, &state->state.source_adv_sid, 1);
+    buf = os_mbuf_extend(ctxt->om, 3);
+    if (buf == NULL) {
+        return BLE_ATT_ERR_INSUFFICIENT_RES;
+    }
+
+    put_le24(buf, state->state.broadcast_id);
+    os_mbuf_append(ctxt->om, &state->state.pa_sync_state, 1);
+    os_mbuf_append(ctxt->om, &state->state.big_encryption, 1);
+
+    if (state->state.big_encryption == BLE_SVC_AUDIO_BASS_BIG_ENC_BAD_CODE) {
+        os_mbuf_append(ctxt->om, &state->state.bad_code, 
BLE_AUDIO_BROADCAST_CODE_SIZE);
+    }
+
+    os_mbuf_append(ctxt->om, &state->state.num_subgroups, 1);
+
+    for (i = 0; i < state->state.num_subgroups; i++) {
+        buf = os_mbuf_extend(ctxt->om, 4);
+        if (buf == NULL) {
+            return BLE_ATT_ERR_INSUFFICIENT_RES;
+        }
+
+        put_le32(buf, state->state.subgroups[i].bis_sync_state);
+        os_mbuf_append(ctxt->om, &state->state.subgroups[i].metadata_length, 
1);
+        os_mbuf_append(ctxt->om, state->state.subgroups[i].metadata,
+                       state->state.subgroups[i].metadata_length);
+    }
+
+    return 0;
+}
+
+int
+ble_svc_audio_bass_accept_fn_set(ble_svc_audio_bass_accept_fn *fn, void *arg)
+{
+    if (accept_fn.ctrl_point_ev_fn) {
+        return BLE_HS_EALREADY;
+    }
+
+    accept_fn.ctrl_point_ev_fn = fn;
+    accept_fn.arg = arg;
+    return 0;
+}
+
+int
+ble_svc_audio_bass_receive_state_add(const struct 
ble_svc_audio_bass_receiver_state_add_params *params,
+                                     uint8_t *source_id)
+{
+    struct ble_svc_audio_bass_rcv_state_entry *rcv_state;
+    int i;
+    int rc;
+
+    rc = ble_svc_audio_bass_receive_state_find_free(&rcv_state);
+    if (rc) {
+        return rc;
+    }
+
+    rcv_state->source_id = ble_svc_audio_bass_get_new_source_id();
+    rcv_state->state.source_addr = params->source_addr;
+    rcv_state->state.source_adv_sid = params->source_adv_sid;
+    rcv_state->state.broadcast_id = params->broadcast_id;
+    rcv_state->state.pa_sync_state = params->pa_sync_state;
+    rcv_state->state.big_encryption = params->big_encryption;
+    memcpy(&rcv_state->state.bad_code, params->bad_code, 
BLE_AUDIO_BROADCAST_CODE_SIZE);
+    rcv_state->state.num_subgroups = params->num_subgroups;
+
+    for (i = 0; i < rcv_state->state.num_subgroups; i++) {
+        rcv_state->state.subgroups[i].metadata =
+            os_memblock_get(&ble_audio_svc_bass_metadata_pool);
+
+        if (!rcv_state->state.subgroups[i].metadata) {
+            return 0;
+        }
+
+        rcv_state->state.subgroups[i].metadata_length =
+            min(params->subgroups[i].metadata_length,
+                ble_audio_svc_bass_metadata_pool.mp_block_size);
+        memcpy(rcv_state->state.subgroups[i].metadata, 
params->subgroups[i].metadata,
+               rcv_state->state.subgroups[i].metadata_length);
+    }
+
+    *source_id = rcv_state->source_id;
+
+    return ble_svc_audio_bass_receive_state_notify(rcv_state);
+}
+
+int
+ble_svc_audio_bass_receive_state_remove(uint8_t source_id)
+{
+    struct ble_svc_audio_bass_rcv_state_entry *rcv_state = NULL;
+    int rc, i;
+
+    rc = ble_svc_audio_bass_receive_state_find_by_source_id(&rcv_state, 
source_id);
+    if (rc) {
+        return rc;
+    }
+
+    memset(&rcv_state->state, 0, sizeof(rcv_state->state));
+    rcv_state->source_id = BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE;
+
+    for (i = 0; i < rcv_state->state.num_subgroups; i++) {
+        os_memblock_put(&ble_audio_svc_bass_metadata_pool, 
rcv_state->state.subgroups[i].metadata);
+    }
+
+    return ble_svc_audio_bass_receive_state_notify(rcv_state);
+}
+
+int
+ble_svc_audio_bass_update_metadata(const struct 
ble_svc_audio_bass_metadata_params *params,
+                                   uint8_t source_id)
+{
+    struct ble_svc_audio_bass_rcv_state_entry *rcv_state = NULL;
+    int rc;
+
+    rc = ble_svc_audio_bass_receive_state_find_by_source_id(&rcv_state, 
source_id);
+    if (rc) {
+        return rc;
+    }
+
+    rcv_state->state.subgroups[params->subgroup_idx].metadata_length = 
params->metadata_length;
+    memcpy(rcv_state->state.subgroups[params->subgroup_idx].metadata,
+           params->metadata, params->metadata_length);
+
+    return ble_svc_audio_bass_receive_state_notify(rcv_state);
+}
+
+int
+ble_svc_audio_bass_receive_state_update(const struct
+                                        ble_svc_audio_bass_update_params 
*params,
+                                        uint8_t source_id)
+{
+    struct ble_svc_audio_bass_rcv_state_entry *rcv_state = NULL;
+    int rc;
+
+    rc = ble_svc_audio_bass_receive_state_find_by_source_id(&rcv_state,
+                                                            source_id);
+    if (rc) {
+        return rc;
+    }
+
+    rcv_state->state.pa_sync_state = params->pa_sync_state;
+    rcv_state->state.big_encryption = params->big_encryption;
+    if (params->bad_code) {
+        memcpy(rcv_state->state.bad_code,
+               params->bad_code,
+               BLE_AUDIO_BROADCAST_CODE_SIZE);
+    }
+    rcv_state->state.subgroups[params->subgroup_idx].bis_sync_state =
+        params->bis_sync_state;

Review Comment:
   If you agree with my comment above, this piece of code should look like:
   ```
       for (size_t i = 0; i < params->num_subgroups; i++) {
           rcv_state->state.subgroups[i].bis_sync_state = 
params->subgroups[i].bis_sync;
           rcv_state->state.subgroups[i].metadata_length = 
params->subgroups[i].metadata_length;
           memcpy(rcv_state->state.subgroups[i].metadata,
                  params->subgroups[i].metadata, 
params->subgroups[i].metadata_length);
       }
   ```



##########
nimble/host/audio/services/bass/src/ble_audio_svc_bass.c:
##########
@@ -0,0 +1,854 @@
+/*
+ * 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 "host/ble_hs.h"
+#include "host/ble_gatt.h"
+#include "../../host/src/ble_gatt_priv.h"
+#include "../../host/src/ble_att_priv.h"
+#include "services/bass/ble_audio_svc_bass.h"
+#include "../../../src/ble_audio_priv.h"
+
+#define BLE_SVC_AUDIO_BASS_CHR_LEN_UNLIMITED                    (-1)
+#define BLE_SVC_AUDIO_BASS_RECEIVE_BIS_SYNC_STATE_ANY           0xFFFFFFFF
+
+ble_uuid_t * bass_receive_state_uuid =
+    BLE_UUID16_DECLARE(BLE_SVC_AUDIO_BASS_CHR_UUID16_BROADCAST_RECEIVE_STATE);
+ble_uuid_t * bass_cp_uuid =
+    BLE_UUID16_DECLARE(BLE_SVC_AUDIO_BASS_CHR_UUID16_BASS_CP);
+
+enum ble_svc_audio_bass_ctrl_point_op_code {
+    BLE_AUDIO_SVC_BASS_REMOTE_SCAN_STOPPED,
+    BLE_AUDIO_SVC_BASS_REMOTE_SCAN_STARTED,
+    BLE_AUDIO_SVC_BASS_ADD_SOURCE,
+    BLE_AUDIO_SVC_BASS_MODIFY_SOURCE,
+    BLE_AUDIO_SVC_BASS_SET_BROADCAST_CODE,
+    BLE_AUDIO_SVC_BASS_REMOVE_SOURCE
+};
+
+typedef int ble_svc_audio_bass_ctrl_point_handler_cb(uint8_t *data,
+                                                     uint16_t data_len,
+                                                     uint16_t conn_handle);
+
+static struct ble_svc_audio_bass_ctrl_point_ev {
+    ble_svc_audio_bass_accept_fn *ctrl_point_ev_fn;
+    void *arg;
+} accept_fn;
+
+struct ble_svc_audio_bass_rcv_state_entry {
+    uint8_t source_id;
+    uint16_t chr_val;
+    struct ble_svc_audio_bass_receiver_state state;
+};
+
+static struct ble_svc_audio_bass_rcv_state_entry
+    receiver_states[MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX)] = {
+    [0 ... MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX) - 1] = {
+        .source_id = BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE
+    }
+};
+
+static struct os_mempool ble_audio_svc_bass_metadata_pool;
+static os_membuf_t ble_audio_svc_bass_metadata_mem[
+    OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX) *
+                    BLE_SVC_AUDIO_BASS_SUB_NUM_MAX,
+                    MYNEWT_VAL(BLE_SVC_AUDIO_BASS_METADATA_MAX_SZ))];
+
+static int
+ble_svc_audio_bass_remote_scan_stopped(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle);
+static int
+ble_svc_audio_bass_remote_scan_started(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle);
+static int
+ble_svc_audio_bass_add_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle);
+static int
+ble_svc_audio_bass_modify_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle);
+static int
+ble_svc_audio_bass_set_broadcast_code(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle);
+static int
+ble_svc_audio_bass_remove_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle);
+
+static int
+ble_svc_audio_bass_ctrl_point_write_access(struct ble_gatt_access_ctxt *ctxt, 
uint16_t conn_handle);
+static int
+ble_svc_audio_bass_rcv_state_read_access(struct ble_gatt_access_ctxt *ctxt, 
void *arg);
+
+static struct ble_svc_audio_bass_ctrl_point_handler {
+    uint8_t op_code;
+    uint8_t length_min;
+    uint8_t length_max;
+    ble_svc_audio_bass_ctrl_point_handler_cb *handler_cb;
+} ble_svc_audio_bass_ctrl_point_handlers[] = {
+    {
+        .op_code = BLE_AUDIO_SVC_BASS_REMOTE_SCAN_STOPPED,
+        .length_min = 0,
+        .length_max = 0,
+        .handler_cb = ble_svc_audio_bass_remote_scan_stopped
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_REMOTE_SCAN_STARTED,
+        .length_min = 0,
+        .length_max = 0,
+        .handler_cb = ble_svc_audio_bass_remote_scan_started
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_ADD_SOURCE,
+        .length_min = 15,
+        .length_max = BLE_SVC_AUDIO_BASS_CHR_LEN_UNLIMITED,
+        .handler_cb = ble_svc_audio_bass_add_source
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_MODIFY_SOURCE,
+        .length_min = 5,
+        .length_max = BLE_SVC_AUDIO_BASS_CHR_LEN_UNLIMITED,
+        .handler_cb = ble_svc_audio_bass_modify_source
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_SET_BROADCAST_CODE,
+        .length_min = 17,
+        .length_max = 17,
+        .handler_cb = ble_svc_audio_bass_set_broadcast_code
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_REMOVE_SOURCE,
+        .length_min = 1,
+        .length_max = 1,
+        .handler_cb = ble_svc_audio_bass_remove_source
+    }
+};
+
+static struct ble_gatt_chr_def 
ble_svc_audio_bass_chrs[MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX) + 2];
+
+static const struct ble_gatt_svc_def 
ble_svc_audio_bass_defs[MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX) + 2] = 
{
+    { /*** Service: Published Audio Capabilities Service (bass) */
+        .type = BLE_GATT_SVC_TYPE_PRIMARY,
+        .uuid = BLE_UUID16_DECLARE(BLE_SVC_AUDIO_BASS_UUID16),
+        .characteristics = ble_svc_audio_bass_chrs,
+    },
+    {
+        0, /* No more services. */
+    },
+};
+
+static uint8_t free_source_id = 0;
+
+static int
+ble_svc_audio_bass_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_BASS_CHR_UUID16_BASS_CP:
+        if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
+            rc = ble_svc_audio_bass_ctrl_point_write_access(ctxt, conn_handle);
+        } else {
+            assert(0);
+        }
+        return rc;
+    case BLE_SVC_AUDIO_BASS_CHR_UUID16_BROADCAST_RECEIVE_STATE:
+        if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
+            rc = ble_svc_audio_bass_rcv_state_read_access(ctxt, arg);
+        } else {
+            assert(0);
+        }
+        return rc;
+    default:
+        assert(0);
+    }
+}
+
+static uint8_t
+ble_svc_audio_bass_get_new_source_id(void)
+{
+    /** Wrap around after all Source IDs were used */
+    if (free_source_id == BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE) {
+        free_source_id = 0;
+    }
+
+    return free_source_id++;
+}
+
+static int
+ble_svc_audio_bass_receive_state_notify(struct 
ble_svc_audio_bass_rcv_state_entry *state)
+{
+    int i;
+
+    for (i = 0; i < sizeof(ble_svc_audio_bass_chrs); i++) {
+        if (ble_svc_audio_bass_chrs[i].arg == state) {
+            ble_gatts_chr_updated(*ble_svc_audio_bass_chrs[i].val_handle);
+            return 0;
+        }
+    }
+
+    return BLE_HS_ENOENT;
+}
+
+static int
+ble_svc_audio_bass_receive_state_find_by_source_id(struct 
ble_svc_audio_bass_rcv_state_entry **out_state,
+                                                   uint8_t source_id)
+{
+    int i;
+
+    for (i = 0; i < sizeof(receiver_states); i++) {
+        if (receiver_states[i].source_id == source_id) {
+            *out_state = &receiver_states[i];
+            return 0;
+        }
+    }
+
+    return BLE_HS_ENOMEM;
+}
+
+int
+ble_svc_audio_bass_receive_state_find_free(struct 
ble_svc_audio_bass_rcv_state_entry **out_state)
+{
+    int i;
+
+    for (i = 0; i < sizeof(receiver_states); i++) {
+        if (receiver_states[i].source_id == 
BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE) {
+            *out_state = &receiver_states[i];
+            return 0;
+        }
+    }
+
+    return BLE_HS_ENOMEM;
+}
+
+static void
+ble_svc_audio_bass_receive_state_free(struct 
ble_svc_audio_bass_rcv_state_entry *state)
+{
+    state->source_id = BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE;
+}
+
+static int
+ble_svc_audio_bass_remote_scan_stopped(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle)
+{
+    struct ble_audio_event ev = {
+        .type = BLE_AUDIO_EVENT_BASS_REMOTE_SCAN_STOPPED
+    };
+
+    ev.remote_scan_stopped.conn_handle = conn_handle;
+    ble_audio_event_listener_call(&ev);
+
+    return 0;
+}
+
+static int
+ble_svc_audio_bass_remote_scan_started(uint8_t *data, uint16_t data_len, 
uint16_t conn_handle)
+{
+    struct ble_audio_event ev = {
+        .type = BLE_AUDIO_EVENT_BASS_REMOTE_SCAN_STARTED
+    };
+
+    ev.remote_scan_started.conn_handle = conn_handle;
+    ble_audio_event_listener_call(&ev);
+
+    return 0;
+}
+
+static int
+ble_svc_audio_bass_add_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle)
+{
+    struct ble_audio_event ev = {
+        .type = BLE_AUDIO_EVENT_BASS_OPERATION_STATUS,
+        .bass_operation_status = {
+            .op = BLE_AUDIO_EVENT_BASS_SOURCE_ADDED,
+            .status = 0
+        }
+    };
+    struct ble_svc_audio_bass_operation operation;
+    struct ble_svc_audio_bass_rcv_state_entry *rcv_state = NULL;
+    uint8_t offset = 0;
+    uint8_t *metadata_ptr;
+    uint8_t source_id_new;
+    uint8_t source_id_to_remove = BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE;
+    int rc = 0;
+    int i;
+
+    memset(&operation, 0, sizeof(operation));
+
+    operation.op = BLE_SVC_AUDIO_BASS_OPERATION_ADD_SOURCE;
+    operation.conn_handle = conn_handle;
+
+    operation.add_source.adv_addr.type = data[offset++];
+    memcpy(operation.add_source.adv_addr.val, &data[offset], 6);
+    offset += 6;
+    operation.add_source.adv_sid = data[offset++];
+    operation.add_source.broadcast_id = get_le24(&data[offset]);
+    offset += 3;
+    operation.add_source.pa_sync = data[offset++];
+    if (operation.add_source.pa_sync >= BLE_SVC_AUDIO_BASS_PA_SYNC_RFU) {
+        rc = BLE_HS_EINVAL;
+        ev.bass_operation_status.status = BLE_HS_EINVAL;
+        goto done;
+    }
+
+    operation.add_source.pa_interval = get_le16(&data[offset]);
+    offset += 2;
+    operation.add_source.num_subgroups = data[offset++];
+
+    /**
+     * Previous data was checked for it's size in 
`ble_svc_audio_bass_ctrl_point_write_access`.
+     * As bis_sync_state array may be of variable length, we need to check it 
separately
+     */
+    data_len -= offset;
+    for (i = 0; i < operation.add_source.num_subgroups; i++) {
+        if (data_len < sizeof(uint32_t)) {
+            rc = BLE_ATT_ERR_WRITE_REQ_REJECTED;
+            ev.bass_operation_status.status = BLE_HS_EREJECT;
+            goto done;
+        }
+        operation.add_source.subgroups[i].bis_sync_state = 
get_le32(&data[offset]);
+        offset += 4;
+        operation.add_source.subgroups[i].metadata_length = data[offset++];
+        data_len -= 5;
+        if (data_len < operation.add_source.subgroups[i].metadata_length) {
+            rc = BLE_ATT_ERR_WRITE_REQ_REJECTED;
+            ev.bass_operation_status.status = BLE_HS_EREJECT;
+            goto done;
+        }
+        operation.add_source.subgroups[i].metadata = &data[offset];
+        offset += operation.add_source.subgroups[i].metadata_length;
+        data_len -= operation.add_source.subgroups[i].metadata_length;
+    }
+
+    source_id_new = ble_svc_audio_bass_get_new_source_id();
+    operation.add_source.source_id = source_id_new;
+
+    ble_svc_audio_bass_receive_state_find_free(&rcv_state);
+    if (rcv_state == NULL) {
+        operation.add_source.out_source_id_to_swap = &source_id_to_remove;
+    } else {
+        operation.add_source.out_source_id_to_swap = NULL;
+        rcv_state->source_id = operation.add_source.source_id;
+    }
+
+    if (accept_fn.ctrl_point_ev_fn) {
+        rc = accept_fn.ctrl_point_ev_fn(&operation, accept_fn.arg);
+        if (rc != 0) {
+            if (rcv_state != NULL) {
+                ble_svc_audio_bass_receive_state_free(rcv_state);
+            }
+            rc = BLE_ATT_ERR_WRITE_REQ_REJECTED;
+            ev.bass_operation_status.status = BLE_HS_EREJECT;
+            goto done;
+        }
+    }
+
+    if (rcv_state == NULL) {
+        if (source_id_to_remove != 
BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE) {
+            ble_svc_audio_bass_receive_state_find_by_source_id(&rcv_state, 
source_id_to_remove);
+            if (rcv_state == NULL) {
+                rc = BLE_HS_EAPP;
+                ev.bass_operation_status.status = BLE_HS_EAPP;
+                goto done;
+            }
+
+            /* Swap Source ID */
+            rcv_state->source_id = operation.add_source.source_id;
+        } else {
+            rc = BLE_HS_ENOMEM;
+            ev.bass_operation_status.status = BLE_HS_ENOMEM;
+            goto done;
+        }
+    } else {
+        rcv_state->source_id = operation.add_source.source_id;
+    }
+
+    ev.bass_operation_status.source_id = rcv_state->source_id;
+    rcv_state->state.source_addr.type = operation.add_source.adv_addr.type;
+    memcpy(&rcv_state->state.source_addr.type, 
operation.add_source.adv_addr.val, 6);
+    rcv_state->state.source_adv_sid = operation.add_source.adv_sid;
+    rcv_state->state.broadcast_id = operation.add_source.broadcast_id;
+
+    for (i = 0; i < operation.add_source.num_subgroups; i++) {
+        metadata_ptr = os_memblock_get(&ble_audio_svc_bass_metadata_pool);
+        if (!metadata_ptr) {
+            rc = BLE_HS_ENOMEM;
+            ev.bass_operation_status.status = BLE_HS_ENOMEM;
+            goto done;
+        }
+        rcv_state->state.subgroups[i].metadata_length = 
operation.add_source.subgroups[i].metadata_length;
+        memcpy(metadata_ptr, operation.add_source.subgroups[i].metadata,
+               min(operation.add_source.subgroups[i].metadata_length,
+                   MYNEWT_VAL(BLE_SVC_AUDIO_BASS_METADATA_MAX_SZ)));
+
+        rcv_state->state.subgroups[i].metadata = metadata_ptr;
+    }
+
+done:
+    if (!rc) {
+        rc = ble_svc_audio_bass_receive_state_notify(rcv_state);
+        ev.bass_operation_status.status = rc;
+        goto done;
+    }
+
+    ble_audio_event_listener_call(&ev);
+
+    return rc;
+}
+
+static int
+check_bis_sync(uint16_t num_subgroups, const uint32_t *bis_sync_list)
+{
+    uint32_t bis_sync_mask = 0;
+    int i;
+    int j;
+
+    for (i = 0; i < num_subgroups; i++) {
+        if (bis_sync_list[i] != 0xFFFFFFFF) {
+            for (j = 0; j < num_subgroups; j++) {
+                if (bis_sync_list[i] & bis_sync_mask) {
+                    return BLE_HS_EINVAL;
+                }
+
+                bis_sync_mask |= bis_sync_list[i];
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int
+ble_svc_audio_bass_modify_source(uint8_t *data, uint16_t data_len, uint16_t 
conn_handle)
+{
+    struct ble_svc_audio_bass_operation operation;
+    struct ble_svc_audio_bass_rcv_state_entry *rcv_state = NULL;
+    struct ble_audio_event ev = {
+        .type = BLE_AUDIO_EVENT_BASS_OPERATION_STATUS,
+        .bass_operation_status = {
+            .op = BLE_AUDIO_EVENT_BASS_SOURCE_MODIFIED,
+            .status = 0
+        }
+    };
+    uint8_t offset = 0;
+    int rc = 0;
+    int i;
+
+    memset(&operation, 0, sizeof(operation));
+
+    operation.op = BLE_SVC_AUDIO_BASS_OPERATION_MODIFY_SOURCE;
+    operation.conn_handle = conn_handle;
+
+    operation.modify_source.source_id = data[offset++];
+
+    ble_svc_audio_bass_receive_state_find_by_source_id(&rcv_state,
+                                                       
operation.modify_source.source_id);
+    if (rcv_state == NULL) {
+        rc = BLE_SVC_AUDIO_BASS_ERR_INVALID_SOURCE_ID;
+        ev.bass_operation_status.status = BLE_HS_EINVAL;
+        goto done;
+    }
+
+    operation.modify_source.pa_sync = data[offset++];
+    if (operation.modify_source.pa_sync >= BLE_SVC_AUDIO_BASS_PA_SYNC_RFU) {
+        return BLE_HS_EINVAL;
+    }
+
+    operation.modify_source.pa_interval = get_le16(&data[offset]);
+    offset += 2;
+    operation.modify_source.num_subgroups = get_le16(&data[offset]);
+    offset += 2;
+
+    data_len -= offset;
+    if (data_len < operation.modify_source.num_subgroups * sizeof(uint32_t)) {
+        rc = BLE_ATT_ERR_WRITE_REQ_REJECTED;
+        ev.bass_operation_status.status = BLE_HS_EREJECT;
+        goto done;
+    }
+
+    for (i = 0; i < operation.modify_source.num_subgroups; i++) {
+        operation.modify_source.bis_sync[i] = get_le32(&data[offset]);
+        offset += 4;
+    }
+
+    if (check_bis_sync(operation.modify_source.num_subgroups,
+                       operation.modify_source.bis_sync)) {
+        return 0;
+    }

Review Comment:
   Shouldn't an error be returned here instead of success?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@mynewt.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to