* [PATCH BlueZ v0 08/10] core: PropertyChanged signal for Icon/Appearance
From: Claudio Takahasi @ 2012-08-15 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1345040407-17767-1-git-send-email-claudio.takahasi@openbossa.org>
This patch emits the PropertyChanged signal in the Device hierarchy when
the remote device Appearance characteristic is read. In general
Appearance is a static value, if the device doesn't expose the
Appearance value in the advertising data, the GAP plugin should read the
value using GATT read procedure.
---
src/device.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/src/device.c b/src/device.c
index f14ea82..d052dd0 100644
--- a/src/device.c
+++ b/src/device.c
@@ -3001,9 +3001,14 @@ void device_set_class(struct btd_device *device, uint32_t value)
void device_set_appearance(struct btd_device *device, uint16_t value)
{
DBusConnection *conn = get_dbus_connection();
+ const char *icon = gap_appearance_to_icon(value);
emit_property_changed(conn, device->path, DEVICE_INTERFACE,
"Appearance", DBUS_TYPE_UINT16, &value);
+
+ if (icon)
+ emit_property_changed(conn, device->path, DEVICE_INTERFACE,
+ "Icon", DBUS_TYPE_STRING, &icon);
}
static gboolean notify_attios(gpointer user_data)
--
1.7.8.6
^ permalink raw reply related
* [PATCH BlueZ v0 07/10] core: PropertyChanged signal for Icon/class
From: Claudio Takahasi @ 2012-08-15 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1345040407-17767-1-git-send-email-claudio.takahasi@openbossa.org>
This patch emits the PropertyChanged signal in the Device hierarchy when
the remote device class is updated.
---
src/device.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/src/device.c b/src/device.c
index ef9f1b2..f14ea82 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2988,9 +2988,14 @@ void btd_device_unref(struct btd_device *device)
void device_set_class(struct btd_device *device, uint32_t value)
{
DBusConnection *conn = get_dbus_connection();
+ const char *icon = class_to_icon(value);
emit_property_changed(conn, device->path, DEVICE_INTERFACE, "Class",
DBUS_TYPE_UINT32, &value);
+
+ if (icon)
+ emit_property_changed(conn, device->path, DEVICE_INTERFACE,
+ "Icon", DBUS_TYPE_STRING, &icon);
}
void device_set_appearance(struct btd_device *device, uint16_t value)
--
1.7.8.6
^ permalink raw reply related
* [PATCH BlueZ v0 06/10] gap: Emit PropertyChanged for Appearance
From: Claudio Takahasi @ 2012-08-15 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1345040407-17767-1-git-send-email-claudio.takahasi@openbossa.org>
Emit PropertyChanged changed signal in the Device hierarchy when the
Appearance characteristic value is read from the remote GAP service.
---
profiles/gap/gap.c | 2 ++
src/device.c | 8 ++++++++
src/device.h | 1 +
3 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/profiles/gap/gap.c b/profiles/gap/gap.c
index 4d21fb6..ff5715b 100644
--- a/profiles/gap/gap.c
+++ b/profiles/gap/gap.c
@@ -96,6 +96,8 @@ static void appearance_cb(guint8 status, const guint8 *pdu, guint16 plen,
DBG("Appearance: 0x%04x", app);
+ device_set_appearance(gap->device, app);
+
adapter_get_address(device_get_adapter(gap->device), &src);
device_get_address(gap->device, &dst, &type);
diff --git a/src/device.c b/src/device.c
index aeb2a86..ef9f1b2 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2993,6 +2993,14 @@ void device_set_class(struct btd_device *device, uint32_t value)
DBUS_TYPE_UINT32, &value);
}
+void device_set_appearance(struct btd_device *device, uint16_t value)
+{
+ DBusConnection *conn = get_dbus_connection();
+
+ emit_property_changed(conn, device->path, DEVICE_INTERFACE,
+ "Appearance", DBUS_TYPE_UINT16, &value);
+}
+
static gboolean notify_attios(gpointer user_data)
{
struct btd_device *device = user_data;
diff --git a/src/device.h b/src/device.h
index 26e17f7..c3a31e9 100644
--- a/src/device.h
+++ b/src/device.h
@@ -103,6 +103,7 @@ guint device_add_disconnect_watch(struct btd_device *device,
GDestroyNotify destroy);
void device_remove_disconnect_watch(struct btd_device *device, guint id);
void device_set_class(struct btd_device *device, uint32_t value);
+void device_set_appearance(struct btd_device *device, uint16_t value);
#define BTD_UUIDS(args...) ((const char *[]) { args, NULL } )
--
1.7.8.6
^ permalink raw reply related
* [PATCH BlueZ v0 05/10] core: Remove Appearance characteristic read
From: Claudio Takahasi @ 2012-08-15 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1345040407-17767-1-git-send-email-claudio.takahasi@openbossa.org>
This patch removes the Appearance characteristic read from the core.
Appearance characteristic is now being read by the GAP plugin.
---
src/device.c | 56 +-------------------------------------------------------
1 files changed, 1 insertions(+), 55 deletions(-)
diff --git a/src/device.c b/src/device.c
index f781298..aeb2a86 100644
--- a/src/device.c
+++ b/src/device.c
@@ -69,8 +69,6 @@
#define AUTO_CONNECTION_INTERVAL 5 /* Next connection attempt */
-#define APPEARANCE_CHR_UUID 0x2a01
-
struct btd_disconnect_data {
guint id;
disconnect_watch watch;
@@ -1832,51 +1830,10 @@ done:
return FALSE;
}
-static void appearance_cb(guint8 status, const guint8 *pdu, guint16 plen,
- gpointer user_data)
-{
- struct btd_device *device = user_data;
- struct btd_adapter *adapter = device->adapter;
- struct att_data_list *list = NULL;
- uint16_t app;
- bdaddr_t src;
- uint8_t *atval;
-
- if (status != 0) {
- DBG("Read characteristics by UUID failed: %s\n",
- att_ecode2str(status));
- goto done;
- }
-
- list = dec_read_by_type_resp(pdu, plen);
- if (list == NULL)
- goto done;
-
- if (list->len != 4) {
- DBG("Appearance value: invalid data");
- goto done;
- }
-
- /* A device shall have only one instance of the
- Appearance characteristic. */
- atval = list->data[0] + 2; /* skip handle value */
- app = att_get_u16(atval);
-
- adapter_get_address(adapter, &src);
- write_remote_appearance(&src, &device->bdaddr, device->bdaddr_type,
- app);
-
-done:
- att_data_list_free(list);
- if (device->attios == NULL && device->attios_offline == NULL)
- attio_cleanup(device);
-}
-
static void primary_cb(GSList *services, guint8 status, gpointer user_data)
{
struct browse_req *req = user_data;
struct btd_device *device = req->device;
- struct gatt_primary *gap_prim = NULL;
GSList *l, *uuids = NULL;
if (status) {
@@ -1894,24 +1851,13 @@ static void primary_cb(GSList *services, guint8 status, gpointer user_data)
for (l = services; l; l = l->next) {
struct gatt_primary *prim = l->data;
- if (strcmp(prim->uuid, GAP_UUID) == 0)
- gap_prim = prim;
-
uuids = g_slist_append(uuids, prim->uuid);
}
device_register_services(req->conn, device, g_slist_copy(services), -1);
device_probe_drivers(device, uuids);
- if (gap_prim) {
- /* Read appearance characteristic */
- bt_uuid_t uuid;
-
- bt_uuid16_create(&uuid, APPEARANCE_CHR_UUID);
-
- gatt_read_char_by_uuid(device->attrib, gap_prim->range.start,
- gap_prim->range.end, &uuid, appearance_cb, device);
- } else if (device->attios == NULL && device->attios_offline == NULL)
+ if (device->attios == NULL && device->attios_offline == NULL)
attio_cleanup(device);
g_slist_free(uuids);
--
1.7.8.6
^ permalink raw reply related
* [PATCH BlueZ v0 04/10] gap: Add storing Appearance
From: Claudio Takahasi @ 2012-08-15 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1345040407-17767-1-git-send-email-claudio.takahasi@openbossa.org>
This patch store the Appearance characteristic value read from the
remote device.
---
profiles/gap/gap.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/profiles/gap/gap.c b/profiles/gap/gap.c
index 0ecadb3..4d21fb6 100644
--- a/profiles/gap/gap.c
+++ b/profiles/gap/gap.c
@@ -69,8 +69,11 @@ static gint cmp_device(gconstpointer a, gconstpointer b)
static void appearance_cb(guint8 status, const guint8 *pdu, guint16 plen,
gpointer user_data)
{
+ struct gap *gap = user_data;
struct att_data_list *list = NULL;
+ bdaddr_t src, dst;
uint16_t app;
+ uint8_t type;
uint8_t *atval;
if (status != 0) {
@@ -93,6 +96,11 @@ static void appearance_cb(guint8 status, const guint8 *pdu, guint16 plen,
DBG("Appearance: 0x%04x", app);
+ adapter_get_address(device_get_adapter(gap->device), &src);
+ device_get_address(gap->device, &dst, &type);
+
+ write_remote_appearance(&src, &dst, type, app);
+
done:
att_data_list_free(list);
}
--
1.7.8.6
^ permalink raw reply related
* [PATCH BlueZ v0 03/10] gap: Add read Appearance characteristic
From: Claudio Takahasi @ 2012-08-15 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1345040407-17767-1-git-send-email-claudio.takahasi@openbossa.org>
This patch registers the ATTIO callbacks, and triggers the Appearance
characteristic read by UUID when the ATT connection is established, and
it's value is not found in the storage.
---
profiles/gap/gap.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 76 insertions(+), 0 deletions(-)
diff --git a/profiles/gap/gap.c b/profiles/gap/gap.c
index 7172975..0ecadb3 100644
--- a/profiles/gap/gap.c
+++ b/profiles/gap/gap.c
@@ -29,22 +29,32 @@
#include "adapter.h"
#include "device.h"
+#include "storage.h"
+
#include "att.h"
#include "gattrib.h"
+#include "attio.h"
#include "gatt.h"
+
#include "log.h"
#include "gap.h"
struct gap {
struct btd_device *device;
struct att_range range; /* GAP Primary service range */
+ GAttrib *attrib;
+ guint attioid;
};
static GSList *devices = NULL;
static void gap_free(struct gap *gap)
{
+ if (gap->attioid)
+ btd_device_remove_attio_callback(gap->device, gap->attioid);
+
btd_device_unref(gap->device);
+
g_free(gap);
}
@@ -56,6 +66,69 @@ static gint cmp_device(gconstpointer a, gconstpointer b)
return (gap->device == device ? 0 : -1);
}
+static void appearance_cb(guint8 status, const guint8 *pdu, guint16 plen,
+ gpointer user_data)
+{
+ struct att_data_list *list = NULL;
+ uint16_t app;
+ uint8_t *atval;
+
+ if (status != 0) {
+ DBG("Read characteristics by UUID failed: %s",
+ att_ecode2str(status));
+ return;
+ }
+
+ list = dec_read_by_type_resp(pdu, plen);
+ if (list == NULL)
+ return;
+
+ if (list->len != 4) {
+ DBG("Appearance value: invalid data");
+ goto done;
+ }
+
+ atval = list->data[0] + 2; /* skip handle value */
+ app = att_get_u16(atval);
+
+ DBG("Appearance: 0x%04x", app);
+
+done:
+ att_data_list_free(list);
+}
+
+static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
+{
+ struct gap *gap = user_data;
+ bdaddr_t src, dst;
+ bt_uuid_t app_uuid;
+ uint16_t app;
+ uint8_t type;
+
+ gap->attrib = g_attrib_ref(attrib);
+
+ adapter_get_address(device_get_adapter(gap->device), &src);
+ device_get_address(gap->device, &dst, &type);
+
+ if (read_remote_appearance(&src, &dst, type, &app) == 0)
+ return;
+
+ bt_uuid16_create(&app_uuid, GATT_CHARAC_APPEARANCE);
+
+ gatt_read_char_by_uuid(gap->attrib, gap->range.start, gap->range.end,
+ &app_uuid, appearance_cb, gap);
+
+ /* TODO: Read other GAP characteristics - See Core spec page 1739 */
+}
+
+static void attio_disconnected_cb(gpointer user_data)
+{
+ struct gap *gap = user_data;
+
+ g_attrib_unref(gap->attrib);
+ gap->attrib = NULL;
+}
+
int gap_register(struct btd_device *device, struct gatt_primary *prim)
{
struct gap *gap;
@@ -67,6 +140,9 @@ int gap_register(struct btd_device *device, struct gatt_primary *prim)
devices = g_slist_append(devices, gap);
+ gap->attioid = btd_device_add_attio_callback(device, attio_connected_cb,
+ attio_disconnected_cb, gap);
+
return 0;
}
--
1.7.8.6
^ permalink raw reply related
* [PATCH BlueZ v0 02/10] gap: Add GAP device registration
From: Claudio Takahasi @ 2012-08-15 14:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1345040407-17767-1-git-send-email-claudio.takahasi@openbossa.org>
This patch adds GAP device driver probe function and the skeleton of
the register GAP device function.
---
Makefile.am | 3 +-
profiles/gap/gap.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++
profiles/gap/gap.h | 24 +++++++++++++
profiles/gap/manager.c | 22 ++++++++++++-
4 files changed, 132 insertions(+), 2 deletions(-)
create mode 100644 profiles/gap/gap.c
create mode 100644 profiles/gap/gap.h
diff --git a/Makefile.am b/Makefile.am
index 2db3ce1..d0a8de6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -239,7 +239,8 @@ builtin_sources += profiles/thermometer/main.c \
profiles/deviceinfo/deviceinfo.h \
profiles/deviceinfo/deviceinfo.c \
profiles/gap/main.c profiles/gap/manager.h \
- profiles/gap/manager.c
+ profiles/gap/manager.c profiles/gap/gap.h \
+ profiles/gap/gap.c
endif
builtin_modules += formfactor
diff --git a/profiles/gap/gap.c b/profiles/gap/gap.c
new file mode 100644
index 0000000..7172975
--- /dev/null
+++ b/profiles/gap/gap.c
@@ -0,0 +1,85 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Instituto Nokia de Tecnologia - INdT
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <bluetooth/uuid.h>
+
+#include "adapter.h"
+#include "device.h"
+#include "att.h"
+#include "gattrib.h"
+#include "gatt.h"
+#include "log.h"
+#include "gap.h"
+
+struct gap {
+ struct btd_device *device;
+ struct att_range range; /* GAP Primary service range */
+};
+
+static GSList *devices = NULL;
+
+static void gap_free(struct gap *gap)
+{
+ btd_device_unref(gap->device);
+ g_free(gap);
+}
+
+static gint cmp_device(gconstpointer a, gconstpointer b)
+{
+ const struct gap *gap = a;
+ const struct btd_device *device = b;
+
+ return (gap->device == device ? 0 : -1);
+}
+
+int gap_register(struct btd_device *device, struct gatt_primary *prim)
+{
+ struct gap *gap;
+
+ gap = g_new0(struct gap, 1);
+ gap->range.start = prim->range.start;
+ gap->range.end = prim->range.end;
+ gap->device = btd_device_ref(device);
+
+ devices = g_slist_append(devices, gap);
+
+ return 0;
+}
+
+void gap_unregister(struct btd_device *device)
+{
+ struct gap *gap;
+ GSList *l;
+
+ l = g_slist_find_custom(devices, device, cmp_device);
+ if (l == NULL)
+ return;
+
+ gap = l->data;
+ devices = g_slist_remove(devices, gap);
+ gap_free(gap);
+}
diff --git a/profiles/gap/gap.h b/profiles/gap/gap.h
new file mode 100644
index 0000000..722750e
--- /dev/null
+++ b/profiles/gap/gap.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Instituto Nokia de Tecnologia - INdT
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+int gap_register(struct btd_device *device, struct gatt_primary *prim);
+void gap_unregister(struct btd_device *device);
diff --git a/profiles/gap/manager.c b/profiles/gap/manager.c
index f2e36f5..9c2f3eb 100644
--- a/profiles/gap/manager.c
+++ b/profiles/gap/manager.c
@@ -26,11 +26,31 @@
#include "adapter.h"
#include "device.h"
+#include "att.h"
+#include "gattrib.h"
+#include "gatt.h"
+#include "gap.h"
#include "manager.h"
+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 int gap_driver_probe(struct btd_device *device, GSList *uuids)
{
- return 0;
+ GSList *primaries, *l;
+
+ primaries = btd_device_get_primaries(device);
+
+ l = g_slist_find_custom(primaries, GAP_UUID, primary_uuid_cmp);
+ if (l == NULL)
+ return -EINVAL;
+
+ return gap_register(device, l->data);
}
static void gap_driver_remove(struct btd_device *device)
--
1.7.8.6
^ permalink raw reply related
* [PATCH BlueZ v0 01/10] gap: Add Generic Access Profile plugin skeleton
From: Claudio Takahasi @ 2012-08-15 14:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1345040407-17767-1-git-send-email-claudio.takahasi@openbossa.org>
Initial patch to create GATT based plugin to handle Generic Access
Profile service. GAP characteristics discovery will be moved from
device.c to this new plugin.
---
Makefile.am | 6 +++-
profiles/gap/main.c | 52 +++++++++++++++++++++++++++++++++++++++++++++
profiles/gap/manager.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++
profiles/gap/manager.h | 24 +++++++++++++++++++++
4 files changed, 135 insertions(+), 2 deletions(-)
create mode 100644 profiles/gap/main.c
create mode 100644 profiles/gap/manager.c
create mode 100644 profiles/gap/manager.h
diff --git a/Makefile.am b/Makefile.am
index a74709d..2db3ce1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -211,7 +211,7 @@ builtin_sources += profiles/health/hdp_main.c profiles/health/hdp_types.h \
endif
if GATTMODULES
-builtin_modules += thermometer alert time gatt_example proximity deviceinfo
+builtin_modules += thermometer alert time gatt_example proximity deviceinfo gap
builtin_sources += profiles/thermometer/main.c \
profiles/thermometer/manager.h \
profiles/thermometer/manager.c \
@@ -237,7 +237,9 @@ builtin_sources += profiles/thermometer/main.c \
profiles/deviceinfo/manager.h \
profiles/deviceinfo/manager.c \
profiles/deviceinfo/deviceinfo.h \
- profiles/deviceinfo/deviceinfo.c
+ profiles/deviceinfo/deviceinfo.c \
+ profiles/gap/main.c profiles/gap/manager.h \
+ profiles/gap/manager.c
endif
builtin_modules += formfactor
diff --git a/profiles/gap/main.c b/profiles/gap/main.c
new file mode 100644
index 0000000..7495807
--- /dev/null
+++ b/profiles/gap/main.c
@@ -0,0 +1,52 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Instituto Nokia de Tecnologia - INdT
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+#include <glib.h>
+#include <errno.h>
+
+#include "plugin.h"
+#include "manager.h"
+#include "hcid.h"
+#include "log.h"
+
+static int gap_init(void)
+{
+ if (!main_opts.gatt_enabled) {
+ error("GAP can not start: GATT is disabled");
+ return -ENOTSUP;
+ }
+
+ return gap_manager_init();
+}
+
+static void gap_exit(void)
+{
+ gap_manager_exit();
+}
+
+BLUETOOTH_PLUGIN_DEFINE(gap, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+ gap_init, gap_exit)
diff --git a/profiles/gap/manager.c b/profiles/gap/manager.c
new file mode 100644
index 0000000..f2e36f5
--- /dev/null
+++ b/profiles/gap/manager.c
@@ -0,0 +1,55 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Instituto Nokia de Tecnologia - INdT
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <glib.h>
+#include <errno.h>
+#include <bluetooth/uuid.h>
+
+#include "adapter.h"
+#include "device.h"
+#include "manager.h"
+
+static int gap_driver_probe(struct btd_device *device, GSList *uuids)
+{
+ return 0;
+}
+
+static void gap_driver_remove(struct btd_device *device)
+{
+}
+
+static struct btd_device_driver gap_device_driver = {
+ .name = "gap-driver",
+ .uuids = BTD_UUIDS(GAP_UUID),
+ .probe = gap_driver_probe,
+ .remove = gap_driver_remove
+};
+
+int gap_manager_init(void)
+{
+ return btd_register_device_driver(&gap_device_driver);
+}
+
+void gap_manager_exit(void)
+{
+ btd_unregister_device_driver(&gap_device_driver);
+}
diff --git a/profiles/gap/manager.h b/profiles/gap/manager.h
new file mode 100644
index 0000000..7bc947f
--- /dev/null
+++ b/profiles/gap/manager.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Instituto Nokia de Tecnologia - INdT
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+int gap_manager_init(void);
+void gap_manager_exit(void);
--
1.7.8.6
^ permalink raw reply related
* [PATCH BlueZ v0 00/10] GAP Plugin
From: Claudio Takahasi @ 2012-08-15 14:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
This patch series adds a new GATT based plugin for GAP service. The
objective is cleanup: moving some GATT related operations from the
device(core) to a GATT based plugin.
Claudio Takahasi (10):
gap: Add Generic Access Profile plugin skeleton
gap: Add GAP device registration
gap: Add read Appearance characteristic
gap: Add storing Appearance
core: Remove Appearance characteristic read
gap: Emit PropertyChanged for Appearance
core: PropertyChanged signal for Icon/class
core: PropertyChanged signal for Icon/Appearance
gap: Map Appearance value 0x0000 to unknown
gap: Don't store Appearance if value is "unknown"
Makefile.am | 7 ++-
profiles/gap/gap.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++++
profiles/gap/gap.h | 24 +++++++
profiles/gap/main.c | 52 ++++++++++++++
profiles/gap/manager.c | 75 +++++++++++++++++++++
profiles/gap/manager.h | 24 +++++++
src/dbus-common.c | 2 +
src/device.c | 74 +++++---------------
src/device.h | 1 +
9 files changed, 376 insertions(+), 57 deletions(-)
create mode 100644 profiles/gap/gap.c
create mode 100644 profiles/gap/gap.h
create mode 100644 profiles/gap/main.c
create mode 100644 profiles/gap/manager.c
create mode 100644 profiles/gap/manager.h
--
1.7.8.6
^ permalink raw reply
* [PATCH BlueZ] lib: Rename GAP UUID
From: Claudio Takahasi @ 2012-08-15 14:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1345040379-17704-1-git-send-email-claudio.takahasi@openbossa.org>
Cosmetic patch changing the GAP UUID declaration to follow the same
standard of the others GATT based services.
---
lib/uuid.h | 2 +-
src/device.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/uuid.h b/lib/uuid.h
index 2c2b351..3bad8cc 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -80,7 +80,7 @@ extern "C" {
#define DUN_GW_UUID "00001103-0000-1000-8000-00805f9b34fb"
-#define GAP_SVC_UUID "00001800-0000-1000-8000-00805f9b34fb"
+#define GAP_UUID "00001800-0000-1000-8000-00805f9b34fb"
#define PNP_UUID "00001200-0000-1000-8000-00805f9b34fb"
typedef struct {
diff --git a/src/device.c b/src/device.c
index dad9c79..f781298 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1894,7 +1894,7 @@ static void primary_cb(GSList *services, guint8 status, gpointer user_data)
for (l = services; l; l = l->next) {
struct gatt_primary *prim = l->data;
- if (strcmp(prim->uuid, GAP_SVC_UUID) == 0)
+ if (strcmp(prim->uuid, GAP_UUID) == 0)
gap_prim = prim;
uuids = g_slist_append(uuids, prim->uuid);
--
1.7.8.6
^ permalink raw reply related
* [PATCH BlueZ] deviceinfo: Remove redundant gattrib include
From: Claudio Takahasi @ 2012-08-15 14:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
---
profiles/deviceinfo/deviceinfo.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/profiles/deviceinfo/deviceinfo.c b/profiles/deviceinfo/deviceinfo.c
index 4548553..ca849ad 100644
--- a/profiles/deviceinfo/deviceinfo.c
+++ b/profiles/deviceinfo/deviceinfo.c
@@ -32,7 +32,6 @@
#include "gattrib.h"
#include "attio.h"
#include "att.h"
-#include "gattrib.h"
#include "gatt.h"
#include "log.h"
#include "deviceinfo.h"
--
1.7.8.6
^ permalink raw reply related
* Re: [RFCv0 14/21] Bluetooth: Handle physical link completion
From: Andrei Emeltchenko @ 2012-08-15 13:51 UTC (permalink / raw)
To: Mat Martineau; +Cc: linux-bluetooth, gustavo, pkrystad
In-Reply-To: <1343260274-11953-15-git-send-email-mathewm@codeaurora.org>
Hi Mat,
On Wed, Jul 25, 2012 at 04:51:06PM -0700, Mat Martineau wrote:
> Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
> ---
> net/bluetooth/l2cap_core.c | 147 +++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 147 insertions(+)
>
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index d981d87..7e253ce 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -975,6 +975,19 @@ static void l2cap_send_conn_req(struct l2cap_chan *chan)
> l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
> }
>
> +static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 chan_id)
> +{
> + struct l2cap_create_chan_req req;
> + req.scid = cpu_to_le16(chan->scid);
> + req.psm = chan->psm;
> + req.amp_id = chan_id;
> +
> + chan->ident = l2cap_get_ident(chan->conn);
> +
> + l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ,
> + sizeof(req), &req);
> +}
> +
> static void l2cap_move_setup(struct l2cap_chan *chan)
> {
> struct sk_buff *skb;
> @@ -4119,6 +4132,24 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn,
> return 0;
> }
>
> +static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id)
> +{
> + struct l2cap_move_chan_req req;
> + u8 ident;
> +
> + BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id);
> +
> + ident = l2cap_get_ident(chan->conn);
> + if (chan)
I think that the check is not needed otherwise you crash at referencing
chan->scid below.
> + chan->ident = ident;
> +
> + req.icid = cpu_to_le16(chan->scid);
> + req.dest_amp_id = dest_amp_id;
> +
> + l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req),
> + &req);
> +}
> +
> static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
> u16 icid, u16 result)
> {
> @@ -4284,6 +4315,122 @@ static void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
> }
> }
>
> +void l2cap_physical_cfm(struct l2cap_chan *chan, int result, u8 local_id,
> + u8 remote_id)
> +{
> + BT_DBG("chan %p, result %d, local_id %d, remote_id %d", chan, result,
> + local_id, remote_id);
> +
> + l2cap_chan_lock(chan);
> +
> + if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) {
> + l2cap_chan_unlock(chan);
> + return;
> + }
> +
> + if (chan->state != BT_CONNECTED) {
> + if (!test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
> + struct l2cap_conn_rsp rsp;
> + char buf[128];
> + rsp.scid = cpu_to_le16(chan->dcid);
> + rsp.dcid = cpu_to_le16(chan->scid);
> +
> + /* Incoming channel on AMP */
> + if (result == L2CAP_CR_SUCCESS) {
> + /* Send successful response */
> + rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
> + rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
> + } else {
> + /* Send negative response */
> + rsp.result = cpu_to_le16(L2CAP_CR_NO_MEM);
> + rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
> + }
> +
> + l2cap_send_cmd(chan->conn, chan->ident,
> + L2CAP_CREATE_CHAN_RSP,
> + sizeof(rsp), &rsp);
> +
> + if (result == L2CAP_CR_SUCCESS) {
> + __l2cap_state_change(chan, BT_CONFIG);
> + set_bit(CONF_REQ_SENT, &chan->conf_state);
> + l2cap_send_cmd(chan->conn,
> + l2cap_get_ident(chan->conn),
> + L2CAP_CONF_REQ,
> + l2cap_build_conf_req(chan, buf),
> + buf);
> + chan->num_conf_req++;
> + }
> + } else {
> + /* Outgoing channel on AMP */
> + if (result == L2CAP_CR_SUCCESS) {
> + chan->chan_id = local_id;
> + l2cap_send_create_chan_req(chan, remote_id);
> + } else {
> + /* Revert to BR/EDR connect */
> + l2cap_send_conn_req(chan);
> + }
> + }
> + } else if (result == L2CAP_MR_SUCCESS &&
> + chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
> + l2cap_move_setup(chan);
> + chan->move_id = local_id;
> + chan->move_state = L2CAP_MOVE_WAIT_RSP;
> +
> + l2cap_send_move_chan_req(chan, remote_id);
> + __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
> + } else if (result == L2CAP_MR_SUCCESS &&
> + chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
> + struct hci_chan *hchan = NULL;
> +
> + /* Placeholder - get hci_chan for logical link */
> +
> + if (hchan) {
> + if (hchan->state == BT_CONNECTED) {
> + /* Logical link is ready to go */
> + chan->hs_hcon = hchan->conn;
> + chan->hs_hcon->l2cap_data = chan->conn;
> + chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
> + l2cap_send_move_chan_rsp(chan->conn,
> + chan->move_cmd_ident,
> + chan->dcid,
> + L2CAP_MR_SUCCESS);
> +
> + l2cap_logical_cfm(chan, hchan,
> + L2CAP_MR_SUCCESS);
> + } else {
> + /* Wait for logical link to be ready */
> + chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
> + }
> + } else {
> + /* Logical link not available */
> + l2cap_send_move_chan_rsp(chan->conn,
> + chan->move_cmd_ident,
> + chan->dcid,
> + L2CAP_MR_NOT_ALLOWED);
> + }
> + } else {
> + if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
> + u8 rsp_result;
> + if (result == -EINVAL)
> + rsp_result = L2CAP_MR_BAD_ID;
> + else
> + rsp_result = L2CAP_MR_NOT_ALLOWED;
> +
> + l2cap_send_move_chan_rsp(chan->conn,
> + chan->move_cmd_ident,
> + chan->dcid, rsp_result);
> + }
> +
> + chan->move_role = L2CAP_MOVE_ROLE_NONE;
> + chan->move_state = L2CAP_MOVE_STABLE;
> +
> + /* Restart data transmission */
> + l2cap_ertm_send(chan);
> + }
> +
> + l2cap_chan_unlock(chan);
> +}
I feel that this function is too big. Maybe we could split channel move
and channel create operations?
Best regards
Andrei Emeltchenko
^ permalink raw reply
* Re: [PATCH v3 0/9] Add GATT Client Battery Service
From: Chen Ganir @ 2012-08-15 13:50 UTC (permalink / raw)
To: chen.ganir; +Cc: linux-bluetooth, jprvita
In-Reply-To: <1344435980-9866-1-git-send-email-chen.ganir@ti.com>
Ping ?
On 08/08/2012 05:26 PM, chen.ganir@ti.com wrote:
> From: Chen Ganir <chen.ganir@ti.com>
>
> Add suupport for LE GATT Client Battery Service.
>
> This plugin adds battery list to the btd_device, exposes DBUS API to list the
> device batteries, and allows querying for battery information. In addition this
> patch allows getting notifications for battery level changes.
>
> Look at doc/device-api.txt and doc/battery-api.txt for more information.
>
> This is version 3 of this patch set, rebased on top of the latest sources and
> fixes issues reported on the ML.
>
> Chen Ganir (9):
> Battery: Add Battery Service GATT Client
> Battery: Add connection logic
> Battery: Discover Characteristic Descriptors
> Battery: Get Battery ID
> Battery: Add Battery list to btd_device
> Battery: Add Battery D-BUS API
> Battery: Read Battery level characteristic
> Battery: Add support for notifications
> Battery: Emit property changed on first read
>
> Makefile.am | 10 +-
> doc/battery-api.txt | 38 ++++
> doc/device-api.txt | 5 +
> profiles/battery/battery.c | 536 ++++++++++++++++++++++++++++++++++++++++++++
> profiles/battery/battery.h | 26 +++
> profiles/battery/main.c | 67 ++++++
> profiles/battery/manager.c | 71 ++++++
> profiles/battery/manager.h | 24 ++
> src/device.c | 65 ++++++
> src/device.h | 3 +
> 10 files changed, 843 insertions(+), 2 deletions(-)
> create mode 100644 doc/battery-api.txt
> create mode 100644 profiles/battery/battery.c
> create mode 100644 profiles/battery/battery.h
> create mode 100644 profiles/battery/main.c
> create mode 100644 profiles/battery/manager.c
> create mode 100644 profiles/battery/manager.h
>
--
BR,
Chen Ganir
^ permalink raw reply
* [RFC hcidump 8/8] AVRCP: Add parsing for AddToNowPlaying PDU
From: Luiz Augusto von Dentz @ 2012-08-15 13:32 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1345037529-1828-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
parser/avrcp.c | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index 1fb085c..6948689 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -1396,6 +1396,44 @@ response:
printf("Status: 0x%02x (%s)\n", status, error2str(status));
}
+static void avrcp_add_to_now_playing_dump(int level, struct frame *frm,
+ uint8_t ctype, uint16_t len)
+{
+ uint64_t uid;
+ uint32_t uidcounter;
+ uint8_t scope, status;
+
+ p_indent(level, frm);
+
+ if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
+ goto response;
+
+ if (len < 11) {
+ printf("PDU Malformed\n");
+ raw_dump(level, frm);
+ return;
+ }
+
+ scope = get_u8(frm);
+ printf("Scope: 0x%02x (%s)\n", scope, scope2str(scope));
+
+ p_indent(level, frm);
+
+ uid = get_u64(frm);
+ printf("UID: 0x%16" PRIx64 " (%" PRIu64 ")\n", uid, uid);
+
+ p_indent(level, frm);
+
+ uidcounter = get_u16(frm);
+ printf("UIDCounter: 0x%04x (%u)\n", uidcounter, uidcounter);
+
+ return;
+
+response:
+ status = get_u8(frm);
+ printf("Status: 0x%02x (%s)\n", status, error2str(status));
+}
+
static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
{
uint8_t pduid, pt;
@@ -1471,6 +1509,9 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
case AVRCP_PLAY_ITEM:
avrcp_play_item_dump(level + 1, frm, ctype, len);
break;
+ case AVRCP_ADD_TO_NOW_PLAYING:
+ avrcp_add_to_now_playing_dump(level + 1, frm, ctype, len);
+ break;
default:
raw_dump(level, frm);
}
--
1.7.11.2
^ permalink raw reply related
* [RFC hcidump 7/8] AVRCP: Add parsing for Search PDU
From: Luiz Augusto von Dentz @ 2012-08-15 13:32 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1345037529-1828-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
parser/avrcp.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index 47dfc9b..1fb085c 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -2055,6 +2055,60 @@ response:
avrcp_attribute_entry_list_dump(level, frm, count);
}
+static void avrcp_search_dump(int level, struct frame *frm, uint8_t hdr,
+ uint16_t len)
+{
+ uint32_t uidcounter, items;
+ uint16_t charset;
+ uint8_t namelen, status;
+
+ p_indent(level, frm);
+
+ if (hdr & 0x02)
+ goto response;
+
+ if (len < 3) {
+ printf("PDU Malformed\n");
+ raw_dump(level, frm);
+ return;
+ }
+
+ charset = get_u16(frm);
+ printf("CharsetID: 0x%04x (%s)\n", charset, charset2str(charset));
+
+ p_indent(level, frm);
+
+ namelen = get_u8(frm);
+ printf("Length: 0x%02x (%u)\n", namelen, namelen);
+
+ p_indent(level, frm);
+
+ printf("String: ");
+ for (; namelen > 0; namelen--) {
+ uint8_t c = get_u8(frm);
+ printf("%1c", isprint(c) ? c : '.');
+ }
+
+ return;
+
+response:
+ status = get_u8(frm);
+ printf("Status: 0x%02x (%s)\n", status, error2str(status));
+
+ if (len == 1)
+ return;
+
+ p_indent(level, frm);
+
+ uidcounter = get_u16(frm);
+ printf("UIDCounter: 0x%04x (%u)\n", uidcounter, uidcounter);
+
+ p_indent(level, frm);
+
+ items = get_u32(frm);
+ printf("Number of Items: 0x%04x (%u)", items, items);
+}
+
static void avrcp_browsing_dump(int level, struct frame *frm, uint8_t hdr)
{
uint8_t pduid;
@@ -2085,6 +2139,9 @@ static void avrcp_browsing_dump(int level, struct frame *frm, uint8_t hdr)
case AVRCP_GET_ITEM_ATTRIBUTES:
avrcp_get_item_attributes_dump(level + 1, frm, hdr, len);
break;
+ case AVRCP_SEARCH:
+ avrcp_search_dump(level + 1, frm, hdr, len);
+ break;
default:
raw_dump(level, frm);
}
--
1.7.11.2
^ permalink raw reply related
* [RFC hcidump 6/8] AVRCP: Add parsing for PlayItem PDU
From: Luiz Augusto von Dentz @ 2012-08-15 13:32 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1345037529-1828-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
parser/avrcp.c | 73 +++++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 57 insertions(+), 16 deletions(-)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index 046368c..47dfc9b 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -1342,6 +1342,60 @@ response:
}
}
+static const char *scope2str(uint8_t scope)
+{
+ switch (scope) {
+ case AVRCP_MEDIA_PLAYER_LIST:
+ return "Media Player List";
+ case AVRCP_MEDIA_PLAYER_VFS:
+ return "Media Player Virtual Filesystem";
+ case AVRCP_MEDIA_SEARCH:
+ return "Search";
+ case AVRCP_MEDIA_NOW_PLAYING:
+ return "Now Playing";
+ default:
+ return "Unknown";
+ }
+}
+
+static void avrcp_play_item_dump(int level, struct frame *frm,
+ uint8_t ctype, uint16_t len)
+{
+ uint64_t uid;
+ uint32_t uidcounter;
+ uint8_t scope, status;
+
+ p_indent(level, frm);
+
+ if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
+ goto response;
+
+ if (len < 13) {
+ printf("PDU Malformed\n");
+ raw_dump(level, frm);
+ return;
+ }
+
+ scope = get_u8(frm);
+ printf("Scope: 0x%02x (%s)", scope, scope2str(scope));
+
+ p_indent(level, frm);
+
+ uid = get_u64(frm);
+ printf("UID: 0x%16" PRIx64 " (%" PRIu64 ")\n", uid, uid);
+
+ p_indent(level, frm);
+
+ uidcounter = get_u16(frm);
+ printf("UIDCounter: 0x%04x (%u)\n", uidcounter, uidcounter);
+
+ return;
+
+response:
+ status = get_u8(frm);
+ printf("Status: 0x%02x (%s)\n", status, error2str(status));
+}
+
static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
{
uint8_t pduid, pt;
@@ -1414,6 +1468,9 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
case AVRCP_SET_ADDRESSED_PLAYER:
avrcp_set_addressed_player(level + 1, frm, ctype, len);
break;
+ case AVRCP_PLAY_ITEM:
+ avrcp_play_item_dump(level + 1, frm, ctype, len);
+ break;
default:
raw_dump(level, frm);
}
@@ -1507,22 +1564,6 @@ static const char *subunit2str(uint8_t subunit)
}
}
-static const char *scope2str(uint8_t scope)
-{
- switch (scope) {
- case AVRCP_MEDIA_PLAYER_LIST:
- return "Media Player List";
- case AVRCP_MEDIA_PLAYER_VFS:
- return "Media Player Virtual Filesystem";
- case AVRCP_MEDIA_SEARCH:
- return "Search";
- case AVRCP_MEDIA_NOW_PLAYING:
- return "Now Playing";
- default:
- return "Unknown";
- }
-}
-
static const char *playertype2str(uint8_t type)
{
switch (type & 0x0F) {
--
1.7.11.2
^ permalink raw reply related
* [RFC hcidump 5/8] AVRCP: Add parsing for GetItemAttributes PDU
From: Luiz Augusto von Dentz @ 2012-08-15 13:32 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1345037529-1828-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
parser/avrcp.c | 129 ++++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 101 insertions(+), 28 deletions(-)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index 7059cb8..046368c 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -1718,6 +1718,41 @@ static const char *elementtype2str(uint8_t type)
return "Reserved";
}
+static void avrcp_attribute_entry_list_dump(int level, struct frame *frm,
+ uint8_t count)
+{
+ for (; count > 0; count--) {
+ uint32_t attr;
+ uint16_t charset;
+ uint8_t len;
+
+ p_indent(level, frm);
+
+ attr = get_u32(frm);
+ printf("AttributeID: 0x%08x (%s)\n", attr, mediattr2str(attr));
+
+ p_indent(level, frm);
+
+ charset = get_u16(frm);
+ printf("CharsetID: 0x%04x (%s)\n", charset,
+ charset2str(charset));
+
+ p_indent(level, frm);
+
+ len = get_u8(frm);
+ printf("AttributeLength: 0x%02x (%u)\n", len, len);
+
+ p_indent(level, frm);
+
+ printf("AttributeValue: ");
+ for (; len > 0; len--) {
+ uint8_t c = get_u8(frm);
+ printf("%1c", isprint(c) ? c : '.');
+ }
+ printf("\n");
+ }
+}
+
static void avrcp_media_element_item_dump(int level, struct frame *frm,
uint16_t len)
{
@@ -1763,34 +1798,7 @@ static void avrcp_media_element_item_dump(int level, struct frame *frm,
count = get_u8(frm);
printf("AttributeCount: 0x%02x (%u)\n", count, count);
- for (; count > 0; count--) {
- uint32_t attr;
-
- p_indent(level, frm);
-
- attr = get_u32(frm);
- printf("AttributeID: 0x%08x (%s)\n", attr, mediattr2str(attr));
-
- p_indent(level, frm);
-
- charset = get_u16(frm);
- printf("CharsetID: 0x%04x (%s)\n", charset,
- charset2str(charset));
-
- p_indent(level, frm);
-
- namelen = get_u8(frm);
- printf("AttributeLength: 0x%02x (%u)\n", namelen, namelen);
-
- p_indent(level, frm);
-
- printf("AttributeValue: ");
- for (; namelen > 0; namelen--) {
- uint8_t c = get_u8(frm);
- printf("%1c", isprint(c) ? c : '.');
- }
- printf("\n");
- }
+ avrcp_attribute_entry_list_dump(level, frm, count);
}
static void avrcp_get_folder_items_dump(int level, struct frame *frm,
@@ -1944,6 +1952,68 @@ response:
printf("Number of Items: 0x%04x (%u)", items, items);
}
+static void avrcp_get_item_attributes_dump(int level, struct frame *frm,
+ uint8_t hdr, uint16_t len)
+{
+ uint64_t uid;
+ uint32_t uidcounter;
+ uint8_t scope, count, status;
+
+ p_indent(level, frm);
+
+ if (hdr & 0x02)
+ goto response;
+
+ if (len < 12) {
+ printf("PDU Malformed\n");
+ raw_dump(level, frm);
+ return;
+ }
+
+ scope = get_u8(frm);
+ printf("Scope: 0x%02x (%s)\n", scope, scope2str(scope));
+
+ p_indent(level, frm);
+
+ uid = get_u64(frm);
+ printf("UID: 0x%16" PRIx64 " (%" PRIu64 ")\n", uid, uid);
+
+ p_indent(level, frm);
+
+ uidcounter = get_u16(frm);
+ printf("UIDCounter: 0x%04x (%u)\n", uidcounter, uidcounter);
+
+ p_indent(level, frm);
+
+ count = get_u32(frm);
+ printf("AttributeCount: 0x%04x (%u)", count, count);
+
+ for (; count > 0; count--) {
+ uint32_t attr;
+
+ p_indent(level, frm);
+
+ attr = get_u32(frm);
+ printf("AttributeID: 0x%08x (%s)\n", attr, mediattr2str(attr));
+ }
+
+ return;
+
+response:
+ status = get_u8(frm);
+ printf("Status: 0x%02x (%s)\n", status, error2str(status));
+
+ if (len == 1)
+ return;
+
+ p_indent(level, frm);
+
+ count = get_u32(frm);
+ printf("AttributeCount: 0x%04x (%u)", count, count);
+
+ avrcp_attribute_entry_list_dump(level, frm, count);
+}
+
static void avrcp_browsing_dump(int level, struct frame *frm, uint8_t hdr)
{
uint8_t pduid;
@@ -1971,6 +2041,9 @@ static void avrcp_browsing_dump(int level, struct frame *frm, uint8_t hdr)
case AVRCP_CHANGE_PATH:
avrcp_change_path_dump(level + 1, frm, hdr, len);
break;
+ case AVRCP_GET_ITEM_ATTRIBUTES:
+ avrcp_get_item_attributes_dump(level + 1, frm, hdr, len);
+ break;
default:
raw_dump(level, frm);
}
--
1.7.11.2
^ permalink raw reply related
* [RFC hcidump 4/8] AVRCP: Add parsing for ChangePath PDU
From: Luiz Augusto von Dentz @ 2012-08-15 13:32 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1345037529-1828-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
parser/avrcp.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 62 insertions(+)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index 9ceb507..7059cb8 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -1885,6 +1885,65 @@ response:
}
}
+static const char *dir2str(uint8_t dir)
+{
+ switch (dir) {
+ case 0x00:
+ return "Folder Up";
+ case 0x01:
+ return "Folder Down";
+ }
+
+ return "Reserved";
+}
+
+static void avrcp_change_path_dump(int level, struct frame *frm, uint8_t hdr,
+ uint16_t len)
+{
+ uint64_t uid;
+ uint32_t items;
+ uint16_t uidcounter;
+ uint8_t dir, status;
+
+ p_indent(level, frm);
+
+ if (hdr & 0x02)
+ goto response;
+
+ if (len < 11) {
+ printf("PDU Malformed\n");
+ raw_dump(level, frm);
+ return;
+ }
+
+ uidcounter = get_u16(frm);
+ printf("UIDCounter: 0x%04x (%u)\n", uidcounter, uidcounter);
+
+ p_indent(level, frm);
+
+ dir = get_u8(frm);
+ printf("Direction: 0x%02x (%s)\n", dir, dir2str(dir));
+
+ p_indent(level, frm);
+
+ uid = get_u64(frm);
+ printf("FolderUID: 0x%16" PRIx64 " (%" PRIu64 ")\n", uid, uid);
+
+ return;
+
+response:
+ status = get_u8(frm);
+ printf("Status: 0x%02x (%s)\n", status, error2str(status));
+
+ if (len == 1)
+ return;
+
+ p_indent(level, frm);
+
+ items = get_u32(frm);
+ printf("Number of Items: 0x%04x (%u)", items, items);
+}
+
static void avrcp_browsing_dump(int level, struct frame *frm, uint8_t hdr)
{
uint8_t pduid;
@@ -1909,6 +1968,9 @@ static void avrcp_browsing_dump(int level, struct frame *frm, uint8_t hdr)
case AVRCP_GET_FOLDER_ITEMS:
avrcp_get_folder_items_dump(level + 1, frm, hdr, len);
break;
+ case AVRCP_CHANGE_PATH:
+ avrcp_change_path_dump(level + 1, frm, hdr, len);
+ break;
default:
raw_dump(level, frm);
}
--
1.7.11.2
^ permalink raw reply related
* [RFC hcidump 3/8] AVRCP: Add parsing for GetFolderItems PDU
From: Luiz Augusto von Dentz @ 2012-08-15 13:32 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1345037529-1828-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
parser/avrcp.c | 389 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 389 insertions(+)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index 5179501..9ceb507 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -31,6 +31,7 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
+#include <inttypes.h>
#include "parser/parser.h"
@@ -179,6 +180,12 @@
#define AVRCP_PLAY_STATUS_REV_SEEK 0x04
#define AVRCP_PLAY_STATUS_ERROR 0xFF
+/* media scope */
+#define AVRCP_MEDIA_PLAYER_LIST 0x00
+#define AVRCP_MEDIA_PLAYER_VFS 0x01
+#define AVRCP_MEDIA_SEARCH 0x02
+#define AVRCP_MEDIA_NOW_PLAYING 0x03
+
static struct avrcp_continuing {
uint16_t num;
uint16_t size;
@@ -1207,6 +1214,7 @@ response:
uid = get_u16(frm);
printf("PlayerID: 0x%04x (%u)\n", uid, uid);
+
p_indent(level, frm);
uid = get_u16(frm);
@@ -1499,6 +1507,384 @@ static const char *subunit2str(uint8_t subunit)
}
}
+static const char *scope2str(uint8_t scope)
+{
+ switch (scope) {
+ case AVRCP_MEDIA_PLAYER_LIST:
+ return "Media Player List";
+ case AVRCP_MEDIA_PLAYER_VFS:
+ return "Media Player Virtual Filesystem";
+ case AVRCP_MEDIA_SEARCH:
+ return "Search";
+ case AVRCP_MEDIA_NOW_PLAYING:
+ return "Now Playing";
+ default:
+ return "Unknown";
+ }
+}
+
+static const char *playertype2str(uint8_t type)
+{
+ switch (type & 0x0F) {
+ case 0x01:
+ return "Audio";
+ case 0x02:
+ return "Video";
+ case 0x03:
+ return "Audio, Video";
+ case 0x04:
+ return "Audio Broadcasting";
+ case 0x05:
+ return "Audio, Audio Broadcasting";
+ case 0x06:
+ return "Video, Audio Broadcasting";
+ case 0x07:
+ return "Audio, Video, Audio Broadcasting";
+ case 0x08:
+ return "Video Broadcasting";
+ case 0x09:
+ return "Audio, Video Broadcasting";
+ case 0x0A:
+ return "Video, Video Broadcasting";
+ case 0x0B:
+ return "Audio, Video, Video Broadcasting";
+ case 0x0C:
+ return "Audio Broadcasting, Video Broadcasting";
+ case 0x0D:
+ return "Audio, Audio Broadcasting, Video Broadcasting";
+ case 0x0E:
+ return "Video, Audio Broadcasting, Video Broadcasting";
+ case 0x0F:
+ return "Audio, Video, Audio Broadcasting, Video Broadcasting";
+ }
+
+ return "None";
+}
+
+static const char *playersubtype2str(uint32_t subtype)
+{
+ switch (subtype & 0x03) {
+ case 0x01:
+ return "Audio Book";
+ case 0x02:
+ return "Podcast";
+ case 0x03:
+ return "Audio Book, Podcast";
+ }
+
+ return "None";
+}
+
+static void avrcp_media_player_item_dump(int level, struct frame *frm,
+ uint16_t len)
+{
+ uint16_t id, charset;
+ uint8_t type, status, namelen;
+ uint32_t subtype;
+ uint64_t features[2];
+
+ p_indent(level, frm);
+
+ if (len < 28) {
+ printf("PDU Malformed\n");
+ raw_dump(level, frm);
+ return;
+ }
+
+ id = get_u16(frm);
+ printf("PlayerID: 0x%04x (%u)\n", id, id);
+
+ p_indent(level, frm);
+
+ type = get_u8(frm);
+ printf("PlayerType: 0x%04x (%s)\n", type, playertype2str(type));
+
+ p_indent(level, frm);
+
+ subtype = get_u32(frm);
+ printf("PlayerSubtype: 0x%08x (%s)\n", subtype,
+ playersubtype2str(subtype));
+
+ p_indent(level, frm);
+
+ status = get_u8(frm);
+ printf("PlayStatus: 0x%02x (%s)\n", status, playstatus2str(status));
+
+ p_indent(level, frm);
+
+ get_u128(frm, &features[0], &features[1]);
+ printf("Features: 0x%16" PRIx64 "%16" PRIx64 "\n", features[1],
+ features[0]);
+
+ p_indent(level, frm);
+
+ charset = get_u16(frm);
+ printf("CharsetID: 0x%04x (%s)\n", charset, charset2str(charset));
+
+ p_indent(level, frm);
+
+ namelen = get_u8(frm);
+ printf("NameLength: 0x%02x (%u)\n", namelen, namelen);
+
+ p_indent(level, frm);
+
+ printf("Name: ");
+ for (; namelen > 0; namelen--) {
+ uint8_t c = get_u8(frm);
+ printf("%1c", isprint(c) ? c : '.');
+ }
+ printf("\n");
+}
+
+static const char *foldertype2str(uint8_t type)
+{
+ switch (type) {
+ case 0x00:
+ return "Mixed";
+ case 0x01:
+ return "Titles";
+ case 0x02:
+ return "Albuns";
+ case 0x03:
+ return "Artists";
+ case 0x04:
+ return "Genres";
+ case 0x05:
+ return "Playlists";
+ case 0x06:
+ return "Years";
+ }
+
+ return "Reserved";
+}
+
+static void avrcp_folder_item_dump(int level, struct frame *frm, uint16_t len)
+{
+ uint8_t type, playable, namelen;
+ uint16_t charset;
+ uint64_t uid;
+
+ p_indent(level, frm);
+
+ if (len < 14) {
+ printf("PDU Malformed\n");
+ raw_dump(level, frm);
+ return;
+ }
+
+ uid = get_u64(frm);
+ printf("FolderUID: 0x%16" PRIx64 " (%" PRIu64 ")\n", uid, uid);
+
+ p_indent(level, frm);
+
+ type = get_u8(frm);
+ printf("FolderType: 0x%02x (%s)\n", type, foldertype2str(type));
+
+ p_indent(level, frm);
+
+ playable = get_u8(frm);
+ printf("IsPlayable: 0x%02x (%s)\n", playable,
+ playable & 0x01 ? "True" : "False");
+
+ p_indent(level, frm);
+
+ charset = get_u16(frm);
+ printf("CharsetID: 0x%04x (%s)\n", charset, charset2str(charset));
+
+ p_indent(level, frm);
+
+ namelen = get_u8(frm);
+ printf("NameLength: 0x%02x (%u)\n", namelen, namelen);
+
+ p_indent(level, frm);
+
+ printf("Name: ");
+ for (; namelen > 0; namelen--) {
+ uint8_t c = get_u8(frm);
+ printf("%1c", isprint(c) ? c : '.');
+ }
+ printf("\n");
+}
+
+static const char *elementtype2str(uint8_t type)
+{
+ switch (type) {
+ case 0x00:
+ return "Audio";
+ case 0x01:
+ return "Video";
+ }
+
+ return "Reserved";
+}
+
+static void avrcp_media_element_item_dump(int level, struct frame *frm,
+ uint16_t len)
+{
+ uint64_t uid;
+ uint16_t charset;
+ uint8_t type, namelen, count;
+
+ if (len < 14) {
+ printf("PDU Malformed\n");
+ raw_dump(level, frm);
+ return;
+ }
+
+ uid = get_u64(frm);
+ printf("ElementUID: 0x%16" PRIx64 " (%" PRIu64 ")\n", uid, uid);
+
+ p_indent(level, frm);
+
+ type = get_u8(frm);
+ printf("ElementType: 0x%02x (%s)\n", type, elementtype2str(type));
+
+ p_indent(level, frm);
+
+ charset = get_u16(frm);
+ printf("CharsetID: 0x%04x (%s)\n", charset, charset2str(charset));
+
+ p_indent(level, frm);
+
+ namelen = get_u8(frm);
+ printf("NameLength: 0x%02x (%u)\n", namelen, namelen);
+
+ p_indent(level, frm);
+
+ printf("Name: ");
+ for (; namelen > 0; namelen--) {
+ uint8_t c = get_u8(frm);
+ printf("%1c", isprint(c) ? c : '.');
+ }
+ printf("\n");
+
+ p_indent(level, frm);
+
+ count = get_u8(frm);
+ printf("AttributeCount: 0x%02x (%u)\n", count, count);
+
+ for (; count > 0; count--) {
+ uint32_t attr;
+
+ p_indent(level, frm);
+
+ attr = get_u32(frm);
+ printf("AttributeID: 0x%08x (%s)\n", attr, mediattr2str(attr));
+
+ p_indent(level, frm);
+
+ charset = get_u16(frm);
+ printf("CharsetID: 0x%04x (%s)\n", charset,
+ charset2str(charset));
+
+ p_indent(level, frm);
+
+ namelen = get_u8(frm);
+ printf("AttributeLength: 0x%02x (%u)\n", namelen, namelen);
+
+ p_indent(level, frm);
+
+ printf("AttributeValue: ");
+ for (; namelen > 0; namelen--) {
+ uint8_t c = get_u8(frm);
+ printf("%1c", isprint(c) ? c : '.');
+ }
+ printf("\n");
+ }
+}
+
+static void avrcp_get_folder_items_dump(int level, struct frame *frm,
+ uint8_t hdr, uint16_t len)
+{
+ uint8_t scope, count, status;
+ uint32_t start, end;
+ uint16_t uid, num;
+
+ p_indent(level, frm);
+
+ if (hdr & 0x02)
+ goto response;
+
+ if (len < 10) {
+ printf("PDU Malformed\n");
+ raw_dump(level, frm);
+ return;
+ }
+
+ scope = get_u8(frm);
+ printf("Scope: 0x%02x (%s)\n", scope, scope2str(scope));
+
+ p_indent(level, frm);
+
+ start = get_u32(frm);
+ printf("StartItem: 0x%08x (%u)\n", start, start);
+
+ p_indent(level, frm);
+
+ end = get_u32(frm);
+ printf("EndItem: 0x%08x (%u)\n", end, end);
+
+ p_indent(level, frm);
+
+ count = get_u8(frm);
+ printf("AttributeCount: 0x%02x (%u)\n", count, count);
+
+ for (; count > 0; count--) {
+ uint32_t attr;
+
+ p_indent(level, frm);
+
+ attr = get_u32(frm);
+ printf("AttributeID: 0x%08x (%s)\n", attr, mediattr2str(attr));
+ }
+
+ return;
+
+response:
+ status = get_u8(frm);
+ printf("Status: 0x%02x (%s)\n", status, error2str(status));
+
+ if (len == 1)
+ return;
+
+ p_indent(level, frm);
+
+ uid = get_u16(frm);
+ printf("UIDCounter: 0x%04x (%u)\n", uid, uid);
+
+ p_indent(level, frm);
+
+ num = get_u16(frm);
+ printf("Number of Items: 0x%04x (%u)\n", num, num);
+
+ for (; num > 0; num--) {
+ uint8_t type;
+ uint16_t len;
+
+ p_indent(level, frm);
+
+ type = get_u8(frm);
+ len = get_u16(frm);
+ switch (type) {
+ case 0x01:
+ printf("Item: 0x01 (Media Player)) ");
+ printf("Length: 0x%04x (%u)\n", len, len);
+ avrcp_media_player_item_dump(level, frm, len);
+ break;
+ case 0x02:
+ printf("Item: 0x02 (Folder) ");
+ printf("Length: 0x%04x (%u)\n", len, len);
+ avrcp_folder_item_dump(level, frm, len);
+ break;
+ case 0x03:
+ printf("Item: 0x03 (Media Element) ");
+ printf("Length: 0x%04x (%u)\n", len, len);
+ avrcp_media_element_item_dump(level, frm, len);
+ break;
+ }
+ }
+}
+
static void avrcp_browsing_dump(int level, struct frame *frm, uint8_t hdr)
{
uint8_t pduid;
@@ -1520,6 +1906,9 @@ static void avrcp_browsing_dump(int level, struct frame *frm, uint8_t hdr)
case AVRCP_SET_BROWSED_PLAYER:
avrcp_set_browsed_player_dump(level + 1, frm, hdr, len);
break;
+ case AVRCP_GET_FOLDER_ITEMS:
+ avrcp_get_folder_items_dump(level + 1, frm, hdr, len);
+ break;
default:
raw_dump(level, frm);
}
--
1.7.11.2
^ permalink raw reply related
* [RFC hcidump 2/8] AVRCP: Fix parsing SetBrowsedPlayer as AV/C pdu
From: Luiz Augusto von Dentz @ 2012-08-15 13:32 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1345037529-1828-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
As per AVRCP specification 1.4 page 32 the command type of
SetBrowsedPlayer is Browsing, so move it to browsing channel.
In addition to that pass the avctp header to avrcp_dump as it is
required to identify if the frame is a command or response.
---
parser/avctp.c | 2 +-
parser/avrcp.c | 18 +++++++++---------
parser/parser.h | 2 +-
3 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/parser/avctp.c b/parser/avctp.c
index 5d913cf..aca1b75 100644
--- a/parser/avctp.c
+++ b/parser/avctp.c
@@ -65,7 +65,7 @@ void avctp_dump(int level, struct frame *frm, uint16_t psm)
pt2str(hdr), hdr & 0x0c, hdr >> 4, pid);
if (pid == SDP_UUID_AV_REMOTE || pid == SDP_UUID_AV_REMOTE_TARGET)
- avrcp_dump(level + 1, frm, psm);
+ avrcp_dump(level + 1, frm, hdr, psm);
else
raw_dump(level + 1, frm);
}
diff --git a/parser/avrcp.c b/parser/avrcp.c
index 46efec9..5179501 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -1264,8 +1264,8 @@ response:
printf("Status: 0x%02x (%s)\n", status, error2str(status));
}
-static void avrcp_set_browsed_player(int level, struct frame *frm,
- uint8_t ctype, uint16_t len)
+static void avrcp_set_browsed_player_dump(int level, struct frame *frm,
+ uint8_t hdr, uint16_t len)
{
uint32_t items;
uint16_t id, uids, charset;
@@ -1273,7 +1273,7 @@ static void avrcp_set_browsed_player(int level, struct frame *frm,
p_indent(level, frm);
- if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
+ if (hdr & 0x02)
goto response;
if (len < 2) {
@@ -1406,9 +1406,6 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
case AVRCP_SET_ADDRESSED_PLAYER:
avrcp_set_addressed_player(level + 1, frm, ctype, len);
break;
- case AVRCP_SET_BROWSED_PLAYER:
- avrcp_set_browsed_player(level + 1, frm, ctype, len);
- break;
default:
raw_dump(level, frm);
}
@@ -1502,7 +1499,7 @@ static const char *subunit2str(uint8_t subunit)
}
}
-static void avrcp_browsing_dump(int level, struct frame *frm)
+static void avrcp_browsing_dump(int level, struct frame *frm, uint8_t hdr)
{
uint8_t pduid;
uint16_t len;
@@ -1520,6 +1517,9 @@ static void avrcp_browsing_dump(int level, struct frame *frm)
}
switch (pduid) {
+ case AVRCP_SET_BROWSED_PLAYER:
+ avrcp_set_browsed_player_dump(level + 1, frm, hdr, len);
+ break;
default:
raw_dump(level, frm);
}
@@ -1579,7 +1579,7 @@ static void avrcp_control_dump(int level, struct frame *frm)
}
}
-void avrcp_dump(int level, struct frame *frm, uint16_t psm)
+void avrcp_dump(int level, struct frame *frm, uint8_t hdr, uint16_t psm)
{
p_indent(level, frm);
@@ -1588,7 +1588,7 @@ void avrcp_dump(int level, struct frame *frm, uint16_t psm)
avrcp_control_dump(level, frm);
break;
case 0x1B:
- avrcp_browsing_dump(level, frm);
+ avrcp_browsing_dump(level, frm, hdr);
break;
default:
raw_dump(level, frm);
diff --git a/parser/parser.h b/parser/parser.h
index c712d42..f8f7009 100644
--- a/parser/parser.h
+++ b/parser/parser.h
@@ -234,7 +234,7 @@ void hidp_dump(int level, struct frame *frm);
void hcrp_dump(int level, struct frame *frm);
void avdtp_dump(int level, struct frame *frm);
void avctp_dump(int level, struct frame *frm, uint16_t psm);
-void avrcp_dump(int level, struct frame *frm, uint16_t psm);
+void avrcp_dump(int level, struct frame *frm, uint8_t hdr, uint16_t psm);
void att_dump(int level, struct frame *frm);
void smp_dump(int level, struct frame *frm);
void sap_dump(int level, struct frame *frm);
--
1.7.11.2
^ permalink raw reply related
* [RFC hcidump 1/8] AVRCP: Add initial support for browsing channel
From: Luiz Augusto von Dentz @ 2012-08-15 13:32 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
parser/avctp.c | 4 ++--
parser/avrcp.c | 43 ++++++++++++++++++++++++++++++++++++++++---
parser/l2cap.c | 3 ++-
parser/parser.h | 4 ++--
4 files changed, 46 insertions(+), 8 deletions(-)
diff --git a/parser/avctp.c b/parser/avctp.c
index cf015d4..5d913cf 100644
--- a/parser/avctp.c
+++ b/parser/avctp.c
@@ -50,7 +50,7 @@ static char *pt2str(uint8_t hdr)
}
}
-void avctp_dump(int level, struct frame *frm)
+void avctp_dump(int level, struct frame *frm, uint16_t psm)
{
uint8_t hdr;
uint16_t pid;
@@ -65,7 +65,7 @@ void avctp_dump(int level, struct frame *frm)
pt2str(hdr), hdr & 0x0c, hdr >> 4, pid);
if (pid == SDP_UUID_AV_REMOTE || pid == SDP_UUID_AV_REMOTE_TARGET)
- avrcp_dump(level + 1, frm);
+ avrcp_dump(level + 1, frm, psm);
else
raw_dump(level + 1, frm);
}
diff --git a/parser/avrcp.c b/parser/avrcp.c
index f25dc34..46efec9 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -1502,13 +1502,34 @@ static const char *subunit2str(uint8_t subunit)
}
}
-void avrcp_dump(int level, struct frame *frm)
+static void avrcp_browsing_dump(int level, struct frame *frm)
+{
+ uint8_t pduid;
+ uint16_t len;
+
+ pduid = get_u8(frm);
+ len = get_u16(frm);
+
+ printf("AVRCP: %s: len 0x%04x\n", pdu2str(pduid), len);
+
+ if (len != frm->len) {
+ p_indent(level, frm);
+ printf("PDU Malformed\n");
+ raw_dump(level, frm);
+ return;
+ }
+
+ switch (pduid) {
+ default:
+ raw_dump(level, frm);
+ }
+}
+
+static void avrcp_control_dump(int level, struct frame *frm)
{
uint8_t ctype, address, subunit, opcode, company[3];
int i;
- p_indent(level, frm);
-
ctype = get_u8(frm);
address = get_u8(frm);
opcode = get_u8(frm);
@@ -1557,3 +1578,19 @@ void avrcp_dump(int level, struct frame *frm)
raw_dump(level, frm);
}
}
+
+void avrcp_dump(int level, struct frame *frm, uint16_t psm)
+{
+ p_indent(level, frm);
+
+ switch (psm) {
+ case 0x17:
+ avrcp_control_dump(level, frm);
+ break;
+ case 0x1B:
+ avrcp_browsing_dump(level, frm);
+ break;
+ default:
+ raw_dump(level, frm);
+ }
+}
diff --git a/parser/l2cap.c b/parser/l2cap.c
index 8dc825b..a6162d7 100644
--- a/parser/l2cap.c
+++ b/parser/l2cap.c
@@ -1487,8 +1487,9 @@ static void l2cap_parse(int level, struct frame *frm)
break;
case 0x17:
+ case 0x1B:
if (!p_filter(FILT_AVCTP))
- avctp_dump(level, frm);
+ avctp_dump(level, frm, psm);
else
raw_dump(level + 1, frm);
break;
diff --git a/parser/parser.h b/parser/parser.h
index 1130a5f..c712d42 100644
--- a/parser/parser.h
+++ b/parser/parser.h
@@ -233,8 +233,8 @@ void cmtp_dump(int level, struct frame *frm);
void hidp_dump(int level, struct frame *frm);
void hcrp_dump(int level, struct frame *frm);
void avdtp_dump(int level, struct frame *frm);
-void avctp_dump(int level, struct frame *frm);
-void avrcp_dump(int level, struct frame *frm);
+void avctp_dump(int level, struct frame *frm, uint16_t psm);
+void avrcp_dump(int level, struct frame *frm, uint16_t psm);
void att_dump(int level, struct frame *frm);
void smp_dump(int level, struct frame *frm);
void sap_dump(int level, struct frame *frm);
--
1.7.11.2
^ permalink raw reply related
* Re: [RFC BlueZ] doc: Introduce Alert API
From: Anderson Lizardo @ 2012-08-15 13:01 UTC (permalink / raw)
To: Gustavo Padovan, Anderson Lizardo, linux-bluetooth
In-Reply-To: <20120815042727.GE3344@joana>
Hi Gustavo,
On Wed, Aug 15, 2012 at 12:27 AM, Gustavo Padovan <gustavo@padovan.org> wrote:
>> +Currently, there are two different GATT server profiles that depend on
>> +receiving alerts or notifications from the platform: Phone Alert Status (PASP)
>> +and Alert Notification (ANP). Additionally, PASP is very specific to mobile
>> +phones, and also allow limited control to alerts (i.e. mute once, or switch to
>> +a silent mode).
>> +
>> +This document presents a unified API that allows to register,
>
> Is there some missing text here?
Yes, I will fill the missing text on next revision. I also have minor
fixes to the alert categories.
>> +
>> +Alert hierarchy
>> +===============
>> +
>> +Service org.bluez
>> +Interface org.bluez.Alert
>> +Object path /org/bluez
>> +
>> +Methods void RegisterAlert(string category)
>> +
>> + Register a new alert category. This means the
>> + application will be responsible for notifying BlueZ of
>> + any alerts of that category, using the Alert() method.
>> +
>> + Supported categories: generic, email, news, call,
>> + missed_call, sms_mms, voice_mail, schedule,
>> + instant_message, ringer, vibrate, display.
>> +
>> + Possible Errors: org.bluez.Error.InvalidArguments
>> +
>> + void RegisterAgent(string category, object agent)
>> +
>> + Register a new agent for the alert category. The agent
>> + object methods to be called depend on the category. The
>> + currently supported category is "ringer", with methods
>> + MuteOnce() and SetRingerMode().
>> +
>> + Possible Errors: org.bluez.Error.InvalidArguments
>
> If I got this right you RegisterAlert() and then RegisterAgent() in the
> sequence, right? Why can't you merge both calls into one.
Originally, the agent was only necessary for the "ringer" category.
But after further thinking, looks like we can use it to update the
"new alert" and "unread alert" counts necessary for ANP. I will
prepare an updated document and send ASAP.
>> +
>> + void NewAlert(string category, string description)
>> +
>> + Notify BlueZ of a new alert for the given category. The
>> + description can be sender name, called ID, title, or
>> + other information specific to the alert. For ringer,
>> + vibrate and display categories, valid descriptions are
>> + "active" and "not active".
>
> The way I understand it I see many NewAlert() calls happening almost at the
> same time. Isn't possible to pass a dict with many {string category, string
> description} inside?
It is not clear from the description above (I will improve it), but
for categories like "email" that can have many messages received after
a sync, only a single NewAlert() call is made. The description is for
the last e-mail sent. So the event is actually a single one: "you got
N e-mails, and the sender for the last one is ...". The same applies
to any alerts which have multiple items.
>
>> +
>> + Possible Errors: org.bluez.Error.InvalidArguments
>> +
>> + void UnreadAlertCount(string category, uint16 count)
>> +
>> + Some services (like SMS and e-mail) keep track of
>> + number of unread items. This method allows to update
>> + this counter, so peer devices can read it using Alert
>> + Notification Profile.
>> +
>> + Note that just calling NewAlert() will not implicitly
>> + increment the unread count for a category. The
>> + application must call this method to increase or
>> + decrease the unread counter.
>
> Is there a good reason for not increment the count on NewAlert()?
There are two counts supported by the ANP profile: "Unread Alert
count" and "New Alert count". I'll try to explain here, but I
suggesting reading sections 1.7.2, 1.7.3, 4.1.2 and 4.1.3 from
ANS_SPEC_V10.pdf. These counts are per category.
Unread Alert count is only useful to some categories, like SMS and
e-mail, that have the concept of "unread message". It may
increase/decrease depending on user interaction with the host UI (e.g.
marking messages as read/unread, deleting messages etc.)
New Alert count is used to keep track of how many alerts are not yet
acknowledged by the user. It is also applicable to SMS/email, and all
other categories. E.g. two calendar events on the same day, and none
of them were opened by the user, will increase this count by two.
As mentioned above, we can use the zgent to have better tracking of
these counts. This would avoid the need for this method, and instead
BlueZ could request for the up-to-date alert counts from the e-mail
application (for example). I will send soon a v2 of this document.
Thanks for your comments!
Best Regards,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil
^ permalink raw reply
* RE: [PATCH] network: Check full BNEP UUID
From: Par-Gunnar HJALMDAHL @ 2012-08-15 12:45 UTC (permalink / raw)
To: Johan Hedberg; +Cc: linux-bluetooth@vger.kernel.org, Anurag GUPTA-1
In-Reply-To: <20120815124030.GA2498@x220>
Hi Johan,
> -----Original Message-----
> From: Johan Hedberg [mailto:johan.hedberg@gmail.com]
> Sent: den 15 augusti 2012 14:41
> To: Par-Gunnar HJALMDAHL
> Cc: linux-bluetooth@vger.kernel.org; Anurag GUPTA-1
> Subject: Re: [PATCH] network: Check full BNEP UUID
>
> Hi P-G,
>
> On Wed, Aug 15, 2012, Par-Gunnar HJALMDAHL wrote:
> > Basically I tried to keep the patch to a minimum since it was quite a
> > simple issue to fix.
> >
> > I have no problems to use the UUID in lib/uuid.c. I could add a 2 new
> > exported functions for retrieving base UUID, one for little endian
> and
> > one for big endian, since uuid.c endian depends on CPU endian while
> > PAN endian is always big endian. So:
> > void get_le_bt_base_uuid(uint128_t *uuid);
> > void get_be_bt_base_uuid(uint128_t *uuid);
>
> Note that the uuid.{c,h} name space is bt_uuid_*
>
> So far uuid.c has been fully hiding any endianness issues in its public
> API by only talking host-endianness. So, if this was to be really done
> in a clean way I'd say the calling code should look like:
>
> uint128_t u128;
> bt_uuid_t uuid;
>
> u128 = bt_get_be128(dest);
>
> bt_uuid128_create(&uuid, u128);
> if (!bt_uuid_is_bluetooth(&uuid))
> return BNEP_CONN_INVALID_DST;
>
> /* same for source */
>
> However, as this would require at least two new functions
> (bt_get_be128() in lib/bluetooth.h and bt_uuid_is_bluetooth() in
> lib/uuid.c) and like you say the use case is quite trivial, I think
> this
> might be a bit overkill.
>
> So, since you were fine with my alteration of your patch I think I'll
> just go ahead and push it upstream. If you still want to add the
> necessary APIs for the "truly clean" approach, feel free, but I won't
> be
> bugging you about it ;)
>
> Johan
Yes, I'm fine with your suggested patch as-is.
It's OK to just push it. :-)
/P-G
^ permalink raw reply
* Re: [PATCH] network: Check full BNEP UUID
From: Johan Hedberg @ 2012-08-15 12:40 UTC (permalink / raw)
To: Par-Gunnar HJALMDAHL; +Cc: linux-bluetooth@vger.kernel.org, Anurag GUPTA-1
In-Reply-To: <81C3A93C17462B4BBD7E272753C1057923B924CB0D@EXDCVYMBSTM005.EQ1STM.local>
Hi P-G,
On Wed, Aug 15, 2012, Par-Gunnar HJALMDAHL wrote:
> Basically I tried to keep the patch to a minimum since it was quite a
> simple issue to fix.
>
> I have no problems to use the UUID in lib/uuid.c. I could add a 2 new
> exported functions for retrieving base UUID, one for little endian and
> one for big endian, since uuid.c endian depends on CPU endian while
> PAN endian is always big endian. So:
> void get_le_bt_base_uuid(uint128_t *uuid);
> void get_be_bt_base_uuid(uint128_t *uuid);
Note that the uuid.{c,h} name space is bt_uuid_*
So far uuid.c has been fully hiding any endianness issues in its public
API by only talking host-endianness. So, if this was to be really done
in a clean way I'd say the calling code should look like:
uint128_t u128;
bt_uuid_t uuid;
u128 = bt_get_be128(dest);
bt_uuid128_create(&uuid, u128);
if (!bt_uuid_is_bluetooth(&uuid))
return BNEP_CONN_INVALID_DST;
/* same for source */
However, as this would require at least two new functions
(bt_get_be128() in lib/bluetooth.h and bt_uuid_is_bluetooth() in
lib/uuid.c) and like you say the use case is quite trivial, I think this
might be a bit overkill.
So, since you were fine with my alteration of your patch I think I'll
just go ahead and push it upstream. If you still want to add the
necessary APIs for the "truly clean" approach, feel free, but I won't be
bugging you about it ;)
Johan
^ permalink raw reply
* RE: [PATCH] network: Check full BNEP UUID
From: Par-Gunnar HJALMDAHL @ 2012-08-15 11:17 UTC (permalink / raw)
To: Johan Hedberg; +Cc: linux-bluetooth@vger.kernel.org, Anurag GUPTA-1
In-Reply-To: <20120815103912.GA26379@x220>
Hi and thanks for you comments Johan,
> -----Original Message-----
> From: Johan Hedberg [mailto:johan.hedberg@gmail.com]
> Sent: den 15 augusti 2012 12:39
> To: Par-Gunnar HJALMDAHL
> Cc: linux-bluetooth@vger.kernel.org; Anurag GUPTA-1
> Subject: Re: [PATCH] network: Check full BNEP UUID
>
> There are a couple of things that bug me a bit with this patch. One is
> the re-definition of bluetooth_base_uuid which really should only exist
> in one central place (lib/uuid.c). Another is the way the code logic
> goes. It seems you want to test for two things:
>
> 1) That the UUID is a Bluetooth UUID. This is the memcmp
> with
> the last 12 bytes of the Bluetooth base UUID for the UUID128
> case. 16 and 32 bit values are already implicitly assumed to
> be
> Bluetooth UUIDs as they don't contain any information to
> reveal
> this as such.
>
> 2) That the (now determined) Bluetooth UUID has a value less
> than or equal to 0xffff. This is quite awkwardly tested for
> by
> comparing with the two first bytes from bluetooth_base_uuid,
> which are both zeros. Based on your code comment it sounds
> like
> this test should really be covered by bnep_setup_chk().
>
> If you really want to have the "<= 0xffff" test be in bnep_setup_decode
> then I'd propose something like the attached patch. However, testing
> for the exact value of the Bluetooth UUID (once the UUID has been
> determined to be a Bluetooth UUID) seems like the task of
> bnep_setup_chk from the way you've laid out the functions.
>
> Johan
Basically I tried to keep the patch to a minimum since it was quite a
simple issue to fix.
I have no problems to use the UUID in lib/uuid.c. I could add a 2 new
exported functions for retrieving base UUID, one for little endian and
one for big endian, since uuid.c endian depends on CPU endian while
PAN endian is always big endian. So:
void get_le_bt_base_uuid(uint128_t *uuid);
void get_be_bt_base_uuid(uint128_t *uuid);
Your suggestion looks fine. It's a bit more effective than my original
code. The reason I did the check in bnep_setup_decode() rather than in
bnep_setup_chk is that only 16 bits are kept when exiting the function
(bnep_setup_decode is the only function aware of the UUID size) and I
thought that was a quite straightforward design.
If it's OK with you I can create a new patch with suggestion above
plus your patch.
/P-G
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox