diff options
-rw-r--r-- | input/input-service.c | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/input/input-service.c b/input/input-service.c index 627c2a99..4982fc7f 100644 --- a/input/input-service.c +++ b/input/input-service.c @@ -696,12 +696,8 @@ static DBusHandlerResult device_connect(DBusConnection *conn, static int disconnect(struct input_device *idev, uint32_t flags) { struct hidp_conndel_req req; - int ctl, err; - - if ((idev->hidp.intr_sock < 0) || (idev->hidp.ctrl_sock < 0)) { - errno = ENOTCONN; - return -1; - } + struct hidp_conninfo ci; + int ctl, err, ret = 0; ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HIDP); if (ctl < 0) { @@ -709,26 +705,39 @@ static int disconnect(struct input_device *idev, uint32_t flags) return -1; } + memset(&ci, 0, sizeof(struct hidp_conninfo)); + str2ba(idev->addr, &ci.bdaddr); + if (ioctl(ctl, HIDPGETCONNINFO, &ci) < 0) { + error("Can't retrive HID information: %s(%d)", + strerror(errno), errno); + goto fail; + } + + if (ci.state != BT_CONNECTED) { + errno = ENOTCONN; + goto fail; + } + memset(&req, 0, sizeof(struct hidp_conndel_req)); str2ba(idev->addr, &req.bdaddr); req.flags = flags; - if (ioctl(ctl, HIDPCONNDEL, &req) < 0) { - err = errno; error("Can't delete the HID device: %s(%d)", strerror(errno), errno); - close(ctl); - errno = err; - return -1; + goto fail; } + ret = 0; +fail: + err = errno; close(ctl); + errno = err; idev->hidp.intr_sock = -1; idev->hidp.ctrl_sock = -1; - return 0; + return ret; } static DBusHandlerResult device_disconnect(DBusConnection *conn, @@ -1283,6 +1292,7 @@ static DBusHandlerResult manager_remove_device(DBusConnection *conn, DBusMessage *msg, void *data) { struct input_manager *mgr = data; + struct input_device *idev; DBusMessage *reply; DBusError derr; GSList *l; @@ -1305,6 +1315,12 @@ static DBusHandlerResult manager_remove_device(DBusConnection *conn, if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; + /* Try disconnect */ + if (dbus_connection_get_object_path_data(conn, path, (void *) &idev) && idev) + disconnect(idev, (1 << HIDP_VIRTUAL_CABLE_UNPLUG)); + + /* FIXME: Remove stored data */ + if (unregister_input_device(conn, path) < 0) { dbus_message_unref(reply); return err_failed(conn, msg, "D-Bus path unregistration failed"); |