summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPauli Virtanen <pav@iki.fi>2023-08-19 16:31:21 +0300
committerAyush Garg <ayush.garg@samsung.com>2024-01-05 19:04:03 +0530
commitab989164531e7f91dd43031424c601c30088c537 (patch)
tree1c65cd2009bb73f3ceb9215cadf882a698ac9d3b
parentfccfb170a5715015dfaf36a1eddc330d7f62ce0a (diff)
downloadbluez-ab989164531e7f91dd43031424c601c30088c537.tar.gz
bluez-ab989164531e7f91dd43031424c601c30088c537.tar.bz2
bluez-ab989164531e7f91dd43031424c601c30088c537.zip
hciemu: Add hciemu_flush_client_events for ordering VHCI vs bthost
bthost commands execute with a delay because events may be sitting in the socketpair queues. This makes it difficult to ensure, when writing tests, that certain bthost commands have been handled, before any new events from VHCI are processed. To make event ordering possible, add a function that flushes client bthost/btdev socketpair queues, before processing any new VHCI events. This is done by pausing VHCI input processing until the kernel socketpair queues are empty.
-rwxr-xr-xemulator/hciemu.c54
-rwxr-xr-xemulator/hciemu.h3
2 files changed, 57 insertions, 0 deletions
diff --git a/emulator/hciemu.c b/emulator/hciemu.c
index 8bfaf380..b9b98fb1 100755
--- a/emulator/hciemu.c
+++ b/emulator/hciemu.c
@@ -20,6 +20,7 @@
#include <stdbool.h>
#include <errno.h>
#include <sys/socket.h>
+#include <sys/ioctl.h>
#include <glib.h>
@@ -40,6 +41,7 @@ struct hciemu_client {
guint start_source;
guint host_source;
guint source;
+ int sock[2];
};
struct hciemu {
@@ -53,6 +55,8 @@ struct hciemu {
hciemu_debug_func_t debug_callback;
hciemu_destroy_func_t debug_destroy;
void *debug_data;
+
+ unsigned int flush_id;
};
struct hciemu_command_hook {
@@ -337,6 +341,9 @@ static struct hciemu_client *hciemu_client_new(struct hciemu *hciemu,
return NULL;
}
+ client->sock[0] = sv[0];
+ client->sock[1] = sv[1];
+
client->source = create_source_btdev(sv[0], client->dev);
client->host_source = create_source_bthost(sv[1], client->host);
client->start_source = g_idle_add(start_host, client);
@@ -434,6 +441,9 @@ void hciemu_unref(struct hciemu *hciemu)
queue_destroy(hciemu->post_command_hooks, destroy_command_hook);
queue_destroy(hciemu->clients, hciemu_client_destroy);
+ if (hciemu->flush_id)
+ g_source_remove(hciemu->flush_id);
+
vhci_close(hciemu->vhci);
free(hciemu);
@@ -743,3 +753,47 @@ bool hciemu_del_hook(struct hciemu *hciemu, enum hciemu_hook_type type,
return btdev_del_hook(dev, hook_type, opcode);
}
+
+static bool client_is_pending(const void *data, const void *match_data)
+{
+ struct hciemu_client *client = (struct hciemu_client *)data;
+ int used, i;
+
+ if (!client->source || !client->host_source)
+ return false;
+
+ for (i = 0; i < 2; ++i) {
+ if (!ioctl(client->sock[i], TIOCOUTQ, &used) && used > 0)
+ return true;
+ if (!ioctl(client->sock[i], TIOCINQ, &used) && used > 0)
+ return true;
+ }
+
+ return false;
+}
+
+static gboolean flush_client_events(gpointer user_data)
+{
+ struct hciemu *hciemu = user_data;
+
+ if (queue_find(hciemu->clients, client_is_pending, NULL))
+ return TRUE;
+
+ hciemu->flush_id = 0;
+
+ util_debug(hciemu->debug_callback, hciemu->debug_data, "vhci: resume");
+ if (hciemu->vhci)
+ vhci_pause_input(hciemu->vhci, false);
+
+ return FALSE;
+}
+
+void hciemu_flush_client_events(struct hciemu *hciemu)
+{
+ if (hciemu->flush_id || !hciemu->vhci)
+ return;
+
+ util_debug(hciemu->debug_callback, hciemu->debug_data, "vhci: pause");
+ vhci_pause_input(hciemu->vhci, true);
+ hciemu->flush_id = g_idle_add(flush_client_events, hciemu);
+}
diff --git a/emulator/hciemu.h b/emulator/hciemu.h
index 3a06ca57..3449eae4 100755
--- a/emulator/hciemu.h
+++ b/emulator/hciemu.h
@@ -48,6 +48,9 @@ bool hciemu_set_debug(struct hciemu *hciemu, hciemu_debug_func_t callback,
struct vhci *hciemu_get_vhci(struct hciemu *hciemu);
struct bthost *hciemu_client_get_host(struct hciemu *hciemu);
+/* Process pending client events before new VHCI events */
+void hciemu_flush_client_events(struct hciemu *hciemu);
+
const char *hciemu_get_address(struct hciemu *hciemu);
uint8_t *hciemu_get_features(struct hciemu *hciemu);