+ dbus_message_iter_init_append(signal, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+ &technology->path);
+ append_properties(&iter, technology);
+
+ dbus_connection_send(connection, signal, NULL);
+ dbus_message_unref(signal);
+}
+
+static void technology_removed_signal(struct connman_technology *technology)
+{
+ g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
+ CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
+ DBUS_TYPE_OBJECT_PATH, &technology->path,
+ DBUS_TYPE_INVALID);
+}
+
+static DBusMessage *get_properties(DBusConnection *conn,
+ DBusMessage *message, void *user_data)
+{
+ struct connman_technology *technology = user_data;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+
+ reply = dbus_message_new_method_return(message);
+ if (reply == NULL)
+ return NULL;
+
+ dbus_message_iter_init_append(reply, &iter);
+ append_properties(&iter, technology);
+
+ return reply;
+}
+
+void __connman_technology_list_struct(DBusMessageIter *array)
+{
+ GSList *list;
+ DBusMessageIter entry;
+
+ for (list = technology_list; list; list = list->next) {
+ struct connman_technology *technology = list->data;
+
+ if (technology->path == NULL ||
+ (technology->rfkill_driven == TRUE &&
+ technology->hardblocked == TRUE))
+ continue;
+
+ dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
+ NULL, &entry);
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
+ &technology->path);
+ append_properties(&entry, technology);
+ dbus_message_iter_close_container(array, &entry);
+ }
+}
+
+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;
+}
+
+static int technology_affect_devices(struct connman_technology *technology,
+ connman_bool_t enable_device)
+{
+ GSList *list;
+ int err = 0;
+
+ for (list = technology->device_list; list; list = list->next) {
+ struct connman_device *device = list->data;
+
+ if (enable_device == TRUE)
+ err = __connman_device_enable(device);
+ else
+ err = __connman_device_disable(device);
+ }
+
+ return err;
+}
+
+static int technology_enable(struct connman_technology *technology)
+{
+ DBG("technology %p enable", technology);
+
+ __sync_synchronize();
+ if (technology->enabled == TRUE)
+ return -EALREADY;
+
+ if (technology->pending_reply != NULL)
+ return -EBUSY;
+
+ if (technology->rfkill_driven == TRUE)
+ return __connman_rfkill_block(technology->type, FALSE);
+
+ return technology_affect_devices(technology, TRUE);
+}
+
+static int technology_disable(struct connman_technology *technology)
+{
+ DBG("technology %p disable", technology);
+
+ __sync_synchronize();
+ if (technology->enabled == FALSE)
+ return -EALREADY;
+
+ if (technology->pending_reply != NULL)
+ return -EBUSY;
+
+ if (technology->tethering == TRUE)
+ set_tethering(technology, FALSE);
+
+ if (technology->rfkill_driven == TRUE)
+ return __connman_rfkill_block(technology->type, TRUE);
+
+ return technology_affect_devices(technology, FALSE);
+}
+
+static DBusMessage *set_powered(struct connman_technology *technology,
+ DBusMessage *msg, connman_bool_t powered)
+{
+ DBusMessage *reply = NULL;
+ int err = 0;
+
+ if (technology->rfkill_driven && technology->hardblocked == TRUE) {
+ err = -EACCES;
+ goto make_reply;
+ }
+
+ if (powered == TRUE)
+ err = technology_enable(technology);
+ else
+ err = technology_disable(technology);
+
+ if (err != -EBUSY) {
+ technology->enable_persistent = powered;
+ technology_save(technology);
+ }
+
+make_reply:
+ if (err == -EINPROGRESS) {
+ technology->pending_reply = dbus_message_ref(msg);
+ technology->pending_timeout = g_timeout_add_seconds(10,
+ technology_pending_reply, technology);
+ } else if (err == -EALREADY) {
+ if (powered == TRUE)
+ reply = __connman_error_already_enabled(msg);
+ else
+ reply = __connman_error_already_disabled(msg);
+ } else if (err < 0)
+ reply = __connman_error_failed(msg, -err);
+ else
+ reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);