diff mbox series

[Bluez,v1,2/2] input: Remove bonding info when receiving virtual cable unplug

Message ID 20200610230524.Bluez.v1.2.I16f38fd33617bbbf84d144605861b8391605a761@changeid (mailing list archive)
State Superseded, archived
Headers show
Series [Bluez,v1,1/2] device: add device_remove_bonding function | expand

Commit Message

Archie Pusaka June 10, 2020, 3:05 p.m. UTC
From: Archie Pusaka <apusaka@chromium.org>

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".
---

 profiles/input/device.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

Comments

Luiz Augusto von Dentz June 10, 2020, 6:18 p.m. UTC | #1
Hi Archie,

On Wed, Jun 10, 2020 at 8:06 AM Archie Pusaka <apusaka@google.com> wrote:
>
> From: Archie Pusaka <apusaka@chromium.org>
>
> 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".
> ---
>
>  profiles/input/device.c | 23 ++++++++++++++++++++++-
>  1 file changed, 22 insertions(+), 1 deletion(-)
>
> diff --git a/profiles/input/device.c b/profiles/input/device.c
> index d89da2d7c..45d86b6cb 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                    unbond_on_disconnect;

Either name it cable_unplug or have a flag with one bit field reserved
to indicate cable unplugged case.

>  };
>
>  static int idle_timeout = 0;
> @@ -148,6 +149,14 @@ static void input_device_free(struct input_device *idev)
>         g_free(idev);
>  }
>
> +static void invalidate_bonding(struct input_device *idev)
> +{
> +       device_remove_bonding(device_get_adapter(idev->device),
> +                               btd_device_get_bdaddr_type(idev->device));
> +
> +       idev->unbond_on_disconnect = false;
> +}
> +
>  static bool hidp_send_message(GIOChannel *chan, uint8_t hdr,
>                                         const uint8_t *data, size_t size)
>  {
> @@ -188,6 +197,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->unbond_on_disconnect = true;
> +
>         return hidp_send_message(idev->ctrl_io, hdr, data, size);
>  }
>
> @@ -342,6 +354,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->unbond_on_disconnect)
> +               invalidate_bonding(idev);
> +
>         return FALSE;
>  }
>
> @@ -406,7 +421,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,
> @@ -530,6 +545,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->unbond_on_disconnect)
> +               invalidate_bonding(idev);
> +
>         return FALSE;
>  }
>
> @@ -1035,6 +1053,9 @@ static int connection_disconnect(struct input_device *idev, uint32_t flags)
>         if (idev->ctrl_io)
>                 g_io_channel_shutdown(idev->ctrl_io, TRUE, NULL);
>
> +       if (flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG))
> +               idev->unbond_on_disconnect = true;
> +
>         if (idev->uhid)
>                 return 0;
>         else
> --
> 2.27.0.278.ge193c7cf3a9-goog
>
diff mbox series

Patch

diff --git a/profiles/input/device.c b/profiles/input/device.c
index d89da2d7c..45d86b6cb 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			unbond_on_disconnect;
 };
 
 static int idle_timeout = 0;
@@ -148,6 +149,14 @@  static void input_device_free(struct input_device *idev)
 	g_free(idev);
 }
 
+static void invalidate_bonding(struct input_device *idev)
+{
+	device_remove_bonding(device_get_adapter(idev->device),
+				btd_device_get_bdaddr_type(idev->device));
+
+	idev->unbond_on_disconnect = false;
+}
+
 static bool hidp_send_message(GIOChannel *chan, uint8_t hdr,
 					const uint8_t *data, size_t size)
 {
@@ -188,6 +197,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->unbond_on_disconnect = true;
+
 	return hidp_send_message(idev->ctrl_io, hdr, data, size);
 }
 
@@ -342,6 +354,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->unbond_on_disconnect)
+		invalidate_bonding(idev);
+
 	return FALSE;
 }
 
@@ -406,7 +421,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,
@@ -530,6 +545,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->unbond_on_disconnect)
+		invalidate_bonding(idev);
+
 	return FALSE;
 }
 
@@ -1035,6 +1053,9 @@  static int connection_disconnect(struct input_device *idev, uint32_t flags)
 	if (idev->ctrl_io)
 		g_io_channel_shutdown(idev->ctrl_io, TRUE, NULL);
 
+	if (flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG))
+		idev->unbond_on_disconnect = true;
+
 	if (idev->uhid)
 		return 0;
 	else