summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.dentz@indt.org.br>2008-08-29 18:14:39 -0300
committerLuiz Augusto von Dentz <luiz.dentz@indt.org.br>2008-08-29 18:14:39 -0300
commit75c562d773e5fe37f4257631318d7f918edc5b53 (patch)
tree1c66fc1385b06866294ca846515a5b591bc35fb8
parent92dcfff75cea59c9e4c65ab2b1d45730a9076a6a (diff)
Make DiscoverDevices to create discover sessions.
-rw-r--r--doc/adapter-api.txt15
-rw-r--r--src/adapter.c492
-rw-r--r--src/adapter.h10
-rw-r--r--src/dbus-hci.c175
-rw-r--r--src/main.c12
-rw-r--r--src/main.conf4
6 files changed, 271 insertions, 437 deletions
diff --git a/doc/adapter-api.txt b/doc/adapter-api.txt
index 4e7e36ba..ca6c2fd8 100644
--- a/doc/adapter-api.txt
+++ b/doc/adapter-api.txt
@@ -218,16 +218,6 @@ Signals PropertyChanged(string name, variant value)
This signal indicates a changed value of the given
property.
- DiscoveryStarted()
-
- This signal indicates that a device discovery
- procedure has been started.
-
- DiscoveryCompleted()
-
- This signal indicates that a device discovery
- procedure has been completed.
-
DeviceFound(string address, dict values)
This signal will be send every time an inquiry result
@@ -278,7 +268,6 @@ Properties string Address [readonly]
The default value for the discoverable timeout should
be 180 seconds (3 minutes).
- boolean PeriodicDiscovery [readwrite]
+ boolean Discovering [readonly]
- Is peridoic inquiry active or not. Changing this
- property will either enable or disable it.
+ Indicates that a device discovery procedure is active.
diff --git a/src/adapter.c b/src/adapter.c
index f52cc671..a16d1a4b 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -79,12 +79,13 @@ struct record_list {
const gchar *addr;
};
-struct mode_req {
+struct session_req {
struct adapter *adapter;
DBusConnection *conn; /* Connection reference */
DBusMessage *msg; /* Message reference */
- uint8_t mode; /* Requested mode */
guint id; /* Listener id */
+ uint8_t mode; /* Requested mode */
+ int refcount; /* Session refcount */
};
struct service_auth {
@@ -504,7 +505,7 @@ static DBusMessage *set_mode(DBusConnection *conn, DBusMessage *msg,
adapter->discov_timeout_id = 0;
}
- if (!adapter->sessions && !adapter->discov_timeout)
+ if (!adapter->mode_sessions && !adapter->discov_timeout)
adapter_set_discov_timeout(adapter,
adapter->discov_timeout * 1000);
}
@@ -520,17 +521,75 @@ done:
return dbus_message_new_method_return(msg);
}
-static gint find_session(struct mode_req *req, DBusMessage *msg)
+static struct session_req *find_session(GSList *list, DBusMessage *msg)
{
- const char *name = dbus_message_get_sender(req->msg);
+ GSList *l;
const char *sender = dbus_message_get_sender(msg);
- return strcmp(name, sender);
+ for (l = list; l; l = l->next) {
+ struct session_req *req = l->data;
+ const char *name = dbus_message_get_sender(req->msg);
+
+ if (g_str_equal(name, sender))
+ return req;
+ }
+
+ return NULL;
+}
+
+static void session_free(struct session_req *req)
+{
+ struct adapter *adapter = req->adapter;
+
+ if (req->mode)
+ adapter->mode_sessions = g_slist_remove(adapter->mode_sessions,
+ req);
+ else
+ adapter->disc_sessions = g_slist_remove(adapter->disc_sessions,
+ req);
+
+ dbus_message_unref(req->msg);
+ dbus_connection_unref(req->conn);
+ g_free(req);
+}
+
+static void session_unref(struct session_req *req)
+{
+ req->refcount--;
+
+ if (req->refcount)
+ return;
+
+ if (req->id)
+ g_dbus_remove_watch(req->conn, req->id);
+
+ session_free(req);
+}
+
+static struct session_req *create_session(struct adapter *adapter,
+ DBusConnection *conn, DBusMessage *msg,
+ uint8_t mode, GDBusWatchFunction cb)
+{
+ struct session_req *req;
+
+ req = g_new0(struct session_req, 1);
+ req->adapter = adapter;
+ req->conn = dbus_connection_ref(conn);
+ req->msg = dbus_message_ref(msg);
+ req->mode = mode;
+ req->refcount = 1;
+
+ if (cb)
+ req->id = g_dbus_add_disconnect_watch(conn,
+ dbus_message_get_sender(msg),
+ cb, req, NULL);
+
+ return req;
}
static void confirm_mode_cb(struct agent *agent, DBusError *err, void *data)
{
- struct mode_req *req = data;
+ struct session_req *req = data;
DBusMessage *reply;
if (err && dbus_error_is_set(err)) {
@@ -544,42 +603,34 @@ static void confirm_mode_cb(struct agent *agent, DBusError *err, void *data)
dbus_connection_send(req->conn, reply, NULL);
dbus_message_unref(reply);
- if (!g_slist_find_custom(req->adapter->sessions, req->msg,
- (GCompareFunc) find_session))
+ if (!find_session(req->adapter->mode_sessions, req->msg))
goto cleanup;
return;
cleanup:
- dbus_message_unref(req->msg);
- if (req->id)
- g_dbus_remove_watch(req->conn, req->id);
- dbus_connection_unref(req->conn);
- g_free(req);
+ session_free(req);
}
static DBusMessage *confirm_mode(DBusConnection *conn, DBusMessage *msg,
const char *mode, void *data)
{
struct adapter *adapter = data;
- struct mode_req *req;
+ struct session_req *req;
int ret;
+ uint8_t umode;
if (!adapter->agent)
return dbus_message_new_method_return(msg);
- req = g_new0(struct mode_req, 1);
- req->adapter = adapter;
- req->conn = dbus_connection_ref(conn);
- req->msg = dbus_message_ref(msg);
- req->mode = str2mode(adapter->address, mode);
+ umode = str2mode(adapter->address, mode);
+
+ req = create_session(adapter, conn, msg, umode, NULL);
ret = agent_confirm_mode_change(adapter->agent, mode, confirm_mode_cb,
req);
if (ret < 0) {
- dbus_connection_unref(req->conn);
- dbus_message_unref(req->msg);
- g_free(req);
+ session_free(req);
return invalid_args(msg);
}
@@ -1158,47 +1209,92 @@ static DBusMessage *create_bonding(DBusConnection *conn, DBusMessage *msg,
return NULL;
}
-static void periodic_discover_req_exit(void *user_data)
+static void discover_req_exit(void *user_data)
{
- struct adapter *adapter = user_data;
+ struct session_req *req = user_data;
+ struct adapter *adapter = req->adapter;
- debug("PeriodicDiscovery requestor exited");
+ info("Discovery session %d deactivated", g_slist_length(adapter->disc_sessions));
+
+ adapter->disc_sessions = g_slist_remove(adapter->disc_sessions, req);
+ req->id = 0;
+ session_free(req);
+
+ if (adapter->disc_sessions)
+ return;
/* Cleanup the discovered devices list and send the cmd to exit from
* periodic inquiry or cancel remote name request. The return value can
* be ignored. */
- cancel_periodic_discovery(adapter);
+ if (adapter->state & STD_INQUIRY)
+ cancel_discovery(adapter);
+ else
+ cancel_periodic_discovery(adapter);
}
-static DBusMessage *adapter_start_periodic(DBusConnection *conn,
- DBusMessage *msg, void *data)
+int start_inquiry(struct adapter *adapter)
{
- periodic_inquiry_cp cp;
+ inquiry_cp cp;
+ evt_cmd_status rp;
struct hci_request rq;
- struct adapter *adapter = data;
uint8_t lap[3] = { 0x33, 0x8b, 0x9e };
- uint8_t status;
- int dd;
+ int dd, err;
- if (!adapter->up)
- return adapter_not_ready(msg);
+ pending_remote_name_cancel(adapter);
- if (dbus_message_is_method_call(msg, ADAPTER_INTERFACE,
- "StartPeriodicDiscovery")) {
- if (!dbus_message_has_signature(msg,
- DBUS_TYPE_INVALID_AS_STRING))
- return invalid_args(msg);
+ dd = hci_open_dev(adapter->dev_id);
+ if (dd < 0)
+ return dd;
+
+ memset(&cp, 0, sizeof(cp));
+ memcpy(&cp.lap, lap, 3);
+ cp.length = 0x08;
+ cp.num_rsp = 0x00;
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_LINK_CTL;
+ rq.ocf = OCF_INQUIRY;
+ rq.cparam = &cp;
+ rq.clen = INQUIRY_CP_SIZE;
+ rq.rparam = &rp;
+ rq.rlen = EVT_CMD_STATUS_SIZE;
+ rq.event = EVT_CMD_STATUS;
+
+ if (hci_send_req(dd, &rq, 500) < 0) {
+ err = errno;
+ error("Unable to start inquiry: %s (%d)",
+ strerror(err), err);
+ hci_close_dev(dd);
+ return -err;
}
- if ((adapter->state & STD_INQUIRY) || (adapter->state & PERIODIC_INQUIRY))
- return in_progress(msg, "Discover in progress");
+ if (rp.status) {
+ err = bt_error(rp.status);
+ error("HCI_Inquiry command failed with status 0x%02x",
+ rp.status);
+ hci_close_dev(dd);
+ return -err;
+ }
- pending_remote_name_cancel(adapter);
+ hci_close_dev(dd);
+
+ adapter->state |= RESOLVE_NAME;
+
+ return 0;
+}
+
+static int start_periodic_inquiry(struct adapter *adapter)
+{
+ periodic_inquiry_cp cp;
+ struct hci_request rq;
+ uint8_t lap[3] = { 0x33, 0x8b, 0x9e };
+ uint8_t status;
+ int dd, err;
dd = hci_open_dev(adapter->dev_id);
if (dd < 0)
- return no_such_adapter(msg);
+ return dd;
memset(&cp, 0, sizeof(cp));
memcpy(&cp.lap, lap, 3);
@@ -1217,143 +1313,61 @@ static DBusMessage *adapter_start_periodic(DBusConnection *conn,
rq.event = EVT_CMD_COMPLETE;
if (hci_send_req(dd, &rq, 1000) < 0) {
- int err = errno;
+ err = errno;
error("Unable to start periodic inquiry: %s (%d)",
- strerror(errno), errno);
+ strerror(err), err);
hci_close_dev(dd);
- return failed_strerror(msg, err);
+ return -err;
}
if (status) {
+ err = bt_error(status);
error("HCI_Periodic_Inquiry_Mode failed with status 0x%02x",
status);
hci_close_dev(dd);
- return failed_strerror(msg, bt_error(status));
+ return -err;
}
- adapter->pdiscov_requestor = g_strdup(dbus_message_get_sender(msg));
-
hci_close_dev(dd);
- /* track the request owner to cancel it automatically if the owner
- * exits */
- adapter->pdiscov_listener = g_dbus_add_disconnect_watch(conn,
- dbus_message_get_sender(msg),
- periodic_discover_req_exit,
- adapter, NULL);
+ adapter->state |= RESOLVE_NAME;
- return dbus_message_new_method_return(msg);
+ return 0;
}
-static DBusMessage *adapter_stop_periodic(DBusConnection *conn,
+static DBusMessage *adapter_discover_devices(DBusConnection *conn,
DBusMessage *msg, void *data)
{
+ struct session_req *req;
struct adapter *adapter = data;
int err;
if (!adapter->up)
return adapter_not_ready(msg);
- if (!(adapter->state & PERIODIC_INQUIRY))
- return g_dbus_create_error(msg,
- ERROR_INTERFACE ".NotAuthorized",
- "Not authorized");
- /*
- * Cleanup the discovered devices list and send the cmd to exit
- * from periodic inquiry mode or cancel remote name request.
- */
- err = cancel_periodic_discovery(adapter);
- if (err < 0) {
- if (err == -ENODEV)
- return no_such_adapter(msg);
-
- else
- return failed_strerror(msg, -err);
+ req = find_session(adapter->disc_sessions, msg);
+ if (req) {
+ req->refcount++;
+ return dbus_message_new_method_return(msg);
}
- return dbus_message_new_method_return(msg);
-}
-
-static void discover_devices_req_exit(void *user_data)
-{
- struct adapter *adapter = user_data;
-
- debug("DiscoverDevices requestor exited");
-
- /* Cleanup the discovered devices list and send the command to cancel
- * inquiry or cancel remote name request. The return can be ignored. */
- cancel_discovery(adapter);
-}
-
-static DBusMessage *adapter_discover_devices(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- inquiry_cp cp;
- evt_cmd_status rp;
- struct hci_request rq;
- struct adapter *adapter = data;
- uint8_t lap[3] = { 0x33, 0x8b, 0x9e };
- int dd;
-
- if (!adapter->up)
- return adapter_not_ready(msg);
-
- if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING))
- return invalid_args(msg);
-
- if (adapter->state & STD_INQUIRY)
- return in_progress(msg, "Discover in progress");
-
- pending_remote_name_cancel(adapter);
-
- if (adapter->bonding)
- return in_progress(msg, "Bonding in progress");
-
- dd = hci_open_dev(adapter->dev_id);
- if (dd < 0)
- return no_such_adapter(msg);
-
- memset(&cp, 0, sizeof(cp));
- memcpy(&cp.lap, lap, 3);
- cp.length = 0x08;
- cp.num_rsp = 0x00;
-
- memset(&rq, 0, sizeof(rq));
- rq.ogf = OGF_LINK_CTL;
- rq.ocf = OCF_INQUIRY;
- rq.cparam = &cp;
- rq.clen = INQUIRY_CP_SIZE;
- rq.rparam = &rp;
- rq.rlen = EVT_CMD_STATUS_SIZE;
- rq.event = EVT_CMD_STATUS;
-
- if (hci_send_req(dd, &rq, 500) < 0) {
- int err = errno;
- error("Unable to start inquiry: %s (%d)",
- strerror(errno), errno);
- hci_close_dev(dd);
- return failed_strerror(msg, err);
- }
+ if ((adapter->state & STD_INQUIRY) || (adapter->state & PERIODIC_INQUIRY))
+ goto done;
- if (rp.status) {
- error("HCI_Inquiry command failed with status 0x%02x",
- rp.status);
- hci_close_dev(dd);
- return failed_strerror(msg, bt_error(rp.status));
- }
+ if (default_device.inqmode)
+ err = start_inquiry(adapter);
+ else
+ err = start_periodic_inquiry(adapter);
- adapter->state |= (STD_INQUIRY | RESOLVE_NAME);
+ if (err < 0)
+ return failed_strerror(msg, -err);
- adapter->discov_requestor = g_strdup(dbus_message_get_sender(msg));
+done:
+ req = create_session(adapter, conn, msg, 0, discover_req_exit);
- hci_close_dev(dd);
+ adapter->disc_sessions = g_slist_append(adapter->disc_sessions, req);
- /* track the request owner to cancel it automatically if the owner
- * exits */
- adapter->discov_listener = g_dbus_add_disconnect_watch(conn,
- dbus_message_get_sender(msg),
- discover_devices_req_exit,
- adapter, NULL);
+ info("Discovery session %d activated", g_slist_length(adapter->disc_sessions));
return dbus_message_new_method_return(msg);
}
@@ -1362,42 +1376,45 @@ static DBusMessage *adapter_cancel_discovery(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct adapter *adapter = data;
- int err;
+ struct session_req *req;
+ int err = 0;
if (!adapter->up)
return adapter_not_ready(msg);
- if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING))
- return invalid_args(msg);
+ req = find_session(adapter->disc_sessions, msg);
+ if (!req)
+ return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
+ "Invalid discovery session");
- /* is there discover pending? or discovery cancel was requested
- * previously */
- if (!(adapter->state & STD_INQUIRY) || adapter->discovery_cancel)
- return g_dbus_create_error(msg,
- ERROR_INTERFACE ".NotAuthorized",
- "Not Authorized");
+ session_unref(req);
+ if (adapter->disc_sessions)
+ return dbus_message_new_method_return(msg);
- /* only the discover requestor can cancel the inquiry process */
- if (!adapter->discov_requestor ||
- strcmp(adapter->discov_requestor, dbus_message_get_sender(msg)))
+ /*
+ * Cleanup the discovered devices list and send the cmd to exit
+ * from periodic inquiry mode or cancel remote name request.
+ */
+ if (adapter->state & STD_INQUIRY)
+ err = cancel_discovery(adapter);
+ else if (adapter->state & PERIODIC_INQUIRY)
+ err = cancel_periodic_discovery(adapter);
+ else if (adapter->scheduler_id)
+ g_source_remove(adapter->scheduler_id);
+ else
return g_dbus_create_error(msg,
ERROR_INTERFACE ".NotAuthorized",
- "Not Authorized");
+ "Not authorized");
- /* Cleanup the discovered devices list and send the cmd to cancel
- * inquiry or cancel remote name request */
- err = cancel_discovery(adapter);
if (err < 0) {
if (err == -ENODEV)
return no_such_adapter(msg);
+
else
return failed_strerror(msg, -err);
}
- /* Reply before send DiscoveryCompleted */
- adapter->discovery_cancel = dbus_message_ref(msg);
-
- return NULL;
+ return dbus_message_new_method_return(msg);
}
struct remote_device_list_t {
@@ -1455,10 +1472,13 @@ static DBusMessage *get_properties(DBusConnection *conn,
dbus_message_iter_append_dict_entry(&dict, "DiscoverableTimeout",
DBUS_TYPE_UINT32, &adapter->discov_timeout);
- discov_active = (adapter->state & PERIODIC_INQUIRY) ? TRUE:FALSE;
+ if (adapter->state & PERIODIC_INQUIRY || adapter->state & STD_INQUIRY)
+ discov_active = TRUE;
+ else
+ discov_active = FALSE;
/* PeriodicDiscovery */
- dbus_message_iter_append_dict_entry(&dict, "PeriodicDiscovery",
+ dbus_message_iter_append_dict_entry(&dict, "Discovering",
DBUS_TYPE_BOOLEAN, &discov_active);
dbus_message_iter_close_container(&iter, &dict);
@@ -1503,17 +1523,6 @@ static DBusMessage *set_property(DBusConnection *conn,
dbus_message_iter_get_basic(&sub, &timeout);
return set_discoverable_timeout(conn, msg, timeout, data);
- } else if (g_str_equal("PeriodicDiscovery", property)) {
- dbus_bool_t value;
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
- return invalid_args(msg);
- dbus_message_iter_get_basic(&sub, &value);
-
- if (value)
- return adapter_start_periodic(conn, msg, data);
- else
- return adapter_stop_periodic(conn, msg, data);
} else if (g_str_equal("Mode", property)) {
const char *mode;
@@ -1527,7 +1536,7 @@ static DBusMessage *set_property(DBusConnection *conn,
if (adapter->global_mode == adapter->mode)
return dbus_message_new_method_return(msg);
- if (adapter->sessions && adapter->global_mode < adapter->mode)
+ if (adapter->mode_sessions && adapter->global_mode < adapter->mode)
return confirm_mode(conn, msg, mode, data);
return set_mode(conn, msg, str2mode(adapter->address, mode),
@@ -1539,20 +1548,17 @@ static DBusMessage *set_property(DBusConnection *conn,
static void session_exit(void *data)
{
- struct mode_req *req = data;
+ struct session_req *req = data;
struct adapter *adapter = req->adapter;
- adapter->sessions = g_slist_remove(adapter->sessions, req);
-
- if (!adapter->sessions) {
+ if (!adapter->mode_sessions) {
debug("Falling back to '%s' mode", mode2str(adapter->global_mode));
/* FIXME: fallback to previous mode
set_mode(req->conn, req->msg, adapter->global_mode, adapter);
*/
}
- dbus_connection_unref(req->conn);
- dbus_message_unref(req->msg);
- g_free(req);
+
+ session_unref(req);
}
static DBusMessage *request_mode(DBusConnection *conn,
@@ -1560,7 +1566,7 @@ static DBusMessage *request_mode(DBusConnection *conn,
{
const char *mode;
struct adapter *adapter = data;
- struct mode_req *req;
+ struct session_req *req;
uint8_t new_mode;
int ret;
@@ -1576,23 +1582,16 @@ static DBusMessage *request_mode(DBusConnection *conn,
return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
"No agent registered");
- if (g_slist_find_custom(adapter->sessions, msg,
- (GCompareFunc) find_session))
+ req = find_session(adapter->mode_sessions, msg);
+ if (req)
return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
"Mode already requested");
- req = g_new0(struct mode_req, 1);
- req->adapter = adapter;
- req->conn = dbus_connection_ref(conn);
- req->msg = dbus_message_ref(msg);
- req->mode = new_mode;
- req->id = g_dbus_add_disconnect_watch(conn,
- dbus_message_get_sender(msg),
- session_exit, req, NULL);
+ req = create_session(adapter, conn, msg, new_mode, session_exit);
- if (!adapter->sessions)
+ if (!adapter->mode_sessions)
adapter->global_mode = adapter->mode;
- adapter->sessions = g_slist_append(adapter->sessions, req);
+ adapter->mode_sessions = g_slist_append(adapter->mode_sessions, req);
/* No need to change mode */
if (adapter->mode >= new_mode)
@@ -1601,10 +1600,7 @@ static DBusMessage *request_mode(DBusConnection *conn,
ret = agent_confirm_mode_change(adapter->agent, mode, confirm_mode_cb,
req);
if (ret < 0) {
- dbus_message_unref(req->msg);
- g_dbus_remove_watch(req->conn, req->id);
- dbus_connection_unref(req->conn);
- g_free(req);
+ session_free(req);
return invalid_args(msg);
}
@@ -1615,15 +1611,14 @@ static DBusMessage *release_mode(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct adapter *adapter = data;
- GSList *l;
+ struct session_req *req;
- l = g_slist_find_custom(adapter->sessions, msg,
- (GCompareFunc) find_session);
- if (!l)
+ req = find_session(adapter->mode_sessions, msg);
+ if (!req)
return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
"No Mode to release");
- session_exit(l->data);
+ session_exit(req);
return dbus_message_new_method_return(msg);
}
@@ -1997,8 +1992,6 @@ static GDBusMethodTable adapter_methods[] = {
};
static GDBusSignalTable adapter_signals[] = {
- { "DiscoveryStarted", "" },
- { "DiscoveryCompleted", "" },
{ "DeviceCreated", "o" },
{ "DeviceRemoved", "o" },
{ "DeviceFound", "sa{sv}" },
@@ -2419,30 +2412,15 @@ static void reply_pending_requests(struct adapter *adapter)
adapter->bonding = NULL;
}
- /* If there is a pending reply for discovery cancel */
- if (adapter->discovery_cancel) {
- reply = dbus_message_new_method_return(adapter->discovery_cancel);
- dbus_connection_send(connection, reply, NULL);
- dbus_message_unref(reply);
- dbus_message_unref(adapter->discovery_cancel);
- adapter->discovery_cancel = NULL;
- }
-
if (adapter->state & STD_INQUIRY) {
- /* Send discovery completed signal if there isn't name
- * to resolve */
- g_dbus_emit_signal(connection, adapter->path,
- ADAPTER_INTERFACE, "DiscoveryCompleted",
- DBUS_TYPE_INVALID);
-
/* Cancel inquiry initiated by D-Bus client */
- if (adapter->discov_requestor)
+ if (adapter->disc_sessions)
cancel_discovery(adapter);
}
if (adapter->state & PERIODIC_INQUIRY) {
/* Stop periodic inquiry initiated by D-Bus client */
- if (adapter->pdiscov_requestor)
+ if (adapter->disc_sessions)
cancel_periodic_discovery(adapter);
}
}
@@ -2472,18 +2450,11 @@ int adapter_stop(struct adapter *adapter)
/* check pending requests */
reply_pending_requests(adapter);
- if (adapter->discov_requestor) {
- g_dbus_remove_watch(connection, adapter->discov_listener);
- adapter->discov_listener = 0;
- g_free(adapter->discov_requestor);
- adapter->discov_requestor = NULL;
- }
-
- if (adapter->pdiscov_requestor) {
- g_dbus_remove_watch(connection, adapter->pdiscov_listener);
- adapter->pdiscov_listener = 0;
- g_free(adapter->pdiscov_requestor);
- adapter->pdiscov_requestor = NULL;
+ if (adapter->disc_sessions) {
+ g_slist_foreach(adapter->disc_sessions, (GFunc) session_free,
+ NULL);
+ g_slist_free(adapter->disc_sessions);
+ adapter->disc_sessions = NULL;
}
if (adapter->found_devices) {
@@ -2761,24 +2732,33 @@ uint8_t adapter_get_mode(struct adapter *adapter)
void adapter_set_state(struct adapter *adapter, int state)
{
- if (!adapter)
- return;
+ gboolean discov_active = FALSE;
+ const char *path = adapter->path;
- /* Both Standard and periodic Inquiry are in progress */
- if ((state & STD_INQUIRY) && (state & PERIODIC_INQUIRY))
- goto set;
+ if (adapter->state == state)
+ return;
- if (!adapter->found_devices)
- goto set;
+ if (state & PERIODIC_INQUIRY || state & STD_INQUIRY) {
+ discov_active = TRUE;
+ if (adapter->scheduler_id)
+ goto done;
+ } else if (adapter->disc_sessions && adapter->state & STD_INQUIRY) {
+ adapter->scheduler_id = g_timeout_add(default_device.inqmode * 1000,
+ (GSourceFunc) start_inquiry, adapter);
+ goto done;
+ }
- /* Free list if standard/periodic inquiry is done */
- if ((adapter->state & (STD_INQUIRY | PERIODIC_INQUIRY)) &&
- (state & (~STD_INQUIRY | ~PERIODIC_INQUIRY))) {
+ if (!discov_active && adapter->found_devices) {
g_slist_foreach(adapter->found_devices, (GFunc) g_free, NULL);
g_slist_free(adapter->found_devices);
adapter->found_devices = NULL;
}
-set:
+
+ dbus_connection_emit_property_changed(connection, path,
+ ADAPTER_INTERFACE, "Discovering",
+ DBUS_TYPE_BOOLEAN, &discov_active);
+
+done:
adapter->state = state;
}
diff --git a/src/adapter.h b/src/adapter.h
index e5432b66..a5e76bc3 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -104,11 +104,7 @@ struct adapter {
uint8_t global_mode; /* last valid global mode */
int state; /* standard inq, periodic inq, name resloving */
GSList *found_devices;
- GSList *oor_devices; /* out of range device list */
- char *pdiscov_requestor; /* periodic discovery requestor unique name */
- guint pdiscov_listener;
- char *discov_requestor; /* discovery requestor unique name */
- guint discov_listener;
+ GSList *oor_devices; /* out of range device list */
DBusMessage *discovery_cancel; /* discovery cancel message request */
GSList *passkey_agents;
struct agent *agent; /* For the new API */
@@ -117,7 +113,9 @@ struct adapter {
GSList *auth_reqs; /* Received and replied HCI
authentication requests */
GSList *devices; /* Devices structure pointers */
- GSList *sessions; /* Request Mode sessions */
+ GSList *mode_sessions; /* Request Mode sessions */
+ GSList *disc_sessions; /* Discovery sessions */
+ guint scheduler_id; /* Scheduler handle */
struct hci_dev dev; /* hci info */
};
diff --git a/src/dbus-hci.c b/src/dbus-hci.c
index 70b15062..e67cb64c 100644
--- a/src/dbus-hci.c
+++ b/src/dbus-hci.c
@@ -710,8 +710,6 @@ cleanup:
void hcid_dbus_inquiry_start(bdaddr_t *local)
{
struct adapter *adapter;
- const gchar *path;
- gboolean discov_active;
int state;
adapter = manager_find_adapter(local);
@@ -731,22 +729,11 @@ void hcid_dbus_inquiry_start(bdaddr_t *local)
pending_remote_name_cancel(adapter);
/* Disable name resolution for non D-Bus clients */
- if (!adapter->discov_requestor) {
+ if (!adapter->disc_sessions) {
state = adapter_get_state(adapter);
state &= ~RESOLVE_NAME;
adapter_set_state(adapter, state);
}
- path = adapter_get_path(adapter);
-
- discov_active = (adapter_get_state(adapter) & STD_INQUIRY) ? TRUE : FALSE;
-
- dbus_connection_emit_property_changed(connection, path,
- ADAPTER_INTERFACE, "PeriodicDiscovery",
- DBUS_TYPE_BOOLEAN, &discov_active);
-
- g_dbus_emit_signal(connection, path,
- ADAPTER_INTERFACE, "DiscoveryStarted",
- DBUS_TYPE_INVALID);
}
static int found_device_req_name(struct adapter *adapter)
@@ -835,15 +822,13 @@ void hcid_dbus_inquiry_complete(bdaddr_t *local)
if ((adapter_get_state(adapter) & PERIODIC_INQUIRY) &&
!(adapter_get_state(adapter) & STD_INQUIRY))
adapter_update_oor_devices(adapter);
- /*
- * Enable resolution again: standard inquiry can be
- * received in the periodic inquiry idle state.
- */
- if (adapter->pdiscov_requestor) {
- state = adapter_get_state(adapter);
- state |= RESOLVE_NAME;
- adapter_set_state(adapter, state);
- }
+
+ /* reset the discover type to be able to handle D-Bus and non D-Bus
+ * requests */
+ state = adapter_get_state(adapter);
+ state &= ~STD_INQUIRY;
+ adapter_set_state(adapter, state);
+
/*
* The following scenarios can happen:
* 1. standard inquiry: always send discovery completed signal
@@ -855,48 +840,12 @@ void hcid_dbus_inquiry_complete(bdaddr_t *local)
*
* Keep in mind that non D-Bus requests can arrive.
*/
-
- if (!found_device_req_name(adapter))
- return; /* skip - there is name to resolve */
-
- if (adapter_get_state(adapter) & STD_INQUIRY) {
- g_dbus_emit_signal(connection, path,
- ADAPTER_INTERFACE, "DiscoveryCompleted",
- DBUS_TYPE_INVALID);
-
- state = adapter_get_state(adapter);
- state &= ~STD_INQUIRY;
- adapter_set_state(adapter, state);
- }
-
- if (adapter->discov_requestor) {
- g_dbus_remove_watch(connection, adapter->discov_listener);
- adapter->discov_listener = 0;
- g_free(adapter->discov_requestor);
- adapter->discov_requestor = NULL;
-
- /* If there is a pending reply for discovery cancel */
- if (adapter->discovery_cancel) {
- DBusMessage *reply;
- reply = dbus_message_new_method_return(adapter->discovery_cancel);
- dbus_connection_send(connection, reply, NULL);
- dbus_message_unref(reply);
- dbus_message_unref(adapter->discovery_cancel);
- adapter->discovery_cancel = NULL;
- }
-
- /* reset the discover type for standard inquiry only */
- state = adapter_get_state(adapter);
- state &= ~STD_INQUIRY;
- adapter_set_state(adapter, state);
- }
+ found_device_req_name(adapter);
}
void hcid_dbus_periodic_inquiry_start(bdaddr_t *local, uint8_t status)
{
struct adapter *adapter;
- const gchar *path;
- gboolean discov_active;
int state;
/* Don't send the signal if the cmd failed */
@@ -912,28 +861,11 @@ void hcid_dbus_periodic_inquiry_start(bdaddr_t *local, uint8_t status)
state = adapter_get_state(adapter);
state |= PERIODIC_INQUIRY;
adapter_set_state(adapter, state);
-
- /* Disable name resolution for non D-Bus clients */
- if (!adapter->pdiscov_requestor) {
- state = adapter_get_state(adapter);
- state &= ~RESOLVE_NAME;
- adapter_set_state(adapter, state);
- }
-
- path = adapter_get_path(adapter);
-
- discov_active = (adapter_get_state(adapter) & PERIODIC_INQUIRY) ? TRUE:FALSE;
-
- dbus_connection_emit_property_changed(connection, path,
- ADAPTER_INTERFACE, "PeriodicDiscovery",
- DBUS_TYPE_BOOLEAN, &discov_active);
}
void hcid_dbus_periodic_inquiry_exit(bdaddr_t *local, uint8_t status)
{
struct adapter *adapter;
- const gchar *path;
- gboolean discov_active;
int state;
/* Don't send the signal if the cmd failed */
@@ -949,41 +881,13 @@ void hcid_dbus_periodic_inquiry_exit(bdaddr_t *local, uint8_t status)
/* reset the discover type to be able to handle D-Bus and non D-Bus
* requests */
state = adapter_get_state(adapter);
- state &= ~(PERIODIC_INQUIRY | RESOLVE_NAME);
+ state &= ~PERIODIC_INQUIRY;
adapter_set_state(adapter, state);
/* free out of range devices list */
g_slist_foreach(adapter->oor_devices, (GFunc) free, NULL);
g_slist_free(adapter->oor_devices);
adapter->oor_devices = NULL;
-
- if (adapter->pdiscov_requestor) {
- g_dbus_remove_watch(connection, adapter->pdiscov_listener);
- adapter->pdiscov_listener = 0;
- g_free(adapter->pdiscov_requestor);
- adapter->pdiscov_requestor = NULL;
- }
-
- path = adapter_get_path(adapter);
-
- /* workaround: inquiry completed is not sent when exiting from
- * periodic inquiry */
- if (adapter_get_state(adapter) & STD_INQUIRY) {
- g_dbus_emit_signal(connection, path,
- ADAPTER_INTERFACE, "DiscoveryCompleted",
- DBUS_TYPE_INVALID);
-
- state = adapter_get_state(adapter);
- state &= ~STD_INQUIRY;
- adapter_set_state(adapter, state);
- }
-
- discov_active = (adapter_get_state(adapter) & STD_INQUIRY) ? TRUE : FALSE;
-
- /* Send discovery completed signal if there isn't name to resolve */
- dbus_connection_emit_property_changed(connection, path,
- ADAPTER_INTERFACE, "PeriodicDiscovery",
- DBUS_TYPE_BOOLEAN, &discov_active);
}
static char *extract_eir_name(uint8_t *data, uint8_t *type)
@@ -1203,8 +1107,6 @@ void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status,
char peer_addr[18];
const char *paddr = peer_addr;
const gchar *dev_path;
- const gchar *path;
- int state;
adapter = manager_find_adapter(local);
if (!adapter) {
@@ -1232,44 +1134,7 @@ void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status,
adapter_remove_found_device(adapter, peer);
/* check if there is more devices to request names */
- if (!found_device_req_name(adapter))
- return; /* skip if a new request has been sent */
-
- /* The discovery completed signal must be sent only for discover
- * devices request WITH name resolving */
- if (adapter->discov_requestor) {
- g_dbus_remove_watch(connection, adapter->discov_listener);
- adapter->discov_listener = 0;
- g_free(adapter->discov_requestor);
- adapter->discov_requestor = NULL;
-
- /* If there is a pending reply for discovery cancel */
- if (adapter->discovery_cancel) {
- DBusMessage *reply;
- reply = dbus_message_new_method_return(adapter->discovery_cancel);
- dbus_connection_send(connection, reply, NULL);
- dbus_message_unref(reply);
- dbus_message_unref(adapter->discovery_cancel);
- adapter->discovery_cancel = NULL;
- }
-
- /* Disable name resolution for non D-Bus clients */
- if (!adapter->pdiscov_requestor) {
- state = adapter_get_state(adapter);
- state &= ~RESOLVE_NAME;
- adapter_set_state(adapter, state);
- }
- }
- path = adapter_get_path(adapter);
-
- if (adapter_get_state(adapter) & STD_INQUIRY) {
- g_dbus_emit_signal(connection, path,
- ADAPTER_INTERFACE, "DiscoveryCompleted",
- DBUS_TYPE_INVALID);
- state = adapter_get_state(adapter);
- state &= ~STD_INQUIRY;
- adapter_set_state(adapter, state);
- }
+ found_device_req_name(adapter);
}
void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle,
@@ -1778,16 +1643,10 @@ int cancel_discovery(struct adapter *adapter)
struct remote_dev_info *dev, match;
int dd, err = 0;
uint16_t dev_id = adapter_get_dev_id(adapter);
- int state;
-
- if (!(adapter_get_state(adapter) & STD_INQUIRY))
- goto cleanup;
dd = hci_open_dev(dev_id);
- if (dd < 0) {
- err = -ENODEV;
- goto cleanup;
- }
+ if (dd < 0)
+ return -ENODEV;
/*
* If there is a pending read remote name request means
@@ -1814,14 +1673,6 @@ int cancel_discovery(struct adapter *adapter)
hci_close_dev(dd);
-cleanup:
- /* Disable name resolution for non D-Bus clients */
- if (!adapter->pdiscov_requestor) {
- state = adapter_get_state(adapter);
- state &= ~RESOLVE_NAME;
- adapter_set_state(adapter, state);
- }
-
return err;
}
diff --git a/src/main.c b/src/main.c
index 64f91870..cf8f0e4a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -169,6 +169,18 @@ static void parse_config(GKeyFile *config)
g_free(str);
}
+ val = g_key_file_get_integer(config, "General",
+ "DiscoverSchedulerInterval",
+ &err);
+ if (err) {
+ debug("%s", err->message);
+ g_error_free(err);
+ err = NULL;
+ } else {
+ debug("inqmode=%d", val);
+ default_device.inqmode = val;
+ }
+
default_device.link_mode = HCI_LM_ACCEPT;
default_device.flags |= (1 << HCID_SET_LM);
diff --git a/src/main.conf b/src/main.conf
index 306dc7c9..16d04579 100644
--- a/src/main.conf
+++ b/src/main.conf
@@ -24,3 +24,7 @@ PageTimeout = 8192
# Behaviour for Adapter.SetProperty("mode", "off")
# Possible values: "DevDown", "NoScan" (default)
OffMode = NoScan
+
+# Discover scheduler interval used in Adapter.DiscoverDevices
+# The value is in seconds. Defaults is 0 to use controller scheduler
+DiscoverSchedulerInterval = 0