The BASS Broadcast Audio Scan Control Point characteristic defines a number of commands that require socket operations, which should be handled inside the BASS plugin. This commit adds shared/bass APIs to register control point handlers with bt_bass. The BASS plugin will use these APIs to register a control point callback to handle each operation based on opcode and parameters. --- src/shared/bass.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++ src/shared/bass.h | 9 +++++++ 2 files changed, 77 insertions(+) diff --git a/src/shared/bass.c b/src/shared/bass.c index 636eb24fd..635fe1054 100644 --- a/src/shared/bass.c +++ b/src/shared/bass.c @@ -66,12 +66,20 @@ struct bt_bass { void *debug_data; struct queue *src_cbs; + struct queue *cp_handlers; unsigned int disconn_id; void *user_data; }; +struct bt_bass_cp_handler { + unsigned int id; + bt_bass_cp_handler_func_t handler; + bt_bass_destroy_func_t destroy; + void *data; +}; + /* BASS subgroup field of the Broadcast * Receive State characteristic */ @@ -134,6 +142,64 @@ static void bass_debug(struct bt_bass *bass, const char *format, ...) va_end(ap); } +unsigned int bt_bass_cp_handler_register(struct bt_bass *bass, + bt_bass_cp_handler_func_t handler, + bt_bass_destroy_func_t destroy, + void *user_data) +{ + struct bt_bass_cp_handler *cb; + static unsigned int id; + + if (!bass) + return 0; + + cb = new0(struct bt_bass_cp_handler, 1); + cb->id = ++id ? id : ++id; + cb->handler = handler; + cb->destroy = destroy; + cb->data = user_data; + + queue_push_tail(bass->cp_handlers, cb); + + return cb->id; +} + +static void bass_cp_handler_free(void *data) +{ + struct bt_bass_cp_handler *cb = data; + + if (cb->destroy) + cb->destroy(cb->data); + + free(cb); +} + +static bool match_cb_id(const void *data, const void *match_data) +{ + const struct bt_bass_cp_handler *cb = data; + unsigned int id = PTR_TO_UINT(match_data); + + return (cb->id == id); +} + +bool bt_bass_cp_handler_unregister(struct bt_bass *bass, + unsigned int id) +{ + struct bt_bass_cp_handler *cb; + + if (!bass) + return false; + + cb = queue_remove_if(bass->cp_handlers, match_cb_id, + UINT_TO_PTR(id)); + if (!cb) + return false; + + bass_cp_handler_free(cb); + + return true; +} + unsigned int bt_bass_src_register(struct bt_bass *bass, bt_bass_src_func_t cb, void *user_data, bt_bass_destroy_func_t destroy) { @@ -1418,6 +1484,7 @@ static void bass_free(void *data) bass_db_free(bass->rdb); queue_destroy(bass->notify, NULL); queue_destroy(bass->src_cbs, bass_src_changed_free); + queue_destroy(bass->cp_handlers, bass_cp_handler_free); free(bass); } @@ -1513,6 +1580,7 @@ struct bt_bass *bt_bass_new(struct gatt_db *ldb, struct gatt_db *rdb, bass->ldb = db; bass->notify = queue_new(); bass->src_cbs = queue_new(); + bass->cp_handlers = queue_new(); if (!rdb) goto done; diff --git a/src/shared/bass.h b/src/shared/bass.h index 086fe335e..2ca659cca 100644 --- a/src/shared/bass.h +++ b/src/shared/bass.h @@ -99,6 +99,9 @@ typedef void (*bt_bass_debug_func_t)(const char *str, void *user_data); typedef void (*bt_bass_src_func_t)(uint8_t id, uint32_t bid, uint8_t enc, uint32_t bis_sync, void *user_data); +typedef int (*bt_bass_cp_handler_func_t)(struct bt_bcast_src *bcast_src, + uint8_t op, void *params, void *user_data); + struct bt_att *bt_bass_get_att(struct bt_bass *bass); struct bt_gatt_client *bt_bass_get_client(struct bt_bass *bass); unsigned int bt_bass_register(bt_bass_func_t attached, bt_bass_func_t detached, @@ -120,3 +123,9 @@ int bt_bass_send(struct bt_bass *bass, unsigned int bt_bass_src_register(struct bt_bass *bass, bt_bass_src_func_t cb, void *user_data, bt_bass_destroy_func_t destroy); bool bt_bass_src_unregister(struct bt_bass *bass, unsigned int id); +unsigned int bt_bass_cp_handler_register(struct bt_bass *bass, + bt_bass_cp_handler_func_t handler, + bt_bass_destroy_func_t destroy, + void *user_data); +bool bt_bass_cp_handler_unregister(struct bt_bass *bass, + unsigned int id); -- 2.39.2