2024-03-08 22:11:25

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ v1 1/4] shared/uhid: Add bt_uhid_create

From: Luiz Augusto von Dentz <[email protected]>

This adds bt_uhid_create which uses UHID_CREATE2 and tracks progress of
when the device is ready to receive events and in the meantime queues
them while waiting for UHID_START.
---
src/shared/uhid.c | 134 ++++++++++++++++++++++++++++++++++++++++++++--
src/shared/uhid.h | 8 +++
2 files changed, 138 insertions(+), 4 deletions(-)

diff --git a/src/shared/uhid.c b/src/shared/uhid.c
index 1f15443cd6d0..65e2d018a82e 100644
--- a/src/shared/uhid.c
+++ b/src/shared/uhid.c
@@ -31,6 +31,9 @@ struct bt_uhid {
struct io *io;
unsigned int notify_id;
struct queue *notify_list;
+ struct queue *input;
+ bool created;
+ bool started;
};

struct uhid_notify {
@@ -48,6 +51,9 @@ static void uhid_free(struct bt_uhid *uhid)
if (uhid->notify_list)
queue_destroy(uhid->notify_list, free);

+ if (uhid->input)
+ queue_destroy(uhid->input, free);
+
free(uhid);
}

@@ -215,14 +221,11 @@ bool bt_uhid_unregister_all(struct bt_uhid *uhid)
return true;
}

-int bt_uhid_send(struct bt_uhid *uhid, const struct uhid_event *ev)
+static int uhid_send(struct bt_uhid *uhid, const struct uhid_event *ev)
{
ssize_t len;
struct iovec iov;

- if (!uhid->io)
- return -ENOTCONN;
-
iov.iov_base = (void *) ev;
iov.iov_len = sizeof(*ev);

@@ -233,3 +236,126 @@ int bt_uhid_send(struct bt_uhid *uhid, const struct uhid_event *ev)
/* uHID kernel driver does not handle partial writes */
return len != sizeof(*ev) ? -EIO : 0;
}
+
+int bt_uhid_send(struct bt_uhid *uhid, const struct uhid_event *ev)
+{
+ if (!uhid->io)
+ return -ENOTCONN;
+
+ /* Queue events if uhid has not been created yet */
+ if (!uhid->started) {
+ if (!uhid->input)
+ uhid->input = queue_new();
+
+ queue_push_tail(uhid->input, util_memdup(&ev, sizeof(ev)));
+ return 0;
+ }
+
+ return uhid_send(uhid, ev);
+}
+
+static bool input_dequeue(const void *data, const void *match_data)
+{
+ struct uhid_event *ev = (void *)data;
+ struct bt_uhid *uhid = (void *)match_data;
+
+ return bt_uhid_send(uhid, ev) == 0;
+}
+
+static void uhid_start(struct uhid_event *ev, void *user_data)
+{
+ struct bt_uhid *uhid = user_data;
+
+ uhid->started = true;
+
+ /* dequeue input events send while UHID_CREATE2 was in progress */
+ queue_remove_all(uhid->input, input_dequeue, uhid, free);
+}
+
+int bt_uhid_create(struct bt_uhid *uhid, const char *name, bdaddr_t *src,
+ bdaddr_t *dst, uint32_t vendor, uint32_t product,
+ uint32_t version, uint32_t country, void *rd_data,
+ size_t rd_size)
+{
+ struct uhid_event ev;
+ int err;
+
+ if (!uhid || !name || rd_size > sizeof(ev.u.create2.rd_data))
+ return -EINVAL;
+
+ if (uhid->created)
+ return 0;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.type = UHID_CREATE2;
+ strncpy((char *) ev.u.create2.name, name,
+ sizeof(ev.u.create2.name) - 1);
+ if (src)
+ sprintf((char *)ev.u.create2.phys,
+ "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
+ src->b[5], src->b[4], src->b[3], src->b[2], src->b[1],
+ src->b[0]);
+ if (dst)
+ sprintf((char *)ev.u.create2.uniq,
+ "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
+ dst->b[5], dst->b[4], dst->b[3], dst->b[2], dst->b[1],
+ dst->b[0]);
+ ev.u.create2.vendor = vendor;
+ ev.u.create2.product = product;
+ ev.u.create2.version = version;
+ ev.u.create2.country = country;
+ ev.u.create2.bus = BUS_BLUETOOTH;
+ if (rd_size)
+ memcpy(ev.u.create2.rd_data, rd_data, rd_size);
+ ev.u.create2.rd_size = rd_size;
+
+ err = uhid_send(uhid, &ev);
+ if (err)
+ return err;
+
+ bt_uhid_register(uhid, UHID_START, uhid_start, uhid);
+
+ uhid->created = true;
+ uhid->started = false;
+
+ return 0;
+}
+
+bool bt_uhid_created(struct bt_uhid *uhid)
+{
+ if (!uhid)
+ return false;
+
+ return uhid->created;
+}
+
+bool bt_uhid_started(struct bt_uhid *uhid)
+{
+ if (!uhid)
+ return false;
+
+ return uhid->started;
+}
+
+int bt_uhid_destroy(struct bt_uhid *uhid)
+{
+ struct uhid_event ev;
+ int err;
+
+ if (!uhid)
+ return -EINVAL;
+
+ if (!uhid->created)
+ return 0;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.type = UHID_DESTROY;
+
+ err = bt_uhid_send(uhid, &ev);
+ if (err < 0)
+ return err;
+
+ uhid->created = false;
+
+ return err;
+}
diff --git a/src/shared/uhid.h b/src/shared/uhid.h
index 55ae839f3017..8d5dfd6e45c9 100644
--- a/src/shared/uhid.h
+++ b/src/shared/uhid.h
@@ -11,6 +11,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <linux/uhid.h>
+#include <bluetooth/bluetooth.h>

struct bt_uhid;

@@ -29,3 +30,10 @@ bool bt_uhid_unregister(struct bt_uhid *uhid, unsigned int id);
bool bt_uhid_unregister_all(struct bt_uhid *uhid);

int bt_uhid_send(struct bt_uhid *uhid, const struct uhid_event *ev);
+int bt_uhid_create(struct bt_uhid *uhid, const char *name, bdaddr_t *src,
+ bdaddr_t *dst, uint32_t vendor, uint32_t product,
+ uint32_t version, uint32_t country, void *rd_data,
+ size_t rd_size);
+bool bt_uhid_created(struct bt_uhid *uhid);
+bool bt_uhid_started(struct bt_uhid *uhid);
+int bt_uhid_destroy(struct bt_uhid *uhid);
--
2.43.0



2024-03-08 22:11:29

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ v1 2/4] hog-lib: Use bt_uhid_create instead of UHID_CREATE2

From: Luiz Augusto von Dentz <[email protected]>

This makes use of bt_uhid_create instead of directly submitting
UHID_CREATE2 since it can track UHID_START by itself.
---
profiles/input/hog-lib.c | 78 +++++++---------------------------------
1 file changed, 13 insertions(+), 65 deletions(-)

diff --git a/profiles/input/hog-lib.c b/profiles/input/hog-lib.c
index 67492a63eca3..ef3d6aa1b1eb 100644
--- a/profiles/input/hog-lib.c
+++ b/profiles/input/hog-lib.c
@@ -79,8 +79,6 @@ struct bt_hog {
GSList *reports;
struct bt_uhid *uhid;
int uhid_fd;
- bool uhid_created;
- bool uhid_start;
uint64_t uhid_flags;
uint16_t bcdhid;
uint8_t bcountrycode;
@@ -360,15 +358,6 @@ static void report_value_cb(const guint8 *pdu, guint16 len, gpointer user_data)
ev.u.input.size = len;
}

- /* If uhid had not sent UHID_START yet queue up the input */
- if (!hog->uhid_created || !hog->uhid_start) {
- if (!hog->input)
- hog->input = queue_new();
-
- queue_push_tail(hog->input, util_memdup(&ev, sizeof(ev)));
- return;
- }
-
err = bt_uhid_send(hog->uhid, &ev);
if (err < 0)
error("bt_uhid_send: %s (%d)", strerror(-err), -err);
@@ -851,7 +840,6 @@ static void start_flags(struct uhid_event *ev, void *user_data)
{
struct bt_hog *hog = user_data;

- hog->uhid_start = true;
hog->uhid_flags = ev->u.start.dev_flags;

DBG("uHID device flags: 0x%16" PRIx64, hog->uhid_flags);
@@ -1037,54 +1025,26 @@ static void uhid_create(struct bt_hog *hog, uint8_t *report_map,
size_t report_map_len)
{
uint8_t *value = report_map;
- struct uhid_event ev;
size_t vlen = report_map_len;
- int i, err;
+ int err;
GError *gerr = NULL;
-
- if (vlen > sizeof(ev.u.create2.rd_data)) {
- error("Report MAP too big: %zu > %zu", vlen,
- sizeof(ev.u.create2.rd_data));
- return;
- }
-
- /* create uHID device */
- memset(&ev, 0, sizeof(ev));
- ev.type = UHID_CREATE2;
+ bdaddr_t src, dst;

bt_io_get(g_attrib_get_channel(hog->attrib), &gerr,
- BT_IO_OPT_SOURCE, ev.u.create2.phys,
- BT_IO_OPT_DEST, ev.u.create2.uniq,
+ BT_IO_OPT_SOURCE_BDADDR, &src,
+ BT_IO_OPT_DEST_BDADDR, &dst,
BT_IO_OPT_INVALID);
-
if (gerr) {
error("Failed to connection details: %s", gerr->message);
g_error_free(gerr);
return;
}

- /* Phys + uniq are the same size (hw address type) */
- for (i = 0;
- i < (int)sizeof(ev.u.create2.phys) && ev.u.create2.phys[i] != 0;
- ++i) {
- ev.u.create2.phys[i] = tolower(ev.u.create2.phys[i]);
- ev.u.create2.uniq[i] = tolower(ev.u.create2.uniq[i]);
- }
-
- strncpy((char *) ev.u.create2.name, hog->name,
- sizeof(ev.u.create2.name) - 1);
- ev.u.create2.vendor = hog->vendor;
- ev.u.create2.product = hog->product;
- ev.u.create2.version = hog->version;
- ev.u.create2.country = hog->bcountrycode;
- ev.u.create2.bus = BUS_BLUETOOTH;
- ev.u.create2.rd_size = vlen;
-
- memcpy(ev.u.create2.rd_data, value, vlen);
-
- err = bt_uhid_send(hog->uhid, &ev);
+ err = bt_uhid_create(hog->uhid, hog->name, &src, &dst,
+ hog->vendor, hog->product, hog->version,
+ hog->bcountrycode, value, vlen);
if (err < 0) {
- error("bt_uhid_send: %s", strerror(-err));
+ error("bt_uhid_create: %s", strerror(-err));
return;
}

@@ -1093,9 +1053,6 @@ static void uhid_create(struct bt_hog *hog, uint8_t *report_map,
bt_uhid_register(hog->uhid, UHID_GET_REPORT, get_report, hog);
bt_uhid_register(hog->uhid, UHID_SET_REPORT, set_report, hog);

- hog->uhid_created = true;
- hog->uhid_start = false;
-
DBG("HoG created uHID device");
}

@@ -1146,7 +1103,8 @@ static void read_report_map(struct bt_hog *hog)
{
uint16_t handle;

- if (!hog->report_map_attr || hog->uhid_created || hog->report_map_id)
+ if (!hog->report_map_attr || bt_uhid_created(hog->uhid) ||
+ hog->report_map_id)
return;

handle = gatt_db_attribute_get_handle(hog->report_map_attr);
@@ -1312,24 +1270,14 @@ static bool cancel_gatt_req(const void *data, const void *user_data)
static void uhid_destroy(struct bt_hog *hog)
{
int err;
- struct uhid_event ev;
-
- if (!hog->uhid_created)
- return;

bt_uhid_unregister_all(hog->uhid);

- memset(&ev, 0, sizeof(ev));
- ev.type = UHID_DESTROY;
-
- err = bt_uhid_send(hog->uhid, &ev);
-
+ err = bt_uhid_destroy(hog->uhid);
if (err < 0) {
error("bt_uhid_send: %s", strerror(-err));
return;
}
-
- hog->uhid_created = false;
}

static void hog_free(void *data)
@@ -1810,7 +1758,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
bt_hog_attach(instance, gatt);
}

- if (!hog->uhid_created) {
+ if (!bt_uhid_created(hog->uhid)) {
DBG("HoG discovering characteristics");
if (hog->attr)
gatt_db_service_foreach_char(hog->attr,
@@ -1822,7 +1770,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
char_discovered_cb, hog);
}

- if (!hog->uhid_created)
+ if (!bt_uhid_created(hog->uhid))
return true;

/* If UHID is already created, set up the report value handlers to
--
2.43.0


2024-03-09 00:54:03

by bluez.test.bot

[permalink] [raw]
Subject: RE: [BlueZ,v1,1/4] shared/uhid: Add bt_uhid_create

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=833928

---Test result---

Test Summary:
CheckPatch PASS 1.71 seconds
GitLint PASS 6.28 seconds
BuildEll PASS 23.74 seconds
BluezMake PASS 1635.49 seconds
MakeCheck PASS 13.16 seconds
MakeDistcheck PASS 175.34 seconds
CheckValgrind PASS 244.12 seconds
CheckSmatch PASS 344.72 seconds
bluezmakeextell PASS 117.34 seconds
IncrementalBuild PASS 5980.43 seconds
ScanBuild PASS 1003.69 seconds



---
Regards,
Linux Bluetooth