/* When the iterator reaches the end, it is NULL and attempt is 0 */
};
+struct exp_pending {
+ struct btd_adapter *adapter;
+ unsigned int id;
+};
+
enum {
ADAPTER_POWER_STATE_OFF,
ADAPTER_POWER_STATE_ON,
#endif
bool is_default; /* true if adapter is default one */
+ struct queue *exp_pending;
struct queue *exps;
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
bool le_2m_phy_supported;
adapter->discovery_list = NULL;
}
+static void cancel_exp_pending(void *data)
+{
+ struct exp_pending *pending = data;
+ struct btd_adapter *adapter = pending->adapter;
+
+ pending->adapter = NULL;
+ mgmt_cancel(adapter->mgmt, pending->id);
+ g_free(pending);
+}
+
static void adapter_free(gpointer user_data)
{
struct btd_adapter *adapter = user_data;
g_queue_free(adapter->auths);
queue_destroy(adapter->exps, NULL);
+ queue_destroy(adapter->exp_pending, cancel_exp_pending);
+
/*
* Unregister all handlers for this specific index since
* the adapter bound to them is no longer valid.
adapter->auths = g_queue_new();
adapter->exps = queue_new();
+ adapter->exp_pending = queue_new();
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
#ifdef TIZEN_FEATURE_BLUEZ_BATTERY_WATCH
g_slist_free(adapter->msd_callbacks);
adapter->msd_callbacks = NULL;
+
+ queue_remove_all(adapter->exp_pending, NULL, NULL, cancel_exp_pending);
}
const char *adapter_get_path(struct btd_adapter *adapter)
.func = _func, \
}
+static void exp_complete(void *user_data);
+
+static bool exp_mgmt_send(struct btd_adapter *adapter, uint16_t opcode,
+ uint16_t index, uint16_t length, const void *param,
+ mgmt_request_func_t callback)
+{
+ struct exp_pending *pending;
+
+ pending = g_new0(struct exp_pending, 1);
+ pending->adapter = adapter;
+
+ if (!queue_push_tail(adapter->exp_pending, pending)) {
+ g_free(pending);
+ return false;
+ }
+
+ pending->id = mgmt_send(adapter->mgmt, opcode, index, length, param,
+ callback, pending, exp_complete);
+ if (!pending->id) {
+ queue_remove(adapter->exp_pending, pending);
+ g_free(pending);
+ return false;
+ }
+
+ return true;
+}
+
static void set_exp_debug_complete(uint8_t status, uint16_t len,
const void *param, void *user_data)
{
- struct btd_adapter *adapter = user_data;
+ struct exp_pending *pending = user_data;
+ struct btd_adapter *adapter = pending->adapter;
uint8_t action;
if (status != 0) {
memcpy(cp.uuid, debug_uuid.val, 16);
cp.action = action;
- if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE,
+ if (exp_mgmt_send(adapter, MGMT_OP_SET_EXP_FEATURE,
adapter->dev_id, sizeof(cp), &cp,
- set_exp_debug_complete, adapter, NULL) > 0)
+ set_exp_debug_complete))
return;
btd_error(adapter->dev_id, "Failed to set exp debug");
static void set_rpa_resolution_complete(uint8_t status, uint16_t len,
const void *param, void *user_data)
{
- struct btd_adapter *adapter = user_data;
+ struct exp_pending *pending = user_data;
+ struct btd_adapter *adapter = pending->adapter;
uint8_t action;
if (status != 0) {
memcpy(cp.uuid, rpa_resolution_uuid.val, 16);
cp.action = action;
- if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE,
+ if (exp_mgmt_send(adapter, MGMT_OP_SET_EXP_FEATURE,
adapter->dev_id, sizeof(cp), &cp,
- set_rpa_resolution_complete, adapter, NULL) > 0)
+ set_rpa_resolution_complete))
return;
btd_error(adapter->dev_id, "Failed to set RPA Resolution");
static void codec_offload_complete(uint8_t status, uint16_t len,
const void *param, void *user_data)
{
- struct btd_adapter *adapter = user_data;
+ struct exp_pending *pending = user_data;
+ struct btd_adapter *adapter = pending->adapter;
uint8_t action;
if (status != 0) {
memcpy(cp.uuid, codec_offload_uuid.val, 16);
cp.action = action;
- if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE,
+ if (exp_mgmt_send(adapter, MGMT_OP_SET_EXP_FEATURE,
adapter->dev_id, sizeof(cp), &cp,
- codec_offload_complete, adapter, NULL) > 0)
+ codec_offload_complete))
return;
btd_error(adapter->dev_id, "Failed to set Codec Offload");
static void iso_socket_complete(uint8_t status, uint16_t len,
const void *param, void *user_data)
{
- struct btd_adapter *adapter = user_data;
+ struct exp_pending *pending = user_data;
+ struct btd_adapter *adapter = pending->adapter;
uint8_t action;
if (status != 0) {
memcpy(cp.uuid, iso_socket_uuid.val, 16);
cp.action = action;
- if (mgmt_send(adapter->mgmt, MGMT_OP_SET_EXP_FEATURE,
+ if (exp_mgmt_send(adapter, MGMT_OP_SET_EXP_FEATURE,
MGMT_INDEX_NONE, sizeof(cp), &cp,
- iso_socket_complete, adapter, NULL) > 0)
+ iso_socket_complete))
return;
btd_error(adapter->dev_id, "Failed to set ISO Socket");
static void read_exp_features_complete(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
- struct btd_adapter *adapter = user_data;
+ struct exp_pending *pending = user_data;
+ struct btd_adapter *adapter = pending->adapter;
const struct mgmt_rp_read_exp_features_info *rp = param;
size_t feature_count = 0;
size_t i = 0;
static void read_exp_features(struct btd_adapter *adapter)
{
- if (mgmt_send(adapter->mgmt, MGMT_OP_READ_EXP_FEATURES_INFO,
- adapter->dev_id, 0, NULL, read_exp_features_complete,
- adapter, NULL) > 0)
+ if (exp_mgmt_send(adapter, MGMT_OP_READ_EXP_FEATURES_INFO,
+ adapter->dev_id, 0, NULL, read_exp_features_complete))
return;
btd_error(adapter->dev_id, "Failed to read exp features info");
error("Failed to reset Adv Monitors");
}
+static void read_info(struct btd_adapter *adapter)
+{
+ DBG("sending read info command for index %u", adapter->dev_id);
+
+ if (mgmt_send(mgmt_primary, MGMT_OP_READ_INFO, adapter->dev_id, 0, NULL,
+ read_info_complete, adapter, NULL) > 0)
+ return;
+
+ btd_error(adapter->dev_id,
+ "Failed to read controller info for index %u",
+ adapter->dev_id);
+
+ adapter_list = g_list_remove(adapter_list, adapter);
+
+ btd_adapter_unref(adapter);
+}
+
+static void exp_complete(void *user_data)
+{
+ struct exp_pending *pending = user_data;
+ struct btd_adapter *adapter = pending->adapter;
+
+ if (!adapter)
+ return; /* canceled */
+
+ queue_remove(adapter->exp_pending, pending);
+ g_free(pending);
+
+ if (queue_isempty(adapter->exp_pending)) {
+ read_info(adapter);
+ return;
+ }
+
+ DBG("index %u has %u pending MGMT EXP requests", adapter->dev_id,
+ queue_length(adapter->exp_pending));
+}
+
static void index_added(uint16_t index, uint16_t length, const void *param,
void *user_data)
{
*/
adapter_list = g_list_append(adapter_list, adapter);
- DBG("sending read info command for index %u", index);
-
- if (mgmt_send(mgmt_primary, MGMT_OP_READ_INFO, index, 0, NULL,
- read_info_complete, adapter, NULL) > 0)
- return;
-
- btd_error(adapter->dev_id,
- "Failed to read controller info for index %u", index);
-
- adapter_list = g_list_remove(adapter_list, adapter);
-
- btd_adapter_unref(adapter);
+ if (queue_isempty(adapter->exp_pending))
+ read_info(adapter);
}
static void index_removed(uint16_t index, uint16_t length, const void *param,