* [PATCH 1/2] Fix not fetching current usb mode when obexd starts
From: Luiz Augusto von Dentz @ 2011-01-28 13:17 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
Cable may be already plugged when obexd starts
---
plugins/usb.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 59 insertions(+), 6 deletions(-)
diff --git a/plugins/usb.c b/plugins/usb.c
index 949e94f..580e7b8 100644
--- a/plugins/usb.c
+++ b/plugins/usb.c
@@ -173,20 +173,27 @@ static void sig_usb(int sig)
{
}
+static void usb_set_mode(struct obex_server *server, const char *mode)
+{
+ DBG("%s", mode);
+
+ if (g_str_equal(mode, "ovi_suite") == TRUE)
+ usb_connect(server);
+ else if (g_str_equal(mode, "USB disconnected") == TRUE)
+ usb_disconnect(server);
+}
+
static gboolean handle_signal(DBusConnection *connection,
DBusMessage *message, void *user_data)
{
struct obex_server *server = user_data;
- const char *state;
+ const char *mode;
dbus_message_get_args(message, NULL,
- DBUS_TYPE_STRING, &state,
+ DBUS_TYPE_STRING, &mode,
DBUS_TYPE_INVALID);
- if (g_str_equal(state, "ovi_suite") == TRUE)
- usb_connect(server);
- else if (g_str_equal(state, "USB disconnected") == TRUE)
- usb_disconnect(server);
+ usb_set_mode(server, mode);
return TRUE;
}
@@ -197,18 +204,64 @@ static void usb_stop(void *data)
g_source_remove(id);
}
+static void mode_request_reply(DBusPendingCall *call, void *user_data)
+{
+ struct obex_server *server = user_data;
+ DBusMessage *reply = dbus_pending_call_steal_reply(call);
+ DBusError derr;
+
+ dbus_error_init(&derr);
+ if (dbus_set_error_from_message(&derr, reply)) {
+ error("usb: Replied with an error: %s, %s",
+ derr.name, derr.message);
+ dbus_error_free(&derr);
+ } else {
+ const char *mode;
+ dbus_message_get_args(reply, NULL,
+ DBUS_TYPE_STRING, &mode,
+ DBUS_TYPE_INVALID);
+
+ usb_set_mode(server, mode);
+ }
+
+ dbus_message_unref(reply);
+}
+
static void *usb_start(struct obex_server *server, int *err)
{
guint id;
+ DBusMessage *msg;
+ DBusPendingCall *call;
+
+ msg = dbus_message_new_method_call("com.meego.usb_moded",
+ "/com/meego/usb_moded",
+ "com.meego.usb_moded",
+ "mode_request");
+
+ if (dbus_connection_send_with_reply(connection,
+ msg, &call, -1) == FALSE) {
+ error("usb: unable to send mode_request");
+ goto fail;
+ }
+
+ dbus_pending_call_set_notify(call, mode_request_reply, server, NULL);
+ dbus_pending_call_unref(call);
id = g_dbus_add_signal_watch(connection, NULL, NULL,
"com.meego.usb_moded",
"sig_usb_state_ind",
handle_signal, server, NULL);
+
if (err != NULL)
*err = 0;
return GUINT_TO_POINTER(id);
+
+fail:
+ if (err != NULL)
+ *err = -1;
+
+ return NULL;
}
static struct obex_transport_driver driver = {
--
1.7.1
^ permalink raw reply related
* [PATCH 2/2] Fix using g_source_remove intead of g_dbus_remove_watch
From: Luiz Augusto von Dentz @ 2011-01-28 13:17 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1296220659-24165-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
Watches created with g_dbus_add_signal_watch cannot be removed with
g_source_remove.
---
plugins/usb.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/plugins/usb.c b/plugins/usb.c
index 580e7b8..466dc99 100644
--- a/plugins/usb.c
+++ b/plugins/usb.c
@@ -201,7 +201,7 @@ static gboolean handle_signal(DBusConnection *connection,
static void usb_stop(void *data)
{
guint id = GPOINTER_TO_UINT(data);
- g_source_remove(id);
+ g_dbus_remove_watch(connection, id);
}
static void mode_request_reply(DBusPendingCall *call, void *user_data)
--
1.7.1
^ permalink raw reply related
* Re: [PATCH 2/2] Fix using g_source_remove intead of g_dbus_remove_watch
From: Johan Hedberg @ 2011-01-28 13:29 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1296220659-24165-2-git-send-email-luiz.dentz@gmail.com>
Hi Luiz,
On Fri, Jan 28, 2011, Luiz Augusto von Dentz wrote:
> Watches created with g_dbus_add_signal_watch cannot be removed with
> g_source_remove.
> ---
> plugins/usb.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
Both patches have been pushed upstream. Thanks.
Johan
^ permalink raw reply
* [RFC] hcitool: automatic flush timeout support
From: Emeltchenko Andrei @ 2011-01-28 13:39 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
---
lib/hci.c | 54 ++++++++++++++++++++++++++++++++++
lib/hci.h | 19 ++++++++++++
lib/hci_lib.h | 2 +
tools/hcitool.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 161 insertions(+), 0 deletions(-)
diff --git a/lib/hci.c b/lib/hci.c
index 048fda4..533512e 100644
--- a/lib/hci.c
+++ b/lib/hci.c
@@ -2569,6 +2569,60 @@ int hci_read_rssi(int dd, uint16_t handle, int8_t *rssi, int to)
return 0;
}
+int hci_read_flush_timeout(int dd, uint16_t handle, uint16_t *timeout, int to)
+{
+ read_flush_timeout_rp rp;
+ struct hci_request rq;
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_HOST_CTL;
+ rq.ocf = OCF_READ_AUTOMATIC_FLUSH_TIMEOUT;
+ rq.cparam = &handle;
+ rq.clen = READ_FLUSH_TIMEOUT_CP_SIZE;
+ rq.rparam = &rp;
+ rq.rlen = READ_FLUSH_TIMEOUT_RP_SIZE;
+
+ if (hci_send_req(dd, &rq, to) < 0)
+ return -1;
+
+ if (rp.status) {
+ errno = EIO;
+ return -1;
+ }
+
+ *timeout = rp.flush_timeout;
+ return 0;
+}
+
+int hci_write_flush_timeout(int dd, uint16_t handle, uint16_t timeout, int to)
+{
+ write_flush_timeout_cp cp;
+ write_flush_timeout_rp rp;
+ struct hci_request rq;
+
+ memset(&cp, 0, sizeof(cp));
+ cp.handle = handle;
+ cp.flush_timeout = timeout;
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_HOST_CTL;
+ rq.ocf = OCF_WRITE_AUTOMATIC_FLUSH_TIMEOUT;
+ rq.cparam = &cp;
+ rq.clen = WRITE_FLUSH_TIMEOUT_CP_SIZE;
+ rq.rparam = &rp;
+ rq.rlen = WRITE_FLUSH_TIMEOUT_RP_SIZE;
+
+ if (hci_send_req(dd, &rq, to) < 0)
+ return -1;
+
+ if (rp.status) {
+ errno = EIO;
+ return -1;
+ }
+
+ return 0;
+}
+
int hci_read_afh_map(int dd, uint16_t handle, uint8_t *mode, uint8_t *map,
int to)
{
diff --git a/lib/hci.h b/lib/hci.h
index 9b5388b..72cf7e3 100644
--- a/lib/hci.h
+++ b/lib/hci.h
@@ -906,8 +906,27 @@ typedef struct {
#define WRITE_VOICE_SETTING_CP_SIZE 2
#define OCF_READ_AUTOMATIC_FLUSH_TIMEOUT 0x0027
+typedef struct {
+ uint8_t status;
+ uint16_t handle;
+ uint16_t flush_timeout;
+} __attribute__ ((packed)) read_flush_timeout_rp;
+#define READ_FLUSH_TIMEOUT_RP_SIZE 5
+
+#define READ_FLUSH_TIMEOUT_CP_SIZE 2
#define OCF_WRITE_AUTOMATIC_FLUSH_TIMEOUT 0x0028
+typedef struct {
+ uint16_t handle;
+ uint16_t flush_timeout;
+} __attribute__ ((packed)) write_flush_timeout_cp;
+#define WRITE_FLUSH_TIMEOUT_CP_SIZE 4
+
+typedef struct {
+ uint8_t status;
+ uint16_t handle;
+} __attribute__ ((packed)) write_flush_timeout_rp;
+#define WRITE_FLUSH_TIMEOUT_RP_SIZE 3
#define OCF_READ_NUM_BROADCAST_RETRANS 0x0029
diff --git a/lib/hci_lib.h b/lib/hci_lib.h
index b63a2a4..d56dfc2 100644
--- a/lib/hci_lib.h
+++ b/lib/hci_lib.h
@@ -114,6 +114,8 @@ int hci_read_link_quality(int dd, uint16_t handle, uint8_t *link_quality, int to
int hci_read_rssi(int dd, uint16_t handle, int8_t *rssi, int to);
int hci_read_afh_map(int dd, uint16_t handle, uint8_t *mode, uint8_t *map, int to);
int hci_read_clock(int dd, uint16_t handle, uint8_t which, uint32_t *clock, uint16_t *accuracy, int to);
+int hci_read_flush_timeout(int dd, uint16_t handle, uint16_t *timeout, int to);
+int hci_write_flush_timeout(int dd, uint16_t handle, uint16_t timeout, int to);
int hci_le_set_scan_enable(int dev_id, uint8_t enable, uint8_t filter_dup);
int hci_le_set_scan_parameters(int dev_id, uint8_t type, uint16_t interval,
diff --git a/tools/hcitool.c b/tools/hcitool.c
index d50adaf..580f867 100644
--- a/tools/hcitool.c
+++ b/tools/hcitool.c
@@ -2517,6 +2517,91 @@ static void cmd_ledc(int dev_id, int argc, char **argv)
hci_close_dev(dd);
}
+/* Flush timer */
+
+static struct option flush_options[] = {
+ { "help", 0, 0, 'h' },
+ { 0, 0, 0, 0 }
+};
+
+static const char *flush_help =
+ "Usage:\n"
+ "\tflush <bdaddr> [timeout in slots]\n";
+
+static void cmd_flush(int dev_id, int argc, char **argv)
+{
+ struct hci_conn_info_req *cr;
+ bdaddr_t bdaddr;
+ int opt, dd;
+ uint16_t flush_timeout;
+
+ for_each_opt(opt, flush_options, NULL) {
+ switch (opt) {
+ default:
+ printf("%s", flush_help);
+ return;
+ }
+ }
+ helper_arg(1, 2, &argc, &argv, flush_help);
+
+ str2ba(argv[0], &bdaddr);
+
+ if (dev_id < 0) {
+ dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr);
+ if (dev_id < 0) {
+ fprintf(stderr, "Not connected.\n");
+ exit(1);
+ }
+ }
+
+ dd = hci_open_dev(dev_id);
+ if (dd < 0) {
+ perror("HCI device open failed");
+ exit(1);
+ }
+
+ cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info));
+ if (!cr) {
+ perror("Can't allocate memory");
+ exit(1);
+ }
+
+ bacpy(&cr->bdaddr, &bdaddr);
+ cr->type = ACL_LINK;
+ if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) {
+ perror("Get connection info failed");
+ exit(1);
+ }
+
+ if (argc == 1) {
+ if (hci_read_flush_timeout(dd, htobs(cr->conn_info->handle),
+ &flush_timeout, 1000) < 0) {
+ perror("Read automatic flush timeout failed");
+ exit(1);
+ }
+
+ flush_timeout = btohs(flush_timeout);
+
+ if (flush_timeout)
+ printf("Automatic flush timeout: %u slots (%.2f ms)\n",
+ flush_timeout, (float) flush_timeout * 0.625);
+ else
+ printf("Automatic flush timeout never expires\n");
+ } else {
+ flush_timeout = strtol(argv[1], NULL, 10);
+
+ if (hci_write_flush_timeout(dd, htobs(cr->conn_info->handle),
+ htobs(flush_timeout), 1000) < 0) {
+ perror("Write automatic flush timeout failed");
+ exit(1);
+ }
+ }
+
+ free(cr);
+
+ hci_close_dev(dd);
+}
+
static struct {
char *cmd;
void (*func)(int dev_id, int argc, char **argv);
@@ -2546,6 +2631,7 @@ static struct {
{ "key", cmd_key, "Change connection link key" },
{ "clkoff", cmd_clkoff, "Read clock offset" },
{ "clock", cmd_clock, "Read local or remote clock" },
+ { "flush", cmd_flush, "Set/display automatic flush timeout" },
{ "lescan", cmd_lescan, "Start LE scan" },
{ "lecc", cmd_lecc, "Create a LE Connection", },
{ "ledc", cmd_ledc, "Disconnect a LE Connection", },
--
1.7.1
^ permalink raw reply related
* Re: [PATCH v2] HDP: reject MDL reconnection with different MTU
From: Johan Hedberg @ 2011-01-28 16:09 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1295005808-9885-1-git-send-email-epx@signove.com>
Hi Elvis,
On Fri, Jan 14, 2011, Elvis Pf??tzenreuter wrote:
> This patch implements refusal of a MDL reconnection if the new L2CAP
> connection presents a different MTU. Accordingly to HDP spec. item 3.5.
>
> It aims to pass the TC_SNK_HCT_BV_07_C PTS test. (It does not pass yet
> because PTS itself seems to have issues. See tickets 7212, 7214 and
> 7244 for details.)
> ---
> health/hdp.c | 21 +++++++++++++++++++--
> health/hdp_types.h | 2 ++
> 2 files changed, 21 insertions(+), 2 deletions(-)
Sorry for missing this one earlier, it's now pushed upstream with a
minor rewrite of the following to a proper if-statement to make is more
readable (at least in my mind):
> + return chan->imtu == imtu && chan->omtu == omtu;
Johan
^ permalink raw reply
* [PATCH] Add read callback support to attribute server
From: Anderson Lizardo @ 2011-01-28 16:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
This callback will allow profiles to act before an attribute is read,
to e.g. update the attribute value from an external source.
Note that by the time the callback is called, the necessary security
checks (attribute permissions, authentication and encryption) were
already performed by the core attribute server.
The callback can optionally return an ATT status code, which will be
sent to the client.
---
attrib/att.h | 5 +++++
src/attrib-server.c | 13 ++++++++++---
src/attrib-server.h | 4 ++--
3 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/attrib/att.h b/attrib/att.h
index 1caa62a..448c66b 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -118,11 +118,16 @@ enum {
ATT_NOT_PERMITTED, /* Operation not permitted */
};
+struct attribute;
+
+typedef uint8_t (*att_read_cb_t)(struct attribute *);
+
struct attribute {
uint16_t handle;
uuid_t uuid;
int read_reqs;
int write_reqs;
+ att_read_cb_t read_cb;
int len;
uint8_t data[0];
};
diff --git a/src/attrib-server.c b/src/attrib-server.c
index f03a5b9..b8264e2 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -543,6 +543,13 @@ static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
return enc_error_resp(ATT_OP_READ_REQ, handle, status, pdu,
len);
+ if (a->read_cb) {
+ status = a->read_cb(a);
+ if (status)
+ return enc_error_resp(ATT_OP_READ_REQ, handle, status,
+ pdu, len);
+ }
+
return enc_read_resp(a->data, a->len, pdu, len);
}
@@ -918,8 +925,8 @@ void attrib_server_exit(void)
remove_record_from_server(sdp_handle);
}
-int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs,
- const uint8_t *value, int len)
+struct attribute *attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs,
+ int write_reqs, const uint8_t *value, int len)
{
struct attribute *a;
@@ -935,7 +942,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 a;
}
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..6caea64 100644
--- a/src/attrib-server.h
+++ b/src/attrib-server.h
@@ -25,8 +25,8 @@
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);
+struct attribute *attrib_db_add(uint16_t handle, uuid_t *uuid, 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.0.4
^ permalink raw reply related
* Re: [PATCH] Add read callback support to attribute server
From: Anderson Lizardo @ 2011-01-28 18:42 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1296231972-6070-1-git-send-email-anderson.lizardo@openbossa.org>
On Fri, Jan 28, 2011 at 12:26 PM, Anderson Lizardo
<anderson.lizardo@openbossa.org> wrote:
> This callback will allow profiles to act before an attribute is read,
> to e.g. update the attribute value from an external source.
>
> Note that by the time the callback is called, the necessary security
> checks (attribute permissions, authentication and encryption) were
> already performed by the core attribute server.
>
> The callback can optionally return an ATT status code, which will be
> sent to the client.
Please ignore this patch. I'll send another one which also addresses
read blob requests and attribute write.
Regards,
--
Anderson Lizardo
OpenBossa Labs - INdT
Manaus - Brazil
^ permalink raw reply
* [PATCH 1/2] Add option to set LE random address to hciconfig
From: Claudio Takahasi @ 2011-01-28 22:33 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
---
tools/hciconfig.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 44 insertions(+), 0 deletions(-)
diff --git a/tools/hciconfig.c b/tools/hciconfig.c
index 6e5117f..c271d14 100644
--- a/tools/hciconfig.c
+++ b/tools/hciconfig.c
@@ -195,6 +195,49 @@ static void cmd_scan(int ctl, int hdev, char *opt)
}
}
+static void cmd_le_addr(int ctl, int hdev, char *opt)
+{
+ struct hci_request rq;
+ le_set_random_address_cp cp;
+ uint8_t status;
+ int dd, err, ret;
+
+ if (!opt)
+ return;
+
+ if (hdev < 0)
+ hdev = hci_get_route(NULL);
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ err = errno;
+ fprintf(stderr, "Could not open device: %s(%d)\n",
+ strerror(err), err);
+ exit(1);
+ }
+
+ memset(&cp, 0, sizeof(cp));
+
+ str2ba(opt, &cp.bdaddr);
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_LE_CTL;
+ rq.ocf = OCF_LE_SET_RANDOM_ADDRESS;
+ rq.cparam = &cp;
+ rq.clen = LE_SET_RANDOM_ADDRESS_CP_SIZE;
+ rq.rparam = &status;
+ rq.rlen = 1;
+
+ ret = hci_send_req(dd, &rq, 1000);
+ if (status || ret < 0) {
+ err = errno;
+ fprintf(stderr, "Can't set random address for hci%d: "
+ "%s (%d)\n", hdev, strerror(err), err);
+ }
+
+ hci_close_dev(dd);
+}
+
static void cmd_le_adv(int ctl, int hdev, char *opt)
{
struct hci_request rq;
@@ -1879,6 +1922,7 @@ static struct {
{ "revision", cmd_revision, 0, "Display revision information" },
{ "block", cmd_block, "<bdaddr>", "Add a device to the blacklist" },
{ "unblock", cmd_unblock, "<bdaddr>", "Remove a device from the blacklist" },
+ { "lerandaddr", cmd_le_addr, "<bdaddr>", "Set LE Random Address" },
{ "leadv", cmd_le_adv, 0, "Enable LE advertising" },
{ "noleadv", cmd_le_adv, 0, "Disable LE advertising" },
{ "lestates", cmd_le_states, 0, "Display the supported LE states" },
--
1.7.4.rc2
^ permalink raw reply related
* [PATCH 2/2] Add option to enable privacy during scanning to hcitool
From: Claudio Takahasi @ 2011-01-28 22:33 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1296254017-3381-1-git-send-email-claudio.takahasi@openbossa.org>
When privacy is enabled, random address is used during active scanning.
The non-resolvable private address shall be set using hciconfig.
---
tools/hcitool.c | 13 +++++++++----
1 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/tools/hcitool.c b/tools/hcitool.c
index d50adaf..536d407 100644
--- a/tools/hcitool.c
+++ b/tools/hcitool.c
@@ -2349,25 +2349,30 @@ done:
static struct option lescan_options[] = {
{ "help", 0, 0, 'h' },
+ { "privacy", 0, 0, 'p' },
{ 0, 0, 0, 0 }
};
static const char *lescan_help =
"Usage:\n"
- "\tlescan\n";
+ "\tlescan [--privacy] enable privacy\n";
static void cmd_lescan(int dev_id, int argc, char **argv)
{
int err, opt, dd;
+ uint8_t own_type = 0x00;
for_each_opt(opt, lescan_options, NULL) {
switch (opt) {
+ case 'p':
+ own_type = 0x01; /* Random */
+ break;
default:
printf("%s", lescan_help);
return;
}
}
- helper_arg(0, 0, &argc, &argv, lescan_help);
+ helper_arg(0, 1, &argc, &argv, lescan_help);
if (dev_id < 0)
dev_id = hci_get_route(NULL);
@@ -2378,8 +2383,8 @@ static void cmd_lescan(int dev_id, int argc, char **argv)
exit(1);
}
- err = hci_le_set_scan_parameters(dd, 0x01, htobs(0x0010), htobs(0x0010),
- 0x00, 0x00);
+ err = hci_le_set_scan_parameters(dd, 0x01, htobs(0x0010),
+ htobs(0x0010), own_type, 0x00);
if (err < 0) {
perror("Set scan parameters failed");
exit(1);
--
1.7.4.rc2
^ permalink raw reply related
* GATT and D-Bus
From: Inga Stotland @ 2011-01-28 23:19 UTC (permalink / raw)
To: 'Vinicius Costa Gomes'; +Cc: linux-bluetooth
In-Reply-To: <20110124213429.GA15121@piper>
Hi Vinicus,
Not sure who to ask, but it seems that you are the active contributor to the
part of the code that I am interested in :)
I am looking at using D-Bus to talk to GATT just over BR/EDR. The support
for that seems to be partially there ( I am working off the current bluez
tip). However, in the current code it does not seem possible to get GATT
over D-Bus working if the device is not LE. Am I missing something here?
Also, I can see that you were sending GATT patches upstream: "[PATCH 00/18]
Making GATT a first class citizen", not all of them have been pushed
through. Are you planning on re-submitting the changes?
Thank you,
Inga Stotland
ingas@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
^ permalink raw reply
* Re: GATT and D-Bus
From: Vinicius Costa Gomes @ 2011-01-29 0:07 UTC (permalink / raw)
To: Inga Stotland; +Cc: linux-bluetooth
In-Reply-To: <000101cbbf41$cc0cee10$6426ca30$@org>
Hi Inga,
On 15:19 Fri 28 Jan, Inga Stotland wrote:
> Hi Vinicus,
>
> Not sure who to ask, but it seems that you are the active contributor to the
> part of the code that I am interested in :)
> I am looking at using D-Bus to talk to GATT just over BR/EDR. The support
> for that seems to be partially there ( I am working off the current bluez
> tip). However, in the current code it does not seem possible to get GATT
> over D-Bus working if the device is not LE. Am I missing something here?
> Also, I can see that you were sending GATT patches upstream: "[PATCH 00/18]
> Making GATT a first class citizen", not all of them have been pushed
> through. Are you planning on re-submitting the changes?
Those patches are already upstream, it was just that the "applied" message
came via IRC.
What is missing for the BR/EDR case is that we need to trigger GATT Service
Discovery after the SDP Browse, if the Device has the GATT Service Record.
SMP is still taking a lot of my time, that I didn't have the time to go back
and solve this issue, but it is still on the top of my todo list ;-)
>
> Thank you,
>
> Inga Stotland
>
> ingas@codeaurora.org
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
>
>
>
>
Cheers,
--
Vinicius
^ permalink raw reply
* [PATCH] Set connection state to BT_DISCONN to avoid multiple responses
From: Liang Bao @ 2011-01-29 13:39 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Bao Liang
From: Bao Liang <tim.bao@gmail.com>
This patch fixes a minor issue that two connection responses will be sent
for one L2CAP connection request. If the L2CAP connection request is first
blocked due to security reason and responded with reason "security block",
the state of the connection remains BT_CONNECT2. If a pairing procedure
completes successfully before the ACL connection is down, local host will
send another connection complete response. See the following packets
captured by hcidump.
2010-12-07 22:21:24.928096 < ACL data: handle 12 flags 0x00 dlen 16
0000: 0c 00 01 00 03 19 08 00 41 00 53 00 03 00 00 00 ........A.S.....
... ...
2010-12-07 22:21:35.791747 > HCI Event: Auth Complete (0x06) plen 3
status 0x00 handle 12
... ...
2010-12-07 22:21:35.872372 > ACL data: handle 12 flags 0x02 dlen 16
L2CAP(s): Connect rsp: dcid 0x0054 scid 0x0040 result 0 status 0
Connection successful
Signed-off-by: Liang Bao <tim.bao@gmail.com>
---
net/bluetooth/l2cap.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index fadf26b..364197d 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -848,6 +848,7 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
result = L2CAP_CR_SEC_BLOCK;
else
result = L2CAP_CR_BAD_PSM;
+ sk->sk_state = BT_DISCONN;
rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
--
1.7.1
^ permalink raw reply related
* Re: [PATCH] Set connection state to BT_DISCONN to avoid multiple responses
From: Ville Tervo @ 2011-01-31 7:57 UTC (permalink / raw)
To: ext Liang Bao; +Cc: linux-bluetooth
In-Reply-To: <1296308377-2207-1-git-send-email-tim.bao@gmail.com>
Hi,
On Sat, Jan 29, 2011 at 09:39:37PM +0800, ext Liang Bao wrote:
> From: Bao Liang <tim.bao@gmail.com>
>
> This patch fixes a minor issue that two connection responses will be sent
> for one L2CAP connection request. If the L2CAP connection request is first
> blocked due to security reason and responded with reason "security block",
> the state of the connection remains BT_CONNECT2. If a pairing procedure
> completes successfully before the ACL connection is down, local host will
> send another connection complete response. See the following packets
> captured by hcidump.
>
> 2010-12-07 22:21:24.928096 < ACL data: handle 12 flags 0x00 dlen 16
> 0000: 0c 00 01 00 03 19 08 00 41 00 53 00 03 00 00 00 ........A.S.....
> ... ...
>
> 2010-12-07 22:21:35.791747 > HCI Event: Auth Complete (0x06) plen 3
> status 0x00 handle 12
> ... ...
>
> 2010-12-07 22:21:35.872372 > ACL data: handle 12 flags 0x02 dlen 16
> L2CAP(s): Connect rsp: dcid 0x0054 scid 0x0040 result 0 status 0
> Connection successful
>
> Signed-off-by: Liang Bao <tim.bao@gmail.com>
Now it looks good to me.
Acked-by: Ville Tervo <ville.tervo@nokia.com>
> ---
> net/bluetooth/l2cap.c | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> index fadf26b..364197d 100644
> --- a/net/bluetooth/l2cap.c
> +++ b/net/bluetooth/l2cap.c
> @@ -848,6 +848,7 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
> result = L2CAP_CR_SEC_BLOCK;
> else
> result = L2CAP_CR_BAD_PSM;
> + sk->sk_state = BT_DISCONN;
>
> rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
> rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
> --
> 1.7.1
>
--
Ville
^ permalink raw reply
* Re: [PATCH 2/4] HCI command to remove device from LE White List
From: Johan Hedberg @ 2011-01-31 8:28 UTC (permalink / raw)
To: Sumit Kumar BAJPAI; +Cc: Anderson Lizardo, linux-bluetooth@vger.kernel.org
In-Reply-To: <4765B7BC10CB4C488A56C73E15D6FBA31DA579F208@EXDCVYMBSTM005.EQ1STM.local>
Hi,
On Tue, Jan 25, 2011, Sumit Kumar BAJPAI wrote:
> Thanks Anderson for review comments.
> Posting patch again.
The latest versions of these patches seem to be scattered around and not
formated properly as something that could be applied with git am (at
least the commit messages aren't right). Could you resend the latest
versions of all of the patches in a new thread using git send-email?
Johan
^ permalink raw reply
* Re: [PATCH 2/2] Implement dumping for evnet LE Connection Update Complete.
From: Johan Hedberg @ 2011-01-31 8:36 UTC (permalink / raw)
To: André Dieb Martins; +Cc: linux-bluetooth
In-Reply-To: <1295897559-5540-2-git-send-email-andre.dieb@signove.com>
Hi André
On Mon, Jan 24, 2011, André Dieb Martins wrote:
> ---
> parser/hci.c | 16 ++++++++++++++++
> 1 files changed, 16 insertions(+), 0 deletions(-)
Both patches have been pushed upstream. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH 2/2] Add option to enable privacy during scanning to hcitool
From: Johan Hedberg @ 2011-01-31 8:40 UTC (permalink / raw)
To: Claudio Takahasi; +Cc: linux-bluetooth
In-Reply-To: <1296254017-3381-2-git-send-email-claudio.takahasi@openbossa.org>
Hi Claudio,
On Fri, Jan 28, 2011, Claudio Takahasi wrote:
> When privacy is enabled, random address is used during active scanning.
> The non-resolvable private address shall be set using hciconfig.
> ---
> tools/hcitool.c | 13 +++++++++----
> 1 files changed, 9 insertions(+), 4 deletions(-)
Both patches have been pushed upstream. Thanks.
Any plans how to represent this feature in the official APIs? I suppose
the random address can be generated automatically using some appropriate
source such as the HCI_LE_Rand command but how do we represent the
public vs random address selection using the D-Bus API? Or do we even
need to do that?
Johan
^ permalink raw reply
* [PATCH 1/2] Fix creating device object when connection fails
From: Luiz Augusto von Dentz @ 2011-01-31 12:56 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
There is no need to create a new object since there is no connection and
the device is not permanent/paired.
---
src/event.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/src/event.c b/src/event.c
index ff768c0..166e401 100644
--- a/src/event.c
+++ b/src/event.c
@@ -676,7 +676,9 @@ void btd_event_conn_failed(bdaddr_t *local, bdaddr_t *peer, uint8_t status)
struct btd_device *device;
DBusConnection *conn = get_dbus_connection();
- if (!get_adapter_and_device(local, peer, &adapter, &device, TRUE))
+ DBG("");
+
+ if (!get_adapter_and_device(local, peer, &adapter, &device, FALSE))
return;
if (device_is_temporary(device))
--
1.7.1
^ permalink raw reply related
* [PATCH 2/2] Fix creating device object when device disconnects
From: Luiz Augusto von Dentz @ 2011-01-31 12:56 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1296478596-18269-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
If object doesn't exist the device is not permanent so there is no need
to create a new object just to handle disconnect event.
---
src/event.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/event.c b/src/event.c
index 166e401..5060e84 100644
--- a/src/event.c
+++ b/src/event.c
@@ -692,7 +692,7 @@ void btd_event_disconn_complete(bdaddr_t *local, bdaddr_t *peer)
DBG("");
- if (!get_adapter_and_device(local, peer, &adapter, &device, TRUE))
+ if (!get_adapter_and_device(local, peer, &adapter, &device, FALSE))
return;
adapter_remove_connection(adapter, device);
--
1.7.1
^ permalink raw reply related
* [RFC] Bluetooth: process received S-frames when socket is locked by user process
From: Suraj Sumangala @ 2011-01-31 13:12 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Jothikumar.Mothilal, Suraj Sumangala
This patch lets L2CAP process received S-frames even when socket is
continuously being locked by user process.
This issue was seen when testing with l2test without using "-D" option.
Since the user process does not expect any Rx packets,
it hogs the socket with continuous call to "send()".
When the TxWindow is full Tx stops untill the I-frames are acked by the receiver.
But the Rx S-Frame acknowleding the Tx frames will stay in the backlog queue
because the "sock_owned_by_user()" call in l2cap_data_channel()
will always return true.
The user process does not have an idea about this
mechanism and keep pumping data and locking the socket and cause a deadlock.
Signed-off-by: Suraj Sumangala <suraj@atheros.com>
---
net/bluetooth/l2cap.c | 16 ++++++++++------
1 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 1761558..dc22291 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -4336,6 +4336,15 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
int len, next_tx_seq_offset, req_seq_offset;
control = get_unaligned_le16(skb->data);
+
+ if (sock_owned_by_user(sk)) {
+ if (__is_iframe(control)) {
+ if (sk_add_backlog(sk, skb))
+ goto drop;
+
+ return 0;
+ }
+ }
skb_pull(skb, 2);
len = skb->len;
@@ -4434,12 +4443,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
break;
case L2CAP_MODE_ERTM:
- if (!sock_owned_by_user(sk)) {
- l2cap_ertm_data_rcv(sk, skb);
- } else {
- if (sk_add_backlog(sk, skb))
- goto drop;
- }
+ l2cap_ertm_data_rcv(sk, skb);
goto done;
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH 2/2] Add option to enable privacy during scanning to hcitool
From: Claudio Takahasi @ 2011-01-31 13:50 UTC (permalink / raw)
To: Claudio Takahasi, linux-bluetooth
In-Reply-To: <20110131084038.GB10034@jh-x301>
Hi Johan,
On Mon, Jan 31, 2011 at 6:40 AM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> Hi Claudio,
>
> On Fri, Jan 28, 2011, Claudio Takahasi wrote:
>> When privacy is enabled, random address is used during active scanning.
>> The non-resolvable private address shall be set using hciconfig.
>> ---
>> tools/hcitool.c | 13 +++++++++----
>> 1 files changed, 9 insertions(+), 4 deletions(-)
>
> Both patches have been pushed upstream. Thanks.
>
> Any plans how to represent this feature in the official APIs? I suppose
> the random address can be generated automatically using some appropriate
> source such as the HCI_LE_Rand command but how do we represent the
> public vs random address selection using the D-Bus API? Or do we even
> need to do that?
>
> Johan
>
I added these changes to investigate the PTS test result, it is not
mandatory. I am was planning to focus on Register Application API
first instead of privacy for central. The implementation is simple, if
someone in the community wants to help us, here are some guidelines:
My idea is add a new property in the adapter interface called:
Privacy. The changes will be:
1. Add Privacy property with persistent storage =>
adapter.SetProperty("Privacy", True/False)
2. Generate a non-resolvable private address. My suggestion is to read
the data directly from "/dev/random" instead of use HCI_LE_Rand
command(needs to wait for command complete).
3. Trigger the LE scanning based on this property.
PS: For LE Create Connection command the own address type must be set
based on privacy value, however this change requires changes in the
kernel. Currently, Own_Address_Type is hard-coded in the kernel(public
address only).
Regards,
Claudio.
^ permalink raw reply
* [PATCH 1/2 v2] Fix creating device object when connection fails
From: Luiz Augusto von Dentz @ 2011-01-31 14:39 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
There is no need to create a new object since there is no connection and
the device is not permanent/paired.
---
src/event.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/src/event.c b/src/event.c
index ff768c0..39feffe 100644
--- a/src/event.c
+++ b/src/event.c
@@ -676,7 +676,9 @@ void btd_event_conn_failed(bdaddr_t *local, bdaddr_t *peer, uint8_t status)
struct btd_device *device;
DBusConnection *conn = get_dbus_connection();
- if (!get_adapter_and_device(local, peer, &adapter, &device, TRUE))
+ DBG("status 0x%02x", status);
+
+ if (!get_adapter_and_device(local, peer, &adapter, &device, FALSE))
return;
if (device_is_temporary(device))
--
1.7.1
^ permalink raw reply related
* Re: [PATCH 2/2] Add option to enable privacy during scanning to hcitool
From: Luiz Augusto von Dentz @ 2011-01-31 15:46 UTC (permalink / raw)
To: Claudio Takahasi; +Cc: linux-bluetooth
In-Reply-To: <AANLkTinUQozBxDAUH4yKW93h6bEKy=WtWWwkJumYYYHA@mail.gmail.com>
Hi Claudio,
On Mon, Jan 31, 2011 at 3:50 PM, Claudio Takahasi
<claudio.takahasi@openbossa.org> wrote:
> Hi Johan,
>
> On Mon, Jan 31, 2011 at 6:40 AM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
>> Hi Claudio,
>>
>> On Fri, Jan 28, 2011, Claudio Takahasi wrote:
>>> When privacy is enabled, random address is used during active scanning.
>>> The non-resolvable private address shall be set using hciconfig.
>>> ---
>>> tools/hcitool.c | 13 +++++++++----
>>> 1 files changed, 9 insertions(+), 4 deletions(-)
>>
>> Both patches have been pushed upstream. Thanks.
>>
>> Any plans how to represent this feature in the official APIs? I suppose
>> the random address can be generated automatically using some appropriate
>> source such as the HCI_LE_Rand command but how do we represent the
>> public vs random address selection using the D-Bus API? Or do we even
>> need to do that?
>>
>> Johan
>>
>
> I added these changes to investigate the PTS test result, it is not
> mandatory. I am was planning to focus on Register Application API
> first instead of privacy for central. The implementation is simple, if
> someone in the community wants to help us, here are some guidelines:
>
> My idea is add a new property in the adapter interface called:
> Privacy. The changes will be:
> 1. Add Privacy property with persistent storage =>
> adapter.SetProperty("Privacy", True/False)
Can this be unset, I mean can a device really use a random/private and
than latter switch to public? For what I understand if anyone pair
using the random/private address they don't store the actual address
but a key to resolve the address, so switching on runtime is IMO not a
good idea, perhaps a parameter on main.conf is enough?
Actually the spec say that there could be at least 3 types of random address:
- Static
- Private Non-resolvable
- Private Resolvable
> 2. Generate a non-resolvable private address. My suggestion is to read
> the data directly from "/dev/random" instead of use HCI_LE_Rand
> command(needs to wait for command complete).
I remember someone saying that the controller should be able to
generate a more random number because it uses the RF signal
interference for that, but Im not sure if this is actually true or
not, or if enough to give up the idea of using /dev/random.
> 3. Trigger the LE scanning based on this property.
>
> PS: For LE Create Connection command the own address type must be set
> based on privacy value, however this change requires changes in the
> kernel. Currently, Own_Address_Type is hard-coded in the kernel(public
> address only).
Yep, we probably need to start by fixing this, it seems some device
will already come with random addresses so it will be nice to have
this fixed asap.
--
Luiz Augusto von Dentz
Computer Engineer
^ permalink raw reply
* [PATCH 1/6 v2] Include check to readline lib on acinlude.m4
From: Sheldon Demario @ 2011-01-31 17:23 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Sheldon Demario
In-Reply-To: <1296155342-31956-1-git-send-email-sheldon.demario@openbossa.org>
---
acinclude.m4 | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/acinclude.m4 b/acinclude.m4
index ecf4b4b..517684c 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 2/6 v2] Add an interactive mode to gatttool
From: Sheldon Demario @ 2011-01-31 17:27 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Sheldon Demario
In-Reply-To: <1296150752-27142-2-git-send-email-sheldon.demario@openbossa.org>
We need a deeper control over the gatttool steps to make easier the
debug process.
---
Makefile.am | 5 +-
attrib/gatttool.c | 323 +++++++++++++++++++++++++++++++++++++++++++---------
configure.ac | 1 +
3 files changed, 272 insertions(+), 57 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index e6639a7..ceb1293 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -175,12 +175,15 @@ 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@
+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..c347f6b 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -37,6 +37,9 @@
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+
#include "att.h"
#include "btio.h"
#include "gattrib.h"
@@ -50,7 +53,7 @@ static gchar *opt_src = NULL;
static gchar *opt_dst = NULL;
static gchar *opt_value = NULL;
static gchar *opt_sec_level = "low";
-static uuid_t *opt_uuid = NULL;
+static uuid_t *opt_uuid;
static int opt_start = 0x0001;
static int opt_end = 0xffff;
static int opt_handle = -1;
@@ -63,8 +66,14 @@ static gboolean opt_listen = FALSE;
static gboolean opt_char_desc = FALSE;
static gboolean opt_le = FALSE;
static gboolean opt_char_write = FALSE;
-static GMainLoop *event_loop;
+static gboolean opt_interactive = FALSE;
+
+static GMainLoop *event_loop = NULL;
+static GIOChannel *iochannel = NULL;
static gboolean got_error = FALSE;
+static GAttrib *attrib = NULL;
+static GString *prompt = NULL;
+static GOptionContext *context = NULL;
struct characteristic_data {
GAttrib *attrib;
@@ -72,16 +81,72 @@ struct characteristic_data {
uint16_t end;
};
+enum state {
+ STATE_DISCONNECTED,
+ STATE_CONNECTING,
+ STATE_CONNECTED
+} conn_state;
+
+static void show_message(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+
+ vprintf(format, ap);
+
+ va_end(ap);
+
+ rl_redisplay();
+}
+
+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_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) {
- g_printerr("%s\n", err->message);
- got_error = TRUE;
- g_main_loop_quit(event_loop);
+ show_message("connect error: %s\n", err->message);
+ if (!opt_interactive) {
+ got_error = TRUE;
+ g_main_loop_quit(event_loop);
+ }
+ }
+
+ if (opt_interactive) {
+ attrib = g_attrib_new(iochannel);
+ set_state(STATE_CONNECTED);
}
}
-static GIOChannel *do_connect(gboolean le)
+static GIOChannel *do_connect(gboolean le, const gchar *dest,
+ BtIOConnect connect_cb)
{
GIOChannel *chan;
bdaddr_t sba, dba;
@@ -97,11 +162,11 @@ static GIOChannel *do_connect(gboolean le)
}
/* Remote device */
- if (opt_dst == NULL) {
+ if (dest == NULL) {
g_printerr("Remote Bluetooth address required\n");
return NULL;
}
- str2ba(opt_dst, &dba);
+ str2ba(dest, &dba);
/* Local adapter */
if (opt_src != NULL) {
@@ -232,6 +297,23 @@ static gboolean listen_start(gpointer user_data)
return FALSE;
}
+static gboolean cmd_disconnect(gpointer cmd)
+{
+ if (conn_state == STATE_DISCONNECTED)
+ return FALSE;
+
+ 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 FALSE;
+}
+
static gboolean primary(gpointer user_data)
{
GAttrib *attrib = user_data;
@@ -256,6 +338,24 @@ static void char_discovered_cb(GSList *characteristics, guint8 status,
goto done;
}
+ if (opt_interactive) {
+ rl_save_prompt();
+ for (l = characteristics; l; l = l->next) {
+ struct att_char *chars = l->data;
+
+ rl_message("handle = 0x%04x, char "
+ "properties = 0x%02x, char value "
+ "handle = 0x%04x, uuid = %s\n", chars->handle,
+ chars->properties, chars->value_handle, chars->uuid);
+ rl_on_new_line();
+ }
+
+ rl_restore_prompt();
+ rl_forced_update_display();
+
+ return;
+ }
+
for (l = characteristics; l; l = l->next) {
struct att_char *chars = l->data;
@@ -265,12 +365,16 @@ static void char_discovered_cb(GSList *characteristics, guint8 status,
}
done:
- g_main_loop_quit(event_loop);
+ if (opt_interactive)
+ g_main_loop_quit(event_loop);
}
static gboolean characteristics(gpointer user_data)
{
- GAttrib *attrib = user_data;
+ if (opt_interactive && conn_state != STATE_CONNECTED) {
+ show_message("Fail: disconnected\n");
+ return FALSE;
+ }
gatt_discover_char(attrib, opt_start, opt_end, char_discovered_cb, NULL);
@@ -487,6 +591,153 @@ static gboolean characteristics_desc(gpointer user_data)
return FALSE;
}
+static gboolean cmd_connect(gpointer cmd)
+{
+ const char **c = (const char **) cmd;
+ if (conn_state != STATE_DISCONNECTED)
+ return FALSE;
+
+ if (c[1] != NULL) {
+ g_free(opt_dst);
+ opt_dst = strdup(c[1]);
+ }
+
+ if (opt_dst == NULL) {
+ show_message("Remote Bluetooth address required\n");
+ return FALSE;
+ }
+
+ set_state(STATE_CONNECTING);
+ iochannel = do_connect(opt_le, opt_dst, connect_cb);
+ if (iochannel == NULL)
+ set_state(STATE_DISCONNECTED);
+
+ return FALSE;
+}
+
+static struct {
+ char *cmd;
+ gboolean (*func)(gpointer cmd);
+ char *param;
+ char *desc;
+} commands[] = {
+ { "connect", cmd_connect, "<bdaddr>", "Connect"},
+ { "disconnect", cmd_disconnect, NULL, "Disconnect"},
+ { "characteristics", characteristics, NULL,
+ "Characteristcs Discovery"},
+ { NULL, NULL, NULL, NULL}
+};
+
+static void parse_line(char *line_read)
+{
+ char **command;
+ int j;
+
+ if (!(line_read && *line_read))
+ return;
+
+ add_history(line_read);
+
+ line_read = g_strstrip(line_read);
+
+ command = g_strsplit(line_read, " ", -1);
+ for (j = 0; commands[j].cmd; j++) {
+ if (strcasecmp(commands[j].cmd, command[0]))
+ continue;
+
+ commands[j].func(command);
+ }
+
+ g_strfreev(command);
+}
+
+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;
+ }
+
+ if (conn_state != STATE_CONNECTING)
+ rl_callback_read_char();
+
+ return TRUE;
+}
+
+static int do_interactive(void)
+{
+ GIOChannel *pchan;
+ gint events;
+
+ event_loop = g_main_loop_new(NULL, FALSE);
+ prompt = g_string_new(NULL);
+
+ 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(get_prompt(), parse_line);
+
+ g_main_loop_run(event_loop);
+
+ cmd_disconnect(NULL);
+ rl_callback_handler_remove();
+ g_io_channel_unref(pchan);
+ g_main_loop_unref(event_loop);
+
+ return 0;
+}
+
+static void do_noninteractive(void)
+{
+ GSourceFunc callback;
+
+ if (opt_primary)
+ callback = primary;
+ else if (opt_characteristics)
+ callback = characteristics;
+ else if (opt_char_read)
+ callback = characteristics_read;
+ else if (opt_char_write)
+ callback = characteristics_write;
+ else if (opt_char_desc)
+ callback = characteristics_desc;
+ else {
+ gchar *help = g_option_context_get_help(context, TRUE, NULL);
+ g_print("%s\n", help);
+ g_free(help);
+ got_error = TRUE;
+ return;
+ }
+
+ iochannel = do_connect(opt_le, opt_dst, connect_cb);
+ if (iochannel == NULL) {
+ got_error = TRUE;
+ return;
+ }
+
+ attrib = g_attrib_new(iochannel);
+
+ event_loop = g_main_loop_new(NULL, FALSE);
+
+ if (opt_listen)
+ g_idle_add(listen_start, attrib);
+
+ g_idle_add(callback, attrib);
+
+ g_main_loop_run(event_loop);
+
+ g_attrib_unregister_all(attrib);
+
+ g_io_channel_unref(iochannel);
+
+ g_attrib_unref(attrib);
+
+ g_main_loop_unref(event_loop);
+}
+
static gboolean parse_uuid(const char *key, const char *value,
gpointer user_data, GError **error)
{
@@ -537,6 +788,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', 0, G_OPTION_ARG_NONE, &opt_interactive,
+ "Use interactive mode", NULL },
{ NULL },
};
@@ -556,12 +809,8 @@ static GOptionEntry options[] = {
int main(int argc, char *argv[])
{
- GOptionContext *context;
GOptionGroup *gatt_group, *params_group, *char_rw_group;
GError *gerr = NULL;
- GAttrib *attrib;
- GIOChannel *chan;
- GSourceFunc callback;
context = g_option_context_new(NULL);
g_option_context_add_main_entries(context, options, NULL);
@@ -594,49 +843,11 @@ int main(int argc, char *argv[])
g_error_free(gerr);
}
- if (opt_primary)
- callback = primary;
- else if (opt_characteristics)
- callback = characteristics;
- else if (opt_char_read)
- callback = characteristics_read;
- else if (opt_char_write)
- callback = characteristics_write;
- else if (opt_char_desc)
- callback = characteristics_desc;
- else {
- gchar *help = g_option_context_get_help(context, TRUE, NULL);
- g_print("%s\n", help);
- g_free(help);
- got_error = TRUE;
- goto done;
- }
-
- chan = do_connect(opt_le);
- if (chan == NULL) {
- got_error = TRUE;
- goto done;
- }
-
- attrib = g_attrib_new(chan);
-
- event_loop = g_main_loop_new(NULL, FALSE);
-
- if (opt_listen)
- g_idle_add(listen_start, attrib);
-
- g_idle_add(callback, attrib);
-
- g_main_loop_run(event_loop);
-
- g_attrib_unregister_all(attrib);
-
- g_main_loop_unref(event_loop);
-
- g_io_channel_unref(chan);
- g_attrib_unref(attrib);
+ if (opt_interactive)
+ do_interactive();
+ else
+ do_noninteractive();
-done:
g_option_context_free(context);
g_free(opt_src);
g_free(opt_dst);
diff --git a/configure.ac b/configure.ac
index bebdc9c..3058fc6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -41,6 +41,7 @@ AC_PATH_ALSA
AC_PATH_GSTREAMER
AC_PATH_USB
AC_PATH_SNDFILE
+AC_PATH_READLINE
AC_PATH_OUI
AC_ARG_BLUEZ
--
1.7.1
^ permalink raw reply related
* Re: [PATCH] Bluetooth: Support SCO over HCI for Atheros AR300x Bluetooth device
From: Suraj Sumangala @ 2011-01-31 17:28 UTC (permalink / raw)
To: Suraj Sumangala; +Cc: linux-bluetooth@vger.kernel.org, Jothikumar Mothilal
In-Reply-To: <1296211744-2487-1-git-send-email-suraj@atheros.com>
Hi,
On 1/28/2011 4:19 PM, Suraj Sumangala wrote:
> This patch adds SCO over HCI support to Atheros AR300x HCI transport
> driver.
>
> Signed-off-by: Suraj Sumangala<suraj@atheros.com>
> ---
> drivers/bluetooth/hci_ath.c | 18 +++++++++---------
> 1 files changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
> index 6a160c1..161bd20 100644
> --- a/drivers/bluetooth/hci_ath.c
> +++ b/drivers/bluetooth/hci_ath.c
*ping*
Regards
Suraj
^ 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