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


##########
nimble/host/audio/services/bass/src/ble_audio_svc_bass.c:
##########
@@ -0,0 +1,915 @@
+/*
+ * 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 "../../host/audio/include/host/audio/ble_audio_bsnk.h"
+
+#define EXPECTED_LEN_VARIABLE                                   (-1)
+#define BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE            0xFF
+#define BLE_SVC_AUDIO_BASS_RECEIVE_BIS_SYNC_STATE_ANY          0xFFFFFFFF
+
+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, void *arg);
+
+static struct ble_svc_audio_bass_ctrl_point_ev {
+    ble_svc_audio_bass_ctrl_point_ev_fn *ctrl_point_ev_fn;
+    void *arg;
+} ctrl_point_ev;
+
+static struct ble_svc_audio_bass_receiver_state
+    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 ble_audio_event_listener ble_svc_audio_bass_audio_event_listener;
+
+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) *
+                    
MYNEWT_VAL(BLE_SVC_AUDIO_BASS_MAX_SUBGROUPS_PER_RECV_STATE),
+                    MYNEWT_VAL(BLE_SVC_AUDIO_BASS_METADATA_MAX_SZ))];
+
+static int
+ble_svc_audio_bass_remote_scan_stopped(uint8_t *data, void *arg);
+static int
+ble_svc_audio_bass_remote_scan_started(uint8_t *data, void *arg);
+static int
+ble_svc_audio_bass_add_source(uint8_t *data, void *arg);
+static int
+ble_svc_audio_bass_modify_source(uint8_t *data, void *arg);
+static int
+ble_svc_audio_bass_set_broadcast_code(uint8_t *data, void *arg);
+static int
+ble_svc_audio_bass_remove_source(uint8_t *data, void *arg);
+
+static struct ble_svc_audio_bass_ctrl_point_handler {
+    uint8_t op_code;
+    int expected_len;
+    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,
+        .expected_len = 0,
+        .handler_cb = ble_svc_audio_bass_remote_scan_stopped
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_REMOTE_SCAN_STARTED,
+        .expected_len = 0,
+        .handler_cb = ble_svc_audio_bass_remote_scan_started
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_ADD_SOURCE,
+        .expected_len = EXPECTED_LEN_VARIABLE,
+        .handler_cb = ble_svc_audio_bass_add_source
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_MODIFY_SOURCE,
+        .expected_len = EXPECTED_LEN_VARIABLE,
+        .handler_cb = ble_svc_audio_bass_modify_source
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_SET_BROADCAST_CODE,
+        .expected_len = 17,
+        .handler_cb = ble_svc_audio_bass_set_broadcast_code
+    }, {
+        .op_code = BLE_AUDIO_SVC_BASS_REMOVE_SOURCE,
+        .expected_len = 1,
+        .handler_cb = ble_svc_audio_bass_remove_source
+    }
+};
+
+static int
+ble_svc_audio_bass_access(uint16_t conn_handle, uint16_t attr_handle,
+                          struct ble_gatt_access_ctxt *ctxt, void *arg);
+
+static int
+ble_svc_audio_bass_ctrl_point_write_access(struct ble_gatt_access_ctxt *ctxt);
+static int
+ble_svc_audio_bass_rcv_state_read_access(struct ble_gatt_access_ctxt *ctxt, 
void *arg);
+
+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 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_BAS_CONTROL_POINT:
+        if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
+            rc = ble_svc_audio_bass_ctrl_point_write_access(ctxt);
+        } 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()
+{
+    struct ble_svc_audio_bass_receiver_state *rcv_state;
+    struct ble_svc_audio_bass_receiver_state *next_rcv_state;
+    uint8_t free_source_id;
+    uint8_t highest_source_id = 0;
+    uint8_t lowest_source_id = BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE;
+
+    int i;
+
+    /* First characteristic is 
BLE_SVC_AUDIO_BASS_CHR_UUID16_BAS_CONTROL_POINT, iterate from 2nd */
+    for (i = 1; i <= MYNEWT_VAL(BLE_SVC_AUDIO_BASS_RECEIVE_STATE_MAX); i++) {
+        rcv_state = ble_svc_audio_bass_chrs[i].arg;
+        if (highest_source_id < rcv_state->source_id &&
+            rcv_state->source_id != 
BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE)
+        {
+            highest_source_id = rcv_state->source_id;
+        }
+
+        if (lowest_source_id > rcv_state->source_id) {
+            lowest_source_id = rcv_state->source_id;
+        }
+    }
+
+    if ((highest_source_id + 1) < 
BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE) {
+        return highest_source_id + 1;
+    }
+
+    return min(lowest_source_id + 1, 0);
+}
+
+static int
+ble_svc_audio_bass_remote_scan_stopped(uint8_t *data, void *arg)
+{
+    struct ble_svc_audio_bass_ctrl_point_event ev = {
+        .op = BLE_SVC_AUDIO_BASS_CTRL_POINT_EVENT_REMOTE_SCAN_STOPPED
+    };
+
+    if (ctrl_point_ev.ctrl_point_ev_fn) {
+        ctrl_point_ev.ctrl_point_ev_fn(&ev, ctrl_point_ev.arg);
+    }
+
+    return 0;
+}
+
+static int
+ble_svc_audio_bass_remote_scan_started(uint8_t *data, void *arg)
+{
+    struct ble_svc_audio_bass_ctrl_point_event ev = {
+        .op = BLE_SVC_AUDIO_BASS_CTRL_POINT_EVENT_REMOTE_SCAN_STARTED
+    };
+
+    if (ctrl_point_ev.ctrl_point_ev_fn) {
+        ctrl_point_ev.ctrl_point_ev_fn(&ev, ctrl_point_ev.arg);
+    }
+
+    return 0;
+}
+
+static int
+ble_svc_audio_bass_create_bsnk(ble_addr_t *addr, uint8_t sid,
+                               uint32_t broadcast_id, uint16_t pa_itvl,
+                               struct ble_audio_bsnk **out_bsnk)
+{
+    struct ble_audio_bsnk_create_params bsnk_create_params;
+
+    bsnk_create_params.adv_addr = addr;
+    bsnk_create_params.adv_sid = sid;
+    bsnk_create_params.broadcast_id = broadcast_id;
+    bsnk_create_params.pa_interval = pa_itvl;
+
+    return ble_audio_bsnk_create(&bsnk_create_params, out_bsnk);
+}
+
+static int
+ble_svc_audio_bass_sync_pa(struct ble_audio_bsnk *bsnk)
+{
+    struct ble_audio_bsnk_pa_sync_params params = {
+        .conn_handle = BLE_HS_CONN_HANDLE_NONE,
+        .retry_count = 0,
+        .skip = 0
+    };
+
+    return ble_audio_bsnk_pa_sync(bsnk, &params);
+}
+
+static int
+ble_svc_audio_bass_receive_state_find_by_sink(struct 
ble_svc_audio_bass_receiver_state **out_state,
+                                              struct ble_audio_bsnk *snk)
+{
+    int i;
+
+    for (i = 0; i < sizeof(receiver_states); i++) {
+        if (receiver_states[i].bsnk == snk) {
+            *out_state = &receiver_states[i];
+            return 0;
+        }
+    }
+
+    return BLE_HS_ENOMEM;
+}
+
+static int
+ble_svc_audio_bass_receive_state_find_by_source_id(struct 
ble_svc_audio_bass_receiver_state **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;
+}
+
+static int
+iso_event_handler(struct ble_iso_event *event, void *arg)
+{
+    struct ble_svc_audio_bass_receiver_state *state = arg;
+
+    switch (event->type) {
+    case BLE_ISO_EVENT_BIG_SYNC_ESTABLISHED:
+
+        break;
+    default:
+        break;
+    }
+
+    return 0;
+}
+
+static void
+ble_svc_audio_bass_sync_bises(struct ble_svc_audio_bass_receiver_state *state,
+                              uint32_t bis_sync_state)
+{
+    struct ble_audio_bsnk_bis_sync_params 
bis_sync_params[MYNEWT_VAL(BLE_MAX_BIS)] = { 0 };
+    struct ble_audio_bsnk_sync_params sync_params = {
+        .params = bis_sync_params,
+    };
+    uint8_t bis_index = 0x01;
+    int rc;
+    int i;
+
+    sync_params.num_bis = __builtin_popcount(bis_sync_state);
+
+    for (i = 0; i < sync_params.num_bis; i++) {
+        while (bis_sync_params[i].bis_index == 0) {
+            if (bis_sync_state & (1 << (bis_index - 1))) {
+                bis_sync_params[i].bis_index = bis_index;
+                bis_sync_params[i].cb = iso_event_handler;
+                bis_sync_params[i].cb_arg = state;
+            }
+
+            bis_index++;
+        }
+    }
+
+    rc = ble_audio_bsnk_sync(state->bsnk, &sync_params);
+    if (rc != 0) {
+        for (i = 0; i < state->params.num_subgroups; i++) {
+            state->params.subgroups[i].bis_sync_state =
+                BLE_SVC_AUDIO_BASS_RECEIVE_BIS_SYNC_STATE_ANY;
+        }
+    }
+}
+
+static int
+ble_svc_audio_bass_receive_state_notify(struct 
ble_svc_audio_bass_receiver_state *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_add_source(uint8_t *data, void *arg)
+{
+    struct ble_svc_audio_bass_ctrl_point_event ev;
+    struct ble_svc_audio_bass_receiver_state *rcv_state = NULL;
+    uint8_t source_id;
+    uint8_t offset = 0;
+    uint8_t *metadata_ptr;
+    int rc;
+    int i;
+
+    memset(&ev, 0, sizeof(ev));
+
+    ev.op = BLE_SVC_AUDIO_BASS_CTRL_POINT_EVENT_ADD_SOURCE;
+
+    ev.add_source.adv_addr.type = data[offset++];
+    memcpy(ev.add_source.adv_addr.val, &data[offset], 6);
+    offset += 6;
+    ev.add_source.adv_sid = data[offset++];
+    ev.add_source.broadcast_id = get_le24(&data[offset]);
+    offset += 3;
+    ev.add_source.pa_sync = data[offset++];
+    if (ev.add_source.pa_sync > 0x02) {
+        return BLE_HS_EINVAL;
+    }
+
+    ev.add_source.pa_interval = get_le16(&data[offset]);
+    offset += 2;
+    ev.add_source.num_subgroups = get_le16(&data[offset]);
+    offset += 2;
+
+    for (i = 0; i < ev.add_source.num_subgroups; i++) {
+        ev.add_source.subgroups[i].bis_sync_state = get_le32(&data[offset]);
+        offset += 4;
+        ev.add_source.subgroups[i].metadata_length = data[offset++];
+        ev.add_source.subgroups[i].metadata = &data[offset];
+        offset += ev.add_source.subgroups[i].metadata_length;
+    }
+
+    *ev.add_source.source_id = BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE;
+
+    if (ctrl_point_ev.ctrl_point_ev_fn) {
+        rc = ctrl_point_ev.ctrl_point_ev_fn(&ev, ctrl_point_ev.arg);
+        if (rc != 0) {
+            return BLE_HS_EREJECT;
+        }
+    }
+
+    if (*ev.add_source.source_id == 
BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE) {
+        ble_svc_audio_bass_receive_state_find_free(&rcv_state);
+    }
+
+    if (!rcv_state) {
+        return BLE_HS_EREJECT;
+    }
+
+    source_id = ble_svc_audio_bass_get_new_source_id();
+
+    rcv_state->source_id = source_id;
+    rcv_state->params.source_addr.type = ev.add_source.adv_addr.type;
+    memcpy(&rcv_state->params.source_addr.type, ev.add_source.adv_addr.val, 6);
+    rcv_state->params.source_adv_sid = ev.add_source.adv_sid;
+    rcv_state->params.broadcast_id = ev.add_source.broadcast_id;
+
+    switch (ev.add_source.pa_sync) {
+    case 0x00:
+        rcv_state->params.pa_sync_state = 
BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_NOT_SYNCED;
+        break;
+    case 0x01:
+    case 0x02:
+        if (MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER)) {
+            rcv_state->params.pa_sync_state = 
BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_SYNC_INFO_REQ;
+        } else {
+            rc = ble_svc_audio_bass_create_bsnk(&ev.add_source.adv_addr,
+                                                ev.add_source.adv_sid,
+                                                ev.add_source.broadcast_id,
+                                                ev.add_source.pa_interval,
+                                                &rcv_state->bsnk);
+            if (rc != 0) {
+                return rc;
+            }
+
+            rc = ble_svc_audio_bass_sync_pa(rcv_state->bsnk);
+            if (rc != 0) {
+                return rc;
+            }
+        }
+    default:
+        break;
+    }
+
+    for (i = 0; i < ev.add_source.num_subgroups; i++) {
+        metadata_ptr = os_memblock_get(&ble_audio_svc_bass_metadata_pool);
+        if (!metadata_ptr) {
+            return 0;
+        }
+        rcv_state->params.subgroups[i].metadata_length = 
ev.add_source.subgroups[i].metadata_length;
+        memcpy(metadata_ptr, ev.add_source.subgroups[i].metadata,
+               min(ev.add_source.subgroups[i].metadata_length,
+                   MYNEWT_VAL(BLE_SVC_AUDIO_BASS_METADATA_MAX_SZ)));
+        if (ev.add_source.subgroups[i].metadata_length > 0) {
+            rcv_state->params.subgroups[i].metadata = metadata_ptr;
+        }
+        rcv_state->params.subgroups[i].metadata = 
ev.add_source.subgroups[i].metadata;
+    }
+
+    return ble_svc_audio_bass_receive_state_notify(rcv_state);
+}
+
+static int
+ble_svc_audio_bass_modify_source(uint8_t *data, void *arg)
+{
+    struct ble_svc_audio_bass_ctrl_point_event ev;
+    struct ble_svc_audio_bass_receiver_state *rcv_state = NULL;
+    uint8_t source_id;
+    uint8_t offset = 0;
+    uint8_t *metadata_ptr;
+    int rc;
+    int i;
+
+    memset(&ev, 0, sizeof(ev));
+
+    ev.op = BLE_SVC_AUDIO_BASS_CTRL_POINT_EVENT_ADD_SOURCE;
+
+    ev.modify_source.source_id = data[offset++];
+    ev.modify_source.pa_sync = data[offset++];
+    if (ev.modify_source.pa_sync > 0x02) {
+        return BLE_HS_EINVAL;
+    }
+
+    ev.modify_source.pa_interval = get_le16(&data[offset]);
+    offset += 2;
+    ev.modify_source.num_subgroups = get_le16(&data[offset]);
+    offset += 2;
+
+    for (i = 0; i < ev.modify_source.num_subgroups; i++) {
+        ev.modify_source.bis_sync[i] = get_le32(&data[offset]);
+        offset += 4;
+    }
+
+    if (ctrl_point_ev.ctrl_point_ev_fn) {
+        rc = ctrl_point_ev.ctrl_point_ev_fn(&ev, ctrl_point_ev.arg);
+        if (rc != 0) {
+            return BLE_HS_EREJECT;
+        }
+    }
+
+    ble_svc_audio_bass_receive_state_find_by_source_id(&rcv_state, 
ev.modify_source.source_id);
+    if (rcv_state == NULL) {
+        return BLE_HS_EREJECT;
+    }
+
+    if (ev.modify_source.pa_sync == BLE_SVC_AUDIO_BASS_PA_SYNC_DO_NOT_SYNC &&
+        rcv_state->params.pa_sync_state != 
BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_SYNCED) {
+        rcv_state->params.pa_sync_state = 
BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_NOT_SYNCED;
+    } else if (ev.modify_source.pa_sync == 
BLE_SVC_AUDIO_BASS_PA_SYNC_DO_NOT_SYNC &&
+               rcv_state->params.pa_sync_state == 
BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_SYNCED) {
+        ble_audio_bsnk_pa_sync_term(rcv_state->bsnk);
+    } else if (ev.modify_source.pa_sync == 
BLE_SVC_AUDIO_BASS_PA_SYNC_SYNC_PAST_AVAILABLE) {
+        if (MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER)) {
+            rcv_state->params.pa_sync_state = 
BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_SYNC_INFO_REQ;
+        } else {
+            rc = ble_svc_audio_bass_sync_pa(rcv_state->bsnk);
+            if (rc != 0) {
+                return rc;
+            }
+        }
+    } else if (ev.modify_source.pa_sync == 
BLE_SVC_AUDIO_BASS_PA_SYNC_SYNC_PAST_NOT_AVAILABLE) {
+        rc = ble_svc_audio_bass_sync_pa(rcv_state->bsnk);
+        if (rc != 0) {
+            return rc;
+        }
+    }
+
+    for (i = 0; i < rcv_state->params.num_subgroups; i++) {
+        ble_svc_audio_bass_sync_bises(rcv_state, ev.modify_source.bis_sync[i]);
+    }
+
+    return ble_svc_audio_bass_receive_state_notify(rcv_state);
+}
+
+static int
+ble_svc_audio_bass_set_broadcast_code(uint8_t *data, void *arg)
+{
+    int offset = 0;
+    struct ble_svc_audio_bass_ctrl_point_event ev = {
+        .op = BLE_SVC_AUDIO_BASS_CTRL_POINT_EVENT_SET_BROADCAST_CODE
+    };
+    struct ble_svc_audio_bass_receiver_state *rcv_state = NULL;
+
+    ev.set_broadcast_code.source_id = data[offset++];
+    memcpy(ev.set_broadcast_code.broadcast_code, &data[offset], 
BLE_AUDIO_BROADCAST_CODE_SIZE);
+
+    ble_svc_audio_bass_receive_state_find_by_source_id(&rcv_state, 
ev.set_broadcast_code.source_id);
+    if (rcv_state == NULL) {
+        return BLE_HS_EREJECT;
+    }
+
+    if (ctrl_point_ev.ctrl_point_ev_fn) {
+        ctrl_point_ev.ctrl_point_ev_fn(&ev, ctrl_point_ev.arg);
+    }
+
+    ble_audio_bsnk_code_set(rcv_state->bsnk, (char 
*)ev.set_broadcast_code.broadcast_code);
+
+    return 0;
+}
+
+static int
+ble_svc_audio_bass_remove_source(uint8_t *data, void *arg)
+{
+    struct ble_svc_audio_bass_ctrl_point_event ev = {
+        .op = BLE_SVC_AUDIO_BASS_CTRL_POINT_EVENT_REMOVE_SOURCE
+    };
+    struct ble_svc_audio_bass_receiver_state *rcv_state = NULL;
+    int rc;
+    int i;
+
+    ev.set_broadcast_code.source_id = data[0];
+
+    if (ctrl_point_ev.ctrl_point_ev_fn) {
+        rc = ctrl_point_ev.ctrl_point_ev_fn(&ev, ctrl_point_ev.arg);
+        if (rc != 0) {
+            return BLE_HS_EREJECT;
+        }
+    }
+
+    ble_svc_audio_bass_receive_state_find_by_source_id(&rcv_state, 
ev.set_broadcast_code.source_id);
+    if (rcv_state == NULL) {
+        return BLE_HS_EREJECT;
+    }
+
+    for (i = 0; i < rcv_state->params.num_subgroups; i++) {
+        os_memblock_put(&ble_audio_svc_bass_metadata_pool, 
rcv_state->params.subgroups[i].metadata);
+    }
+
+    ble_audio_bsnk_destroy(rcv_state->bsnk);
+
+    memset(rcv_state, 0, sizeof(struct ble_svc_audio_bass_receiver_state));
+    rcv_state->source_id = BLE_SVC_AUDIO_BASS_RECEIVE_STATE_SRC_ID_NONE;
+
+    return ble_svc_audio_bass_receive_state_notify(rcv_state);
+}
+
+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)
+{
+    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_HS_ENOENT;
+    }
+
+    if (handler->expected_len != EXPECTED_LEN_VARIABLE &&
+        handler->expected_len != ctxt->om->om_len - 1) {
+        return BLE_HS_EINVAL;
+    }
+
+    return handler->handler_cb(&ctxt->om->om_data[1], NULL);
+}
+
+static enum ble_svc_audio_bass_big_enc
+ble_svc_audio_bass_bsnk_enc_state_to_big_enc(enum ble_audio_bsnk_enc_state 
enc_state)
+{
+    switch (enc_state) {
+    case BLE_AUDIO_BSNK_ENC_NONE:
+        return BLE_SVC_AUDIO_BASS_BIG_ENC_NOT_ENCRYPTED;
+    case BLE_AUDIO_BSNK_ENC_PENDING:
+        return BLE_SVC_AUDIO_BASS_BIG_ENC_BROADCAST_CODE_REQ;
+    case BLE_AUDIO_BSNK_ENC_ACTIVE:
+        return BLE_SVC_AUDIO_BASS_BIG_ENC_DECRYPTING;
+    case BLE_AUDIO_BSNK_ENC_FAILED_CODE_MISSING:
+        /* TODO: Check */
+        return BLE_SVC_AUDIO_BASS_BIG_ENC_BROADCAST_CODE_REQ;
+    case BLE_AUDIO_BSNK_ENC_FAILED_CODE_INVALID:
+        return BLE_SVC_AUDIO_BASS_BIG_ENC_BAD_CODE;
+    default:
+        return BLE_SVC_AUDIO_BASS_BIG_ENC_NOT_ENCRYPTED;
+    }
+}
+static int
+ble_svc_audio_bass_rcv_state_read_access(struct ble_gatt_access_ctxt *ctxt, 
void *arg)
+{
+    struct ble_svc_audio_bass_receiver_state *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->params.source_addr.type, 1);
+    os_mbuf_append(ctxt->om, &state->params.source_addr.val, 6);
+    os_mbuf_append(ctxt->om, &state->params.source_adv_sid, 1);
+    buf = os_mbuf_extend(ctxt->om, 3);
+    if (buf == NULL) {
+        return BLE_ATT_ERR_INSUFFICIENT_RES;
+    }
+
+    put_le24(buf, state->params.broadcast_id);
+    os_mbuf_append(ctxt->om, state->params.pa_sync_state != 
BLE_AUDIO_BSNK_PA_SYNC_TRANSFER_TIMEOUT ?
+                   &state->params.pa_sync_state : BLE_AUDIO_BSNK_PA_SYNC_NONE, 
1);
+    os_mbuf_append(ctxt->om, &state->params.big_encryption, 1);
+
+    if (state->params.big_encryption == BLE_SVC_AUDIO_BASS_BIG_ENC_BAD_CODE) {
+        os_mbuf_append(ctxt->om, &state->params.bad_code, 
BLE_AUDIO_BROADCAST_CODE_SIZE);
+    }
+
+    os_mbuf_append(ctxt->om, &state->params.num_subgroups, 1);
+
+    for (i = 0; i < state->params.num_subgroups; i++) {
+        buf = os_mbuf_extend(ctxt->om, 4);
+        if (buf == NULL) {
+            return BLE_ATT_ERR_INSUFFICIENT_RES;
+        }
+
+        put_le32(buf, state->params.subgroups[i].bis_sync_state);
+        os_mbuf_append(ctxt->om, &state->params.subgroups[i].metadata_length, 
1);
+        os_mbuf_append(ctxt->om, state->params.subgroups[i].metadata,
+                       state->params.subgroups[i].metadata_length);
+    }
+
+    return 0;
+}
+
+int
+ble_svc_audio_bass_receive_state_find_free(struct 
ble_svc_audio_bass_receiver_state **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
+handle_bsnk_pa_sync_state_changed(struct 
ble_audio_event_bsnk_pa_sync_state_changed *ev)
+{
+    struct ble_svc_audio_bass_receiver_state *state;
+    int i;
+
+    assert(ev->snk != NULL);
+
+    ble_svc_audio_bass_receive_state_find_by_sink(&state, ev->snk);
+    if (state == NULL) {
+        return;
+    }
+
+    switch (ev->state) {
+    case BLE_AUDIO_BSNK_PA_SYNC_NONE:
+        state->params.pa_sync_state = 
BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_NOT_SYNCED;
+    case BLE_AUDIO_BSNK_PA_SYNC_ACTIVE:
+        state->params.pa_sync_state = BLE_SVC_AUDIO_BASS_PA_SYNC_STATE_SYNCED;
+
+        for (i = 0; i < state->params.num_subgroups; i++) {

Review Comment:
   We are synced; save state, do not sync again



-- 
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