diff --git a/src/adapter.c b/src/adapter.c index c1995a3..ba2c5fb 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -977,6 +977,36 @@ struct btd_device *adapter_create_device(DBusConnection *conn, return device; } +struct btd_device *adapter_add_cable_paired_device(DBusConnection *conn, + struct btd_adapter *adapter, + const char *name, + const char *address, + guint32 vendor_id, + guint32 product_id, + const char *pnp_record) +{ + struct btd_device *device; + const char *path; + + debug("adapter_add_cable_paired_device(%s)", address); + + device = device_create_cable_paired_device(conn, adapter, name, address, vendor_id, product_id, pnp_record); + if (!device) + return NULL; + + adapter->devices = g_slist_append(adapter->devices, device); + + path = device_get_path(device); + g_dbus_emit_signal(conn, adapter->path, + ADAPTER_INTERFACE, "DeviceCreated", + DBUS_TYPE_OBJECT_PATH, &path, + DBUS_TYPE_INVALID); + + adapter_update_devices(adapter); + + return device; +} + void adapter_remove_device(DBusConnection *conn, struct btd_adapter *adapter, struct btd_device *device) { @@ -1508,6 +1538,41 @@ static DBusMessage *create_device(DBusConnection *conn, return NULL; } +static DBusMessage *add_cable_paired_device(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct btd_adapter *adapter = data; + struct btd_device *device; + guint vendor_id, product_id; + const gchar *address, *pnp_record, *name; + + if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_UINT32, &vendor_id, + DBUS_TYPE_UINT32, &product_id, + DBUS_TYPE_STRING, &pnp_record, + DBUS_TYPE_INVALID) == FALSE) + return invalid_args(msg); + + if (check_address(address) < 0) + return invalid_args(msg); + + if (adapter_find_device(adapter, address)) + return g_dbus_create_error(msg, + ERROR_INTERFACE ".AlreadyExists", + "Device already exists"); + + debug("create_device(%s)", address); + + device = adapter_add_cable_paired_device(conn, adapter, name, address, vendor_id, product_id, pnp_record); + if (!device) + return NULL; + + device_set_temporary(device, FALSE); + + return dbus_message_new_method_return(msg); +} + static uint8_t parse_io_capability(const char *capability) { if (g_str_equal(capability, "")) @@ -1707,6 +1772,7 @@ static GDBusMethodTable adapter_methods[] = { G_DBUS_METHOD_FLAG_ASYNC}, { "ListDevices", "", "ao", list_devices, G_DBUS_METHOD_FLAG_DEPRECATED}, + { "AddCablePairedDevice", "ssuus", "o", add_cable_paired_device }, { "CreateDevice", "s", "o", create_device, G_DBUS_METHOD_FLAG_ASYNC}, { "CreatePairedDevice", "sos", "o", create_paired_device, diff --git a/src/adapter.h b/src/adapter.h index 06f558a..1a24a1a 100644 --- a/src/adapter.h +++ b/src/adapter.h @@ -91,6 +91,14 @@ void adapter_remove_device(DBusConnection *conn, struct btd_adapter *adapter, struct btd_device *adapter_create_device(DBusConnection *conn, struct btd_adapter *adapter, const char *address); +struct btd_device *adapter_add_cable_paired_device(DBusConnection *conn, + struct btd_adapter *adapter, + const char *name, + const char *address, + guint vendor_id, + guint product_id, + const char *pnp_record); + int pending_remote_name_cancel(struct btd_adapter *adapter); void remove_pending_device(struct btd_adapter *adapter); diff --git a/src/device.c b/src/device.c index 9b32379..6a153dc 100644 --- a/src/device.c +++ b/src/device.c @@ -654,6 +654,57 @@ struct btd_device *device_create(DBusConnection *conn, return device; } +struct btd_device *device_create_cable_paired_device(DBusConnection *conn, + struct btd_adapter *adapter, + const char *name, + const char *address, + guint32 vendor_id, + guint32 product_id, + const char *pnp_record) +{ + gchar *address_up; + sdp_record_t *rec; + struct btd_device *device; + const gchar *adapter_path = adapter_get_path(adapter); + bdaddr_t src; + char srcaddr[18]; + + device = g_try_malloc0(sizeof(struct btd_device)); + if (device == NULL) + return NULL; + + address_up = g_ascii_strup(address, -1); + device->path = g_strdup_printf("%s/dev_%s", adapter_path, address_up); + g_strdelimit(device->path, ":", '_'); + g_free(address_up); + + debug("Creating cable paired device %s", device->path); + + if (g_dbus_register_interface(conn, device->path, DEVICE_INTERFACE, + device_methods, device_signals, NULL, + device, device_free) == FALSE) { + device_free(device); + return NULL; + } + + str2ba(address, &device->bdaddr); + device->adapter = adapter; + adapter_get_address(adapter, &src); + ba2str(&src, srcaddr); + write_device_name(&device->bdaddr, &src, name); + device_set_name (device, name); + + /* Store the device's SDP record */ + rec = record_from_string (pnp_record); + store_record(srcaddr, address, rec); + sdp_record_free(rec); + /* Set the device id */ + store_device_id(srcaddr, address, 0xffff, vendor_id, product_id, 0); + /* Don't write a profile, it will be updated when the device connects */ + + return device; +} + void device_set_name(struct btd_device *device, const char *name) { DBusConnection *conn = get_dbus_connection(); diff --git a/src/device.h b/src/device.h index 5c230b8..a3e5447 100644 --- a/src/device.h +++ b/src/device.h @@ -36,6 +36,13 @@ typedef enum { struct btd_device *device_create(DBusConnection *conn, struct btd_adapter *adapter, const gchar *address); +struct btd_device *device_create_cable_paired_device(DBusConnection *conn, + struct btd_adapter *adapter, + const char *name, + const char *address, + guint32 vendor_id, + guint32 product_id, + const char *pnp_record); void device_set_name(struct btd_device *device, const char *name); void device_remove(struct btd_device *device, DBusConnection *conn, gboolean remove_stored);