* [RFC BlueZ 4/5] heartrate: Use the per handle GATT event notifier
From: Vinicius Costa Gomes @ 2012-10-09 0:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1349742372-18420-1-git-send-email-vinicius.gomes@openbossa.org>
---
profiles/heartrate/heartrate.c | 287 +++++++++++++++++++++--------------------
1 file changed, 145 insertions(+), 142 deletions(-)
diff --git a/profiles/heartrate/heartrate.c b/profiles/heartrate/heartrate.c
index d9d6c03..871b74e 100644
--- a/profiles/heartrate/heartrate.c
+++ b/profiles/heartrate/heartrate.c
@@ -260,6 +260,150 @@ static void char_write_cb(guint8 status, const guint8 *pdu, guint16 len,
g_free(msg);
}
+static void update_watcher(gpointer data, gpointer user_data)
+{
+ struct watcher *w = data;
+ struct measurement *m = user_data;
+ struct heartrate *hr = m->hr;
+ const gchar *path = device_get_path(hr->dev);
+ DBusMessageIter iter;
+ DBusMessageIter dict;
+ DBusMessage *msg;
+
+ msg = dbus_message_new_method_call(w->srv, w->path,
+ HEART_RATE_WATCHER_INTERFACE, "MeasurementReceived");
+ if (msg == NULL)
+ return;
+
+ dbus_message_iter_init_append(msg, &iter);
+
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH , &path);
+
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+ dict_append_entry(&dict, "Value", DBUS_TYPE_UINT16, &m->value);
+
+ if (m->has_energy)
+ dict_append_entry(&dict, "Energy", DBUS_TYPE_UINT16,
+ &m->energy);
+
+ if (m->has_contact)
+ dict_append_entry(&dict, "Contact", DBUS_TYPE_BOOLEAN,
+ &m->contact);
+
+ if (m->num_interval > 0)
+ dict_append_array(&dict, "Interval", DBUS_TYPE_UINT16,
+ &m->interval, m->num_interval);
+
+ dbus_message_iter_close_container(&iter, &dict);
+
+ dbus_message_set_no_reply(msg, TRUE);
+ g_dbus_send_message(btd_get_dbus_connection(), msg);
+}
+
+static void process_measurement(struct heartrate *hr, const uint8_t *pdu,
+ uint16_t len)
+{
+ struct measurement m;
+ uint8_t flags;
+
+ flags = *pdu;
+
+ pdu++;
+ len--;
+
+ memset(&m, 0, sizeof(m));
+
+ if (flags & HR_VALUE_FORMAT) {
+ if (len < 2) {
+ error("Heart Rate Measurement field missing");
+ return;
+ }
+
+ m.value = att_get_u16(pdu);
+ pdu += 2;
+ len -= 2;
+ } else {
+ if (len < 1) {
+ error("Heart Rate Measurement field missing");
+ return;
+ }
+
+ m.value = *pdu;
+ pdu++;
+ len--;
+ }
+
+ if (flags & ENERGY_EXP_STATUS) {
+ if (len < 2) {
+ error("Energy Expended field missing");
+ return;
+ }
+
+ m.has_energy = TRUE;
+ m.energy = att_get_u16(pdu);
+ pdu += 2;
+ len -= 2;
+ }
+
+ if (flags & RR_INTERVAL) {
+ int i;
+
+ if (len == 0 || (len % 2 != 0)) {
+ error("RR-Interval field malformed");
+ return;
+ }
+
+ m.num_interval = len / 2;
+ m.interval = g_new(uint16_t, m.num_interval);
+
+ for (i = 0; i < m.num_interval; pdu += 2, i++)
+ m.interval[i] = att_get_u16(pdu);
+ }
+
+ if (flags & SENSOR_CONTACT_SUPPORT) {
+ m.has_contact = TRUE;
+ m.contact = !!(flags & SENSOR_CONTACT_DETECTED);
+ }
+
+ /* Notify all registered watchers */
+ m.hr = hr;
+ g_slist_foreach(hr->hradapter->watchers, update_watcher, &m);
+
+ g_free(m.interval);
+}
+
+static void notify_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
+{
+ struct heartrate *hr = user_data;
+
+ /* should be at least opcode (1b) + handle (2b) */
+ if (len < 3) {
+ error("Invalid PDU received");
+ return;
+ }
+
+ process_measurement(hr, pdu + 3, len - 3);
+}
+
+static void ccc_write_cb(guint8 status, const guint8 *pdu, guint16 len,
+ gpointer user_data)
+{
+ struct heartrate *hr = user_data;
+
+ if (status != 0) {
+ error("Enable measurement failed");
+ return;
+ }
+
+ hr->attionotid = g_attrib_register(hr->attrib, ATT_OP_HANDLE_NOTIFY,
+ hr->measurement_val_handle,
+ notify_handler, hr, NULL);
+}
+
static void discover_ccc_cb(guint8 status, const guint8 *pdu,
guint16 len, gpointer user_data)
{
@@ -291,7 +435,6 @@ static void discover_ccc_cb(guint8 status, const guint8 *pdu,
if (uuid == GATT_CLIENT_CHARAC_CFG_UUID) {
uint8_t value[2];
- char *msg;
hr->measurement_ccc_handle = handle;
@@ -299,10 +442,9 @@ static void discover_ccc_cb(guint8 status, const guint8 *pdu,
break;
att_put_u16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value);
- msg = g_strdup("Enable measurement");
gatt_write_char(hr->attrib, handle, value,
- sizeof(value), char_write_cb, msg);
+ sizeof(value), ccc_write_cb, hr);
break;
}
@@ -399,142 +541,6 @@ static void disable_measurement(gpointer data, gpointer user_data)
char_write_cb, msg);
}
-static void update_watcher(gpointer data, gpointer user_data)
-{
- struct watcher *w = data;
- struct measurement *m = user_data;
- struct heartrate *hr = m->hr;
- const gchar *path = device_get_path(hr->dev);
- DBusMessageIter iter;
- DBusMessageIter dict;
- DBusMessage *msg;
-
- msg = dbus_message_new_method_call(w->srv, w->path,
- HEART_RATE_WATCHER_INTERFACE, "MeasurementReceived");
- if (msg == NULL)
- return;
-
- dbus_message_iter_init_append(msg, &iter);
-
- dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH , &path);
-
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
- DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
- DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
- DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
-
- dict_append_entry(&dict, "Value", DBUS_TYPE_UINT16, &m->value);
-
- if (m->has_energy)
- dict_append_entry(&dict, "Energy", DBUS_TYPE_UINT16,
- &m->energy);
-
- if (m->has_contact)
- dict_append_entry(&dict, "Contact", DBUS_TYPE_BOOLEAN,
- &m->contact);
-
- if (m->num_interval > 0)
- dict_append_array(&dict, "Interval", DBUS_TYPE_UINT16,
- &m->interval, m->num_interval);
-
- dbus_message_iter_close_container(&iter, &dict);
-
- dbus_message_set_no_reply(msg, TRUE);
- g_dbus_send_message(btd_get_dbus_connection(), msg);
-}
-
-static void process_measurement(struct heartrate *hr, const uint8_t *pdu,
- uint16_t len)
-{
- struct measurement m;
- uint8_t flags;
-
- flags = *pdu;
-
- pdu++;
- len--;
-
- memset(&m, 0, sizeof(m));
-
- if (flags & HR_VALUE_FORMAT) {
- if (len < 2) {
- error("Heart Rate Measurement field missing");
- return;
- }
-
- m.value = att_get_u16(pdu);
- pdu += 2;
- len -= 2;
- } else {
- if (len < 1) {
- error("Heart Rate Measurement field missing");
- return;
- }
-
- m.value = *pdu;
- pdu++;
- len--;
- }
-
- if (flags & ENERGY_EXP_STATUS) {
- if (len < 2) {
- error("Energy Expended field missing");
- return;
- }
-
- m.has_energy = TRUE;
- m.energy = att_get_u16(pdu);
- pdu += 2;
- len -= 2;
- }
-
- if (flags & RR_INTERVAL) {
- int i;
-
- if (len == 0 || (len % 2 != 0)) {
- error("RR-Interval field malformed");
- return;
- }
-
- m.num_interval = len / 2;
- m.interval = g_new(uint16_t, m.num_interval);
-
- for (i = 0; i < m.num_interval; pdu += 2, i++)
- m.interval[i] = att_get_u16(pdu);
- }
-
- if (flags & SENSOR_CONTACT_SUPPORT) {
- m.has_contact = TRUE;
- m.contact = !!(flags & SENSOR_CONTACT_DETECTED);
- }
-
- /* Notify all registered watchers */
- m.hr = hr;
- g_slist_foreach(hr->hradapter->watchers, update_watcher, &m);
-
- g_free(m.interval);
-}
-
-static void notify_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
-{
- struct heartrate *hr = user_data;
- uint16_t handle;
-
- /* should be at least opcode (1b) + handle (2b) */
- if (len < 3) {
- error("Invalid PDU received");
- return;
- }
-
- handle = att_get_u16(pdu + 1);
- if (handle != hr->measurement_val_handle) {
- error("Unexpected handle: 0x%04x", handle);
- return;
- }
-
- process_measurement(hr, pdu + 3, len - 3);
-}
-
static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
{
struct heartrate *hr = user_data;
@@ -543,9 +549,6 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
hr->attrib = g_attrib_ref(attrib);
- hr->attionotid = g_attrib_register(hr->attrib, ATT_OP_HANDLE_NOTIFY,
- GATTRIB_ALL_HANDLES, notify_handler, hr, NULL);
-
gatt_discover_char(hr->attrib, hr->svc_range->start, hr->svc_range->end,
NULL, discover_char_cb, hr);
}
--
1.7.12.2
^ permalink raw reply related
* [RFC BlueZ 3/5] hog: Use the per handle GATT event notifier
From: Vinicius Costa Gomes @ 2012-10-09 0:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1349742372-18420-1-git-send-email-vinicius.gomes@openbossa.org>
---
profiles/input/hog_device.c | 66 ++++++++++++++++++++++++---------------------
1 file changed, 36 insertions(+), 30 deletions(-)
diff --git a/profiles/input/hog_device.c b/profiles/input/hog_device.c
index 52ebd95..34f4a41 100644
--- a/profiles/input/hog_device.c
+++ b/profiles/input/hog_device.c
@@ -92,27 +92,18 @@ struct hog_device {
struct report {
uint8_t id;
uint8_t type;
+ guint notifyid;
struct gatt_char *decl;
struct hog_device *hogdev;
};
-static gint report_handle_cmp(gconstpointer a, gconstpointer b)
-{
- const struct report *report = a;
- uint16_t handle = GPOINTER_TO_UINT(b);
-
- return report->decl->value_handle - handle;
-}
-
static void report_value_cb(const uint8_t *pdu, uint16_t len,
gpointer user_data)
{
- struct hog_device *hogdev = user_data;
+ struct report *report = user_data;
+ struct hog_device *hogdev = report->hogdev;
struct uhid_event ev;
uint16_t report_size = len - 3;
- guint handle;
- GSList *l;
- struct report *report;
uint8_t *buf;
if (len < 3) { /* 1-byte opcode + 2-byte handle */
@@ -120,17 +111,6 @@ static void report_value_cb(const uint8_t *pdu, uint16_t len,
return;
}
- handle = att_get_u16(&pdu[1]);
-
- l = g_slist_find_custom(hogdev->reports, GUINT_TO_POINTER(handle),
- report_handle_cmp);
- if (!l) {
- error("Invalid report");
- return;
- }
-
- report = l->data;
-
memset(&ev, 0, sizeof(ev));
ev.type = UHID_INPUT;
ev.u.input.size = MIN(report_size, UHID_DATA_MAX);
@@ -154,22 +134,31 @@ static void report_value_cb(const uint8_t *pdu, uint16_t len,
static void report_ccc_written_cb(guint8 status, const guint8 *pdu,
guint16 plen, gpointer user_data)
{
+ struct report *report = user_data;
+ struct hog_device *hogdev = report->hogdev;
+
if (status != 0) {
error("Write report characteristic descriptor failed: %s",
att_ecode2str(status));
return;
}
+ report->notifyid = g_attrib_register(hogdev->attrib,
+ ATT_OP_HANDLE_NOTIFY,
+ report->decl->value_handle,
+ report_value_cb, report, NULL);
+
DBG("Report characteristic descriptor written: notifications enabled");
}
static void write_ccc(uint16_t handle, gpointer user_data)
{
- struct hog_device *hogdev = user_data;
+ struct report *report = user_data;
+ struct hog_device *hogdev = report->hogdev;
uint8_t value[] = { 0x01, 0x00 };
gatt_write_char(hogdev->attrib, handle, value, sizeof(value),
- report_ccc_written_cb, hogdev);
+ report_ccc_written_cb, report);
}
static void report_reference_cb(guint8 status, const guint8 *pdu,
@@ -196,6 +185,7 @@ static void report_reference_cb(guint8 status, const guint8 *pdu,
static void external_report_reference_cb(guint8 status, const guint8 *pdu,
guint16 plen, gpointer user_data);
+
static void discover_descriptor_cb(guint8 status, const guint8 *pdu,
guint16 len, gpointer user_data)
{
@@ -608,24 +598,37 @@ 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;
hogdev->attrib = g_attrib_ref(attrib);
- hogdev->report_cb_id = g_attrib_register(hogdev->attrib,
- ATT_OP_HANDLE_NOTIFY,
- GATTRIB_ALL_HANDLES,
- report_value_cb, hogdev, NULL);
-
if (hogdev->reports == NULL) {
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;
+
+ r->notifyid = g_attrib_register(hogdev->attrib,
+ ATT_OP_HANDLE_NOTIFY,
+ r->decl->value_handle,
+ report_value_cb, r, NULL);
}
}
static void attio_disconnected_cb(gpointer user_data)
{
struct hog_device *hogdev = user_data;
+ GSList *l;
+
+ for (l = hogdev->reports; l; l = l->next) {
+ struct report *r = l->data;
+
+ g_attrib_unregister(hogdev->attrib, r->notifyid);
+ }
g_attrib_unregister(hogdev->attrib, hogdev->report_cb_id);
hogdev->report_cb_id = 0;
@@ -652,6 +655,9 @@ static struct hog_device *hog_device_new(struct btd_device *device,
static void report_free(void *data)
{
struct report *report = data;
+ struct hog_device *hogdev = report->hogdev;
+
+ g_attrib_unregister(hogdev->attrib, report->notifyid);
g_free(report->decl);
g_free(report);
}
--
1.7.12.2
^ permalink raw reply related
* [RFC BlueZ 2/5] scan: Use the per handle GATT event notifier
From: Vinicius Costa Gomes @ 2012-10-09 0:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1349742372-18420-1-git-send-email-vinicius.gomes@openbossa.org>
---
profiles/scanparam/scan.c | 15 ++-------------
1 file changed, 2 insertions(+), 13 deletions(-)
diff --git a/profiles/scanparam/scan.c b/profiles/scanparam/scan.c
index bbf646c..09fbe1f 100644
--- a/profiles/scanparam/scan.c
+++ b/profiles/scanparam/scan.c
@@ -83,17 +83,6 @@ static void refresh_value_cb(const uint8_t *pdu, uint16_t len,
gpointer user_data)
{
struct scan *scan = user_data;
- uint16_t handle;
-
- if (len < 4) { /* 1-byte opcode + 2-byte handle + refresh */
- error("Malformed ATT notification");
- return;
- }
-
- handle = att_get_u16(&pdu[1]);
-
- if (handle != scan->refresh_handle)
- return;
DBG("Server requires refresh: %d", pdu[3]);
@@ -115,8 +104,8 @@ static void ccc_written_cb(guint8 status, const guint8 *pdu,
DBG("Scan Refresh: notification enabled");
scan->refresh_cb_id = g_attrib_register(scan->attrib,
- ATT_OP_HANDLE_NOTIFY, GATTRIB_ALL_HANDLES,
- refresh_value_cb, user_data, NULL);
+ ATT_OP_HANDLE_NOTIFY, scan->refresh_handle,
+ refresh_value_cb, scan, NULL);
}
static void discover_descriptor_cb(guint8 status, const guint8 *pdu,
--
1.7.12.2
^ permalink raw reply related
* [RFC BlueZ 1/5] gattrib: Add support for listening for events for specific handles
From: Vinicius Costa Gomes @ 2012-10-09 0:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1349742372-18420-1-git-send-email-vinicius.gomes@openbossa.org>
We want only the profile that implements a service to be notified of
changes on that service. Before this patch, all the registered event
notifiers are being called.
---
attrib/client.c | 4 ++--
attrib/gattrib.c | 33 ++++++++++++++++++++++++++++-----
attrib/gattrib.h | 7 ++++---
attrib/gatttool.c | 8 ++++----
attrib/interactive.c | 8 ++++----
profiles/gatt/gas.c | 1 +
profiles/heartrate/heartrate.c | 2 +-
profiles/input/hog_device.c | 5 +++--
profiles/scanparam/scan.c | 4 ++--
profiles/thermometer/thermometer.c | 2 ++
src/attrib-server.c | 2 +-
11 files changed, 52 insertions(+), 24 deletions(-)
diff --git a/attrib/client.c b/attrib/client.c
index 8b29cbb..cda5bc0 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -393,9 +393,9 @@ static void attio_connected(GAttrib *attrib, gpointer user_data)
gatt->attrib = g_attrib_ref(attrib);
g_attrib_register(gatt->attrib, ATT_OP_HANDLE_NOTIFY,
- events_handler, gatt, NULL);
+ GATTRIB_ALL_HANDLES, events_handler, gatt, NULL);
g_attrib_register(gatt->attrib, ATT_OP_HANDLE_IND,
- events_handler, gatt, NULL);
+ GATTRIB_ALL_HANDLES, events_handler, gatt, NULL);
g_slist_foreach(gatt->offline_chars, offline_char_write, attrib);
diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index 6f6942f..c928798 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -70,6 +70,7 @@ struct command {
struct event {
guint id;
guint8 expected;
+ guint16 handle;
GAttribNotifyFunc func;
gpointer user_data;
GDestroyNotify notify;
@@ -351,6 +352,30 @@ static void wake_up_sender(struct _GAttrib *attrib)
can_write_data, attrib, destroy_sender);
}
+static gboolean match_event(struct event *evt, const uint8_t *pdu, gsize len)
+{
+ guint16 handle;
+
+ if (evt->expected == GATTRIB_ALL_EVENTS)
+ return TRUE;
+
+ if (is_response(pdu[0]) == FALSE && evt->expected == GATTRIB_ALL_REQS)
+ return TRUE;
+
+ if (evt->expected == pdu[0] && evt->handle == GATTRIB_ALL_HANDLES)
+ return TRUE;
+
+ if (len < 3)
+ return FALSE;
+
+ handle = att_get_u16(&pdu[1]);
+
+ if (evt->expected == pdu[0] && evt->handle == handle)
+ return TRUE;
+
+ return FALSE;
+}
+
static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
{
struct _GAttrib *attrib = data;
@@ -381,10 +406,7 @@ static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data)
for (l = attrib->events; l; l = l->next) {
struct event *evt = l->data;
- if (evt->expected == buf[0] ||
- evt->expected == GATTRIB_ALL_EVENTS ||
- (is_response(buf[0]) == FALSE &&
- evt->expected == GATTRIB_ALL_REQS))
+ if (match_event(evt, buf, len))
evt->func(buf, len, evt->user_data);
}
@@ -639,7 +661,7 @@ gboolean g_attrib_set_mtu(GAttrib *attrib, int mtu)
return TRUE;
}
-guint g_attrib_register(GAttrib *attrib, guint8 opcode,
+guint g_attrib_register(GAttrib *attrib, guint8 opcode, guint16 handle,
GAttribNotifyFunc func, gpointer user_data,
GDestroyNotify notify)
{
@@ -651,6 +673,7 @@ guint g_attrib_register(GAttrib *attrib, guint8 opcode,
return 0;
event->expected = opcode;
+ event->handle = handle;
event->func = func;
event->user_data = user_data;
event->notify = notify;
diff --git a/attrib/gattrib.h b/attrib/gattrib.h
index bca966f..3fe92c7 100644
--- a/attrib/gattrib.h
+++ b/attrib/gattrib.h
@@ -30,6 +30,7 @@ extern "C" {
#define GATTRIB_ALL_EVENTS 0xFF
#define GATTRIB_ALL_REQS 0xFE
+#define GATTRIB_ALL_HANDLES 0x0000
struct _GAttrib;
typedef struct _GAttrib GAttrib;
@@ -60,9 +61,9 @@ gboolean g_attrib_cancel_all(GAttrib *attrib);
gboolean g_attrib_set_debug(GAttrib *attrib,
GAttribDebugFunc func, gpointer user_data);
-guint g_attrib_register(GAttrib *attrib, guint8 opcode,
- GAttribNotifyFunc func, gpointer user_data,
- GDestroyNotify notify);
+guint g_attrib_register(GAttrib *attrib, guint8 opcode, guint16 handle,
+ GAttribNotifyFunc func, gpointer user_data,
+ GDestroyNotify notify);
gboolean g_attrib_is_encrypted(GAttrib *attrib);
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 16cce0c..5517408 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -111,10 +111,10 @@ static gboolean listen_start(gpointer user_data)
{
GAttrib *attrib = user_data;
- g_attrib_register(attrib, ATT_OP_HANDLE_NOTIFY, events_handler,
- attrib, NULL);
- g_attrib_register(attrib, ATT_OP_HANDLE_IND, events_handler,
- attrib, NULL);
+ g_attrib_register(attrib, ATT_OP_HANDLE_NOTIFY, GATTRIB_ALL_HANDLES,
+ events_handler, attrib, NULL);
+ g_attrib_register(attrib, ATT_OP_HANDLE_IND, GATTRIB_ALL_HANDLES,
+ events_handler, attrib, NULL);
return FALSE;
}
diff --git a/attrib/interactive.c b/attrib/interactive.c
index b41a7bb..df0bb86 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -147,10 +147,10 @@ static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
}
attrib = g_attrib_new(iochannel);
- g_attrib_register(attrib, ATT_OP_HANDLE_NOTIFY, events_handler,
- attrib, NULL);
- g_attrib_register(attrib, ATT_OP_HANDLE_IND, events_handler,
- attrib, NULL);
+ g_attrib_register(attrib, ATT_OP_HANDLE_NOTIFY, GATTRIB_ALL_HANDLES,
+ events_handler, attrib, NULL);
+ g_attrib_register(attrib, ATT_OP_HANDLE_IND, GATTRIB_ALL_HANDLES,
+ events_handler, attrib, NULL);
set_state(STATE_CONNECTED);
}
diff --git a/profiles/gatt/gas.c b/profiles/gatt/gas.c
index 74ca9ce..35a9152 100644
--- a/profiles/gatt/gas.c
+++ b/profiles/gatt/gas.c
@@ -333,6 +333,7 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
}
gas->changed_ind = g_attrib_register(gas->attrib, ATT_OP_HANDLE_IND,
+ GATTRIB_ALL_HANDLES,
indication_cb, gas, NULL);
if (device_get_appearance(gas->device, &app) < 0) {
diff --git a/profiles/heartrate/heartrate.c b/profiles/heartrate/heartrate.c
index 94d4b8d..d9d6c03 100644
--- a/profiles/heartrate/heartrate.c
+++ b/profiles/heartrate/heartrate.c
@@ -544,7 +544,7 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
hr->attrib = g_attrib_ref(attrib);
hr->attionotid = g_attrib_register(hr->attrib, ATT_OP_HANDLE_NOTIFY,
- notify_handler, hr, NULL);
+ GATTRIB_ALL_HANDLES, notify_handler, hr, NULL);
gatt_discover_char(hr->attrib, hr->svc_range->start, hr->svc_range->end,
NULL, discover_char_cb, hr);
diff --git a/profiles/input/hog_device.c b/profiles/input/hog_device.c
index a8cc568..52ebd95 100644
--- a/profiles/input/hog_device.c
+++ b/profiles/input/hog_device.c
@@ -612,8 +612,9 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
hogdev->attrib = g_attrib_ref(attrib);
hogdev->report_cb_id = g_attrib_register(hogdev->attrib,
- ATT_OP_HANDLE_NOTIFY, report_value_cb,
- hogdev, NULL);
+ ATT_OP_HANDLE_NOTIFY,
+ GATTRIB_ALL_HANDLES,
+ report_value_cb, hogdev, NULL);
if (hogdev->reports == NULL) {
gatt_discover_char(hogdev->attrib, prim->range.start,
diff --git a/profiles/scanparam/scan.c b/profiles/scanparam/scan.c
index e523df5..bbf646c 100644
--- a/profiles/scanparam/scan.c
+++ b/profiles/scanparam/scan.c
@@ -115,8 +115,8 @@ static void ccc_written_cb(guint8 status, const guint8 *pdu,
DBG("Scan Refresh: notification enabled");
scan->refresh_cb_id = g_attrib_register(scan->attrib,
- ATT_OP_HANDLE_NOTIFY, refresh_value_cb,
- user_data, NULL);
+ ATT_OP_HANDLE_NOTIFY, GATTRIB_ALL_HANDLES,
+ refresh_value_cb, user_data, NULL);
}
static void discover_descriptor_cb(guint8 status, const guint8 *pdu,
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index 98cfb34..de5a5bb 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -1201,8 +1201,10 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
t->attrib = g_attrib_ref(attrib);
t->attindid = g_attrib_register(t->attrib, ATT_OP_HANDLE_IND,
+ GATTRIB_ALL_HANDLES,
ind_handler, t, NULL);
t->attnotid = g_attrib_register(t->attrib, ATT_OP_HANDLE_NOTIFY,
+ GATTRIB_ALL_HANDLES,
notif_handler, t, NULL);
gatt_discover_char(t->attrib, t->svc_range->start, t->svc_range->end,
NULL, configure_thermometer_cb, t);
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 76a32af..d174301 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -1086,7 +1086,7 @@ guint attrib_channel_attach(GAttrib *attrib)
channel->attrib = g_attrib_ref(attrib);
channel->id = g_attrib_register(channel->attrib, GATTRIB_ALL_REQS,
- channel_handler, channel, NULL);
+ GATTRIB_ALL_HANDLES, channel_handler, channel, NULL);
channel->cleanup_id = g_io_add_watch(io, G_IO_HUP, channel_watch_cb,
channel);
--
1.7.12.2
^ permalink raw reply related
* [RFC BlueZ 0/5] gattrib: Registering per-handle event listeners
From: Vinicius Costa Gomes @ 2012-10-09 0:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
Hi,
This RFC is mostly to gather some comments about the idea, and see if
anyone can see any problem with it.
As we are starting to have devices that support multiple profiles,
something like this is inevitable, if we want to avoid having every
profile getting notified for each notification/indication received.
Cheers,
--
Vinicius Costa Gomes (5):
gattrib: Add support for listening for events for specific handles
scan: Use the per handle GATT event notifier
hog: Use the per handle GATT event notifier
heartrate: Use the per handle GATT event notifier
gas: Add the per handle GATT event notifier
attrib/client.c | 4 +-
attrib/gattrib.c | 33 ++++-
attrib/gattrib.h | 7 +-
attrib/gatttool.c | 8 +-
attrib/interactive.c | 8 +-
profiles/gatt/gas.c | 71 +++++----
profiles/heartrate/heartrate.c | 287 +++++++++++++++++++------------------
profiles/input/hog_device.c | 65 +++++----
profiles/scanparam/scan.c | 15 +-
profiles/thermometer/thermometer.c | 2 +
src/attrib-server.c | 2 +-
11 files changed, 262 insertions(+), 240 deletions(-)
--
1.7.12.2
^ permalink raw reply
* [PATCH v4 BlueZ 4/4] attrib: Remove opcode parameter from g_attrib_send()
From: Vinicius Costa Gomes @ 2012-10-09 0:17 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1349741858-18325-1-git-send-email-vinicius.gomes@openbossa.org>
In all uses of g_attrib_send() the opcode of the command/event is
already clear because of the att.h functions used to build the ATT
PDU.
---
attrib/client.c | 3 +--
attrib/gatt.c | 51 ++++++++++++++++----------------------
attrib/gattrib.c | 9 ++++---
attrib/gattrib.h | 6 ++---
attrib/gatttool.c | 2 +-
attrib/interactive.c | 2 +-
profiles/alert/server.c | 3 +--
profiles/gatt/gas.c | 2 +-
profiles/thermometer/thermometer.c | 3 +--
src/attrib-server.c | 3 +--
10 files changed, 37 insertions(+), 47 deletions(-)
diff --git a/attrib/client.c b/attrib/client.c
index 30513d1..8b29cbb 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -354,8 +354,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len,
case ATT_OP_HANDLE_IND:
opdu = g_attrib_get_buffer(gatt->attrib, &plen);
olen = enc_confirmation(opdu, plen);
- g_attrib_send(gatt->attrib, 0, opdu[0], opdu, olen,
- NULL, NULL, NULL);
+ g_attrib_send(gatt->attrib, 0, opdu, olen, NULL, NULL, NULL);
case ATT_OP_HANDLE_NOTIFY:
if (characteristic_set_value(chr, &pdu[3], len - 3) < 0)
DBG("Can't change Characteristic 0x%02x", handle);
diff --git a/attrib/gatt.c b/attrib/gatt.c
index d55e7fe..963fa20 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -176,8 +176,7 @@ static void primary_by_uuid_cb(guint8 status, const guint8 *ipdu,
if (oplen == 0)
goto done;
- g_attrib_send(dp->attrib, 0, buf[0], buf, oplen, primary_by_uuid_cb,
- dp, NULL);
+ g_attrib_send(dp->attrib, 0, buf, oplen, primary_by_uuid_cb, dp, NULL);
return;
done:
@@ -242,7 +241,7 @@ static void primary_all_cb(guint8 status, const guint8 *ipdu, guint16 iplen,
guint16 oplen = encode_discover_primary(end + 1, 0xffff, NULL,
buf, buflen);
- g_attrib_send(dp->attrib, 0, buf[0], buf, oplen, primary_all_cb,
+ g_attrib_send(dp->attrib, 0, buf, oplen, primary_all_cb,
dp, NULL);
return;
@@ -280,7 +279,7 @@ guint gatt_discover_primary(GAttrib *attrib, bt_uuid_t *uuid, gatt_cb_t func,
} else
cb = primary_all_cb;
- return g_attrib_send(attrib, 0, buf[0], buf, plen, cb, dp, NULL);
+ return g_attrib_send(attrib, 0, buf, plen, cb, dp, NULL);
}
static void resolve_included_uuid_cb(uint8_t status, const uint8_t *pdu,
@@ -331,7 +330,7 @@ static guint resolve_included_uuid(struct included_discovery *isd,
query->isd = isd_ref(isd);
query->included = incl;
- return g_attrib_send(isd->attrib, 0, buf[0], buf, oplen,
+ return g_attrib_send(isd->attrib, 0, buf, oplen,
resolve_included_uuid_cb, query, NULL);
}
@@ -368,8 +367,8 @@ static guint find_included(struct included_discovery *isd, uint16_t start)
oplen = enc_read_by_type_req(start, isd->end_handle, &uuid,
buf, buflen);
- return g_attrib_send(isd->attrib, 0, buf[0], buf, oplen,
- find_included_cb, isd_ref(isd), NULL);
+ return g_attrib_send(isd->attrib, 0, buf, oplen, find_included_cb,
+ isd_ref(isd), NULL);
}
static void find_included_cb(uint8_t status, const uint8_t *pdu, uint16_t len,
@@ -506,8 +505,8 @@ static void char_discovered_cb(guint8 status, const guint8 *ipdu, guint16 iplen,
if (oplen == 0)
return;
- g_attrib_send(dc->attrib, 0, buf[0], buf, oplen,
- char_discovered_cb, dc, NULL);
+ g_attrib_send(dc->attrib, 0, buf, oplen, char_discovered_cb,
+ dc, NULL);
return;
}
@@ -545,7 +544,7 @@ guint gatt_discover_char(GAttrib *attrib, uint16_t start, uint16_t end,
dc->end = end;
dc->uuid = g_memdup(uuid, sizeof(bt_uuid_t));
- return g_attrib_send(attrib, 0, buf[0], buf, plen, char_discovered_cb,
+ return g_attrib_send(attrib, 0, buf, plen, char_discovered_cb,
dc, NULL);
}
@@ -561,8 +560,7 @@ guint gatt_read_char_by_uuid(GAttrib *attrib, uint16_t start, uint16_t end,
if (plen == 0)
return 0;
- return g_attrib_send(attrib, 0, ATT_OP_READ_BY_TYPE_REQ,
- buf, plen, func, user_data, NULL);
+ return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL);
}
struct read_long_data {
@@ -621,8 +619,7 @@ static void read_blob_helper(guint8 status, const guint8 *rpdu, guint16 rlen,
plen = enc_read_blob_req(long_read->handle, long_read->size - 1,
buf, buflen);
- id = g_attrib_send(long_read->attrib, long_read->id,
- ATT_OP_READ_BLOB_REQ, buf, plen,
+ id = g_attrib_send(long_read->attrib, long_read->id, buf, plen,
read_blob_helper, long_read, read_long_destroy);
if (id != 0) {
@@ -658,9 +655,8 @@ static void read_char_helper(guint8 status, const guint8 *rpdu,
long_read->size = rlen;
plen = enc_read_blob_req(long_read->handle, rlen - 1, buf, buflen);
- id = g_attrib_send(long_read->attrib, long_read->id,
- ATT_OP_READ_BLOB_REQ, buf, plen, read_blob_helper,
- long_read, read_long_destroy);
+ id = g_attrib_send(long_read->attrib, long_read->id, buf, plen,
+ read_blob_helper, long_read, read_long_destroy);
if (id != 0) {
g_atomic_int_inc(&long_read->ref);
@@ -694,9 +690,8 @@ guint gatt_read_char(GAttrib *attrib, uint16_t handle, GAttribResultFunc func,
buf = g_attrib_get_buffer(attrib, &buflen);
plen = enc_read_req(handle, buf, buflen);
- id = g_attrib_send(attrib, 0, ATT_OP_READ_REQ, buf, plen,
- read_char_helper, long_read, read_long_destroy);
-
+ id = g_attrib_send(attrib, 0, buf, plen, read_char_helper,
+ long_read, read_long_destroy);
if (id == 0)
g_free(long_read);
else {
@@ -729,8 +724,7 @@ static guint execute_write(GAttrib *attrib, uint8_t flags,
if (plen == 0)
return 0;
- return g_attrib_send(attrib, 0, buf[0], buf, plen, func, user_data,
- NULL);
+ return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL);
}
static guint prepare_write(GAttrib *attrib, uint16_t handle, uint16_t offset,
@@ -779,7 +773,7 @@ static guint prepare_write(GAttrib *attrib, uint16_t handle, uint16_t offset,
if (plen == 0)
return 0;
- return g_attrib_send(attrib, 0, buf[0], buf, plen, prepare_write_cb,
+ return g_attrib_send(attrib, 0, buf, plen, prepare_write_cb,
user_data, NULL);
}
@@ -803,7 +797,7 @@ guint gatt_write_char(GAttrib *attrib, uint16_t handle, uint8_t *value,
plen = enc_write_cmd(handle, value, vlen, buf,
buflen);
- return g_attrib_send(attrib, 0, buf[0], buf, plen, func,
+ return g_attrib_send(attrib, 0, buf, plen, func,
user_data, NULL);
}
@@ -832,8 +826,7 @@ guint gatt_exchange_mtu(GAttrib *attrib, uint16_t mtu, GAttribResultFunc func,
buf = g_attrib_get_buffer(attrib, &buflen);
plen = enc_mtu_req(mtu, buf, buflen);
- return g_attrib_send(attrib, 0, ATT_OP_MTU_REQ, buf, plen, func,
- user_data, NULL);
+ return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL);
}
guint gatt_find_info(GAttrib *attrib, uint16_t start, uint16_t end,
@@ -848,8 +841,7 @@ guint gatt_find_info(GAttrib *attrib, uint16_t start, uint16_t end,
if (plen == 0)
return 0;
- return g_attrib_send(attrib, 0, ATT_OP_FIND_INFO_REQ, buf, plen, func,
- user_data, NULL);
+ return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL);
}
guint gatt_write_cmd(GAttrib *attrib, uint16_t handle, uint8_t *value, int vlen,
@@ -861,8 +853,7 @@ guint gatt_write_cmd(GAttrib *attrib, uint16_t handle, uint8_t *value, int vlen,
buf = g_attrib_get_buffer(attrib, &buflen);
plen = enc_write_cmd(handle, value, vlen, buf, buflen);
- return g_attrib_send(attrib, 0, ATT_OP_WRITE_CMD, buf, plen, NULL,
- user_data, notify);
+ return g_attrib_send(attrib, 0, buf, plen, NULL, user_data, notify);
}
static sdp_data_t *proto_seq_find(sdp_list_t *proto_list)
diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index 108d1d3..6f6942f 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -472,12 +472,13 @@ GAttrib *g_attrib_new(GIOChannel *io)
return g_attrib_ref(attrib);
}
-guint g_attrib_send(GAttrib *attrib, guint id, guint8 opcode,
- const guint8 *pdu, guint16 len, GAttribResultFunc func,
- gpointer user_data, GDestroyNotify notify)
+guint g_attrib_send(GAttrib *attrib, guint id, const guint8 *pdu, guint16 len,
+ GAttribResultFunc func, gpointer user_data,
+ GDestroyNotify notify)
{
struct command *c;
GQueue *queue;
+ uint8_t opcode;
if (attrib->stale)
return 0;
@@ -486,6 +487,8 @@ guint g_attrib_send(GAttrib *attrib, guint id, guint8 opcode,
if (c == NULL)
return 0;
+ opcode = pdu[0];
+
c->opcode = opcode;
c->expected = opcode2expected(opcode);
c->pdu = g_malloc(len);
diff --git a/attrib/gattrib.h b/attrib/gattrib.h
index bcff039..bca966f 100644
--- a/attrib/gattrib.h
+++ b/attrib/gattrib.h
@@ -50,9 +50,9 @@ GIOChannel *g_attrib_get_channel(GAttrib *attrib);
gboolean g_attrib_set_destroy_function(GAttrib *attrib,
GDestroyNotify destroy, gpointer user_data);
-guint g_attrib_send(GAttrib *attrib, guint id, guint8 opcode,
- const guint8 *pdu, guint16 len, GAttribResultFunc func,
- gpointer user_data, GDestroyNotify notify);
+guint g_attrib_send(GAttrib *attrib, guint id, const guint8 *pdu, guint16 len,
+ GAttribResultFunc func, gpointer user_data,
+ GDestroyNotify notify);
gboolean g_attrib_cancel(GAttrib *attrib, guint id);
gboolean g_attrib_cancel_all(GAttrib *attrib);
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 3b0ebbc..16cce0c 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -104,7 +104,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
olen = enc_confirmation(opdu, plen);
if (olen > 0)
- g_attrib_send(attrib, 0, opdu[0], opdu, olen, NULL, NULL, NULL);
+ g_attrib_send(attrib, 0, opdu, olen, NULL, NULL, NULL);
}
static gboolean listen_start(gpointer user_data)
diff --git a/attrib/interactive.c b/attrib/interactive.c
index 85f72ad..b41a7bb 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -135,7 +135,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
olen = enc_confirmation(opdu, plen);
if (olen > 0)
- g_attrib_send(attrib, 0, opdu[0], opdu, olen, NULL, NULL, NULL);
+ g_attrib_send(attrib, 0, opdu, olen, NULL, NULL, NULL);
}
static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
diff --git a/profiles/alert/server.c b/profiles/alert/server.c
index b8ea141..77de704 100644
--- a/profiles/alert/server.c
+++ b/profiles/alert/server.c
@@ -381,8 +381,7 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
al_adapter->hnd_value[type],
al_adapter->hnd_ccc[type]);
- g_attrib_send(attrib, 0, ATT_OP_HANDLE_NOTIFY, pdu, len,
- NULL, NULL, NULL);
+ g_attrib_send(attrib, 0, pdu, len, NULL, NULL, NULL);
end:
btd_device_remove_attio_callback(cb->device, cb->id);
diff --git a/profiles/gatt/gas.c b/profiles/gatt/gas.c
index 82c2ef0..74ca9ce 100644
--- a/profiles/gatt/gas.c
+++ b/profiles/gatt/gas.c
@@ -224,7 +224,7 @@ static void indication_cb(const uint8_t *pdu, uint16_t len, gpointer user_data)
/* Confirming indication received */
opdu = g_attrib_get_buffer(gas->attrib, &plen);
olen = enc_confirmation(opdu, plen);
- g_attrib_send(gas->attrib, 0, opdu[0], opdu, olen, NULL, NULL, NULL);
+ g_attrib_send(gas->attrib, 0, opdu, olen, NULL, NULL, NULL);
btd_device_gatt_set_service_changed(gas->device, start, end);
}
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index 3506ba7..98cfb34 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -1167,8 +1167,7 @@ static void ind_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
olen = enc_confirmation(opdu, plen);
if (olen > 0)
- g_attrib_send(t->attrib, 0, opdu[0], opdu, olen, NULL, NULL,
- NULL);
+ g_attrib_send(t->attrib, 0, opdu, olen, NULL, NULL, NULL);
}
static void notif_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 9155ab2..76a32af 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -1027,8 +1027,7 @@ done:
length = enc_error_resp(ipdu[0], 0x0000, status, opdu,
channel->mtu);
- g_attrib_send(channel->attrib, 0, opdu[0], opdu, length,
- NULL, NULL, NULL);
+ g_attrib_send(channel->attrib, 0, opdu, length, NULL, NULL, NULL);
}
guint attrib_channel_attach(GAttrib *attrib)
--
1.7.12.2
^ permalink raw reply related
* [PATCH v4 BlueZ 3/4] core: Add support for included services
From: Vinicius Costa Gomes @ 2012-10-09 0:17 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1349741858-18325-1-git-send-email-vinicius.gomes@openbossa.org>
Soon after the primary service discovery is complete, we do a included
services discovery for all found services and add each included service
to the 'services' list so they can be probe()'d as a normal profile.
This will also make these services to appear on the D-Bus object tree.
---
src/device.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 96 insertions(+), 13 deletions(-)
diff --git a/src/device.c b/src/device.c
index d356631..e94b222 100644
--- a/src/device.c
+++ b/src/device.c
@@ -112,6 +112,12 @@ struct browse_req {
guint listener_id;
};
+struct included_search {
+ struct browse_req *req;
+ GSList *services;
+ GSList *current;
+};
+
struct attio_data {
guint id;
attio_connect_cb cfunc;
@@ -2192,21 +2198,10 @@ static void device_unregister_services(struct btd_device *device)
device->services = NULL;
}
-static void primary_cb(GSList *services, guint8 status, gpointer user_data)
+static void register_all_services(struct browse_req *req, GSList *services)
{
- struct browse_req *req = user_data;
struct btd_device *device = req->device;
- if (status) {
- if (req->msg) {
- DBusMessage *reply;
- reply = btd_error_failed(req->msg,
- att_ecode2str(status));
- g_dbus_send_message(btd_get_dbus_connection(), reply);
- }
- goto done;
- }
-
device_set_temporary(device, FALSE);
if (device->services)
@@ -2231,11 +2226,99 @@ static void primary_cb(GSList *services, guint8 status, gpointer user_data)
store_services(device);
-done:
device->browse = NULL;
browse_request_free(req);
}
+static int service_by_range_cmp(gconstpointer a, gconstpointer b)
+{
+ const struct gatt_primary *prim = a;
+ const struct att_range *range = b;
+
+ return memcmp(&prim->range, range, sizeof(*range));
+}
+
+static void find_included_cb(GSList *includes, uint8_t status,
+ gpointer user_data)
+{
+ struct included_search *search = user_data;
+ struct btd_device *device = search->req->device;
+ struct gatt_primary *prim;
+ GSList *l;
+
+ if (includes == NULL)
+ goto done;
+
+ for (l = includes; l; l = l->next) {
+ struct gatt_included *incl = l->data;
+
+ if (g_slist_find_custom(search->services, &incl->range,
+ service_by_range_cmp))
+ continue;
+
+ prim = g_new0(struct gatt_primary, 1);
+ memcpy(prim->uuid, incl->uuid, sizeof(prim->uuid));
+ memcpy(&prim->range, &incl->range, sizeof(prim->range));
+
+ search->services = g_slist_append(search->services, prim);
+ }
+
+done:
+ search->current = search->current->next;
+ if (search->current == NULL) {
+ register_all_services(search->req, search->services);
+ g_slist_free(search->services);
+ g_free(search);
+ return;
+ }
+
+ prim = search->current->data;
+ gatt_find_included(device->attrib, prim->range.start, prim->range.end,
+ find_included_cb, search);
+}
+
+static void find_included_services(struct browse_req *req, GSList *services)
+{
+ struct btd_device *device = req->device;
+ struct included_search *search;
+ struct gatt_primary *prim;
+
+ if (services == NULL)
+ return;
+
+ search = g_new0(struct included_search, 1);
+ search->req = req;
+ search->services = g_slist_copy(services);
+ search->current = search->services;
+
+ prim = search->current->data;
+ gatt_find_included(device->attrib, prim->range.start, prim->range.end,
+ find_included_cb, search);
+
+}
+
+static void primary_cb(GSList *services, guint8 status, gpointer user_data)
+{
+ struct browse_req *req = user_data;
+
+ if (status) {
+ struct btd_device *device = req->device;
+
+ if (req->msg) {
+ DBusMessage *reply;
+ reply = btd_error_failed(req->msg,
+ att_ecode2str(status));
+ g_dbus_send_message(btd_get_dbus_connection(), reply);
+ }
+
+ device->browse = NULL;
+ browse_request_free(req);
+ return;
+ }
+
+ find_included_services(req, services);
+}
+
static void bonding_request_free(struct bonding_req *bonding)
{
struct btd_device *device;
--
1.7.12.2
^ permalink raw reply related
* [PATCH v4 BlueZ 2/4] gatttool: Add "included" command
From: Vinicius Costa Gomes @ 2012-10-09 0:17 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Jefferson Delfes
In-Reply-To: <1349741858-18325-1-git-send-email-vinicius.gomes@openbossa.org>
From: Jefferson Delfes <jefferson.delfes@openbossa.org>
New command to find included services in interactive mode.
---
This produces a warning when applying, but the warning can be ignored for that
particular string.
WARNING:SPLIT_STRING: quoted string split across lines
#36: FILE: attrib/interactive.c:233:
+ printf("handle: 0x%04x, start handle: 0x%04x, "
+ "end handle: 0x%04x uuid: %s\n",
attrib/interactive.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)
diff --git a/attrib/interactive.c b/attrib/interactive.c
index 8d9531f..85f72ad 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -211,6 +211,34 @@ static void primary_by_uuid_cb(GSList *ranges, guint8 status,
rl_forced_update_display();
}
+static void included_cb(GSList *includes, guint8 status, gpointer user_data)
+{
+ GSList *l;
+
+ if (status) {
+ printf("Find included services failed: %s\n",
+ att_ecode2str(status));
+ goto done;
+ }
+
+ if (includes == NULL) {
+ printf("No included services found for this range\n");
+ goto done;
+ }
+
+ printf("\n");
+ for (l = includes; l; l = l->next) {
+ struct gatt_included *incl = l->data;
+ printf("handle: 0x%04x, start handle: 0x%04x, "
+ "end handle: 0x%04x uuid: %s\n",
+ incl->handle, incl->range.start,
+ incl->range.end, incl->uuid);
+ }
+
+done:
+ rl_forced_update_display();
+}
+
static void char_cb(GSList *characteristics, guint8 status, gpointer user_data)
{
GSList *l;
@@ -431,6 +459,36 @@ static int strtohandle(const char *src)
return dst;
}
+static void cmd_included(int argcp, char **argvp)
+{
+ int start = 0x0001;
+ int end = 0xffff;
+
+ if (conn_state != STATE_CONNECTED) {
+ printf("Command failed: disconnected\n");
+ return;
+ }
+
+ if (argcp > 1) {
+ start = strtohandle(argvp[1]);
+ if (start < 0) {
+ printf("Invalid start handle: %s\n", argvp[1]);
+ return;
+ }
+ end = start;
+ }
+
+ if (argcp > 2) {
+ end = strtohandle(argvp[2]);
+ if (end < 0) {
+ printf("Invalid end handle: %s\n", argvp[2]);
+ return;
+ }
+ }
+
+ gatt_find_included(attrib, start, end, included_cb, NULL);
+}
+
static void cmd_char(int argcp, char **argvp)
{
int start = 0x0001;
@@ -743,6 +801,8 @@ static struct {
"Disconnect from a remote device" },
{ "primary", cmd_primary, "[UUID]",
"Primary Service Discovery" },
+ { "included", cmd_included, "[start hnd [end hnd]]",
+ "Find Included Services" },
{ "characteristics", cmd_char, "[start hnd [end hnd [UUID]]]",
"Characteristics Discovery" },
{ "char-desc", cmd_char_desc, "[start hnd] [end hnd]",
--
1.7.12.2
^ permalink raw reply related
* [PATCH v4 BlueZ 1/4] gatt: Add support for find included services
From: Vinicius Costa Gomes @ 2012-10-09 0:17 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
Some services like HID over LE can reference another service using
included services.
See Vol 3, Part G, section 2.6.3 of Core specification for more
details.
---
attrib/gatt.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
attrib/gatt.h | 9 +++
2 files changed, 201 insertions(+)
diff --git a/attrib/gatt.c b/attrib/gatt.c
index 882f3c1..d55e7fe 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -45,6 +45,22 @@ struct discover_primary {
void *user_data;
};
+/* Used for the Included Services Discovery (ISD) procedure */
+struct included_discovery {
+ GAttrib *attrib;
+ int refs;
+ int err;
+ uint16_t end_handle;
+ GSList *includes;
+ gatt_cb_t cb;
+ void *user_data;
+};
+
+struct included_uuid_query {
+ struct included_discovery *isd;
+ struct gatt_included *included;
+};
+
struct discover_char {
GAttrib *attrib;
bt_uuid_t *uuid;
@@ -61,6 +77,25 @@ static void discover_primary_free(struct discover_primary *dp)
g_free(dp);
}
+static struct included_discovery *isd_ref(struct included_discovery *isd)
+{
+ g_atomic_int_inc(&isd->refs);
+
+ return isd;
+}
+
+static void isd_unref(struct included_discovery *isd)
+{
+ if (g_atomic_int_dec_and_test(&isd->refs) == FALSE)
+ return;
+
+ isd->cb(isd->includes, isd->err, isd->user_data);
+
+ g_slist_free_full(isd->includes, g_free);
+ g_attrib_unref(isd->attrib);
+ g_free(isd);
+}
+
static void discover_char_free(struct discover_char *dc)
{
g_slist_free_full(dc->characteristics, g_free);
@@ -248,6 +283,163 @@ guint gatt_discover_primary(GAttrib *attrib, bt_uuid_t *uuid, gatt_cb_t func,
return g_attrib_send(attrib, 0, buf[0], buf, plen, cb, dp, NULL);
}
+static void resolve_included_uuid_cb(uint8_t status, const uint8_t *pdu,
+ uint16_t len, gpointer user_data)
+{
+ struct included_uuid_query *query = user_data;
+ struct included_discovery *isd = query->isd;
+ struct gatt_included *incl = query->included;
+ unsigned int err = status;
+ bt_uuid_t uuid;
+ size_t buflen;
+ uint8_t *buf;
+
+ if (err)
+ goto done;
+
+ buf = g_attrib_get_buffer(isd->attrib, &buflen);
+ if (dec_read_resp(pdu, len, buf, buflen) != 16) {
+ err = ATT_ECODE_IO;
+ goto done;
+ }
+
+ uuid = att_get_uuid128(buf);
+ bt_uuid_to_string(&uuid, incl->uuid, sizeof(incl->uuid));
+ isd->includes = g_slist_append(isd->includes, incl);
+
+done:
+ if (err)
+ g_free(incl);
+
+ if (isd->err == 0)
+ isd->err = err;
+
+ isd_unref(isd);
+
+ g_free(query);
+}
+
+static guint resolve_included_uuid(struct included_discovery *isd,
+ struct gatt_included *incl)
+{
+ struct included_uuid_query *query;
+ size_t buflen;
+ uint8_t *buf = g_attrib_get_buffer(isd->attrib, &buflen);
+ guint16 oplen = enc_read_req(incl->range.start, buf, buflen);
+
+ query = g_new0(struct included_uuid_query, 1);
+ query->isd = isd_ref(isd);
+ query->included = incl;
+
+ return g_attrib_send(isd->attrib, 0, buf[0], buf, oplen,
+ resolve_included_uuid_cb, query, NULL);
+}
+
+static struct gatt_included *included_from_buf(const uint8_t *buf, gsize len)
+{
+ struct gatt_included *incl = g_new0(struct gatt_included, 1);
+
+ incl->handle = att_get_u16(&buf[0]);
+ incl->range.start = att_get_u16(&buf[2]);
+ incl->range.end = att_get_u16(&buf[4]);
+
+ if (len == 8) {
+ bt_uuid_t uuid128;
+ bt_uuid_t uuid16 = att_get_uuid16(&buf[6]);
+
+ bt_uuid_to_uuid128(&uuid16, &uuid128);
+ bt_uuid_to_string(&uuid128, incl->uuid, sizeof(incl->uuid));
+ }
+
+ return incl;
+}
+
+static void find_included_cb(uint8_t status, const uint8_t *pdu, uint16_t len,
+ gpointer user_data);
+
+static guint find_included(struct included_discovery *isd, uint16_t start)
+{
+ bt_uuid_t uuid;
+ size_t buflen;
+ uint8_t *buf = g_attrib_get_buffer(isd->attrib, &buflen);
+ guint16 oplen;
+
+ bt_uuid16_create(&uuid, GATT_INCLUDE_UUID);
+ oplen = enc_read_by_type_req(start, isd->end_handle, &uuid,
+ buf, buflen);
+
+ return g_attrib_send(isd->attrib, 0, buf[0], buf, oplen,
+ find_included_cb, isd_ref(isd), NULL);
+}
+
+static void find_included_cb(uint8_t status, const uint8_t *pdu, uint16_t len,
+ gpointer user_data)
+{
+ struct included_discovery *isd = user_data;
+ uint16_t last_handle = isd->end_handle;
+ unsigned int err = status;
+ struct att_data_list *list;
+ int i;
+
+ if (err == ATT_ECODE_ATTR_NOT_FOUND)
+ err = 0;
+
+ if (status)
+ goto done;
+
+ list = dec_read_by_type_resp(pdu, len);
+ if (list == NULL) {
+ err = ATT_ECODE_IO;
+ goto done;
+ }
+
+ if (list->len != 6 && list->len != 8) {
+ err = ATT_ECODE_IO;
+ att_data_list_free(list);
+ goto done;
+ }
+
+ for (i = 0; i < list->num; i++) {
+ struct gatt_included *incl;
+
+ incl = included_from_buf(list->data[i], list->len);
+ last_handle = incl->handle;
+
+ /* 128 bit UUID, needs resolving */
+ if (list->len == 6) {
+ resolve_included_uuid(isd, incl);
+ continue;
+ }
+
+ isd->includes = g_slist_append(isd->includes, incl);
+ }
+
+ att_data_list_free(list);
+
+ if (last_handle < isd->end_handle)
+ find_included(isd, last_handle + 1);
+
+done:
+ if (isd->err == 0)
+ isd->err = err;
+
+ isd_unref(isd);
+}
+
+unsigned int gatt_find_included(GAttrib *attrib, uint16_t start, uint16_t end,
+ gatt_cb_t func, gpointer user_data)
+{
+ struct included_discovery *isd;
+
+ isd = g_new0(struct included_discovery, 1);
+ isd->attrib = g_attrib_ref(attrib);
+ isd->end_handle = end;
+ isd->cb = func;
+ isd->user_data = user_data;
+
+ return find_included(isd, start);
+}
+
static void char_discovered_cb(guint8 status, const guint8 *ipdu, guint16 iplen,
gpointer user_data)
{
diff --git a/attrib/gatt.h b/attrib/gatt.h
index 3862011..305b4c6 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -61,6 +61,12 @@ struct gatt_primary {
struct att_range range;
};
+struct gatt_included {
+ char uuid[MAX_LEN_UUID_STR + 1];
+ uint16_t handle;
+ struct att_range range;
+};
+
struct gatt_char {
char uuid[MAX_LEN_UUID_STR + 1];
uint16_t handle;
@@ -71,6 +77,9 @@ struct gatt_char {
guint gatt_discover_primary(GAttrib *attrib, bt_uuid_t *uuid, gatt_cb_t func,
gpointer user_data);
+unsigned int gatt_find_included(GAttrib *attrib, uint16_t start, uint16_t end,
+ gatt_cb_t func, gpointer user_data);
+
guint gatt_discover_char(GAttrib *attrib, uint16_t start, uint16_t end,
bt_uuid_t *uuid, gatt_cb_t func,
gpointer user_data);
--
1.7.12.2
^ permalink raw reply related
* [PATCH BlueZ] Fix registering HoG service for non-HoG profiles
From: Vinicius Costa Gomes @ 2012-10-09 0:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
We need to handle the case that the device has multiple HoG services,
but before registering we must check the service UUID.
---
profiles/input/hog_manager.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index 362c38a..9dbaff2 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -91,6 +91,9 @@ static int hog_device_probe(struct btd_profile *p, struct btd_device *device,
struct gatt_primary *prim = l->data;
struct hog_device *hogdev;
+ if (strcmp(prim->uuid, HOG_UUID) != 0)
+ continue;
+
hogdev = hog_device_register(device, prim);
if (hogdev == NULL)
continue;
--
1.7.12.2
^ permalink raw reply related
* [PATCH resend] net, bluetooth: don't attempt to free a channel that wasn't created
From: Sasha Levin @ 2012-10-08 20:48 UTC (permalink / raw)
To: marcel, gustavo, johan.hedberg, davem
Cc: linux-bluetooth, davej, netdev, linux-kernel, levinsasha928,
Sasha Levin
We may currently attempt to free a channel which wasn't created due to
an error in the initialization path, this would cause a NULL ptr deref.
This would cause the following oops:
[ 12.919073] BUG: unable to handle kernel NULL pointer dereference at 0000000000000010
[ 12.919131] IP: [<ffffffff836645c4>] l2cap_chan_put+0x34/0x50
[ 12.919135] PGD 0
[ 12.919138] Oops: 0002 [#1] PREEMPT SMP DEBUG_PAGEALLOC
[ 12.919193] Dumping ftrace buffer:
[ 12.919242] (ftrace buffer empty)
[ 12.919314] Modules linked in:
[ 12.919318] CPU 1
[ 12.919319] Pid: 6210, comm: krfcommd Tainted: G W 3.6.0-next-20121004-sasha-00005-gb010653-dirty #30
[ 12.919374] RIP: 0010:[<ffffffff836645c4>] [<ffffffff836645c4>] l2cap_chan_put+0x34/0x50
[ 12.919377] RSP: 0000:ffff880066933c38 EFLAGS: 00010246
[ 12.919378] RAX: ffffffff8366c780 RBX: 0000000000000000 RCX: 6666666666666667
[ 12.919379] RDX: 0000000000000fa0 RSI: ffffffff84d3f79e RDI: 0000000000000010
[ 12.919381] RBP: ffff880066933c48 R08: ffffffff859989f8 R09: 0000000000000001
[ 12.919382] R10: 0000000000000000 R11: 7fffffffffffffff R12: 0000000000000000
[ 12.919383] R13: ffff88009b00a200 R14: ffff88009b00a200 R15: 0000000000000001
[ 12.919385] FS: 0000000000000000(0000) GS:ffff880033600000(0000) knlGS:0000000000000000
[ 12.919437] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 12.919440] CR2: 0000000000000010 CR3: 0000000005026000 CR4: 00000000000406e0
[ 12.919446] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 12.919451] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[ 12.919504] Process krfcommd (pid: 6210, threadinfo ffff880066932000, task ffff880065c4b000)
[ 12.919506] Stack:
[ 12.919510] ffff88009b00a200 ffff880032084000 ffff880066933c68 ffffffff8366c7bc
[ 12.919513] 7fffffffffffffff ffff880032084000 ffff880066933c98 ffffffff833ae0ae
[ 12.919516] ffff880066933ca8 0000000000000000 0000000000000000 ffff88009b00a200
[ 12.919517] Call Trace:
[ 12.919522] [<ffffffff8366c7bc>] l2cap_sock_destruct+0x3c/0x80
[ 12.919527] [<ffffffff833ae0ae>] __sk_free+0x1e/0x1f0
[ 12.919530] [<ffffffff833ae2f7>] sk_free+0x17/0x20
[ 12.919585] [<ffffffff8366ca4e>] l2cap_sock_alloc.constprop.5+0x9e/0xd0
[ 12.919591] [<ffffffff8366cb9e>] l2cap_sock_create+0x7e/0x100
[ 12.919652] [<ffffffff83a4f32a>] ? _raw_read_lock+0x6a/0x80
[ 12.919658] [<ffffffff836402c4>] ? bt_sock_create+0x74/0x110
[ 12.919660] [<ffffffff83640308>] bt_sock_create+0xb8/0x110
[ 12.919664] [<ffffffff833aa232>] __sock_create+0x282/0x3b0
[ 12.919720] [<ffffffff833aa0b0>] ? __sock_create+0x100/0x3b0
[ 12.919725] [<ffffffff836785b0>] ? rfcomm_process_sessions+0x17e0/0x17e0
[ 12.919779] [<ffffffff833aa37f>] sock_create_kern+0x1f/0x30
[ 12.919784] [<ffffffff83675714>] rfcomm_l2sock_create+0x44/0x70
[ 12.919787] [<ffffffff836785b0>] ? rfcomm_process_sessions+0x17e0/0x17e0
[ 12.919790] [<ffffffff836785fe>] rfcomm_run+0x4e/0x1f0
[ 12.919846] [<ffffffff836785b0>] ? rfcomm_process_sessions+0x17e0/0x17e0
[ 12.919852] [<ffffffff81138ee3>] kthread+0xe3/0xf0
[ 12.919908] [<ffffffff8117b12e>] ? put_lock_stats.isra.14+0xe/0x40
[ 12.919914] [<ffffffff81138e00>] ? flush_kthread_work+0x1f0/0x1f0
[ 12.919968] [<ffffffff83a5077c>] ret_from_fork+0x7c/0x90
[ 12.919973] [<ffffffff81138e00>] ? flush_kthread_work+0x1f0/0x1f0
[ 12.920161] Code: 83 ec 08 f6 05 ff 58 44 02 04 74 1b 8b 4f 10 48 89 fa 48 c7 c6 d9 d7 d4 84 48 c7 c7 80 9e aa 85 31 c0 e8 80
ac 3a fe 48 8d 7b 10 <f0> 83 6b 10 01 0f 94 c0 84 c0 74 05 e8 8b e0 ff ff 48 83 c4 08
[ 12.920165] RIP [<ffffffff836645c4>] l2cap_chan_put+0x34/0x50
[ 12.920166] RSP <ffff880066933c38>
[ 12.920167] CR2: 0000000000000010
[ 12.920417] ---[ end trace 5a9114e8a158ab84 ]---
Introduced in commit 61d6ef3e ("Bluetooth: Make better use of l2cap_chan
reference counting").
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
---
net/bluetooth/l2cap_sock.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 083f2bf..66c295a 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1083,7 +1083,8 @@ static void l2cap_sock_destruct(struct sock *sk)
{
BT_DBG("sk %p", sk);
- l2cap_chan_put(l2cap_pi(sk)->chan);
+ if (l2cap_pi(sk)->chan)
+ l2cap_chan_put(l2cap_pi(sk)->chan);
if (l2cap_pi(sk)->rx_busy_skb) {
kfree_skb(l2cap_pi(sk)->rx_busy_skb);
l2cap_pi(sk)->rx_busy_skb = NULL;
--
1.7.12
^ permalink raw reply related
* [PATCH BlueZ] service: Fix passing stack variable as reference value
From: Luiz Augusto von Dentz @ 2012-10-08 20:08 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
BDADDR_ANY cannot be return as it uses stack allocation:
Conditional jump or move depends on uninitialised value(s)
at 0x170E47: sdp_record_remove (sdpd-database.c:269)
by 0x17071A: remove_record_from_server (sdpd-service.c:290)
by 0x14D416: exit_callback (service.c:131)
by 0x124396: service_filter (watch.c:486)
by 0x12405A: message_filter (watch.c:554)
by 0x4F63A35: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.5.6)
by 0x122EE7: message_dispatch (mainloop.c:76)
by 0x4C7B3BA: ??? (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x4C7A824: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x4C7AB57: ??? (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x4C7AF51: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x1225B1: main (main.c:551)
Uninitialised value was created by a stack allocation
at 0x1705B0: add_record_to_server (sdpd-service.c:235)
Conditional jump or move depends on uninitialised value(s)
at 0x4A0AD21: bcmp (mc_replace_strmem.c:889)
by 0x4C959E0: g_slist_find_custom (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x17C059: manager_find_adapter (manager.c:291)
by 0x170E8F: sdp_record_remove (sdpd-database.c:270)
by 0x17071A: remove_record_from_server (sdpd-service.c:290)
by 0x14D416: exit_callback (service.c:131)
by 0x124396: service_filter (watch.c:486)
by 0x12405A: message_filter (watch.c:554)
by 0x4F63A35: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.5.6)
by 0x122EE7: message_dispatch (mainloop.c:76)
by 0x4C7B3BA: ??? (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x4C7A824: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3200.4)
Uninitialised value was created by a stack allocation
at 0x1705B0: add_record_to_server (sdpd-service.c:235)
---
plugins/service.c | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/plugins/service.c b/plugins/service.c
index cea36e0..eebacc5 100644
--- a/plugins/service.c
+++ b/plugins/service.c
@@ -45,6 +45,8 @@
#include "log.h"
#define SERVICE_INTERFACE "org.bluez.Service"
+#define get_address(adp) \
+ (adp->adapter ? adapter_get_address(adp->adapter) : BDADDR_ANY)
struct record_data {
uint32_t handle;
@@ -134,14 +136,6 @@ static void exit_callback(DBusConnection *conn, void *user_data)
g_free(user_record);
}
-static const bdaddr_t *get_address(struct service_adapter *serv_adapter)
-{
- if (serv_adapter->adapter)
- return adapter_get_address(serv_adapter->adapter);
-
- return BDADDR_ANY;
-}
-
static int add_xml_record(const char *sender,
struct service_adapter *serv_adapter,
const char *record, dbus_uint32_t *handle)
--
1.7.11.4
^ permalink raw reply related
* [RFCv1 6/6] Bluetooth: AMP: Hanlde AMP_LINK case in conn_put
From: Andrei Emeltchenko @ 2012-10-08 14:52 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1349707932-10006-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Handle AMP link when setting up disconnect timeout.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/hci_core.h | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 744713b..0cc8c85 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -604,7 +604,10 @@ static inline void hci_conn_put(struct hci_conn *conn)
if (atomic_dec_and_test(&conn->refcnt)) {
unsigned long timeo;
- if (conn->type == ACL_LINK || conn->type == LE_LINK) {
+
+ switch (conn->type) {
+ case ACL_LINK:
+ case LE_LINK:
del_timer(&conn->idle_timer);
if (conn->state == BT_CONNECTED) {
timeo = conn->disc_timeout;
@@ -613,12 +616,20 @@ static inline void hci_conn_put(struct hci_conn *conn)
} else {
timeo = msecs_to_jiffies(10);
}
- } else {
+ break;
+
+ case AMP_LINK:
+ timeo = conn->disc_timeout;
+ break;
+
+ default:
timeo = msecs_to_jiffies(10);
+ break;
}
+
cancel_delayed_work(&conn->disc_work);
queue_delayed_work(conn->hdev->workqueue,
- &conn->disc_work, timeo);
+ &conn->disc_work, timeo);
}
}
--
1.7.9.5
^ permalink raw reply related
* [RFCv1 5/6] Bluetooth: AMP: Handle AMP_LINK connection
From: Andrei Emeltchenko @ 2012-10-08 14:52 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1349707932-10006-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
AMP_LINK represents physical link between AMP controllers.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/hci_core.h | 13 +++++++++++++
net/bluetooth/hci_core.c | 22 +++++++++++++++++++---
net/bluetooth/hci_event.c | 1 +
3 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 951f604..744713b 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -73,6 +73,7 @@ struct discovery_state {
struct hci_conn_hash {
struct list_head list;
unsigned int acl_num;
+ unsigned int amp_num;
unsigned int sco_num;
unsigned int le_num;
};
@@ -447,6 +448,9 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
case ACL_LINK:
h->acl_num++;
break;
+ case AMP_LINK:
+ h->amp_num++;
+ break;
case LE_LINK:
h->le_num++;
break;
@@ -468,6 +472,9 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
case ACL_LINK:
h->acl_num--;
break;
+ case AMP_LINK:
+ h->amp_num--;
+ break;
case LE_LINK:
h->le_num--;
break;
@@ -484,6 +491,8 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type)
switch (type) {
case ACL_LINK:
return h->acl_num;
+ case AMP_LINK:
+ return h->amp_num;
case LE_LINK:
return h->le_num;
case SCO_LINK:
@@ -800,6 +809,10 @@ static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason)
sco_disconn_cfm(conn, reason);
break;
+ /* L2CAP would be handled for BREDR chan */
+ case AMP_LINK:
+ break;
+
default:
BT_ERR("unknown link type %d", conn->type);
break;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index bd26cb5..2e72c41 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2379,6 +2379,9 @@ static struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
case ACL_LINK:
cnt = hdev->acl_cnt;
break;
+ case AMP_LINK:
+ cnt = hdev->block_cnt;
+ break;
case SCO_LINK:
case ESCO_LINK:
cnt = hdev->sco_cnt;
@@ -2508,11 +2511,19 @@ static void hci_sched_acl_blk(struct hci_dev *hdev)
struct hci_chan *chan;
struct sk_buff *skb;
int quote;
+ u8 type;
__check_timeout(hdev, cnt);
+ BT_DBG("%s", hdev->name);
+
+ if (hdev->dev_type == HCI_AMP)
+ type = AMP_LINK;
+ else
+ type = ACL_LINK;
+
while (hdev->block_cnt > 0 &&
- (chan = hci_chan_sent(hdev, ACL_LINK, "e))) {
+ (chan = hci_chan_sent(hdev, type, "e))) {
u32 priority = (skb_peek(&chan->data_q))->priority;
while (quote > 0 && (skb = skb_peek(&chan->data_q))) {
int blocks;
@@ -2545,14 +2556,19 @@ static void hci_sched_acl_blk(struct hci_dev *hdev)
}
if (cnt != hdev->block_cnt)
- hci_prio_recalculate(hdev, ACL_LINK);
+ hci_prio_recalculate(hdev, type);
}
static void hci_sched_acl(struct hci_dev *hdev)
{
BT_DBG("%s", hdev->name);
- if (!hci_conn_num(hdev, ACL_LINK))
+ /* No ACL link over BR/EDR controller */
+ if (!hci_conn_num(hdev, ACL_LINK) && hdev->dev_type == HCI_BREDR)
+ return;
+
+ /* No AMP link over AMP controller */
+ if (!hci_conn_num(hdev, AMP_LINK) && hdev->dev_type == HCI_AMP)
return;
switch (hdev->flow_ctl_mode) {
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index c479732..9a1c2f6 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2720,6 +2720,7 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
switch (conn->type) {
case ACL_LINK:
+ case AMP_LINK:
hdev->block_cnt += block_count;
if (hdev->block_cnt > hdev->num_blocks)
hdev->block_cnt = hdev->num_blocks;
--
1.7.9.5
^ permalink raw reply related
* [RFCv1 4/6] Bluetooth: Handle number of compl blocks for AMP_LINK
From: Andrei Emeltchenko @ 2012-10-08 14:52 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1349707932-10006-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Add handling blocks count for AMP link.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
net/bluetooth/hci_event.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 82e478a..c479732 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2698,13 +2698,21 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
for (i = 0; i < ev->num_hndl; i++) {
struct hci_comp_blocks_info *info = &ev->handles[i];
- struct hci_conn *conn;
+ struct hci_conn *conn = NULL;
+ struct hci_chan *chan;
__u16 handle, block_count;
handle = __le16_to_cpu(info->handle);
block_count = __le16_to_cpu(info->blocks);
- conn = hci_conn_hash_lookup_handle(hdev, handle);
+ if (hdev->dev_type == HCI_BREDR) {
+ conn = hci_conn_hash_lookup_handle(hdev, handle);
+ } else {
+ chan = hci_chan_lookup_handle_all(hdev, handle);
+ if (chan)
+ conn = chan->conn;
+ }
+
if (!conn)
continue;
--
1.7.9.5
^ permalink raw reply related
* [RFCv1 3/6] Bluetooth: AMP: Add handle to hci_chan structure
From: Andrei Emeltchenko @ 2012-10-08 14:52 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1349707932-10006-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
hci_chan will be identified by handle used in logical link creation
process. This handle is used in AMP ACL-U packet handle field.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/hci_core.h | 6 ++++--
net/bluetooth/hci_conn.c | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 90ae4f0..951f604 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -348,7 +348,7 @@ struct hci_conn {
struct hci_chan {
struct list_head list;
-
+ __u16 handle;
struct hci_conn *conn;
struct sk_buff_head data_q;
unsigned int sent;
@@ -565,7 +565,9 @@ void hci_conn_check_pending(struct hci_dev *hdev);
struct hci_chan *hci_chan_create(struct hci_conn *conn);
void hci_chan_del(struct hci_chan *chan);
void hci_chan_list_flush(struct hci_conn *conn);
-
+struct hci_chan *hci_chan_lookup_handle(struct hci_conn *hcon, __u16 handle);
+struct hci_chan *hci_chan_lookup_handle_all(struct hci_dev *hdev,
+ __u16 handle);
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
__u8 dst_type, __u8 sec_level, __u8 auth_type);
int hci_conn_check_link_mode(struct hci_conn *conn);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 3584f58..7387516 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -992,3 +992,37 @@ void hci_chan_list_flush(struct hci_conn *conn)
list_for_each_entry_safe(chan, n, &conn->chan_list, list)
hci_chan_del(chan);
}
+
+struct hci_chan *hci_chan_lookup_handle(struct hci_conn *hcon, __u16 handle)
+{
+ struct hci_chan *hchan;
+
+ list_for_each_entry(hchan, &hcon->chan_list, list) {
+ if (hchan->handle == handle)
+ return hchan;
+ }
+
+ return NULL;
+}
+
+struct hci_chan *hci_chan_lookup_handle_all(struct hci_dev *hdev, __u16 handle)
+{
+ struct hci_conn_hash *h = &hdev->conn_hash;
+ struct hci_conn *hcon;
+
+ rcu_read_lock();
+
+ list_for_each_entry_rcu(hcon, &h->list, list) {
+ struct hci_chan *hchan;
+
+ hchan = hci_chan_lookup_handle(hcon, handle);
+ if (hchan) {
+ rcu_read_unlock();
+ return hchan;
+ }
+ }
+
+ rcu_read_unlock();
+
+ return NULL;
+}
--
1.7.9.5
^ permalink raw reply related
* [RFCv1 2/6] Bluetooth: AMP: Handle AMP_LINK timeout
From: Andrei Emeltchenko @ 2012-10-08 14:52 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1349707932-10006-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
When AMP_LINK timeouts execute HCI_OP_DISCONN_PHY_LINK as analog to
HCI_OP_DISCONNECT for ACL_LINK.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
net/bluetooth/hci_conn.c | 35 ++++++++++++++++++++++++++++++++---
1 file changed, 32 insertions(+), 3 deletions(-)
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 53202f6..3584f58 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -130,6 +130,20 @@ void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp);
}
+static void hci_amp_disconn(struct hci_conn *conn, __u8 reason)
+{
+ struct hci_cp_disconn_phy_link cp;
+
+ BT_DBG("hcon %p", conn);
+
+ conn->state = BT_DISCONN;
+
+ cp.phy_handle = (u8) conn->handle;
+ cp.reason = reason;
+ hci_send_cmd(conn->hdev, HCI_OP_DISCONN_PHY_LINK,
+ sizeof(cp), &cp);
+}
+
static void hci_add_sco(struct hci_conn *conn, __u16 handle)
{
struct hci_dev *hdev = conn->hdev;
@@ -230,11 +244,27 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status)
}
}
+static void hci_conn_disconnect(struct hci_conn *conn)
+{
+ u8 reason;
+
+ reason = hci_proto_disconn_ind(conn);
+
+ switch (conn->type) {
+ case ACL_LINK:
+ hci_acl_disconn(conn, reason);
+ break;
+
+ case AMP_LINK:
+ hci_amp_disconn(conn, reason);
+ break;
+ }
+}
+
static void hci_conn_timeout(struct work_struct *work)
{
struct hci_conn *conn = container_of(work, struct hci_conn,
disc_work.work);
- __u8 reason;
BT_DBG("hcon %p state %s", conn, state_to_string(conn->state));
@@ -253,8 +283,7 @@ static void hci_conn_timeout(struct work_struct *work)
break;
case BT_CONFIG:
case BT_CONNECTED:
- reason = hci_proto_disconn_ind(conn);
- hci_acl_disconn(conn, reason);
+ hci_conn_disconnect(conn);
break;
default:
conn->state = BT_CLOSED;
--
1.7.9.5
^ permalink raw reply related
* [RFCv1 1/6] Bluetooth: Allow to set flush timeout
From: Andrei Emeltchenko @ 2012-10-08 14:52 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1349707932-10006-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
net/bluetooth/l2cap_sock.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index a71c408..b0014d5 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -529,6 +529,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
chan->fcs = opts.fcs;
chan->max_tx = opts.max_tx;
chan->tx_win = opts.txwin_size;
+ chan->flush_to = opts.flush_to;
break;
case L2CAP_LM:
--
1.7.9.5
^ permalink raw reply related
* [RFCv1 0/6] Handle AMP_LINK
From: Andrei Emeltchenko @ 2012-10-08 14:52 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Add code for handling High Speed link
Andrei Emeltchenko (6):
Bluetooth: Allow to set flush timeout
Bluetooth: AMP: Handle AMP_LINK timeout
Bluetooth: AMP: Add handle to hci_chan structure
Bluetooth: Handle number of compl blocks for AMP_LINK
Bluetooth: AMP: Handle AMP_LINK connection
Bluetooth: AMP: Hanlde AMP_LINK case in conn_put
include/net/bluetooth/hci_core.h | 36 +++++++++++++++++---
net/bluetooth/hci_conn.c | 69 ++++++++++++++++++++++++++++++++++++--
net/bluetooth/hci_core.c | 22 ++++++++++--
net/bluetooth/hci_event.c | 13 +++++--
net/bluetooth/l2cap_sock.c | 1 +
5 files changed, 128 insertions(+), 13 deletions(-)
--
1.7.9.5
^ permalink raw reply
* Re: [WORKAROUND BlueZ 1/3] gdbus: Add fallback to GetProperties
From: Luiz Augusto von Dentz @ 2012-10-08 14:29 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <CABBYNZL9LaALwQzL7Ca3E=K8OewpTNX4ySSc2OZ2CM3jv0O_cA@mail.gmail.com>
Hi,
On Mon, Oct 8, 2012 at 4:25 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> Hi Marcel,
>
> On Mon, Oct 8, 2012 at 3:43 PM, Marcel Holtmann <marcel@holtmann.org> wrote:
>> Hi Luiz,
>>
>>> This adds a fallback for GetProperties method when it is not
>>> implemented.
>>> ---
>>> This set of patches are workarounds to old properties interface to be able to
>>> test new code until other components are ported.
>>
>> I am not sure I want this at all. This is a nasty hack.
>>
>> Especially since interfaces that previously had neither or only some of
>> these methods get these methods. Bad idea. It might work inside BlueZ
>> where we always added these methods, but in other projects some of these
>> methods had been left out since the properties where send via signals
>> with the object path being announced.
>
> Yep, I fully agree this is not meant to be upstream (only perhaps
> behind a compilation flag or something like that), also this does not
> work with clients which do use the introspection data like dbus-python
> because the fallback methods are not part of it the python scripts
> will just fail.
Actually it does work with our test scripts for some reason.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: Wireshark
From: Marcel Holtmann @ 2012-10-08 14:26 UTC (permalink / raw)
To: Michal.Labedzki; +Cc: johan.hedberg, linux-bluetooth
In-Reply-To: <E50901D4F2CF69428D43141B7C8586793514C59580@EXMB03.eu.tieto.com>
Hi Michal,
> > I think you must have misunderstood what I was trying to say. Did you
> > actually look into what the monitor socket we talked about is? I wasn't
> > trying to say wireshark shouldn't be used (so no point in iterating it's
> > benefits - you've already convinced me) but that its Bluetooth decoding
> > support be ported from traditional HCI sockets to use monitor sockets
> > instead. This wouldn't give us any new decoders to wireshark but it
> > would allow early HCI traffic decoding (e.g. on plugged in USB dongles)
>
> Hmm... Do you mean something like:
> https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5032
that is Bluetooth HCI data inside USB traffic captured via usbmon
interfaces. Would work as well, but you need a lot of filtering to get
the right data that you are looking for. Especially problematic if the
device is not on USB or split across multiple USB busses. Which is
possible with Bluetooth 3.0 HighSpeed.
The Bluetooth monitor socket would give all at once. And will also give
you some extra data in case you missed the initial packets when the
adapter was plugged in. Like type (BR/EDR vs AMP) and address.
> I will look at that and I this is on my TODO list. But please note that my first goal is add
> full Bluetooth stack support to Wireshark (profiles and protocols). When this will be done I want to and other stuff like BToverUSB, etc.
You will never be done with all profiles and protocols. I have been
working with Bluetooth for over 11 years, they will always come with
another protocol or profile.
> The purpose of my visit here is fetch some needed logs for testing new dissectors and present this new tool to all Bluetooth developers here.
> And of course I very like new idea.
>
> New monitor sockets is not very important for now, I focus on decoding dump files (I do not have any real devices to live-capture testing).
> It is ok for future. By the way, this sounds like task for libpcap, not really Wireshark (by I am not familiar with internals yet)
Maybe it should be added to libpcap, but nevertheless it needs to be
done. It is the only way to get reliable data from the system these
days. The kernel is taking more and more control. And that becomes hard
to capture from userspace since it will be by definition too late.
> > which isn't possible with current wireshark or hcidump and context
> > discovery when tracing is started after there already exists
> > connections.
>
> > Considering these benefits monitor sockets compared to HCI ones is it
> > something you might be interested in implementing?
>
> Is that stable?
Yes, it is stable.
> Hmmm... Has anyone logs? :)
It is like HCI with an extra header. Look at hci_mon.h.
Regards
Marcel
^ permalink raw reply
* Re: [WORKAROUND BlueZ 1/3] gdbus: Add fallback to GetProperties
From: Luiz Augusto von Dentz @ 2012-10-08 14:25 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <1349703809.27233.65.camel@aeonflux>
Hi Marcel,
On Mon, Oct 8, 2012 at 3:43 PM, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Luiz,
>
>> This adds a fallback for GetProperties method when it is not
>> implemented.
>> ---
>> This set of patches are workarounds to old properties interface to be able to
>> test new code until other components are ported.
>
> I am not sure I want this at all. This is a nasty hack.
>
> Especially since interfaces that previously had neither or only some of
> these methods get these methods. Bad idea. It might work inside BlueZ
> where we always added these methods, but in other projects some of these
> methods had been left out since the properties where send via signals
> with the object path being announced.
Yep, I fully agree this is not meant to be upstream (only perhaps
behind a compilation flag or something like that), also this does not
work with clients which do use the introspection data like dbus-python
because the fallback methods are not part of it the python scripts
will just fail.
The purpose of these patches is for testing the new code with
components such as PulseAudio, oFono, Connman and gnome-shell as we
move forward and finish the changes they should no longer be
necessary.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: Unreliable communication with multiple bluetooth devices and some delay
From: Sietse Achterop @ 2012-10-08 14:23 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <20121008091535.GG2456@aemeltch-MOBL1>
On 08-10-12 11:15, Andrei Emeltchenko wrote:
>
> Get capture with hcidump like "hcidump -tX -i hciX". It will tell you why
> connection is closed. Also dmesg might give some warnings.
Dear Andrei,
thanks for the response.
I did some tests, see the dump fragment below. I shows the output from just before
the error until the 20 second timeout. There is nothing in dmesg or syslog at all.
I cannot completely interpret the output, but have the following questions.
1 When sending the next 3 strings "l,1,2\n" as shown in the beginning of the fragment,
i see that only handle 48 talks about RFCOMM and has a different psm than the other 2.
When running the test without the 0.1 second delay each time in the loop, then the psm
value is always 3.
Is there any significance to this?
2 According to the log, around timestamp 13:36:59.436715 the "ack" for handle 42 is missing.
After that handle 42 is out of order and the rest hangs because of the program loop.
After 20 seconds the timeout occurs.
What does this mean? What are the possible and probable causes.
How likely is it that the hardware (on either side) is so broken?
Where is the failure, on which side of the communication channel, what is more likely.
If the lmx9838 is malfunctioning, shouldn't there be attempts (retries) to try and
recover from this. Could i instrument the driver to see this better?
Thanks for your attention,
Sietse
==========================================================================================
2012-10-08 13:36:59.030346 < ACL data: handle 42 flags 0x02 dlen 14
L2CAP(d): cid 0x0040 len 10 [psm 0]
0000: 0b ef 0d 6c 2c 31 2c 32 0a 9a ...l,1,2..
2012-10-08 13:36:59.030371 < ACL data: handle 45 flags 0x02 dlen 14
L2CAP(d): cid 0x0040 len 10 [psm 0]
0000: 0b ef 0d 6c 2c 31 2c 32 0a 9a ...l,1,2..
2012-10-08 13:36:59.030393 < ACL data: handle 48 flags 0x02 dlen 14
L2CAP(d): cid 0x0040 len 10 [psm 3]
RFCOMM(d): UIH: cr 1 dlci 2 pf 0 ilen 6 fcs 0x9a
0000: 6c 2c 31 2c 32 0a l,1,2.
2012-10-08 13:36:59.034712 > HCI Event: Number of Completed Packets (0x13) plen 5
handle 42 packets 1
2012-10-08 13:36:59.036709 > HCI Event: Number of Completed Packets (0x13) plen 5
handle 48 packets 1
2012-10-08 13:36:59.039712 > HCI Event: Number of Completed Packets (0x13) plen 5
handle 45 packets 1
2012-10-08 13:36:59.130538 < ACL data: handle 42 flags 0x02 dlen 14
L2CAP(d): cid 0x0040 len 10 [psm 0]
0000: 0b ef 0d 6c 2c 31 2c 32 0a 9a ...l,1,2..
2012-10-08 13:36:59.130560 < ACL data: handle 45 flags 0x02 dlen 14
L2CAP(d): cid 0x0040 len 10 [psm 0]
0000: 0b ef 0d 6c 2c 31 2c 32 0a 9a ...l,1,2..
2012-10-08 13:36:59.130584 < ACL data: handle 48 flags 0x02 dlen 14
L2CAP(d): cid 0x0040 len 10 [psm 3]
RFCOMM(d): UIH: cr 1 dlci 2 pf 0 ilen 6 fcs 0x9a
0000: 6c 2c 31 2c 32 0a l,1,2.
2012-10-08 13:36:59.135710 > HCI Event: Number of Completed Packets (0x13) plen 5
handle 42 packets 1
2012-10-08 13:36:59.135719 > ACL data: handle 42 flags 0x02 dlen 9
L2CAP(d): cid 0x0040 len 5 [psm 0]
0000: 09 ff 01 02 5c ....\
2012-10-08 13:36:59.139711 > HCI Event: Number of Completed Packets (0x13) plen 5
handle 48 packets 1
2012-10-08 13:36:59.141711 > HCI Event: Number of Completed Packets (0x13) plen 5
handle 45 packets 1
2012-10-08 13:36:59.142714 > ACL data: handle 48 flags 0x02 dlen 9
L2CAP(d): cid 0x0040 len 5 [psm 3]
RFCOMM(d): UIH: cr 0 dlci 2 pf 1 ilen 0 fcs 0x5c credits 2
2012-10-08 13:36:59.144715 > ACL data: handle 45 flags 0x02 dlen 9
L2CAP(d): cid 0x0040 len 5 [psm 0]
0000: 09 ff 01 02 5c ....\
2012-10-08 13:36:59.230650 < ACL data: handle 42 flags 0x02 dlen 14
L2CAP(d): cid 0x0040 len 10 [psm 0]
0000: 0b ef 0d 6c 2c 31 2c 32 0a 9a ...l,1,2..
2012-10-08 13:36:59.230671 < ACL data: handle 45 flags 0x02 dlen 14
L2CAP(d): cid 0x0040 len 10 [psm 0]
0000: 0b ef 0d 6c 2c 31 2c 32 0a 9a ...l,1,2..
2012-10-08 13:36:59.230694 < ACL data: handle 48 flags 0x02 dlen 14
L2CAP(d): cid 0x0040 len 10 [psm 3]
RFCOMM(d): UIH: cr 1 dlci 2 pf 0 ilen 6 fcs 0x9a
0000: 6c 2c 31 2c 32 0a l,1,2.
2012-10-08 13:36:59.235713 > HCI Event: Number of Completed Packets (0x13) plen 5
handle 42 packets 1
2012-10-08 13:36:59.239711 > HCI Event: Number of Completed Packets (0x13) plen 5
handle 48 packets 1
2012-10-08 13:36:59.241711 > HCI Event: Number of Completed Packets (0x13) plen 5
handle 45 packets 1
2012-10-08 13:36:59.330765 < ACL data: handle 42 flags 0x02 dlen 14
L2CAP(d): cid 0x0040 len 10 [psm 0]
0000: 0b ef 0d 6c 2c 31 2c 32 0a 9a ...l,1,2..
2012-10-08 13:36:59.330785 < ACL data: handle 45 flags 0x02 dlen 14
L2CAP(d): cid 0x0040 len 10 [psm 0]
0000: 0b ef 0d 6c 2c 31 2c 32 0a 9a ...l,1,2..
2012-10-08 13:36:59.330809 < ACL data: handle 48 flags 0x02 dlen 14
L2CAP(d): cid 0x0040 len 10 [psm 3]
RFCOMM(d): UIH: cr 1 dlci 2 pf 0 ilen 6 fcs 0x9a
0000: 6c 2c 31 2c 32 0a l,1,2.
2012-10-08 13:36:59.335713 > HCI Event: Number of Completed Packets (0x13) plen 5
handle 42 packets 1
2012-10-08 13:36:59.339712 > HCI Event: Number of Completed Packets (0x13) plen 5
handle 48 packets 1
2012-10-08 13:36:59.340715 > ACL data: handle 48 flags 0x02 dlen 9
L2CAP(d): cid 0x0040 len 5 [psm 3]
RFCOMM(d): UIH: cr 0 dlci 2 pf 1 ilen 0 fcs 0x5c credits 2
2012-10-08 13:36:59.341713 > HCI Event: Number of Completed Packets (0x13) plen 5
handle 45 packets 1
2012-10-08 13:36:59.342715 > ACL data: handle 45 flags 0x02 dlen 9
L2CAP(d): cid 0x0040 len 5 [psm 0]
0000: 09 ff 01 02 5c ....\
2012-10-08 13:36:59.430914 < ACL data: handle 42 flags 0x02 dlen 14
L2CAP(d): cid 0x0040 len 10 [psm 0]
0000: 0b ef 0d 6c 2c 31 2c 32 0a 9a ...l,1,2..
2012-10-08 13:36:59.430926 < ACL data: handle 45 flags 0x02 dlen 14
L2CAP(d): cid 0x0040 len 10 [psm 0]
0000: 0b ef 0d 6c 2c 31 2c 32 0a 9a ...l,1,2..
2012-10-08 13:36:59.430946 < ACL data: handle 48 flags 0x02 dlen 14
L2CAP(d): cid 0x0040 len 10 [psm 3]
RFCOMM(d): UIH: cr 1 dlci 2 pf 0 ilen 6 fcs 0x9a
0000: 6c 2c 31 2c 32 0a l,1,2.
2012-10-08 13:36:59.436715 > HCI Event: Number of Completed Packets (0x13) plen 5
handle 48 packets 1
2012-10-08 13:36:59.439713 > HCI Event: Number of Completed Packets (0x13) plen 5
handle 45 packets 1
2012-10-08 13:36:59.531023 < ACL data: handle 45 flags 0x02 dlen 14
L2CAP(d): cid 0x0040 len 10 [psm 0]
0000: 0b ef 0d 6c 2c 31 2c 32 0a 9a ...l,1,2..
2012-10-08 13:36:59.531043 < ACL data: handle 48 flags 0x02 dlen 14
L2CAP(d): cid 0x0040 len 10 [psm 3]
RFCOMM(d): UIH: cr 1 dlci 2 pf 0 ilen 6 fcs 0x9a
0000: 6c 2c 31 2c 32 0a l,1,2.
2012-10-08 13:36:59.538714 > HCI Event: Number of Completed Packets (0x13) plen 5
handle 48 packets 1
2012-10-08 13:36:59.540714 > HCI Event: Number of Completed Packets (0x13) plen 5
handle 45 packets 1
2012-10-08 13:36:59.540721 > ACL data: handle 48 flags 0x02 dlen 9
L2CAP(d): cid 0x0040 len 5 [psm 3]
RFCOMM(d): UIH: cr 0 dlci 2 pf 1 ilen 0 fcs 0x5c credits 2
2012-10-08 13:36:59.543715 > ACL data: handle 45 flags 0x02 dlen 9
L2CAP(d): cid 0x0040 len 5 [psm 0]
0000: 09 ff 01 02 5c ....\
2012-10-08 13:36:59.631126 < ACL data: handle 45 flags 0x02 dlen 14
L2CAP(d): cid 0x0040 len 10 [psm 0]
0000: 0b ef 0d 6c 2c 31 2c 32 0a 9a ...l,1,2..
2012-10-08 13:36:59.631132 < ACL data: handle 48 flags 0x02 dlen 14
L2CAP(d): cid 0x0040 len 10 [psm 3]
RFCOMM(d): UIH: cr 1 dlci 2 pf 0 ilen 6 fcs 0x9a
0000: 6c 2c 31 2c 32 0a l,1,2.
2012-10-08 13:36:59.636714 > HCI Event: Number of Completed Packets (0x13) plen 5
handle 45 packets 1
2012-10-08 13:36:59.638712 > HCI Event: Number of Completed Packets (0x13) plen 5
handle 48 packets 1
2012-10-08 13:37:19.361788 > HCI Event: Disconn Complete (0x05) plen 4
status 0x00 handle 42 reason 0x08
Reason: Connection Timeout
^ permalink raw reply
* RE: Wireshark
From: Michal.Labedzki @ 2012-10-08 14:19 UTC (permalink / raw)
To: johan.hedberg; +Cc: linux-bluetooth
In-Reply-To: <20121003080438.GA11960@x220>
Hi Johan,
> I think you must have misunderstood what I was trying to say. Did you
> actually look into what the monitor socket we talked about is? I wasn't
> trying to say wireshark shouldn't be used (so no point in iterating it's
> benefits - you've already convinced me) but that its Bluetooth decoding
> support be ported from traditional HCI sockets to use monitor sockets
> instead. This wouldn't give us any new decoders to wireshark but it
> would allow early HCI traffic decoding (e.g. on plugged in USB dongles)
Hmm... Do you mean something like:
https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5032
I will look at that and I this is on my TODO list. But please note that my first goal is add
full Bluetooth stack support to Wireshark (profiles and protocols). When this will be done I want to and other stuff like BToverUSB, etc.
The purpose of my visit here is fetch some needed logs for testing new dissectors and present this new tool to all Bluetooth developers here.
And of course I very like new idea.
New monitor sockets is not very important for now, I focus on decoding dump files (I do not have any real devices to live-capture testing).
It is ok for future. By the way, this sounds like task for libpcap, not really Wireshark (by I am not familiar with internals yet)
> which isn't possible with current wireshark or hcidump and context
> discovery when tracing is started after there already exists
> connections.
> Considering these benefits monitor sockets compared to HCI ones is it
> something you might be interested in implementing?
Is that stable?
Hmmm... Has anyone logs? :)
Regards / Pozdrawiam
-------------------------------------------------------------------------------------------------------------
Michał Łabędzki
ASCII: Michal Labedzki
e-mail: michal.labedzki@tieto.com
location: Poland, Wrocław, Legnicka 55F
---
Tieto Corporation / Tieto Poland
http://www.tieto.com / http://www.tieto.pl
---
Tieto Poland spółka z ograniczoną odpowiedzialnością z siedzibą w Szczecinie, ul. Malczewskiego 26. Zarejestrowana w Sądzie Rejonowym Szczecin-Centrum w Szczecinie, XIII Wydział Gospodarczy Krajowego Rejestru Sądowego pod numerem 0000124858. NIP: 8542085557. REGON: 812023656. Kapitał zakładowy: 4 271500 PLN
^ permalink raw reply
* Re: [WORKAROUND BlueZ 1/3] gdbus: Add fallback to GetProperties
From: Marcel Holtmann @ 2012-10-08 13:43 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1349683884-22251-1-git-send-email-luiz.dentz@gmail.com>
Hi Luiz,
> This adds a fallback for GetProperties method when it is not
> implemented.
> ---
> This set of patches are workarounds to old properties interface to be able to
> test new code until other components are ported.
I am not sure I want this at all. This is a nasty hack.
Especially since interfaces that previously had neither or only some of
these methods get these methods. Bad idea. It might work inside BlueZ
where we always added these methods, but in other projects some of these
methods had been left out since the properties where send via signals
with the object path being announced.
Regards
Marcel
^ 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