From 9c03b30330d7b483b307c0077b3f5d676d166073 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 29 Nov 2008 21:15:19 +0200 Subject: Fix/cleanup set_mode() and its usage --- src/adapter.c | 156 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 91 insertions(+), 65 deletions(-) diff --git a/src/adapter.c b/src/adapter.c index b92688d6..aafc1f76 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -597,37 +597,35 @@ static void adapter_set_discov_timeout(struct btd_adapter *adapter, adapter); } -static DBusMessage *set_mode(DBusConnection *conn, DBusMessage *msg, - uint8_t new_mode, void *data) +static uint8_t mode2scan(uint8_t mode) { - struct btd_adapter *adapter = data; - uint8_t scan_enable; - uint8_t current_scan = adapter->scan_mode; - gboolean limited; - int err, dd; - const char *mode; - - switch (new_mode) { + switch (mode) { case MODE_OFF: - scan_enable = SCAN_DISABLED; - break; + return SCAN_DISABLED; case MODE_CONNECTABLE: - scan_enable = SCAN_PAGE; - break; + return SCAN_PAGE; case MODE_DISCOVERABLE: case MODE_LIMITED: - scan_enable = (SCAN_PAGE | SCAN_INQUIRY); - break; + return (SCAN_PAGE | SCAN_INQUIRY); default: - return invalid_args(msg); + error("Invalid mode given to mode2scan: %u", mode); + return SCAN_PAGE; } +} + +static int set_mode(struct btd_adapter *adapter, uint8_t new_mode) +{ + uint8_t scan_enable; + uint8_t current_scan = adapter->scan_mode; + gboolean limited; + int err, dd; + const char *modestr; - /* Do reverse resolution in case of "on" mode */ - mode = mode2str(new_mode); + scan_enable = mode2scan(new_mode); dd = hci_open_dev(adapter->dev_id); if (dd < 0) - return no_such_adapter(msg); + return -EIO; if (!adapter->up && (main_opts.offmode == HCID_OFFMODE_NOSCAN || @@ -643,7 +641,7 @@ static DBusMessage *set_mode(DBusConnection *conn, DBusMessage *msg, adapter->dev_id, strerror(errno), errno); hci_close_dev(dd); - return failed_strerror(msg, err); + return -err; } } @@ -651,7 +649,7 @@ static DBusMessage *set_mode(DBusConnection *conn, DBusMessage *msg, main_opts.offmode == HCID_OFFMODE_DEVDOWN) { if (ioctl(dd, HCIDEVDOWN, adapter->dev_id) < 0) { hci_close_dev(dd); - return failed_strerror(msg, errno); + return -err; } goto done; @@ -661,7 +659,7 @@ static DBusMessage *set_mode(DBusConnection *conn, DBusMessage *msg, err = set_limited_discoverable(dd, adapter->dev.class, limited); if (err < 0) { hci_close_dev(dd); - return failed_strerror(msg, -err); + return err; } if (current_scan != scan_enable) { @@ -682,14 +680,14 @@ static DBusMessage *set_mode(DBusConnection *conn, DBusMessage *msg, error("Sending write scan enable command failed: %s (%d)", strerror(errno), errno); hci_close_dev(dd); - return failed_strerror(msg, err); + return -err; } if (status) { error("Setting scan enable failed with status 0x%02x", status); hci_close_dev(dd); - return failed_strerror(msg, bt_error(status)); + return -EIO; } } else { /* discoverable or limited */ @@ -705,13 +703,15 @@ static DBusMessage *set_mode(DBusConnection *conn, DBusMessage *msg, } } done: - write_device_mode(&adapter->bdaddr, mode); + modestr = mode2str(new_mode); + + write_device_mode(&adapter->bdaddr, modestr); hci_close_dev(dd); adapter->mode = new_mode; - return dbus_message_new_method_return(msg); + return 0; } static DBusMessage *set_powered(DBusConnection *conn, DBusMessage *msg, @@ -719,24 +719,28 @@ static DBusMessage *set_powered(DBusConnection *conn, DBusMessage *msg, { struct btd_adapter *adapter = data; uint8_t mode; + int err; mode = powered ? get_mode(&adapter->bdaddr, "on") : MODE_OFF; if (mode == adapter->mode) return dbus_message_new_method_return(msg); - return set_mode(conn, msg, mode, data); + err = set_mode(adapter, mode); + if (err < 0) + return failed_strerror(msg, -err); + + return dbus_message_new_method_return(msg); } static DBusMessage *set_discoverable(DBusConnection *conn, DBusMessage *msg, gboolean discoverable, void *data) { struct btd_adapter *adapter = data; - const char *strmode; uint8_t mode; + int err; - strmode = discoverable ? "discoverable" : "connectable"; - mode = get_mode(&adapter->bdaddr, strmode); + mode = discoverable ? MODE_DISCOVERABLE : MODE_CONNECTABLE; if (mode == MODE_DISCOVERABLE && adapter->pairable) mode = MODE_LIMITED; @@ -744,13 +748,19 @@ static DBusMessage *set_discoverable(DBusConnection *conn, DBusMessage *msg, if (mode == adapter->mode) return dbus_message_new_method_return(msg); - return set_mode(conn, msg, mode, data); + err = set_mode(adapter, mode); + if (err < 0) + return failed_strerror(msg, -err); + + return dbus_message_new_method_return(msg); } static DBusMessage *set_pairable(DBusConnection *conn, DBusMessage *msg, gboolean pairable, void *data) { struct btd_adapter *adapter = data; + uint8_t mode; + int err; if (pairable == adapter->pairable) goto done; @@ -767,10 +777,14 @@ static DBusMessage *set_pairable(DBusConnection *conn, DBusMessage *msg, adapter_set_pairable_timeout(adapter, adapter->pairable_timeout); - if (adapter->scan_mode & SCAN_INQUIRY) { - uint8_t mode = pairable ? MODE_LIMITED : MODE_DISCOVERABLE; - return set_mode(conn, msg, mode, data); - } + if (!(adapter->scan_mode & SCAN_INQUIRY)) + goto done; + + mode = pairable ? MODE_LIMITED : MODE_DISCOVERABLE; + + err = set_mode(adapter, mode); + if (err < 0 && msg) + return failed_strerror(msg, -err); done: return msg ? dbus_message_new_method_return(msg) : NULL; @@ -815,29 +829,41 @@ static struct session_req *find_session(GSList *list, DBusMessage *msg) return NULL; } +static uint8_t get_needed_mode(struct btd_adapter *adapter, uint8_t mode) +{ + GSList *l; + + if (adapter->global_mode > mode) + mode = adapter->global_mode; + + for (l = adapter->mode_sessions; l; l = l->next) { + struct session_req *req = l->data; + + if (req->mode > mode) + mode = req->mode; + } + + return mode; +} + static void session_remove(struct session_req *req) { struct btd_adapter *adapter = req->adapter; if (req->mode) { - GSList *l; - uint8_t mode = adapter->global_mode; + uint8_t mode; adapter->mode_sessions = g_slist_remove(adapter->mode_sessions, req); - for (l = adapter->mode_sessions; l; l = l->next) { - struct session_req *req = l->data; - - if (req->mode > mode) - mode = req->mode; - } + mode = get_needed_mode(adapter, adapter->global_mode); if (mode == adapter->mode) return; debug("Switching to '%s' mode", mode2str(mode)); - set_mode(req->conn, req->msg, mode, adapter); + + set_mode(adapter, mode); } else { adapter->disc_sessions = g_slist_remove(adapter->disc_sessions, req); @@ -926,27 +952,30 @@ static struct session_req *create_session(struct btd_adapter *adapter, return session_ref(req); } -static void confirm_mode_cb(struct agent *agent, DBusError *err, void *data) +static void confirm_mode_cb(struct agent *agent, DBusError *derr, void *data) { struct session_req *req = data; + int err; DBusMessage *reply; - if (err && dbus_error_is_set(err)) { - reply = dbus_message_new_error(req->msg, err->name, err->message); + if (derr && dbus_error_is_set(derr)) { + reply = dbus_message_new_error(req->msg, derr->name, + derr->message); g_dbus_send_message(req->conn, reply); - goto cleanup; + session_unref(req); + return; } - reply = set_mode(req->conn, req->msg, req->mode, req->adapter); + err = set_mode(req->adapter, req->mode); + if (err < 0) + reply = failed_strerror(req->msg, -err); + else + reply = dbus_message_new_method_return(req->msg); + g_dbus_send_message(req->conn, reply); if (!find_session(req->adapter->mode_sessions, req->msg)) - goto cleanup; - - return; - -cleanup: - session_unref(req); + session_unref(req); } static DBusMessage *set_discoverable_timeout(DBusConnection *conn, @@ -1903,7 +1932,7 @@ static DBusMessage *request_session(DBusConnection *conn, if (!adapter->agent) return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", - "No agent registered"); + "No agent registered"); if (!adapter->mode_sessions) adapter->global_mode = adapter->mode; @@ -1911,17 +1940,14 @@ static DBusMessage *request_session(DBusConnection *conn, new_mode = get_mode(&adapter->bdaddr, "on"); req = find_session(adapter->mode_sessions, msg); - if (!req) { + if (req) { + session_ref(req); + return dbus_message_new_method_return(msg); + } else { req = create_session(adapter, conn, msg, new_mode, session_owner_exit); adapter->mode_sessions = g_slist_append(adapter->mode_sessions, req); - } else { - req->mode = new_mode; - adapter->mode_sessions = g_slist_append(adapter->mode_sessions, - req); - session_remove(req); - return dbus_message_new_method_return(msg); } /* No need to change mode */ @@ -1932,7 +1958,7 @@ static DBusMessage *request_session(DBusConnection *conn, confirm_mode_cb, req); if (ret < 0) { session_unref(req); - return invalid_args(msg); + return failed_strerror(msg, -ret); } return NULL; -- cgit