diff mbox series

[BlueZ,v4,1/4] shared/uhid: Add dedicated functions for each UHID opcode

Message ID 20240311224327.1023070-1-luiz.dentz@gmail.com
State Superseded
Headers show
Series [BlueZ,v4,1/4] shared/uhid: Add dedicated functions for each UHID opcode | expand

Commit Message

Luiz Augusto von Dentz March 11, 2024, 10:43 p.m. UTC
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

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 and other dedicated functions for each
UHID opcode so users don't need to build each command manually.
---
 src/shared/uhid.c | 212 +++++++++++++++++++++++++++++++++++++++++++++-
 src/shared/uhid.h |  13 +++
 2 files changed, 221 insertions(+), 4 deletions(-)

Comments

bluez.test.bot@gmail.com March 12, 2024, 1:54 a.m. UTC | #1
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=834468

---Test result---

Test Summary:
CheckPatch                    PASS      2.00 seconds
GitLint                       PASS      1.22 seconds
BuildEll                      PASS      25.08 seconds
BluezMake                     PASS      1601.22 seconds
MakeCheck                     PASS      13.81 seconds
MakeDistcheck                 PASS      176.59 seconds
CheckValgrind                 PASS      246.14 seconds
CheckSmatch                   PASS      348.92 seconds
bluezmakeextell               PASS      118.82 seconds
IncrementalBuild              PASS      6046.28 seconds
ScanBuild                     PASS      1009.66 seconds



---
Regards,
Linux Bluetooth
patchwork-bot+bluetooth@kernel.org March 13, 2024, 3:20 p.m. UTC | #2
Hello:

This series was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Mon, 11 Mar 2024 18:43:24 -0400 you wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> 
> 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 and other dedicated functions for each
> UHID opcode so users don't need to build each command manually.
> 
> [...]

Here is the summary with links:
  - [BlueZ,v4,1/4] shared/uhid: Add dedicated functions for each UHID opcode
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=92ed637ab2bc
  - [BlueZ,v4,2/4] hog-lib: Use bt_uhid functions
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=256d0b594d04
  - [BlueZ,v4,3/4] input/device: Use bt_uhid functions
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=c0c9e462be46
  - [BlueZ,v4,4/4] test-uhid: Test bt_uhid functions
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=f5fecf037b1e

You are awesome, thank you!
diff mbox series

Patch

diff --git a/src/shared/uhid.c b/src/shared/uhid.c
index 1f15443cd6d0..46edb3bfa3ba 100644
--- a/src/shared/uhid.c
+++ b/src/shared/uhid.c
@@ -26,11 +26,18 @@ 
 
 #define UHID_DEVICE_FILE "/dev/uhid"
 
+#ifndef MIN
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+#endif
+
 struct bt_uhid {
 	int ref_count;
 	struct io *io;
 	unsigned int notify_id;
 	struct queue *notify_list;
+	struct queue *input;
+	bool created;
+	bool started;
 };
 
 struct uhid_notify {
@@ -48,6 +55,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 +225,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 +240,200 @@  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 || !ev)
+		return -EINVAL;
+
+	if (!uhid->io)
+		return -ENOTCONN;
+
+	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 = bt_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_input(struct bt_uhid *uhid, uint8_t number, const void *data,
+			size_t size)
+{
+	struct uhid_event ev;
+	struct uhid_input2_req *req = &ev.u.input2;
+	size_t len = 0;
+
+	if (!uhid)
+		return -EINVAL;
+
+	memset(&ev, 0, sizeof(ev));
+	ev.type = UHID_INPUT2;
+
+	if (number) {
+		req->data[len++] = number;
+		req->size = 1 + MIN(size, sizeof(req->data) - 1);
+	} else
+		req->size = MIN(size, sizeof(req->data));
+
+	if (data && size)
+		memcpy(&req->data[len], data, req->size - len);
+
+	/* Queue events if UHID_START has not been received yet */
+	if (!uhid->started) {
+		if (!uhid->input)
+			uhid->input = queue_new();
+
+		queue_push_tail(uhid->input, util_memdup(&ev, sizeof(ev)));
+		return 0;
+	}
+
+	return bt_uhid_send(uhid, &ev);
+}
+
+int bt_uhid_set_report_reply(struct bt_uhid *uhid, uint8_t id, uint8_t status)
+{
+	struct uhid_event ev;
+	struct uhid_set_report_reply_req *rsp = &ev.u.set_report_reply;
+
+	if (!uhid)
+		return false;
+
+	memset(&ev, 0, sizeof(ev));
+	ev.type = UHID_SET_REPORT_REPLY;
+	rsp->id = id;
+	rsp->err = status;
+
+	return bt_uhid_send(uhid, &ev);
+}
+
+int bt_uhid_get_report_reply(struct bt_uhid *uhid, uint8_t id, uint8_t number,
+				uint8_t status, const void *data, size_t size)
+{
+	struct uhid_event ev;
+	struct uhid_get_report_reply_req *rsp = &ev.u.get_report_reply;
+	size_t len = 0;
+
+	if (!uhid)
+		return false;
+
+	memset(&ev, 0, sizeof(ev));
+	ev.type = UHID_GET_REPORT_REPLY;
+	rsp->id = id;
+	rsp->err = status;
+
+	if (!data || !size)
+		goto done;
+
+	if (number) {
+		rsp->data[len++] = number;
+		rsp->size += MIN(size, sizeof(rsp->data) - 1);
+	} else
+		rsp->size = MIN(size, sizeof(ev.u.input.data));
+
+	memcpy(&rsp->data[len], data, rsp->size - len);
+
+done:
+	return bt_uhid_send(uhid, &ev);
+}
+
+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..d70533882727 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,15 @@  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_input(struct bt_uhid *uhid, uint8_t number, const void *data,
+			size_t size);
+int bt_uhid_set_report_reply(struct bt_uhid *uhid, uint8_t id, uint8_t status);
+int bt_uhid_get_report_reply(struct bt_uhid *uhid, uint8_t id, uint8_t number,
+				uint8_t status, const void *data, size_t size);
+int bt_uhid_destroy(struct bt_uhid *uhid);