summaryrefslogtreecommitdiff
path: root/profiles/input
diff options
context:
space:
mode:
authorArchie Pusaka <apusaka@chromium.org>2020-07-17 02:04:33 +0800
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2020-07-28 11:01:35 -0700
commita081a337bddd68924e3f48835c5e09f1bdbaeef9 (patch)
tree778935d7e2334c02902ead23e5e562f5891a6b25 /profiles/input
parentcfe249a5c3420b7a5d0863dac92b75a209745144 (diff)
downloadbluez-a081a337bddd68924e3f48835c5e09f1bdbaeef9.tar.gz
input: Remove bonding info when receiving virtual cable unplug
From Bluetooth HID Profile 1.1 Spec: If a Virtual Cable is unplugged via a HID control Virtual Unplug command, then both the Bluetooth HID device and Bluetooth HID Host shall destroy or invalidate all Bluetooth bonding and Virtual Cable information that was previously stored in persistent memory for the respective Virtually Cabled devices and hosts. This patch removes the bonding information upon receiving and/or sending a "virtual cable unplug".
Diffstat (limited to 'profiles/input')
-rw-r--r--profiles/input/device.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/profiles/input/device.c b/profiles/input/device.c
index 6ec0a4c63..ee0b2404a 100644
--- a/profiles/input/device.c
+++ b/profiles/input/device.c
@@ -88,6 +88,7 @@ struct input_device {
uint8_t report_req_pending;
guint report_req_timer;
uint32_t report_rsp_id;
+ bool virtual_cable_unplug;
};
static int idle_timeout = 0;
@@ -159,6 +160,14 @@ static void input_device_free(struct input_device *idev)
g_free(idev);
}
+static void virtual_cable_unplug(struct input_device *idev)
+{
+ device_remove_bonding(idev->device,
+ btd_device_get_bdaddr_type(idev->device));
+
+ idev->virtual_cable_unplug = false;
+}
+
static bool hidp_send_message(GIOChannel *chan, uint8_t hdr,
const uint8_t *data, size_t size)
{
@@ -199,6 +208,9 @@ static bool hidp_send_message(GIOChannel *chan, uint8_t hdr,
static bool hidp_send_ctrl_message(struct input_device *idev, uint8_t hdr,
const uint8_t *data, size_t size)
{
+ if (hdr == (HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG))
+ idev->virtual_cable_unplug = true;
+
return hidp_send_message(idev->ctrl_io, hdr, data, size);
}
@@ -355,6 +367,9 @@ static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data
/* Enter the auto-reconnect mode if needed */
input_device_enter_reconnect_mode(idev);
+ if (!idev->ctrl_io && idev->virtual_cable_unplug)
+ virtual_cable_unplug(idev);
+
return FALSE;
}
@@ -419,7 +434,7 @@ static void hidp_recv_ctrl_hid_control(struct input_device *idev, uint8_t param)
DBG("");
if (param == HIDP_CTRL_VIRTUAL_CABLE_UNPLUG)
- connection_disconnect(idev, 0);
+ connection_disconnect(idev, (1 << HIDP_VIRTUAL_CABLE_UNPLUG));
}
static void hidp_recv_ctrl_data(struct input_device *idev, uint8_t param,
@@ -543,6 +558,9 @@ static gboolean ctrl_watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data
if (idev->intr_io && !(cond & G_IO_NVAL))
g_io_channel_shutdown(idev->intr_io, TRUE, NULL);
+ if (!idev->intr_io && idev->virtual_cable_unplug)
+ virtual_cable_unplug(idev);
+
return FALSE;
}
@@ -1052,6 +1070,9 @@ static int connection_disconnect(struct input_device *idev, uint32_t flags)
shutdown(sock, SHUT_WR);
}
+ if (flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG))
+ idev->virtual_cable_unplug = true;
+
if (idev->uhid)
return 0;
else