[PATCH BlueZ v1 2/2] hog: Add support for multiple instances

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds support for multiple HID services instances exposed by
the same remote device.
---
 profiles/input/hog_device.c  | 90 +++++++++++---------------------------------
 profiles/input/hog_device.h  |  3 +-
 profiles/input/hog_manager.c | 41 ++++++++++++--------
 3 files changed, 48 insertions(+), 86 deletions(-)

diff --git a/profiles/input/hog_device.c b/profiles/input/hog_device.c
index a558110..d0912f5 100644
--- a/profiles/input/hog_device.c
+++ b/profiles/input/hog_device.c
@@ -46,13 +46,13 @@
 #include "../src/adapter.h"
 #include "../src/device.h"
 
-#include "hog_device.h"
-
 #include "att.h"
 #include "gattrib.h"
 #include "attio.h"
 #include "gatt.h"
 
+#include "hog_device.h"
+
 #define HOG_INFO_UUID		0x2A4A
 #define HOG_REPORT_MAP_UUID	0x2A4B
 #define HOG_REPORT_UUID		0x2A4D
@@ -72,7 +72,7 @@
 #define HID_INFO_SIZE			4
 
 struct hog_device {
-	char			*path;
+	uint16_t		id;
 	struct btd_device	*device;
 	GAttrib			*attrib;
 	guint			attioid;
@@ -147,8 +147,8 @@ static void report_value_cb(const uint8_t *pdu, uint16_t len,
 	if (write(hogdev->uhid_fd, &ev, sizeof(ev)) < 0)
 		error("uHID write failed: %s", strerror(errno));
 	else
-		DBG("Report from HoG device %s written to uHID fd %d",
-						hogdev->path, hogdev->uhid_fd);
+		DBG("Report from HoG device 0x%04X written to uHID fd %d",
+						hogdev->id, hogdev->uhid_fd);
 }
 
 static void report_ccc_written_cb(guint8 status, const guint8 *pdu,
@@ -428,14 +428,14 @@ static void proto_mode_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
 	if (value == HOG_PROTO_MODE_BOOT) {
 		uint8_t nval = HOG_PROTO_MODE_REPORT;
 
-		DBG("HoG device %s is operating in Boot Procotol Mode",
-								hogdev->path);
+		DBG("HoG device 0x%04X is operating in Boot Procotol Mode",
+								hogdev->id);
 
 		gatt_write_char(hogdev->attrib, hogdev->proto_mode_handle, &nval,
 						sizeof(nval), NULL, NULL);
 	} else if (value == HOG_PROTO_MODE_REPORT)
-		DBG("HoG device %s is operating in Report Protocol Mode",
-								hogdev->path);
+		DBG("HoG device 0x%04X is operating in Report Protocol Mode",
+								hogdev->id);
 }
 
 static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
@@ -548,8 +548,8 @@ static void forward_report(struct hog_device *hogdev,
 
 	report = l->data;
 
-	DBG("Sending report type %d to device %s handle 0x%X", type,
-				hogdev->path, report->decl->value_handle);
+	DBG("Sending report type %d to device 0x%04X handle 0x%X", type,
+				hogdev->id, report->decl->value_handle);
 
 	if (report->decl->properties & ATT_CHAR_PROPER_WRITE)
 		gatt_write_char(hogdev->attrib, report->decl->value_handle,
@@ -633,20 +633,8 @@ static void attio_disconnected_cb(gpointer user_data)
 	hogdev->attrib = NULL;
 }
 
-struct hog_device *hog_device_find(GSList *list, const char *path)
-{
-	for (; list; list = list->next) {
-		struct hog_device *hogdev = list->data;
-
-		if (!strcmp(hogdev->path, path))
-			return hogdev;
-	}
-
-	return NULL;
-}
-
 static struct hog_device *hog_device_new(struct btd_device *device,
-							const char *path)
+								uint16_t id)
 {
 	struct hog_device *hogdev;
 
@@ -654,31 +642,12 @@ static struct hog_device *hog_device_new(struct btd_device *device,
 	if (!hogdev)
 		return NULL;
 
-	hogdev->path = g_strdup(path);
+	hogdev->id = id;
 	hogdev->device = btd_device_ref(device);
 
 	return hogdev;
 }
 
-static gint primary_uuid_cmp(gconstpointer a, gconstpointer b)
-{
-	const struct gatt_primary *prim = a;
-	const char *uuid = b;
-
-	return g_strcmp0(prim->uuid, uuid);
-}
-
-static struct gatt_primary *load_hog_primary(struct btd_device *device)
-{
-	GSList *primaries, *l;
-
-	primaries = btd_device_get_primaries(device);
-
-	l = g_slist_find_custom(primaries, HOG_UUID, primary_uuid_cmp);
-
-	return (l ? l->data : NULL);
-}
-
 static void report_free(void *data)
 {
 	struct report *report = data;
@@ -690,38 +659,27 @@ static void hog_device_free(struct hog_device *hogdev)
 {
 	btd_device_unref(hogdev->device);
 	g_slist_free_full(hogdev->reports, report_free);
-	g_free(hogdev->path);
 	g_free(hogdev->hog_primary);
 	g_free(hogdev);
 }
 
 struct hog_device *hog_device_register(struct btd_device *device,
-					const char *path, int *perr)
+						struct gatt_primary *prim)
 {
-	struct gatt_primary *prim;
 	struct hog_device *hogdev;
 	GIOCondition cond = G_IO_IN | G_IO_ERR | G_IO_NVAL;
 	GIOChannel *io;
-	int err;
 
-	prim = load_hog_primary(device);
-	if (!prim) {
-		err = -EINVAL;
-		goto failed;
-	}
-
-	hogdev = hog_device_new(device, path);
-	if (!hogdev) {
-		err = -ENOMEM;
-		goto failed;
-	}
+	hogdev = hog_device_new(device, prim->range.start);
+	if (!hogdev)
+		return NULL;
 
 	hogdev->uhid_fd = open(UHID_DEVICE_FILE, O_RDWR | O_CLOEXEC);
 	if (hogdev->uhid_fd < 0) {
-		err = -errno;
-		error("Failed to open uHID device: %s", strerror(-err));
+		error("Failed to open uHID device: %s(%d)", strerror(errno),
+									errno);
 		hog_device_free(hogdev);
-		goto failed;
+		return NULL;
 	}
 
 	io = g_io_channel_unix_new(hogdev->uhid_fd);
@@ -740,12 +698,6 @@ struct hog_device *hog_device_register(struct btd_device *device,
 	device_set_auto_connect(device, TRUE);
 
 	return hogdev;
-
-failed:
-	if (perr)
-		*perr = err;
-
-	return NULL;
 }
 
 int hog_device_unregister(struct hog_device *hogdev)
@@ -779,7 +731,7 @@ int hog_device_set_control_point(struct hog_device *hogdev, gboolean suspend)
 	if (hogdev->attrib == NULL)
 		return -ENOTCONN;
 
-	DBG("%s HID Control Point: %s", hogdev->path, suspend ?
+	DBG("0x%4X HID Control Point: %s", hogdev->id, suspend ?
 						"Suspend" : "Exit Suspend");
 
 	if (hogdev->ctrlpt_handle == 0)
diff --git a/profiles/input/hog_device.h b/profiles/input/hog_device.h
index 03f1c90..d1bfc08 100644
--- a/profiles/input/hog_device.h
+++ b/profiles/input/hog_device.h
@@ -28,7 +28,6 @@
 struct hog_device;
 
 struct hog_device *hog_device_register(struct btd_device *device,
-						const char *path, int *perr);
+						struct gatt_primary *prim);
 int hog_device_unregister(struct hog_device *hogdev);
-struct hog_device *hog_device_find(GSList *list, const char *path);
 int hog_device_set_control_point(struct hog_device *hogdev, gboolean suspend);
diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index 2d72444..362c38a 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -29,6 +29,9 @@
 #include <errno.h>
 #include <stdbool.h>
 
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/uuid.h>
+
 #include "log.h"
 #include "../src/adapter.h"
 #include "../src/device.h"
@@ -38,6 +41,9 @@
 #include "hcid.h"
 #include "device.h"
 #include "suspend.h"
+#include "att.h"
+#include "gattrib.h"
+#include "gatt.h"
 #include "hog_device.h"
 
 static gboolean suspend_supported = FALSE;
@@ -73,36 +79,41 @@ static int hog_device_probe(struct btd_profile *p, struct btd_device *device,
 								GSList *uuids)
 {
 	const char *path = device_get_path(device);
-	struct hog_device *hogdev;
-	int err;
+	GSList *primaries, *l;
 
 	DBG("path %s", path);
 
-	hogdev = hog_device_find(devices, path);
-	if (hogdev)
-		return -EALREADY;
+	primaries = btd_device_get_primaries(device);
+	if (primaries == NULL)
+		return -EINVAL;
 
-	hogdev = hog_device_register(device, path, &err);
-	if (hogdev == NULL)
-		return err;
+	for (l = primaries; l; l = g_slist_next(l)) {
+		struct gatt_primary *prim = l->data;
+		struct hog_device *hogdev;
 
-	devices = g_slist_append(devices, hogdev);
+		hogdev = hog_device_register(device, prim);
+		if (hogdev == NULL)
+			continue;
+
+		devices = g_slist_append(devices, hogdev);
+	}
 
 	return 0;
 }
 
+static void remove_device(gpointer hogdev, gpointer b)
+{
+	devices = g_slist_remove(devices, hogdev);
+	hog_device_unregister(hogdev);
+}
+
 static void hog_device_remove(struct btd_profile *p, struct btd_device *device)
 {
 	const gchar *path = device_get_path(device);
-	struct hog_device *hogdev;
 
 	DBG("path %s", path);
 
-	hogdev = hog_device_find(devices, path);
-	if (hogdev) {
-		devices = g_slist_remove(devices, hogdev);
-		hog_device_unregister(hogdev);
-	}
+	g_slist_foreach(devices, remove_device, NULL);
 }
 
 static struct btd_profile hog_profile = {
-- 
1.7.12

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux