X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Fdevice.c;h=ef899332551b37f0f7d22810658fdea2ecef660d;hb=b972ec96236afc662b21ace09d6adaa29d222411;hp=7bda8c25001c15e374fc64820c653607f5acbb18;hpb=08898a3702fd821da3239eb93f8a0af02cff5573;p=connman diff --git a/src/device.c b/src/device.c index 7bda8c2..ef89933 100644 --- a/src/device.c +++ b/src/device.c @@ -42,7 +42,7 @@ struct connman_device { struct connman_device_driver *driver; void *driver_data; - GSList *networks; + GHashTable *networks; }; static const char *type2description(enum connman_device_type type) @@ -56,6 +56,8 @@ static const char *type2description(enum connman_device_type type) return "WiMAX"; case CONNMAN_DEVICE_TYPE_BLUETOOTH: return "Bluetooth"; + case CONNMAN_DEVICE_TYPE_HSO: + return "Cellular"; default: return NULL; } @@ -74,6 +76,8 @@ static const char *type2string(enum connman_device_type type) return "modem"; case CONNMAN_DEVICE_TYPE_BLUETOOTH: return "bluetooth"; + case CONNMAN_DEVICE_TYPE_HSO: + return "cellular"; default: return NULL; } @@ -84,15 +88,31 @@ static const char *policy2string(enum connman_device_policy policy) switch (policy) { case CONNMAN_DEVICE_POLICY_IGNORE: return "ignore"; - case CONNMAN_DEVICE_POLICY_AUTO: - return "auto"; case CONNMAN_DEVICE_POLICY_OFF: return "off"; + case CONNMAN_DEVICE_POLICY_AUTO: + return "auto"; + case CONNMAN_DEVICE_POLICY_MANUAL: + return "manual"; default: return NULL; } } +static enum connman_device_policy string2policy(const char *policy) +{ + if (g_str_equal(policy, "ignore") == TRUE) + return CONNMAN_DEVICE_POLICY_IGNORE; + else if (g_str_equal(policy, "off") == TRUE) + return CONNMAN_DEVICE_POLICY_OFF; + else if (g_str_equal(policy, "auto") == TRUE) + return CONNMAN_DEVICE_POLICY_AUTO; + else if (g_str_equal(policy, "manual") == TRUE) + return CONNMAN_DEVICE_POLICY_MANUAL; + else + return CONNMAN_DEVICE_POLICY_UNKNOWN; +} + static int set_powered(struct connman_device *device, gboolean powered) { struct connman_device_driver *driver = device->driver; @@ -118,12 +138,87 @@ static int set_powered(struct connman_device *device, gboolean powered) return err; } +static int set_policy(DBusConnection *connection, + struct connman_device *device, + enum connman_device_policy policy) +{ + DBusMessage *signal; + DBusMessageIter entry, value; + const char *str, *key = "Policy"; + int err = 0; + + DBG("device %p policy %d", device, policy); + + if (device->policy == policy) + return 0; + + switch (policy) { + case CONNMAN_DEVICE_POLICY_OFF: + if (device->powered == TRUE) + err = set_powered(device, FALSE); + break; + case CONNMAN_DEVICE_POLICY_AUTO: + case CONNMAN_DEVICE_POLICY_MANUAL: + if (device->powered == FALSE) + err = set_powered(device, TRUE); + break; + default: + break; + } + + if (err < 0) + return err; + + device->policy = policy; + + signal = dbus_message_new_signal(device->element.path, + CONNMAN_DEVICE_INTERFACE, "PropertyChanged"); + if (signal == NULL) + return 0; + + dbus_message_iter_init_append(signal, &entry); + + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); + + str = policy2string(policy); + + dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, + DBUS_TYPE_STRING_AS_STRING, &value); + dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str); + dbus_message_iter_close_container(&entry, &value); + + g_dbus_send_message(connection, signal); + + return 0; +} + +static void append_networks(struct connman_device *device, + DBusMessageIter *entry) +{ + DBusMessageIter value, iter; + const char *key = "Networks"; + + dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key); + + dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT, + DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING, + &value); + + dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY, + DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter); + __connman_element_list((struct connman_element *) device, + CONNMAN_ELEMENT_TYPE_NETWORK, &iter); + dbus_message_iter_close_container(&value, &iter); + + dbus_message_iter_close_container(entry, &value); +} + static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg, void *data) { struct connman_device *device = data; DBusMessage *reply; - DBusMessageIter array, dict; + DBusMessageIter array, dict, entry; const char *str; DBG("conn %p", conn); @@ -169,6 +264,13 @@ static DBusMessage *get_properties(DBusConnection *conn, connman_dbus_dict_append_variant(&dict, "Scanning", DBUS_TYPE_BOOLEAN, &device->scanning); + if (device->mode != CONNMAN_DEVICE_MODE_NO_NETWORK) { + dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, + NULL, &entry); + append_networks(device, &entry); + dbus_message_iter_close_container(&dict, &entry); + } + dbus_message_iter_close_container(&array, &dict); return reply; @@ -205,6 +307,19 @@ static DBusMessage *set_property(DBusConnection *conn, err = set_powered(device, powered); if (err < 0 && err != -EINPROGRESS) return __connman_error_failed(msg); + } else if (g_str_equal(name, "Policy") == TRUE) { + enum connman_device_policy policy; + const char *str; + int err; + + dbus_message_iter_get_basic(&value, &str); + policy = string2policy(str); + if (policy == CONNMAN_DEVICE_POLICY_UNKNOWN) + return __connman_error_invalid_arguments(msg); + + err = set_policy(conn, device, policy); + if (err < 0) + return __connman_error_failed(msg); } __connman_element_store(&device->element); @@ -237,9 +352,22 @@ static DBusMessage *remove_network(DBusConnection *conn, static DBusMessage *propose_scan(DBusConnection *conn, DBusMessage *msg, void *data) { + struct connman_device *device = data; + int err; + DBG("conn %p", conn); - return __connman_error_not_supported(msg); + if (device->mode == CONNMAN_DEVICE_MODE_NO_NETWORK) + return __connman_error_not_supported(msg); + + if (!device->driver || !device->driver->scan) + return __connman_error_not_supported(msg); + + err = device->driver->scan(device); + if (err < 0) + return __connman_error_failed(msg); + + return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } static GDBusMethodTable device_methods[] = { @@ -258,13 +386,46 @@ static GDBusSignalTable device_signals[] = { static DBusConnection *connection; +static void append_devices(DBusMessageIter *entry) +{ + DBusMessageIter value, iter; + const char *key = "Devices"; + + dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key); + + dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT, + DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING, + &value); + + dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY, + DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter); + __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_DEVICE, &iter); + dbus_message_iter_close_container(&value, &iter); + + dbus_message_iter_close_container(entry, &value); +} + +static void emit_devices_signal(void) +{ + DBusMessage *signal; + DBusMessageIter entry; + + signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH, + CONNMAN_MANAGER_INTERFACE, "PropertyChanged"); + if (signal == NULL) + return; + + dbus_message_iter_init_append(signal, &entry); + + append_devices(&entry); + + g_dbus_send_message(connection, signal); +} + static int register_interface(struct connman_element *element) { struct connman_device *device = element->device; - g_dbus_unregister_interface(connection, element->path, - CONNMAN_DEVICE_INTERFACE); - if (g_dbus_register_interface(connection, element->path, CONNMAN_DEVICE_INTERFACE, device_methods, device_signals, @@ -273,11 +434,15 @@ static int register_interface(struct connman_element *element) return -EIO; } + emit_devices_signal(); + return 0; } static void unregister_interface(struct connman_element *element) { + emit_devices_signal(); + g_dbus_unregister_interface(connection, element->path, CONNMAN_DEVICE_INTERFACE); } @@ -325,6 +490,17 @@ void connman_device_driver_unregister(struct connman_device_driver *driver) driver_list = g_slist_remove(driver_list, driver); } +static void unregister_network(gpointer data) +{ + struct connman_network *network = data; + + DBG("network %p", network); + + connman_element_unregister((struct connman_element *) network); + + connman_network_unref(network); +} + static void device_destruct(struct connman_element *element) { struct connman_device *device = element->device; @@ -332,6 +508,8 @@ static void device_destruct(struct connman_element *element) DBG("element %p name %s", element, element->name); g_free(device->interface); + + g_hash_table_destroy(device->networks); } /** @@ -356,6 +534,8 @@ struct connman_device *connman_device_create(const char *node, DBG("device %p", device); + device->element.refcount = 1; + device->element.name = g_strdup(node); device->element.type = CONNMAN_ELEMENT_TYPE_DEVICE; device->element.index = -1; @@ -367,6 +547,9 @@ struct connman_device *connman_device_create(const char *node, device->mode = CONNMAN_DEVICE_MODE_NO_NETWORK; device->policy = CONNMAN_DEVICE_POLICY_AUTO; + device->networks = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, unregister_network); + return device; } @@ -474,6 +657,19 @@ const char *connman_device_get_interface(struct connman_device *device) } /** + * connman_device_set_policy: + * @device: device structure + * @policy: power and connection policy + * + * Change power and connection policy of device + */ +void connman_device_set_policy(struct connman_device *device, + enum connman_device_policy policy) +{ + device->policy = policy; +} + +/** * connman_device_set_mode: * @device: device structure * @mode: network mode @@ -609,6 +805,67 @@ int connman_device_set_scanning(struct connman_device *device, } /** + * connman_device_add_network: + * @device: device structure + * @network: network structure + * + * Add new network to the device + */ +int connman_device_add_network(struct connman_device *device, + struct connman_network *network) +{ + const char *identifier = connman_network_get_identifier(network); + int err; + + DBG("device %p network %p", device, network); + + if (device->mode == CONNMAN_DEVICE_MODE_NO_NETWORK) + return -EINVAL; + + err = connman_element_register((struct connman_element *) network, + &device->element); + if (err < 0) + return err; + + g_hash_table_insert(device->networks, g_strdup(identifier), + network); + + return 0; +} + +/** + * connman_device_get_network: + * @device: device structure + * @identifier: network identifier + * + * Get network for given identifier + */ +struct connman_network *connman_device_get_network(struct connman_device *device, + const char *identifier) +{ + DBG("device %p identifier %s", device, identifier); + + return g_hash_table_lookup(device->networks, identifier); +} + +/** + * connman_device_remove_network: + * @device: device structure + * @identifier: network identifier + * + * Remove network for given identifier + */ +int connman_device_remove_network(struct connman_device *device, + const char *identifier) +{ + DBG("device %p identifier %s", device, identifier); + + g_hash_table_remove(device->networks, identifier); + + return 0; +} + +/** * connman_device_register: * @device: device structure * @@ -657,7 +914,8 @@ static void device_enable(struct connman_device *device) { DBG("device %p", device); - if (device->policy != CONNMAN_DEVICE_POLICY_AUTO) + if (device->policy == CONNMAN_DEVICE_POLICY_IGNORE || + device->policy == CONNMAN_DEVICE_POLICY_OFF) return; if (device->powered == TRUE) @@ -671,7 +929,7 @@ static void device_disable(struct connman_device *device) { DBG("device %p", device); - if (device->policy != CONNMAN_DEVICE_POLICY_AUTO) + if (device->policy == CONNMAN_DEVICE_POLICY_IGNORE) return; if (device->powered == FALSE) @@ -702,10 +960,6 @@ static int device_probe(struct connman_element *element) if (device == NULL) return -ENODEV; - err = register_interface(element); - if (err < 0) - return err; - for (list = driver_list; list; list = list->next) { struct connman_device_driver *driver = list->data; @@ -716,11 +970,22 @@ static int device_probe(struct connman_element *element) if (driver->probe(device) == 0) { device->driver = driver; - device_enable(device); break; } } + if (!device->driver) + return -ENODEV; + + err = register_interface(element); + if (err < 0) { + if (device->driver->remove) + device->driver->remove(device); + return err; + } + + device_enable(device); + return 0; } @@ -733,14 +998,15 @@ static void device_remove(struct connman_element *element) if (device == NULL) return; - unregister_interface(element); + if (!device->driver) + return; - if (device->driver) { - device_disable(device); + device_disable(device); - if (device->driver->remove) - device->driver->remove(device); - } + unregister_interface(element); + + if (device->driver->remove) + device->driver->remove(device); } static struct connman_driver device_driver = {