[PATCH] core: add D-Bus property for ManufacturerData

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

 



---
 doc/device-api.txt | 10 +++++++
 src/adapter.c      |  1 +
 src/device.c       | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/device.h       |  2 ++
 src/eir.c          | 30 ++++++++++++++++++++
 src/eir.h          | 10 +++++++
 6 files changed, 135 insertions(+)

diff --git a/doc/device-api.txt b/doc/device-api.txt
index 68388e9..4df6ec9 100644
--- a/doc/device-api.txt
+++ b/doc/device-api.txt
@@ -134,6 +134,16 @@ Properties	string Address [readonly]
 			List of 128-bit UUIDs that represents the available
 			remote services.
 
+		array{struct of data} ManufacturerData [readonly, optional]
+
+			List of manufacturer-specific data obtained from the
+			device. Each array member is a struct of uint16
+			containing the vendor identifier and an array of bytes
+			containing the manufacturer data.
+
+			Duplicate entries for a single manufacturer are
+			permitted.
+
 		boolean Paired [readonly]
 
 			Indicates if the remote device is paired.
diff --git a/src/adapter.c b/src/adapter.c
index 1b44dc5..037a3c3 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -4739,6 +4739,7 @@ static void update_found_devices(struct btd_adapter *adapter,
 							eir_data.did_version);
 
 	device_add_eir_uuids(dev, eir_data.services);
+	device_set_eir_manufacturer_data(dev, eir_data.manufacturer_data);
 
 	eir_data_free(&eir_data);
 
diff --git a/src/device.c b/src/device.c
index d4ebf4f..3e7a7b4 100644
--- a/src/device.c
+++ b/src/device.c
@@ -66,6 +66,7 @@
 #include "textfile.h"
 #include "storage.h"
 #include "attrib-server.h"
+#include "eir.h"
 
 #define IO_CAPABILITY_NOINPUTNOOUTPUT	0x03
 
@@ -174,6 +175,7 @@ struct btd_device {
 	bool		svc_refreshed;
 	GSList		*svc_callbacks;
 	GSList		*eir_uuids;
+	GSList		*eir_manufacturer_data;
 	char		name[MAX_NAME_LENGTH + 1];
 	char		*alias;
 	uint32_t	class;
@@ -515,6 +517,8 @@ static void device_free(gpointer user_data)
 {
 	struct btd_device *device = user_data;
 
+	g_slist_free_full(device->eir_manufacturer_data,
+				(GDestroyNotify)eir_manufacturer_data_free);
 	g_slist_free_full(device->uuids, g_free);
 	g_slist_free_full(device->primaries, g_free);
 	g_slist_free_full(device->attios, g_free);
@@ -970,6 +974,50 @@ static gboolean dev_property_get_uuids(const GDBusPropertyTable *property,
 	return TRUE;
 }
 
+static gboolean dev_property_exists_manufacturer_data(
+				const GDBusPropertyTable *property, void *data)
+{
+	struct btd_device *dev = data;
+
+	return dev->eir_manufacturer_data != NULL;
+}
+
+static gboolean dev_property_get_manufacturer_data(
+	const GDBusPropertyTable *property, DBusMessageIter *iter, void *data)
+{
+	struct btd_device *dev = data;
+	DBusMessageIter entry;
+	GSList *l;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+			DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+			DBUS_TYPE_UINT16_AS_STRING
+			DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING
+			DBUS_STRUCT_END_CHAR_AS_STRING, &entry);
+
+	for (l = dev->eir_manufacturer_data; l != NULL; l = l->next) {
+		struct eir_manufacturer_data *manufacturer_data = l->data;
+		DBusMessageIter member, array;
+
+		dbus_message_iter_open_container(&entry, DBUS_TYPE_STRUCT,
+							NULL, &member);
+		dbus_message_iter_append_basic(&member, DBUS_TYPE_UINT16,
+						&manufacturer_data->vendor);
+
+		dbus_message_iter_open_container(&member, DBUS_TYPE_ARRAY,
+					DBUS_TYPE_BYTE_AS_STRING, &array);
+		dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
+			&manufacturer_data->data, manufacturer_data->len);
+		dbus_message_iter_close_container(&member, &array);
+
+		dbus_message_iter_close_container(&entry, &member);
+	}
+
+	dbus_message_iter_close_container(iter, &entry);
+
+	return TRUE;
+}
+
 static gboolean dev_property_get_modalias(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
@@ -1333,6 +1381,38 @@ void device_add_eir_uuids(struct btd_device *dev, GSList *uuids)
 						DEVICE_INTERFACE, "UUIDs");
 }
 
+void device_set_eir_manufacturer_data(struct btd_device *dev,
+						GSList *manufacturer_data)
+{
+	GSList *l;
+	bool changed = false;
+
+	if (dev->eir_service_data) {
+		g_slist_free_full(dev->eir_manufacturer_data,
+				(GDestroyNotify)eir_manufacturer_data_free);
+		dev->eir_manufacturer_data = NULL;
+		changed = true;
+	}
+
+	for (l = manufacturer_data; l != NULL; l = l->next) {
+		struct eir_manufacturer_data *data = l->data;
+		struct eir_manufacturer_data *new_data;
+
+		new_data = g_new0(struct eir_manufacturer_data, 1);
+		new_data->vendor = data->vendor;
+		new_data->data = g_memdup(data->data, data->len);
+		new_data->len = data->len;
+
+		dev->eir_manufacturer_data = g_slist_append(
+				dev->eir_manufacturer_data, new_data);
+		changed = true;
+	}
+
+	if (changed)
+		g_dbus_emit_property_changed(dbus_conn, dev->path,
+					DEVICE_INTERFACE, "ManufacturerData");
+}
+
 static struct btd_service *find_connectable_service(struct btd_device *dev,
 							const char *uuid)
 {
@@ -1984,6 +2064,8 @@ static const GDBusPropertyTable device_properties[] = {
 						dev_property_exists_tx_power },
 	{ "Connected", "b", dev_property_get_connected },
 	{ "UUIDs", "as", dev_property_get_uuids },
+	{ "ManufacturerData", "a(qay)", dev_property_get_manufacturer_data,
+				NULL, dev_property_exists_manufacturer_data },
 	{ "Modalias", "s", dev_property_get_modalias, NULL,
 						dev_property_exists_modalias },
 	{ "Adapter", "o", dev_property_get_adapter },
diff --git a/src/device.h b/src/device.h
index b568593..783833a 100644
--- a/src/device.h
+++ b/src/device.h
@@ -72,6 +72,8 @@ void btd_device_gatt_set_service_changed(struct btd_device *device,
 bool device_attach_attrib(struct btd_device *dev, GIOChannel *io);
 void btd_device_add_uuid(struct btd_device *device, const char *uuid);
 void device_add_eir_uuids(struct btd_device *dev, GSList *uuids);
+void device_set_eir_manufacturer_data(struct btd_device *dev,
+						GSList *manufacturer_data);
 void device_probe_profile(gpointer a, gpointer b);
 void device_remove_profile(gpointer a, gpointer b);
 struct btd_adapter *device_get_adapter(struct btd_device *device);
diff --git a/src/eir.c b/src/eir.c
index d22ad91..d4594d6 100644
--- a/src/eir.c
+++ b/src/eir.c
@@ -43,10 +43,19 @@
 
 #define EIR_OOB_MIN (2 + 6)
 
+void eir_manufacturer_data_free(struct eir_manufacturer_data *manufacturer_data)
+{
+	g_free(manufacturer_data->data);
+	manufacturer_data->data = NULL;
+}
+
 void eir_data_free(struct eir_data *eir)
 {
 	g_slist_free_full(eir->services, free);
 	eir->services = NULL;
+	g_slist_free_full(eir->manufacturer_data,
+				(GDestroyNotify)eir_manufacturer_data_free);
+	eir->manufacturer_data = NULL;
 	g_free(eir->name);
 	eir->name = NULL;
 	g_free(eir->hash);
@@ -114,6 +123,23 @@ static void eir_parse_uuid128(struct eir_data *eir, const uint8_t *data,
 	}
 }
 
+static void eir_parse_manufacturer_data(struct eir_data *eir,
+					const uint8_t *data, uint8_t len)
+{
+	struct eir_manufacturer_data *manufacturer_data;
+
+	if (len < 2)
+		return;
+
+	manufacturer_data = g_new0(struct eir_manufacturer_data, 1);
+	manufacturer_data->vendor = get_le16(data);
+	manufacturer_data->data = g_memdup(data + 2, len - 2);
+	manufacturer_data->len = len - 2;
+
+	eir->manufacturer_data = g_slist_append(eir->manufacturer_data,
+							manufacturer_data);
+}
+
 static char *name2utf8(const uint8_t *name, uint8_t len)
 {
 	char utf8_name[HCI_MAX_NAME_LENGTH + 2];
@@ -240,6 +266,10 @@ void eir_parse(struct eir_data *eir, const uint8_t *eir_data, uint8_t eir_len)
 			eir->did_product = data[4] | (data[5] << 8);
 			eir->did_version = data[6] | (data[7] << 8);
 			break;
+
+		case EIR_MANUFACTURER_DATA:
+			eir_parse_manufacturer_data(eir, data, data_len);
+			break;
 		}
 
 		eir_data += field_len + 1;
diff --git a/src/eir.h b/src/eir.h
index e486fa2..65ba18a 100644
--- a/src/eir.h
+++ b/src/eir.h
@@ -37,6 +37,7 @@
 #define EIR_SSP_RANDOMIZER          0x0F  /* SSP Randomizer */
 #define EIR_DEVICE_ID               0x10  /* device ID */
 #define EIR_GAP_APPEARANCE          0x19  /* GAP appearance */
+#define EIR_MANUFACTURER_DATA       0xFF  /* Manufacturer-specific data */
 
 /* Flags Descriptions */
 #define EIR_LIM_DISC                0x01 /* LE Limited Discoverable Mode */
@@ -49,6 +50,7 @@
 
 struct eir_data {
 	GSList *services;
+	GSList *manufacturer_data;
 	unsigned int flags;
 	char *name;
 	uint32_t class;
@@ -64,6 +66,14 @@ struct eir_data {
 	uint16_t did_source;
 };
 
+struct eir_manufacturer_data {
+	uint16_t vendor;
+	uint8_t *data;
+	uint8_t len;
+};
+
+void eir_manufacturer_data_free(struct eir_manufacturer_data *
+							manufacturer_data);
 void eir_data_free(struct eir_data *eir);
 void eir_parse(struct eir_data *eir, const uint8_t *eir_data, uint8_t eir_len);
 int eir_parse_oob(struct eir_data *eir, uint8_t *eir_data, uint16_t eir_len);
-- 
2.1.0.rc2.206.gedb03e5

--
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