All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 BlueZ 1/7] android/hog: Port fixes to profiles HoG
@ 2015-11-12 15:46 Luiz Augusto von Dentz
  2015-11-12 15:46 ` [PATCH v2 BlueZ 2/7] bas: Move code from android to profiles Luiz Augusto von Dentz
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2015-11-12 15:46 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This align the 2 copies of Hog since the plan is to merge android
version back to profiles and just reuse from there.

The fix for incomplete discover is modified so the reports are keep
while attempting to discover.
---
v2: Fix devices queue not being initialized and attioid not being unregistered,
also adds better output when printing report details.

 android/hog.c | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/android/hog.c b/android/hog.c
index 22f4228..3af9329 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -88,6 +88,7 @@ struct bt_hog {
 	GSList			*reports;
 	struct bt_uhid		*uhid;
 	int			uhid_fd;
+	bool			uhid_created;
 	gboolean		has_report_id;
 	uint16_t		bcdhid;
 	uint8_t			bcountrycode;
@@ -496,9 +497,23 @@ static void report_read_cb(guint8 status, const guint8 *pdu, guint16 len,
 	report->len = len;
 }
 
+static int report_chrc_cmp(const void *data, const void *user_data)
+{
+	const struct report *report = data;
+	const struct gatt_char *decl = user_data;
+
+	return report->decl->handle - decl->handle;
+}
+
 static struct report *report_new(struct bt_hog *hog, struct gatt_char *chr)
 {
 	struct report *report;
+	GSList *l;
+
+	/* Skip if report already exists */
+	l = g_slist_find_custom(hog->reports, chr, report_chrc_cmp);
+	if (l)
+		return l->data;
 
 	report = g_new0(struct report, 1);
 	report->hog = hog;
@@ -939,6 +954,8 @@ static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
 
 	destroy_gatt_req(req);
 
+	DBG("HoG inspecting report map");
+
 	if (status != 0) {
 		error("Report Map read failed: %s", att_ecode2str(status));
 		return;
@@ -1006,6 +1023,10 @@ static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
 	bt_uhid_register(hog->uhid, UHID_FEATURE, get_feature, hog);
 	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;
+
+	DBG("HoG created uHID device");
 }
 
 static void info_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
@@ -1084,6 +1105,8 @@ static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data)
 
 	destroy_gatt_req(req);
 
+	DBG("HoG inspecting characteristics");
+
 	if (status != 0) {
 		const char *str = att_ecode2str(status);
 		DBG("Discover all characteristics failed: %s", str);
@@ -1116,6 +1139,7 @@ static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data)
 			report = report_new(hog, chr);
 			discover_report(hog, hog->attrib, start, end, report);
 		} else if (bt_uuid_cmp(&uuid, &report_map_uuid) == 0) {
+			DBG("HoG discovering report map");
 			read_char(hog, hog->attrib, chr->value_handle,
 						report_map_read_cb, hog);
 			discover_external(hog, hog->attrib, start, end, hog);
@@ -1404,7 +1428,8 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
 		bt_hog_attach(instance, gatt);
 	}
 
-	if (hog->reports == NULL) {
+	if (!hog->uhid_created) {
+		DBG("HoG discovering characteristics");
 		discover_char(hog, hog->attrib, primary->range.start,
 						primary->range.end, NULL,
 						char_discovered_cb, hog);
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 BlueZ 2/7] bas: Move code from android to profiles
  2015-11-12 15:46 [PATCH v2 BlueZ 1/7] android/hog: Port fixes to profiles HoG Luiz Augusto von Dentz
@ 2015-11-12 15:46 ` Luiz Augusto von Dentz
  2015-11-12 15:46 ` [PATCH v2 BlueZ 3/7] scpp: " Luiz Augusto von Dentz
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2015-11-12 15:46 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This is a place holder until the code is ported to use shared API so it
can be shared by android and D-Bus daemon.
---
 Makefile.am                         | 2 +-
 android/Android.mk                  | 2 +-
 android/Makefile.am                 | 2 +-
 android/hog.c                       | 2 +-
 {android => profiles/battery}/bas.c | 2 +-
 {android => profiles/battery}/bas.h | 0
 6 files changed, 5 insertions(+), 5 deletions(-)
 rename {android => profiles/battery}/bas.c (99%)
 rename {android => profiles/battery}/bas.h (100%)

diff --git a/Makefile.am b/Makefile.am
index 614922e..1027613 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -402,7 +402,7 @@ unit_test_hog_SOURCES = unit/test-hog.c \
 			$(btio_sources) \
 			android/hog.h android/hog.c \
 			android/scpp.h android/scpp.c \
-			android/bas.h android/bas.c \
+			profiles/battery/bas.h profiles/battery/bas.c \
 			android/dis.h android/dis.c \
 			src/log.h src/log.c \
 			attrib/att.h attrib/att.c \
diff --git a/android/Android.mk b/android/Android.mk
index 89ca2c2..2f1f6bb 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -41,7 +41,7 @@ LOCAL_SRC_FILES := \
 	bluez/android/bluetooth.c \
 	bluez/android/scpp.c \
 	bluez/android/dis.c \
-	bluez/android/bas.c \
+	bluez/profiles/battery/bas.c \
 	bluez/android/hog.c \
 	bluez/android/hidhost.c \
 	bluez/android/socket.c \
diff --git a/android/Makefile.am b/android/Makefile.am
index cb32bc3..63bcb63 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -30,7 +30,7 @@ android_bluetoothd_SOURCES = android/main.c \
 				android/hidhost.h android/hidhost.c \
 				android/scpp.h android/scpp.c \
 				android/dis.h android/dis.c \
-				android/bas.h android/bas.c \
+				profiles/battery/bas.h profiles/battery/bas.c \
 				android/hog.h android/hog.c \
 				android/ipc-common.h \
 				android/ipc.h android/ipc.c \
diff --git a/android/hog.c b/android/hog.c
index 3af9329..93e0655 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -55,7 +55,7 @@
 
 #include "android/scpp.h"
 #include "android/dis.h"
-#include "android/bas.h"
+#include "profiles/battery/bas.h"
 #include "android/hog.h"
 
 #define HOG_UUID		"00001812-0000-1000-8000-00805f9b34fb"
diff --git a/android/bas.c b/profiles/battery/bas.c
similarity index 99%
rename from android/bas.c
rename to profiles/battery/bas.c
index 7a1c4ca..de369fd 100644
--- a/android/bas.c
+++ b/profiles/battery/bas.c
@@ -43,7 +43,7 @@
 #include "attrib/att.h"
 #include "attrib/gatt.h"
 
-#include "android/bas.h"
+#include "profiles/battery/bas.h"
 
 #define ATT_NOTIFICATION_HEADER_SIZE 3
 #define ATT_READ_RESPONSE_HEADER_SIZE 1
diff --git a/android/bas.h b/profiles/battery/bas.h
similarity index 100%
rename from android/bas.h
rename to profiles/battery/bas.h
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 BlueZ 3/7] scpp: Move code from android to profiles
  2015-11-12 15:46 [PATCH v2 BlueZ 1/7] android/hog: Port fixes to profiles HoG Luiz Augusto von Dentz
  2015-11-12 15:46 ` [PATCH v2 BlueZ 2/7] bas: Move code from android to profiles Luiz Augusto von Dentz
@ 2015-11-12 15:46 ` Luiz Augusto von Dentz
  2015-11-12 15:46 ` [PATCH v2 BlueZ 4/7] dis: " Luiz Augusto von Dentz
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2015-11-12 15:46 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This is a place holder until the code is ported to use shared API so it
can be shared by android and D-Bus daemon.
---
 Makefile.am                            | 2 +-
 android/Android.mk                     | 2 +-
 android/Makefile.am                    | 3 ++-
 android/hog.c                          | 2 +-
 {android => profiles/scanparam}/scpp.c | 2 +-
 {android => profiles/scanparam}/scpp.h | 0
 6 files changed, 6 insertions(+), 5 deletions(-)
 rename {android => profiles/scanparam}/scpp.c (99%)
 rename {android => profiles/scanparam}/scpp.h (100%)

diff --git a/Makefile.am b/Makefile.am
index 1027613..34fb27f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -401,7 +401,7 @@ unit_tests += unit/test-hog
 unit_test_hog_SOURCES = unit/test-hog.c \
 			$(btio_sources) \
 			android/hog.h android/hog.c \
-			android/scpp.h android/scpp.c \
+			profiles/scanparam/scpp.h profiles/scanparam/scpp.c \
 			profiles/battery/bas.h profiles/battery/bas.c \
 			android/dis.h android/dis.c \
 			src/log.h src/log.c \
diff --git a/android/Android.mk b/android/Android.mk
index 2f1f6bb..03afacd 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -39,7 +39,7 @@ include $(CLEAR_VARS)
 LOCAL_SRC_FILES := \
 	bluez/android/main.c \
 	bluez/android/bluetooth.c \
-	bluez/android/scpp.c \
+	bluez/profiles/scanparam/scpp.c \
 	bluez/android/dis.c \
 	bluez/profiles/battery/bas.c \
 	bluez/android/hog.c \
diff --git a/android/Makefile.am b/android/Makefile.am
index 63bcb63..128e9dd 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -28,7 +28,8 @@ android_bluetoothd_SOURCES = android/main.c \
 				src/eir.h src/eir.c \
 				android/bluetooth.h android/bluetooth.c \
 				android/hidhost.h android/hidhost.c \
-				android/scpp.h android/scpp.c \
+				profiles/scanparam/scpp.h \
+				profiles/scanparam/scpp.c \
 				android/dis.h android/dis.c \
 				profiles/battery/bas.h profiles/battery/bas.c \
 				android/hog.h android/hog.c \
diff --git a/android/hog.c b/android/hog.c
index 93e0655..e0decac 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -53,7 +53,7 @@
 
 #include "btio/btio.h"
 
-#include "android/scpp.h"
+#include "profiles/scanparam/scpp.h"
 #include "android/dis.h"
 #include "profiles/battery/bas.h"
 #include "android/hog.h"
diff --git a/android/scpp.c b/profiles/scanparam/scpp.c
similarity index 99%
rename from android/scpp.c
rename to profiles/scanparam/scpp.c
index a432733..df65d2c 100644
--- a/android/scpp.c
+++ b/profiles/scanparam/scpp.c
@@ -44,7 +44,7 @@
 #include "attrib/gattrib.h"
 #include "attrib/gatt.h"
 
-#include "android/scpp.h"
+#include "profiles/scanparam/scpp.h"
 
 #define SCAN_INTERVAL_WIN_UUID		0x2A4F
 #define SCAN_REFRESH_UUID		0x2A31
diff --git a/android/scpp.h b/profiles/scanparam/scpp.h
similarity index 100%
rename from android/scpp.h
rename to profiles/scanparam/scpp.h
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 BlueZ 4/7] dis: Move code from android to profiles
  2015-11-12 15:46 [PATCH v2 BlueZ 1/7] android/hog: Port fixes to profiles HoG Luiz Augusto von Dentz
  2015-11-12 15:46 ` [PATCH v2 BlueZ 2/7] bas: Move code from android to profiles Luiz Augusto von Dentz
  2015-11-12 15:46 ` [PATCH v2 BlueZ 3/7] scpp: " Luiz Augusto von Dentz
@ 2015-11-12 15:46 ` Luiz Augusto von Dentz
  2015-11-12 15:46 ` [PATCH v2 BlueZ 5/7] hog: " Luiz Augusto von Dentz
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2015-11-12 15:46 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This is a place holder until the code is ported to use shared API so it
can be shared by android and D-Bus daemon.
---
 Makefile.am                            | 2 +-
 android/Android.mk                     | 2 +-
 android/Makefile.am                    | 3 ++-
 android/hog.c                          | 2 +-
 {android => profiles/deviceinfo}/dis.c | 2 +-
 {android => profiles/deviceinfo}/dis.h | 0
 6 files changed, 6 insertions(+), 5 deletions(-)
 rename {android => profiles/deviceinfo}/dis.c (99%)
 rename {android => profiles/deviceinfo}/dis.h (100%)

diff --git a/Makefile.am b/Makefile.am
index 34fb27f..3a29412 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -403,7 +403,7 @@ unit_test_hog_SOURCES = unit/test-hog.c \
 			android/hog.h android/hog.c \
 			profiles/scanparam/scpp.h profiles/scanparam/scpp.c \
 			profiles/battery/bas.h profiles/battery/bas.c \
-			android/dis.h android/dis.c \
+			profiles/deviceinfo/dis.h profiles/deviceinfo/dis.c \
 			src/log.h src/log.c \
 			attrib/att.h attrib/att.c \
 			attrib/gatt.h attrib/gatt.c \
diff --git a/android/Android.mk b/android/Android.mk
index 03afacd..1399178 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -40,7 +40,7 @@ LOCAL_SRC_FILES := \
 	bluez/android/main.c \
 	bluez/android/bluetooth.c \
 	bluez/profiles/scanparam/scpp.c \
-	bluez/android/dis.c \
+	bluez/profiles/deviceinfo/dis.c \
 	bluez/profiles/battery/bas.c \
 	bluez/android/hog.c \
 	bluez/android/hidhost.c \
diff --git a/android/Makefile.am b/android/Makefile.am
index 128e9dd..7d66929 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -30,7 +30,8 @@ android_bluetoothd_SOURCES = android/main.c \
 				android/hidhost.h android/hidhost.c \
 				profiles/scanparam/scpp.h \
 				profiles/scanparam/scpp.c \
-				android/dis.h android/dis.c \
+				profiles/deviceinfo/dis.h \
+				profiles/deviceinfo/dis.c \
 				profiles/battery/bas.h profiles/battery/bas.c \
 				android/hog.h android/hog.c \
 				android/ipc-common.h \
diff --git a/android/hog.c b/android/hog.c
index e0decac..ab1e008 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -54,7 +54,7 @@
 #include "btio/btio.h"
 
 #include "profiles/scanparam/scpp.h"
-#include "android/dis.h"
+#include "profiles/deviceinfo/dis.h"
 #include "profiles/battery/bas.h"
 #include "android/hog.h"
 
diff --git a/android/dis.c b/profiles/deviceinfo/dis.c
similarity index 99%
rename from android/dis.c
rename to profiles/deviceinfo/dis.c
index 0c20850..91c5d39 100644
--- a/android/dis.c
+++ b/profiles/deviceinfo/dis.c
@@ -42,7 +42,7 @@
 #include "attrib/att.h"
 #include "attrib/gatt.h"
 
-#include "android/dis.h"
+#include "profiles/deviceinfo/dis.h"
 
 #define PNP_ID_SIZE	7
 
diff --git a/android/dis.h b/profiles/deviceinfo/dis.h
similarity index 100%
rename from android/dis.h
rename to profiles/deviceinfo/dis.h
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 BlueZ 5/7] hog: Move code from android to profiles
  2015-11-12 15:46 [PATCH v2 BlueZ 1/7] android/hog: Port fixes to profiles HoG Luiz Augusto von Dentz
                   ` (2 preceding siblings ...)
  2015-11-12 15:46 ` [PATCH v2 BlueZ 4/7] dis: " Luiz Augusto von Dentz
@ 2015-11-12 15:46 ` Luiz Augusto von Dentz
  2015-11-12 15:46 ` [PATCH v2 BlueZ 6/7] input/hog: Make use of hog-lib Luiz Augusto von Dentz
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2015-11-12 15:46 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This is a place holder until the code is ported to use shared API so it
can be shared by android and D-Bus daemon.
---
 Makefile.am                               | 2 +-
 android/Android.mk                        | 2 +-
 android/Makefile.am                       | 3 ++-
 android/hidhost.c                         | 2 +-
 android/hog.c => profiles/input/hog-lib.c | 2 +-
 android/hog.h => profiles/input/hog-lib.h | 0
 unit/test-hog.c                           | 2 +-
 7 files changed, 7 insertions(+), 6 deletions(-)
 rename android/hog.c => profiles/input/hog-lib.c (99%)
 rename android/hog.h => profiles/input/hog-lib.h (100%)

diff --git a/Makefile.am b/Makefile.am
index 3a29412..444f6d5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -400,7 +400,7 @@ unit_tests += unit/test-hog
 
 unit_test_hog_SOURCES = unit/test-hog.c \
 			$(btio_sources) \
-			android/hog.h android/hog.c \
+			profiles/input/hog-lib.h profiles/input/hog-lib.c \
 			profiles/scanparam/scpp.h profiles/scanparam/scpp.c \
 			profiles/battery/bas.h profiles/battery/bas.c \
 			profiles/deviceinfo/dis.h profiles/deviceinfo/dis.c \
diff --git a/android/Android.mk b/android/Android.mk
index 1399178..694a94e 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -42,7 +42,7 @@ LOCAL_SRC_FILES := \
 	bluez/profiles/scanparam/scpp.c \
 	bluez/profiles/deviceinfo/dis.c \
 	bluez/profiles/battery/bas.c \
-	bluez/android/hog.c \
+	bluez/profiles/input/hog-lib.c \
 	bluez/android/hidhost.c \
 	bluez/android/socket.c \
 	bluez/android/ipc.c \
diff --git a/android/Makefile.am b/android/Makefile.am
index 7d66929..154f8db 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -33,7 +33,8 @@ android_bluetoothd_SOURCES = android/main.c \
 				profiles/deviceinfo/dis.h \
 				profiles/deviceinfo/dis.c \
 				profiles/battery/bas.h profiles/battery/bas.c \
-				android/hog.h android/hog.c \
+				profiles/input/hog-lib.h \
+				profiles/input/hog-lib.c \
 				android/ipc-common.h \
 				android/ipc.h android/ipc.c \
 				android/avdtp.h android/avdtp.c \
diff --git a/android/hidhost.c b/android/hidhost.c
index a2b820f..591ca95 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -44,13 +44,13 @@
 #include "src/sdp-client.h"
 #include "src/uuid-helper.h"
 #include "src/log.h"
+#include "profiles/input/hog-lib.h"
 
 #include "hal-msg.h"
 #include "ipc-common.h"
 #include "ipc.h"
 #include "bluetooth.h"
 #include "gatt.h"
-#include "hog.h"
 #include "hidhost.h"
 #include "utils.h"
 
diff --git a/android/hog.c b/profiles/input/hog-lib.c
similarity index 99%
rename from android/hog.c
rename to profiles/input/hog-lib.c
index ab1e008..a45e59f 100644
--- a/android/hog.c
+++ b/profiles/input/hog-lib.c
@@ -56,7 +56,7 @@
 #include "profiles/scanparam/scpp.h"
 #include "profiles/deviceinfo/dis.h"
 #include "profiles/battery/bas.h"
-#include "android/hog.h"
+#include "profiles/input/hog-lib.h"
 
 #define HOG_UUID		"00001812-0000-1000-8000-00805f9b34fb"
 
diff --git a/android/hog.h b/profiles/input/hog-lib.h
similarity index 100%
rename from android/hog.h
rename to profiles/input/hog-lib.h
diff --git a/unit/test-hog.c b/unit/test-hog.c
index 24731d7..9f026e5 100644
--- a/unit/test-hog.c
+++ b/unit/test-hog.c
@@ -37,7 +37,7 @@
 
 #include "attrib/gattrib.h"
 
-#include "android/hog.h"
+#include "profiles/input/hog-lib.h"
 
 struct test_pdu {
 	bool valid;
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 BlueZ 6/7] input/hog: Make use of hog-lib
  2015-11-12 15:46 [PATCH v2 BlueZ 1/7] android/hog: Port fixes to profiles HoG Luiz Augusto von Dentz
                   ` (3 preceding siblings ...)
  2015-11-12 15:46 ` [PATCH v2 BlueZ 5/7] hog: " Luiz Augusto von Dentz
@ 2015-11-12 15:46 ` Luiz Augusto von Dentz
  2015-11-12 15:46 ` [PATCH v2 BlueZ 7/7] input/hog-lib: Print report value handle and type Luiz Augusto von Dentz
  2015-11-13 12:31 ` [PATCH v2 BlueZ 1/7] android/hog: Port fixes to profiles HoG Luiz Augusto von Dentz
  6 siblings, 0 replies; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2015-11-12 15:46 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This changes the input plugin to use hog-lib so the same code is used in
both D-Bus daemon, Android and unit tests.
---
 Makefile.plugins     |   4 +
 profiles/input/hog.c | 966 +++------------------------------------------------
 2 files changed, 60 insertions(+), 910 deletions(-)

diff --git a/Makefile.plugins b/Makefile.plugins
index cae43d9..f85b642 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -60,6 +60,10 @@ builtin_sources += profiles/input/manager.c \
 
 builtin_modules += hog
 builtin_sources += profiles/input/hog.c profiles/input/uhid_copy.h \
+			profiles/input/hog-lib.c profiles/input/hog-lib.h \
+			profiles/deviceinfo/dis.c profiles/deviceinfo/dis.h \
+			profiles/battery/bas.c profiles/battery/bas.h \
+			profiles/scanparam/scpp.c profiles/scanparam/scpp.h \
 			profiles/input/suspend.h profiles/input/suspend-none.c
 
 EXTRA_DIST += profiles/input/suspend-dummy.c
diff --git a/profiles/input/hog.c b/profiles/input/hog.c
index e006add..935a920 100644
--- a/profiles/input/hog.c
+++ b/profiles/input/hog.c
@@ -48,6 +48,7 @@
 #include "src/service.h"
 #include "src/shared/util.h"
 #include "src/shared/uhid.h"
+#include "src/shared/queue.h"
 #include "src/plugin.h"
 
 #include "suspend.h"
@@ -55,939 +56,97 @@
 #include "attrib/gattrib.h"
 #include "src/attio.h"
 #include "attrib/gatt.h"
+#include "hog-lib.h"
 
 #define HOG_UUID		"00001812-0000-1000-8000-00805f9b34fb"
 
-#define HOG_INFO_UUID		0x2A4A
-#define HOG_REPORT_MAP_UUID	0x2A4B
-#define HOG_REPORT_UUID		0x2A4D
-#define HOG_PROTO_MODE_UUID	0x2A4E
-#define HOG_CONTROL_POINT_UUID	0x2A4C
-
-#define HOG_REPORT_TYPE_INPUT	1
-#define HOG_REPORT_TYPE_OUTPUT	2
-#define HOG_REPORT_TYPE_FEATURE	3
-
-#define HOG_PROTO_MODE_BOOT    0
-#define HOG_PROTO_MODE_REPORT  1
-
-#define HOG_REPORT_MAP_MAX_SIZE        512
-#define HID_INFO_SIZE			4
-#define ATT_NOTIFICATION_HEADER_SIZE	3
-
 struct hog_device {
-	uint16_t		id;
-	struct btd_device	*device;
-	GAttrib			*attrib;
 	guint			attioid;
-	struct gatt_primary	*hog_primary;
-	GSList			*reports;
-	struct bt_uhid		*uhid;
-	gboolean		uhid_created;
-	gboolean		has_report_id;
-	uint16_t		bcdhid;
-	uint8_t			bcountrycode;
-	uint16_t		proto_mode_handle;
-	uint16_t		ctrlpt_handle;
-	uint8_t			flags;
-	guint			getrep_att;
-	uint16_t		getrep_id;
-	guint			setrep_att;
-	uint16_t		setrep_id;
-};
-
-struct report {
-	uint8_t			id;
-	uint8_t			type;
-	uint16_t		ccc_handle;
-	guint			notifyid;
-	struct gatt_char	*decl;
-	struct hog_device	*hogdev;
+	struct btd_device	*device;
+	struct bt_hog		*hog;
 };
 
 static gboolean suspend_supported = FALSE;
-static GSList *devices = NULL;
-
-static void report_value_cb(const guint8 *pdu, guint16 len, gpointer user_data)
-{
-	struct report *report = user_data;
-	struct hog_device *hogdev = report->hogdev;
-	struct uhid_event ev;
-	uint8_t *buf;
-	int err;
-
-	if (len < ATT_NOTIFICATION_HEADER_SIZE) {
-		error("Malformed ATT notification");
-		return;
-	}
-
-	pdu += ATT_NOTIFICATION_HEADER_SIZE;
-	len -= ATT_NOTIFICATION_HEADER_SIZE;
-
-	memset(&ev, 0, sizeof(ev));
-	ev.type = UHID_INPUT;
-	buf = ev.u.input.data;
-
-	if (hogdev->has_report_id) {
-		buf[0] = report->id;
-		len = MIN(len, sizeof(ev.u.input.data) - 1);
-		memcpy(buf + 1, pdu, len);
-		ev.u.input.size = ++len;
-	} else {
-		len = MIN(len, sizeof(ev.u.input.data));
-		memcpy(buf, pdu, len);
-		ev.u.input.size = len;
-	}
-
-	err = bt_uhid_send(hogdev->uhid, &ev);
-	if (err < 0) {
-		error("bt_uhid_send: %s (%d)", strerror(-err), -err);
-		return;
-	}
-
-	DBG("HoG report (%u bytes)", ev.u.input.size);
-}
-
-static void report_ccc_written_cb(guint8 status, const guint8 *pdu,
-					guint16 plen, gpointer user_data)
-{
-	struct report *report = user_data;
-
-	if (status != 0) {
-		error("Report 0x%04x CCC write failed: %s",
-				report->decl->handle, att_ecode2str(status));
-		return;
-	}
-
-	DBG("Report 0x%04x CCC written: notifications enabled",
-							report->decl->handle);
-}
-
-static void enable_report_notifications(struct report *report,
-							bool enable_on_device)
-{
-	struct hog_device *hogdev = report->hogdev;
-	uint8_t value[2];
-
-	if (!hogdev->uhid_created)
-		return;
-
-	if (!report->ccc_handle)
-		return;
-
-	/* Register callback for HoG report notifications */
-	report->notifyid = g_attrib_register(hogdev->attrib,
-					ATT_OP_HANDLE_NOTIFY,
-					report->decl->value_handle,
-					report_value_cb, report, NULL);
-
-	if (!enable_on_device)
-		return;
-
-	/* Enable HoG report notifications on the HoG device */
-	put_le16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value);
-	gatt_write_char(hogdev->attrib, report->ccc_handle, value,
-				sizeof(value), report_ccc_written_cb, report);
-}
-
-static void report_reference_cb(guint8 status, const guint8 *pdu,
-					guint16 plen, gpointer user_data)
-{
-	struct report *report = user_data;
-
-	if (status != 0) {
-		error("Read Report Reference descriptor failed: %s",
-							att_ecode2str(status));
-		return;
-	}
-
-	if (plen != 3) {
-		error("Malformed ATT read response");
-		return;
-	}
-
-	report->id = pdu[1];
-	report->type = pdu[2];
-	DBG("Report ID: 0x%02x Report type: 0x%02x", pdu[1], pdu[2]);
-}
-
-static void external_report_reference_cb(guint8 status, const guint8 *pdu,
-					guint16 plen, gpointer user_data);
-
-
-static void discover_descriptor_cb(uint8_t status, GSList *descs,
-								void *user_data)
-{
-	struct report *report;
-	struct hog_device *hogdev;
-	GAttrib *attrib = NULL;
-
-	if (status != 0) {
-		error("Discover all descriptors failed: %s",
-							att_ecode2str(status));
-		return;
-	}
-
-	for ( ; descs; descs = descs->next) {
-		struct gatt_desc *desc = descs->data;
-
-		switch (desc->uuid16) {
-		case GATT_CLIENT_CHARAC_CFG_UUID:
-			report = user_data;
-			report->ccc_handle = desc->handle;
-			enable_report_notifications(report, true);
-			break;
-		case GATT_REPORT_REFERENCE:
-			report = user_data;
-			attrib = report->hogdev->attrib;
-			gatt_read_char(attrib, desc->handle,
-						report_reference_cb, report);
-			break;
-		case GATT_EXTERNAL_REPORT_REFERENCE:
-			hogdev = user_data;
-			attrib = hogdev->attrib;
-			gatt_read_char(attrib, desc->handle,
-					external_report_reference_cb, hogdev);
-			break;
-		}
-	}
-}
-
-static void discover_descriptor(GAttrib *attrib, uint16_t start, uint16_t end,
-							gpointer user_data)
-{
-	if (start > end)
-		return;
-
-	gatt_discover_desc(attrib, start, end, NULL,
-					discover_descriptor_cb, user_data);
-}
-
-static void external_service_char_cb(uint8_t status, GSList *chars,
-								void *user_data)
-{
-	struct hog_device *hogdev = user_data;
-	struct gatt_primary *prim = hogdev->hog_primary;
-	struct report *report;
-	GSList *l;
-
-	if (status != 0) {
-		const char *str = att_ecode2str(status);
-		DBG("Discover external service characteristic failed: %s", str);
-		return;
-	}
-
-	for (l = chars; l; l = g_slist_next(l)) {
-		struct gatt_char *chr, *next;
-		uint16_t start, end;
-
-		chr = l->data;
-		next = l->next ? l->next->data : NULL;
-
-		DBG("0x%04x UUID: %s properties: %02x",
-				chr->handle, chr->uuid, chr->properties);
-
-		report = g_new0(struct report, 1);
-		report->hogdev = hogdev;
-		report->decl = g_memdup(chr, sizeof(*chr));
-		hogdev->reports = g_slist_append(hogdev->reports, report);
-		start = chr->value_handle + 1;
-		end = (next ? next->handle - 1 : prim->range.end);
-		discover_descriptor(hogdev->attrib, start, end, report);
-	}
-}
-
-static void external_report_reference_cb(guint8 status, const guint8 *pdu,
-					guint16 plen, gpointer user_data)
-{
-	struct hog_device *hogdev = user_data;
-	uint16_t uuid16;
-	bt_uuid_t uuid;
-
-	if (status != 0) {
-		error("Read External Report Reference descriptor failed: %s",
-							att_ecode2str(status));
-		return;
-	}
-
-	if (plen != 3) {
-		error("Malformed ATT read response");
-		return;
-	}
-
-	uuid16 = get_le16(&pdu[1]);
-	DBG("External report reference read, external report characteristic "
-						"UUID: 0x%04x", uuid16);
-	bt_uuid16_create(&uuid, uuid16);
-	gatt_discover_char(hogdev->attrib, 0x0001, 0xffff, &uuid,
-					external_service_char_cb, hogdev);
-}
-
-static int report_cmp(gconstpointer a, gconstpointer b)
-{
-	const struct report *ra = a, *rb = b;
-
-	/* sort by type first.. */
-	if (ra->type != rb->type)
-		return ra->type - rb->type;
-
-	/* ..then by id */
-	return ra->id - rb->id;
-}
-
-static void output_written_cb(guint8 status, const guint8 *pdu,
-					guint16 plen, gpointer user_data)
-{
-	if (status != 0) {
-		error("Write output report failed: %s", att_ecode2str(status));
-		return;
-	}
-}
-
-static struct report *find_report(struct hog_device *hogdev, uint8_t type, uint8_t id)
-{
-	struct report cmp;
-	GSList *l;
-
-	switch (type) {
-	case UHID_FEATURE_REPORT:
-		cmp.type = HOG_REPORT_TYPE_FEATURE;
-		break;
-	case UHID_OUTPUT_REPORT:
-		cmp.type = HOG_REPORT_TYPE_OUTPUT;
-		break;
-	case UHID_INPUT_REPORT:
-		cmp.type = HOG_REPORT_TYPE_INPUT;
-		break;
-	default:
-		return NULL;
-	}
-
-	cmp.id = hogdev->has_report_id ? id : 0;
-
-	l = g_slist_find_custom(hogdev->reports, &cmp, report_cmp);
-
-	return l ? l->data : NULL;
-}
-
-static void forward_report(struct uhid_event *ev, void *user_data)
-{
-	struct hog_device *hogdev = user_data;
-	struct report *report;
-	void *data;
-	int size;
-
-	report = find_report(hogdev, ev->u.output.rtype, ev->u.output.data[0]);
-	if (!report)
-		return;
-
-	data = ev->u.output.data;
-	size = ev->u.output.size;
-	if (hogdev->has_report_id && size > 0) {
-		data++;
-		--size;
-	}
-
-	DBG("Sending report type %d ID %d to handle 0x%X", report->type,
-				report->id, report->decl->value_handle);
-
-	if (hogdev->attrib == NULL)
-		return;
-
-	if (report->decl->properties & GATT_CHR_PROP_WRITE)
-		gatt_write_char(hogdev->attrib, report->decl->value_handle,
-				data, size, output_written_cb, hogdev);
-	else if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
-		gatt_write_cmd(hogdev->attrib, report->decl->value_handle,
-						data, size, NULL, NULL);
-}
-
-static void set_report_cb(guint8 status, const guint8 *pdu,
-					guint16 plen, gpointer user_data)
-{
-	struct hog_device *hogdev = user_data;
-	struct uhid_event rsp;
-	int err;
-
-	hogdev->setrep_att = 0;
-
-	memset(&rsp, 0, sizeof(rsp));
-	rsp.type = UHID_SET_REPORT_REPLY;
-	rsp.u.set_report_reply.id = hogdev->setrep_id;
-	rsp.u.set_report_reply.err = status;
-
-	if (status != 0)
-		error("Error setting Report value: %s", att_ecode2str(status));
-
-	err = bt_uhid_send(hogdev->uhid, &rsp);
-	if (err < 0)
-		error("bt_uhid_send: %s", strerror(-err));
-}
-
-static void set_report(struct uhid_event *ev, void *user_data)
-{
-	struct hog_device *hogdev = user_data;
-	struct report *report;
-	void *data;
-	int size;
-	int err;
-
-	/* uhid never sends reqs in parallel; if there's a req, it timed out */
-	if (hogdev->setrep_att) {
-		g_attrib_cancel(hogdev->attrib, hogdev->setrep_att);
-		hogdev->setrep_att = 0;
-	}
-
-	hogdev->setrep_id = ev->u.set_report.id;
-
-	report = find_report(hogdev, ev->u.set_report.rtype,
-							ev->u.set_report.rnum);
-	if (!report) {
-		err = ENOTSUP;
-		goto fail;
-	}
-
-	data = ev->u.set_report.data;
-	size = ev->u.set_report.size;
-	if (hogdev->has_report_id && size > 0) {
-		data++;
-		--size;
-	}
-
-	DBG("Sending report type %d ID %d to handle 0x%X", report->type,
-				report->id, report->decl->value_handle);
-
-	if (hogdev->attrib == NULL)
-		return;
-
-	hogdev->setrep_att = gatt_write_char(hogdev->attrib,
-						report->decl->value_handle,
-						data, size, set_report_cb,
-						hogdev);
-	if (!hogdev->setrep_att) {
-		err = ENOMEM;
-		goto fail;
-	}
-
-	return;
-fail:
-	/* cancel the request on failure */
-	set_report_cb(err, NULL, 0, hogdev);
-}
-
-static void get_report_cb(guint8 status, const guint8 *pdu, guint16 len,
-							gpointer user_data)
-{
-	struct hog_device *hogdev = user_data;
-	struct uhid_event rsp;
-	int err;
-
-	hogdev->getrep_att = 0;
-
-	memset(&rsp, 0, sizeof(rsp));
-	rsp.type = UHID_GET_REPORT_REPLY;
-	rsp.u.get_report_reply.id = hogdev->getrep_id;
-
-	if (status != 0) {
-		error("Error reading Report value: %s", att_ecode2str(status));
-		goto exit;
-	}
-
-	if (len == 0) {
-		error("Error reading Report, length %d", len);
-		status = EIO;
-		goto exit;
-	}
-
-	if (pdu[0] != 0x0b) {
-		error("Error reading Report, invalid response: %02x", pdu[0]);
-		status = EPROTO;
-		goto exit;
-	}
-
-	--len;
-	++pdu;
-	if (hogdev->has_report_id && len > 0) {
-		--len;
-		++pdu;
-	}
-
-	rsp.u.get_report_reply.size = len;
-	memcpy(rsp.u.get_report_reply.data, pdu, len);
-
-exit:
-	rsp.u.get_report_reply.err = status;
-	err = bt_uhid_send(hogdev->uhid, &rsp);
-	if (err < 0)
-		error("bt_uhid_send: %s", strerror(-err));
-}
-
-static void get_report(struct uhid_event *ev, void *user_data)
-{
-	struct hog_device *hogdev = user_data;
-	struct report *report;
-	guint8 err;
-
-	/* uhid never sends reqs in parallel; if there's a req, it timed out */
-	if (hogdev->getrep_att) {
-		g_attrib_cancel(hogdev->attrib, hogdev->getrep_att);
-		hogdev->getrep_att = 0;
-	}
-
-	hogdev->getrep_id = ev->u.get_report.id;
-
-	report = find_report(hogdev, ev->u.get_report.rtype,
-							ev->u.get_report.rnum);
-	if (!report) {
-		err = ENOTSUP;
-		goto fail;
-	}
-
-	hogdev->getrep_att = gatt_read_char(hogdev->attrib,
-						report->decl->value_handle,
-						get_report_cb, hogdev);
-	if (!hogdev->getrep_att) {
-		err = ENOMEM;
-		goto fail;
-	}
-
-	return;
-
-fail:
-	/* cancel the request on failure */
-	get_report_cb(err, NULL, 0, hogdev);
-}
-
-static bool get_descriptor_item_info(uint8_t *buf, ssize_t blen, ssize_t *len,
-								bool *is_long)
-{
-	if (!blen)
-		return false;
-
-	*is_long = (buf[0] == 0xfe);
-
-	if (*is_long) {
-		if (blen < 3)
-			return false;
-
-		/*
-		 * long item:
-		 * byte 0 -> 0xFE
-		 * byte 1 -> data size
-		 * byte 2 -> tag
-		 * + data
-		 */
-
-		*len = buf[1] + 3;
-	} else {
-		uint8_t b_size;
-
-		/*
-		 * short item:
-		 * byte 0[1..0] -> data size (=0, 1, 2, 4)
-		 * byte 0[3..2] -> type
-		 * byte 0[7..4] -> tag
-		 * + data
-		 */
-
-		b_size = buf[0] & 0x03;
-		*len = (b_size ? 1 << (b_size - 1) : 0) + 1;
-	}
-
-	/* item length should be no more than input buffer length */
-	return *len <= blen;
-}
-
-static char *item2string(char *str, uint8_t *buf, uint8_t len)
-{
-	char *p = str;
-	int i;
-
-	/*
-	 * Since long item tags are not defined except for vendor ones, we
-	 * just ensure that short items are printed properly (up to 5 bytes).
-	 */
-	for (i = 0; i < 6 && i < len; i++)
-		p += sprintf(p, " %02x", buf[i]);
-
-	/*
-	 * If there are some data left, just add continuation mark to indicate
-	 * this.
-	 */
-	if (i < len)
-		sprintf(p, " ...");
-
-	return str;
-}
-
-static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
-							gpointer user_data)
-{
-	struct hog_device *hogdev = user_data;
-	struct btd_adapter *adapter = device_get_adapter(hogdev->device);
-	uint8_t value[HOG_REPORT_MAP_MAX_SIZE];
-	struct uhid_event ev;
-	uint16_t vendor_src, vendor, product, version;
-	ssize_t vlen;
-	char itemstr[20]; /* 5x3 (data) + 4 (continuation) + 1 (null) */
-	int i, err;
-	GSList *l;
-
-	DBG("HoG inspecting report map");
-
-	if (status != 0) {
-		error("Report Map read failed: %s", att_ecode2str(status));
-		return;
-	}
-
-	vlen = dec_read_resp(pdu, plen, value, sizeof(value));
-	if (vlen < 0) {
-		error("ATT protocol error");
-		return;
-	}
-
-	DBG("Report MAP:");
-	for (i = 0; i < vlen;) {
-		ssize_t ilen = 0;
-		bool long_item = false;
-
-		if (get_descriptor_item_info(&value[i], vlen - i, &ilen,
-								&long_item)) {
-			/* Report ID is short item with prefix 100001xx */
-			if (!long_item && (value[i] & 0xfc) == 0x84)
-				hogdev->has_report_id = TRUE;
-
-			DBG("\t%s", item2string(itemstr, &value[i], ilen));
-
-			i += ilen;
-		} else {
-			error("Report Map parsing failed at %d", i);
-
-			/* Just print remaining items at once and break */
-			DBG("\t%s", item2string(itemstr, &value[i], vlen - i));
-			break;
-		}
-	}
-
-	vendor_src = btd_device_get_vendor_src(hogdev->device);
-	vendor = btd_device_get_vendor(hogdev->device);
-	product = btd_device_get_product(hogdev->device);
-	version = btd_device_get_version(hogdev->device);
-	DBG("DIS information: vendor_src=0x%X, vendor=0x%X, product=0x%X, "
-			"version=0x%X",	vendor_src, vendor, product, version);
-
-	/* create uHID device */
-	memset(&ev, 0, sizeof(ev));
-	ev.type = UHID_CREATE;
-	if (device_name_known(hogdev->device))
-		device_get_name(hogdev->device, (char *) ev.u.create.name,
-						sizeof(ev.u.create.name));
-	else
-		strcpy((char *) ev.u.create.name, "bluez-hog-device");
-	ba2str(btd_adapter_get_address(adapter), (char *) ev.u.create.phys);
-	ba2str(device_get_address(hogdev->device), (char *) ev.u.create.uniq);
-	ev.u.create.vendor = vendor;
-	ev.u.create.product = product;
-	ev.u.create.version = version;
-	ev.u.create.country = hogdev->bcountrycode;
-	ev.u.create.bus = BUS_BLUETOOTH;
-	ev.u.create.rd_data = value;
-	ev.u.create.rd_size = vlen;
-
-	err = bt_uhid_send(hogdev->uhid, &ev);
-	if (err < 0) {
-		error("bt_uhid_send: %s", strerror(-err));
-		return;
-	}
-
-	bt_uhid_register(hogdev->uhid, UHID_OUTPUT, forward_report, hogdev);
-	bt_uhid_register(hogdev->uhid, UHID_SET_REPORT, set_report, hogdev);
-	bt_uhid_register(hogdev->uhid, UHID_GET_REPORT, get_report, hogdev);
-
-	hogdev->uhid_created = TRUE;
-	DBG("HoG created uHID device");
-
-	for (l = hogdev->reports; l; l = l->next) {
-		struct report *r = l->data;
-
-		enable_report_notifications(r, true);
-	}
-}
-
-static void info_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
-							gpointer user_data)
-{
-	struct hog_device *hogdev = user_data;
-	uint8_t value[HID_INFO_SIZE];
-	ssize_t vlen;
-
-	if (status != 0) {
-		error("HID Information read failed: %s",
-						att_ecode2str(status));
-		return;
-	}
-
-	vlen = dec_read_resp(pdu, plen, value, sizeof(value));
-	if (vlen != 4) {
-		error("ATT protocol error");
-		return;
-	}
-
-	hogdev->bcdhid = get_le16(&value[0]);
-	hogdev->bcountrycode = value[2];
-	hogdev->flags = value[3];
-
-	DBG("bcdHID: 0x%04X bCountryCode: 0x%02X Flags: 0x%02X",
-			hogdev->bcdhid, hogdev->bcountrycode, hogdev->flags);
-}
-
-static void proto_mode_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
-							gpointer user_data)
-{
-	struct hog_device *hogdev = user_data;
-	uint8_t value;
-	ssize_t vlen;
-
-	if (status != 0) {
-		error("Protocol Mode characteristic read failed: %s",
-							att_ecode2str(status));
-		return;
-	}
-
-	vlen = dec_read_resp(pdu, plen, &value, sizeof(value));
-	if (vlen < 0) {
-		error("ATT protocol error");
-		return;
-	}
-
-	if (value == HOG_PROTO_MODE_BOOT) {
-		uint8_t nval = HOG_PROTO_MODE_REPORT;
-
-		DBG("HoG device 0x%04X is operating in Boot Procotol Mode",
-								hogdev->id);
-
-		gatt_write_cmd(hogdev->attrib, hogdev->proto_mode_handle, &nval,
-						sizeof(nval), NULL, NULL);
-	} else if (value == HOG_PROTO_MODE_REPORT)
-		DBG("HoG device 0x%04X is operating in Report Protocol Mode",
-								hogdev->id);
-}
-
-static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data)
-{
-	struct hog_device *hogdev = user_data;
-	struct gatt_primary *prim = hogdev->hog_primary;
-	bt_uuid_t report_uuid, report_map_uuid, info_uuid;
-	bt_uuid_t proto_mode_uuid, ctrlpt_uuid;
-	struct report *report;
-	GSList *l;
-	uint16_t info_handle = 0, proto_mode_handle = 0;
-
-	DBG("HoG inspecting characteristics");
-
-	if (status != 0) {
-		const char *str = att_ecode2str(status);
-		DBG("Discover all characteristics failed: %s", str);
-		return;
-	}
-
-	bt_uuid16_create(&report_uuid, HOG_REPORT_UUID);
-	bt_uuid16_create(&report_map_uuid, HOG_REPORT_MAP_UUID);
-	bt_uuid16_create(&info_uuid, HOG_INFO_UUID);
-	bt_uuid16_create(&proto_mode_uuid, HOG_PROTO_MODE_UUID);
-	bt_uuid16_create(&ctrlpt_uuid, HOG_CONTROL_POINT_UUID);
-
-	for (l = chars; l; l = g_slist_next(l)) {
-		struct gatt_char *chr, *next;
-		bt_uuid_t uuid;
-		uint16_t start, end;
-
-		chr = l->data;
-		next = l->next ? l->next->data : NULL;
-
-		DBG("0x%04x UUID: %s properties: %02x",
-				chr->handle, chr->uuid, chr->properties);
-
-		bt_string_to_uuid(&uuid, chr->uuid);
-
-		start = chr->value_handle + 1;
-		end = (next ? next->handle - 1 : prim->range.end);
-
-		if (bt_uuid_cmp(&uuid, &report_uuid) == 0) {
-			report = g_new0(struct report, 1);
-			report->hogdev = hogdev;
-			report->decl = g_memdup(chr, sizeof(*chr));
-			hogdev->reports = g_slist_append(hogdev->reports,
-								report);
-			discover_descriptor(hogdev->attrib, start, end, report);
-		} else if (bt_uuid_cmp(&uuid, &report_map_uuid) == 0) {
-			DBG("HoG discovering report map");
-			gatt_read_char(hogdev->attrib, chr->value_handle,
-						report_map_read_cb, hogdev);
-			discover_descriptor(hogdev->attrib, start, end, hogdev);
-		} else if (bt_uuid_cmp(&uuid, &info_uuid) == 0)
-			info_handle = chr->value_handle;
-		else if (bt_uuid_cmp(&uuid, &proto_mode_uuid) == 0)
-			proto_mode_handle = chr->value_handle;
-		else if (bt_uuid_cmp(&uuid, &ctrlpt_uuid) == 0)
-			hogdev->ctrlpt_handle = chr->value_handle;
-	}
-
-	if (proto_mode_handle) {
-		hogdev->proto_mode_handle = proto_mode_handle;
-		gatt_read_char(hogdev->attrib, proto_mode_handle,
-						proto_mode_read_cb, hogdev);
-	}
-
-	if (info_handle)
-		gatt_read_char(hogdev->attrib, info_handle, info_read_cb,
-									hogdev);
-}
-
-static void report_free(void *data)
-{
-	struct report *report = data;
-	struct hog_device *hogdev = report->hogdev;
-
-	if (hogdev->attrib)
-		g_attrib_unregister(hogdev->attrib, report->notifyid);
-
-	g_free(report->decl);
-	g_free(report);
-}
+static struct queue *devices = NULL;
 
 static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 {
-	struct hog_device *hogdev = user_data;
-	struct gatt_primary *prim = hogdev->hog_primary;
-	GSList *l;
+	struct hog_device *dev = user_data;
 
 	DBG("HoG connected");
 
-	if (!hogdev->uhid_created && hogdev->reports) {
-		DBG("HoG init failed previously, preparing for re-init");
-		g_slist_free_full(hogdev->reports, report_free);
-		hogdev->reports = NULL;
-	}
-
-	hogdev->attrib = g_attrib_ref(attrib);
-
-	if (hogdev->reports == NULL) {
-		DBG("HoG discovering characteristics");
-		gatt_discover_char(hogdev->attrib, prim->range.start,
-						prim->range.end, NULL,
-						char_discovered_cb, hogdev);
-		return;
-	}
-
-	for (l = hogdev->reports; l; l = l->next) {
-		struct report *r = l->data;
-
-		enable_report_notifications(r, false);
-	}
+	bt_hog_attach(dev->hog, attrib);
 }
 
 static void attio_disconnected_cb(gpointer user_data)
 {
-	struct hog_device *hogdev = user_data;
-	GSList *l;
+	struct hog_device *dev = user_data;
 
 	DBG("HoG disconnected");
 
-	for (l = hogdev->reports; l; l = l->next) {
-		struct report *r = l->data;
-
-		g_attrib_unregister(hogdev->attrib, r->notifyid);
-	}
-
-	g_attrib_unref(hogdev->attrib);
-	hogdev->attrib = NULL;
-}
-
-static struct hog_device *hog_new_device(struct btd_device *device,
-								uint16_t id)
-{
-	struct hog_device *hogdev;
-
-	hogdev = g_try_new0(struct hog_device, 1);
-	if (!hogdev)
-		return NULL;
-
-	hogdev->id = id;
-	hogdev->device = btd_device_ref(device);
-
-	return hogdev;
-}
-
-static void hog_free_device(struct hog_device *hogdev)
-{
-	btd_device_unref(hogdev->device);
-	g_slist_free_full(hogdev->reports, report_free);
-	g_attrib_unref(hogdev->attrib);
-	g_free(hogdev->hog_primary);
-	g_free(hogdev);
+	bt_hog_detach(dev->hog);
 }
 
-static struct hog_device *hog_register_device(struct btd_device *device,
+static struct hog_device *hog_device_new(struct btd_device *device,
 						struct gatt_primary *prim)
 {
-	struct hog_device *hogdev;
+	struct hog_device *dev;
+	char name[248];
+	uint16_t vendor, product, version;
 
-	hogdev = hog_new_device(device, prim->range.start);
-	if (!hogdev)
-		return NULL;
+	if (device_name_known(device))
+		device_get_name(device, name, sizeof(name));
+	else
+		strcpy(name, "bluez-hog-device");
 
-	hogdev->uhid = bt_uhid_new_default();
-	if (!hogdev->uhid) {
-		error("bt_uhid_new_default: failed");
-		hog_free_device(hogdev);
-		return NULL;
-	}
+	vendor = btd_device_get_vendor(device);
+	product = btd_device_get_product(device);
+	version = btd_device_get_version(device);
+
+	DBG("name=%s vendor=0x%X, product=0x%X, version=0x%X", name, vendor,
+							product, version);
 
-	hogdev->hog_primary = g_memdup(prim, sizeof(*prim));
+	dev = new0(struct hog_device, 1);
+	dev->device = btd_device_ref(device);
+	dev->hog = bt_hog_new_default(name, vendor, product, version, prim);
 
-	hogdev->attioid = btd_device_add_attio_callback(device,
+	/*
+	 * TODO: Remove attio callback and use .accept once using
+	 * bt_gatt_client.
+	 */
+	dev->attioid = btd_device_add_attio_callback(device,
 							attio_connected_cb,
 							attio_disconnected_cb,
-							hogdev);
+							dev);
 
-	return hogdev;
-}
+	if (!devices)
+		devices = queue_new();
 
-static int hog_unregister_device(struct hog_device *hogdev)
-{
-	btd_device_remove_attio_callback(hogdev->device, hogdev->attioid);
-	bt_uhid_unref(hogdev->uhid);
-	hog_free_device(hogdev);
+	queue_push_tail(devices, dev);
 
-	return 0;
+	return dev;
 }
 
-static int set_control_point(struct hog_device *hogdev, gboolean suspend)
+static void hog_device_free(void *data)
 {
-	uint8_t value = suspend ? 0x00 : 0x01;
-
-	if (hogdev->attrib == NULL)
-		return -ENOTCONN;
-
-	DBG("0x%4X HID Control Point: %s", hogdev->id, suspend ?
-						"Suspend" : "Exit Suspend");
+	struct hog_device *dev = data;
 
-	if (hogdev->ctrlpt_handle == 0)
-		return -ENOTSUP;
+	queue_remove(devices, dev);
+	if (queue_isempty(devices))
+		queue_destroy(devices, NULL);
 
-	gatt_write_cmd(hogdev->attrib, hogdev->ctrlpt_handle, &value,
-					sizeof(value), NULL, NULL);
-
-	return 0;
+	btd_device_remove_attio_callback(dev->device, dev->attioid);
+	btd_device_unref(dev->device);
+	bt_hog_unref(dev->hog);
+	free(dev);
 }
 
 static void set_suspend(gpointer data, gpointer user_data)
 {
-	struct hog_device *hogdev = data;
+	struct hog_device *dev = data;
 	gboolean suspend = GPOINTER_TO_INT(user_data);
 
-	set_control_point(hogdev, suspend);
+	bt_hog_set_control_point(dev->hog, suspend);
 }
 
 static void suspend_callback(void)
@@ -996,7 +155,7 @@ static void suspend_callback(void)
 
 	DBG("Suspending ...");
 
-	g_slist_foreach(devices, set_suspend, GINT_TO_POINTER(suspend));
+	queue_foreach(devices, set_suspend, GINT_TO_POINTER(suspend));
 }
 
 static void resume_callback(void)
@@ -1005,7 +164,7 @@ static void resume_callback(void)
 
 	DBG("Resuming ...");
 
-	g_slist_foreach(devices, set_suspend, GINT_TO_POINTER(suspend));
+	queue_foreach(devices, set_suspend, GINT_TO_POINTER(suspend));
 }
 
 static int hog_probe(struct btd_service *service)
@@ -1022,41 +181,28 @@ static int hog_probe(struct btd_service *service)
 
 	for (l = primaries; l; l = g_slist_next(l)) {
 		struct gatt_primary *prim = l->data;
-		struct hog_device *hogdev;
+		struct hog_device *dev;
 
 		if (strcmp(prim->uuid, HOG_UUID) != 0)
 			continue;
 
-		hogdev = hog_register_device(device, prim);
-		if (hogdev == NULL)
-			continue;
-
-		devices = g_slist_append(devices, hogdev);
+		dev = hog_device_new(device, prim);
+		btd_service_set_user_data(service, dev);
+		return 0;
 	}
 
-	return 0;
-}
-
-static void remove_device(gpointer a, gpointer b)
-{
-	struct hog_device *hogdev = a;
-	struct btd_device *device = b;
-
-	if (hogdev->device != device)
-		return;
-
-	devices = g_slist_remove(devices, hogdev);
-	hog_unregister_device(hogdev);
+	return -EINVAL;
 }
 
 static void hog_remove(struct btd_service *service)
 {
+	struct hog_device *dev = btd_service_get_user_data(service);
 	struct btd_device *device = btd_service_get_device(service);
 	const char *path = device_get_path(device);
 
 	DBG("path %s", path);
 
-	g_slist_foreach(devices, remove_device, device);
+	hog_device_free(dev);
 }
 
 static struct btd_profile hog_profile = {
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 BlueZ 7/7] input/hog-lib: Print report value handle and type
  2015-11-12 15:46 [PATCH v2 BlueZ 1/7] android/hog: Port fixes to profiles HoG Luiz Augusto von Dentz
                   ` (4 preceding siblings ...)
  2015-11-12 15:46 ` [PATCH v2 BlueZ 6/7] input/hog: Make use of hog-lib Luiz Augusto von Dentz
@ 2015-11-12 15:46 ` Luiz Augusto von Dentz
  2015-11-13 12:31 ` [PATCH v2 BlueZ 1/7] android/hog: Port fixes to profiles HoG Luiz Augusto von Dentz
  6 siblings, 0 replies; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2015-11-12 15:46 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This adds better debug logs when discovering report type.
---
 profiles/input/hog-lib.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/profiles/input/hog-lib.c b/profiles/input/hog-lib.c
index a45e59f..1df1799 100644
--- a/profiles/input/hog-lib.c
+++ b/profiles/input/hog-lib.c
@@ -369,6 +369,20 @@ static void ccc_read_cb(guint8 status, const guint8 *pdu, guint16 len,
 	write_ccc(report->hog, report->hog->attrib, report->ccc_handle, report);
 }
 
+static const char *type_to_string(uint8_t type)
+{
+	switch (type) {
+	case HOG_REPORT_TYPE_INPUT:
+		return "input";
+	case HOG_REPORT_TYPE_OUTPUT:
+		return "output";
+	case HOG_REPORT_TYPE_FEATURE:
+		return "feature";
+	}
+
+	return NULL;
+}
+
 static void report_reference_cb(guint8 status, const guint8 *pdu,
 					guint16 plen, gpointer user_data)
 {
@@ -390,7 +404,9 @@ static void report_reference_cb(guint8 status, const guint8 *pdu,
 
 	report->id = pdu[1];
 	report->type = pdu[2];
-	DBG("Report ID: 0x%02x Report type: 0x%02x", pdu[1], pdu[2]);
+
+	DBG("Report 0x%04x: id 0x%02x type %s", report->decl->value_handle,
+				report->id, type_to_string(report->type));
 
 	/* Enable notifications only for Input Reports */
 	if (report->type == HOG_REPORT_TYPE_INPUT)
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 BlueZ 1/7] android/hog: Port fixes to profiles HoG
  2015-11-12 15:46 [PATCH v2 BlueZ 1/7] android/hog: Port fixes to profiles HoG Luiz Augusto von Dentz
                   ` (5 preceding siblings ...)
  2015-11-12 15:46 ` [PATCH v2 BlueZ 7/7] input/hog-lib: Print report value handle and type Luiz Augusto von Dentz
@ 2015-11-13 12:31 ` Luiz Augusto von Dentz
  6 siblings, 0 replies; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2015-11-13 12:31 UTC (permalink / raw)
  To: linux-bluetooth

Hi,

On Thu, Nov 12, 2015 at 5:46 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> This align the 2 copies of Hog since the plan is to merge android
> version back to profiles and just reuse from there.
>
> The fix for incomplete discover is modified so the reports are keep
> while attempting to discover.
> ---
> v2: Fix devices queue not being initialized and attioid not being unregistered,
> also adds better output when printing report details.
>
>  android/hog.c | 27 ++++++++++++++++++++++++++-
>  1 file changed, 26 insertions(+), 1 deletion(-)
>
> diff --git a/android/hog.c b/android/hog.c
> index 22f4228..3af9329 100644
> --- a/android/hog.c
> +++ b/android/hog.c
> @@ -88,6 +88,7 @@ struct bt_hog {
>         GSList                  *reports;
>         struct bt_uhid          *uhid;
>         int                     uhid_fd;
> +       bool                    uhid_created;
>         gboolean                has_report_id;
>         uint16_t                bcdhid;
>         uint8_t                 bcountrycode;
> @@ -496,9 +497,23 @@ static void report_read_cb(guint8 status, const guint8 *pdu, guint16 len,
>         report->len = len;
>  }
>
> +static int report_chrc_cmp(const void *data, const void *user_data)
> +{
> +       const struct report *report = data;
> +       const struct gatt_char *decl = user_data;
> +
> +       return report->decl->handle - decl->handle;
> +}
> +
>  static struct report *report_new(struct bt_hog *hog, struct gatt_char *chr)
>  {
>         struct report *report;
> +       GSList *l;
> +
> +       /* Skip if report already exists */
> +       l = g_slist_find_custom(hog->reports, chr, report_chrc_cmp);
> +       if (l)
> +               return l->data;
>
>         report = g_new0(struct report, 1);
>         report->hog = hog;
> @@ -939,6 +954,8 @@ static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
>
>         destroy_gatt_req(req);
>
> +       DBG("HoG inspecting report map");
> +
>         if (status != 0) {
>                 error("Report Map read failed: %s", att_ecode2str(status));
>                 return;
> @@ -1006,6 +1023,10 @@ static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
>         bt_uhid_register(hog->uhid, UHID_FEATURE, get_feature, hog);
>         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;
> +
> +       DBG("HoG created uHID device");
>  }
>
>  static void info_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
> @@ -1084,6 +1105,8 @@ static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data)
>
>         destroy_gatt_req(req);
>
> +       DBG("HoG inspecting characteristics");
> +
>         if (status != 0) {
>                 const char *str = att_ecode2str(status);
>                 DBG("Discover all characteristics failed: %s", str);
> @@ -1116,6 +1139,7 @@ static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data)
>                         report = report_new(hog, chr);
>                         discover_report(hog, hog->attrib, start, end, report);
>                 } else if (bt_uuid_cmp(&uuid, &report_map_uuid) == 0) {
> +                       DBG("HoG discovering report map");
>                         read_char(hog, hog->attrib, chr->value_handle,
>                                                 report_map_read_cb, hog);
>                         discover_external(hog, hog->attrib, start, end, hog);
> @@ -1404,7 +1428,8 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
>                 bt_hog_attach(instance, gatt);
>         }
>
> -       if (hog->reports == NULL) {
> +       if (!hog->uhid_created) {
> +               DBG("HoG discovering characteristics");
>                 discover_char(hog, hog->attrib, primary->range.start,
>                                                 primary->range.end, NULL,
>                                                 char_discovered_cb, hog);
> --
> 2.4.3

Applied.


-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2015-11-13 12:31 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-12 15:46 [PATCH v2 BlueZ 1/7] android/hog: Port fixes to profiles HoG Luiz Augusto von Dentz
2015-11-12 15:46 ` [PATCH v2 BlueZ 2/7] bas: Move code from android to profiles Luiz Augusto von Dentz
2015-11-12 15:46 ` [PATCH v2 BlueZ 3/7] scpp: " Luiz Augusto von Dentz
2015-11-12 15:46 ` [PATCH v2 BlueZ 4/7] dis: " Luiz Augusto von Dentz
2015-11-12 15:46 ` [PATCH v2 BlueZ 5/7] hog: " Luiz Augusto von Dentz
2015-11-12 15:46 ` [PATCH v2 BlueZ 6/7] input/hog: Make use of hog-lib Luiz Augusto von Dentz
2015-11-12 15:46 ` [PATCH v2 BlueZ 7/7] input/hog-lib: Print report value handle and type Luiz Augusto von Dentz
2015-11-13 12:31 ` [PATCH v2 BlueZ 1/7] android/hog: Port fixes to profiles HoG Luiz Augusto von Dentz

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.