@@ -451,24 +451,24 @@ static int asha_source_accept(struct btd_service *service)
ba2str(device_get_address(device), addr);
DBG("Accepting ASHA connection on %s", addr);
if (!asha_dev) {
/* Can this actually happen? */
DBG("Not handling ASHA profile");
return -1;
}
- if (!bt_asha_probe(asha_dev->asha, db, client))
+ if (!bt_asha_probe(asha_dev->asha, db, client,
+ (bt_asha_probe_cb_t) asha_source_endpoint_register, asha_dev)) {
return -1;
-
- asha_source_endpoint_register(asha_dev);
+ }
btd_service_connecting_complete(service, 0);
return 0;
}
static int asha_source_disconnect(struct btd_service *service)
{
struct btd_device *device = btd_service_get_device(service);
struct bt_asha_device *asha_dev = btd_service_get_user_data(service);
@@ -168,20 +168,24 @@ void bt_asha_reset(struct bt_asha *asha)
asha->status_notify_id);
}
gatt_db_unref(asha->db);
asha->db = NULL;
bt_gatt_client_unref(asha->client);
asha->client = NULL;
asha->psm = 0;
+ memset(asha->hisyncid, 0, sizeof(asha->hisyncid));
+
+ asha->probe_cb = NULL;
+ asha->probe_cb_data = NULL;
update_asha_set(asha, false);
}
void bt_asha_state_reset(struct bt_asha *asha)
{
asha->state = ASHA_STOPPED;
asha->cb = NULL;
asha->cb_user_data = NULL;
@@ -326,41 +330,59 @@ bool bt_asha_set_volume(struct bt_asha *asha, int8_t volume)
static bool uuid_cmp(const char *uuid1, const bt_uuid_t *uuid2)
{
bt_uuid_t lhs;
bt_string_to_uuid(&lhs, uuid1);
return bt_uuid_cmp(&lhs, uuid2) == 0;
}
+static void check_probe_done(struct bt_asha *asha)
+{
+ uint8_t zeroes[8] = { 0, };
+
+ /* Once we have ROPs & PSM, we should be good to go */
+ if (asha->psm == 0 ||
+ memcmp(asha->hisyncid, zeroes, sizeof(zeroes) == 0))
+ return;
+
+ if (asha->probe_cb) {
+ asha->probe_cb(asha->probe_cb_data);
+ asha->probe_cb = NULL;
+ asha->probe_cb_data = NULL;
+ }
+}
+
static void read_psm(bool success,
uint8_t att_ecode,
const uint8_t *value,
uint16_t length,
void *user_data)
{
struct bt_asha *asha = user_data;
if (!success) {
DBG("Reading PSM failed with ATT error: %u", att_ecode);
return;
}
if (length != 2) {
DBG("Reading PSM failed: unexpected length %u", length);
return;
}
asha->psm = get_le16(value);
DBG("Got PSM: %u", asha->psm);
+
+ check_probe_done(asha);
}
static void read_rops(bool success,
uint8_t att_ecode,
const uint8_t *value,
uint16_t length,
void *user_data)
{
struct bt_asha *asha = user_data;
@@ -391,20 +413,22 @@ static void read_rops(bool success,
asha->render_delay = get_le16(&value[11]);
/* byte 13 & 14 are reserved */
/* Codec IDs */
asha->codec_ids = get_le16(&value[15]);
DBG("Got ROPS: side %u, binaural %u, csis: %u, delay %u, codecs: %u",
asha->right_side, asha->binaural, asha->csis_supported,
asha->render_delay, asha->codec_ids);
update_asha_set(asha, true);
+
+ check_probe_done(asha);
}
static void audio_status_register(uint16_t att_ecode, void *user_data)
{
if (att_ecode)
DBG("AudioStatusPoint register failed 0x%04x", att_ecode);
else
DBG("AudioStatusPoint register succeeded");
}
@@ -493,27 +517,31 @@ static void foreach_asha_service(struct gatt_db_attribute *attr,
struct bt_asha *asha = user_data;
DBG("Found ASHA GATT service");
asha->attr = attr;
gatt_db_service_set_claimed(attr, true);
gatt_db_service_foreach_char(asha->attr, handle_characteristic, asha);
}
bool bt_asha_probe(struct bt_asha *asha, struct gatt_db *db,
- struct bt_gatt_client *client)
+ struct bt_gatt_client *client, bt_asha_probe_cb_t probe_cb,
+ void *cb_user_data)
{
bt_uuid_t asha_uuid;
asha->db = gatt_db_ref(db);
asha->client = bt_gatt_client_clone(client);
+ asha->probe_cb = probe_cb;
+ asha->probe_cb_data = cb_user_data;
+
bt_uuid16_create(&asha_uuid, ASHA_SERVICE);
gatt_db_foreach_service(db, &asha_uuid, foreach_asha_service, asha);
if (!asha->attr) {
error("ASHA attribute not found");
bt_asha_reset(asha);
return false;
}
if (!asha_devices)
@@ -16,54 +16,59 @@
#include <stdint.h>
enum bt_asha_state_t {
ASHA_STOPPED = 0,
ASHA_STARTING,
ASHA_STARTED,
ASHA_STOPPING,
};
typedef void (*bt_asha_cb_t)(int status, void *data);
+typedef void (*bt_asha_probe_cb_t)(void *data);
struct bt_asha {
struct bt_gatt_client *client;
struct gatt_db *db;
struct gatt_db_attribute *attr;
uint16_t acp_handle;
uint16_t volume_handle;
unsigned int status_notify_id;
uint16_t psm;
bool right_side;
bool binaural;
bool csis_supported;
bool coc_streaming_supported;
uint8_t hisyncid[8];
uint16_t render_delay;
uint16_t codec_ids;
int8_t volume;
enum bt_asha_state_t state;
bt_asha_cb_t cb;
void *cb_user_data;
+
+ bt_asha_probe_cb_t probe_cb;
+ void *probe_cb_data;
};
struct bt_asha_set {
uint8_t hisyncid[8];
struct bt_asha *left;
struct bt_asha *right;
};
struct bt_asha *bt_asha_new(void);
void bt_asha_reset(struct bt_asha *asha);
void bt_asha_state_reset(struct bt_asha *asha);
void bt_asha_free(struct bt_asha *asha);
unsigned int bt_asha_start(struct bt_asha *asha, bt_asha_cb_t cb,
void *user_data);
unsigned int bt_asha_stop(struct bt_asha *asha, bt_asha_cb_t cb,
void *user_data);
bool bt_asha_set_volume(struct bt_asha *asha, int8_t volume);
bool bt_asha_probe(struct bt_asha *asha, struct gatt_db *db,
- struct bt_gatt_client *client);
+ struct bt_gatt_client *client, bt_asha_probe_cb_t probe_cb,
+ void *cb_user_data);
From: Arun Raghavan <arun@asymptotic.io> Let's get the PSM and read-only properties before we expose the device and transport. --- profiles/audio/asha.c | 6 +++--- src/shared/asha.c | 30 +++++++++++++++++++++++++++++- src/shared/asha.h | 7 ++++++- 3 files changed, 38 insertions(+), 5 deletions(-)