* [PATCH 5/7 v3] Add support for notyfying pbap about more parts from backend
From: Radoslaw Jablonski @ 2011-02-14 9:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Radoslaw Jablonski
In-Reply-To: <1297675191-8046-1-git-send-email-ext-jablonski.radoslaw@nokia.com>
Added new parameter to phonebook_cb - lastpart variable.
If backend want to notify that more parts of current
request will be delivered later, it should use lastpart=FALSE.
Because of that, PBAP core will 'know' that should not finalize
request immediately after receiving data and wait for more
parts to come.
If result is returned in one part and no more responses part
will be sent later, then backend should use lastparam=TRUE.
Previously results of request from backend was always returned
in one part to PBAP core.
---
plugins/irmc.c | 5 +++--
plugins/pbap.c | 10 +++++++---
plugins/phonebook-dummy.c | 4 ++--
plugins/phonebook-ebook.c | 7 ++++---
plugins/phonebook-tracker.c | 13 +++++++------
plugins/phonebook.h | 2 +-
6 files changed, 24 insertions(+), 17 deletions(-)
diff --git a/plugins/irmc.c b/plugins/irmc.c
index 0488cae..e1e83f9 100644
--- a/plugins/irmc.c
+++ b/plugins/irmc.c
@@ -133,7 +133,8 @@ static const char *owner_vcard =
"END:VCARD\r\n";
static void phonebook_size_result(const char *buffer, size_t bufsize,
- int vcards, int missed, void *user_data)
+ int vcards, int missed,
+ gboolean lastpart, void *user_data)
{
struct irmc_session *irmc = user_data;
@@ -148,7 +149,7 @@ static void phonebook_size_result(const char *buffer, size_t bufsize,
}
static void query_result(const char *buffer, size_t bufsize, int vcards,
- int missed, void *user_data)
+ int missed, gboolean lastpart, void *user_data)
{
struct irmc_session *irmc = user_data;
const char *s, *t;
diff --git a/plugins/pbap.c b/plugins/pbap.c
index 6579d09..5775eea 100644
--- a/plugins/pbap.c
+++ b/plugins/pbap.c
@@ -148,6 +148,7 @@ struct pbap_object {
GString *buffer;
GByteArray *aparams;
gboolean firstpacket;
+ gboolean lastpart;
struct pbap_session *session;
void *request;
};
@@ -254,7 +255,8 @@ static GByteArray *append_aparam_header(GByteArray *buf, uint8_t tag,
}
static void phonebook_size_result(const char *buffer, size_t bufsize,
- int vcards, int missed, void *user_data)
+ int vcards, int missed,
+ gboolean lastpart, void *user_data)
{
struct pbap_session *pbap = user_data;
uint16_t phonebooksize;
@@ -286,17 +288,19 @@ static void phonebook_size_result(const char *buffer, size_t bufsize,
}
static void query_result(const char *buffer, size_t bufsize, int vcards,
- int missed, void *user_data)
+ int missed, gboolean lastpart, void *user_data)
{
struct pbap_session *pbap = user_data;
DBG("");
- if (pbap->obj->request) {
+ if (pbap->obj->request && lastpart) {
phonebook_req_finalize(pbap->obj->request);
pbap->obj->request = NULL;
}
+ pbap->obj->lastpart = lastpart;
+
if (vcards <= 0) {
obex_object_set_io_flags(pbap->obj, G_IO_ERR, -ENOENT);
return;
diff --git a/plugins/phonebook-dummy.c b/plugins/phonebook-dummy.c
index 60b7640..76dd550 100644
--- a/plugins/phonebook-dummy.c
+++ b/plugins/phonebook-dummy.c
@@ -248,7 +248,7 @@ static gboolean read_dir(void *user_data)
closedir(dp);
done:
/* FIXME: Missing vCards fields filtering */
- dummy->cb(buffer->str, buffer->len, count, 0, dummy->user_data);
+ dummy->cb(buffer->str, buffer->len, count, 0, TRUE, dummy->user_data);
g_string_free(buffer, TRUE);
@@ -346,7 +346,7 @@ static gboolean read_entry(void *user_data)
/* FIXME: Missing vCards fields filtering */
- dummy->cb(buffer, count, 1, 0, dummy->user_data);
+ dummy->cb(buffer, count, 1, 0, TRUE, dummy->user_data);
return FALSE;
}
diff --git a/plugins/phonebook-ebook.c b/plugins/phonebook-ebook.c
index 70b9c02..6cc4f31 100644
--- a/plugins/phonebook-ebook.c
+++ b/plugins/phonebook-ebook.c
@@ -186,7 +186,8 @@ static void ebookpull_cb(EBook *book, EBookStatus estatus, GList *contacts,
done:
data->completed = TRUE;
- data->contacts_cb(string->str, string->len, count, 0, data->user_data);
+ data->contacts_cb(string->str, string->len, count, 0, TRUE,
+ data->user_data);
fail:
g_string_free(string, TRUE);
@@ -212,7 +213,7 @@ static void ebook_entry_cb(EBook *book, EBookStatus estatus,
if (estatus != E_BOOK_ERROR_OK) {
error("E-Book query failed: status %d", estatus);
- data->contacts_cb(NULL, 0, 1, 0, data->user_data);
+ data->contacts_cb(NULL, 0, 1, 0, TRUE, data->user_data);
goto fail;
}
@@ -223,7 +224,7 @@ static void ebook_entry_cb(EBook *book, EBookStatus estatus,
len = vcard ? strlen(vcard) : 0;
- data->contacts_cb(vcard, len, 1, 0, data->user_data);
+ data->contacts_cb(vcard, len, 1, 0, TRUE, data->user_data);
g_free(vcard);
diff --git a/plugins/phonebook-tracker.c b/plugins/phonebook-tracker.c
index 210799d..aea2365 100644
--- a/plugins/phonebook-tracker.c
+++ b/plugins/phonebook-tracker.c
@@ -1334,7 +1334,7 @@ static int pull_contacts_size(const char **reply, int num_fields,
struct phonebook_data *data = user_data;
if (num_fields < 0) {
- data->cb(NULL, 0, num_fields, 0, data->user_data);
+ data->cb(NULL, 0, num_fields, 0, TRUE, data->user_data);
return -EINTR;
}
@@ -1343,7 +1343,8 @@ static int pull_contacts_size(const char **reply, int num_fields,
return 0;
}
- data->cb(NULL, 0, data->index, data->newmissedcalls, data->user_data);
+ data->cb(NULL, 0, data->index, data->newmissedcalls, TRUE,
+ data->user_data);
return 0;
/*
@@ -1561,7 +1562,7 @@ static int pull_contacts(const char **reply, int num_fields, void *user_data)
static char *temp_id = NULL;
if (num_fields < 0) {
- data->cb(NULL, 0, num_fields, 0, data->user_data);
+ data->cb(NULL, 0, num_fields, 0, TRUE, data->user_data);
goto fail;
}
@@ -1641,7 +1642,7 @@ done:
vcards = gen_vcards(data->contacts, params);
data->cb(vcards->str, vcards->len, g_slist_length(data->contacts),
- data->newmissedcalls, data->user_data);
+ data->newmissedcalls, TRUE, data->user_data);
g_string_free(vcards, TRUE);
fail:
@@ -1868,7 +1869,7 @@ done:
data->contacts = NULL;
if (num_fields < 0) {
- data->cb(NULL, 0, num_fields, 0, data->user_data);
+ data->cb(NULL, 0, num_fields, 0, TRUE, data->user_data);
return -EINTR;
}
@@ -1884,7 +1885,7 @@ done:
err = query_tracker(query, col_amount, pull_cb, data);
if (err < 0) {
- data->cb(NULL, 0, err, 0, data->user_data);
+ data->cb(NULL, 0, err, 0, TRUE, data->user_data);
return -EINTR;
}
diff --git a/plugins/phonebook.h b/plugins/phonebook.h
index bfbae0f..f6df164 100644
--- a/plugins/phonebook.h
+++ b/plugins/phonebook.h
@@ -50,7 +50,7 @@ struct apparam_field {
* Contacts will be returned in the vcard format.
*/
typedef void (*phonebook_cb) (const char *buffer, size_t bufsize,
- int vcards, int missed, void *user_data);
+ int vcards, int missed, gboolean lastpart, void *user_data);
/*
* Interface between the PBAP core and backends to
--
1.7.0.4
^ permalink raw reply related
* [PATCH 6/7 v3] Introduction of phonebook_pull_read
From: Radoslaw Jablonski @ 2011-02-14 9:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Radoslaw Jablonski
In-Reply-To: <1297675191-8046-1-git-send-email-ext-jablonski.radoslaw@nokia.com>
Previosly reading from backend was initialized in phonebook_pull.
Now phonebook_pull should be used only for preparing request data
and phonebook_pull_read for 'real' reading vcards data from back-end.
The back-end can return data in one response or it can return data in
many parts. After obtaining one part, PBAP core need to call
phonebook_pull_read with the same request again to get more results.
Using that, PBAP core has control of its the buffer size - it can
ask for new parts of data when buffer is empty or when its size
will be lower than some level.
---
plugins/irmc.c | 11 +++++++++
plugins/pbap.c | 22 +++++++++++++++++-
plugins/phonebook-dummy.c | 27 ++++++++++++++++------
plugins/phonebook-ebook.c | 23 +++++++++++++------
plugins/phonebook-tracker.c | 51 +++++++++++++++++++++++++++----------------
plugins/phonebook.h | 20 +++++++++++++---
6 files changed, 116 insertions(+), 38 deletions(-)
diff --git a/plugins/irmc.c b/plugins/irmc.c
index e1e83f9..2cf673c 100644
--- a/plugins/irmc.c
+++ b/plugins/irmc.c
@@ -197,6 +197,7 @@ static void *irmc_connect(struct obex_session *os, int *err)
{
struct irmc_session *irmc;
struct apparam_field *param;
+ int ret;
DBG("");
@@ -224,6 +225,9 @@ static void *irmc_connect(struct obex_session *os, int *err)
irmc->params = param;
irmc->request = phonebook_pull("telecom/pb.vcf", irmc->params,
phonebook_size_result, irmc, err);
+ ret = phonebook_pull_read(irmc->request);
+ if (err)
+ *err = ret;
return irmc;
}
@@ -313,6 +317,13 @@ static void *irmc_open_pb(const char *name, struct irmc_session *irmc,
DBG("phonebook_pull failed...");
goto fail;
}
+
+ ret = phonebook_pull_read(irmc->request);
+ if (ret < 0) {
+ DBG("phonebook_pull_read failed...");
+ goto fail;
+ }
+
return irmc;
}
diff --git a/plugins/pbap.c b/plugins/pbap.c
index 5775eea..b04dca9 100644
--- a/plugins/pbap.c
+++ b/plugins/pbap.c
@@ -806,6 +806,11 @@ static void *vobject_pull_open(const char *name, int oflag, mode_t mode,
if (ret < 0)
goto fail;
+ /* reading first part of results from backend */
+ ret = phonebook_pull_read(request);
+ if (ret < 0)
+ goto fail;
+
if (err)
*err = 0;
@@ -962,6 +967,7 @@ static ssize_t vobject_pull_read(void *object, void *buf, size_t count,
{
struct pbap_object *obj = object;
struct pbap_session *pbap = obj->session;
+ int len, ret;
DBG("buffer %p maxlistcount %d", obj->buffer,
pbap->params->maxlistcount);
@@ -987,7 +993,21 @@ static ssize_t vobject_pull_read(void *object, void *buf, size_t count,
*hi = OBEX_HDR_BODY;
if (flags)
*flags = 0;
- return string_read(obj->buffer, buf, count);
+
+ len = string_read(obj->buffer, buf, count);
+ if (len == 0 && !obj->lastpart) {
+ /* in case when buffer is empty and we know that more
+ * data is still available in backend, requesting new
+ * data part via phonebook_pull_read and returning
+ * -EAGAIN to suspend request for now */
+ ret = phonebook_pull_read(obj->request);
+ if (ret)
+ return -EPERM;
+
+ return -EAGAIN;
+ }
+
+ return len;
}
}
diff --git a/plugins/phonebook-dummy.c b/plugins/phonebook-dummy.c
index 76dd550..ede4643 100644
--- a/plugins/phonebook-dummy.c
+++ b/plugins/phonebook-dummy.c
@@ -52,6 +52,7 @@ struct dummy_data {
const struct apparam_field *apparams;
char *folder;
int fd;
+ guint id;
};
struct cache_query {
@@ -449,9 +450,12 @@ done:
void phonebook_req_finalize(void *request)
{
- guint id = GPOINTER_TO_INT(request);
+ struct dummy_data *dummy = request;
- g_source_remove(id);
+ /* dummy_data will be cleaned when request will be finished via
+ * g_source_remove */
+ if (dummy && dummy->id)
+ g_source_remove(dummy->id);
}
void *phonebook_pull(const char *name, const struct apparam_field *params,
@@ -459,7 +463,6 @@ void *phonebook_pull(const char *name, const struct apparam_field *params,
{
struct dummy_data *dummy;
char *filename, *folder;
- guint ret;
/*
* Main phonebook objects will be created dinamically based on the
@@ -492,13 +495,23 @@ void *phonebook_pull(const char *name, const struct apparam_field *params,
dummy->folder = folder;
dummy->fd = -1;
- ret = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, read_dir, dummy,
- dummy_free);
-
if (err)
*err = 0;
- return GINT_TO_POINTER(ret);
+ return dummy;
+}
+
+int phonebook_pull_read(void *request)
+{
+ struct dummy_data *dummy = request;
+
+ if (!dummy)
+ return -ENOENT;
+
+ dummy->id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, read_dir, dummy,
+ dummy_free);
+
+ return 0;
}
void *phonebook_get_entry(const char *folder, const char *id,
diff --git a/plugins/phonebook-ebook.c b/plugins/phonebook-ebook.c
index 6cc4f31..82019da 100644
--- a/plugins/phonebook-ebook.c
+++ b/plugins/phonebook-ebook.c
@@ -453,25 +453,34 @@ void *phonebook_pull(const char *name, const struct apparam_field *params,
phonebook_cb cb, void *user_data, int *err)
{
struct query_context *data;
- EBookQuery *query;
-
- query = e_book_query_any_field_contains("");
data = g_new0(struct query_context, 1);
data->contacts_cb = cb;
data->params = params;
data->user_data = user_data;
- e_book_async_get_contacts(ebook, query, ebookpull_cb, data);
-
- e_book_query_unref(query);
-
if (err)
*err = 0;
return data;
}
+int phonebook_pull_read(void *request)
+{
+ struct query_context *data = request;
+ EBookQuery *query;
+
+ if (!data)
+ return -ENOENT;
+
+ query = e_book_query_any_field_contains("");
+ e_book_async_get_contacts(ebook, query, ebookpull_cb, data);
+
+ e_book_query_unref(query);
+
+ return 0;
+}
+
void *phonebook_get_entry(const char *folder, const char *id,
const struct apparam_field *params,
phonebook_cb cb, void *user_data, int *err)
diff --git a/plugins/phonebook-tracker.c b/plugins/phonebook-tracker.c
index aea2365..e7f0807 100644
--- a/plugins/phonebook-tracker.c
+++ b/plugins/phonebook-tracker.c
@@ -918,6 +918,7 @@ struct phonebook_data {
phonebook_entry_cb entry_cb;
int newmissedcalls;
GCancellable *query_canc;
+ char *req_name;
};
struct phonebook_index {
@@ -1819,6 +1820,7 @@ void phonebook_req_finalize(void *request)
}
g_slist_free(data->contacts);
+ g_free(data->req_name);
g_free(data);
}
@@ -1897,41 +1899,52 @@ void *phonebook_pull(const char *name, const struct apparam_field *params,
phonebook_cb cb, void *user_data, int *err)
{
struct phonebook_data *data;
- const char *query;
- reply_list_foreach_t pull_cb;
- int col_amount, ret;
DBG("name %s", name);
- if (g_strcmp0(name, "telecom/mch.vcf") == 0) {
+ data = g_new0(struct phonebook_data, 1);
+ data->params = params;
+ data->user_data = user_data;
+ data->cb = cb;
+ data->req_name = g_strdup(name);
+
+ if (err)
+ *err = 0;
+
+ return data;
+}
+
+int phonebook_pull_read(void *request)
+{
+ struct phonebook_data *data = request;
+ reply_list_foreach_t pull_cb;
+ const char *query;
+ int col_amount;
+ int ret;
+
+ if(!data)
+ return -ENOENT;
+
+ if (g_strcmp0(data->req_name, "telecom/mch.vcf") == 0) {
query = NEW_MISSED_CALLS_LIST;
col_amount = PULL_QUERY_COL_AMOUNT;
pull_cb = pull_newmissedcalls;
- } else if (params->maxlistcount == 0) {
- query = name2count_query(name);
+ } else if (data->params->maxlistcount == 0) {
+ query = name2count_query(data->req_name);
col_amount = COUNT_QUERY_COL_AMOUNT;
pull_cb = pull_contacts_size;
} else {
- query = name2query(name);
+ query = name2query(data->req_name);
col_amount = PULL_QUERY_COL_AMOUNT;
pull_cb = pull_contacts;
}
- if (query == NULL) {
- if (err)
- *err = -ENOENT;
- return NULL;
- }
+ if (query == NULL)
+ return -ENOENT;
- data = g_new0(struct phonebook_data, 1);
- data->params = params;
- data->user_data = user_data;
- data->cb = cb;
ret = query_tracker(query, col_amount, pull_cb, data);
- if (err)
- *err = ret;
- return data;
+ return ret;
}
void *phonebook_get_entry(const char *folder, const char *id,
diff --git a/plugins/phonebook.h b/plugins/phonebook.h
index f6df164..00abc08 100644
--- a/plugins/phonebook.h
+++ b/plugins/phonebook.h
@@ -82,17 +82,29 @@ char *phonebook_set_folder(const char *current_folder,
const char *new_folder, uint8_t flags, int *err);
/*
- * PullPhoneBook never use cached entries. PCE use this function to get all
- * entries of a given folder. The back-end MUST return only the content based
- * on the application parameters requested by the client.
+ * phonebook_pull should be used only to prepare pull request - prepared
+ * request data is returned by this function. Start of fetching data from
+ * back-end will be done only after calling phonebook_pull_read with this
+ * returned request given as a parameter.
*
- * Return value is a pointer to asynchronous request to phonebook back-end.
* phonebook_req_finalize MUST always be used to free associated resources.
*/
void *phonebook_pull(const char *name, const struct apparam_field *params,
phonebook_cb cb, void *user_data, int *err);
/*
+ * phonebook_pull_read should be used to start getting results from back-end.
+ * The back-end can return data as one response or can return it many parts.
+ * After obtaining one part, PBAP core need to call phonebook_pull_read with
+ * the same request again to get more results from back-end.
+ * The back-end MUST return only the content based on the application
+ * parameters requested by the client.
+ *
+ * Returns error code or 0 in case of success
+ */
+int phonebook_pull_read(void *request);
+
+/*
* Function used to retrieve a contact from the backend. Only contacts
* found in the cache are requested to the back-ends. The back-end MUST
* return only the content based on the application parameters requested
--
1.7.0.4
^ permalink raw reply related
* [PATCH 7/7 v3] Support for multipart response sending from phonebook-tracker
From: Radoslaw Jablonski @ 2011-02-14 9:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Radoslaw Jablonski
In-Reply-To: <1297675191-8046-1-git-send-email-ext-jablonski.radoslaw@nokia.com>
Now data are being sent with smaller parts - vcard amount for
one part is defined in VCARDS_PART_COUNT. When one part of
data is sent, then data download from tracker is stopped.
It will be resumed when phonebook_pull_read will be called again.
This is needed to start sending data from PBAP quicker - now
transfer can be started when first part of data is processed.
Previously transfer was started when all results for response
were downloaded, and (for large responses) some PBAP clients
were disconnecting due to timeout.
---
plugins/phonebook-tracker.c | 81 +++++++++++++++++++++++++++++++++---------
1 files changed, 63 insertions(+), 18 deletions(-)
diff --git a/plugins/phonebook-tracker.c b/plugins/phonebook-tracker.c
index e7f0807..eb38a46 100644
--- a/plugins/phonebook-tracker.c
+++ b/plugins/phonebook-tracker.c
@@ -81,6 +81,8 @@
#define MAIN_DELIM "\30" /* Main delimiter between phones, addresses, emails*/
#define SUB_DELIM "\31" /* Delimiter used in telephone number strings*/
#define MAX_FIELDS 100 /* Max amount of fields to be concatenated at once*/
+#define VCARDS_PART_COUNT 50 /* amount of vcards sent at once to PBAP core */
+#define QUERY_OFFSET_FORMAT "%s OFFSET %d"
#define CONTACTS_QUERY_ALL \
"SELECT " \
@@ -919,6 +921,8 @@ struct phonebook_data {
int newmissedcalls;
GCancellable *query_canc;
char *req_name;
+ int vcard_part_count;
+ int tracker_index;
};
struct phonebook_index {
@@ -1551,15 +1555,45 @@ static void contact_add_organization(struct phonebook_contact *contact,
add_affiliation(&contact->role, reply[COL_ORG_ROLE]);
}
+static void free_data_contacts(struct phonebook_data *data)
+{
+ GSList *l;
+
+ /* freeing contacts */
+ for (l = data->contacts; l; l = l->next) {
+ struct contact_data *c_data = l->data;
+
+ g_free(c_data->id);
+ phonebook_contact_free(c_data->contact);
+ g_free(c_data);
+ }
+
+ g_slist_free(data->contacts);
+ data->contacts = NULL;
+}
+
+static void send_pull_part(struct phonebook_data *data,
+ const struct apparam_field *params, gboolean lastpart)
+{
+ GString *vcards;
+
+ DBG("");
+ vcards = gen_vcards(data->contacts, params);
+ data->cb(vcards->str, vcards->len, g_slist_length(data->contacts),
+ data->newmissedcalls, lastpart, data->user_data);
+
+ free_data_contacts(data);
+ g_string_free(vcards, TRUE);
+}
+
static int pull_contacts(const char **reply, int num_fields, void *user_data)
{
struct phonebook_data *data = user_data;
const struct apparam_field *params = data->params;
struct phonebook_contact *contact;
struct contact_data *contact_data;
- GString *vcards;
int last_index, i;
- gboolean cdata_present = FALSE;
+ gboolean cdata_present = FALSE, part_sent = FALSE;
static char *temp_id = NULL;
if (num_fields < 0) {
@@ -1568,6 +1602,7 @@ static int pull_contacts(const char **reply, int num_fields, void *user_data)
}
DBG("reply %p", reply);
+ data->tracker_index++;
if (reply == NULL)
goto done;
@@ -1600,6 +1635,25 @@ static int pull_contacts(const char **reply, int num_fields, void *user_data)
data->index++;
g_free(temp_id);
temp_id = g_strdup(reply[CONTACTS_ID_COL]);
+
+ /* Incrementing counter for vcards in current part of data,
+ * but only if liststartoffset has been already reached */
+ if (data->index > params->liststartoffset)
+ data->vcard_part_count++;
+ }
+
+ if (data->vcard_part_count > VCARDS_PART_COUNT) {
+ DBG("Part of vcard data ready for sending...");
+ data->vcard_part_count = 0;
+ /* Sending part of data to PBAP core - more data can be still
+ * fetched, so marking lastpart as FALSE */
+ send_pull_part(data, params, FALSE);
+
+ /* Later, after adding contact data, need to return -EINTR to
+ * stop fetching more data for this request. Data will be
+ * downloaded again from this point, when phonebook_pull_read
+ * will be called again with current request as a parameter*/
+ part_sent = TRUE;
}
last_index = params->liststartoffset + params->maxlistcount;
@@ -1637,15 +1691,16 @@ add_numbers:
data->contacts = g_slist_append(data->contacts, contact_data);
}
+ if (part_sent)
+ return -EINTR;
+
return 0;
done:
- vcards = gen_vcards(data->contacts, params);
+ /* Processing is end, this is definitely last part of transmission
+ * (marking lastpart as TRUE) */
+ send_pull_part(data, params, TRUE);
- data->cb(vcards->str, vcards->len, g_slist_length(data->contacts),
- data->newmissedcalls, TRUE, data->user_data);
-
- g_string_free(vcards, TRUE);
fail:
g_free(temp_id);
temp_id = NULL;
@@ -1797,7 +1852,6 @@ done:
void phonebook_req_finalize(void *request)
{
struct phonebook_data *data = request;
- GSList *l;
DBG("");
@@ -1810,16 +1864,7 @@ void phonebook_req_finalize(void *request)
g_object_unref(data->query_canc);
}
- /* freeing contacts */
- for (l = data->contacts; l; l = l->next) {
- struct contact_data *c_data = l->data;
-
- g_free(c_data->id);
- phonebook_contact_free(c_data->contact);
- g_free(c_data);
- }
-
- g_slist_free(data->contacts);
+ free_data_contacts(data);
g_free(data->req_name);
g_free(data);
}
--
1.7.0.4
^ permalink raw reply related
* [PATCH 1/3] Fix not stopping name resolving when discovery is suspended
From: Luiz Augusto von Dentz @ 2011-02-14 10:21 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
During device creation if discovery is active we suspend it to avoid
interfering with pairing, but although it attempt to cancel name request
there could be one already completed which would cause next name on the
list to be requested.
---
src/adapter.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 3e609c1..fd4b685 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -268,6 +268,10 @@ int adapter_resolve_names(struct btd_adapter *adapter)
struct remote_dev_info *dev, match;
int err;
+ /* Do not attempt to resolve more names if on suspended state */
+ if (adapter->state & STATE_SUSPENDED)
+ return 0;
+
memset(&match, 0, sizeof(struct remote_dev_info));
bacpy(&match.bdaddr, BDADDR_ANY);
match.name_status = NAME_REQUIRED;
--
1.7.1
^ permalink raw reply related
* [PATCH 2/3] Fix not resetting indicators whenever the driver is initialized
From: Luiz Augusto von Dentz @ 2011-02-14 10:21 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1297678882-26893-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
This may cause invalid values to be reported since the status of call can
change during the time adaptor was off.
---
audio/telephony-maemo6.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/audio/telephony-maemo6.c b/audio/telephony-maemo6.c
index 0c99c34..0ab1a77 100644
--- a/audio/telephony-maemo6.c
+++ b/audio/telephony-maemo6.c
@@ -1981,6 +1981,15 @@ int telephony_init(void)
DBG("telephony-maemo6 registering %s interface on path %s",
TELEPHONY_MAEMO_INTERFACE, TELEPHONY_MAEMO_PATH);
+ /* Reset indicators */
+ telephony_update_indicator(maemo_indicators, "battchg", 5);
+ telephony_update_indicator(maemo_indicators, "signal", 0);
+ telephony_update_indicator(maemo_indicators, "service", 0);
+ telephony_update_indicator(maemo_indicators, "call", 0);
+ telephony_update_indicator(maemo_indicators, "callsetup", 0);
+ telephony_update_indicator(maemo_indicators, "callhelp", 0);
+ telephony_update_indicator(maemo_indicators, "roam", 0);
+
telephony_ready_ind(features, maemo_indicators, BTRH_NOT_SUPPORTED,
chld_str);
if (send_method_call("org.freedesktop.Hal",
--
1.7.1
^ permalink raw reply related
* [PATCH 3/3] Fix not updating call indicator when parsing call info reply
From: Luiz Augusto von Dentz @ 2011-02-14 10:21 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1297678882-26893-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
This can happen if there is a call with a status different than idle when
adaptor is turned on the call indicators weren't updated.
---
audio/telephony-maemo6.c | 63 ++++++++++++++++++++++++++-------------------
1 files changed, 36 insertions(+), 27 deletions(-)
diff --git a/audio/telephony-maemo6.c b/audio/telephony-maemo6.c
index 0ab1a77..0ba21b8 100644
--- a/audio/telephony-maemo6.c
+++ b/audio/telephony-maemo6.c
@@ -973,35 +973,13 @@ static void handle_create_requested(DBusMessage *msg)
EV_CALLSETUP_OUTGOING);
}
-static void handle_call_status(DBusMessage *msg, const char *call_path)
+static void call_set_status(struct csd_call *call, dbus_uint32_t status)
{
- struct csd_call *call;
- dbus_uint32_t status, cause_type, cause, prev_status;
+ dbus_uint32_t prev_status;
int callheld = telephony_get_indicator(maemo_indicators, "callheld");
- if (!dbus_message_get_args(msg, NULL,
- DBUS_TYPE_UINT32, &status,
- DBUS_TYPE_UINT32, &cause_type,
- DBUS_TYPE_UINT32, &cause,
- DBUS_TYPE_INVALID)) {
- error("Unexpected paramters in Instance.CallStatus() signal");
- return;
- }
-
- call = find_call(call_path);
- if (!call) {
- error("Didn't find any matching call object for %s",
- call_path);
- return;
- }
-
- if (status > 16) {
- error("Invalid call status %u", status);
- return;
- }
-
prev_status = call->status;
- DBG("Call %s changed from %s to %s", call_path,
+ DBG("Call %s changed from %s to %s", call->object_path,
call_status_str[prev_status], call_status_str[status]);
if (prev_status == status) {
@@ -1132,6 +1110,35 @@ static void handle_call_status(DBusMessage *msg, const char *call_path)
}
}
+static void handle_call_status(DBusMessage *msg, const char *call_path)
+{
+ struct csd_call *call;
+ dbus_uint32_t status, cause_type, cause;
+
+ if (!dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_UINT32, &status,
+ DBUS_TYPE_UINT32, &cause_type,
+ DBUS_TYPE_UINT32, &cause,
+ DBUS_TYPE_INVALID)) {
+ error("Unexpected paramters in Instance.CallStatus() signal");
+ return;
+ }
+
+ call = find_call(call_path);
+ if (!call) {
+ error("Didn't find any matching call object for %s",
+ call_path);
+ return;
+ }
+
+ if (status > 16) {
+ error("Invalid call status %u", status);
+ return;
+ }
+
+ call_set_status(call, status);
+}
+
static void handle_conference(DBusMessage *msg, gboolean joined)
{
const char *path;
@@ -1470,13 +1477,12 @@ static void parse_call_list(DBusMessageIter *iter)
if (!call) {
call = g_new0(struct csd_call, 1);
call->object_path = g_strdup(object_path);
- call->status = (int) status;
calls = g_slist_append(calls, call);
DBG("telephony-maemo6: new csd call instance at %s",
object_path);
}
- if (call->status == CSD_CALL_STATUS_IDLE)
+ if (status == CSD_CALL_STATUS_IDLE)
continue;
/* CSD gives incorrect call_hold property sometimes */
@@ -1493,6 +1499,9 @@ static void parse_call_list(DBusMessageIter *iter)
g_free(call->number);
call->number = g_strdup(number);
+ /* Update indicators */
+ call_set_status(call, status);
+
} while (dbus_message_iter_next(iter));
}
--
1.7.1
^ permalink raw reply related
* Re: [PATCH 2/3] Fix not resetting indicators whenever the driver is initialized
From: Luiz Augusto von Dentz @ 2011-02-14 10:26 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1297678882-26893-2-git-send-email-luiz.dentz@gmail.com>
Hi,
On Mon, Feb 14, 2011 at 12:21 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
>
> This may cause invalid values to be reported since the status of call can
> change during the time adaptor was off.
> ---
> audio/telephony-maemo6.c | 9 +++++++++
> 1 files changed, 9 insertions(+), 0 deletions(-)
>
> diff --git a/audio/telephony-maemo6.c b/audio/telephony-maemo6.c
> index 0c99c34..0ab1a77 100644
> --- a/audio/telephony-maemo6.c
> +++ b/audio/telephony-maemo6.c
> @@ -1981,6 +1981,15 @@ int telephony_init(void)
> DBG("telephony-maemo6 registering %s interface on path %s",
> TELEPHONY_MAEMO_INTERFACE, TELEPHONY_MAEMO_PATH);
>
> + /* Reset indicators */
> + telephony_update_indicator(maemo_indicators, "battchg", 5);
> + telephony_update_indicator(maemo_indicators, "signal", 0);
> + telephony_update_indicator(maemo_indicators, "service", 0);
> + telephony_update_indicator(maemo_indicators, "call", 0);
> + telephony_update_indicator(maemo_indicators, "callsetup", 0);
> + telephony_update_indicator(maemo_indicators, "callhelp", 0);
> + telephony_update_indicator(maemo_indicators, "roam", 0);
> +
> telephony_ready_ind(features, maemo_indicators, BTRH_NOT_SUPPORTED,
> chld_str);
> if (send_method_call("org.freedesktop.Hal",
> --
> 1.7.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Please ignore this, it is probably better to just reset the fields
directly and not call telephony_update_indicator.
--
Luiz Augusto von Dentz
Computer Engineer
^ permalink raw reply
* [PATCH] bluethooth: sco: fix information leak to userspace
From: Vasiliy Kulikov @ 2011-02-14 10:54 UTC (permalink / raw)
To: linux-kernel
Cc: security, Marcel Holtmann, Gustavo F. Padovan, David S. Miller,
linux-bluetooth, netdev
struct sco_conninfo has one padding byte in the end. Local variable
cinfo of type sco_conninfo is copied to userspace with this uninizialized
one byte, leading to old stack contents leak.
Signed-off-by: Vasiliy Kulikov <segoon@openwall.com>
---
Compile tested.
net/bluetooth/sco.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 960c6d1..926ed39 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -703,6 +703,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname, char __user
break;
}
+ memset(&cinfo, 0, sizeof(cinfo));
cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
--
1.7.0.4
^ permalink raw reply related
* [PATCH] bluetooth: bnep: fix buffer overflow
From: Vasiliy Kulikov @ 2011-02-14 10:54 UTC (permalink / raw)
To: linux-kernel
Cc: security, Marcel Holtmann, Gustavo F. Padovan, David S. Miller,
Tejun Heo, linux-bluetooth, netdev
Struct ca is copied from userspace. It is not checked whether the "device"
field is NULL terminated. This potentially leads to BUG() inside of
alloc_netdev_mqs() and/or information leak by creating a device with a name
made of contents of kernel stack.
Signed-off-by: Vasiliy Kulikov <segoon@openwall.com>
---
Compile tested.
net/bluetooth/bnep/sock.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
index 2862f53..30faaf1 100644
--- a/net/bluetooth/bnep/sock.c
+++ b/net/bluetooth/bnep/sock.c
@@ -88,6 +88,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
sockfd_put(nsock);
return -EBADFD;
}
+ ca.device[sizeof(ca.device)-1] = 0;
err = bnep_add_connection(&ca, nsock);
if (!err) {
--
1.7.0.4
^ permalink raw reply related
* [PATCH 2/3 v2] Fix not resetting indicators whenever the driver is initialized
From: Luiz Augusto von Dentz @ 2011-02-14 11:02 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
This may cause invalid values to be reported since the status of call can
change during the time adaptor was off.
---
audio/telephony-maemo6.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/audio/telephony-maemo6.c b/audio/telephony-maemo6.c
index 0c99c34..86405fc 100644
--- a/audio/telephony-maemo6.c
+++ b/audio/telephony-maemo6.c
@@ -1950,6 +1950,7 @@ int telephony_init(void)
AG_FEATURE_ENHANCED_CALL_CONTROL |
AG_FEATURE_EXTENDED_ERROR_RESULT_CODES |
AG_FEATURE_THREE_WAY_CALLING;
+ int i;
DBG("");
@@ -1981,6 +1982,14 @@ int telephony_init(void)
DBG("telephony-maemo6 registering %s interface on path %s",
TELEPHONY_MAEMO_INTERFACE, TELEPHONY_MAEMO_PATH);
+ /* Reset indicators */
+ for (i = 0; maemo_indicators[i].desc != NULL; i++) {
+ if (g_str_equal(maemo_indicators[i].desc, "battchg"))
+ maemo_indicators[i].val = 5;
+ else
+ maemo_indicators[i].val = 0;
+ }
+
telephony_ready_ind(features, maemo_indicators, BTRH_NOT_SUPPORTED,
chld_str);
if (send_method_call("org.freedesktop.Hal",
--
1.7.1
^ permalink raw reply related
* [PATCH v2] Bluetooth: Use proper timer for hci command timout
From: ville.tervo @ 2011-02-14 11:36 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ville Tervo
From: Ville Tervo <ville.tervo@nokia.com>
Use proper timer instead of hci command flow control to timeout
failed hci commands. Otherwise stack ends up sending commands
when flow control is used to block new commands.
2010-09-01 18:29:41.592132 < HCI Command: Remote Name Request (0x01|0x0019) plen 10
bdaddr 00:16:CF:E1:C7:D7 mode 2 clkoffset 0x0000
2010-09-01 18:29:41.592681 > HCI Event: Command Status (0x0f) plen 4
Remote Name Request (0x01|0x0019) status 0x00 ncmd 0
2010-09-01 18:29:51.022033 < HCI Command: Remote Name Request Cancel (0x01|0x001a) plen 6
bdaddr 00:16:CF:E1:C7:D7
Signed-off-by: Ville Tervo <ville.tervo@nokia.com>
---
include/net/bluetooth/hci.h | 3 +++
include/net/bluetooth/hci_core.h | 2 +-
net/bluetooth/hci_core.c | 22 ++++++++++++++++------
net/bluetooth/hci_event.c | 6 ++++++
4 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 4bee030..918af32 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -119,6 +119,7 @@ enum {
#define HCI_PAIRING_TIMEOUT (60000) /* 60 seconds */
#define HCI_IDLE_TIMEOUT (6000) /* 6 seconds */
#define HCI_INIT_TIMEOUT (10000) /* 10 seconds */
+#define HCI_CMD_TIMEOUT (1000) /* 1 seconds */
/* HCI data types */
#define HCI_COMMAND_PKT 0x01
@@ -242,6 +243,8 @@ enum {
#define HCI_AT_GENERAL_BONDING_MITM 0x05
/* ----- HCI Commands ---- */
+#define HCI_OP_NOP 0x0000
+
#define HCI_OP_INQUIRY 0x0401
struct hci_cp_inquiry {
__u8 lap[3];
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 6163bff..51dd73b 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -128,7 +128,6 @@ struct hci_dev {
unsigned int acl_pkts;
unsigned int sco_pkts;
- unsigned long cmd_last_tx;
unsigned long acl_last_tx;
unsigned long sco_last_tx;
@@ -138,6 +137,7 @@ struct hci_dev {
struct work_struct power_off;
struct timer_list off_timer;
+ struct timer_list cmd_timer;
struct tasklet_struct cmd_task;
struct tasklet_struct rx_task;
struct tasklet_struct tx_task;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 2f00322..069c2bc 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -41,6 +41,7 @@
#include <linux/interrupt.h>
#include <linux/notifier.h>
#include <linux/rfkill.h>
+#include <linux/timer.h>
#include <net/sock.h>
#include <asm/system.h>
@@ -611,6 +612,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
/* Drop last sent command */
if (hdev->sent_cmd) {
+ del_timer_sync(&hdev->cmd_timer);
kfree_skb(hdev->sent_cmd);
hdev->sent_cmd = NULL;
}
@@ -1054,6 +1056,16 @@ int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
return 0;
}
+/* HCI command timer function */
+static void hci_cmd_timer(unsigned long arg)
+{
+ struct hci_dev *hdev = (void *) arg;
+
+ BT_ERR("%s command tx timeout", hdev->name);
+ atomic_set(&hdev->cmd_cnt, 1);
+ tasklet_schedule(&hdev->cmd_task);
+}
+
/* Register HCI device */
int hci_register_dev(struct hci_dev *hdev)
{
@@ -1100,6 +1112,8 @@ int hci_register_dev(struct hci_dev *hdev)
skb_queue_head_init(&hdev->cmd_q);
skb_queue_head_init(&hdev->raw_q);
+ setup_timer(&hdev->cmd_timer, hci_cmd_timer, (unsigned long) hdev);
+
for (i = 0; i < NUM_REASSEMBLY; i++)
hdev->reassembly[i] = NULL;
@@ -1936,11 +1950,6 @@ static void hci_cmd_task(unsigned long arg)
BT_DBG("%s cmd %d", hdev->name, atomic_read(&hdev->cmd_cnt));
- if (!atomic_read(&hdev->cmd_cnt) && time_after(jiffies, hdev->cmd_last_tx + HZ)) {
- BT_ERR("%s command tx timeout", hdev->name);
- atomic_set(&hdev->cmd_cnt, 1);
- }
-
/* Send queued commands */
if (atomic_read(&hdev->cmd_cnt)) {
skb = skb_dequeue(&hdev->cmd_q);
@@ -1953,7 +1962,8 @@ static void hci_cmd_task(unsigned long arg)
if (hdev->sent_cmd) {
atomic_dec(&hdev->cmd_cnt);
hci_send_frame(skb);
- hdev->cmd_last_tx = jiffies;
+ mod_timer(&hdev->cmd_timer,
+ jiffies + msecs_to_jiffies(HCI_CMD_TIMEOUT));
} else {
skb_queue_head(&hdev->cmd_q, skb);
tasklet_schedule(&hdev->cmd_task);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index cee46cb..3836fd3 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1672,6 +1672,9 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
break;
}
+ if (ev->opcode != HCI_OP_NOP)
+ del_timer(&hdev->cmd_timer);
+
if (ev->ncmd) {
atomic_set(&hdev->cmd_cnt, 1);
if (!skb_queue_empty(&hdev->cmd_q))
@@ -1743,6 +1746,9 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
break;
}
+ if (ev->opcode != HCI_OP_NOP)
+ del_timer(&hdev->cmd_timer);
+
if (ev->ncmd) {
atomic_set(&hdev->cmd_cnt, 1);
if (!skb_queue_empty(&hdev->cmd_q))
--
1.7.1
^ permalink raw reply related
* Re: [PATCH] bluetooth: bnep: fix buffer overflow
From: Gustavo F. Padovan @ 2011-02-14 14:35 UTC (permalink / raw)
To: Vasiliy Kulikov
Cc: linux-kernel, security, Marcel Holtmann, David S. Miller,
Tejun Heo, linux-bluetooth, netdev
In-Reply-To: <1297680871-11617-1-git-send-email-segoon@openwall.com>
Hi Vasiliy,
* Vasiliy Kulikov <segoon@openwall.com> [2011-02-14 13:54:31 +0300]:
> Struct ca is copied from userspace. It is not checked whether the "device"
> field is NULL terminated. This potentially leads to BUG() inside of
> alloc_netdev_mqs() and/or information leak by creating a device with a name
> made of contents of kernel stack.
>
> Signed-off-by: Vasiliy Kulikov <segoon@openwall.com>
> ---
> Compile tested.
>
> net/bluetooth/bnep/sock.c | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
Applied, thanks.
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* Re: [PATCH] bluethooth: sco: fix information leak to userspace
From: Gustavo F. Padovan @ 2011-02-14 14:36 UTC (permalink / raw)
To: Vasiliy Kulikov
Cc: linux-kernel, security, Marcel Holtmann, David S. Miller,
linux-bluetooth, netdev
In-Reply-To: <1297680867-11551-1-git-send-email-segoon@openwall.com>
Hi Vasiliy,
* Vasiliy Kulikov <segoon@openwall.com> [2011-02-14 13:54:26 +0300]:
> struct sco_conninfo has one padding byte in the end. Local variable
> cinfo of type sco_conninfo is copied to userspace with this uninizialized
> one byte, leading to old stack contents leak.
>
> Signed-off-by: Vasiliy Kulikov <segoon@openwall.com>
> ---
> Compile tested.
>
> net/bluetooth/sco.c | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
Applied as well, thanks.
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* Re: [PATCH v2] Bluetooth: Use proper timer for hci command timout
From: Gustavo F. Padovan @ 2011-02-14 14:40 UTC (permalink / raw)
To: ville.tervo; +Cc: linux-bluetooth
In-Reply-To: <1297683372-28351-1-git-send-email-ville.tervo@nokia.com>
Hi Ville,
* ville.tervo@nokia.com <ville.tervo@nokia.com> [2011-02-14 13:36:12 +0200]:
> From: Ville Tervo <ville.tervo@nokia.com>
>
> Use proper timer instead of hci command flow control to timeout
> failed hci commands. Otherwise stack ends up sending commands
> when flow control is used to block new commands.
>
> 2010-09-01 18:29:41.592132 < HCI Command: Remote Name Request (0x01|0x0019) plen 10
> bdaddr 00:16:CF:E1:C7:D7 mode 2 clkoffset 0x0000
> 2010-09-01 18:29:41.592681 > HCI Event: Command Status (0x0f) plen 4
> Remote Name Request (0x01|0x0019) status 0x00 ncmd 0
> 2010-09-01 18:29:51.022033 < HCI Command: Remote Name Request Cancel (0x01|0x001a) plen 6
> bdaddr 00:16:CF:E1:C7:D7
>
> Signed-off-by: Ville Tervo <ville.tervo@nokia.com>
> ---
> include/net/bluetooth/hci.h | 3 +++
> include/net/bluetooth/hci_core.h | 2 +-
> net/bluetooth/hci_core.c | 22 ++++++++++++++++------
> net/bluetooth/hci_event.c | 6 ++++++
> 4 files changed, 26 insertions(+), 7 deletions(-)
Patch has been applied. Thanks.
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* Re: [PATCH] Bluetooth: rfcomm: Release BTM while sleeping to avoid deadlock.
From: Gustavo F. Padovan @ 2011-02-14 14:49 UTC (permalink / raw)
To: Владислав
Cc: linux-bluetooth
In-Reply-To: <E1PoQLR-0008E5-00.vladisslav-inbox-ru@f68.mail.ru>
Hi
* Владислав <vladisslav@inbox.ru> [2011-02-13 04:01:45 +0300]:
> Bug description:
> Kernel freezes for ~2 seconds after trying to access /dev/rfcommX device.
> Steps to reproduce:
> 1. Edit /etc/bluetooth/rfcomm.conf - uncomment default config, set "bind" to "yes".
> 2. Issue "sudo rfcomm bind all" to create /dev/rfcomm0 device node.
> 3. Issue "cat /dev/rfcomm0" to trigger a bug.
> Everything freezes (at least GUI): cursor does not move, no response from
> keypresses, no gui redraw for 2~3 seconds.
> Then cat displays expected error message "cat: /dev/rfcomm0: Host is down"
> and system starts to respond again.
> What expected (and occurs with 2.6.35) : no freeze between cat and error message.
> Things goes worse when device, mentioned in /etc/bluetooth/rfcomm.conf
> is in range and not paired - system displays pairing request and locks
> up for a longer time, maybe completely - I did not wait longer than ~30
> seconds and turned off bluetooth device.
>
> Fix:
> Release BTM while sleeping to avoid deadlock.
>
> diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
> index 2575c2d..d7b9af4 100644
> --- a/net/bluetooth/rfcomm/tty.c
> +++ b/net/bluetooth/rfcomm/tty.c
> @@ -727,7 +727,9 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
> break;
> }
>
> + tty_unlock();
> schedule();
> + tty_lock();
> }
> set_current_state(TASK_RUNNING);
> remove_wait_queue(&dev->wait, &wait);
I've faced this issue some days ago and your patch looks good. But I need
proper git patch with your Signed-off-by line.
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* Re: [HACK PATCH] N900 l2cap connect crash, NULL parent
From: Gustavo F. Padovan @ 2011-02-14 14:56 UTC (permalink / raw)
To: David Fries; +Cc: linux-bluetooth
In-Reply-To: <20110211035309.GA22204@spacedout.fries.net>
Hi David,
* David Fries <david@fries.net> [2011-02-10 21:53:09 -0600]:
> Here's a patch to avoid a very repeatable crash in the N900. If I
> take a Motorola S305 bluetooth headset that was previously paried with
> the N900, turn it on, and press the play button before the headphones
> automatically pair with the cell phone, the N900 will crash (and
> reboot) in pairing. If I wait until after they have paired there
> isn't any problem. The patch is against the kernel-power
> 2.6.28-maemo46 by Thomas Tanner, the stock Nokia PR1.2 oops looked
> the same, I just haven't gone back to that kernel.
This is a very old kernel. You need to check this issue against
bluetooth-next-2.6.
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* [PATCH v3 1/3] Include check to readline lib on acinlude.m4
From: Sheldon Demario @ 2011-02-14 15:07 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Sheldon Demario
In-Reply-To: <20110209212642.GA11368@jh-x301>
---
acinclude.m4 | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/acinclude.m4 b/acinclude.m4
index 9d3f6b2..91e0956 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -153,6 +153,15 @@ AC_DEFUN([AC_PATH_SNDFILE], [
AC_SUBST(SNDFILE_LIBS)
])
+AC_DEFUN([AC_PATH_READLINE], [
+ AC_CHECK_HEADER(readline/readline.h,
+ AC_CHECK_LIB(readline, main,
+ [ readline_found=yes
+ AC_SUBST(READLINE_LIBS, "-lreadline")
+ ], readline_found=no),
+ [])
+])
+
AC_DEFUN([AC_PATH_OUI], [
AC_ARG_WITH(ouifile,
AS_HELP_STRING([--with-ouifile=PATH],[Path to the oui.txt file @<:@auto@:>@]),
@@ -356,6 +365,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
AM_CONDITIONAL(HEALTHPLUGIN, test "${health_enable}" = "yes")
AM_CONDITIONAL(MCAP, test "${health_enable}" = "yes")
AM_CONDITIONAL(HAL, test "${hal_enable}" = "yes")
+ AM_CONDITIONAL(READLINE, test "${readline_found}" = "yes")
AM_CONDITIONAL(ATTRIBPLUGIN, test "${attrib_enable}" = "yes")
AM_CONDITIONAL(ECHOPLUGIN, test "no" = "yes")
AM_CONDITIONAL(PNATPLUGIN, test "${pnat_enable}" = "yes")
--
1.7.1
^ permalink raw reply related
* [PATCH v3 2/3] Add an initial interactive mode to gatttool
From: Sheldon Demario @ 2011-02-14 15:07 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Sheldon Demario
In-Reply-To: <20110209212642.GA11368@jh-x301>
Mode required to allow better GATT procedures control. Some scenarios
require sequential commands without disconnection and delay between
operations. It is also desirable to change some connection parameters
of an active connection.
---
Makefile.am | 8 ++-
attrib/gatttool.c | 9 ++++
attrib/gatttool.h | 24 +++++++++
attrib/interactive.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++
configure.ac | 1 +
5 files changed, 168 insertions(+), 2 deletions(-)
create mode 100644 attrib/gatttool.h
create mode 100644 attrib/interactive.c
diff --git a/Makefile.am b/Makefile.am
index e6639a7..11f990b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -175,12 +175,16 @@ builtin_sources += plugins/service.c
endif
if ATTRIBPLUGIN
+
+if READLINE
bin_PROGRAMS += attrib/gatttool
attrib_gatttool_SOURCES = attrib/gatttool.c attrib/att.c attrib/gatt.c \
attrib/gattrib.c btio/btio.c \
- src/glib-helper.h src/glib-helper.c
-attrib_gatttool_LDADD = lib/libbluetooth.la @GLIB_LIBS@
+ src/glib-helper.h src/glib-helper.c \
+ attrib/gatttool.h attrib/interactive.c
+attrib_gatttool_LDADD = lib/libbluetooth.la @GLIB_LIBS@ @READLINE_LIBS@
+endif
builtin_modules += attrib
builtin_sources += attrib/main.c \
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 8e8ed8e..d663eb5 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -42,6 +42,7 @@
#include "gattrib.h"
#include "glib-helper.h"
#include "gatt.h"
+#include "gatttool.h"
/* Minimum MTU for L2CAP connections over BR/EDR */
#define ATT_MIN_MTU_L2CAP 48
@@ -63,6 +64,7 @@ static gboolean opt_listen = FALSE;
static gboolean opt_char_desc = FALSE;
static gboolean opt_le = FALSE;
static gboolean opt_char_write = FALSE;
+static gboolean opt_interactive = FALSE;
static GMainLoop *event_loop;
static gboolean got_error = FALSE;
@@ -537,6 +539,8 @@ static GOptionEntry gatt_options[] = {
"Listen for notifications and indications", NULL },
{ "le", 0, 0, G_OPTION_ARG_NONE, &opt_le,
"Use Bluetooth Low Energy transport", NULL },
+ { "interactive", 'I', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
+ &opt_interactive, "Use interactive mode", NULL },
{ NULL },
};
@@ -594,6 +598,11 @@ int main(int argc, char *argv[])
g_error_free(gerr);
}
+ if (opt_interactive) {
+ interactive();
+ goto done;
+ }
+
if (opt_primary)
callback = primary;
else if (opt_characteristics)
diff --git a/attrib/gatttool.h b/attrib/gatttool.h
new file mode 100644
index 0000000..ed5d9d6
--- /dev/null
+++ b/attrib/gatttool.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ *
+ *
+ * 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 interactive(void);
diff --git a/attrib/interactive.c b/attrib/interactive.c
new file mode 100644
index 0000000..0653609
--- /dev/null
+++ b/attrib/interactive.c
@@ -0,0 +1,128 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ *
+ *
+ * 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 <strings.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <glib.h>
+
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#include "gatttool.h"
+
+static GMainLoop *event_loop;
+
+static void cmd_help(int argcp, char **argvp);
+
+static void cmd_exit(int argcp, char **argvp)
+{
+ rl_callback_handler_remove();
+ g_main_loop_quit(event_loop);
+}
+
+static struct {
+ const char *cmd;
+ void (*func)(int argcp, char **argvp);
+ const char *desc;
+} commands[] = {
+ { "help", cmd_help, "Show this help"},
+ { "exit", cmd_exit, "Exit interactive mode"},
+ { NULL, NULL, NULL}
+};
+
+static void cmd_help(int argcp, char **argvp)
+{
+ int i;
+
+ for (i = 0; commands[i].cmd; i++)
+ printf("%-12s\t%s\n", commands[i].cmd, commands[i].desc);
+}
+
+static void parse_line(char *line_read)
+{
+ gchar **argvp;
+ int argcp;
+ int i;
+
+ if (line_read == NULL) {
+ printf("\n");
+ cmd_exit(0, NULL);
+ return;
+ }
+
+ line_read = g_strstrip(line_read);
+
+ if (*line_read == '\0')
+ return;
+
+ add_history(line_read);
+
+ g_shell_parse_argv(line_read, &argcp, &argvp, NULL);
+
+ for (i = 0; commands[i].cmd; i++)
+ if (strcasecmp(commands[i].cmd, argvp[0]) == 0)
+ break;
+
+ if (commands[i].cmd)
+ commands[i].func(argcp, argvp);
+ else
+ printf("%s: command not found\n", argvp[0]);
+
+ g_strfreev(argvp);
+}
+
+static gboolean prompt_read(GIOChannel *chan, GIOCondition cond,
+ gpointer user_data)
+{
+ if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+ g_io_channel_unref(chan);
+ return FALSE;
+ }
+
+ rl_callback_read_char();
+
+ return TRUE;
+}
+
+int interactive(void)
+{
+ GIOChannel *pchan;
+ gint events;
+
+ event_loop = g_main_loop_new(NULL, FALSE);
+
+ pchan = g_io_channel_unix_new(fileno(stdin));
+ g_io_channel_set_close_on_unref(pchan, TRUE);
+ events = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
+ g_io_add_watch(pchan, events, prompt_read, NULL);
+
+ rl_callback_handler_install("> ", parse_line);
+
+ g_main_loop_run(event_loop);
+
+ rl_callback_handler_remove();
+ g_io_channel_unref(pchan);
+ g_main_loop_unref(event_loop);
+
+ return 0;
+}
diff --git a/configure.ac b/configure.ac
index bebdc9c..a8e8fc6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -42,6 +42,7 @@ AC_PATH_GSTREAMER
AC_PATH_USB
AC_PATH_SNDFILE
AC_PATH_OUI
+AC_PATH_READLINE
AC_ARG_BLUEZ
--
1.7.1
^ permalink raw reply related
* [PATCH v3 3/3] Add connect/disconnect options on interactive mode of gatttool
From: Sheldon Demario @ 2011-02-14 15:07 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Sheldon Demario
In-Reply-To: <20110209212642.GA11368@jh-x301>
---
attrib/gatttool.c | 10 ++--
attrib/gatttool.h | 3 +-
attrib/interactive.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 119 insertions(+), 8 deletions(-)
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index d663eb5..cd6b60d 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -83,7 +83,7 @@ static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
}
}
-static GIOChannel *do_connect(gboolean le)
+GIOChannel *do_connect(gchar *dst, gboolean le, BtIOConnect connect_cb)
{
GIOChannel *chan;
bdaddr_t sba, dba;
@@ -99,11 +99,11 @@ static GIOChannel *do_connect(gboolean le)
}
/* Remote device */
- if (opt_dst == NULL) {
+ if (dst == NULL) {
g_printerr("Remote Bluetooth address required\n");
return NULL;
}
- str2ba(opt_dst, &dba);
+ str2ba(dst, &dba);
/* Local adapter */
if (opt_src != NULL) {
@@ -599,7 +599,7 @@ int main(int argc, char *argv[])
}
if (opt_interactive) {
- interactive();
+ interactive(opt_dst, opt_le);
goto done;
}
@@ -621,7 +621,7 @@ int main(int argc, char *argv[])
goto done;
}
- chan = do_connect(opt_le);
+ chan = do_connect(opt_dst, opt_le, connect_cb);
if (chan == NULL) {
got_error = TRUE;
goto done;
diff --git a/attrib/gatttool.h b/attrib/gatttool.h
index ed5d9d6..2237330 100644
--- a/attrib/gatttool.h
+++ b/attrib/gatttool.h
@@ -21,4 +21,5 @@
*
*/
-int interactive(void);
+int interactive(gchar *dst, gboolean le);
+GIOChannel *do_connect(gchar *dst, gboolean le, BtIOConnect connect_cb);
diff --git a/attrib/interactive.c b/attrib/interactive.c
index 0653609..83a0778 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -28,18 +28,119 @@
#include <readline/readline.h>
#include <readline/history.h>
+#include "btio.h"
+#include "gattrib.h"
#include "gatttool.h"
+static GIOChannel *iochannel = NULL;
+static GAttrib *attrib = NULL;
static GMainLoop *event_loop;
+static GString *prompt;
+
+static gchar *opt_dst = NULL;
+static gboolean opt_le = FALSE;
static void cmd_help(int argcp, char **argvp);
+enum state {
+ STATE_DISCONNECTED,
+ STATE_CONNECTING,
+ STATE_CONNECTED
+} conn_state;
+
+static char *get_prompt(void)
+{
+ if (conn_state == STATE_CONNECTING) {
+ g_string_assign(prompt, "Connecting... ");
+ return prompt->str;
+ }
+
+ if (conn_state == STATE_CONNECTED)
+ g_string_assign(prompt, "[CON]");
+ else
+ g_string_assign(prompt, "[ ]");
+
+ if (opt_dst)
+ g_string_append_printf(prompt, "[%17s]", opt_dst);
+ else
+ g_string_append_printf(prompt, "[%17s]", "");
+
+ if (opt_le)
+ g_string_append(prompt, "[LE]");
+ else
+ g_string_append(prompt, "[BR]");
+
+ g_string_append(prompt, "> ");
+
+ return prompt->str;
+}
+
+
+static void set_state(enum state st)
+{
+ conn_state = st;
+ rl_set_prompt(get_prompt());
+ rl_redisplay();
+}
+
+static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
+{
+ if (err) {
+ printf("connect error: %s\n", err->message);
+ set_state(STATE_DISCONNECTED);
+ return;
+ }
+
+ attrib = g_attrib_new(iochannel);
+ set_state(STATE_CONNECTED);
+}
+
static void cmd_exit(int argcp, char **argvp)
{
rl_callback_handler_remove();
g_main_loop_quit(event_loop);
}
+static void cmd_connect(int argcp, char **argvp)
+{
+ if (conn_state != STATE_DISCONNECTED)
+ return;
+
+ if (argcp > 1) {
+ g_free(opt_dst);
+ opt_dst = strdup(argvp[1]);
+ }
+
+ if (opt_dst == NULL) {
+ printf("Remote Bluetooth address required\n");
+ return;
+ }
+
+ set_state(STATE_CONNECTING);
+ iochannel = do_connect(opt_dst, opt_le, connect_cb);
+ if (iochannel == NULL)
+ set_state(STATE_DISCONNECTED);
+
+ return;
+}
+
+static void cmd_disconnect(int argcp, char **argvp)
+{
+ if (conn_state == STATE_DISCONNECTED)
+ return;
+
+ g_attrib_unref(attrib);
+ attrib = NULL;
+
+ g_io_channel_shutdown(iochannel, FALSE, NULL);
+ g_io_channel_unref(iochannel);
+ iochannel = NULL;
+
+ set_state(STATE_DISCONNECTED);
+
+ return;
+}
+
static struct {
const char *cmd;
void (*func)(int argcp, char **argvp);
@@ -47,6 +148,8 @@ static struct {
} commands[] = {
{ "help", cmd_help, "Show this help"},
{ "exit", cmd_exit, "Exit interactive mode"},
+ { "connect", cmd_connect, "Connect to a remote device"},
+ { "disconnect", cmd_disconnect, "Disconnect from a remote device"},
{ NULL, NULL, NULL}
};
@@ -104,11 +207,16 @@ static gboolean prompt_read(GIOChannel *chan, GIOCondition cond,
return TRUE;
}
-int interactive(void)
+int interactive(gchar *dst, gboolean le)
{
GIOChannel *pchan;
gint events;
+ opt_dst = dst;
+ opt_le = le;
+
+ prompt = g_string_new(NULL);
+
event_loop = g_main_loop_new(NULL, FALSE);
pchan = g_io_channel_unix_new(fileno(stdin));
@@ -116,13 +224,15 @@ int interactive(void)
events = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
g_io_add_watch(pchan, events, prompt_read, NULL);
- rl_callback_handler_install("> ", parse_line);
+ rl_callback_handler_install(get_prompt(), parse_line);
g_main_loop_run(event_loop);
rl_callback_handler_remove();
+ cmd_disconnect(0, NULL);
g_io_channel_unref(pchan);
g_main_loop_unref(event_loop);
+ g_string_free(prompt, TRUE);
return 0;
}
--
1.7.1
^ permalink raw reply related
* Re: [PATCH] Bluetooth: rfcomm: Release BTM while sleeping to avoid deadlock.
From: Gustavo F. Padovan @ 2011-02-14 17:25 UTC (permalink / raw)
To: Vladislav P; +Cc: linux-bluetooth
In-Reply-To: <E1Pp0gh-0002s9-00.vladisslav-inbox-ru@f95.mail.ru>
Hi Vladislav,
* Vladislav P <vladisslav@inbox.ru> [2011-02-14 18:50:07 +0300]:
> Mon, 14 Feb 2011 12:49:31 -0200 письмо от "Gustavo F. Padovan" <padovan@profusion.mobi>:
>
> > Hi
> >
> > * Владислав <vladisslav@inbox.ru> [2011-02-13 04:01:45 +0300]:
> >
> > > Bug description:
> > > Kernel freezes for ~2 seconds after trying to access /dev/rfcommX device.
> > > Steps to reproduce:
> > > 1. Edit /etc/bluetooth/rfcomm.conf - uncomment default config, set "bind" to
> > "yes".
> > > 2. Issue "sudo rfcomm bind all" to create /dev/rfcomm0 device node.
> > > 3. Issue "cat /dev/rfcomm0" to trigger a bug.
> > > Everything freezes (at least GUI): cursor does not move, no response from
> > > keypresses, no gui redraw for 2~3 seconds.
> > > Then cat displays expected error message "cat: /dev/rfcomm0: Host is down"
> > > and system starts to respond again.
> > > What expected (and occurs with 2.6.35) : no freeze between cat and error
> > message.
> > > Things goes worse when device, mentioned in /etc/bluetooth/rfcomm.conf
> > > is in range and not paired - system displays pairing request and locks
> > > up for a longer time, maybe completely - I did not wait longer than ~30
> > > seconds and turned off bluetooth device.
> >
> > I've faced this issue some days ago and your patch looks good. But I need
> > proper git patch with your Signed-off-by line.
> >
> > --
> > Gustavo F. Padovan
> > http://profusion.mobi
> Made proper patch:
>
> From d1459f3042b4b8cdea1f1a184eb61f7be4002203 Mon Sep 17 00:00:00 2001
> From: Vladislav P <vladisslav@inbox.ru>
> Date: Mon, 14 Feb 2011 18:42:27 +0300
> Subject: [PATCH] Release BTM while sleeping to avoid deadlock.
>
> Signed-off-by: Vladislav P <vladisslav@inbox.ru>
> ---
> net/bluetooth/rfcomm/tty.c | 2 ++
> 1 files changed, 2 insertions(+), 0 deletions(-)
Applied, thanks.
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* [PATCH] Fix parsing of "Flags" AD type
From: Anderson Lizardo @ 2011-02-14 17:36 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
If an advertising report did not contain a "Flags" AD Type (e.g. a Scan
response), the previous flags value was mistakenly set to 0x00. This fix
makes sure dev->flags is only updated for valid values.
---
src/adapter.c | 5 +++--
src/adapter.h | 2 +-
src/event.c | 4 +++-
3 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 3e609c1..5366285 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3028,7 +3028,7 @@ static void dev_prepend_uuid(gpointer data, gpointer user_data)
void adapter_update_device_from_info(struct btd_adapter *adapter,
bdaddr_t bdaddr, int8_t rssi,
uint8_t evt_type, const char *name,
- GSList *services, uint8_t flags)
+ GSList *services, int flags)
{
struct remote_dev_info *dev;
gboolean new_dev;
@@ -3049,7 +3049,8 @@ void adapter_update_device_from_info(struct btd_adapter *adapter,
g_slist_foreach(services, remove_same_uuid, dev);
g_slist_foreach(services, dev_prepend_uuid, dev);
- dev->flags = flags;
+ if (flags >= 0)
+ dev->flags = flags;
if (name) {
g_free(dev->name);
diff --git a/src/adapter.h b/src/adapter.h
index 1edc441..39dd905 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -135,7 +135,7 @@ struct remote_dev_info *adapter_search_found_devices(struct btd_adapter *adapter
void adapter_update_device_from_info(struct btd_adapter *adapter,
bdaddr_t bdaddr, int8_t rssi,
uint8_t evt_type, const char *name,
- GSList *services, uint8_t flags);
+ GSList *services, int flags);
void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
int8_t rssi, uint32_t class, const char *name,
const char *alias, gboolean legacy,
diff --git a/src/event.c b/src/event.c
index 0659fd1..6f345d4 100644
--- a/src/event.c
+++ b/src/event.c
@@ -60,7 +60,7 @@
struct eir_data {
GSList *services;
- uint8_t flags;
+ int flags;
char *name;
gboolean name_complete;
};
@@ -289,6 +289,8 @@ static int parse_eir_data(struct eir_data *eir, uint8_t *eir_data,
char *uuid_str;
unsigned int i;
+ eir->flags = -1;
+
/* No EIR data to parse */
if (eir_data == NULL || eir_length == 0)
return 0;
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH v3 2/3] Add an initial interactive mode to gatttool
From: Gustavo F. Padovan @ 2011-02-14 18:13 UTC (permalink / raw)
To: Sheldon Demario; +Cc: linux-bluetooth
In-Reply-To: <1297696040-16453-2-git-send-email-sheldon.demario@openbossa.org>
Hi Sheldon,
* Sheldon Demario <sheldon.demario@openbossa.org> [2011-02-14 12:07:19 -0300]:
> Mode required to allow better GATT procedures control. Some scenarios
> require sequential commands without disconnection and delay between
> operations. It is also desirable to change some connection parameters
> of an active connection.
> ---
> Makefile.am | 8 ++-
> attrib/gatttool.c | 9 ++++
> attrib/gatttool.h | 24 +++++++++
> attrib/interactive.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++
> configure.ac | 1 +
> 5 files changed, 168 insertions(+), 2 deletions(-)
> create mode 100644 attrib/gatttool.h
> create mode 100644 attrib/interactive.c
>
> diff --git a/Makefile.am b/Makefile.am
> index e6639a7..11f990b 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -175,12 +175,16 @@ builtin_sources += plugins/service.c
> endif
>
> if ATTRIBPLUGIN
> +
> +if READLINE
Is that really needed? You already checked for READLINE in ./configure at
this point.
> bin_PROGRAMS += attrib/gatttool
>
> attrib_gatttool_SOURCES = attrib/gatttool.c attrib/att.c attrib/gatt.c \
> attrib/gattrib.c btio/btio.c \
> - src/glib-helper.h src/glib-helper.c
> -attrib_gatttool_LDADD = lib/libbluetooth.la @GLIB_LIBS@
> + src/glib-helper.h src/glib-helper.c \
> + attrib/gatttool.h attrib/interactive.c
> +attrib_gatttool_LDADD = lib/libbluetooth.la @GLIB_LIBS@ @READLINE_LIBS@
> +endif
>
> builtin_modules += attrib
> builtin_sources += attrib/main.c \
> diff --git a/attrib/gatttool.c b/attrib/gatttool.c
> index 8e8ed8e..d663eb5 100644
> --- a/attrib/gatttool.c
> +++ b/attrib/gatttool.c
> @@ -42,6 +42,7 @@
> #include "gattrib.h"
> #include "glib-helper.h"
> #include "gatt.h"
> +#include "gatttool.h"
>
> /* Minimum MTU for L2CAP connections over BR/EDR */
> #define ATT_MIN_MTU_L2CAP 48
> @@ -63,6 +64,7 @@ static gboolean opt_listen = FALSE;
> static gboolean opt_char_desc = FALSE;
> static gboolean opt_le = FALSE;
> static gboolean opt_char_write = FALSE;
> +static gboolean opt_interactive = FALSE;
> static GMainLoop *event_loop;
> static gboolean got_error = FALSE;
>
> @@ -537,6 +539,8 @@ static GOptionEntry gatt_options[] = {
> "Listen for notifications and indications", NULL },
> { "le", 0, 0, G_OPTION_ARG_NONE, &opt_le,
> "Use Bluetooth Low Energy transport", NULL },
> + { "interactive", 'I', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
> + &opt_interactive, "Use interactive mode", NULL },
> { NULL },
> };
>
> @@ -594,6 +598,11 @@ int main(int argc, char *argv[])
> g_error_free(gerr);
> }
>
> + if (opt_interactive) {
> + interactive();
> + goto done;
> + }
> +
> if (opt_primary)
> callback = primary;
> else if (opt_characteristics)
> diff --git a/attrib/gatttool.h b/attrib/gatttool.h
> new file mode 100644
> index 0000000..ed5d9d6
> --- /dev/null
> +++ b/attrib/gatttool.h
> @@ -0,0 +1,24 @@
> +/*
> + *
> + * BlueZ - Bluetooth protocol stack for Linux
> + *
> + * Copyright (C) 2011 Nokia Corporation
> + *
> + *
> + * 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 interactive(void);
> diff --git a/attrib/interactive.c b/attrib/interactive.c
> new file mode 100644
> index 0000000..0653609
> --- /dev/null
> +++ b/attrib/interactive.c
> @@ -0,0 +1,128 @@
> +/*
> + *
> + * BlueZ - Bluetooth protocol stack for Linux
> + *
> + * Copyright (C) 2011 Nokia Corporation
> + *
> + *
> + * 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 <strings.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <glib.h>
> +
> +#include <readline/readline.h>
> +#include <readline/history.h>
> +
> +#include "gatttool.h"
> +
> +static GMainLoop *event_loop;
> +
> +static void cmd_help(int argcp, char **argvp);
Just move cmd_help() up to avoid this.
> +
> +static void cmd_exit(int argcp, char **argvp)
> +{
> + rl_callback_handler_remove();
> + g_main_loop_quit(event_loop);
> +}
> +
> +static struct {
> + const char *cmd;
> + void (*func)(int argcp, char **argvp);
> + const char *desc;
> +} commands[] = {
> + { "help", cmd_help, "Show this help"},
> + { "exit", cmd_exit, "Exit interactive mode"},
> + { NULL, NULL, NULL}
> +};
> +
> +static void cmd_help(int argcp, char **argvp)
> +{
> + int i;
> +
> + for (i = 0; commands[i].cmd; i++)
> + printf("%-12s\t%s\n", commands[i].cmd, commands[i].desc);
> +}
> +
> +static void parse_line(char *line_read)
> +{
> + gchar **argvp;
> + int argcp;
> + int i;
> +
> + if (line_read == NULL) {
> + printf("\n");
> + cmd_exit(0, NULL);
> + return;
> + }
> +
> + line_read = g_strstrip(line_read);
> +
> + if (*line_read == '\0')
> + return;
> +
> + add_history(line_read);
> +
> + g_shell_parse_argv(line_read, &argcp, &argvp, NULL);
> +
> + for (i = 0; commands[i].cmd; i++)
> + if (strcasecmp(commands[i].cmd, argvp[0]) == 0)
> + break;
> +
> + if (commands[i].cmd)
> + commands[i].func(argcp, argvp);
> + else
> + printf("%s: command not found\n", argvp[0]);
> +
> + g_strfreev(argvp);
> +}
> +
> +static gboolean prompt_read(GIOChannel *chan, GIOCondition cond,
> + gpointer user_data)
> +{
> + if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
> + g_io_channel_unref(chan);
> + return FALSE;
> + }
> +
> + rl_callback_read_char();
> +
> + return TRUE;
> +}
> +
> +int interactive(void)
> +{
> + GIOChannel *pchan;
> + gint events;
> +
> + event_loop = g_main_loop_new(NULL, FALSE);
> +
> + pchan = g_io_channel_unix_new(fileno(stdin));
> + g_io_channel_set_close_on_unref(pchan, TRUE);
Please add a blank line here.
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* Re: [PATCH v3 2/3] Add an initial interactive mode to gatttool
From: Sheldon Demario @ 2011-02-14 18:40 UTC (permalink / raw)
To: Gustavo F. Padovan; +Cc: linux-bluetooth
In-Reply-To: <20110214181338.GG2597@joana>
Hi Gustavo,
On Mon, Feb 14, 2011 at 3:13 PM, Gustavo F. Padovan
<padovan@profusion.mobi> wrote:
> Hi Sheldon,
>
> * Sheldon Demario <sheldon.demario@openbossa.org> [2011-02-14 12:07:19 -0300]:
>
>> Mode required to allow better GATT procedures control. Some scenarios
>> require sequential commands without disconnection and delay between
>> operations. It is also desirable to change some connection parameters
>> of an active connection.
>> ---
>> Makefile.am | 8 ++-
>> attrib/gatttool.c | 9 ++++
>> attrib/gatttool.h | 24 +++++++++
>> attrib/interactive.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++
>> configure.ac | 1 +
>> 5 files changed, 168 insertions(+), 2 deletions(-)
>> create mode 100644 attrib/gatttool.h
>> create mode 100644 attrib/interactive.c
>>
>> diff --git a/Makefile.am b/Makefile.am
>> index e6639a7..11f990b 100644
>> --- a/Makefile.am
>> +++ b/Makefile.am
>> @@ -175,12 +175,16 @@ builtin_sources += plugins/service.c
>> endif
>>
>> if ATTRIBPLUGIN
>> +
>> +if READLINE
>
> Is that really needed? You already checked for READLINE in ./configure at
> this point.
Actually ./configure just check if it exists and doesn't fail if so.
The libreadline doesn't have pkgconfig files to make this process
easy, thats why it is just not compiled if it is missing.
>
>> bin_PROGRAMS += attrib/gatttool
>>
>> attrib_gatttool_SOURCES = attrib/gatttool.c attrib/att.c attrib/gatt.c \
>> attrib/gattrib.c btio/btio.c \
>> - src/glib-helper.h src/glib-helper.c
>> -attrib_gatttool_LDADD = lib/libbluetooth.la @GLIB_LIBS@
>> + src/glib-helper.h src/glib-helper.c \
>> + attrib/gatttool.h attrib/interactive.c
>> +attrib_gatttool_LDADD = lib/libbluetooth.la @GLIB_LIBS@ @READLINE_LIBS@
>> +endif
>>
>> builtin_modules += attrib
>> builtin_sources += attrib/main.c \
>> diff --git a/attrib/gatttool.c b/attrib/gatttool.c
>> index 8e8ed8e..d663eb5 100644
>> --- a/attrib/gatttool.c
>> +++ b/attrib/gatttool.c
>> @@ -42,6 +42,7 @@
>> #include "gattrib.h"
>> #include "glib-helper.h"
>> #include "gatt.h"
>> +#include "gatttool.h"
>>
>> /* Minimum MTU for L2CAP connections over BR/EDR */
>> #define ATT_MIN_MTU_L2CAP 48
>> @@ -63,6 +64,7 @@ static gboolean opt_listen = FALSE;
>> static gboolean opt_char_desc = FALSE;
>> static gboolean opt_le = FALSE;
>> static gboolean opt_char_write = FALSE;
>> +static gboolean opt_interactive = FALSE;
>> static GMainLoop *event_loop;
>> static gboolean got_error = FALSE;
>>
>> @@ -537,6 +539,8 @@ static GOptionEntry gatt_options[] = {
>> "Listen for notifications and indications", NULL },
>> { "le", 0, 0, G_OPTION_ARG_NONE, &opt_le,
>> "Use Bluetooth Low Energy transport", NULL },
>> + { "interactive", 'I', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
>> + &opt_interactive, "Use interactive mode", NULL },
>> { NULL },
>> };
>>
>> @@ -594,6 +598,11 @@ int main(int argc, char *argv[])
>> g_error_free(gerr);
>> }
>>
>> + if (opt_interactive) {
>> + interactive();
>> + goto done;
>> + }
>> +
>> if (opt_primary)
>> callback = primary;
>> else if (opt_characteristics)
>> diff --git a/attrib/gatttool.h b/attrib/gatttool.h
>> new file mode 100644
>> index 0000000..ed5d9d6
>> --- /dev/null
>> +++ b/attrib/gatttool.h
>> @@ -0,0 +1,24 @@
>> +/*
>> + *
>> + * BlueZ - Bluetooth protocol stack for Linux
>> + *
>> + * Copyright (C) 2011 Nokia Corporation
>> + *
>> + *
>> + * 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 interactive(void);
>> diff --git a/attrib/interactive.c b/attrib/interactive.c
>> new file mode 100644
>> index 0000000..0653609
>> --- /dev/null
>> +++ b/attrib/interactive.c
>> @@ -0,0 +1,128 @@
>> +/*
>> + *
>> + * BlueZ - Bluetooth protocol stack for Linux
>> + *
>> + * Copyright (C) 2011 Nokia Corporation
>> + *
>> + *
>> + * 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 <strings.h>
>> +#include <stdlib.h>
>> +#include <stdio.h>
>> +#include <glib.h>
>> +
>> +#include <readline/readline.h>
>> +#include <readline/history.h>
>> +
>> +#include "gatttool.h"
>> +
>> +static GMainLoop *event_loop;
>> +
>> +static void cmd_help(int argcp, char **argvp);
>
> Just move cmd_help() up to avoid this.
>
>> +
>> +static void cmd_exit(int argcp, char **argvp)
>> +{
>> + rl_callback_handler_remove();
>> + g_main_loop_quit(event_loop);
>> +}
>> +
>> +static struct {
>> + const char *cmd;
>> + void (*func)(int argcp, char **argvp);
>> + const char *desc;
>> +} commands[] = {
>> + { "help", cmd_help, "Show this help"},
>> + { "exit", cmd_exit, "Exit interactive mode"},
>> + { NULL, NULL, NULL}
>> +};
>> +
>> +static void cmd_help(int argcp, char **argvp)
>> +{
>> + int i;
>> +
>> + for (i = 0; commands[i].cmd; i++)
>> + printf("%-12s\t%s\n", commands[i].cmd, commands[i].desc);
>> +}
>> +
>> +static void parse_line(char *line_read)
>> +{
>> + gchar **argvp;
>> + int argcp;
>> + int i;
>> +
>> + if (line_read == NULL) {
>> + printf("\n");
>> + cmd_exit(0, NULL);
>> + return;
>> + }
>> +
>> + line_read = g_strstrip(line_read);
>> +
>> + if (*line_read == '\0')
>> + return;
>> +
>> + add_history(line_read);
>> +
>> + g_shell_parse_argv(line_read, &argcp, &argvp, NULL);
>> +
>> + for (i = 0; commands[i].cmd; i++)
>> + if (strcasecmp(commands[i].cmd, argvp[0]) == 0)
>> + break;
>> +
>> + if (commands[i].cmd)
>> + commands[i].func(argcp, argvp);
>> + else
>> + printf("%s: command not found\n", argvp[0]);
>> +
>> + g_strfreev(argvp);
>> +}
>> +
>> +static gboolean prompt_read(GIOChannel *chan, GIOCondition cond,
>> + gpointer user_data)
>> +{
>> + if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
>> + g_io_channel_unref(chan);
>> + return FALSE;
>> + }
>> +
>> + rl_callback_read_char();
>> +
>> + return TRUE;
>> +}
>> +
>> +int interactive(void)
>> +{
>> + GIOChannel *pchan;
>> + gint events;
>> +
>> + event_loop = g_main_loop_new(NULL, FALSE);
>> +
>> + pchan = g_io_channel_unix_new(fileno(stdin));
>> + g_io_channel_set_close_on_unref(pchan, TRUE);
>
> Please add a blank line here.
>
> --
> Gustavo F. Padovan
> http://profusion.mobi
>
Sheldon
^ permalink raw reply
* Question about controlling channel hopping and paging
From: Hayden Gomes @ 2011-02-14 19:46 UTC (permalink / raw)
To: linux-bluetooth list
Hi list,
I need to be able to manually control the channel and paging behavior
of my adapter rather than having it follow it's usual hopping sequence
while scanning. Can this be done with BlueZ? Could someone please
direct me to a good reference or resource where I can read more on how
to accomplish this?
thanks,
Hayden
^ permalink raw reply
* [PATCH] src: fix typo
From: Gustavo F. Padovan @ 2011-02-14 21:34 UTC (permalink / raw)
To: linux-bluetooth
---
src/event.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/event.c b/src/event.c
index 0659fd1..a415468 100644
--- a/src/event.c
+++ b/src/event.c
@@ -731,7 +731,7 @@ void btd_event_le_set_scan_enable_complete(bdaddr_t *local, uint8_t status)
}
if (status) {
- error("Can't enabled/disable LE scan");
+ error("Can't enable/disable LE scan");
return;
}
--
1.7.4
^ permalink raw reply related
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