* [PATCH 3/3] Add gatttool enhancements for UPF
From: Brian Gix @ 2011-02-16 21:18 UTC (permalink / raw)
To: linux-bluetooth; +Cc: johan.hedberg, padovan, Brian Gix
In-Reply-To: <1297891081-27976-1-git-send-email-bgix@codeaurora.org>
Including seperating write-cmd from write-char, and enabling
--listen to stand on it's own if needed. (PTS tester)
---
attrib/gatttool.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 52 insertions(+), 5 deletions(-)
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 8e8ed8e..054adb1 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -63,6 +63,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_char_cmd = FALSE;
static GMainLoop *event_loop;
static gboolean got_error = FALSE;
@@ -90,9 +91,9 @@ static GIOChannel *do_connect(gboolean le)
/* This check is required because currently setsockopt() returns no
* errors for MTU values smaller than the allowed minimum. */
- if (opt_mtu != 0 && opt_mtu < ATT_MIN_MTU_L2CAP) {
+ if (opt_mtu != 0 && opt_mtu < 23) {
g_printerr("MTU cannot be smaller than %d\n",
- ATT_MIN_MTU_L2CAP);
+ 23);
return NULL;
}
@@ -277,6 +278,14 @@ static gboolean characteristics(gpointer user_data)
return FALSE;
}
+static void char_write_cb(guint8 status, const guint8 *pdu, guint16 plen,
+ gpointer user_data)
+{
+ if (plen == 1)
+ g_print("Attrib Write Succeeded\n");
+ else
+ g_printerr("Attrib Write failed: %s\n", att_ecode2str(status));
+}
static void char_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
gpointer user_data)
{
@@ -427,7 +436,40 @@ static gboolean characteristics_write(gpointer user_data)
goto error;
}
+ gatt_write_char(attrib, opt_handle, value, len, char_write_cb, value);
+ gatt_read_char(attrib, opt_handle, char_read_cb, attrib);
+
+ return FALSE;
+
+error:
+ g_main_loop_quit(event_loop);
+ return FALSE;
+}
+
+static gboolean characteristics_cmd(gpointer user_data)
+{
+ GAttrib *attrib = user_data;
+ uint8_t *value;
+ size_t len;
+
+ if (opt_handle <= 0) {
+ g_printerr("A valid handle is required\n");
+ goto error;
+ }
+
+ if (opt_value == NULL || opt_value[0] == '\0') {
+ g_printerr("A value is required\n");
+ goto error;
+ }
+
+ len = attr_data_from_string(opt_value, &value);
+ if (len == 0) {
+ g_printerr("Invalid value\n");
+ goto error;
+ }
+
gatt_write_cmd(attrib, opt_handle, value, len, mainloop_quit, value);
+ gatt_read_char(attrib, opt_handle, char_read_cb, attrib);
return FALSE;
@@ -531,6 +573,8 @@ static GOptionEntry gatt_options[] = {
"Characteristics Value/Descriptor Read", NULL },
{ "char-write", 0, 0, G_OPTION_ARG_NONE, &opt_char_write,
"Characteristics Value Write", NULL },
+ { "char-cmd", 0, 0, G_OPTION_ARG_NONE, &opt_char_cmd,
+ "Characteristics Value Cmd", NULL },
{ "char-desc", 0, 0, G_OPTION_ARG_NONE, &opt_char_desc,
"Characteristics Descriptor Discovery", NULL },
{ "listen", 0, 0, G_OPTION_ARG_NONE, &opt_listen,
@@ -561,7 +605,7 @@ int main(int argc, char *argv[])
GError *gerr = NULL;
GAttrib *attrib;
GIOChannel *chan;
- GSourceFunc callback;
+ GSourceFunc callback = NULL;
context = g_option_context_new(NULL);
g_option_context_add_main_entries(context, options, NULL);
@@ -602,9 +646,11 @@ int main(int argc, char *argv[])
callback = characteristics_read;
else if (opt_char_write)
callback = characteristics_write;
+ else if (opt_char_cmd)
+ callback = characteristics_cmd;
else if (opt_char_desc)
callback = characteristics_desc;
- else {
+ else if (!opt_listen) {
gchar *help = g_option_context_get_help(context, TRUE, NULL);
g_print("%s\n", help);
g_free(help);
@@ -625,7 +671,8 @@ int main(int argc, char *argv[])
if (opt_listen)
g_idle_add(listen_start, attrib);
- g_idle_add(callback, attrib);
+ if (callback)
+ g_idle_add(callback, attrib);
g_main_loop_run(event_loop);
--
1.7.1
--
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
^ permalink raw reply related
* [PATCH 2/3] Add SDP registration of Primary GATT services
From: Brian Gix @ 2011-02-16 21:18 UTC (permalink / raw)
To: linux-bluetooth; +Cc: johan.hedberg, padovan, Brian Gix
In-Reply-To: <1297891081-27976-1-git-send-email-bgix@codeaurora.org>
SDP registration can be supressed by passing Zero as the end
handle argument to attrib_db_add().
---
attrib/example.c | 119 +++++++++++++++++++++++++++++++------------
src/attrib-server.c | 139 +++++++++++++++++++++++++++++++++++----------------
src/attrib-server.h | 6 ++-
3 files changed, 184 insertions(+), 80 deletions(-)
diff --git a/attrib/example.c b/attrib/example.c
index 1911912..eab3c0f 100644
--- a/attrib/example.c
+++ b/attrib/example.c
@@ -31,6 +31,7 @@
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
+#include <src/sdpd.h>
#include <glib.h>
@@ -59,6 +60,9 @@
#define FMT_KILOGRAM_UUID 0xA010
#define FMT_HANGING_UUID 0xA011
+#define SDP_RECORD_COUNT 10
+sdp_record_t *sdp_records[SDP_RECORD_COUNT];
+
static int register_attributes(void)
{
const char *desc_out_temp = "Outside Temperature";
@@ -77,59 +81,73 @@ static int register_attributes(void)
uint8_t atval[256];
uuid_t uuid;
int len;
+ int i = 0;
/* Battery state service: primary service definition */
sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
att_put_u16(BATTERY_STATE_SVC_UUID, &atval[0]);
- attrib_db_add(0x0100, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+ sdp_records[i++] = attrib_db_add(0x0100, 0x0111, &uuid,
+ "Battery State Service",
+ ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 2);
/* Battery: battery state characteristic */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0110, &atval[1]);
att_put_u16(BATTERY_STATE_UUID, &atval[3]);
- attrib_db_add(0x0106, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+ attrib_db_add(0x0106, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 5);
/* Battery: battery state attribute */
sdp_uuid16_create(&uuid, BATTERY_STATE_UUID);
atval[0] = 0x04;
- attrib_db_add(0x0110, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 1);
+ attrib_db_add(0x0110, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 1);
/* Battery: Client Characteristic Configuration */
sdp_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
atval[0] = 0x00;
atval[1] = 0x00;
- attrib_db_add(0x0111, &uuid, ATT_NONE, ATT_AUTHENTICATION, atval, 2);
+ attrib_db_add(0x0111, 0, &uuid, NULL, ATT_NONE, ATT_AUTHENTICATION,
+ atval, 2);
/* Thermometer: primary service definition */
sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
att_put_u16(THERM_HUMIDITY_SVC_UUID, &atval[0]);
- attrib_db_add(0x0200, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+ sdp_records[i++] = attrib_db_add(0x0200, 0x0214, &uuid, "Thermometer",
+ ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 2);
/* Thermometer: Include */
sdp_uuid16_create(&uuid, GATT_INCLUDE_UUID);
att_put_u16(0x0500, &atval[0]);
att_put_u16(0x0504, &atval[2]);
att_put_u16(MANUFACTURER_SVC_UUID, &atval[4]);
- attrib_db_add(0x0201, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
+ attrib_db_add(0x0201, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 6);
/* Thermometer: Include */
att_put_u16(0x0550, &atval[0]);
att_put_u16(0x0568, &atval[2]);
- attrib_db_add(0x0202, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 4);
+ att_put_u16(VENDOR_SPECIFIC_SVC_UUID, &atval[4]);
+ attrib_db_add(0x0202, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 6);
/* Thermometer: temperature characteristic */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0204, &atval[1]);
att_put_u16(TEMPERATURE_UUID, &atval[3]);
- attrib_db_add(0x0203, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+ attrib_db_add(0x0203, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 5);
/* Thermometer: temperature characteristic value */
sdp_uuid16_create(&uuid, TEMPERATURE_UUID);
atval[0] = 0x8A;
atval[1] = 0x02;
- attrib_db_add(0x0204, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+ attrib_db_add(0x0204, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 2);
/* Thermometer: temperature characteristic format */
sdp_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
@@ -138,25 +156,29 @@ static int register_attributes(void)
att_put_u16(FMT_CELSIUS_UUID, &atval[2]);
atval[4] = 0x01;
att_put_u16(FMT_OUTSIDE_UUID, &atval[5]);
- attrib_db_add(0x0205, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 7);
+ attrib_db_add(0x0205, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 7);
/* Thermometer: characteristic user description */
sdp_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
len = strlen(desc_out_temp);
strncpy((char *) atval, desc_out_temp, len);
- attrib_db_add(0x0206, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+ attrib_db_add(0x0206, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, len);
/* Thermometer: relative humidity characteristic */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0212, &atval[1]);
att_put_u16(RELATIVE_HUMIDITY_UUID, &atval[3]);
- attrib_db_add(0x0210, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+ attrib_db_add(0x0210, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 5);
/* Thermometer: relative humidity value */
sdp_uuid16_create(&uuid, RELATIVE_HUMIDITY_UUID);
atval[0] = 0x27;
- attrib_db_add(0x0212, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 1);
+ attrib_db_add(0x0212, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 1);
/* Thermometer: relative humidity characteristic format */
sdp_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
@@ -165,68 +187,79 @@ static int register_attributes(void)
att_put_u16(FMT_PERCENT_UUID, &atval[2]);
att_put_u16(BLUETOOTH_SIG_UUID, &atval[4]);
att_put_u16(FMT_OUTSIDE_UUID, &atval[6]);
- attrib_db_add(0x0213, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 8);
+ attrib_db_add(0x0213, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 8);
/* Thermometer: characteristic user description */
sdp_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
len = strlen(desc_out_hum);
strncpy((char *) atval, desc_out_hum, len);
- attrib_db_add(0x0214, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+ attrib_db_add(0x0214, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, len);
/* Secondary Service: Manufacturer Service */
sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID);
att_put_u16(MANUFACTURER_SVC_UUID, &atval[0]);
- attrib_db_add(0x0500, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+ attrib_db_add(0x0500, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 2);
/* Manufacturer name characteristic definition */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0502, &atval[1]);
att_put_u16(MANUFACTURER_NAME_UUID, &atval[3]);
- attrib_db_add(0x0501, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+ attrib_db_add(0x0501, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 5);
/* Manufacturer name characteristic value */
sdp_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
len = strlen(manufacturer_name1);
strncpy((char *) atval, manufacturer_name1, len);
- attrib_db_add(0x0502, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+ attrib_db_add(0x0502, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, len);
/* Manufacturer serial number characteristic */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0504, &atval[1]);
att_put_u16(MANUFACTURER_SERIAL_UUID, &atval[3]);
- attrib_db_add(0x0503, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+ attrib_db_add(0x0503, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 5);
/* Manufacturer serial number characteristic value */
sdp_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
len = strlen(serial1);
strncpy((char *) atval, serial1, len);
- attrib_db_add(0x0504, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+ attrib_db_add(0x0504, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, len);
/* Secondary Service: Manufacturer Service */
sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID);
att_put_u16(MANUFACTURER_SVC_UUID, &atval[0]);
- attrib_db_add(0x0505, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+ attrib_db_add(0x0505, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 2);
/* Manufacturer name characteristic definition */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0507, &atval[1]);
att_put_u16(MANUFACTURER_NAME_UUID, &atval[3]);
- attrib_db_add(0x0506, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+ attrib_db_add(0x0506, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 5);
/* Secondary Service: Vendor Specific Service */
sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID);
att_put_u16(VENDOR_SPECIFIC_SVC_UUID, &atval[0]);
- attrib_db_add(0x0550, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+ attrib_db_add(0x0550, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 2);
/* Vendor Specific Type characteristic definition */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0568, &atval[1]);
att_put_u16(VENDOR_SPECIFIC_TYPE_UUID, &atval[3]);
- attrib_db_add(0x0560, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+ attrib_db_add(0x0560, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 5);
/* Vendor Specific Type characteristic value */
sdp_uuid16_create(&uuid, VENDOR_SPECIFIC_TYPE_UUID);
@@ -236,45 +269,53 @@ static int register_attributes(void)
atval[3] = 0x64;
atval[4] = 0x6F;
atval[5] = 0x72;
- attrib_db_add(0x0568, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
+ attrib_db_add(0x0568, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 6);
/* Manufacturer name attribute */
sdp_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
len = strlen(manufacturer_name2);
strncpy((char *) atval, manufacturer_name2, len);
- attrib_db_add(0x0507, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+ attrib_db_add(0x0507, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, len);
/* Characteristic: serial number */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0509, &atval[1]);
att_put_u16(MANUFACTURER_SERIAL_UUID, &atval[3]);
- attrib_db_add(0x0508, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+ attrib_db_add(0x0508, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 5);
/* Serial number characteristic value */
sdp_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
len = strlen(serial2);
strncpy((char *) atval, serial2, len);
- attrib_db_add(0x0509, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+ attrib_db_add(0x0509, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, len);
/* Weight service: primary service definition */
sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
memcpy(atval, prim_weight_uuid, 16);
- attrib_db_add(0x0680, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 16);
+ sdp_records[i++] = attrib_db_add(0x0680, 0x685, &uuid, "Weight Service",
+ ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 16);
/* Weight: include */
sdp_uuid16_create(&uuid, GATT_INCLUDE_UUID);
att_put_u16(0x0505, &atval[0]);
att_put_u16(0x0509, &atval[2]);
att_put_u16(MANUFACTURER_SVC_UUID, &atval[4]);
- attrib_db_add(0x0681, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
+ attrib_db_add(0x0681, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 6);
/* Weight: characteristic */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0683, &atval[1]);
memcpy(&atval[3], char_weight_uuid, 16);
- attrib_db_add(0x0682, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 19);
+ attrib_db_add(0x0682, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 19);
/* Weight: characteristic value */
sdp_uuid128_create(&uuid, char_weight_uuid);
@@ -282,7 +323,8 @@ static int register_attributes(void)
atval[1] = 0x55;
atval[2] = 0x00;
atval[3] = 0x00;
- attrib_db_add(0x0683, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 4);
+ attrib_db_add(0x0683, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 4);
/* Weight: characteristic format */
sdp_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
@@ -291,13 +333,15 @@ static int register_attributes(void)
att_put_u16(FMT_KILOGRAM_UUID, &atval[2]);
att_put_u16(BLUETOOTH_SIG_UUID, &atval[4]);
att_put_u16(FMT_HANGING_UUID, &atval[6]);
- attrib_db_add(0x0684, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 8);
+ attrib_db_add(0x0684, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 8);
/* Weight: characteristic user description */
sdp_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
len = strlen(desc_weight);
strncpy((char *) atval, desc_weight, len);
- attrib_db_add(0x0685, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+ attrib_db_add(0x0685, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, len);
return 0;
}
@@ -309,4 +353,11 @@ int server_example_init(void)
void server_example_exit(void)
{
+ int i;
+
+ for (i = 0; i < SDP_RECORD_COUNT; i++)
+ if (sdp_records[i]) {
+ remove_record_from_server(sdp_records[i]->handle);
+ sdp_records[i] = NULL;
+ }
}
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 72f5b17..db42ab2 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -70,7 +70,8 @@ struct group_elem {
static GIOChannel *l2cap_io = NULL;
static GIOChannel *le_io = NULL;
static GSList *clients = NULL;
-static uint32_t sdp_handle = 0;
+static uint32_t gatt_sdp_handle = 0;
+static uint32_t gap_sdp_handle = 0;
static uuid_t prim_uuid = {
.type = SDP_UUID16,
@@ -81,14 +82,19 @@ static uuid_t snd_uuid = {
.value.uuid16 = GATT_SND_SVC_UUID
};
-static sdp_record_t *server_record_new(void)
+static sdp_record_t *server_record_new(uuid_t *uuid, uint16_t start, uint16_t end)
{
- sdp_list_t *svclass_id, *apseq, *proto[2], *profiles, *root, *aproto;
+ sdp_list_t *svclass_id, *apseq, *proto[2], *root, *aproto;
uuid_t root_uuid, proto_uuid, gatt_uuid, l2cap;
- sdp_profile_desc_t profile;
sdp_record_t *record;
sdp_data_t *psm, *sh, *eh;
- uint16_t lp = GATT_PSM, start = 0x0001, end = 0xffff;
+ uint16_t lp = GATT_PSM;
+
+ if (uuid == NULL)
+ return NULL;
+
+ if (start > end)
+ return NULL;
record = sdp_record_alloc();
if (record == NULL)
@@ -99,17 +105,10 @@ static sdp_record_t *server_record_new(void)
sdp_set_browse_groups(record, root);
sdp_list_free(root, NULL);
- sdp_uuid16_create(&gatt_uuid, GENERIC_ATTRIB_SVCLASS_ID);
- svclass_id = sdp_list_append(NULL, &gatt_uuid);
+ svclass_id = sdp_list_append(NULL, uuid);
sdp_set_service_classes(record, svclass_id);
sdp_list_free(svclass_id, NULL);
- sdp_uuid16_create(&profile.uuid, GENERIC_ATTRIB_PROFILE_ID);
- profile.version = 0x0100;
- profiles = sdp_list_append(NULL, &profile);
- sdp_set_profile_descs(record, profiles);
- sdp_list_free(profiles, NULL);
-
sdp_uuid16_create(&l2cap, L2CAP_UUID);
proto[0] = sdp_list_append(NULL, &l2cap);
psm = sdp_data_alloc(SDP_UINT16, &lp);
@@ -127,11 +126,6 @@ static sdp_record_t *server_record_new(void)
aproto = sdp_list_append(NULL, apseq);
sdp_set_access_protos(record, aproto);
- sdp_set_info_attr(record, "Generic Attribute Profile", "BlueZ", NULL);
-
- sdp_set_url_attr(record, "http://www.bluez.org/",
- "http://www.bluez.org/", "http://www.bluez.org/");
-
sdp_set_service_id(record, gatt_uuid);
sdp_data_free(psm);
@@ -609,7 +603,7 @@ static uint16_t write_value(struct gatt_channel *channel, uint16_t handle,
static uint16_t mtu_exchange(struct gatt_channel *channel, uint16_t mtu,
uint8_t *pdu, int len)
{
- channel->mtu = MIN(mtu, ATT_MAX_MTU);
+ channel->mtu = MIN(mtu, channel->mtu);
return enc_mtu_resp(channel->mtu, pdu, len);
}
@@ -796,43 +790,68 @@ static void confirm_event(GIOChannel *io, void *user_data)
return;
}
-static void register_core_services(void)
+static gboolean register_core_services(void)
{
uint8_t atval[256];
uuid_t uuid;
int len;
+ sdp_record_t *record;
/* GAP service: primary service definition */
sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
att_put_u16(GENERIC_ACCESS_PROFILE_ID, &atval[0]);
- attrib_db_add(0x0001, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+ record = attrib_db_add(0x0001, 0x0006, &uuid, "Generic Access Profile",
+ ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
/* GAP service: device name characteristic */
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
atval[0] = ATT_CHAR_PROPER_READ;
att_put_u16(0x0006, &atval[1]);
att_put_u16(GATT_CHARAC_DEVICE_NAME, &atval[3]);
- attrib_db_add(0x0004, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+ attrib_db_add(0x0004, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
+ atval, 5);
/* GAP service: device name attribute */
sdp_uuid16_create(&uuid, GATT_CHARAC_DEVICE_NAME);
len = strlen(main_opts.name);
- attrib_db_add(0x0006, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
+ attrib_db_add(0x0006, 0, &uuid, NULL, ATT_NONE, ATT_NOT_PERMITTED,
(uint8_t *) main_opts.name, len);
/* TODO: Implement Appearance characteristic. It is mandatory for
* Peripheral/Central GAP roles. */
+ if (record == NULL) {
+ error("Failed to register GAP service record");
+ goto failed;
+ }
+
+ gap_sdp_handle = record->handle;
+
/* GATT service: primary service definition */
sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
att_put_u16(GENERIC_ATTRIB_PROFILE_ID, &atval[0]);
- attrib_db_add(0x0010, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+ record = attrib_db_add(0x0010, 0x0010, &uuid, "Generic Attribute Profile",
+ ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+
+ if (record == NULL) {
+ error("Failed to register GATT service record");
+ goto failed;
+ }
+
+ gatt_sdp_handle = record->handle;
+
+ return TRUE;
+
+failed:
+ if (gap_sdp_handle)
+ remove_record_from_server(gap_sdp_handle);
+
+ return FALSE;
}
int attrib_server_init(void)
{
GError *gerr = NULL;
- sdp_record_t *record;
/* BR/EDR socket */
l2cap_io = bt_io_listen(BT_IO_L2CAP, NULL, confirm_event,
@@ -848,21 +867,8 @@ int attrib_server_init(void)
return -1;
}
- record = server_record_new();
- if (record == NULL) {
- error("Unable to create GATT service record");
+ if (!register_core_services())
goto failed;
- }
-
- if (add_record_to_server(BDADDR_ANY, record) < 0) {
- error("Failed to register GATT service record");
- sdp_record_free(record);
- goto failed;
- }
-
- sdp_handle = record->handle;
-
- register_core_services();
if (!main_opts.le)
return 0;
@@ -921,15 +927,60 @@ void attrib_server_exit(void)
g_slist_free(clients);
- if (sdp_handle)
- remove_record_from_server(sdp_handle);
+ if (gatt_sdp_handle)
+ remove_record_from_server(gatt_sdp_handle);
+
+ if (gap_sdp_handle)
+ remove_record_from_server(gap_sdp_handle);
}
-int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs,
- const uint8_t *value, int len)
+sdp_record_t *attrib_db_add(uint16_t handle, uint16_t end, uuid_t *uuid,
+ const char *name,
+ int read_reqs, int write_reqs,
+ const uint8_t *value, int len)
{
struct attribute *a;
+ uuid_t svc;
+ sdp_record_t *record = NULL;
+
+ /* If a valid range is being added AND this is a Primary Service, */
+ /* add it to the SDP database as well. */
+
+ if (end == 0 || handle > end)
+ goto no_sdp;
+
+ if (uuid->type != SDP_UUID16 || uuid->value.uuid16 != GATT_PRIM_SVC_UUID)
+ goto no_sdp;
+
+ if (len == 2) {
+ svc.type = SDP_UUID16;
+ svc.value.uuid16 = att_get_u16(value);
+ } else if (len == 16) {
+ svc.type = SDP_UUID128;
+ memcpy(&svc.value.uuid128, value, sizeof(uint128_t));
+ } else
+ return NULL;
+ record = server_record_new(&svc, handle, end);
+ if (record == NULL)
+ return NULL;
+
+ if (name)
+ sdp_set_info_attr(record, name, "BlueZ", NULL);
+
+ if (svc.type == SDP_UUID16 &&
+ svc.value.uuid16 == GENERIC_ACCESS_PROFILE_ID) {
+ sdp_set_url_attr(record, "http://www.bluez.org/",
+ "http://www.bluez.org/",
+ "http://www.bluez.org/");
+ }
+
+ if (add_record_to_server(BDADDR_ANY, record) < 0) {
+ sdp_record_free(record);
+ return NULL;
+ }
+
+no_sdp:
/* FIXME: handle conflicts */
a = g_malloc0(sizeof(struct attribute) + len);
@@ -942,7 +993,7 @@ int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs,
database = g_slist_insert_sorted(database, a, attribute_cmp);
- return 0;
+ return record;
}
int attrib_db_update(uint16_t handle, uuid_t *uuid, const uint8_t *value,
diff --git a/src/attrib-server.h b/src/attrib-server.h
index ba90ff4..2601d0e 100644
--- a/src/attrib-server.h
+++ b/src/attrib-server.h
@@ -25,8 +25,10 @@
int attrib_server_init(void);
void attrib_server_exit(void);
-int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs,
- const uint8_t *value, int len);
+sdp_record_t *attrib_db_add(uint16_t handle, uint16_t end, uuid_t *uuid,
+ const char *name,
+ int read_reqs, int write_reqs,
+ const uint8_t *value, int len);
int attrib_db_update(uint16_t handle, uuid_t *uuid, const uint8_t *value,
int len);
int attrib_db_del(uint16_t handle);
--
1.7.1
--
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
^ permalink raw reply related
* [PATCH 1/3] Fixed def of ATT_UUID per BT Assigned Numbers
From: Brian Gix @ 2011-02-16 21:17 UTC (permalink / raw)
To: linux-bluetooth; +Cc: johan.hedberg, padovan, Brian Gix
In-Reply-To: <1297891081-27976-1-git-send-email-bgix@codeaurora.org>
---
lib/sdp.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lib/sdp.h b/lib/sdp.h
index 16b59fc..e901b2a 100644
--- a/lib/sdp.h
+++ b/lib/sdp.h
@@ -55,6 +55,7 @@ extern "C" {
#define TCS_BIN_UUID 0x0005
#define TCS_AT_UUID 0x0006
#define OBEX_UUID 0x0008
+#define ATT_UUID 0x0007
#define IP_UUID 0x0009
#define FTP_UUID 0x000a
#define HTTP_UUID 0x000c
@@ -72,7 +73,6 @@ extern "C" {
#define MCAP_CTRL_UUID 0x001e
#define MCAP_DATA_UUID 0x001f
#define L2CAP_UUID 0x0100
-#define ATT_UUID 0x1801
/*
* Service class identifiers of standard services and service groups
--
1.7.1
--
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
^ permalink raw reply related
* [PATCH 0/3] Modifications composed during UPF38
From: Brian Gix @ 2011-02-16 21:17 UTC (permalink / raw)
To: linux-bluetooth; +Cc: johan.hedberg, padovan
The major change in these patches is to register Primary Services
into the SDP databases as required when registering them
into the attrib-server's database. The Core v4.0 specification
indicates that the only valid/foolproof way for a BR/EDR
client to query a server for Primary Services is to do so via
an SDP query. This is from Core v4.0, Vol 3, Part G, Sec 4.4:
"GATT service discovery over BR/EDR transport will list services that only run
over an LE transport and therefore only SDP service discovery shall be used
on BR/EDR."
This also means that there can be "LE Only" primary services that do NOT
need to be in the SDP database, so if a valid range is not specified
when registering a Primary Service, it will be omitted from SDP, and
only appear when performing a GATT based Primary Service Discover.
Also -- The ATT_UUID we were using was incorrect, and I extended the
functionality of the gatttool to allow for listening without sending
anything, and ability to perform both a char-write and char-cmd.
--
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
^ permalink raw reply
* [PATCH 1/1] Fix Min MTU to reflect values for both L2CAP & LE
From: Brian Gix @ 2011-02-16 21:16 UTC (permalink / raw)
To: linux-bluetooth; +Cc: johan.hedberg, padovan, anderson.lizardo, Brian Gix
In-Reply-To: <1297890984-7809-1-git-send-email-bgix@codeaurora.org>
---
attrib/gatttool.c | 9 +++++----
1 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 1e2a8db..38636f9 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -44,8 +44,9 @@
#include "gatt.h"
#include "gatttool.h"
-/* Minimum MTU for L2CAP connections over BR/EDR */
-#define ATT_MIN_MTU_L2CAP 48
+/* Minimum MTU for ATT connections */
+#define ATT_MIN_MTU_LE 23
+#define ATT_MIN_MTU_L2CAP 48
static gchar *opt_src = NULL;
static gchar *opt_dst = NULL;
@@ -93,9 +94,9 @@ GIOChannel *do_connect(gchar *dst, gboolean le, BtIOConnect connect_cb)
/* This check is required because currently setsockopt() returns no
* errors for MTU values smaller than the allowed minimum. */
- if (opt_mtu != 0 && opt_mtu < ATT_MIN_MTU_L2CAP) {
+ if (opt_mtu != 0 && opt_mtu < (le ? ATT_MIN_MTU_LE : ATT_MIN_MTU_L2CAP)) {
g_printerr("MTU cannot be smaller than %d\n",
- ATT_MIN_MTU_L2CAP);
+ (le ? ATT_MIN_MTU_LE : ATT_MIN_MTU_L2CAP));
return NULL;
}
--
1.7.1
--
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
^ permalink raw reply related
* [PATCH 0/1] Fix Minimum gatttool MTU
From: Brian Gix @ 2011-02-16 21:16 UTC (permalink / raw)
To: linux-bluetooth; +Cc: johan.hedberg, padovan, anderson.lizardo
I am satisfied with the rest of the functionality added
to the now "interactive" gatttool, so this patch fixes
the one remaining deficiency from my earlier patch.
--
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
^ permalink raw reply
* pull request: bluetooth-2.6 2011-02-16
From: Gustavo F. Padovan @ 2011-02-16 20:04 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, linux-bluetooth
Hi John,
Here goes new fixes to the Bluetooth subsystem for 2.6.38. We have here
support for firmware dowloading for the Atheros AR5BBU12 device. Also a fix
for btusb a crash from Oliver Neukum and a system freeze fix due to not
releasing the Big TTY Mutex in RFCOMM from Vladislav P.
Please pull! :)
The following changes since commit a7b545f7fe753ca3dc1b51ca57f90cd59d974e44:
mac80211: add missing locking in ieee80211_reconfig (2011-02-09 15:35:13 -0500)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-2.6.git master
Cho, Yu-Chen (1):
Bluetooth: Add Atheros BT AR5BBU12 fw supported
Oliver Neukum (1):
Bluetooth: fix crash with quirky dongles doing sound
Vladislav P (1):
Bluetooth: Release BTM while sleeping to avoid deadlock
drivers/bluetooth/ath3k.c | 3 +++
drivers/bluetooth/btusb.c | 7 +++++--
net/bluetooth/rfcomm/tty.c | 2 ++
3 files changed, 10 insertions(+), 2 deletions(-)
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* Re: bluetooth disabled with current 2.6.38-rc4
From: Gustavo F. Padovan @ 2011-02-16 19:35 UTC (permalink / raw)
To: Justin Mattock; +Cc: Johan Hedberg, linux-bluetooth
In-Reply-To: <5C042A85-6D54-451D-8BAC-CE24D61907CA@gmail.com>
Hi Justin,
* Justin Mattock <justinmattock@gmail.com> [2011-02-16 07:34:52 -0800]:
>
> On Feb 16, 2011, at 5:34 AM, Gustavo F. Padovan wrote:
>
> > Hi Justin,
> >
> > * Justin Mattock <justinmattock@gmail.com> [2011-02-15 19:26:12
> > -0800]:
> >
> >>
> >> On Feb 15, 2011, at 5:52 AM, Johan Hedberg wrote:
> >>
> >>> Hi Justin,
> >>>
> >>> On Sun, Feb 13, 2011, Justin Mattock wrote:
> >>>> maybe I missed something, but my bluetooth is just not functioning
> >>>> with
> >>>> 2.6.38-rc4(works with 2.6.37-rc4)
> >>>>
> >>>> I've done a bisect on this, but was pointed to:
> >>>> c0e45c1ca3162acb2e77b3d9e152ce6e7b6fa3f5
> >>>> but doesn't look correct to me
> >>>>
> >>>> here is what I am seeing with the bluetooth-applet etc..:
> >>>>
> >>>> working correctly:
> >>>> http://www.flickr.com/photos/44066293@N08/5443727238/
> >>>>
> >>>> not working:
> >>>> http://www.flickr.com/photos/44066293@N08/5443124859/
> >>>>
> >>>> my /var/log/daemon.log shows:
> >>>>
> >>>> Feb 13 17:12:22 Linux-2 acpid: 1 client rule loaded
> >>>> Feb 13 17:12:23 Linux-2 bluetoothd[1950]: HCI dev 0 registered
> >>>> Feb 13 17:12:23 Linux-2 bluetoothd[1950]: Listening for HCI events
> >>>> on hci0
> >>>> Feb 13 17:12:23 Linux-2 bluetoothd[1950]: HCI dev 0 up
> >>>> Feb 13 17:12:23 Linux-2 bluetoothd[1950]: Unable to find matching
> >>>> adapter
> >>>>
> >>>> I can try at another bisect, but might take some time.. let me know
> >>>> if there is something I can test
> >>>> or do.
> >>>
> >>> Are you sure this is a kernel problem? There was a similar issue
> >>> with
> >>> BlueZ 4.86 or 4.87 which was already fixed. Could you try with 4.88?
> >>>
> >>> Johan
> >>
> >> o.k. I built 4.88 and still had the issue show up, except this time
> >> no
> >> icon(instead of the icon, that is not lit up)..
> >>
> >>
> >> anyways I did do another bisect and had better results(hopefully)this
> >> time..:
> >>
> >> 23bb57633df97ede067ea26f3cdc8a7ba2cd8109 is the first bad commit
> >> commit 23bb57633df97ede067ea26f3cdc8a7ba2cd8109
> >> Author: Johan Hedberg <johan.hedberg@nokia.com>
> >> Date: Tue Dec 21 23:01:27 2010 +0200
> >>
> >> Bluetooth: Fix __hci_request synchronization for hci_open_dev
> >>
> >> The initialization function used by hci_open_dev (hci_init_req)
> >> sends
> >> many different HCI commands. The __hci_request function should
> >> only
> >> return when all of these commands have completed (or a timeout
> >> occurs).
> >> Several of these commands cause hci_req_complete to be called
> >> which
> >> causes __hci_request to return prematurely.
> >>
> >> This patch fixes the issue by adding a new hdev->req_last_cmd
> >> variable
> >> which is set during the initialization procedure. The
> >> hci_req_complete
> >> function will no longer mark the request as complete until the
> >> command
> >> matching hdev->req_last_cmd completes.
> >>
> >> Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
> >> Acked-by: Marcel Holtmann <marcel@holtmann.org>
> >> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
> >>
> >> :040000 040000 e8d8ae5fab74b2ba73d0c52e7e09b30e5df8484e
> >> 8d1409e8dc2206492cb86e8848c8c23aff182e2a M include
> >> :040000 040000 07fdb5f6ceadcfde12c46a3b5c82937b7dac892c
> >> 8f3b08fbbc9fcd078d0f5224b8bc818eeb072dc4 M net
> >
> > Can you please send the hcidump output? There should be a package
> > for it in
> > your distribution, if not get the bluez-hcidump from git.kernel.org
> >
> > --
> > Gustavo F. Padovan
> > http://profusion.mobi
>
>
>
> o.k...keep in mind I hve never really used that tool, but here goes:
>
> HCI sniffer - Bluetooth packet analyzer ver 2.0
> device: hci0 snap_len: 1028 filter: 0xffffffffffffffff
> > ACL data: handle 46 flags 0x02 dlen 12
> L2CAP(d): cid 0x0041 len 8 [psm 0]
> A1 02 00 11 FD 00 00 00
> > ACL data: handle 46 flags 0x02 dlen 12
> L2CAP(d): cid 0x0041 len 8 [psm 0]
> A1 02 00 0A FF 00 00 00
> > ACL data: handle 46 flags 0x02 dlen 12
> L2CAP(d): cid 0x0041 len 8 [psm 0]
> A1 02 00 1B FC 00 00 00
> > ACL data: handle 46 flags 0x02 dlen 12
> L2CAP(d): cid 0x0041 len 8 [psm 0]
> A1 02 00 22 FE 00 00 00
> > ACL data: handle 46 flags 0x02 dlen 12
> L2CAP(d): cid 0x0041 len 8 [psm 0]
> A1 02 00 27 FF 00 00 00
> > ACL data: handle 46 flags 0x02 dlen 12
> L2CAP(d): cid 0x0041 len 8 [psm 0]
> A1 02 00 15 FF 00 00 00
> > ACL data: handle 46 flags 0x02 dlen 12
> L2CAP(d): cid 0x0041 len 8 [psm 0]
> A1 02 00 2C 00 00 00 00
> > ACL data: handle 46 flags 0x02 dlen 12
> L2CAP(d): cid 0x0041 len 8 [psm 0]
> A1 02 00 2B 00 00 00 00
> > ACL data: handle 46 flags 0x02 dlen 12
> L2CAP(d): cid 0x0041 len 8 [psm 0]
> A1 02 00 14 FF 00 00 00
> > ACL data: handle 46 flags 0x02 dlen 12
> L2CAP(d): cid 0x0041 len 8 [psm 0]
> A1 02 00 21 FD 00 00 00
> > ACL data: handle 46 flags 0x02 dlen 12
> L2CAP(d): cid 0x0041 len 8 [psm 0]
> A1 02 00 18 FB 00 00 00
> > ACL data: handle 46 flags 0x02 dlen 12
> L2CAP(d): cid 0x0041 len 8 [psm 0]
> A1 02 00 09 FD 00 00 00
> > ACL data: handle 46 flags 0x02 dlen 12
> L2CAP(d): cid 0x0041 len 8 [psm 0]
> A1 02 00 0C FC 00 00 00
> > ACL data: handle 46 flags 0x02 dlen 12
> L2CAP(d): cid 0x0041 len 8 [psm 0]
> A1 02 00 04 FE 00 00 00
> > ACL data: handle 46 flags 0x02 dlen 12
> L2CAP(d): cid 0x0041 len 8 [psm 0]
>
> Justin P. Mattock
>
It seems that Bluetooth is working for you. If you really have an issue,
please run "bluetooth -nd" by hand and get the full debugs logs. Also check
if you can run "hciconfig -a".
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* Re: [PATCH v4 1/2] HID: Documentation for hidraw
From: Jiri Kosina @ 2011-02-16 19:10 UTC (permalink / raw)
To: Alan Ott
Cc: Jonathan Corbet, Randy Dunlap, linux-doc, linux-kernel, ospite,
linux-input, linux-bluetooth, bgood
In-Reply-To: <4D5C202B.5030403@signal11.us>
On Wed, 16 Feb 2011, Alan Ott wrote:
> > > Documentation/hid/Makefile | 8 ++
> > > Documentation/hid/hid-example.c | 167
> > > +++++++++++++++++++++++++++++++++++++++
> > >
> > I believe we're trying to get code - especially runnable code - out of the
> > Documentation tree. Should this go under samples/ or, if it's useful
> > enough, under tools/?
> >
>
> Not a problem. I'd say samples/ over tools/ for this stuff. I'll re-spin
> and re-submit.
Perfect, thanks, I'd prefer samples/ as well.
Otherwise I like the hidraw documentation, thanks a lot for putting it
together.
--
Jiri Kosina
SUSE Labs, Novell Inc.
^ permalink raw reply
* Re: [PATCH v4 1/2] HID: Documentation for hidraw
From: Alan Ott @ 2011-02-16 19:06 UTC (permalink / raw)
To: Jonathan Corbet
Cc: Randy Dunlap, linux-doc, linux-kernel, jkosina, ospite,
linux-input, linux-bluetooth, bgood
In-Reply-To: <20110216071200.02ccdaa5@bike.lwn.net>
On 02/16/2011 09:12 AM, Jonathan Corbet wrote:
>> Documentation/hid/Makefile | 8 ++
>> Documentation/hid/hid-example.c | 167 +++++++++++++++++++++++++++++++++++++++
>>
> I believe we're trying to get code - especially runnable code - out of the
> Documentation tree. Should this go under samples/ or, if it's useful
> enough, under tools/?
>
Hi Jon,
Not a problem. I'd say samples/ over tools/ for this stuff. I'll re-spin
and re-submit.
Alan.
^ permalink raw reply
* Re: [PATCH] Fix wrong header include on interactive gatttool
From: Johan Hedberg @ 2011-02-16 19:05 UTC (permalink / raw)
To: Claudio Takahasi; +Cc: linux-bluetooth
In-Reply-To: <1297869099-4419-1-git-send-email-claudio.takahasi@openbossa.org>
Hi Claudio,
On Wed, Feb 16, 2011, Claudio Takahasi wrote:
> This wrong include is triggering compiler warning: implicit declaration
> of function 'strdup'.
> ---
> attrib/interactive.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
Applied. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH] Fix no sink SEP if source interface not registered
From: Luiz Augusto von Dentz @ 2011-02-16 19:05 UTC (permalink / raw)
To: Dmitriy Paliy; +Cc: linux-bluetooth
In-Reply-To: <1297881972-31557-1-git-send-email-dmitriy.paliy@nokia.com>
Hi,
On Wed, Feb 16, 2011 at 8:46 PM, Dmitriy Paliy <dmitriy.paliy@nokia.com> wrote:
> A2DP sink endpoint shall not be created when using media API, if audio
> source D-Bus interface is not registered.
>
> Such fixes bluetoothd crash when SDP record is registered and remote
> device tries to connect and stream to A2DP sink which is not initialized.
> Dereferencing of NULL happens in source_new_stream since device->source
> was not created.
> ---
> audio/media.c | 9 +++++++--
> 1 files changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/audio/media.c b/audio/media.c
> index 9cfbe0e..03e1a96 100644
> --- a/audio/media.c
> +++ b/audio/media.c
> @@ -43,6 +43,7 @@
> #include "a2dp.h"
> #include "headset.h"
> #include "manager.h"
> +#include "source.h"
>
> #ifndef DBUS_TYPE_UNIX_FD
> #define DBUS_TYPE_UNIX_FD -1
> @@ -188,6 +189,7 @@ static struct media_endpoint *media_endpoint_create(struct media_adapter *adapte
> int size)
> {
> struct media_endpoint *endpoint;
> + struct audio_device *dev;
>
> endpoint = g_new0(struct media_endpoint, 1);
> endpoint->sender = g_strdup(sender);
> @@ -210,6 +212,11 @@ static struct media_endpoint *media_endpoint_create(struct media_adapter *adapte
> if (endpoint->sep == NULL)
> goto failed;
> } else if (strcasecmp(uuid, A2DP_SINK_UUID) == 0) {
> + dev = manager_find_device(NULL, &adapter->src, BDADDR_ANY,
> + AUDIO_SOURCE_INTERFACE, FALSE);
> + if (!dev)
> + goto failed;
> +
> endpoint->sep = a2dp_add_sep(&adapter->src,
> AVDTP_SEP_TYPE_SINK, codec,
> delay_reporting, endpoint);
> @@ -217,8 +224,6 @@ static struct media_endpoint *media_endpoint_create(struct media_adapter *adapte
> goto failed;
> } else if (strcasecmp(uuid, HFP_AG_UUID) == 0 ||
> g_strcmp0(uuid, HSP_AG_UUID) == 0) {
> - struct audio_device *dev;
> -
> endpoint->hs_watch = headset_add_state_cb(headset_state_changed,
> endpoint);
> dev = manager_find_device(NULL, &adapter->src, BDADDR_ANY,
I would have done it differently, we need to check if Source/Sink
interfaces are enabled not if there is any device object which
implements them (because there could be none), the best place I think
for this is directly on a2dp.c because iirc it already reads the
endpoints registered using the audio.conf e.g. SBCSinks, SBCSources,
etc so it can also check for interfaces disabled. That way
a2dp_add_sep can just return NULL if interface counterpart is disabled
and it should be propagated back as error to sender of
RegisterEndpoint.
--
Luiz Augusto von Dentz
Computer Engineer
^ permalink raw reply
* Re: [PATCH] telephony-maemo6: fix not cleaning up network status on exit
From: Johan Hedberg @ 2011-02-16 19:04 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1297867103-7310-1-git-send-email-luiz.dentz@gmail.com>
Hi Luiz,
On Wed, Feb 16, 2011, Luiz Augusto von Dentz wrote:
> This may cause indicators to not be reported correctly when adapter is
> reset.
> ---
> audio/telephony-maemo6.c | 3 +++
> 1 files changed, 3 insertions(+), 0 deletions(-)
This patch has also been pushed upstream, thanks.
Johan
^ permalink raw reply
* Re: [BUG] usb problems in .38-rc3+
From: Gustavo F. Padovan @ 2011-02-16 18:47 UTC (permalink / raw)
To: Ed Tomlinson; +Cc: linux-kernel, linux-bluetooth, linux-usb
In-Reply-To: <201102161338.00975.edt@aei.ca>
Hi Ed,
* Ed Tomlinson <edt@aei.ca> [2011-02-16 13:38:00 -0500]:
> On Wednesday 16 February 2011 09:00:53 Gustavo F. Padovan wrote:
> > Hi Ed,
> >
> > * Ed Tomlinson <edt@aei.ca> [2011-02-05 14:17:57 -0500]:
> >
> > > Hi,
> > >
> > > My bluetooth usb dongle has stopped working in .38-rc3+
> > >
> > > Bus 002 Device 008: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
> > >
> > > and in dmesg
> > >
> > > [108495.369056] usb 5-1: new full speed USB device using ohci_hcd and address 3
> > > [108495.573077] usb 5-1: New USB device found, idVendor=0a12, idProduct=0001
> > > [108495.580099] usb 5-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
> > > [108652.971977] usb 5-1: USB disconnect, address 3
> > > [108652.972718] btusb_bulk_complete: hci0 urb ffff8800684e99c0 failed to resubmit (19)
> > > [108652.973725] btusb_bulk_complete: hci0 urb ffff8800684e9c00 failed to resubmit (19)
> > > [108652.974707] btusb_intr_complete: hci0 urb ffff8800684e9840 failed to resubmit (19)
> > > [108653.001690] btusb_send_frame: hci0 urb ffff8800bb42a240 submission failed
> > > [108657.007541] usb 2-4.7: new full speed USB device using ehci_hcd and address 8
> > > [108657.147736] usb 2-4.7: New USB device found, idVendor=0a12, idProduct=0001
> > > [108657.154954] usb 2-4.7: New USB device strings: Mfr=0, Product=0, SerialNumber=0
> > >
> > > Its been working for years here.
> > >
> > > Any ideas on what to try or additional info to gather?
> >
> > What's the symptom? what do you mean by stopped to work?
>
> With .37 kernel my bluetooth apple magicmouse is detected at boot and works as expected & when
> kde 4.6 is active bluedevil sees my bluetooth adaptor. With .38-rc my bluetooth mouse is not detected
> nor does bluedevil see the bluetooth adaptor.
>
> > Can you provide me output of "hciconfig -a"?
> This gives nothing when the doogle is not plugged (it runs but prints out nothing).
>
> > And if possible enable dynamic debug for your kernel, mount the debugfs
> > and then
> >
> > echo -n "module btusb +p" > /sys/kernel/debug/dynamic_debug/control
> > echo -n "module bluetooth +p" > /sys/kernel/debug/dynamic_debug/control
>
> Hey a new debug option to enable! With it enabled and the system booted with the bluetooth doogle
> unpluged here is what happens when it gets plugged (with 38-rc5):
>
> grover ed # hciconfig -a
> hci0: Type: BR/EDR Bus: USB
> BD Address: 00:0A:3A:55:07:5A ACL MTU: 192:8 SCO MTU: 64:8
> UP RUNNING
> RX bytes:356 acl:0 sco:0 events:13 errors:0
> TX bytes:53 acl:0 sco:0 commands:13 errors:0
> Features: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
> Packet type: DM1 DH1 HV1
> Link policy:
> Link mode: SLAVE ACCEPT
> Name: 'grover-0'
> Class: 0x000000
> Service Classes: Unspecified
> Device Class: Miscellaneous,
> HCI Version: 1.1 (0x1) Revision: 0x20d
> LMP Version: 1.1 (0x1) Subversion: 0x20d
> Manufacturer: Cambridge Silicon Radio (10)
>
> and the device works. So either enabling dynamic debug, something between rc4 and rc5 or booting with the
> adaptor unplugged makes things work. Will do some more checking to figure out which.
Great that it is working now. It might be a usb bug that you had, because we
had no changes in the Bluetooth subsystem between rc4 and rc5.
But does booting with the adapter work as well?
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* [PATCH] Fix no sink SEP if source interface not registered
From: Dmitriy Paliy @ 2011-02-16 18:46 UTC (permalink / raw)
To: linux-bluetooth, luiz.dentz; +Cc: Dmitriy Paliy
A2DP sink endpoint shall not be created when using media API, if audio
source D-Bus interface is not registered.
Such fixes bluetoothd crash when SDP record is registered and remote
device tries to connect and stream to A2DP sink which is not initialized.
Dereferencing of NULL happens in source_new_stream since device->source
was not created.
---
audio/media.c | 9 +++++++--
1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/audio/media.c b/audio/media.c
index 9cfbe0e..03e1a96 100644
--- a/audio/media.c
+++ b/audio/media.c
@@ -43,6 +43,7 @@
#include "a2dp.h"
#include "headset.h"
#include "manager.h"
+#include "source.h"
#ifndef DBUS_TYPE_UNIX_FD
#define DBUS_TYPE_UNIX_FD -1
@@ -188,6 +189,7 @@ static struct media_endpoint *media_endpoint_create(struct media_adapter *adapte
int size)
{
struct media_endpoint *endpoint;
+ struct audio_device *dev;
endpoint = g_new0(struct media_endpoint, 1);
endpoint->sender = g_strdup(sender);
@@ -210,6 +212,11 @@ static struct media_endpoint *media_endpoint_create(struct media_adapter *adapte
if (endpoint->sep == NULL)
goto failed;
} else if (strcasecmp(uuid, A2DP_SINK_UUID) == 0) {
+ dev = manager_find_device(NULL, &adapter->src, BDADDR_ANY,
+ AUDIO_SOURCE_INTERFACE, FALSE);
+ if (!dev)
+ goto failed;
+
endpoint->sep = a2dp_add_sep(&adapter->src,
AVDTP_SEP_TYPE_SINK, codec,
delay_reporting, endpoint);
@@ -217,8 +224,6 @@ static struct media_endpoint *media_endpoint_create(struct media_adapter *adapte
goto failed;
} else if (strcasecmp(uuid, HFP_AG_UUID) == 0 ||
g_strcmp0(uuid, HSP_AG_UUID) == 0) {
- struct audio_device *dev;
-
endpoint->hs_watch = headset_add_state_cb(headset_state_changed,
endpoint);
dev = manager_find_device(NULL, &adapter->src, BDADDR_ANY,
--
1.7.1
^ permalink raw reply related
* Re: [BUG] usb problems in .38-rc3+
From: Ed Tomlinson @ 2011-02-16 18:38 UTC (permalink / raw)
To: Gustavo F. Padovan; +Cc: linux-kernel, linux-bluetooth, linux-usb
In-Reply-To: <20110216140053.GE14085@joana>
On Wednesday 16 February 2011 09:00:53 Gustavo F. Padovan wrote:
> Hi Ed,
>
> * Ed Tomlinson <edt@aei.ca> [2011-02-05 14:17:57 -0500]:
>
> > Hi,
> >
> > My bluetooth usb dongle has stopped working in .38-rc3+
> >
> > Bus 002 Device 008: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
> >
> > and in dmesg
> >
> > [108495.369056] usb 5-1: new full speed USB device using ohci_hcd and address 3
> > [108495.573077] usb 5-1: New USB device found, idVendor=0a12, idProduct=0001
> > [108495.580099] usb 5-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
> > [108652.971977] usb 5-1: USB disconnect, address 3
> > [108652.972718] btusb_bulk_complete: hci0 urb ffff8800684e99c0 failed to resubmit (19)
> > [108652.973725] btusb_bulk_complete: hci0 urb ffff8800684e9c00 failed to resubmit (19)
> > [108652.974707] btusb_intr_complete: hci0 urb ffff8800684e9840 failed to resubmit (19)
> > [108653.001690] btusb_send_frame: hci0 urb ffff8800bb42a240 submission failed
> > [108657.007541] usb 2-4.7: new full speed USB device using ehci_hcd and address 8
> > [108657.147736] usb 2-4.7: New USB device found, idVendor=0a12, idProduct=0001
> > [108657.154954] usb 2-4.7: New USB device strings: Mfr=0, Product=0, SerialNumber=0
> >
> > Its been working for years here.
> >
> > Any ideas on what to try or additional info to gather?
>
> What's the symptom? what do you mean by stopped to work?
With .37 kernel my bluetooth apple magicmouse is detected at boot and works as expected & when
kde 4.6 is active bluedevil sees my bluetooth adaptor. With .38-rc my bluetooth mouse is not detected
nor does bluedevil see the bluetooth adaptor.
> Can you provide me output of "hciconfig -a"?
This gives nothing when the doogle is not plugged (it runs but prints out nothing).
> And if possible enable dynamic debug for your kernel, mount the debugfs
> and then
>
> echo -n "module btusb +p" > /sys/kernel/debug/dynamic_debug/control
> echo -n "module bluetooth +p" > /sys/kernel/debug/dynamic_debug/control
Hey a new debug option to enable! With it enabled and the system booted with the bluetooth doogle
unpluged here is what happens when it gets plugged (with 38-rc5):
grover ed # hciconfig -a
hci0: Type: BR/EDR Bus: USB
BD Address: 00:0A:3A:55:07:5A ACL MTU: 192:8 SCO MTU: 64:8
UP RUNNING
RX bytes:356 acl:0 sco:0 events:13 errors:0
TX bytes:53 acl:0 sco:0 commands:13 errors:0
Features: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Packet type: DM1 DH1 HV1
Link policy:
Link mode: SLAVE ACCEPT
Name: 'grover-0'
Class: 0x000000
Service Classes: Unspecified
Device Class: Miscellaneous,
HCI Version: 1.1 (0x1) Revision: 0x20d
LMP Version: 1.1 (0x1) Subversion: 0x20d
Manufacturer: Cambridge Silicon Radio (10)
and the device works. So either enabling dynamic debug, something between rc4 and rc5 or booting with the
adaptor unplugged makes things work. Will do some more checking to figure out which.
Thanks,
Ed
^ permalink raw reply
* [PATCH 3/3] Implement generic descriptor access to Attribute API
From: Elvis Pfützenreuter @ 2011-02-16 18:13 UTC (permalink / raw)
To: linux-bluetooth; +Cc: epx
In-Reply-To: <1297880021-31728-1-git-send-email-epx@signove.com>
---
attrib/client.c | 302 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 291 insertions(+), 11 deletions(-)
diff --git a/attrib/client.c b/attrib/client.c
index 0f9ba3e..cfc8535 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -79,6 +79,15 @@ struct primary {
GSList *watchers;
};
+struct descriptor {
+ char *path;
+ uint16_t handle;
+ uuid_t uuid;
+ char type[MAX_LEN_UUID_STR + 1];
+ uint8_t *value;
+ size_t vlen;
+};
+
struct characteristic {
struct primary *prim;
char *path;
@@ -91,12 +100,14 @@ struct characteristic {
struct format *format;
uint8_t *value;
size_t vlen;
+ GSList *descriptors;
};
struct query_data {
struct primary *prim;
struct characteristic *chr;
uint16_t handle;
+ struct descriptor *descr;
};
struct watcher {
@@ -110,10 +121,22 @@ static GSList *gatt_services = NULL;
static DBusConnection *connection;
+static void descriptor_free(void *user_data)
+{
+ struct descriptor *descr = user_data;
+
+ g_free(descr->path);
+ g_free(descr->value);
+
+ g_free(descr);
+}
+
static void characteristic_free(void *user_data)
{
struct characteristic *chr = user_data;
+ g_slist_foreach(chr->descriptors, (GFunc) descriptor_free, NULL);
+
g_free(chr->path);
g_free(chr->desc);
g_free(chr->format);
@@ -188,11 +211,90 @@ static int watcher_cmp(gconstpointer a, gconstpointer b)
return g_strcmp0(watcher->path, match->path);
}
+static void add_descriptor_dict(DBusMessageIter *entry,
+ struct descriptor *descr)
+{
+ DBusMessageIter descr_dict_var;
+ DBusMessageIter descr_dict;
+ const char *uuid;
+ const uint8_t *value;
+ size_t vlen;
+
+ value = descr->value;
+ vlen = descr->vlen;
+ uuid = descr->type;
+
+ dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
+ DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &descr_dict_var);
+
+ dbus_message_iter_open_container(&descr_dict_var, 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,
+ &descr_dict);
+
+ dict_append_entry(&descr_dict, "UUID", DBUS_TYPE_STRING, &uuid);
+
+ if (value)
+ dict_append_array(&descr_dict, "Value", DBUS_TYPE_BYTE,
+ &value, vlen);
+
+ dbus_message_iter_close_container(&descr_dict_var, &descr_dict);
+ dbus_message_iter_close_container(entry, &descr_dict_var);
+}
+
+static void add_descriptors_dict(DBusMessageIter *outer_entry,
+ struct characteristic *chr)
+{
+ DBusMessageIter descrs_dict_var;
+ DBusMessageIter descrs_dict;
+ GSList *l;
+
+ dbus_message_iter_open_container(outer_entry, DBUS_TYPE_VARIANT,
+ DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &descrs_dict_var);
+
+ dbus_message_iter_open_container(&descrs_dict_var, 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,
+ &descrs_dict);
+
+ for (l = chr->descriptors; l; l = l->next) {
+ struct descriptor *descr = l->data;
+ const char *key;
+ DBusMessageIter entry;
+
+ key = descr->path;
+
+ dbus_message_iter_open_container(&descrs_dict,
+ DBUS_TYPE_DICT_ENTRY, NULL, &entry);
+
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+ add_descriptor_dict(&entry, descr);
+
+ dbus_message_iter_close_container(&descrs_dict, &entry);
+ }
+
+ dbus_message_iter_close_container(&descrs_dict_var, &descrs_dict);
+ dbus_message_iter_close_container(outer_entry, &descrs_dict_var);
+}
+
static void append_char_dict(DBusMessageIter *iter, struct characteristic *chr)
{
DBusMessageIter dict;
+ DBusMessageIter entry;
const char *name = "";
char *uuid;
+ const char *key;
dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
@@ -214,6 +316,19 @@ static void append_char_dict(DBusMessageIter *iter, struct characteristic *chr)
dict_append_array(&dict, "Value", DBUS_TYPE_BYTE, &chr->value,
chr->vlen);
+ /* Descriptors entry */
+
+ dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
+ NULL, &entry);
+
+ key = "Descriptors";
+
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+ add_descriptors_dict(&entry, chr);
+
+ dbus_message_iter_close_container(&dict, &entry);
+
/* FIXME: Missing Format, Value and Representation */
dbus_message_iter_close_container(iter, &dict);
@@ -245,6 +360,19 @@ static int characteristic_set_value(struct characteristic *chr,
return 0;
}
+static int descriptor_set_value(struct descriptor *descr,
+ const uint8_t *value, size_t vlen)
+{
+ descr->value = g_try_realloc(descr->value, vlen);
+ if (descr->value == NULL)
+ return -ENOMEM;
+
+ memcpy(descr->value, value, vlen);
+ descr->vlen = vlen;
+
+ return 0;
+}
+
static void update_watchers(gpointer data, gpointer user_data)
{
struct watcher *w = data;
@@ -483,6 +611,76 @@ static DBusMessage *set_value(DBusConnection *conn, DBusMessage *msg,
return dbus_message_new_method_return(msg);
}
+static int descriptor_path_cmp(gconstpointer a, gconstpointer b)
+{
+ const struct descriptor *descr = a;
+ const char *path = b;
+
+ return strcmp(descr->path, path);
+}
+
+static struct descriptor *find_descriptor_by_path(struct characteristic *chr,
+ const char *path)
+{
+ GSList *ldescr;
+
+ ldescr = g_slist_find_custom(chr->descriptors, path,
+ descriptor_path_cmp);
+
+ if (ldescr)
+ return ldescr->data;
+
+ return NULL;
+}
+
+static int descriptor_handle_cmp(gconstpointer a, gconstpointer b)
+{
+ const struct descriptor *descr = a;
+ uint16_t handle = GPOINTER_TO_UINT(b);
+
+ return descr->handle - handle;
+}
+
+static struct descriptor *find_descriptor_by_handle(struct characteristic *chr,
+ guint handle)
+{
+ GSList *ldescr;
+
+ ldescr = g_slist_find_custom(chr->descriptors, GUINT_TO_POINTER(handle),
+ descriptor_handle_cmp);
+
+ if (ldescr)
+ return ldescr->data;
+
+ return NULL;
+}
+
+static DBusMessage *set_descriptor(DBusConnection *conn, DBusMessage *msg,
+ struct characteristic *chr, const char *path,
+ uint8_t *value, int len)
+{
+ struct gatt_service *gatt = chr->prim->gatt;
+ GError *gerr = NULL;
+ struct descriptor *descr;
+
+ descr = find_descriptor_by_path(chr, path);
+
+ if (!descr)
+ return btd_error_invalid_args(msg);
+
+ if (l2cap_connect(gatt, &gerr, FALSE) < 0) {
+ DBusMessage *reply = btd_error_failed(msg, gerr->message);
+ g_error_free(gerr);
+ return reply;
+ }
+
+ gatt_write_cmd(gatt->attrib, descr->handle, value, len, NULL, NULL);
+
+ descriptor_set_value(descr, value, len);
+
+ return dbus_message_new_method_return(msg);
+}
+
static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg,
void *data)
{
@@ -529,10 +727,43 @@ static DBusMessage *set_property(DBusConnection *conn,
return btd_error_invalid_args(msg);
}
+static DBusMessage *set_descriptor_front(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ struct characteristic *chr = data;
+ DBusMessageIter iter;
+ DBusMessageIter sub;
+ const char *descriptor_path;
+ uint8_t *value;
+ int len;
+
+ if (!dbus_message_iter_init(msg, &iter))
+ return btd_error_invalid_args(msg);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
+ return btd_error_invalid_args(msg);
+
+ dbus_message_iter_get_basic(&iter, &descriptor_path);
+ dbus_message_iter_next(&iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
+ return btd_error_invalid_args(msg);
+
+ if (dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE)
+ return btd_error_invalid_args(msg);
+
+ dbus_message_iter_recurse(&iter, &sub);
+ dbus_message_iter_get_fixed_array(&sub, &value, &len);
+
+ return set_descriptor(conn, msg, chr, descriptor_path, value, len);
+}
+
static GDBusMethodTable char_methods[] = {
{ "GetProperties", "", "a{sv}", get_properties },
{ "SetProperty", "sv", "", set_property,
G_DBUS_METHOD_FLAG_ASYNC},
+ { "SetDescriptorValue", "oay", "", set_descriptor_front,
+ G_DBUS_METHOD_FLAG_ASYNC},
{ }
};
@@ -737,6 +968,26 @@ done:
g_free(current);
}
+static void update_descriptor(guint8 status, const guint8 *pdu, guint16 len,
+ gpointer user_data)
+{
+ struct query_data *current = user_data;
+ struct gatt_service *gatt = current->prim->gatt;
+ struct descriptor *descr = current->descr;
+
+ if (status != 0)
+ goto done;
+
+ if (len < 2)
+ goto done;
+
+ descriptor_set_value(descr, pdu + 1, len - 1);
+
+done:
+ g_attrib_unref(gatt->attrib);
+ g_free(current);
+}
+
static void update_char_value(guint8 status, const guint8 *pdu,
guint16 len, gpointer user_data)
{
@@ -762,6 +1013,31 @@ static void update_char_value(guint8 status, const guint8 *pdu,
g_free(current);
}
+static struct descriptor *char_add_descriptor(struct characteristic *chr,
+ uint16_t handle, uuid_t uuid)
+{
+ struct descriptor *descr;
+
+ descr = find_descriptor_by_handle(chr, handle);
+
+ if (!descr) {
+ descr = g_new0(struct descriptor, 1);
+ descr->path = g_strdup_printf("%s/descriptor%04x",
+ chr->path, handle);
+ descr->handle = handle;
+ chr->descriptors = g_slist_append(chr->descriptors, descr);
+ }
+
+ if (sdp_uuid_cmp(&uuid, &descr->uuid) != 0) {
+ char *uuidstr = bt_uuid2string(&uuid);
+ strcpy(descr->type, uuidstr);
+ g_free(uuidstr);
+ descr->uuid = uuid;
+ }
+
+ return descr;
+}
+
static int uuid_desc16_cmp(uuid_t *uuid, guint16 desc)
{
uuid_t u16;
@@ -783,7 +1059,7 @@ static void descriptor_cb(guint8 status, const guint8 *pdu, guint16 plen,
if (status != 0)
goto done;
- DBG("Find Information Response received");
+ DBG("Discover Descriptors Response received");
list = dec_find_info_resp(pdu, plen, &format);
if (list == NULL)
@@ -797,15 +1073,14 @@ static void descriptor_cb(guint8 status, const guint8 *pdu, guint16 plen,
handle = att_get_u16(info);
- if (format == 0x01) {
+ if (format == 0x01)
sdp_uuid16_create(&uuid, att_get_u16(&info[2]));
- } else {
- /* Currently, only "user description" and "presentation
- * format" descriptors are used, and both have 16-bit
- * UUIDs. Therefore there is no need to support format
- * 0x02 yet. */
+ else if (format == 0x02)
+ // FIXME use att_get_u128
+ sdp_uuid128_create(&uuid, &info[2]);
+ else
continue;
- }
+
qfmt = g_new0(struct query_data, 1);
qfmt->prim = current->prim;
qfmt->chr = current->chr;
@@ -819,8 +1094,13 @@ static void descriptor_cb(guint8 status, const guint8 *pdu, guint16 plen,
gatt->attrib = g_attrib_ref(gatt->attrib);
gatt_read_char(gatt->attrib, handle,
update_char_format, qfmt);
- } else
- g_free(qfmt);
+ } else {
+ qfmt->descr = char_add_descriptor(current->chr, handle,
+ uuid);
+ gatt->attrib = g_attrib_ref(gatt->attrib);
+ gatt_read_char(gatt->attrib, handle, update_descriptor,
+ qfmt);
+ }
}
att_data_list_free(list);
@@ -888,7 +1168,7 @@ static void char_discovered_cb(GSList *characteristics, guint8 status,
strncpy(chr->type, current_chr->uuid, sizeof(chr->type));
if (previous_end)
- *previous_end = current_chr->handle;
+ *previous_end = current_chr->handle - 1;
previous_end = &chr->end;
--
1.7.1
^ permalink raw reply related
* [PATCH 2/3] Add generic descriptor support to Attribute API document
From: Elvis Pfützenreuter @ 2011-02-16 18:13 UTC (permalink / raw)
To: linux-bluetooth; +Cc: epx
In-Reply-To: <1297880021-31728-1-git-send-email-epx@signove.com>
This patch proposes extensions to Attribute API, giving access to all
characteristic descriptors (beyond 'Description' and 'Format').
---
doc/attribute-api.txt | 28 ++++++++++++++++++++++++++++
1 files changed, 28 insertions(+), 0 deletions(-)
diff --git a/doc/attribute-api.txt b/doc/attribute-api.txt
index 23808e6..5ee189e 100644
--- a/doc/attribute-api.txt
+++ b/doc/attribute-api.txt
@@ -104,6 +104,14 @@ Methods dict GetProperties()
Possible Errors: org.bluez.Error.InvalidArguments
+ void SetDescriptorValue(object descriptor, array{byte} value)
+
+ Sets descriptor value, provided that it is writable.
+
+ Possible Errors: org.bluez.Error.InvalidArguments
+ org.bluez.Error.NotAuthorized
+
+
Properties string UUID [readonly]
UUID128 of this characteristic.
@@ -143,6 +151,26 @@ Properties string UUID [readonly]
Friendly representation of the Characteristic Value
based on the format attribute.
+ dict Descriptors [readonly]
+
+ List of descriptors for this characteristic.
+
+ This list contains only the descriptors not already
+ covered by other properties (v.g. Description, Format).
+
+ Each descriptor is mapped to an unique object path,
+ which is the key for the dict.
+
+ Each dict value is, in turn, a dict with at least
+ the following keys:
+
+ {
+ "UUID": string (descriptor UUID - mandatory),
+ "Value": array of bytes (raw descriptor value -
+ optional, shows up when value can be
+ fetched)
+ }
+
Characteristic Watcher hierarchy
===============================
--
1.7.1
^ permalink raw reply related
* [PATCH 1/3] Add UUID property to GATT service object
From: Elvis Pfützenreuter @ 2011-02-16 18:13 UTC (permalink / raw)
To: linux-bluetooth; +Cc: epx
---
attrib/client.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/attrib/client.c b/attrib/client.c
index ec5fcf2..0f9ba3e 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -941,6 +941,7 @@ static DBusMessage *prim_get_properties(DBusConnection *conn, DBusMessage *msg,
DBusMessageIter dict;
GSList *l;
char **chars;
+ const char *uuid;
int i;
reply = dbus_message_new_method_return(msg);
@@ -963,6 +964,9 @@ static DBusMessage *prim_get_properties(DBusConnection *conn, DBusMessage *msg,
dict_append_array(&dict, "Characteristics", DBUS_TYPE_OBJECT_PATH,
&chars, i);
+ uuid = prim->att->uuid;
+ dict_append_entry(&dict, "UUID", DBUS_TYPE_STRING, &uuid);
+
g_free(chars);
dbus_message_iter_close_container(&iter, &dict);
--
1.7.1
^ permalink raw reply related
* Re: [RFC 2/7] Use memcpy to convert from network to host order on BE hosts
From: Anderson Lizardo @ 2011-02-16 17:02 UTC (permalink / raw)
To: Claudio Takahasi; +Cc: linux-bluetooth
In-Reply-To: <1297456626-22837-3-git-send-email-claudio.takahasi@openbossa.org>
Hi Claudio,
On Fri, Feb 11, 2011 at 5:37 PM, Claudio Takahasi
<claudio.takahasi@openbossa.org> wrote:
> ---
> lib/bluetooth.h | 4 +---
> 1 files changed, 1 insertions(+), 3 deletions(-)
>
> diff --git a/lib/bluetooth.h b/lib/bluetooth.h
> index bc020ad..d8f36f8 100644
> --- a/lib/bluetooth.h
> +++ b/lib/bluetooth.h
> @@ -127,9 +127,7 @@ static inline void btoh128(const uint128_t *src, uint128_t *dst)
> #define ntoh64(x) (x)
> static inline void ntoh128(const uint128_t *src, uint128_t *dst)
> {
> - int i;
> - for (i = 0; i < 16; i++)
> - dst->data[i] = src->data[i];
> + memcpy(dst, src, sizeof(uint128_t));
> }
I believe this patch is harmless and can be already applied
independently from other patches on this series, right?
Regards,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil
^ permalink raw reply
* Re: [PATCH 2/3] Add SDP registration of Primary GATT services
From: Anderson Lizardo @ 2011-02-16 17:00 UTC (permalink / raw)
To: Brian Gix; +Cc: linux-bluetooth, johan.hedberg, padovan
In-Reply-To: <4D5BFAB8.7030608@codeaurora.org>
Hi Brian,
On Wed, Feb 16, 2011 at 1:26 PM, Brian Gix <bgix@codeaurora.org> wrote:
> 1. We currently register everything into the attribute database a single
> attribute at a time. The current attrib_db_add therefore has no inherent
> knowledge of entire "Service" objects, and lacks the start-end range that is
> required not only by the SDP record, but also the ATT driven GATT Service
> Discovery. Ideally I would like to see a "Register Service" API which
> internally would register all INCLUDES, CHARACTERISTICS, and SDP Records,
> but this would be a significant departure from the current code.
You are right. In fact, we have a proposal (currently not implemented)
to create a server side API for registering GATT services. Please see
my e-mail from 2010-12-30 entitled "[RFC] BlueZ server side API for
registering GATT services". I was actually expecting comments from you
:)
Suggestions/comments on the proposal are welcome. Please try to keep
discussion on this topic here on the list because there are other
people interested on contributing to the implementation as well.
ALso note the proposal is to create an API on top of the current one,
with minimal changes to allow both to be used in parallel (it may be
necessary in cases we want more control over the attributes).
> 2. A less significant change would be to create an sdp_record_from_attrib()
> API, but it would need to be called after all attributes for the service
> have been registered, because it needs to calculate the "end" handle of the
> service, much like the current GATT procedures to Discover and Find
> Services. This would probably constitute the "least change necessary" to the
> current paradigm.
This is my suggestion on this thread. After the attributes of a
specific service have been inserted into the database, you can know
the start-end attributes.
> 3. I'm not sure that the "struct attrib *a" would add anything here, except
> as a way to prevent having to explicitly specify the attribute handle value
> in the first place. We should eventually get away from specifying explicit
> attribute handle values, because that makes it hard to have mix-and-match
> services. A service app writer should not be expected to know the remaining
> 0-65535 "number space" that is available on every device that they want to
> target there service app to. In that respect, having attrib_db_add assign
> an available handle, and return a "struct attrib *" pointer could then be
> used instead of a handle when registering the SDP of a completely registered
> primary service.
What I had in mind (still not discussed on the list), was to make the
"automatic handle allocation" feature together with the high-level
GATT Service oriented API. This would work by keeping track of
used/unused start-end ranges, and allocating ranges for services as
they are registered/unregistered. Example:
* "free range list" starts with: [0x1000, 0xFFFF]
* Register service A with 10 attributes: [0x1000, 0x1009] (free range:
[0x100A, 0xFFFF])
* Register service B with 5 attributes: [0x100A, 0x100E] (free range:
[0x100F, 0xFFFF])
* Register service C with 11 attributes: [0x100F, 0x1019] (free range:
[0x101A, 0xFFFF])
* Unregister service B (free ranges: [0x100A, 0x100E], [0x101A, 0xFFFF])
* Register service D with 4 attributes: [0x100A, 0x100D] (free ranges:
[0x100E, 0x100E], [0x101A, 0xFFFF])
> I propose that I change this patch set to follow plan "2" above. If you
> want to subsequently change the return of attrib_db_add() as you have
> described, it should then be trivial to change the arguments to the new
> sdp_record_from_attrib() API to accept the attrib struct pointer rather than
> the explicit start handle.
Agreed. sdp_record_from_attrib() may receive just start/end handles if
other fields of struct attrubute are not necessary.
>>> @@ -609,7 +603,7 @@ static uint16_t write_value(struct gatt_channel
>>> *channel, uint16_t handle,
>>> static uint16_t mtu_exchange(struct gatt_channel *channel, uint16_t mtu,
>>> uint8_t *pdu, int len)
>>> {
>>> - channel->mtu = MIN(mtu, ATT_MAX_MTU);
>>> + channel->mtu = MIN(mtu, channel->mtu);
>>>
>>> return enc_mtu_resp(channel->mtu, pdu, len);
>>> }
>>
>> This change looks unrelated to the patch.
Any comments on this?
Regards,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil
^ permalink raw reply
* Re: [PATCH 3/3] Add gatttool enhancements for UPF
From: Anderson Lizardo @ 2011-02-16 16:38 UTC (permalink / raw)
To: Brian Gix; +Cc: linux-bluetooth, johan.hedberg, padovan
In-Reply-To: <4D5BF2E1.6070102@codeaurora.org>
Hi Brian,
On Wed, Feb 16, 2011 at 12:53 PM, Brian Gix <bgix@codeaurora.org> wrote:
> Hi Anderson,
>
> The modifications to gatttool were largely organic in nature and on the fly
> responses to the needs of my UPF testing. Also, it is of course just a test
> tool.
Understood, but if you could split these changes into more "logic"
pieces (separate commits), with commit messages which explain the
reasoning of the change (e.g. the answers on this thread), it will be
nice.
Regards,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil
^ permalink raw reply
* Re: [PATCH 2/3] Add SDP registration of Primary GATT services
From: Brian Gix @ 2011-02-16 16:26 UTC (permalink / raw)
To: Anderson Lizardo; +Cc: linux-bluetooth, johan.hedberg, padovan
In-Reply-To: <AANLkTikCnorqDid1cRYmCm=-Jq04K67wJOHpOdWE8Pn+@mail.gmail.com>
Hi Anderson,
On 2/14/2011 1:53 PM, Anderson Lizardo wrote:
> On Wed, Feb 16, 2011 at 6:18 PM, Brian Gix<bgix@codeaurora.org> wrote:
>> SDP registration can be supressed by passing Zero as the end
>> handle argument to attrib_db_add().
>> ---
>> attrib/example.c | 119 +++++++++++++++++++++++++++++++------------
>> src/attrib-server.c | 139 +++++++++++++++++++++++++++++++++++----------------
>> src/attrib-server.h | 6 ++-
>> 3 files changed, 184 insertions(+), 80 deletions(-)
>>
>> diff --git a/attrib/example.c b/attrib/example.c
>> index 1911912..eab3c0f 100644
>> --- a/attrib/example.c
>> +++ b/attrib/example.c
>> @@ -31,6 +31,7 @@
>>
>> #include<bluetooth/sdp.h>
>> #include<bluetooth/sdp_lib.h>
>> +#include<src/sdpd.h>
>>
>> #include<glib.h>
>>
>> @@ -59,6 +60,9 @@
>> #define FMT_KILOGRAM_UUID 0xA010
>> #define FMT_HANGING_UUID 0xA011
>>
>> +#define SDP_RECORD_COUNT 10
>> +sdp_record_t *sdp_records[SDP_RECORD_COUNT];
>> +
>> static int register_attributes(void)
>> {
>> const char *desc_out_temp = "Outside Temperature";
>> @@ -77,59 +81,73 @@ static int register_attributes(void)
>> uint8_t atval[256];
>> uuid_t uuid;
>> int len;
>> + int i = 0;
>>
>> /* Battery state service: primary service definition */
>> sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
>> att_put_u16(BATTERY_STATE_SVC_UUID,&atval[0]);
>> - attrib_db_add(0x0100,&uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
>> + sdp_records[i++] = attrib_db_add(0x0100, 0x0111,&uuid,
>> + "Battery State Service",
>> + ATT_NONE, ATT_NOT_PERMITTED,
>> + atval, 2);
>
> What if instead of changing attrib_db_add() signature to return a SDP
> record, you create a "sdp_record_from_attrib()" for this purpose? This
> function could get the struct attribute * pointers for start/end.
>
> There are plans for attrib_db_add() to return the created struct
> attribute *a (as shown in a patch I sent sometime ago which I still
> need to resend), I can send an updated version of that patch if you
> agree to this approach.
I was considering an approach like this during UPF but abandoned it for
lack of time. There are few hours available to make hot fixes during
these events, and I just learned of the requirement for SDP records in
"real time".
However, here are the issues as I see them:
1. We currently register everything into the attribute database a single
attribute at a time. The current attrib_db_add therefore has no
inherent knowledge of entire "Service" objects, and lacks the start-end
range that is required not only by the SDP record, but also the ATT
driven GATT Service Discovery. Ideally I would like to see a "Register
Service" API which internally would register all INCLUDES,
CHARACTERISTICS, and SDP Records, but this would be a significant
departure from the current code.
2. A less significant change would be to create an
sdp_record_from_attrib() API, but it would need to be called after all
attributes for the service have been registered, because it needs to
calculate the "end" handle of the service, much like the current GATT
procedures to Discover and Find Services. This would probably constitute
the "least change necessary" to the current paradigm.
3. I'm not sure that the "struct attrib *a" would add anything here,
except as a way to prevent having to explicitly specify the attribute
handle value in the first place. We should eventually get away from
specifying explicit attribute handle values, because that makes it hard
to have mix-and-match services. A service app writer should not be
expected to know the remaining 0-65535 "number space" that is available
on every device that they want to target there service app to. In that
respect, having attrib_db_add assign an available handle, and return a
"struct attrib *" pointer could then be used instead of a handle when
registering the SDP of a completely registered primary service.
I propose that I change this patch set to follow plan "2" above. If you
want to subsequently change the return of attrib_db_add() as you have
described, it should then be trivial to change the arguments to the new
sdp_record_from_attrib() API to accept the attrib struct pointer rather
than the explicit start handle.
>
>> @@ -609,7 +603,7 @@ static uint16_t write_value(struct gatt_channel *channel, uint16_t handle,
>> static uint16_t mtu_exchange(struct gatt_channel *channel, uint16_t mtu,
>> uint8_t *pdu, int len)
>> {
>> - channel->mtu = MIN(mtu, ATT_MAX_MTU);
>> + channel->mtu = MIN(mtu, channel->mtu);
>>
>> return enc_mtu_resp(channel->mtu, pdu, len);
>> }
>
> This change looks unrelated to the patch.
>
> Regards,
--
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
^ permalink raw reply
* Re: [PATCH 3/3] Add gatttool enhancements for UPF
From: Brian Gix @ 2011-02-16 15:53 UTC (permalink / raw)
To: Anderson Lizardo; +Cc: linux-bluetooth, johan.hedberg, padovan
In-Reply-To: <AANLkTi=dwj0Bc_509JW8-HfkYBfzmfSzR0GJxNqoLXye@mail.gmail.com>
Hi Anderson,
The modifications to gatttool were largely organic in nature and on the
fly responses to the needs of my UPF testing. Also, it is of course just
a test tool.
More inline.
On 2/14/2011 1:41 PM, Anderson Lizardo wrote:
> Hi Brian,
>
> On Wed, Feb 16, 2011 at 6:18 PM, Brian Gix<bgix@codeaurora.org> wrote:
>> @@ -90,9 +91,9 @@ static GIOChannel *do_connect(gboolean le)
>>
>> /* This check is required because currently setsockopt() returns no
>> * errors for MTU values smaller than the allowed minimum. */
>> - if (opt_mtu != 0&& opt_mtu< ATT_MIN_MTU_L2CAP) {
>> + if (opt_mtu != 0&& opt_mtu< 23) {
>> g_printerr("MTU cannot be smaller than %d\n",
>> - ATT_MIN_MTU_L2CAP);
>> + 23);
>> return NULL;
>> }
>
> The changes above seem unrelated to this patch.
The code was incorrect in that it limited it to 48 instead of 23.
However, I should have used the ATT_MIN_MTU_LE define. This will be fixed.
>
>>
>> @@ -277,6 +278,14 @@ static gboolean characteristics(gpointer user_data)
>> return FALSE;
>> }
>>
>> +static void char_write_cb(guint8 status, const guint8 *pdu, guint16 plen,
>> + gpointer user_data)
>> +{
>> + if (plen == 1)
>> + g_print("Attrib Write Succeeded\n");
>> + else
>> + g_printerr("Attrib Write failed: %s\n", att_ecode2str(status));
>
> Why not check by the status instead of plen ?
During testing, it was apparent that status did not contain Zero. This
may be due to there being no status octet in the WRITE_RSP packet. I
didn't have time to trace this back into the gatt code, but will do so now.
>
> Also, I'd suggest "Characteristic write" instead of "Attrib Write".
>
>> +}
>> static void char_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
>> gpointer user_data)
>> {
>> @@ -427,7 +436,40 @@ static gboolean characteristics_write(gpointer user_data)
>> goto error;
>> }
>>
>> + gatt_write_char(attrib, opt_handle, value, len, char_write_cb, value);
>> + gatt_read_char(attrib, opt_handle, char_read_cb, attrib);
>
> Why both read and write ?
I needed to do this to confirm that the write actually succeeded within
the bounds of the testing, which included not dropping the connection
between the two procedures. This will not be needed for the forthcoming
interactive gatttool, but that was not available for UPF. As it is, I
would argue that this is more useful in a test tool than superfluous.
>
>> +
>> + return FALSE;
>> +
>> +error:
>> + g_main_loop_quit(event_loop);
>> + return FALSE;
>> +}
>> +
>> +static gboolean characteristics_cmd(gpointer user_data)
>> +{
>> + GAttrib *attrib = user_data;
>> + uint8_t *value;
>> + size_t len;
>> +
>> + if (opt_handle<= 0) {
>> + g_printerr("A valid handle is required\n");
>> + goto error;
>> + }
>> +
>> + if (opt_value == NULL || opt_value[0] == '\0') {
>> + g_printerr("A value is required\n");
>> + goto error;
>> + }
>> +
>> + len = attr_data_from_string(opt_value,&value);
>> + if (len == 0) {
>> + g_printerr("Invalid value\n");
>> + goto error;
>> + }
>> +
>> gatt_write_cmd(attrib, opt_handle, value, len, mainloop_quit, value);
>> + gatt_read_char(attrib, opt_handle, char_read_cb, attrib);
>
> Same question here.
Same response here.
>
>>
>> return FALSE;
>>
>> @@ -531,6 +573,8 @@ static GOptionEntry gatt_options[] = {
>> "Characteristics Value/Descriptor Read", NULL },
>> { "char-write", 0, 0, G_OPTION_ARG_NONE,&opt_char_write,
>> "Characteristics Value Write", NULL },
>> + { "char-cmd", 0, 0, G_OPTION_ARG_NONE,&opt_char_cmd,
>> + "Characteristics Value Cmd", NULL },
>
> Suggestion: "Characteristic Value write using Write Command" (or
> something similar).
>
>> { "char-desc", 0, 0, G_OPTION_ARG_NONE,&opt_char_desc,
>> "Characteristics Descriptor Discovery", NULL },
>> { "listen", 0, 0, G_OPTION_ARG_NONE,&opt_listen,
>> @@ -561,7 +605,7 @@ int main(int argc, char *argv[])
>> GError *gerr = NULL;
>> GAttrib *attrib;
>> GIOChannel *chan;
>> - GSourceFunc callback;
>> + GSourceFunc callback = NULL;
>>
>> context = g_option_context_new(NULL);
>> g_option_context_add_main_entries(context, options, NULL);
>> @@ -602,9 +646,11 @@ int main(int argc, char *argv[])
>> callback = characteristics_read;
>> else if (opt_char_write)
>> callback = characteristics_write;
>> + else if (opt_char_cmd)
>> + callback = characteristics_cmd;
>> else if (opt_char_desc)
>> callback = characteristics_desc;
>> - else {
>> + else if (!opt_listen) {
>> gchar *help = g_option_context_get_help(context, TRUE, NULL);
>> g_print("%s\n", help);
>> g_free(help);
>> @@ -625,7 +671,8 @@ int main(int argc, char *argv[])
>> if (opt_listen)
>> g_idle_add(listen_start, attrib);
>>
>> - g_idle_add(callback, attrib);
>> + if (callback)
>> + g_idle_add(callback, attrib);
>>
>> g_main_loop_run(event_loop);
>
> Regards,
--
Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
^ permalink raw reply
* Re: bluetooth disabled with current 2.6.38-rc4
From: Justin Mattock @ 2011-02-16 15:34 UTC (permalink / raw)
To: Gustavo F. Padovan; +Cc: Johan Hedberg, linux-bluetooth
In-Reply-To: <20110216133411.GD14085@joana>
On Feb 16, 2011, at 5:34 AM, Gustavo F. Padovan wrote:
> Hi Justin,
>
> * Justin Mattock <justinmattock@gmail.com> [2011-02-15 19:26:12
> -0800]:
>
>>
>> On Feb 15, 2011, at 5:52 AM, Johan Hedberg wrote:
>>
>>> Hi Justin,
>>>
>>> On Sun, Feb 13, 2011, Justin Mattock wrote:
>>>> maybe I missed something, but my bluetooth is just not functioning
>>>> with
>>>> 2.6.38-rc4(works with 2.6.37-rc4)
>>>>
>>>> I've done a bisect on this, but was pointed to:
>>>> c0e45c1ca3162acb2e77b3d9e152ce6e7b6fa3f5
>>>> but doesn't look correct to me
>>>>
>>>> here is what I am seeing with the bluetooth-applet etc..:
>>>>
>>>> working correctly:
>>>> http://www.flickr.com/photos/44066293@N08/5443727238/
>>>>
>>>> not working:
>>>> http://www.flickr.com/photos/44066293@N08/5443124859/
>>>>
>>>> my /var/log/daemon.log shows:
>>>>
>>>> Feb 13 17:12:22 Linux-2 acpid: 1 client rule loaded
>>>> Feb 13 17:12:23 Linux-2 bluetoothd[1950]: HCI dev 0 registered
>>>> Feb 13 17:12:23 Linux-2 bluetoothd[1950]: Listening for HCI events
>>>> on hci0
>>>> Feb 13 17:12:23 Linux-2 bluetoothd[1950]: HCI dev 0 up
>>>> Feb 13 17:12:23 Linux-2 bluetoothd[1950]: Unable to find matching
>>>> adapter
>>>>
>>>> I can try at another bisect, but might take some time.. let me know
>>>> if there is something I can test
>>>> or do.
>>>
>>> Are you sure this is a kernel problem? There was a similar issue
>>> with
>>> BlueZ 4.86 or 4.87 which was already fixed. Could you try with 4.88?
>>>
>>> Johan
>>
>> o.k. I built 4.88 and still had the issue show up, except this time
>> no
>> icon(instead of the icon, that is not lit up)..
>>
>>
>> anyways I did do another bisect and had better results(hopefully)this
>> time..:
>>
>> 23bb57633df97ede067ea26f3cdc8a7ba2cd8109 is the first bad commit
>> commit 23bb57633df97ede067ea26f3cdc8a7ba2cd8109
>> Author: Johan Hedberg <johan.hedberg@nokia.com>
>> Date: Tue Dec 21 23:01:27 2010 +0200
>>
>> Bluetooth: Fix __hci_request synchronization for hci_open_dev
>>
>> The initialization function used by hci_open_dev (hci_init_req)
>> sends
>> many different HCI commands. The __hci_request function should
>> only
>> return when all of these commands have completed (or a timeout
>> occurs).
>> Several of these commands cause hci_req_complete to be called
>> which
>> causes __hci_request to return prematurely.
>>
>> This patch fixes the issue by adding a new hdev->req_last_cmd
>> variable
>> which is set during the initialization procedure. The
>> hci_req_complete
>> function will no longer mark the request as complete until the
>> command
>> matching hdev->req_last_cmd completes.
>>
>> Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
>> Acked-by: Marcel Holtmann <marcel@holtmann.org>
>> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
>>
>> :040000 040000 e8d8ae5fab74b2ba73d0c52e7e09b30e5df8484e
>> 8d1409e8dc2206492cb86e8848c8c23aff182e2a M include
>> :040000 040000 07fdb5f6ceadcfde12c46a3b5c82937b7dac892c
>> 8f3b08fbbc9fcd078d0f5224b8bc818eeb072dc4 M net
>
> Can you please send the hcidump output? There should be a package
> for it in
> your distribution, if not get the bluez-hcidump from git.kernel.org
>
> --
> Gustavo F. Padovan
> http://profusion.mobi
o.k...keep in mind I hve never really used that tool, but here goes:
HCI sniffer - Bluetooth packet analyzer ver 2.0
device: hci0 snap_len: 1028 filter: 0xffffffffffffffff
> ACL data: handle 46 flags 0x02 dlen 12
L2CAP(d): cid 0x0041 len 8 [psm 0]
A1 02 00 11 FD 00 00 00
> ACL data: handle 46 flags 0x02 dlen 12
L2CAP(d): cid 0x0041 len 8 [psm 0]
A1 02 00 0A FF 00 00 00
> ACL data: handle 46 flags 0x02 dlen 12
L2CAP(d): cid 0x0041 len 8 [psm 0]
A1 02 00 1B FC 00 00 00
> ACL data: handle 46 flags 0x02 dlen 12
L2CAP(d): cid 0x0041 len 8 [psm 0]
A1 02 00 22 FE 00 00 00
> ACL data: handle 46 flags 0x02 dlen 12
L2CAP(d): cid 0x0041 len 8 [psm 0]
A1 02 00 27 FF 00 00 00
> ACL data: handle 46 flags 0x02 dlen 12
L2CAP(d): cid 0x0041 len 8 [psm 0]
A1 02 00 15 FF 00 00 00
> ACL data: handle 46 flags 0x02 dlen 12
L2CAP(d): cid 0x0041 len 8 [psm 0]
A1 02 00 2C 00 00 00 00
> ACL data: handle 46 flags 0x02 dlen 12
L2CAP(d): cid 0x0041 len 8 [psm 0]
A1 02 00 2B 00 00 00 00
> ACL data: handle 46 flags 0x02 dlen 12
L2CAP(d): cid 0x0041 len 8 [psm 0]
A1 02 00 14 FF 00 00 00
> ACL data: handle 46 flags 0x02 dlen 12
L2CAP(d): cid 0x0041 len 8 [psm 0]
A1 02 00 21 FD 00 00 00
> ACL data: handle 46 flags 0x02 dlen 12
L2CAP(d): cid 0x0041 len 8 [psm 0]
A1 02 00 18 FB 00 00 00
> ACL data: handle 46 flags 0x02 dlen 12
L2CAP(d): cid 0x0041 len 8 [psm 0]
A1 02 00 09 FD 00 00 00
> ACL data: handle 46 flags 0x02 dlen 12
L2CAP(d): cid 0x0041 len 8 [psm 0]
A1 02 00 0C FC 00 00 00
> ACL data: handle 46 flags 0x02 dlen 12
L2CAP(d): cid 0x0041 len 8 [psm 0]
A1 02 00 04 FE 00 00 00
> ACL data: handle 46 flags 0x02 dlen 12
L2CAP(d): cid 0x0041 len 8 [psm 0]
Justin P. Mattock
^ 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