static DBusConnection *connection = NULL;
-static enum connman_service_type technology_type;
-static connman_bool_t technology_enabled;
-static DBusMessage *technology_pending = NULL;
-static guint technology_timeout = 0;
-
-static void technology_reply(int error)
-{
- DBG("");
-
- if (technology_timeout > 0) {
- g_source_remove(technology_timeout);
- technology_timeout = 0;
- }
-
- if (technology_pending != NULL) {
- if (error > 0) {
- DBusMessage *reply;
-
- reply = __connman_error_failed(technology_pending,
- error);
- if (reply != NULL)
- g_dbus_send_message(connection, reply);
- } else
- g_dbus_send_reply(connection, technology_pending,
- DBUS_TYPE_INVALID);
-
- dbus_message_unref(technology_pending);
- technology_pending = NULL;
- }
-
- technology_type = CONNMAN_SERVICE_TYPE_UNKNOWN;
-}
-
-static gboolean technology_abort(gpointer user_data)
-{
- DBG("");
-
- technology_timeout = 0;
-
- technology_reply(ETIMEDOUT);
-
- return FALSE;
-}
-
-static void technology_notify(enum connman_service_type type,
- connman_bool_t enabled)
-{
- DBG("type %d enabled %d", type, enabled);
-
- if (type == technology_type && enabled == technology_enabled)
- technology_reply(0);
-}
-
static void session_mode_notify(void)
{
DBusMessage *reply;
static struct connman_notifier technology_notifier = {
.name = "manager",
.priority = CONNMAN_NOTIFIER_PRIORITY_HIGH,
- .service_enabled= technology_notify,
.idle_state = idle_state,
};
{
enum connman_service_type type;
const char *str;
- int err;
DBG("conn %p", conn);
- if (technology_pending != NULL)
- return __connman_error_in_progress(msg);
-
dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &str,
DBUS_TYPE_INVALID);
if (__connman_notifier_is_enabled(type) == TRUE)
return __connman_error_already_enabled(msg);
- technology_type = type;
- technology_enabled = TRUE;
- technology_pending = dbus_message_ref(msg);
-
- err = __connman_technology_enable(type);
- if (err < 0)
- technology_reply(-err);
- else
- technology_timeout = g_timeout_add_seconds(15,
- technology_abort, NULL);
+ __connman_technology_enable(type, msg);
return NULL;
}
{
enum connman_service_type type;
const char *str;
- int err;
DBG("conn %p", conn);
- if (technology_pending != NULL)
- return __connman_error_in_progress(msg);
-
dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &str,
DBUS_TYPE_INVALID);
if (__connman_notifier_is_enabled(type) == FALSE)
return __connman_error_already_disabled(msg);
- technology_type = type;
- technology_enabled = FALSE;
- technology_pending = dbus_message_ref(msg);
-
- err = __connman_technology_disable(type);
- if (err < 0)
- technology_reply(-err);
- else
- technology_timeout = g_timeout_add_seconds(10,
- technology_abort, NULL);
+ __connman_technology_disable(type, msg);
return NULL;
}
{
DBG("");
- connman_notifier_unregister(&technology_notifier);
-
if (connection == NULL)
return;
+ connman_notifier_unregister(&technology_notifier);
+
g_dbus_unregister_interface(connection, CONNMAN_MANAGER_PATH,
CONNMAN_MANAGER_INTERFACE);
struct connman_technology_driver *driver;
void *driver_data;
+
+ DBusMessage *pending_reply;
+ guint pending_timeout;
};
static GSList *driver_list = NULL;
NULL, free_rfkill);
technology->device_list = NULL;
+ technology->pending_reply = NULL;
technology->state = CONNMAN_TECHNOLOGY_STATE_OFFLINE;
if (g_dbus_register_interface(connection, technology->path,
return 0;
}
+static gboolean technology_pending_reply(gpointer user_data)
+{
+ struct connman_technology *technology = user_data;
+ DBusMessage *reply;
+
+ /* Power request timedout, send ETIMEDOUT. */
+ if (technology->pending_reply != NULL) {
+ reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
+ if (reply != NULL)
+ g_dbus_send_message(connection, reply);
+
+ dbus_message_unref(technology->pending_reply);
+ technology->pending_reply = NULL;
+ technology->pending_timeout = 0;
+ }
+
+ return FALSE;
+}
+
int __connman_technology_enabled(enum connman_service_type type)
{
struct connman_technology *technology;
__connman_profile_save_default();
}
+ if (technology->pending_reply != NULL) {
+ g_dbus_send_reply(connection, technology->pending_reply, DBUS_TYPE_INVALID);
+ dbus_message_unref(technology->pending_reply);
+ technology->pending_reply = NULL;
+ technology->pending_timeout = 0;
+ }
+
return 0;
}
-int __connman_technology_enable(enum connman_service_type type)
+int __connman_technology_enable(enum connman_service_type type, DBusMessage *msg)
{
struct connman_technology *technology;
GSList *list;
- int err;
+ int err = 0;
int ret = -ENODEV;
+ DBusMessage *reply;
DBG("type %d enable", type);
technology = technology_find(type);
- if (technology == NULL)
- return -ENXIO;
+ if (technology == NULL) {
+ err = -ENXIO;
+ goto done;
+ }
+
+ if (technology->pending_reply != NULL) {
+ err = -EBUSY;
+ goto done;
+ }
+
+ if (msg != NULL)
+ technology->pending_reply = dbus_message_ref(msg);
for (list = technology->device_list; list; list = list->next) {
struct connman_device *device = list->data;
err = __connman_device_enable_persistent(device);
/*
* err = 0 : Device was enabled right away.
- * err = -EINPROGRESS : DBus call was successful.
* If atleast one device gets enabled, we consider
* the technology to be enabled.
*/
- if (err == 0 || err == -EINPROGRESS)
+ if (err == 0)
ret = 0;
}
- return ret;
+done:
+ if (ret == 0)
+ return ret;
+
+ if (msg != NULL) {
+ if (err == -EINPROGRESS)
+ technology->pending_timeout = g_timeout_add_seconds(10,
+ technology_pending_reply, technology);
+ else {
+ reply = __connman_error_failed(msg, -err);
+ if (reply != NULL)
+ g_dbus_send_message(connection, reply);
+ }
+ }
+
+ return err;
}
int __connman_technology_disabled(enum connman_service_type type)
if (technology == NULL)
return -ENXIO;
+ if (technology->pending_reply != NULL) {
+ g_dbus_send_reply(connection, technology->pending_reply, DBUS_TYPE_INVALID);
+ dbus_message_unref(technology->pending_reply);
+ technology->pending_reply = NULL;
+ }
+
if (g_atomic_int_dec_and_test(&technology->enabled) == TRUE) {
__connman_notifier_disable(type);
return 0;
}
-int __connman_technology_disable(enum connman_service_type type)
+int __connman_technology_disable(enum connman_service_type type, DBusMessage *msg)
{
struct connman_technology *technology;
GSList *list;
- int err;
+ int err = 0;
int ret = -ENODEV;
+ DBusMessage *reply;
DBG("type %d disable", type);
technology = technology_find(type);
- if (technology == NULL)
- return -ENXIO;
+ if (technology == NULL) {
+ err = -ENXIO;
+ goto done;
+ }
+
+ if (technology->pending_reply != NULL) {
+ err = -EBUSY;
+ goto done;
+ }
+
+ if (msg != NULL)
+ technology->pending_reply = dbus_message_ref(msg);
for (list = technology->device_list; list; list = list->next) {
struct connman_device *device = list->data;
err = __connman_device_disable_persistent(device);
- if (err == 0 || err == -EINPROGRESS)
+ if (err == 0)
ret = 0;
}
- return ret;
+done:
+ if (ret == 0)
+ return ret;
+
+ if (msg != NULL) {
+ if (err == -EINPROGRESS)
+ technology->pending_timeout = g_timeout_add_seconds(10,
+ technology_pending_reply, technology);
+ else {
+ reply = __connman_error_failed(msg, -err);
+ if (reply != NULL)
+ g_dbus_send_message(connection, reply);
+ }
+ }
+
+ return err;
}
static void technology_blocked(struct connman_technology *technology,