* [PATCH 7/7] Bluetooth: Fix updating scan mode in set_bredr()
From: johan.hedberg @ 2013-10-14 10:52 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1381747965-24599-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
Now that the connectable setting is also applicable for the LE side it's
possible that the HCI_CONNECTABLE flag is already set when changing the
BR/EDR setting from false to true while the controller is powered. In
this situation we need to update the BR/EDR scan mode to reflect the
setting. Additionally, since HCI_CONNECTABLE also applies to LE we must
not clear the HCI_CONNECTABLE flag when disabling bredr.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/mgmt.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 4f3fd50..abaa58a 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3612,7 +3612,6 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
if (!hdev_is_powered(hdev)) {
if (!cp->val) {
- clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
@@ -3655,7 +3654,12 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
hci_req_init(&req, hdev);
+
+ if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
+ set_bredr_scan(&req);
+
hci_update_ad(&req);
+
err = hci_req_run(&req, set_bredr_complete);
if (err < 0)
mgmt_pending_remove(cmd);
--
1.8.3.1
^ permalink raw reply related
* [PATCH 6/7] Bluetooth: Move set_bredr_scan() to avoid forward declaration
From: johan.hedberg @ 2013-10-14 10:52 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1381747965-24599-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
The set_bredr_scan() function will soon be needed by the set_bredr()
function, so move it to a new location to avoid having to add a forward
declaration.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/mgmt.c | 40 ++++++++++++++++++++--------------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index b8feb8a..4f3fd50 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3530,6 +3530,26 @@ unlock:
return err;
}
+static void set_bredr_scan(struct hci_request *req)
+{
+ struct hci_dev *hdev = req->hdev;
+ u8 scan = 0;
+
+ /* Ensure that fast connectable is disabled. This function will
+ * not do anything if the page scan parameters are already what
+ * they should be.
+ */
+ write_fast_connectable(req, false);
+
+ if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
+ scan |= SCAN_PAGE;
+ if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
+ scan |= SCAN_INQUIRY;
+
+ if (scan)
+ hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+}
+
static void set_bredr_complete(struct hci_dev *hdev, u8 status)
{
struct pending_cmd *cmd;
@@ -3889,26 +3909,6 @@ void mgmt_index_removed(struct hci_dev *hdev)
mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
}
-static void set_bredr_scan(struct hci_request *req)
-{
- struct hci_dev *hdev = req->hdev;
- u8 scan = 0;
-
- /* Ensure that fast connectable is disabled. This function will
- * not do anything if the page scan parameters are already what
- * they should be.
- */
- write_fast_connectable(req, false);
-
- if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
- scan |= SCAN_PAGE;
- if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
- scan |= SCAN_INQUIRY;
-
- if (scan)
- hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
-}
-
static void powered_complete(struct hci_dev *hdev, u8 status)
{
struct cmd_lookup match = { NULL, hdev };
--
1.8.3.1
^ permalink raw reply related
* [PATCH 5/7] Bluetooth: Update Set Connectable to also impact the advertising type
From: johan.hedberg @ 2013-10-14 10:52 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1381747965-24599-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
This patch updates the Set Connectable Management command to also update
the advertising type to either connectable or non-connectable
advertising. Extra care needs to be taken when BR/EDR is disabled since
then we need to have an extra flip of the HCI_CONNECTABLE flag in the
set_bredr() handler as well as an extra new_settings() call in the
request completion callback.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/mgmt.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 0200c7e..b8feb8a 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1115,6 +1115,9 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status)
if (!cmd)
goto unlock;
+ if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
+ new_settings(hdev, cmd->sk);
+
send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
mgmt_pending_remove(cmd);
@@ -1129,15 +1132,15 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
struct mgmt_mode *cp = data;
struct pending_cmd *cmd;
struct hci_request req;
- u8 scan, status;
+ u8 scan;
int err;
BT_DBG("request for %s", hdev->name);
- status = mgmt_bredr_support(hdev);
- if (status)
+ if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
+ !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
- status);
+ MGMT_STATUS_REJECTED);
if (cp->val != 0x00 && cp->val != 0x01)
return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
@@ -1208,6 +1211,14 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
write_fast_connectable(&req, false);
+ if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
+ hci_conn_num(hdev, LE_LINK) == 0) {
+ if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
+ change_bit(HCI_CONNECTABLE, &hdev->dev_flags);
+ disable_advertising(&req);
+ enable_advertising(&req, cp->val);
+ }
+
err = hci_req_run(&req, set_connectable_complete);
if (err < 0) {
mgmt_pending_remove(cmd);
--
1.8.3.1
^ permalink raw reply related
* [PATCH 4/7] Bluetooth: Fix updating advertising data needlessly
From: johan.hedberg @ 2013-10-14 10:52 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1381747965-24599-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
We need to ensure that the advertising data is up-to-date whenever
advertising is enabled, but when disabling advertising we do not need to
worry about it (since it will eventually get fixed as soon as
advertising is enabled again). This patch fixes this in the command
complete callback for set_adv_enable.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/hci_event.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index aa6fed3..da2bc3d 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -924,7 +924,7 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
}
- if (!test_bit(HCI_INIT, &hdev->flags)) {
+ if (*sent && !test_bit(HCI_INIT, &hdev->flags)) {
struct hci_request req;
hci_req_init(&req, hdev);
--
1.8.3.1
^ permalink raw reply related
* [PATCH 3/7] Bluetooth: Move static advertising functions to avoid forward declarations
From: johan.hedberg @ 2013-10-14 10:52 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1381747965-24599-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
These functions will soon be used by set_connectable() so move them to a
location in mgmt.c that doesn't require forward declarations.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/mgmt.c | 62 ++++++++++++++++++++++++++--------------------------
1 file changed, 31 insertions(+), 31 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 982b397..0200c7e 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1072,6 +1072,37 @@ static void write_fast_connectable(struct hci_request *req, bool enable)
hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
}
+static void enable_advertising(struct hci_request *req, bool connectable)
+{
+ struct hci_dev *hdev = req->hdev;
+ struct hci_cp_le_set_adv_param cp;
+ u8 enable = 0x01;
+
+ memset(&cp, 0, sizeof(cp));
+ cp.min_interval = __constant_cpu_to_le16(0x0800);
+ cp.max_interval = __constant_cpu_to_le16(0x0800);
+ if (connectable)
+ cp.type = LE_ADV_IND;
+ else
+ cp.type = LE_ADV_NONCONN_IND;
+ if (bacmp(&hdev->bdaddr, BDADDR_ANY))
+ cp.own_address_type = ADDR_LE_DEV_PUBLIC;
+ else
+ cp.own_address_type = ADDR_LE_DEV_RANDOM;
+ cp.channel_map = 0x07;
+
+ hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
+
+ hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
+}
+
+static void disable_advertising(struct hci_request *req)
+{
+ u8 enable = 0x00;
+
+ hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
+}
+
static void set_connectable_complete(struct hci_dev *hdev, u8 status)
{
struct pending_cmd *cmd;
@@ -1422,37 +1453,6 @@ unlock:
return err;
}
-static void enable_advertising(struct hci_request *req, bool connectable)
-{
- struct hci_dev *hdev = req->hdev;
- struct hci_cp_le_set_adv_param cp;
- u8 enable = 0x01;
-
- memset(&cp, 0, sizeof(cp));
- cp.min_interval = __constant_cpu_to_le16(0x0800);
- cp.max_interval = __constant_cpu_to_le16(0x0800);
- if (connectable)
- cp.type = LE_ADV_IND;
- else
- cp.type = LE_ADV_NONCONN_IND;
- if (bacmp(&hdev->bdaddr, BDADDR_ANY))
- cp.own_address_type = ADDR_LE_DEV_PUBLIC;
- else
- cp.own_address_type = ADDR_LE_DEV_RANDOM;
- cp.channel_map = 0x07;
-
- hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
-
- hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
-}
-
-static void disable_advertising(struct hci_request *req)
-{
- u8 enable = 0x00;
-
- hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
-}
-
static void le_enable_complete(struct hci_dev *hdev, u8 status)
{
struct cmd_lookup match = { NULL, hdev };
--
1.8.3.1
^ permalink raw reply related
* [PATCH 2/7] Bluetooth: Reorganize set_connectable HCI command sending
From: johan.hedberg @ 2013-10-14 10:52 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1381747965-24599-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
This patch moves all the decisions of which HCI commands to send (or not
to send) to the code between hci_req_init() and hci_req_run() this
allows us to further extend the request with further commands but still
keep the same logic of handling whether to return a direct mgmt response
in the case that no HCI commands were sent.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/mgmt.c | 36 ++++++++++++++++++++----------------
1 file changed, 20 insertions(+), 16 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 6f07523..982b397 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1144,30 +1144,29 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
goto failed;
}
- if (!!cp->val == test_bit(HCI_PSCAN, &hdev->flags)) {
- err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
- goto failed;
- }
-
cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
}
- if (cp->val) {
- scan = SCAN_PAGE;
- } else {
- scan = 0;
+ hci_req_init(&req, hdev);
- if (test_bit(HCI_ISCAN, &hdev->flags) &&
- hdev->discov_timeout > 0)
- cancel_delayed_work(&hdev->discov_off);
- }
+ if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
+ cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
- hci_req_init(&req, hdev);
+ if (cp->val) {
+ scan = SCAN_PAGE;
+ } else {
+ scan = 0;
- hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+ if (test_bit(HCI_ISCAN, &hdev->flags) &&
+ hdev->discov_timeout > 0)
+ cancel_delayed_work(&hdev->discov_off);
+ }
+
+ hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+ }
/* If we're going from non-connectable to connectable or
* vice-versa when fast connectable is enabled ensure that fast
@@ -1179,8 +1178,13 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
write_fast_connectable(&req, false);
err = hci_req_run(&req, set_connectable_complete);
- if (err < 0)
+ if (err < 0) {
mgmt_pending_remove(cmd);
+ if (err == -ENODATA)
+ err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE,
+ hdev);
+ goto failed;
+ }
failed:
hci_dev_unlock(hdev);
--
1.8.3.1
^ permalink raw reply related
* [PATCH 1/7] Bluetooth: Add connectable argument to enable_advertising()
From: johan.hedberg @ 2013-10-14 10:52 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1381747965-24599-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
We want to be able to control whether enable_advertising() enables
connectable or non-connectable advertising based on the connectable
setting of the adapter. We could have the function check directly for
the HCI_CONNECTABLE flag, but since the flag may not be set or unset
before we call the function it's necessary to pass an explicit parameter
value to it.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/mgmt.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 020f95b..6f07523 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1418,7 +1418,7 @@ unlock:
return err;
}
-static void enable_advertising(struct hci_request *req)
+static void enable_advertising(struct hci_request *req, bool connectable)
{
struct hci_dev *hdev = req->hdev;
struct hci_cp_le_set_adv_param cp;
@@ -1427,7 +1427,10 @@ static void enable_advertising(struct hci_request *req)
memset(&cp, 0, sizeof(cp));
cp.min_interval = __constant_cpu_to_le16(0x0800);
cp.max_interval = __constant_cpu_to_le16(0x0800);
- cp.type = LE_ADV_IND;
+ if (connectable)
+ cp.type = LE_ADV_IND;
+ else
+ cp.type = LE_ADV_NONCONN_IND;
if (bacmp(&hdev->bdaddr, BDADDR_ANY))
cp.own_address_type = ADDR_LE_DEV_PUBLIC;
else
@@ -3323,7 +3326,8 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
hci_req_init(&req, hdev);
if (val)
- enable_advertising(&req);
+ enable_advertising(&req,
+ test_bit(HCI_CONNECTABLE, &hdev->dev_flags));
else
disable_advertising(&req);
@@ -3948,7 +3952,9 @@ static int powered_update_hci(struct hci_dev *hdev)
&hdev->static_addr);
if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
- enable_advertising(&req);
+ enable_advertising(&req,
+ test_bit(HCI_CONNECTABLE,
+ &hdev->dev_flags));
}
link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
@@ -4735,7 +4741,7 @@ void mgmt_reenable_advertising(struct hci_dev *hdev)
return;
hci_req_init(&req, hdev);
- enable_advertising(&req);
+ enable_advertising(&req, test_bit(HCI_CONNECTABLE, &hdev->dev_flags));
/* If this fails we have no option but to let user space know
* that we've disabled advertising.
--
1.8.3.1
^ permalink raw reply related
* [PATCH 0/7] Bluetooth: Hook up connectable setting for LE
From: johan.hedberg @ 2013-10-14 10:52 UTC (permalink / raw)
To: linux-bluetooth
Hi,
This set of patches adds hooks to associsate the connectable setting
with the LE advertising type. This means that we can now do
non-connectable advertising by enabling the advertising setting but
having the connectable setting disabled.
Johan
----------------------------------------------------------------
Johan Hedberg (7):
Bluetooth: Add connectable argument to enable_advertising()
Bluetooth: Reorganize set_connectable HCI command sending
Bluetooth: Move static advertising functions to avoid forward declarations
Bluetooth: Fix updating advertising data needlessly
Bluetooth: Update Set Connectable to also impact the advertising type
Bluetooth: Move set_bredr_scan() to avoid forward declaration
Bluetooth: Fix updating scan mode in set_bredr()
net/bluetooth/hci_event.c | 2 +-
net/bluetooth/mgmt.c | 169 ++++++++++++++++++++++++++--------------------
2 files changed, 98 insertions(+), 73 deletions(-)
^ permalink raw reply
* [PATCH BlueZ 3/3] obexd/session: Fix crash when transport is disconnected
From: Luiz Augusto von Dentz @ 2013-10-14 10:14 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1381745687-5677-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
When transport is disconnected unexpectedly it can cause the following
crash:
gobex-DEBUG: gobex/gobex.c:g_obex_send_internal() The transport is not connected
Invalid read of size 8
at 0x42662E: session_process_queue (session.c:789)
by 0x42668F: session_process (session.c:719)
by 0x3D46047E05: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3600.3)
by 0x3D46048157: ??? (in /usr/lib64/libglib-2.0.so.0.3600.3)
by 0x3D46048559: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3600.3)
by 0x40D5FC: main (main.c:319)
Address 0x5086760 is 32 bytes inside a block of size 56 free'd
at 0x4A074C4: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x3D4604D9AE: g_free (in /usr/lib64/libglib-2.0.so.0.3600.3)
by 0x426146: session_process_setpath (session.c:1063)
by 0x426629: session_process_queue (session.c:786)
by 0x42668F: session_process (session.c:719)
by 0x3D46047E05: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3600.3)
by 0x3D46048157: ??? (in /usr/lib64/libglib-2.0.so.0.3600.3)
by 0x3D46048559: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3600.3)
by 0x40D5FC: main (main.c:319)
---
obexd/client/session.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/obexd/client/session.c b/obexd/client/session.c
index 67c2b83..8138b1e 100644
--- a/obexd/client/session.c
+++ b/obexd/client/session.c
@@ -296,6 +296,16 @@ done:
g_free(callback);
}
+static void session_disconnected(GObex *obex, GError *err, gpointer user_data)
+{
+ struct obc_session *session = user_data;
+
+ if (err)
+ error("%s", err->message);
+
+ obc_session_shutdown(session);
+}
+
static void transport_func(GIOChannel *io, GError *err, gpointer user_data)
{
struct callback_data *callback = user_data;
@@ -345,6 +355,8 @@ static void transport_func(GIOChannel *io, GError *err, gpointer user_data)
session->obex = obex;
sessions = g_slist_prepend(sessions, session);
+ g_obex_set_disconnect_function(obex, session_disconnected, session);
+
return;
done:
callback->func(callback->session, NULL, err, callback->data);
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ 2/3] audio/AVDTP: Add struct for discover specific data
From: Luiz Augusto von Dentz @ 2013-10-14 10:14 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1381745687-5677-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This pushes discover specific data to a struct which is a common practice
if the field contains callback and user_data specific to certain
operations.
---
profiles/audio/avdtp.c | 48 +++++++++++++++++++++++++-----------------------
1 file changed, 25 insertions(+), 23 deletions(-)
diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c
index 57e644c..dab8f1c 100644
--- a/profiles/audio/avdtp.c
+++ b/profiles/audio/avdtp.c
@@ -354,6 +354,12 @@ struct avdtp_state_callback {
void *user_data;
};
+struct discover_callback {
+ unsigned int id;
+ avdtp_discover_cb_t cb;
+ void *user_data;
+};
+
struct avdtp_stream {
GIOChannel *io;
uint16_t imtu;
@@ -412,10 +418,7 @@ struct avdtp {
char *buf;
- guint discov_id;
- avdtp_discover_cb_t discov_cb;
- void *user_data;
-
+ struct discover_callback *discover;
struct pending_req *req;
guint dc_timer;
@@ -1042,24 +1045,21 @@ static void avdtp_sep_set_state(struct avdtp *session,
static void finalize_discovery(struct avdtp *session, int err)
{
+ struct discover_callback *discover = session->discover;
struct avdtp_error avdtp_err;
- avdtp_error_init(&avdtp_err, AVDTP_ERRNO, err);
-
- if (!session->discov_cb)
+ if (!discover)
return;
- if (session->discov_id > 0) {
- g_source_remove(session->discov_id);
- session->discov_id = 0;
- }
+ avdtp_error_init(&avdtp_err, AVDTP_ERRNO, err);
- session->discov_cb(session, session->seps,
- err ? &avdtp_err : NULL,
- session->user_data);
+ if (discover->id > 0)
+ g_source_remove(discover->id);
- session->discov_cb = NULL;
- session->user_data = NULL;
+ discover->cb(session, session->seps, err ? &avdtp_err : NULL,
+ discover->user_data);
+ g_free(discover);
+ session->discover = NULL;
}
static void release_stream(struct avdtp_stream *stream, struct avdtp *session)
@@ -3328,7 +3328,7 @@ static gboolean process_discover(gpointer data)
{
struct avdtp *session = data;
- session->discov_id = 0;
+ session->discover->id = 0;
finalize_discovery(session, 0);
@@ -3340,20 +3340,22 @@ int avdtp_discover(struct avdtp *session, avdtp_discover_cb_t cb,
{
int err;
- if (session->discov_cb)
+ if (session->discover)
return -EBUSY;
+ session->discover = g_new0(struct discover_callback, 1);
+
if (session->seps) {
- session->discov_cb = cb;
- session->user_data = user_data;
- session->discov_id = g_idle_add(process_discover, session);
+ session->discover->cb = cb;
+ session->discover->user_data = user_data;
+ session->discover->id = g_idle_add(process_discover, session);
return 0;
}
err = send_request(session, FALSE, NULL, AVDTP_DISCOVER, NULL, 0);
if (err == 0) {
- session->discov_cb = cb;
- session->user_data = user_data;
+ session->discover->cb = cb;
+ session->discover->user_data = user_data;
}
return err;
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ 1/3] audio/AVDTP: Fix crash after disconnecting
From: Luiz Augusto von Dentz @ 2013-10-14 10:14 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
If the session is disconnected while process_discover is pending the
source id is not removed causing the following crash:
at 0x414C08: finalize_discovery (avdtp.c:1050)
by 0x414C5A: process_discover (avdtp.c:3346)
by 0x3D46047E05: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3600.3)
by 0x3D46048157: ??? (in /usr/lib64/libglib-2.0.so.0.3600.3)
by 0x3D46048559: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3600.3)
by 0x40A3B6: main (main.c:595)
Address 0x5e25de8 is 1,144 bytes inside a block of size 1,176 free'd
at 0x4A074C4: free (in
/usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x3D4604D9AE: g_free (in /usr/lib64/libglib-2.0.so.0.3600.3)
by 0x4152F2: connection_lost (avdtp.c:1206)
by 0x4162C4: cancel_request (avdtp.c:2662)
by 0x4164BD: request_timeout (avdtp.c:2672)
by 0x3D46048962: ??? (in /usr/lib64/libglib-2.0.so.0.3600.3)
by 0x3D46047E05: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3600.3)
by 0x3D46048157: ??? (in /usr/lib64/libglib-2.0.so.0.3600.3)
by 0x3D46048559: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3600.3)
by 0x40A3B6: main (main.c:595)
---
profiles/audio/avdtp.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c
index 622dff8..57e644c 100644
--- a/profiles/audio/avdtp.c
+++ b/profiles/audio/avdtp.c
@@ -412,6 +412,7 @@ struct avdtp {
char *buf;
+ guint discov_id;
avdtp_discover_cb_t discov_cb;
void *user_data;
@@ -1048,6 +1049,11 @@ static void finalize_discovery(struct avdtp *session, int err)
if (!session->discov_cb)
return;
+ if (session->discov_id > 0) {
+ g_source_remove(session->discov_id);
+ session->discov_id = 0;
+ }
+
session->discov_cb(session, session->seps,
err ? &avdtp_err : NULL,
session->user_data);
@@ -3322,6 +3328,8 @@ static gboolean process_discover(gpointer data)
{
struct avdtp *session = data;
+ session->discov_id = 0;
+
finalize_discovery(session, 0);
return FALSE;
@@ -3338,7 +3346,7 @@ int avdtp_discover(struct avdtp *session, avdtp_discover_cb_t cb,
if (session->seps) {
session->discov_cb = cb;
session->user_data = user_data;
- g_idle_add(process_discover, session);
+ session->discov_id = g_idle_add(process_discover, session);
return 0;
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH 5/5] android: Add calls to adapter methods in haltest
From: Jerzy Kasenberg @ 2013-10-14 9:59 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Jerzy Kasenberg
In-Reply-To: <1381744794-17994-1-git-send-email-jerzy.kasenberg@tieto.com>
This is first code that actually calls HAL functions.
Functions defined in bt_interface_t can be executed.
---
android/Android.mk | 1 +
android/hal_client/haltest.c | 79 +++++-
android/hal_client/if_bt.c | 637 ++++++++++++++++++++++++++++++++++++++++++
android/hal_client/if_main.h | 105 +++++++
4 files changed, 821 insertions(+), 1 deletion(-)
create mode 100644 android/hal_client/if_bt.c
create mode 100644 android/hal_client/if_main.h
diff --git a/android/Android.mk b/android/Android.mk
index a37db38..dffed58 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -42,6 +42,7 @@ LOCAL_SRC_FILES := \
hal_client/terminal.c \
hal_client/history.c \
hal_client/textconv.c \
+ hal_client/if_bt.c \
LOCAL_SHARED_LIBRARIES := libhardware
diff --git a/android/hal_client/haltest.c b/android/hal_client/haltest.c
index a618cf0..3cd3a73 100644
--- a/android/hal_client/haltest.c
+++ b/android/hal_client/haltest.c
@@ -22,11 +22,53 @@
*/
#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
#include <poll.h>
#include <unistd.h>
+#include "if_main.h"
#include "terminal.h"
#include "pollhandler.h"
+#include "history.h"
+
+const struct interface *interfaces[] = {
+ &bluetooth_if,
+ NULL
+};
+
+int haltest_error(const char *format, ...)
+{
+ va_list args;
+ int ret;
+ va_start(args, format);
+ ret = terminal_vprint(format, args);
+ va_end(args);
+ return ret;
+}
+
+int haltest_info(const char *format, ...)
+{
+ va_list args;
+ int ret;
+ va_start(args, format);
+ ret = terminal_vprint(format, args);
+ va_end(args);
+ return ret;
+}
+
+int haltest_warn(const char *format, ...)
+{
+ va_list args;
+ int ret;
+ va_start(args, format);
+ ret = terminal_vprint(format, args);
+ va_end(args);
+ return ret;
+}
/*
* This function changes input parameter line_buffer so it has
@@ -54,10 +96,44 @@ static void process_line(char *line_buffer)
{
char *argv[10];
int argc;
+ int i = 0;
+ int j;
argc = command_line_to_argv(line_buffer, argv, 10);
+ if (argc < 1)
+ return;
+
+ while (interfaces[i] != NULL) {
+ if (strcmp(interfaces[i]->name, argv[0])) {
+ i++;
+ continue;
+ }
+ if (argc < 2 || strcmp(argv[1], "?") == 0) {
+ j = 0;
+ while (strcmp(interfaces[i]->methods[j].name, "")) {
+ haltest_info("%s %s\n", argv[0],
+ interfaces[i]->methods[j].name);
+ ++j;
+ }
+ return;
+ }
+ j = 0;
+ while (strcmp(interfaces[i]->methods[j].name, "")) {
+ if (strcmp(interfaces[i]->methods[j].name, argv[1])) {
+ j++;
+ continue;
+ }
+ interfaces[i]->methods[j].func(argc,
+ (const char **)argv);
+ break;
+ }
+ if (strcmp(interfaces[i]->methods[j].name, "") == 0)
+ printf("No function %s found\n", argv[1]);
+ break;
+ }
- /* TODO: process command line */
+ if (interfaces[i] == NULL)
+ printf("No such interface %s\n", argv[0]);
}
/* called when there is something on stdin */
@@ -80,6 +156,7 @@ static void stdin_handler(struct pollfd *pollfd)
int main(int argc, char **argv)
{
terminal_setup();
+ history_restore(".haltest_history");
/* Register command line handler */
poll_register_fd(0, POLLIN, stdin_handler);
diff --git a/android/hal_client/if_bt.c b/android/hal_client/if_bt.c
new file mode 100644
index 0000000..7dd5c99
--- /dev/null
+++ b/android/hal_client/if_bt.c
@@ -0,0 +1,637 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 Intel Corporation
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "if_main.h"
+
+const bt_interface_t *if_bluetooth;
+
+static char *bdaddr2str(const bt_bdaddr_t *bd_addr)
+{
+ static char buf[18];
+
+ return bt_bdaddr_t2str(bd_addr, buf);
+}
+
+static char *btuuid2str(const bt_uuid_t *uuid)
+{
+ static char buf[39];
+
+ return bt_uuid_t2str(uuid, buf);
+}
+
+static bt_scan_mode_t str2btscanmode(const char *str)
+{
+ bt_scan_mode_t v = str2bt_scan_mode_t(str);
+
+ if ((int)v != -1)
+ return v;
+
+ haltest_warn("WARN: %s cannot convert %s\n", __func__, str);
+ return (bt_scan_mode_t)atoi(str);
+}
+
+static bt_ssp_variant_t str2btsspvariant(const char *str)
+{
+ bt_ssp_variant_t v = str2bt_ssp_variant_t(str);
+
+ if ((int)v != -1)
+ return v;
+
+ haltest_warn("WARN: %s cannot convert %s\n", __func__, str);
+ return (bt_ssp_variant_t)atoi(str);
+}
+
+static bt_property_type_t str2btpropertytype(const char *str)
+{
+ bt_property_type_t v = str2bt_property_type_t(str);
+
+ if ((int)v != -1)
+ return v;
+
+ haltest_warn("WARN: %s cannot convert %s\n", __func__, str);
+ return (bt_property_type_t)atoi(str);
+}
+
+static char *btproperty2str(bt_property_t property)
+{
+ static char buf[4096];
+ char *p;
+
+ p = buf + sprintf(buf, "type=%s len=%d val=",
+ bt_property_type_t2str(property.type), property.len);
+
+ switch (property.type) {
+ case BT_PROPERTY_BDNAME:
+ case BT_PROPERTY_REMOTE_FRIENDLY_NAME:
+ sprintf(p, "%*s", property.len,
+ ((bt_bdname_t *) property.val)->name);
+ break;
+
+ case BT_PROPERTY_BDADDR:
+ sprintf(p, "%s", bdaddr2str((bt_bdaddr_t *)property.val));
+ break;
+
+ case BT_PROPERTY_CLASS_OF_DEVICE:
+ sprintf(p, "%06x", *((int *)property.val));
+ break;
+
+ case BT_PROPERTY_TYPE_OF_DEVICE:
+ sprintf(p, "%s", bt_device_type_t2str(
+ *((bt_device_type_t *)property.val)));
+ break;
+
+ case BT_PROPERTY_REMOTE_RSSI:
+ sprintf(p, "%d", *((char *)property.val));
+ break;
+
+ case BT_PROPERTY_ADAPTER_SCAN_MODE:
+ sprintf(p, "%s",
+ bt_scan_mode_t2str(*((bt_scan_mode_t *)property.val)));
+ break;
+
+ case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
+ sprintf(p, "%d", *((int *)property.val));
+ break;
+
+ case BT_PROPERTY_ADAPTER_BONDED_DEVICES:
+ {
+ int count = property.len / sizeof(bt_bdaddr_t);
+ char *ptr = property.val;
+
+ strcat(p, "{");
+
+ while (count--) {
+ strcat(p, bdaddr2str((bt_bdaddr_t *)ptr));
+ if (count)
+ strcat(p, ", ");
+ ptr += sizeof(bt_bdaddr_t);
+ }
+
+ strcat(p, "}");
+
+ }
+ break;
+
+ case BT_PROPERTY_UUIDS:
+ {
+ int count = property.len / sizeof(bt_uuid_t);
+ char *ptr = property.val;
+
+ strcat(p, "{");
+
+ while (count--) {
+ strcat(p, btuuid2str((bt_uuid_t *)ptr));
+ if (count)
+ strcat(p, ", ");
+ ptr += sizeof(bt_uuid_t);
+ }
+
+ strcat(p, "}");
+
+ }
+ break;
+
+ case BT_PROPERTY_SERVICE_RECORD:
+ {
+ bt_service_record_t *rec = property.val;
+
+ sprintf(p, "{%s, %d, %s}", btuuid2str(&rec->uuid),
+ rec->channel, rec->name);
+ }
+ break;
+
+ default:
+ sprintf(p, "%p", property.val);
+ }
+
+ return buf;
+}
+
+static void dump_properties(int num_properties, bt_property_t *properties)
+{
+ int i;
+
+ for (i = 0; i < num_properties; i++) {
+ /*
+ * properities sometimes come unaligned hence memcp to
+ * aligned buffer
+ */
+ bt_property_t prop;
+ memcpy(&prop, properties + i, sizeof(prop));
+
+ haltest_info("prop: %s\n", btproperty2str(prop));
+ }
+}
+
+static void adapter_state_changed_cb(bt_state_t state)
+{
+ haltest_info("%s: state=%s\n", __func__, bt_state_t2str(state));
+}
+
+static void adapter_properties_cb(bt_status_t status,
+ int num_properties, bt_property_t *properties)
+{
+ haltest_info("%s: status=%s num_properties=%d\n",
+ __func__, bt_status_t2str(status), num_properties);
+
+ dump_properties(num_properties, properties);
+}
+
+static void remote_device_properties_cb(bt_status_t status,
+ bt_bdaddr_t *bd_addr, int num_properties, bt_property_t *properties)
+{
+ haltest_info("%s: status=%s bd_addr=%s num_properties=%d\n",
+ __func__, bt_status_t2str(status), bdaddr2str(bd_addr),
+ num_properties);
+
+ dump_properties(num_properties, properties);
+}
+
+static void device_found_cb(int num_properties, bt_property_t *properties)
+{
+ haltest_info("%s: num_properties=%d\n", __func__, num_properties);
+
+ dump_properties(num_properties, properties);
+}
+
+static void discovery_state_changed_cb(bt_discovery_state_t state)
+{
+ haltest_info("%s: state=%s\n", __func__,
+ bt_discovery_state_t2str(state));
+}
+
+static void pin_request_cb(bt_bdaddr_t *remote_bd_addr, bt_bdname_t *bd_name,
+ uint32_t cod)
+{
+ haltest_info("%s: remote_bd_addr=%s bd_name=%s cod=%06x\n", __func__,
+ bdaddr2str(remote_bd_addr), bd_name->name, cod);
+}
+
+static void ssp_request_cb(bt_bdaddr_t *remote_bd_addr, bt_bdname_t *bd_name,
+ uint32_t cod, bt_ssp_variant_t pairing_variant,
+ uint32_t pass_key)
+{
+ haltest_info("%s: remote_bd_addr=%s bd_name=%s cod=%06x pairing_variant=%s pass_key=%d\n",
+ __func__, bdaddr2str(remote_bd_addr), bd_name->name, cod,
+ bt_ssp_variant_t2str(pairing_variant), pass_key);
+}
+
+static void bond_state_changed_cb(bt_status_t status,
+ bt_bdaddr_t *remote_bd_addr,
+ bt_bond_state_t state)
+{
+ haltest_info("%s: status=%s remote_bd_addr=%s state=%s\n", __func__,
+ bt_status_t2str(status), bdaddr2str(remote_bd_addr),
+ bt_bond_state_t2str(state));
+}
+
+static void acl_state_changed_cb(bt_status_t status,
+ bt_bdaddr_t *remote_bd_addr,
+ bt_acl_state_t state)
+{
+ haltest_info("%s: status=%s remote_bd_addr=%s state=%s\n", __func__,
+ bt_status_t2str(status), bdaddr2str(remote_bd_addr),
+ bt_acl_state_t2str(state));
+}
+
+static void thread_evt_cb(bt_cb_thread_evt evt)
+{
+ haltest_info("%s: evt=%s\n", __func__, bt_cb_thread_evt2str(evt));
+}
+
+static void dut_mode_recv_cb(uint16_t opcode, uint8_t *buf, uint8_t len)
+{
+ haltest_info("%s\n", __func__);
+}
+
+static void le_test_mode_cb(bt_status_t status, uint16_t num_packets)
+{
+ haltest_info("%s %s %d\n", __func__, bt_state_t2str(status),
+ num_packets);
+}
+
+static bt_callbacks_t bt_callbacks = {
+ sizeof(bt_callbacks),
+ adapter_state_changed_cb,
+ adapter_properties_cb,
+ remote_device_properties_cb,
+ device_found_cb,
+ discovery_state_changed_cb,
+ pin_request_cb,
+ ssp_request_cb,
+ bond_state_changed_cb,
+ acl_state_changed_cb,
+ thread_evt_cb,
+ dut_mode_recv_cb,
+ le_test_mode_cb
+};
+
+static void init_p(int argc, const char **argv)
+{
+ int err;
+ const hw_module_t *module;
+ hw_device_t *device;
+
+ err = hw_get_module(BT_HARDWARE_MODULE_ID, &module);
+ if (err) {
+ haltest_error("he_get_module returned %d\n", err);
+ return;
+ }
+
+ err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
+ if (err) {
+ haltest_error("module->methods->open returned %d\n", err);
+ return;
+ }
+
+ if_bluetooth =
+ ((bluetooth_device_t *)device)->get_bluetooth_interface();
+ if (!if_bluetooth) {
+ haltest_error("get_bluetooth_interface returned NULL\n");
+ return;
+ }
+
+ EXEC(if_bluetooth->init, &bt_callbacks);
+}
+
+static void cleanup_p(int argc, const char **argv)
+{
+ RETURN_IF_NULL(if_bluetooth);
+
+ EXECV(if_bluetooth->cleanup);
+
+ if_bluetooth = NULL;
+}
+
+static void enable_p(int argc, const char **argv)
+{
+ RETURN_IF_NULL(if_bluetooth);
+
+ EXEC(if_bluetooth->enable);
+}
+
+static void disable_p(int argc, const char **argv)
+{
+ RETURN_IF_NULL(if_bluetooth);
+
+ EXEC(if_bluetooth->disable);
+}
+
+static void get_adapter_properties_p(int argc, const char **argv)
+{
+ RETURN_IF_NULL(if_bluetooth);
+
+ EXEC(if_bluetooth->get_adapter_properties);
+}
+
+static void get_adapter_property_p(int argc, const char **argv)
+{
+ int type = str2btpropertytype(argv[2]);
+
+ RETURN_IF_NULL(if_bluetooth);
+
+ EXEC(if_bluetooth->get_adapter_property, type);
+}
+
+static void set_adapter_property_p(int argc, const char **argv)
+{
+ bt_property_t property;
+ bt_scan_mode_t mode;
+ int timeout;
+
+ RETURN_IF_NULL(if_bluetooth);
+
+ property.type = str2btpropertytype(argv[2]);
+
+ switch (property.type) {
+ case BT_PROPERTY_BDNAME:
+ property.len = strlen(argv[3]) + 1;
+ property.val = (char *)argv[3];
+ break;
+
+ case BT_PROPERTY_ADAPTER_SCAN_MODE:
+ mode = str2btscanmode(argv[3]);
+ property.len = sizeof(bt_scan_mode_t);
+ property.val = &mode;
+ break;
+
+ case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
+ timeout = atoi(argv[3]);
+ property.val = &timeout;
+ property.len = sizeof(timeout);
+ break;
+
+ default:
+ haltest_error("Invalid property %s\n", argv[3]);
+ return;
+ }
+
+ EXEC(if_bluetooth->set_adapter_property, &property);
+}
+
+static void get_remote_device_properties_p(int argc, const char **argv)
+{
+ bt_bdaddr_t addr;
+
+ RETURN_IF_NULL(if_bluetooth);
+
+ str2bt_bdaddr_t(argv[2], &addr);
+
+ EXEC(if_bluetooth->get_remote_device_properties, &addr);
+}
+
+static void get_remote_device_property_p(int argc, const char **argv)
+{
+ bt_property_type_t type;
+ bt_bdaddr_t addr;
+
+ RETURN_IF_NULL(if_bluetooth);
+
+ str2bt_bdaddr_t(argv[2], &addr);
+ type = str2btpropertytype(argv[3]);
+
+ EXEC(if_bluetooth->get_remote_device_property, &addr, type);
+}
+
+static void set_remote_device_property_p(int argc, const char **argv)
+{
+ bt_property_t property;
+ bt_bdaddr_t addr;
+
+ RETURN_IF_NULL(if_bluetooth);
+
+ str2bt_bdaddr_t(argv[2], &addr);
+ property.type = str2btpropertytype(argv[3]);
+
+ switch (property.type) {
+ case BT_PROPERTY_REMOTE_FRIENDLY_NAME:
+ property.len = strlen(argv[4]);
+ property.val = (char *)argv[4];
+ break;
+
+ default:
+ return;
+ }
+
+ EXEC(if_bluetooth->set_remote_device_property, &addr, &property);
+}
+
+static void get_remote_service_record_p(int argc, const char **argv)
+{
+ bt_bdaddr_t addr;
+ bt_uuid_t uuid;
+
+ RETURN_IF_NULL(if_bluetooth);
+
+ str2bt_bdaddr_t(argv[2], &addr);
+ str2bt_uuid_t(argv[3], &uuid);
+
+ EXEC(if_bluetooth->get_remote_service_record, &addr, &uuid);
+}
+
+static void get_remote_services_p(int argc, const char **argv)
+{
+ bt_bdaddr_t addr;
+
+ RETURN_IF_NULL(if_bluetooth);
+
+ str2bt_bdaddr_t(argv[2], &addr);
+
+ EXEC(if_bluetooth->get_remote_services, &addr);
+}
+
+static void start_discovery_p(int argc, const char **argv)
+{
+ RETURN_IF_NULL(if_bluetooth);
+
+ EXEC(if_bluetooth->start_discovery);
+}
+
+static void cancel_discovery_p(int argc, const char **argv)
+{
+ RETURN_IF_NULL(if_bluetooth);
+
+ EXEC(if_bluetooth->cancel_discovery);
+}
+
+static void create_bond_p(int argc, const char **argv)
+{
+ bt_bdaddr_t addr;
+
+ RETURN_IF_NULL(if_bluetooth);
+
+ str2bt_bdaddr_t(argv[2], &addr);
+
+ EXEC(if_bluetooth->create_bond, &addr);
+}
+
+static void remove_bond_p(int argc, const char **argv)
+{
+ bt_bdaddr_t addr;
+
+ RETURN_IF_NULL(if_bluetooth);
+
+ str2bt_bdaddr_t(argv[2], &addr);
+
+ EXEC(if_bluetooth->remove_bond, &addr);
+}
+
+static void cancel_bond_p(int argc, const char **argv)
+{
+ bt_bdaddr_t addr;
+
+ RETURN_IF_NULL(if_bluetooth);
+
+ str2bt_bdaddr_t(argv[2], &addr);
+
+ EXEC(if_bluetooth->cancel_bond, &addr);
+}
+
+static void pin_reply_p(int argc, const char **argv)
+{
+ bt_bdaddr_t addr;
+ bt_pin_code_t pin;
+ int pin_len = 0;
+ int accept;
+
+ RETURN_IF_NULL(if_bluetooth);
+
+ if (argc < 3) {
+ haltest_error("No address specified\n");
+ return;
+ }
+ str2bt_bdaddr_t(argv[2], &addr);
+
+ if (argc >= 4) {
+ accept = 1;
+ pin_len = strlen(argv[3]);
+ memcpy(pin.pin, argv[3], pin_len);
+ }
+
+ EXEC(if_bluetooth->pin_reply, &addr, accept, pin_len, &pin);
+}
+
+static void ssp_reply_p(int argc, const char **argv)
+{
+ bt_bdaddr_t addr;
+ bt_ssp_variant_t var;
+ int accept;
+ int passkey;
+
+ RETURN_IF_NULL(if_bluetooth);
+
+ if (argc < 3) {
+ haltest_error("No address specified\n");
+ return;
+ }
+ str2bt_bdaddr_t(argv[2], &addr);
+ if (argc < 4) {
+ haltest_error("No ssp variant specified\n");
+ return;
+ }
+ var = str2btsspvariant(argv[3]);
+ if (argc < 5) {
+ haltest_error("No accept value specified\n");
+ return;
+ }
+ accept = atoi(argv[4]);
+ passkey = 0;
+
+ if (accept && var == BT_SSP_VARIANT_PASSKEY_ENTRY && argc >= 5)
+ passkey = atoi(argv[4]);
+
+ EXEC(if_bluetooth->ssp_reply, &addr, var, accept, passkey);
+}
+
+static void get_profile_interface_p(int argc, const char **argv)
+{
+ const char *id = argv[2];
+ const void **pif = NULL;
+ const void *dummy = NULL;
+
+ RETURN_IF_NULL(if_bluetooth);
+
+ if (strcmp(BT_PROFILE_HANDSFREE_ID, id) == 0)
+ pif = &dummy; /* TODO: chenge when if_hf is there */
+ else if (strcmp(BT_PROFILE_ADVANCED_AUDIO_ID, id) == 0)
+ pif = &dummy; /* TODO: chenge when if_av is there */
+ else if (strcmp(BT_PROFILE_HEALTH_ID, id) == 0)
+ pif = &dummy; /* TODO: chenge when if_hl is there */
+ else if (strcmp(BT_PROFILE_SOCKETS_ID, id) == 0)
+ pif = &dummy; /* TODO: chenge when if_sock is there */
+ else if (strcmp(BT_PROFILE_HIDHOST_ID, id) == 0)
+ pif = &dummy; /* TODO: chenge when if_hh is there */
+ else if (strcmp(BT_PROFILE_PAN_ID, id) == 0)
+ pif = &dummy; /* TODO: chenge when if_pan is there */
+ else if (strcmp(BT_PROFILE_AV_RC_ID, id) == 0)
+ pif = &dummy; /* TODO: chenge when if_rc is there */
+ else
+ haltest_error("%s is not correct for get_profile_interface\n",
+ id);
+
+ if (pif != NULL) {
+ *pif = if_bluetooth->get_profile_interface(id);
+ haltest_info("get_profile_interface(%s) : %p\n", id, *pif);
+ }
+}
+
+static void dut_mode_configure_p(int argc, const char **argv)
+{
+ uint8_t mode;
+
+ RETURN_IF_NULL(if_bluetooth);
+
+ mode = strtol(argv[2], NULL, 0);
+
+ EXEC(if_bluetooth->dut_mode_configure, mode);
+}
+
+static struct method methods[] = {
+ STD_METHOD(init),
+ STD_METHOD(cleanup),
+ STD_METHOD(enable),
+ STD_METHOD(disable),
+ STD_METHOD(get_adapter_properties),
+ STD_METHOD(get_adapter_property),
+ STD_METHOD(set_adapter_property),
+ STD_METHOD(get_remote_device_properties),
+ STD_METHOD(get_remote_device_property),
+ STD_METHOD(set_remote_device_property),
+ STD_METHOD(get_remote_service_record),
+ STD_METHOD(get_remote_services),
+ STD_METHOD(start_discovery),
+ STD_METHOD(cancel_discovery),
+ STD_METHOD(create_bond),
+ STD_METHOD(remove_bond),
+ STD_METHOD(cancel_bond),
+ STD_METHOD(pin_reply),
+ STD_METHOD(ssp_reply),
+ STD_METHOD(get_profile_interface),
+ STD_METHOD(dut_mode_configure),
+ END_METHOD
+};
+
+const struct interface bluetooth_if = {
+ .name = "adapter",
+ .methods = methods
+};
diff --git a/android/hal_client/if_main.h b/android/hal_client/if_main.h
new file mode 100644
index 0000000..fd18dc6
--- /dev/null
+++ b/android/hal_client/if_main.h
@@ -0,0 +1,105 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 Intel Corporation
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/un.h>
+#include <poll.h>
+
+#include <hardware/bluetooth.h>
+#include <hardware/bt_av.h>
+#include <hardware/bt_hh.h>
+#include <hardware/bt_pan.h>
+#include <hardware/bt_sock.h>
+#include <hardware/bt_hf.h>
+#include <hardware/bt_hl.h>
+#include <hardware/bt_rc.h>
+
+#include "textconv.h"
+
+/* Interfaces from hal that can be populated during application lifetime */
+extern const bt_interface_t *if_bluetooth;
+
+/*
+ * Structure defines top level interfaces that can be used in test tool
+ * this will contain values as: adapter, av, gatt, sock, pan...
+ */
+struct interface {
+ const char *name; /* interface name */
+ struct method *methods; /* methods available for this interface */
+};
+
+extern const struct interface bluetooth_if;
+
+/* Interfaces that will show up in tool (first part of command line) */
+extern const struct interface *interfaces[];
+
+#define METHOD(name, func) {name, func}
+#define STD_METHOD(m) {#m, m##_p}
+#define END_METHOD {"", NULL}
+
+/*
+ * Function to parse argument for function, argv[0] and argv[1] are already
+ * parsed before this function is called and contain interface and method name
+ * up to argc - 1 arguments are finished and should be used to decide which
+ * function enumeration function to return
+ */
+typedef void (*parse_and_call)(int argc, const char **argv);
+
+/*
+ * For each method there is name and two functions to parse command line
+ * and call proper hal function on.
+ */
+struct method {
+ const char *name;
+ parse_and_call func;
+};
+
+int haltest_error(const char *format, ...);
+int haltest_info(const char *format, ...);
+int haltest_warn(const char *format, ...);
+
+/* Helper macro for executing function on interface and printing BT_STATUS */
+#define EXEC(f, ...) \
+ { \
+ int err = f(__VA_ARGS__); \
+ haltest_info("%s: %s\n", #f, bt_status_t2str(err)); \
+ }
+
+/* Helper macro for executing void function on interface */
+#define EXECV(f, ...) \
+ { \
+ (void) f(__VA_ARGS__); \
+ haltest_info("%s: void\n", #f); \
+ }
+
+#define RETURN_IF_NULL(x) \
+ do { if (!x) { haltest_error("%s is NULL\n", #x); return; } } while (0)
--
1.7.9.5
^ permalink raw reply related
* [PATCH 4/5] android: Add text conversion helpers to haltest
From: Jerzy Kasenberg @ 2013-10-14 9:59 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Jerzy Kasenberg
In-Reply-To: <1381744794-17994-1-git-send-email-jerzy.kasenberg@tieto.com>
Application uses a lot of text in the form of defines found in header
files to represent arguments and output.
Conversion helpers keep functionality of converting string as
bt_status_t or uuid in one place.
---
android/Android.mk | 1 +
android/hal_client/textconv.c | 211 +++++++++++++++++++++++++++++++++++++++++
android/hal_client/textconv.h | 119 +++++++++++++++++++++++
3 files changed, 331 insertions(+)
create mode 100644 android/hal_client/textconv.c
create mode 100644 android/hal_client/textconv.h
diff --git a/android/Android.mk b/android/Android.mk
index b26a766..a37db38 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -41,6 +41,7 @@ LOCAL_SRC_FILES := \
hal_client/pollhandler.c \
hal_client/terminal.c \
hal_client/history.c \
+ hal_client/textconv.c \
LOCAL_SHARED_LIBRARIES := libhardware
diff --git a/android/hal_client/textconv.c b/android/hal_client/textconv.c
new file mode 100644
index 0000000..6b6d0d2
--- /dev/null
+++ b/android/hal_client/textconv.c
@@ -0,0 +1,211 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 Intel Corporation
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <hardware/bluetooth.h>
+
+#include "textconv.h"
+
+/*
+ * Following are maps of defines found in bluetooth header files to strings
+ *
+ * Those mappings are used to accurately use defines as input parameters in
+ * command line as well as for printing of statuses
+ */
+
+INTMAP(bt_status_t, -1, "(unknown)")
+ DELEMENT(BT_STATUS_SUCCESS),
+ DELEMENT(BT_STATUS_FAIL),
+ DELEMENT(BT_STATUS_NOT_READY),
+ DELEMENT(BT_STATUS_NOMEM),
+ DELEMENT(BT_STATUS_BUSY),
+ DELEMENT(BT_STATUS_DONE),
+ DELEMENT(BT_STATUS_UNSUPPORTED),
+ DELEMENT(BT_STATUS_PARM_INVALID),
+ DELEMENT(BT_STATUS_UNHANDLED),
+ DELEMENT(BT_STATUS_AUTH_FAILURE),
+ DELEMENT(BT_STATUS_RMT_DEV_DOWN),
+ENDMAP
+
+INTMAP(bt_state_t, -1, "(unknown)")
+ DELEMENT(BT_STATE_OFF),
+ DELEMENT(BT_STATE_ON),
+ENDMAP
+
+INTMAP(bt_device_type_t, -1, "(unknown)")
+ DELEMENT(BT_DEVICE_DEVTYPE_BREDR),
+ DELEMENT(BT_DEVICE_DEVTYPE_BLE),
+ DELEMENT(BT_DEVICE_DEVTYPE_DUAL),
+ENDMAP
+
+INTMAP(bt_scan_mode_t, -1, "(unknown)")
+ DELEMENT(BT_SCAN_MODE_NONE),
+ DELEMENT(BT_SCAN_MODE_CONNECTABLE),
+ DELEMENT(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE),
+ENDMAP
+
+INTMAP(bt_discovery_state_t, -1, "(unknown)")
+ DELEMENT(BT_DISCOVERY_STOPPED),
+ DELEMENT(BT_DISCOVERY_STARTED),
+ENDMAP
+
+INTMAP(bt_acl_state_t, -1, "(unknown)")
+ DELEMENT(BT_ACL_STATE_CONNECTED),
+ DELEMENT(BT_ACL_STATE_DISCONNECTED),
+ENDMAP
+
+INTMAP(bt_bond_state_t, -1, "(unknown)")
+ DELEMENT(BT_BOND_STATE_NONE),
+ DELEMENT(BT_BOND_STATE_BONDING),
+ DELEMENT(BT_BOND_STATE_BONDED),
+ENDMAP
+
+INTMAP(bt_ssp_variant_t, -1, "(unknown)")
+ DELEMENT(BT_SSP_VARIANT_PASSKEY_CONFIRMATION),
+ DELEMENT(BT_SSP_VARIANT_PASSKEY_ENTRY),
+ DELEMENT(BT_SSP_VARIANT_CONSENT),
+ DELEMENT(BT_SSP_VARIANT_PASSKEY_NOTIFICATION),
+ENDMAP
+
+INTMAP(bt_property_type_t, -1, "(unknown)")
+ DELEMENT(BT_PROPERTY_BDNAME),
+ DELEMENT(BT_PROPERTY_BDADDR),
+ DELEMENT(BT_PROPERTY_UUIDS),
+ DELEMENT(BT_PROPERTY_CLASS_OF_DEVICE),
+ DELEMENT(BT_PROPERTY_TYPE_OF_DEVICE),
+ DELEMENT(BT_PROPERTY_SERVICE_RECORD),
+ DELEMENT(BT_PROPERTY_ADAPTER_SCAN_MODE),
+ DELEMENT(BT_PROPERTY_ADAPTER_BONDED_DEVICES),
+ DELEMENT(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT),
+ DELEMENT(BT_PROPERTY_REMOTE_FRIENDLY_NAME),
+ DELEMENT(BT_PROPERTY_REMOTE_RSSI),
+ DELEMENT(BT_PROPERTY_REMOTE_VERSION_INFO),
+ DELEMENT(BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP),
+ENDMAP
+
+INTMAP(bt_cb_thread_evt, -1, "(unknown)")
+ DELEMENT(ASSOCIATE_JVM),
+ DELEMENT(DISASSOCIATE_JVM),
+ENDMAP
+
+/* Find first index of given value in table m */
+int int2str_findint(int v, const struct int2str m[])
+{
+ int i;
+
+ for (i = 0; m[i].str; ++i) {
+ if (m[i].val == v)
+ return i;
+ }
+ return -1;
+}
+
+/* Find first index of given string in table m */
+int int2str_findstr(const char *str, const struct int2str m[])
+{
+ int i;
+
+ for (i = 0; m[i].str; ++i) {
+ if (strcmp(m[i].str, str) == 0)
+ return i;
+ }
+ return -1;
+}
+
+/*
+ * convert bd_addr to string
+ * buf must be at least 18 char long
+ *
+ * returns buf
+ */
+char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf)
+{
+ const char *p = (const char *)bd_addr;
+
+ snprintf(buf, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
+ p[0], p[1], p[2], p[3], p[4], p[5]);
+
+ return buf;
+}
+
+/* converts string to bt_bdaddr_t */
+void str2bt_bdaddr_t(const char *str, bt_bdaddr_t *bd_addr)
+{
+ char *p = (char *)bd_addr;
+
+ sscanf(str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+ &p[0], &p[1], &p[2], &p[3], &p[4], &p[5]);
+}
+
+static const char BT_BASE_UUID[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb
+};
+
+/*
+ * converts uuid to string
+ * buf should be at least 39 bytes
+ *
+ * returns string representation of uuid
+ */
+char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf)
+{
+ int shift = 0;
+ int i;
+ int is_bt;
+
+ is_bt = !memcmp(&uuid->uu[4], &BT_BASE_UUID[4], sizeof(bt_uuid_t) - 4);
+
+ for (i = 0; i < (int)sizeof(bt_uuid_t); i++) {
+ if (i == 4 && is_bt)
+ break;
+
+ if (i == 4 || i == 6 || i == 8 || i == 10) {
+ buf[i * 2 + shift] = '-';
+ shift++;
+ }
+ sprintf(buf + i * 2 + shift, "%02x", uuid->uu[i]);
+ }
+
+ return buf;
+}
+
+/* converts string to uuid */
+void str2bt_uuid_t(const char *str, bt_uuid_t *uuid)
+{
+ int i = 0;
+
+ memcpy(uuid, BT_BASE_UUID, sizeof(bt_uuid_t));
+
+ while (*str && i < (int)sizeof(bt_uuid_t)) {
+ while (*str == '-')
+ str++;
+
+ if (sscanf(str, "%02hhx", &uuid->uu[i]) != 1)
+ break;
+
+ i++;
+ str += 2;
+ }
+}
diff --git a/android/hal_client/textconv.h b/android/hal_client/textconv.h
new file mode 100644
index 0000000..6f381b8
--- /dev/null
+++ b/android/hal_client/textconv.h
@@ -0,0 +1,119 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 Intel Corporation
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/**
+ * Begin mapping section
+ *
+ * There are some mappings between integer values (enums) and strings
+ * to be presented to user. To make it easier to convert between those two
+ * set of macros is given. It is specially useful when we want to have
+ * strings that match constants from header files like:
+ * BT_STATUS_SUCCESS (0) and corresponding "BT_STATUS_SUCCESS"
+ * Example of usage:
+ *
+ * INTMAP(int, -1, "invalid")
+ * DELEMENT(BT_STATUS_SUCCESS)
+ * DELEMENT(BT_STATUS_FAIL)
+ * MELEMENT(123, "Some strange value")
+ * ENDMAP
+ *
+ * Just by doing this we have mapping table plus two functions:
+ * int str2int(const char *str);
+ * const char *int2str(int v);
+ *
+ * second argument to INTMAP specifies value to be returned from
+ * str2int function when there is not mapping for such number
+ * third argument specifies default value to be returned from int2str
+ *
+ * If same mapping is to be used in several source files put
+ * INTMAP in c file and DECINTMAP in h file.
+ *
+ * For mappings that are to be used in single file only
+ * use SINTMAP which will create the same but everything will be marked
+ * as static.
+ */
+
+struct int2str {
+ int val; /* int value */
+ const char *str; /* corresponding string */
+};
+
+int int2str_findint(int v, const struct int2str m[]);
+int int2str_findstr(const char *str, const struct int2str m[]);
+
+#define DECINTMAP(type) \
+extern struct int2str __##type##2str[]; \
+const char *type##2##str(type v); \
+type str##2##type(const char *str); \
+
+#define INTMAP(type, deft, defs) \
+const char *type##2##str(type v) \
+{ \
+ int i = int2str_findint((int)v, __##type##2str); \
+ return (i < 0) ? defs : __##type##2str[i].str; \
+} \
+type str##2##type(const char *str) \
+{ \
+ int i = int2str_findstr(str, __##type##2str); \
+ return (i < 0) ? (type)deft : (type)(__##type##2str[i].val); \
+} \
+struct int2str __##type##2str[] = {
+
+#define SINTMAP(type, deft, defs) \
+static struct int2str __##type##2str[]; \
+static inline const char *type##2##str(type v) \
+{ \
+ int i = int2str_findint((int)v, __##type##2str); \
+ return (i < 0) ? defs : __##type##2str[i].str; \
+} \
+static inline type str##2##type(const char *str) \
+{ \
+ int i = int2str_findstr(str, __##type##2str); \
+ return (i < 0) ? (type)deft : (type)(__##type##2str[i].val); \
+} \
+static struct int2str __##type##2str[] = {
+
+#define ENDMAP {0, NULL} };
+
+/* use this to generate string from header file constant */
+#define MELEMENT(v, s) {v, s}
+/* use this to have arbitrary mapping from int to string */
+#define DELEMENT(s) {s, #s}
+/* End of mapping section */
+
+char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf);
+void str2bt_bdaddr_t(const char *str, bt_bdaddr_t *bd_addr);
+
+char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf);
+void str2bt_uuid_t(const char *str, bt_uuid_t *uuid);
+
+DECINTMAP(bt_status_t);
+DECINTMAP(bt_state_t);
+DECINTMAP(bt_device_type_t);
+DECINTMAP(bt_scan_mode_t);
+DECINTMAP(bt_discovery_state_t);
+DECINTMAP(bt_acl_state_t);
+DECINTMAP(bt_bond_state_t);
+DECINTMAP(bt_ssp_variant_t);
+DECINTMAP(bt_property_type_t);
+DECINTMAP(bt_cb_thread_evt);
--
1.7.9.5
^ permalink raw reply related
* [PATCH 3/5] android: Add history to line editor in haltest
From: Jerzy Kasenberg @ 2013-10-14 9:59 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Jerzy Kasenberg
In-Reply-To: <1381744794-17994-1-git-send-email-jerzy.kasenberg@tieto.com>
Added simple history to editor to save time.
---
android/Android.mk | 1 +
android/hal_client/history.c | 104 ++++++++++++++++++++++++++++++++++++++++
android/hal_client/history.h | 27 +++++++++++
android/hal_client/terminal.c | 106 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 238 insertions(+)
create mode 100644 android/hal_client/history.c
create mode 100644 android/hal_client/history.h
diff --git a/android/Android.mk b/android/Android.mk
index c75187d..b26a766 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -40,6 +40,7 @@ LOCAL_SRC_FILES := \
hal_client/haltest.c \
hal_client/pollhandler.c \
hal_client/terminal.c \
+ hal_client/history.c \
LOCAL_SHARED_LIBRARIES := libhardware
diff --git a/android/hal_client/history.c b/android/hal_client/history.c
new file mode 100644
index 0000000..71c1e73
--- /dev/null
+++ b/android/hal_client/history.c
@@ -0,0 +1,104 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 Intel Corporation
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "history.h"
+
+/*
+ * Very simple history storage for easy usage of tool
+ */
+
+#define HISTORY_DEPTH 20
+#define LINE_SIZE 100
+static char lines[HISTORY_DEPTH][LINE_SIZE];
+static int last_line = 0;
+static int history_size = 0;
+
+/* TODO: Storing history not implemented yet */
+void history_store(const char *filename)
+{
+}
+
+/* Restoring history from file */
+void history_restore(const char *filename)
+{
+ char line[1000];
+ FILE *f = fopen(filename, "rt");
+
+ if (f == NULL)
+ return;
+
+ for (;;) {
+ if (fgets(line, 1000, f) != NULL) {
+ int l = strlen(line);
+ while (l > 0 && isspace(line[--l]))
+ line[l] = 0;
+ if (l > 0)
+ history_add_line(line);
+ } else
+ break;
+ }
+ fclose(f);
+}
+
+/* Add new line to history buffer */
+void history_add_line(const char *line)
+{
+ if (line == NULL || strlen(line) == 0)
+ return;
+
+ if (strcmp(line, lines[last_line]) == 0)
+ return;
+
+ last_line = (last_line + 1) % HISTORY_DEPTH;
+ strncpy(&lines[last_line][0], line, LINE_SIZE - 1);
+ if (history_size < HISTORY_DEPTH)
+ history_size++;
+}
+
+/*
+ * Get n-th line from history
+ * 0 - means latest
+ * -1 - means oldest
+ * return -1 if there is no such line
+ */
+int history_get_line(int n, char *buf, int buf_size)
+{
+ if (n == -1)
+ n = history_size - 1;
+
+ if (n >= history_size || buf_size == 0 || n < 0)
+ return -1;
+
+ strncpy(buf,
+ &lines[(HISTORY_DEPTH + last_line - n) % HISTORY_DEPTH][0],
+ buf_size - 1);
+ buf[buf_size - 1] = 0;
+
+ return n;
+}
+
diff --git a/android/hal_client/history.h b/android/hal_client/history.h
new file mode 100644
index 0000000..981f81e
--- /dev/null
+++ b/android/hal_client/history.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 Intel Corporation
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+void history_store(const char *filename);
+void history_restore(const char *filename);
+void history_add_line(const char *line);
+int history_get_line(int n, char *buf, int buf_size);
diff --git a/android/hal_client/terminal.c b/android/hal_client/terminal.c
index e48a413..837e459 100644
--- a/android/hal_client/terminal.c
+++ b/android/hal_client/terminal.c
@@ -28,6 +28,7 @@
#include <termios.h>
#include "terminal.h"
+#include "history.h"
/*
* Character sequences recognized by code in this file
@@ -113,6 +114,9 @@ static int line_buf_ix = 0;
/* current length of input line */
static int line_len = 0;
+/* line index used for fetching lines from history */
+static int line_index = 0;
+
/*
* Moves cursor to right or left
*
@@ -193,6 +197,86 @@ int terminal_vprint(const char *format, va_list args)
}
/*
+ * Call this when text in line_buf was changed
+ * and line needs to be redrawn
+ */
+static void terminal_line_replaced(void)
+{
+ int len = strlen(line_buf);
+
+ /* line is shorter that previous */
+ if (len < line_len) {
+ /* if new line is shorter move cursor to end of new end */
+ while (line_buf_ix > len) {
+ putchar('\b');
+ line_buf_ix--;
+ }
+ /* If cursor was not at the end, move it to the end */
+ if (line_buf_ix < line_len)
+ printf("%.*s", line_len - line_buf_ix,
+ line_buf + line_buf_ix);
+ /* over write end of previous line */
+ while (line_len >= len++)
+ putchar(' ');
+ }
+ /* draw new line */
+ printf("\r>%s", line_buf);
+ /* set up indexes to new line */
+ line_len = line_buf_ix = strlen(line_buf);
+}
+
+/*
+ * Function tries to replace current line with specified line in history
+ * new_line_index - new line to show, -1 to show oldest
+ */
+static void terminal_get_line_from_history(int new_line_index)
+{
+ new_line_index = history_get_line(new_line_index,
+ line_buf, LINE_BUF_MAX);
+
+ if (new_line_index >= 0) {
+ terminal_line_replaced();
+ line_index = new_line_index;
+ }
+}
+
+/*
+ * Function searches history back or forward for command line that starts
+ * with characters up to cursor position
+ *
+ * back - true - searches backward
+ * back - false - searches forward (more recent commands)
+ */
+static void terminal_match_hitory(bool back)
+{
+ char buf[line_buf_ix + 1];
+ int line;
+ int matching_line = -1;
+ int dir = back ? 1 : -1;
+
+ line = line_index + dir;
+ while (matching_line == -1 && line >= 0) {
+ int new_line_index;
+
+ new_line_index = history_get_line(line, buf, line_buf_ix + 1);
+ if (new_line_index < 0)
+ break;
+
+ if (0 == strncmp(line_buf, buf, line_buf_ix))
+ matching_line = line;
+ line += dir;
+ }
+
+ if (matching_line >= 0) {
+ int pos = line_buf_ix;
+ terminal_get_line_from_history(matching_line);
+ /* move back to cursor position to origianl place */
+ line_buf_ix = pos;
+ terminal_move_cursor(pos - line_len);
+ }
+}
+
+/*
* Converts terminal character sequences to single value representing
* keyboard keys
*/
@@ -339,12 +423,29 @@ void terminal_process_char(int c, void (*process_line)(char *line))
printf("%.*s", (int)(line_buf_ix - old_pos),
line_buf + old_pos);
break;
+ case KEY_SUP:
+ terminal_get_line_from_history(-1);
+ break;
+ case KEY_SDOWN:
+ if (line_index > 0)
+ terminal_get_line_from_history(0);
+ break;
case KEY_UP:
+ terminal_get_line_from_history(line_index + 1);
+ break;
case KEY_DOWN:
+ if (line_index > 0)
+ terminal_get_line_from_history(line_index - 1);
break;
case '\n':
case '\r':
+ /*
+ * On new line add line to history
+ * forget history position
+ */
+ history_add_line(line_buf);
line_len = line_buf_ix = 0;
+ line_index = -1;
/* print new line */
putchar(c);
process_line(line_buf);
@@ -386,7 +487,12 @@ void terminal_process_char(int c, void (*process_line)(char *line))
case KEY_MDOWN:
case KEY_STAB:
case KEY_M_n:
+ /* Search history forward */
+ terminal_match_hitory(false);
+ break;
case KEY_M_p:
+ /* Search history backward */
+ terminal_match_hitory(true);
break;
default:
if (!isprint(c)) {
--
1.7.9.5
^ permalink raw reply related
* [PATCH 2/5] android: Add line editing to haltest
From: Jerzy Kasenberg @ 2013-10-14 9:59 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Jerzy Kasenberg
In-Reply-To: <1381744794-17994-1-git-send-email-jerzy.kasenberg@tieto.com>
Android does not have readline.
This patch allows to edit command line.
---
android/Android.mk | 1 +
android/hal_client/haltest.c | 39 +++-
android/hal_client/terminal.c | 434 +++++++++++++++++++++++++++++++++++++++++
android/hal_client/terminal.h | 65 ++++++
4 files changed, 536 insertions(+), 3 deletions(-)
create mode 100644 android/hal_client/terminal.c
create mode 100644 android/hal_client/terminal.h
diff --git a/android/Android.mk b/android/Android.mk
index c6bab81..c75187d 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -39,6 +39,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
hal_client/haltest.c \
hal_client/pollhandler.c \
+ hal_client/terminal.c \
LOCAL_SHARED_LIBRARIES := libhardware
diff --git a/android/hal_client/haltest.c b/android/hal_client/haltest.c
index 8a733a2..a618cf0 100644
--- a/android/hal_client/haltest.c
+++ b/android/hal_client/haltest.c
@@ -25,8 +25,40 @@
#include <poll.h>
#include <unistd.h>
+#include "terminal.h"
#include "pollhandler.h"
+/*
+ * This function changes input parameter line_buffer so it has
+ * null termination after each token (due to strtok)
+ * Output argv is filled with pointers to arguments
+ * returns number of tokens parsed - argc
+ */
+static int command_line_to_argv(char *line_buffer,
+ char *argv[], int argv_size)
+{
+ static const char *token_breaks = "\r\n\t ";
+ char *token;
+ int argc = 0;
+
+ token = strtok(line_buffer, token_breaks);
+ while (token != NULL && argc < (int)argv_size) {
+ argv[argc++] = token;
+ token = strtok(NULL, token_breaks);
+ }
+
+ return argc;
+}
+
+static void process_line(char *line_buffer)
+{
+ char *argv[10];
+ int argc;
+
+ argc = command_line_to_argv(line_buffer, argv, 10);
+
+ /* TODO: process command line */
+}
/* called when there is something on stdin */
static void stdin_handler(struct pollfd *pollfd)
@@ -39,15 +71,16 @@ static void stdin_handler(struct pollfd *pollfd)
if (count > 0) {
int i;
- for (i = 0; i < count; ++i) {
- /* TODO: process input */
- }
+ for (i = 0; i < count; ++i)
+ terminal_process_char(buf[i], process_line);
}
}
}
int main(int argc, char **argv)
{
+ terminal_setup();
+
/* Register command line handler */
poll_register_fd(0, POLLIN, stdin_handler);
diff --git a/android/hal_client/terminal.c b/android/hal_client/terminal.c
new file mode 100644
index 0000000..e48a413
--- /dev/null
+++ b/android/hal_client/terminal.c
@@ -0,0 +1,434 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 Intel Corporation
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdbool.h>
+#include <termios.h>
+
+#include "terminal.h"
+
+/*
+ * Character sequences recognized by code in this file
+ * Leading ESC 0x1B is not included
+ */
+#define SEQ_INSERT "[2~"
+#define SEQ_DELETE "[3~"
+#define SEQ_HOME "OH"
+#define SEQ_END "OF"
+#define SEQ_PGUP "[5~"
+#define SEQ_PGDOWN "[6~"
+#define SEQ_LEFT "[D"
+#define SEQ_RIGHT "[C"
+#define SEQ_UP "[A"
+#define SEQ_DOWN "[B"
+#define SEQ_STAB "[Z"
+#define SEQ_M_n "n"
+#define SEQ_M_p "p"
+#define SEQ_CLEFT "[1;5D"
+#define SEQ_CRIGHT "[1;5C"
+#define SEQ_CUP "[1;5A"
+#define SEQ_CDOWN "[1;5B"
+#define SEQ_SLEFT "[1;2D"
+#define SEQ_SRIGHT "[1;2C"
+#define SEQ_SUP "[1;2A"
+#define SEQ_SDOWN "[1;2B"
+#define SEQ_MLEFT "[1;3D"
+#define SEQ_MRIGHT "[1;3C"
+#define SEQ_MUP "[1;3A"
+#define SEQ_MDOWN "[1;3B"
+
+#define KEY_SEQUENCE(k) { KEY_##k, SEQ_##k }
+struct ansii_sequence {
+ int code;
+ const char *sequence;
+};
+
+/* Table connects single int key codes with character sequences */
+static const struct ansii_sequence ansii_sequnces[] = {
+ KEY_SEQUENCE(INSERT),
+ KEY_SEQUENCE(DELETE),
+ KEY_SEQUENCE(HOME),
+ KEY_SEQUENCE(END),
+ KEY_SEQUENCE(PGUP),
+ KEY_SEQUENCE(PGDOWN),
+ KEY_SEQUENCE(LEFT),
+ KEY_SEQUENCE(RIGHT),
+ KEY_SEQUENCE(UP),
+ KEY_SEQUENCE(DOWN),
+ KEY_SEQUENCE(CLEFT),
+ KEY_SEQUENCE(CRIGHT),
+ KEY_SEQUENCE(CUP),
+ KEY_SEQUENCE(CDOWN),
+ KEY_SEQUENCE(SLEFT),
+ KEY_SEQUENCE(SRIGHT),
+ KEY_SEQUENCE(SUP),
+ KEY_SEQUENCE(SDOWN),
+ KEY_SEQUENCE(MLEFT),
+ KEY_SEQUENCE(MRIGHT),
+ KEY_SEQUENCE(MUP),
+ KEY_SEQUENCE(MDOWN),
+ KEY_SEQUENCE(STAB),
+ KEY_SEQUENCE(M_p),
+ KEY_SEQUENCE(M_n),
+ { 0, NULL }
+};
+
+#define isseqence(c) ((c) == 0x1B)
+
+/*
+ * Number of characters that consist of ANSII sequence
+ * Should not be less then longest string in ansii_sequnces
+ */
+#define MAX_ASCII_SEQUENCE 10
+
+static char current_sequence[MAX_ASCII_SEQUENCE];
+static int current_sequence_len = -1;
+
+/* single line typed by user goes here */
+static char line_buf[LINE_BUF_MAX];
+/* index of cursor in input line */
+static int line_buf_ix = 0;
+/* current length of input line */
+static int line_len = 0;
+
+/*
+ * Moves cursor to right or left
+ *
+ * n - positive - moves cursor right
+ * n - negative - moves cursor left
+ */
+static void terminal_move_cursor(int n)
+{
+ if (n < 0) {
+ for (; n < 0; n++)
+ putchar('\b');
+ } else if (n > 0)
+ printf("%*s", n, line_buf + line_buf_ix);
+}
+
+/* Draw command line */
+void terminal_draw_command_line(void)
+{
+ /*
+ * this needs to be checked here since line_buf is not cleard
+ * before parsing event though line_len and line_buf_ix are
+ */
+ if (line_len > 0)
+ printf(">%s", line_buf);
+ else
+ putchar('>');
+
+ /* move cursor to it's place */
+ terminal_move_cursor(line_len - line_buf_ix);
+}
+
+/* inserts string into command line at cursor position */
+void terminal_insert_into_command_line(const char *p)
+{
+ int len = strlen(p);
+
+ if (line_len == line_buf_ix) {
+ strcat(line_buf, p);
+ printf("%s", p);
+ line_buf_ix = line_len = line_len + len;
+ } else {
+ memmove(line_buf + line_buf_ix + len,
+ line_buf + line_buf_ix, line_len - line_buf_ix + 1);
+ memmove(line_buf + line_buf_ix, p, len);
+ printf("%s", line_buf + line_buf_ix);
+ line_buf_ix += len;
+ line_len += len;
+ terminal_move_cursor(line_buf_ix - line_len);
+ }
+}
+
+/* Prints string and redraws command line */
+int terminal_print(const char *format, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, format);
+
+ ret = terminal_vprint(format, args);
+
+ va_end(args);
+ return ret;
+}
+
+/* Prints string and redraws command line */
+int terminal_vprint(const char *format, va_list args)
+{
+ int ret;
+
+ printf("\r%*s\r", (int)line_len + 1, " ");
+
+ ret = vprintf(format, args);
+
+ terminal_draw_command_line();
+
+ return ret;
+}
+
+/*
+ * Converts terminal character sequences to single value representing
+ * keyboard keys
+ */
+static int terminal_convert_sequence(int c)
+{
+ int i;
+
+ /* Not in sequence yet? */
+ if (current_sequence_len == -1) {
+ /* Is ansii sequence detected by 0x1B ? */
+ if (isseqence(c)) {
+ current_sequence_len++;
+ return 0;
+ }
+ return c;
+ }
+ /* Inside sequence */
+ current_sequence[current_sequence_len++] = c;
+ current_sequence[current_sequence_len] = '\0';
+ for (i = 0; ansii_sequnces[i].code; ++i) {
+ /* Matches so far? */
+ if (0 != strncmp(current_sequence,
+ ansii_sequnces[i].sequence, current_sequence_len))
+ continue;
+
+ /* Matches as a whole? */
+ if (ansii_sequnces[i].sequence[current_sequence_len] == 0) {
+ current_sequence_len = -1;
+ return ansii_sequnces[i].code;
+ }
+ /* partial match (not whole sequence yet) */
+ return 0;
+ }
+ terminal_print("ansii char 0x%X %c\n", c);
+ /*
+ * Sequence does not match
+ * mark that no in sequence any more, return char
+ */
+ current_sequence_len = -1;
+ return c;
+}
+
+void terminal_process_char(int c, void (*process_line)(char *line))
+{
+ int refresh_from = -1;
+ int old_pos;
+
+ c = terminal_convert_sequence(c);
+
+ switch (c) {
+ case 0:
+ break;
+ case KEY_LEFT:
+ /* if not at the beginning move to previous character */
+ if (line_buf_ix <= 0)
+ break;
+ line_buf_ix--;
+ terminal_move_cursor(-1);
+ break;
+ case KEY_RIGHT:
+ /*
+ * If not at the end, just print current character
+ * and modify position
+ */
+ if (line_buf_ix < line_len)
+ putchar(line_buf[line_buf_ix++]);
+ break;
+ case KEY_HOME:
+ /* move to beginning of line and update position */
+ putchar('\r');
+ putchar('>');
+ line_buf_ix = 0;
+ break;
+ case KEY_END:
+ /* if not at the end of line */
+ if (line_buf_ix < line_len) {
+ /* print everything from cursor */
+ printf("%s", line_buf + line_buf_ix);
+ /* just modify current position */
+ line_buf_ix = line_len;
+ }
+ break;
+ case KEY_DELETE:
+ /* delete character under cursor if not at the very end */
+ if (line_buf_ix >= line_len)
+ break;
+ /*
+ * Prepare buffer with one character missing
+ * trailing 0 is moved
+ */
+ line_len--;
+ memmove(line_buf + line_buf_ix,
+ line_buf + line_buf_ix + 1,
+ line_len - line_buf_ix + 1);
+ /* print rest of line from current cursor position */
+ printf("%s \b", line_buf + line_buf_ix);
+ /* move back cursor */
+ terminal_move_cursor(line_buf_ix - line_len);
+ break;
+ case KEY_CLEFT:
+ /*
+ * Move by word left
+ *
+ * Are we at the beginning of line?
+ */
+ if (line_buf_ix <= 0)
+ break;
+
+ old_pos = line_buf_ix;
+ line_buf_ix--;
+ /* skip spaces left */
+ while (line_buf_ix && isspace(line_buf[line_buf_ix]))
+ line_buf_ix--;
+ /* skip all non spaces to the left */
+ while (line_buf_ix > 0 &&
+ !isspace(line_buf[line_buf_ix - 1]))
+ line_buf_ix--;
+ /* move cursor to new position */
+ terminal_move_cursor(line_buf_ix - old_pos);
+ break;
+ case KEY_CRIGHT:
+ /*
+ * Move by word right
+ *
+ * are we at the end of line?
+ */
+ if (line_buf_ix >= line_len)
+ break;
+
+ old_pos = line_buf_ix;
+ /* skip all spaces */
+ while (line_buf_ix < line_len &&
+ isspace(line_buf[line_buf_ix]))
+ line_buf_ix++;
+ /* skip all non spaces */
+ while (line_buf_ix < line_len &&
+ !isspace(line_buf[line_buf_ix]))
+ line_buf_ix++;
+ /*
+ * Move cursor to right by printing text
+ * between old cursor and new
+ */
+ if (line_buf_ix > old_pos)
+ printf("%.*s", (int)(line_buf_ix - old_pos),
+ line_buf + old_pos);
+ break;
+ case KEY_UP:
+ case KEY_DOWN:
+ break;
+ case '\n':
+ case '\r':
+ line_len = line_buf_ix = 0;
+ /* print new line */
+ putchar(c);
+ process_line(line_buf);
+ /* clear current line */
+ line_buf[0] = '\0';
+ putchar('>');
+ break;
+ case '\t':
+ /* tab processing */
+ /* TODO Add completion here */
+ break;
+ case KEY_BACKSPACE:
+ if (line_buf_ix <= 0)
+ break;
+
+ if (line_buf_ix == line_len) {
+ printf("\b \b");
+ line_len = --line_buf_ix;
+ line_buf[line_len] = 0;
+ } else {
+ putchar('\b');
+ refresh_from = --line_buf_ix;
+ line_len--;
+ memmove(line_buf + line_buf_ix,
+ line_buf + line_buf_ix + 1,
+ line_len - line_buf_ix + 1);
+ }
+ break;
+ case KEY_INSERT:
+ case KEY_PGUP:
+ case KEY_PGDOWN:
+ case KEY_CUP:
+ case KEY_CDOWN:
+ case KEY_SLEFT:
+ case KEY_SRIGHT:
+ case KEY_MLEFT:
+ case KEY_MRIGHT:
+ case KEY_MUP:
+ case KEY_MDOWN:
+ case KEY_STAB:
+ case KEY_M_n:
+ case KEY_M_p:
+ break;
+ default:
+ if (!isprint(c)) {
+ /*
+ * TODO: remove this print once all meaningful sequences
+ * are identified
+ */
+ printf("char-0x%02x\n", c);
+ break;
+ }
+ if (line_buf_ix < LINE_BUF_MAX - 1) {
+ if (line_len == line_buf_ix) {
+ putchar(c);
+ line_buf[line_buf_ix++] = (char)c;
+ line_len++;
+ line_buf[line_len] = '\0';
+ } else {
+ memmove(line_buf + line_buf_ix + 1,
+ line_buf + line_buf_ix,
+ line_len - line_buf_ix + 1);
+ line_buf[line_buf_ix] = c;
+ refresh_from = line_buf_ix++;
+ line_len++;
+ }
+ }
+ break;
+ }
+
+ if (refresh_from >= 0) {
+ printf("%s \b", line_buf + refresh_from);
+ terminal_move_cursor(line_buf_ix - line_len);
+ }
+}
+
+void terminal_setup(void)
+{
+ struct termios tios;
+
+ /* Turn off echo since all editing is done by hand */
+ tcgetattr(0, &tios);
+ tios.c_lflag &= ~(ICANON | ECHO);
+ tcsetattr(0, TCSANOW, &tios);
+ putchar('>');
+}
+
diff --git a/android/hal_client/terminal.h b/android/hal_client/terminal.h
new file mode 100644
index 0000000..073ebf0
--- /dev/null
+++ b/android/hal_client/terminal.h
@@ -0,0 +1,65 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 Intel Corporation
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdarg.h>
+
+/* size of supported line */
+#define LINE_BUF_MAX 1024
+
+enum key_codes {
+ KEY_BACKSPACE = 0x7F,
+ KEY_INSERT = 1000, /* arbitrary value */
+ KEY_DELETE,
+ KEY_HOME,
+ KEY_END,
+ KEY_PGUP,
+ KEY_PGDOWN,
+ KEY_LEFT,
+ KEY_RIGHT,
+ KEY_UP,
+ KEY_DOWN,
+ KEY_CLEFT,
+ KEY_CRIGHT,
+ KEY_CUP,
+ KEY_CDOWN,
+ KEY_SLEFT,
+ KEY_SRIGHT,
+ KEY_SUP,
+ KEY_SDOWN,
+ KEY_MLEFT,
+ KEY_MRIGHT,
+ KEY_MUP,
+ KEY_MDOWN,
+ KEY_STAB,
+ KEY_M_p,
+ KEY_M_n
+};
+
+void terminal_setup(void);
+int terminal_print(const char *format, ...);
+int terminal_vprint(const char *format, va_list args);
+void terminal_process_char(int c, void (*process_line)(char *line));
+void terminal_insert_into_command_line(const char *p);
+void terminal_draw_command_line(void);
+
+void process_tab(const char *line, int len);
--
1.7.9.5
^ permalink raw reply related
* [PATCH 1/5] android: Add haltest skeleton
From: Jerzy Kasenberg @ 2013-10-14 9:59 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Jerzy Kasenberg
In-Reply-To: <1381744794-17994-1-git-send-email-jerzy.kasenberg@tieto.com>
This tool will be used to test Android Bluetooth HAL implementation.
---
android/Android.mk | 17 +++++
android/hal_client/haltest.c | 57 +++++++++++++++++
android/hal_client/pollhandler.c | 129 ++++++++++++++++++++++++++++++++++++++
android/hal_client/pollhandler.h | 32 ++++++++++
4 files changed, 235 insertions(+)
create mode 100644 android/hal_client/haltest.c
create mode 100644 android/hal_client/pollhandler.c
create mode 100644 android/hal_client/pollhandler.h
diff --git a/android/Android.mk b/android/Android.mk
index ec820ac..c6bab81 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -29,3 +29,20 @@ LOCAL_SHARED_LIBRARIES := \
LOCAL_MODULE := bluetoothd
include $(BUILD_EXECUTABLE)
+
+#
+# haltest
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ hal_client/haltest.c \
+ hal_client/pollhandler.c \
+
+LOCAL_SHARED_LIBRARIES := libhardware
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := haltest
+
+include $(BUILD_EXECUTABLE)
diff --git a/android/hal_client/haltest.c b/android/hal_client/haltest.c
new file mode 100644
index 0000000..8a733a2
--- /dev/null
+++ b/android/hal_client/haltest.c
@@ -0,0 +1,57 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 Intel Corporation
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdlib.h>
+#include <poll.h>
+#include <unistd.h>
+
+#include "pollhandler.h"
+
+
+/* called when there is something on stdin */
+static void stdin_handler(struct pollfd *pollfd)
+{
+ char buf[10];
+
+ if (pollfd->revents & POLLIN) {
+ int count = read(0, buf, 10);
+
+ if (count > 0) {
+ int i;
+
+ for (i = 0; i < count; ++i) {
+ /* TODO: process input */
+ }
+ }
+ }
+}
+
+int main(int argc, char **argv)
+{
+ /* Register command line handler */
+ poll_register_fd(0, POLLIN, stdin_handler);
+
+ poll_dispatch_loop();
+
+ return 0;
+}
diff --git a/android/hal_client/pollhandler.c b/android/hal_client/pollhandler.c
new file mode 100644
index 0000000..14cff34
--- /dev/null
+++ b/android/hal_client/pollhandler.c
@@ -0,0 +1,129 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 Intel Corporation
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <poll.h>
+
+#include "pollhandler.h"
+
+/*
+ * Code that allows to poll multiply file descriptors for events
+ * File descriptors can be added and removed at runtime
+ *
+ * Call poll_register_fd function first to add file descriptors to monitor
+ * Then call poll_dispatch_loop that will poll all registered file descriptors
+ * as long as they are not unregistered.
+ *
+ * When event happen on given fd appropriate user supplied handler is called
+ */
+
+/* Maximum number of files to monitor */
+#define MAX_OPEN_FD 10
+
+/* Storage for pollfd structures for monitored file descriptors */
+static struct pollfd fds[MAX_OPEN_FD];
+static poll_handler fds_handler[MAX_OPEN_FD];
+/* Number of registered file descriptors */
+static int fds_count = 0;
+
+/*
+ * Function polls file descriptor in loop and calls appropriate handler
+ * on event. Function returns when there is no more file descriptor to
+ * monitor
+ */
+void poll_dispatch_loop(void)
+{
+ while (fds_count > 0) {
+ int i;
+ int cur_fds_count = fds_count;
+ int ready = poll(fds, fds_count, 1000);
+
+ for (i = 0; i < fds_count && ready > 0; ++i) {
+ if (fds[i].revents == 0)
+ continue;
+
+ fds_handler[i](fds + i);
+ ready--;
+ /*
+ * If handler was remove from table
+ * just skip the rest and poll again
+ * This is due to reordering of tables in
+ * register/unregister functions
+ */
+ if (cur_fds_count != fds_count)
+ break;
+ }
+ /*
+ * This seems to be needed for correct output handling
+ * when all waiting is performed in poll
+ */
+ fflush(stdout);
+ }
+}
+
+/*
+ * Registers file descriptor to be monitored for events (see man poll(2))
+ * for events.
+ *
+ * return non negative value on success
+ * -EMFILE when there are to much descriptors
+ */
+int poll_register_fd(int fd, short events, poll_handler ph)
+{
+ if (fds_count >= MAX_OPEN_FD)
+ return -EMFILE;
+
+ fds_handler[fds_count] = ph;
+ fds[fds_count].fd = fd;
+ fds[fds_count].events = events;
+ fds_count++;
+
+ return fds_count;
+}
+
+/*
+ * Unregisters file descriptor
+ * Both fd and ph must match previously registered data
+ *
+ * return 0 if unregister succeeded
+ * -EBADF if arguments do not match any register handler
+ */
+int poll_unregister_fd(int fd, poll_handler ph)
+{
+ int i;
+
+ for (i = 0; i < fds_count; ++i) {
+ if (fds_handler[i] == ph && fds[i].fd == fd) {
+ fds_count--;
+ if (i < fds_count) {
+ fds[i].fd = fds[fds_count].fd;
+ fds[i].events = fds[fds_count].events;
+ fds_handler[i] = fds_handler[fds_count];
+ }
+ return 0;
+ }
+ }
+ return -EBADF;
+}
+
diff --git a/android/hal_client/pollhandler.h b/android/hal_client/pollhandler.h
new file mode 100644
index 0000000..c011786
--- /dev/null
+++ b/android/hal_client/pollhandler.h
@@ -0,0 +1,32 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 Intel Corporation
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <poll.h>
+
+/* Function to be called when there are event for some descriptor */
+typedef void (*poll_handler)(struct pollfd *pollfd);
+
+int poll_register_fd(int fd, short events, poll_handler ph);
+int poll_unregister_fd(int fd, poll_handler ph);
+
+void poll_dispatch_loop(void);
--
1.7.9.5
^ permalink raw reply related
* [PATCH 0/5] Stack independent BT HAL test tool
From: Jerzy Kasenberg @ 2013-10-14 9:59 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Jerzy Kasenberg
This tool is for testing Android HAL interfaces from command line.
Due to lack of readline on Android simple equivalent is hand coded.
This tool can be used with bluedroid stack so no glib dependency.
Tool source code is in folder hal_client, please comment if it should be
somewhere else.
Comments welcome.
Best regards
Jerzy Kasenberg
Jerzy Kasenberg (5):
android: Add haltest skeleton
android: Add line editing to haltest
android: Add history to line editor in haltest
android: Add text conversion helpers to haltest
android: Add calls to adapter methods in haltest
android/Android.mk | 21 ++
android/hal_client/haltest.c | 167 ++++++++++
android/hal_client/history.c | 104 +++++++
android/hal_client/history.h | 27 ++
android/hal_client/if_bt.c | 637 ++++++++++++++++++++++++++++++++++++++
android/hal_client/if_main.h | 105 +++++++
android/hal_client/pollhandler.c | 129 ++++++++
android/hal_client/pollhandler.h | 32 ++
android/hal_client/terminal.c | 540 ++++++++++++++++++++++++++++++++
android/hal_client/terminal.h | 65 ++++
android/hal_client/textconv.c | 211 +++++++++++++
android/hal_client/textconv.h | 119 +++++++
12 files changed, 2157 insertions(+)
create mode 100644 android/hal_client/haltest.c
create mode 100644 android/hal_client/history.c
create mode 100644 android/hal_client/history.h
create mode 100644 android/hal_client/if_bt.c
create mode 100644 android/hal_client/if_main.h
create mode 100644 android/hal_client/pollhandler.c
create mode 100644 android/hal_client/pollhandler.h
create mode 100644 android/hal_client/terminal.c
create mode 100644 android/hal_client/terminal.h
create mode 100644 android/hal_client/textconv.c
create mode 100644 android/hal_client/textconv.h
--
1.7.9.5
^ permalink raw reply
* [PATCH] Bluetooth: Introduce L2CAP channel callback for resuming
From: Marcel Holtmann @ 2013-10-14 9:53 UTC (permalink / raw)
To: linux-bluetooth
Clearing the BT_SK_SUSPEND socket flag from the L2CAP core is causing
a dependency on the socket. So intead of doing that, use a channel
callback into the socket handling to resume.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
include/net/bluetooth/l2cap.h | 1 +
net/bluetooth/l2cap_core.c | 6 +-----
net/bluetooth/l2cap_sock.c | 9 +++++++++
3 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 1a38ede..07757a2 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -554,6 +554,7 @@ struct l2cap_ops {
int state);
void (*ready) (struct l2cap_chan *chan);
void (*defer) (struct l2cap_chan *chan);
+ void (*resume) (struct l2cap_chan *chan);
struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan,
unsigned long len, int nb);
};
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index e5819cb..0c3446d 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -6669,11 +6669,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
if (!status && (chan->state == BT_CONNECTED ||
chan->state == BT_CONFIG)) {
- struct sock *sk = chan->sk;
-
- clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
- sk->sk_state_change(sk);
-
+ chan->ops->resume(chan);
l2cap_check_encryption(chan, encrypt);
l2cap_chan_unlock(chan);
continue;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index f5d9573..fcf012a 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1112,6 +1112,14 @@ static void l2cap_sock_defer_cb(struct l2cap_chan *chan)
parent->sk_data_ready(parent, 0);
}
+static void l2cap_sock_resume_cb(struct l2cap_chan *chan)
+{
+ struct sock *sk = chan->data;
+
+ clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
+ sk->sk_state_change(sk);
+}
+
static struct l2cap_ops l2cap_chan_ops = {
.name = "L2CAP Socket Interface",
.new_connection = l2cap_sock_new_connection_cb,
@@ -1121,6 +1129,7 @@ static struct l2cap_ops l2cap_chan_ops = {
.state_change = l2cap_sock_state_change_cb,
.ready = l2cap_sock_ready_cb,
.defer = l2cap_sock_defer_cb,
+ .resume = l2cap_sock_resume_cb,
.alloc_skb = l2cap_sock_alloc_skb_cb,
};
--
1.8.3.1
^ permalink raw reply related
* [PATCH] Bluetooth: Introduce L2CAP channel flag for defer setup
From: Marcel Holtmann @ 2013-10-14 9:45 UTC (permalink / raw)
To: linux-bluetooth
The L2CAP core should not look into the socket flags to figure out the
setting of defer setup. So introduce a L2CAP channel flag that mirrors
the socket flag.
Since the defer setup option is only set in one place this becomes a
really easy thing to do.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
include/net/bluetooth/l2cap.h | 1 +
net/bluetooth/l2cap_core.c | 15 +++++++--------
net/bluetooth/l2cap_sock.c | 7 +++++--
3 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index a27d51d..1a38ede 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -652,6 +652,7 @@ enum {
FLAG_FLUSHABLE,
FLAG_EXT_CTRL,
FLAG_EFS_ENABLE,
+ FLAG_DEFER_SETUP,
};
enum {
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index f6b5f94..e5819cb 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -655,14 +655,14 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
case BT_CONNECT2:
if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
conn->hcon->type == ACL_LINK) {
- struct sock *sk = chan->sk;
struct l2cap_conn_rsp rsp;
__u16 result;
- if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
+ if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
result = L2CAP_CR_SEC_BLOCK;
else
result = L2CAP_CR_BAD_PSM;
+
l2cap_state_change(chan, BT_DISCONN);
rsp.scid = cpu_to_le16(chan->dcid);
@@ -1294,16 +1294,16 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
l2cap_start_connection(chan);
} else if (chan->state == BT_CONNECT2) {
- struct sock *sk = chan->sk;
struct l2cap_conn_rsp rsp;
char buf[128];
rsp.scid = cpu_to_le16(chan->dcid);
rsp.dcid = cpu_to_le16(chan->scid);
if (l2cap_chan_check_security(chan)) {
+ struct sock *sk = chan->sk;
+
lock_sock(sk);
- if (test_bit(BT_SK_DEFER_SETUP,
- &bt_sk(sk)->flags)) {
+ if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
chan->ops->defer(chan);
@@ -3823,7 +3823,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
if (l2cap_chan_check_security(chan)) {
- if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
+ if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
__l2cap_state_change(chan, BT_CONNECT2);
result = L2CAP_CR_PEND;
status = L2CAP_CS_AUTHOR_PEND;
@@ -6693,8 +6693,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
lock_sock(sk);
if (!status) {
- if (test_bit(BT_SK_DEFER_SETUP,
- &bt_sk(sk)->flags)) {
+ if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
res = L2CAP_CR_PEND;
stat = L2CAP_CS_AUTHOR_PEND;
chan->ops->defer(chan);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index f1b462f..f5d9573 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -672,10 +672,13 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break;
}
- if (opt)
+ if (opt) {
set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
- else
+ set_bit(FLAG_DEFER_SETUP, &chan->flags);
+ } else {
clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
+ clear_bit(FLAG_DEFER_SETUP, &chan->flags);
+ }
break;
case BT_FLUSHABLE:
--
1.8.3.1
^ permalink raw reply related
* Re: [RFC] Bluetooth: Set ISOC altsetting from within notify callback
From: Timo Mueller @ 2013-10-14 9:20 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <DC0E2A8A-DF32-4E70-ACF4-B203D17057B9@holtmann.org>
Hi Marcel,
Am 11.10.2013 14:36, schrieb Marcel Holtmann:
> Hi Timo,
>
>>> Since the event handling is done within a workqueue, the notify
>>> callback can now sleep. So no need to trigger a separate workqueue
>>> from within the Bluetooth USB driver.
>>>
>>> This should give a little bit better latency with the SCO packet
>>> processing since the ISOC altsetting is correct from the beginning.
>>>
>>> However I am not sure if we can actually sleep in the USB reset
>>> handler and what we need to do to restore the correct altsetting
>>> in there. This could potentially fail, so please test ;)
>>>
>>> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
>>> ---
>>> drivers/bluetooth/btusb.c | 34 ++++++++++++++--------------------
>>> 1 file changed, 14 insertions(+), 20 deletions(-)
>>>
>>> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
>>> index f3dfc0a..32cae73 100644
>>> --- a/drivers/bluetooth/btusb.c
>>> +++ b/drivers/bluetooth/btusb.c
>>> @@ -245,7 +245,6 @@ struct btusb_data {
>>>
>>> unsigned long flags;
>>>
>>> - struct work_struct work;
>>> struct work_struct waker;
>>>
>>> struct usb_anchor tx_anchor;
>>> @@ -685,7 +684,6 @@ static int btusb_close(struct hci_dev *hdev)
>>> if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
>>> return 0;
>>>
>>> - cancel_work_sync(&data->work);
>>> cancel_work_sync(&data->waker);
>>>
>>> clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
>>> @@ -827,18 +825,6 @@ done:
>>> return err;
>>> }
>>>
>>> -static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
>>> -{
>>> - struct btusb_data *data = hci_get_drvdata(hdev);
>>> -
>>> - BT_DBG("%s evt %d", hdev->name, evt);
>>> -
>>> - if (hdev->conn_hash.sco_num != data->sco_num) {
>>> - data->sco_num = hdev->conn_hash.sco_num;
>>> - schedule_work(&data->work);
>>> - }
>>> -}
>>> -
>>> static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
>>> {
>>> struct btusb_data *data = hci_get_drvdata(hdev);
>>> @@ -882,9 +868,8 @@ static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
>>> return 0;
>>> }
>>>
>>> -static void btusb_work(struct work_struct *work)
>>> +static void btusb_update_isoc_altsetting(struct btusb_data *data)
>>> {
>>> - struct btusb_data *data = container_of(work, struct btusb_data, work);
>>> struct hci_dev *hdev = data->hdev;
>>> int new_alts;
>>> int err;
>>> @@ -932,6 +917,18 @@ static void btusb_work(struct work_struct *work)
>>> }
>>> }
>>>
>>> +static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
>>> +{
>>> + struct btusb_data *data = hci_get_drvdata(hdev);
>>> +
>>> + BT_DBG("%s evt %d", hdev->name, evt);
>>> +
>>> + if (hdev->conn_hash.sco_num != data->sco_num) {
>>> + data->sco_num = hdev->conn_hash.sco_num;
>>> + btusb_update_isoc_altsetting(data);
>>> + }
>>> +}
>>> +
>>> static void btusb_waker(struct work_struct *work)
>>> {
>>> struct btusb_data *data = container_of(work, struct btusb_data, waker);
>>> @@ -1404,7 +1401,6 @@ static int btusb_probe(struct usb_interface *intf,
>>>
>>> spin_lock_init(&data->lock);
>>>
>>> - INIT_WORK(&data->work, btusb_work);
>>> INIT_WORK(&data->waker, btusb_waker);
>>> spin_lock_init(&data->txlock);
>>>
>>> @@ -1540,8 +1536,6 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
>>> return -EBUSY;
>>> }
>>>
>>> - cancel_work_sync(&data->work);
>>> -
>>> btusb_stop_traffic(data);
>>> usb_kill_anchored_urbs(&data->tx_anchor);
>>>
>>> @@ -1606,8 +1600,8 @@ static int btusb_resume(struct usb_interface *intf)
>>> play_deferred(data);
>>> clear_bit(BTUSB_SUSPENDING, &data->flags);
>>> spin_unlock_irq(&data->txlock);
>>> - schedule_work(&data->work);
>>>
>>> + btusb_update_isoc_altsetting(data);
>>> return 0;
>>>
>>> failed:
>>>
>> I have been testing this patch for the last two days at the UPF in Vienna. It was running fine most of the time, but I experienced two crashes. Both crashes appeared when there was an active call and the phone transferred audio to the phone and back. Both times I wasn't able to reproduce, when I restarted everything and tested again it worked fine.
>>
>> Unfortunately the kernel log is not complete but, when it failed the kernel reported:
>> [147.344546] Bluetooth: hci0 SCO packet for unknown connection handle 5
>> [147.354515] Bluetooth: hci0 SCO packet for unknown connection handle 21
>> [147.354537] Bluetooth: hci0 SCO packet for unknown connection handle 29
>> [147.354548] Bluetooth: hci0 SCO packet for unknown connection handle 65534
>> [147.364574] Bluetooth: hci0 SCO packet for unknown connection handle 65532
>> [147.364581] Bluetooth: hci0 SCO packet for unknown connection handle 27
>> …
> what kind of hardware where you testing with?
It was nothing special, an off-the-shelf CSR USB BT Dongle.
>
> This handle mismatch normally means that our SCO packet frames are out of sync. I think we are not doing a good job trying to keep them nicely lined up.
>
> For the crash, do you happen to have a backtrace of the crash. Personally I was worried about the reset handling and not the actual alternate setting switching.
Unfortunately I haven't. To be precise the first crash wasn't even a
crash, as everything was continuing to run, but without a working audio
of course. The second time my system completely froze, but due to my
fault I wasn't able to pull the backtrace. I'll see if I can reproduce
this week and send a backtrace if I manage to.
>
> Regards
>
> Marcel
Regards,
Timo
^ permalink raw reply
* [PATCH] Bluetooth: Adjust header for proc socket information
From: Marcel Holtmann @ 2013-10-14 9:05 UTC (permalink / raw)
To: linux-bluetooth
The exposed socket information do not contain source or destination
addresses. So adjust the header accordingly.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/af_bluetooth.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 61501c9..1f1a111 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -611,7 +611,7 @@ static int bt_seq_show(struct seq_file *seq, void *v)
struct bt_sock_list *l = s->l;
if (v == SEQ_START_TOKEN) {
- seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent");
+ seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Parent");
if (l->custom_seq_show) {
seq_putc(seq, ' ');
--
1.8.3.1
^ permalink raw reply related
* [RFC] doc: Draft of 3D synchronization mgmt commands
From: Marcel Holtmann @ 2013-10-14 8:45 UTC (permalink / raw)
To: linux-bluetooth
---
doc/mgmt-api.txt | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 98 insertions(+)
diff --git a/doc/mgmt-api.txt b/doc/mgmt-api.txt
index d68b70a..0395ddc 100644
--- a/doc/mgmt-api.txt
+++ b/doc/mgmt-api.txt
@@ -1338,6 +1338,104 @@ Set Scan Parameters Command
Invalid Index
+Get 3D Synchronization Features Command
+=======================================
+
+ Command Code: 0x002D
+ Controller Index: <controller id>
+ Command Parameters:
+ Return Parameters: Features (4 Octets)
+
+ This command allows for gettig the supported 3D synchronization
+ features. These features can be used to detect what kind of 3D
+ synchronization modes are supported.
+
+ When BR/EDR is not supported, this command is supported for
+ simplicity, but it will return an empty features set. This
+ command can also be used when the controller is powered off.
+
+ NOTES: Since 3DPS is its own profiles, these supported features
+ are not to be intermixed with the GAP settings. These are special
+ hardware features like Connectionless Slave Broadcast roles that
+ are either supported or not. The advantage with a separate command
+ for 3DPS lets it easy to detect if it is running on a 3DPS enabled
+ kernel and what features of 3DPS are available.
+
+ If it happens that the controller supports all the right features,
+ but not Secure Simple Pairing, then the broadcaster modes will be
+ left out.
+
+ This command generates a Command Complete event on success or a
+ Command Status event on failure.
+
+ Possible errors: Rejected
+ Not Supported
+ Invalid Parameters
+ Invalid Index
+
+
+Set 3D Synchronization Broadcast Command
+========================================
+
+ Command Code: 0x002E
+ Controller Index: <controller id>
+ Command Parameters: Mode (1 Octets)
+ ...
+ Return Parameters:
+
+ This command allows for enabling 3D synchronization broadcast
+ modes. This is normally the 3D display role.
+
+ It is required that the controller has support for connectionless
+ slave broadcast and train synchronization in master role.
+
+ When Secure Simple Pairing is disabled, this command will fail
+ with an error.
+
+ NOTES: The actual list of parameters still needs to be figured
+ out, but it should include broadcast data and 3D information data.
+
+ This command generates a Command Complete event on success or a
+ Command Status event on failure.
+
+ Possible errors: Rejected
+ Not Supported
+ Invalid Parameters
+ Invalid Index
+
+
+Set 3D Synchronization Receiver Command
+=======================================
+
+ Command Code: 0x002E
+ Controller Index: <controller id>
+ Command Parameters: Address (6 Octets)
+ Address_Type (1 Octet)
+ ...
+ Return Parameters:
+
+ This command allows for enabling 3D synchronization receiver
+ modes. This is normally the 3D glasses role.
+
+ It is required that the controller has support for connectionless
+ slave broadcast and train synchronization in slave role.
+
+ NOTES: The actual list of parameters still needs to be figured
+ out, but it should include broadcast data and 3D information data.
+
+ NOTES: The actual data information can be either reported via
+ an event or via an L2CAP channel. That still needs to be figured
+ out.
+
+ This command generates a Command Complete event on success or a
+ Command Status event on failure.
+
+ Possible errors: Rejected
+ Not Supported
+ Invalid Parameters
+ Invalid Index
+
+
Command Complete Event
======================
--
1.8.3.1
^ permalink raw reply related
* [PATCH 22/22] gitignore: Add blueatchat unit tests
From: Jakub Tyszkowski @ 2013-10-14 8:34 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1381739678-16260-1-git-send-email-jakub.tyszkowski@tieto.com>
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index f9bf975..c72c911 100644
--- a/.gitignore
+++ b/.gitignore
@@ -76,6 +76,7 @@ unit/test-sdp
unit/test-lib
unit/test-mgmt
unit/test-cbuffer
+unit/test-blueatchat
tools/mgmt-tester
tools/gap-tester
tools/btattach
--
1.7.9.5
^ permalink raw reply related
* [PATCH 21/22] gitignore: Add curcular buffer unit tests
From: Jakub Tyszkowski @ 2013-10-14 8:34 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1381739678-16260-1-git-send-email-jakub.tyszkowski@tieto.com>
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index e492c3f..f9bf975 100644
--- a/.gitignore
+++ b/.gitignore
@@ -75,6 +75,7 @@ unit/test-gdbus-client
unit/test-sdp
unit/test-lib
unit/test-mgmt
+unit/test-cbuffer
tools/mgmt-tester
tools/gap-tester
tools/btattach
--
1.7.9.5
^ permalink raw reply related
* [PATCH 20/22] unit: Circular buffer overflow test
From: Jakub Tyszkowski @ 2013-10-14 8:34 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1381739678-16260-1-git-send-email-jakub.tyszkowski@tieto.com>
---
unit/test-blueatchat.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/unit/test-blueatchat.c b/unit/test-blueatchat.c
index e0cd23b..e0c51cd 100644
--- a/unit/test-blueatchat.c
+++ b/unit/test-blueatchat.c
@@ -595,6 +595,50 @@ static void tc_blueat_atbac(struct blueat_fixture *fix,
g_assert_cmpint(called, ==, 1);
}
+static void tc_blueat_overflow(struct blueat_fixture *fix,
+ gconstpointer test_data)
+{
+ fix->msg = "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n"
+ "\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n\r\nOK\r\n";
+
+ g_main_loop_run(fix->loop);
+ g_assert_cmpint(called, ==, 180);
+}
+
/******************************************************************************
* Parser configuration and command registration
******************************************************************************/
@@ -850,5 +894,8 @@ int main(int argc, char **argv)
g_test_add("/blueatchat/cind_2", struct blueat_fixture, 0,
blueat_fix_setup, tc_blueat_cind2,
blueat_fix_teardown);
+ g_test_add("/blueatchat/overflow", struct blueat_fixture, 0,
+ blueat_fix_setup, tc_blueat_overflow,
+ blueat_fix_teardown);
return g_test_run();
}
--
1.7.9.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox