* [PATCHv1 14/16] android/hal-sock: Send RFCOMM channel to framework
From: Andrei Emeltchenko @ 2013-11-14 15:11 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384441915-23966-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Framework expects channel to be send.
---
android/socket.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/android/socket.c b/android/socket.c
index 3c4e2fc..905def2 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -462,6 +462,11 @@ static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
goto fail;
}
+ if (write(rfslot->fd, &chan, sizeof(chan)) != sizeof(chan)) {
+ error("Error sending RFCOMM channel");
+ goto fail;
+ }
+
rfslot->real_sock = g_io_channel_unix_get_fd(io);
rfslot->channel = chan;
rfcomm_connected_list = g_list_append(rfcomm_connected_list, rfslot);
--
1.7.10.4
^ permalink raw reply related
* [PATCHv1 15/16] android/hal-sock: Send connect signal on connect
From: Andrei Emeltchenko @ 2013-11-14 15:11 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384441915-23966-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Android framework expects connect signal to be sent when
remote device is connected.
---
android/socket.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/android/socket.c b/android/socket.c
index 905def2..742c156 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -362,6 +362,33 @@ static int handle_listen(void *buf)
return hal_fd;
}
+static ssize_t sock_send_connect(struct rfcomm_slot *rfslot, bdaddr_t *bdaddr)
+{
+ struct hal_sock_connect_signal cmd;
+ ssize_t len;
+
+ DBG("");
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.size = sizeof(cmd);
+ bdaddr2android(bdaddr, cmd.bdaddr);
+ cmd.channel = rfslot->channel;
+ cmd.status = 0;
+
+ len = write(rfslot->fd, &cmd, sizeof(cmd));
+ if (len < 0) {
+ error("%s", strerror(errno));
+ return len;
+ }
+
+ if (len != (ssize_t) sizeof(cmd)) {
+ error("Error sending connect signal");
+ return -1;
+ }
+
+ return len;
+}
+
static void connect_cb(GIOChannel *io, GError *conn_err, gpointer user_data)
{
struct rfcomm_slot *rfslot = user_data;
@@ -392,6 +419,9 @@ static void connect_cb(GIOChannel *io, GError *conn_err, gpointer user_data)
rfslot->fd, rfslot->real_sock, rfslot->channel,
g_io_channel_unix_get_fd(io));
+ if (sock_send_connect(rfslot, &dst) < 0)
+ goto fail;
+
/* Handle events from Android */
io_stack = g_io_channel_unix_new(rfslot->fd);
g_io_add_watch(io_stack, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
--
1.7.10.4
^ permalink raw reply related
* [PATCHv1 16/16] android/hal-sock: Close file descriptor after sending
From: Andrei Emeltchenko @ 2013-11-14 15:11 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384441915-23966-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
android/socket.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/android/socket.c b/android/socket.c
index 742c156..a2193cc 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -545,6 +545,7 @@ void bt_sock_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
break;
ipc_send(sk, HAL_SERVICE_ID_SOCK, opcode, 0, NULL, fd);
+ close(fd);
return;
case HAL_OP_SOCK_CONNECT:
fd = handle_connect(buf);
@@ -552,6 +553,7 @@ void bt_sock_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
break;
ipc_send(sk, HAL_SERVICE_ID_SOCK, opcode, 0, NULL, fd);
+ close(fd);
return;
default:
DBG("Unhandled command, opcode 0x%x", opcode);
--
1.7.10.4
^ permalink raw reply related
* [PATCH v3 0/3] Fixes for incoming connection and bonding
From: Lukasz Rymanowski @ 2013-11-14 15:24 UTC (permalink / raw)
To: linux-bluetooth; +Cc: johan.hedberg, szymon.janc, Lukasz Rymanowski
V3:
Removed adapter bonding state
Added device list in order to track bonding state per device.
Fix for incoming legacy paring. We act here same as Bluedroid.
V2:
Bonding state added.
V1:
With those patches it is possible to bond from remote device and in addition
you will see the name of remote device on Android pairing request pop up.
Lukasz Rymanowski (3):
android: Update bond state on incoming bonding
android: Update bond state on auth and connect failed
android: Change TODO with explaining comment
android/bluetooth.c | 168 ++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 130 insertions(+), 38 deletions(-)
--
1.8.4
^ permalink raw reply
* [PATCH v3 1/3] android: Update bond state on incoming bonding
From: Lukasz Rymanowski @ 2013-11-14 15:24 UTC (permalink / raw)
To: linux-bluetooth; +Cc: johan.hedberg, szymon.janc, Lukasz Rymanowski
In-Reply-To: <1384442660-2730-1-git-send-email-lukasz.rymanowski@tieto.com>
Before sending any ssp request or pin code request up to HAL library we
need to send bond state change with bonding state. Otherwise incoming
bonding is not correctly handled by Bluetooth.apk.
In this patch also device list has been added in order to e.g track
bonding state.
Note: For incoming legacy paring there is need to send
HAL_EVE_REMOTE_DEVICE_PROPS before HAL_EV_PIN_REQUEST.
It is because Android will crash due to bug in pinRequestCallback
function in java. Android checks if device is already in HashMap and if
not then creates device, but forget to use that one, but instead do
operations on NULL. By sending HAL_BOND_STATE_BONDING event it works
better but we have race issue. It is because new device is added to
HashMap not in callback context but later after BONDING msg will be
received by BondStateMachine. If it happens before pin_request_cb hits
java then we are fine, otherwise not. So for that reason we send
HAL_EV_REMOTE_DEVICE_PROPS so in the java handler class new device will
be added to HashMap in the callback context.
In ssp case we don't have this problem as we send device found once acl
is created.
---
android/bluetooth.c | 106 ++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 91 insertions(+), 15 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 39589fa..3ecd300 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -62,6 +62,8 @@ static uint16_t option_index = MGMT_INDEX_NONE;
static int notification_sk = -1;
+#define BASELEN_REMOTE_DEV_PROP (sizeof(struct hal_ev_remote_device_props) \
+ + sizeof(struct hal_property))
/* This list contains addresses which are asked for records */
static GSList *browse_reqs;
@@ -91,6 +93,11 @@ static struct {
.uuids = NULL,
};
+struct device {
+ bdaddr_t bdaddr;
+ int bond_state;
+};
+
struct browse_req {
bdaddr_t bdaddr;
GSList *uuids;
@@ -106,6 +113,7 @@ static const uint16_t uuid_list[] = {
};
static GSList *found_devices = NULL;
+static GSList *devices = NULL;
static void adapter_name_changed(const uint8_t *name)
{
@@ -301,6 +309,14 @@ static void store_link_key(const bdaddr_t *dst, const uint8_t *key,
}
+static int bdaddr_cmp(gconstpointer a, gconstpointer b)
+{
+ const bdaddr_t *bda = a;
+ const bdaddr_t *bdb = b;
+
+ return bacmp(bdb, bda);
+}
+
static void send_bond_state_change(const bdaddr_t *addr, uint8_t status,
uint8_t state)
{
@@ -314,6 +330,29 @@ static void send_bond_state_change(const bdaddr_t *addr, uint8_t status,
HAL_EV_BOND_STATE_CHANGED, sizeof(ev), &ev, -1);
}
+static void set_device_bond_state(const bdaddr_t *addr, uint8_t status,
+ int state) {
+
+ struct device *dev = NULL;
+ GSList *l;
+
+ l = g_slist_find_custom(devices, addr, bdaddr_cmp);
+ if (l)
+ dev = l->data;
+
+ if (!dev) {
+ dev = g_new0( struct device, 1);
+ bacpy(&dev->bdaddr, addr);
+ dev->bond_state = HAL_BOND_STATE_NONE;
+ devices = g_slist_prepend(devices, dev);
+ }
+
+ if (dev->bond_state != state) {
+ dev->bond_state = state;
+ send_bond_state_change(&dev->bdaddr, status, state);
+ }
+}
+
static void browse_req_free(struct browse_req *req)
{
g_slist_free_full(req->uuids, g_free);
@@ -497,12 +536,32 @@ static void new_link_key_callback(uint16_t index, uint16_t length,
key->pin_len);
}
- send_bond_state_change(&addr->bdaddr, HAL_STATUS_SUCCESS,
+ set_device_bond_state(&addr->bdaddr, HAL_STATUS_SUCCESS,
HAL_BOND_STATE_BONDED);
browse_remote_sdp(&addr->bdaddr);
}
+static void send_remote_device_name_prop(const bdaddr_t *bdaddr, char *name)
+{
+ struct hal_ev_remote_device_props *ev;
+ uint8_t buf[BASELEN_REMOTE_DEV_PROP + strlen(name)];
+
+ ev = (void *) buf;
+ memset(buf, 0, sizeof(buf));
+
+ ev->status = HAL_STATUS_SUCCESS;
+ bdaddr2android(bdaddr, ev->bdaddr);
+ ev->num_props = 1;
+ ev->props[0].type = HAL_PROP_DEVICE_NAME;
+ ev->props[0].len = strlen(name);
+ memcpy(&ev->props[0].val, name, strlen(name));
+
+ ipc_send(notification_sk, HAL_SERVICE_ID_BLUETOOTH,
+ HAL_EV_REMOTE_DEVICE_PROPS, sizeof(buf), ev, -1);
+}
+
static void pin_code_request_callback(uint16_t index, uint16_t length,
const void *param, void *user_data)
{
@@ -517,6 +576,13 @@ static void pin_code_request_callback(uint16_t index, uint16_t length,
ba2str(&ev->addr.bdaddr, dst);
+ /* Workaround for Android Bluetooth.apk issue: send remote
+ * device property. Lets use address as a name for now */
+ send_remote_device_name_prop(&ev->addr.bdaddr, dst);
+
+ set_device_bond_state(&ev->addr.bdaddr, HAL_STATUS_SUCCESS,
+ HAL_BOND_STATE_BONDING);
+
DBG("%s type %u secure %u", dst, ev->addr.type, ev->secure);
/* TODO name and CoD of remote devices should probably be cached */
@@ -556,6 +622,9 @@ static void user_confirm_request_callback(uint16_t index, uint16_t length,
ba2str(&ev->addr.bdaddr, dst);
DBG("%s confirm_hint %u", dst, ev->confirm_hint);
+ set_device_bond_state(&ev->addr.bdaddr, HAL_STATUS_SUCCESS,
+ HAL_BOND_STATE_BONDING);
+
if (ev->confirm_hint)
send_ssp_request(&ev->addr.bdaddr, HAL_SSP_VARIANT_CONSENT, 0);
else
@@ -577,6 +646,9 @@ static void user_passkey_request_callback(uint16_t index, uint16_t length,
ba2str(&ev->addr.bdaddr, dst);
DBG("%s", dst);
+ set_device_bond_state(&ev->addr.bdaddr, HAL_STATUS_SUCCESS,
+ HAL_BOND_STATE_BONDING);
+
send_ssp_request(&ev->addr.bdaddr, HAL_SSP_VARIANT_ENTRY, 0);
}
@@ -595,9 +667,15 @@ static void user_passkey_notify_callback(uint16_t index, uint16_t length,
DBG("%s entered %u", dst, ev->entered);
/* HAL seems to not support entered characters */
- if (!ev->entered)
- send_ssp_request(&ev->addr.bdaddr, HAL_SSP_VARIANT_NOTIF,
+ if (ev->entered)
+ return;
+
+ set_device_bond_state(&ev->addr.bdaddr, HAL_STATUS_SUCCESS,
+ HAL_BOND_STATE_BONDING);
+
+ send_ssp_request(&ev->addr.bdaddr, HAL_SSP_VARIANT_NOTIF,
ev->passkey);
}
static void mgmt_discovering_event(uint16_t index, uint16_t length,
@@ -647,14 +725,6 @@ static void confirm_device_name(const bdaddr_t *addr, uint8_t addr_type)
error("Failed to send confirm name request");
}
-static int bdaddr_cmp(gconstpointer a, gconstpointer b)
-{
- const bdaddr_t *bda = a;
- const bdaddr_t *bdb = b;
-
- return bacmp(bdb, bda);
-}
-
static int fill_device_props(struct hal_property *prop, bdaddr_t *addr,
uint32_t cod, int8_t rssi, char *name)
{
@@ -1838,7 +1908,7 @@ static void pair_device_complete(uint8_t status, uint16_t length,
if (status == MGMT_STATUS_SUCCESS)
return;
- send_bond_state_change(&rp->addr.bdaddr, status_mgmt2hal(status),
+ set_device_bond_state(&rp->addr.bdaddr, status_mgmt2hal(status),
HAL_BOND_STATE_NONE);
}
@@ -1855,7 +1925,7 @@ static bool create_bond(void *buf, uint16_t len)
&cp, pair_device_complete, NULL, NULL) == 0)
return false;
- send_bond_state_change(&cp.addr.bdaddr, HAL_STATUS_SUCCESS,
+ set_device_bond_state(&cp.addr.bdaddr, HAL_STATUS_SUCCESS,
HAL_BOND_STATE_BONDING);
return true;
@@ -1865,12 +1935,18 @@ static bool cancel_bond(void *buf, uint16_t len)
{
struct hal_cmd_cancel_bond *cmd = buf;
struct mgmt_addr_info cp;
+ bool result;
cp.type = BDADDR_BREDR;
android2bdaddr(cmd->bdaddr, &cp.bdaddr);
- return mgmt_reply(mgmt_if, MGMT_OP_CANCEL_PAIR_DEVICE, adapter.index,
+ result = mgmt_reply(mgmt_if, MGMT_OP_CANCEL_PAIR_DEVICE, adapter.index,
sizeof(cp), &cp, NULL, NULL, NULL) > 0;
+ if (result)
+ set_device_bond_state(&cp.bdaddr, HAL_STATUS_SUCCESS,
+ HAL_BOND_STATE_NONE);
+
+ return result;
}
static void unpair_device_complete(uint8_t status, uint16_t length,
@@ -1883,7 +1959,7 @@ static void unpair_device_complete(uint8_t status, uint16_t length,
if (status != MGMT_STATUS_SUCCESS)
return;
- send_bond_state_change(&rp->addr.bdaddr, HAL_STATUS_SUCCESS,
+ set_device_bond_state(&rp->addr.bdaddr, HAL_STATUS_SUCCESS,
HAL_BOND_STATE_NONE);
}
--
1.8.4
^ permalink raw reply related
* [PATCH v3 2/3] android: Update bond state on auth and connect failed
From: Lukasz Rymanowski @ 2013-11-14 15:24 UTC (permalink / raw)
To: linux-bluetooth; +Cc: johan.hedberg, szymon.janc, Lukasz Rymanowski
In-Reply-To: <1384442660-2730-1-git-send-email-lukasz.rymanowski@tieto.com>
---
android/bluetooth.c | 57 ++++++++++++++++++++++++++++++++---------------------
1 file changed, 35 insertions(+), 22 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 3ecd300..b4e74e5 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -939,16 +939,51 @@ static void mgmt_device_disconnected_event(uint16_t index, uint16_t length,
HAL_EV_ACL_STATE_CHANGED, sizeof(hal_ev), &hal_ev, -1);
}
+static uint8_t status_mgmt2hal(uint8_t mgmt)
+{
+ switch (mgmt) {
+ case MGMT_STATUS_SUCCESS:
+ return HAL_STATUS_SUCCESS;
+ case MGMT_STATUS_NO_RESOURCES:
+ return HAL_STATUS_NOMEM;
+ case MGMT_STATUS_BUSY:
+ return HAL_STATUS_BUSY;
+ case MGMT_STATUS_NOT_SUPPORTED:
+ return HAL_STATUS_UNSUPPORTED;
+ case MGMT_STATUS_INVALID_PARAMS:
+ return HAL_STATUS_INVALID;
+ case MGMT_STATUS_AUTH_FAILED:
+ return HAL_STATUS_AUTH_FAILURE;
+ case MGMT_STATUS_NOT_CONNECTED:
+ return HAL_STATUS_REMOTE_DEVICE_DOWN;
+ default:
+ return HAL_STATUS_FAILED;
+ }
+}
+
static void mgmt_connect_failed_event(uint16_t index, uint16_t length,
const void *param, void *user_data)
{
+ const struct mgmt_ev_connect_failed *ev = param;
+
DBG("");
+
+ /* In case legacy pairing, we will get connect failed event
+ * in case e.g wrong PIN code entered. Let's check if device is
+ * bonding, if so update bond state */
+ set_device_bond_state(&ev->addr.bdaddr, status_mgmt2hal(ev->status),
+ HAL_BOND_STATE_NONE);
}
static void mgmt_auth_failed_event(uint16_t index, uint16_t length,
const void *param, void *user_data)
{
+ const struct mgmt_ev_auth_failed *ev = param;
+
DBG("");
+
+ set_device_bond_state(&ev->addr.bdaddr, status_mgmt2hal(ev->status),
+ HAL_BOND_STATE_NONE);
}
static void mgmt_device_unpaired_event(uint16_t index, uint16_t length,
@@ -1874,28 +1909,6 @@ static uint8_t set_property(void *buf, uint16_t len)
}
}
-static uint8_t status_mgmt2hal(uint8_t mgmt)
-{
- switch (mgmt) {
- case MGMT_STATUS_SUCCESS:
- return HAL_STATUS_SUCCESS;
- case MGMT_STATUS_NO_RESOURCES:
- return HAL_STATUS_NOMEM;
- case MGMT_STATUS_BUSY:
- return HAL_STATUS_BUSY;
- case MGMT_STATUS_NOT_SUPPORTED:
- return HAL_STATUS_UNSUPPORTED;
- case MGMT_STATUS_INVALID_PARAMS:
- return HAL_STATUS_INVALID;
- case MGMT_STATUS_AUTH_FAILED:
- return HAL_STATUS_AUTH_FAILURE;
- case MGMT_STATUS_NOT_CONNECTED:
- return HAL_STATUS_REMOTE_DEVICE_DOWN;
- default:
- return HAL_STATUS_FAILED;
- }
-}
-
static void pair_device_complete(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
--
1.8.4
^ permalink raw reply related
* [PATCH v3 3/3] android: Change TODO with explaining comment
From: Lukasz Rymanowski @ 2013-11-14 15:24 UTC (permalink / raw)
To: linux-bluetooth; +Cc: johan.hedberg, szymon.janc, Lukasz Rymanowski
In-Reply-To: <1384442660-2730-1-git-send-email-lukasz.rymanowski@tieto.com>
---
android/bluetooth.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index b4e74e5..dfeb54b 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -598,7 +598,10 @@ static void send_ssp_request(const bdaddr_t *addr, uint8_t variant,
{
struct hal_ev_ssp_request ev;
- /* TODO name and CoD of remote devices should probably be cached */
+ /* It is ok to have empty name and CoD of remote devices here since
+ * those information has been already provided on device_connected event
+ * or during device scaning. Android will use that instead.
+ */
memset(&ev, 0, sizeof(ev));
bdaddr2android(addr, ev.bdaddr);
ev.pairing_variant = variant;
--
1.8.4
^ permalink raw reply related
* Re: [PATCH v2 BlueZ] android/a2dp: Add implementation of SDP record
From: Johan Hedberg @ 2013-11-14 15:28 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1384441288-6490-1-git-send-email-luiz.dentz@gmail.com>
Hi Luiz,
On Thu, Nov 14, 2013, Luiz Augusto von Dentz wrote:
> This adds the following record:
>
> Service Name: Audio Source
> Service RecHandle: 0x10001
> Service Class ID List:
> "Audio Source" (0x110a)
> Protocol Descriptor List:
> "L2CAP" (0x0100)
> PSM: 25
> "AVDTP" (0x0019)
> uint16: 0x103
> Profile Descriptor List:
> "Advanced Audio" (0x110d)
> Version: 0x0103
> ---
> v2: Fix leaking record if bt_adapter_add_record fails
>
> android/a2dp.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 82 insertions(+)
Applied. Thanks.
Johan
^ permalink raw reply
* Re: Reading RSSI value from an RFCOMM connection
From: Michael Kehm @ 2013-11-14 17:54 UTC (permalink / raw)
To: linux-bluetooth@vger.kernel.org
In-Reply-To: <143dd8d2d4ec433e843fc98d67dd0a55@corinto.intern.hamm.cx>
Resending.
I hope someone can help out or point me into the right direction.
Thanks,
Michael
From: Michael Kehm
Sent: Saturday, November 9, 2013 10:31 PM
To: linux-bluetooth@vger.kernel.org
Hi folks,
I am trying to get the RSSI value from an established RFCOMM connection.
While searching on the Internet for hints I found the following discussions:
http://comments.gmane.org/gmane.linux.bluez.user/9986
http://stackoverflow.com/questions/2149295/android-2-1-how-do-i-poll-the-rssi-value-of-an-existing-bluetooth-connection
http://sourceforge.net/mailarchive/forum.php?forum_name=bluez-devel&style=nested&viewmonth=200505&viewday=17
Most suggestions point to the hci_read_rssi API (int hci_read_rssi(int dd, uint16_t handle, int8_t *rssi, int to);).
I am using Python. As a basic skeleton I am using Albert Huang's rfcomm-client.py and rfcomm-server.py scripts.
Looking into bluez.py and inquiry-with-rssi.py samples, it helped me to understand how to access the hci layer but I am stuck in execution.
This is my script based on rfcomm-server.py:
import os, sys, struct, fcntl, array, binascii
import btcommon
import bluetooth._bluetooth as _bt
from bluetooth import *
#################################################################
# Added code
def get_acl_conn_handle (hci_sock, addr):
hci_fd = hci_sock.fileno ()
reqstr = struct.pack ("6sB17s", _bt.str2ba (addr), _bt.ACL_LINK, "\0" * 17)
request = array.array ("c", reqstr)
print "ACL_LINK:%s" % _bt.ACL_LINK
print "hci_fd:%s" % hci_fd
print "HCIGETCONNINFO:%s" % _bt.HCIGETCONNINFO
print "request:%s" % request
fcntl.ioctl (hci_fd, _bt.HCIGETCONNINFO, request, 1)
try:
fcntl.ioctl (hci_fd, _bt.HCIGETCONNINFO, request, 1)
except IOError, e:
raise BluetoothError ("There is no ACL connection to %s" % addr)
# XXX should this be "<8xH14x"?
handle = struct.unpack ("8xH14x", request.tostring ())[0]
return handle
#################################################################
server_sock=BluetoothSocket( RFCOMM )
server_sock.bind(("",PORT_ANY))
server_sock.listen(1)
port = server_sock.getsockname()[1]
uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee"
advertise_service( server_sock, "SampleServer",
service_id = uuid,
service_classes = [ uuid, SERIAL_PORT_CLASS ],
profiles = [ SERIAL_PORT_PROFILE ],
# protocols = [ OBEX_UUID ]
)
print "Waiting for connection on RFCOMM channel %d" % port
client_sock, client_info = server_sock.accept()
print "Accepted connection from ", client_info
#################################################################
# Added code
rssi = 0
handle = get_acl_conn_handle(server_sock._sock, client_info[0])
rssi = bluez.hci_read_rssi(server_sock._sock, handle, rssi, 1000)
#################################################################
try:
client_sock.send(rssi)
print "sent [%s]" % rssi
except IOError:
pass
print "disconnected"
client_sock.close()
server_sock.close()
print "all done"
I have added/copied the get_acl_conn_handle function and the call to hci_read_rssi.
The problem is that I run into the following exception:
Traceback (most recent call last):
File "rfcomm-rssi.py", line 48, in <module>
handle = get_acl_conn_handle(server_sock._sock, client_info[0])
File "rfcomm-rssi.py", line 16, in get_acl_conn_handle
fcntl.ioctl (hci_fd, _bt.HCIGETCONNINFO, request, 1)
IOError: [Errno 22] Invalid argument
The print statements in get_acl_conn_handle return the following information:
ACL_LINK:1
hci_fd:3
HCIGETCONNINFO:-2147202859
request:array('c', '9\x91\x97g\x1d\x1c\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
I am bit lost on how to fix this.
If anyone can help me with my script above or if anyone has sample code in Python or C how to get the RSSI data from a RFCOMM connection then I would highly appreciate it.
Thanks in advance,
Michael
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH BlueZ] build: Fix out of tree builds
From: Andre Heider @ 2013-11-14 17:58 UTC (permalink / raw)
To: linux-bluetooth
Don't create bogus symlinks when passing an absolute path to --prefix.
---
Makefile.am | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 69a2805..87448ab 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -318,9 +318,9 @@ tools/%.rules:
$(lib_libbluetooth_la_OBJECTS): $(local_headers)
-lib/bluetooth/%.h: lib/%.h
+lib/bluetooth/%.h: $(abs_top_srcdir)/lib/%.h
$(AM_V_at)$(MKDIR_P) lib/bluetooth
- $(AM_V_GEN)$(LN_S) -f $(abs_top_builddir)/$< $@
+ $(AM_V_GEN)$(LN_S) -f $< $@
clean-local:
$(RM) -r lib/bluetooth
--
1.8.4.3
^ permalink raw reply related
* [PATCH v4 0/4] Fixes for incoming connection and bonding
From: Lukasz Rymanowski @ 2013-11-14 18:30 UTC (permalink / raw)
To: linux-bluetooth; +Cc: johan.hedberg, szymon.janc, Lukasz Rymanowski
V4:
Added device name caching in device list
Changes according to Johan comments
V3:
Removed adapter bonding state
Added device list in order to track bonding state per device.
Fix for incoming legacy paring. We act here same as Bluedroid.
V2:
Bonding state added.
V1:
With those patches it is possible to bond from remote device and in addition
you will see the name of remote device on Android pairing request pop up.
Lukasz Rymanowski (4):
android: Update bond state on incoming bonding
android: Cache device name on device list.
android: Update bond state on auth and connect failed
android: Change TODO with explaining comment
android/bluetooth.c | 229 +++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 189 insertions(+), 40 deletions(-)
--
1.8.4
^ permalink raw reply
* [PATCH v4 1/4] android: Update bond state on incoming bonding
From: Lukasz Rymanowski @ 2013-11-14 18:30 UTC (permalink / raw)
To: linux-bluetooth; +Cc: johan.hedberg, szymon.janc, Lukasz Rymanowski
In-Reply-To: <1384453825-19241-1-git-send-email-lukasz.rymanowski@tieto.com>
Before sending any ssp request or pin code request up to HAL library we
need to send bond state change with bonding state. Otherwise incoming
bonding is not correctly handled by Bluetooth.apk.
In this patch also device list has been added in order to e.g track
bonding state.
Note: For incoming paring (security mode 3) there is a need to send
HAL_EVE_REMOTE_DEVICE_PROPS before HAL_EV_PIN_REQUEST.
It is because Android will crash due to bug in pinRequestCallback
function in java. Android checks if device is already in HashMap and if
not then creates device, but forget to use that one, but instead do
operations on NULL. By sending HAL_BOND_STATE_BONDING event it works
better but we have race issue. It is because new device is added to
HashMap not in callback context but later after BONDING msg will be
received by BondStateMachine. If it happens before pin_request_cb hits
java then we are fine, otherwise not. So for that reason we send
HAL_EV_REMOTE_DEVICE_PROPS so in the java handler class new device will
be added to HashMap in the callback context.
In ssp case we don't have this problem as we send device found once acl
is created.
---
android/bluetooth.c | 104 ++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 89 insertions(+), 15 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 39589fa..f70db5b 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -62,6 +62,8 @@ static uint16_t option_index = MGMT_INDEX_NONE;
static int notification_sk = -1;
+#define BASELEN_REMOTE_DEV_PROP (sizeof(struct hal_ev_remote_device_props) \
+ + sizeof(struct hal_property))
/* This list contains addresses which are asked for records */
static GSList *browse_reqs;
@@ -91,6 +93,11 @@ static struct {
.uuids = NULL,
};
+struct device {
+ bdaddr_t bdaddr;
+ int bond_state;
+};
+
struct browse_req {
bdaddr_t bdaddr;
GSList *uuids;
@@ -106,6 +113,7 @@ static const uint16_t uuid_list[] = {
};
static GSList *found_devices = NULL;
+static GSList *devices = NULL;
static void adapter_name_changed(const uint8_t *name)
{
@@ -301,6 +309,14 @@ static void store_link_key(const bdaddr_t *dst, const uint8_t *key,
}
+static int bdaddr_cmp(gconstpointer a, gconstpointer b)
+{
+ const bdaddr_t *bda = a;
+ const bdaddr_t *bdb = b;
+
+ return bacmp(bdb, bda);
+}
+
static void send_bond_state_change(const bdaddr_t *addr, uint8_t status,
uint8_t state)
{
@@ -314,6 +330,29 @@ static void send_bond_state_change(const bdaddr_t *addr, uint8_t status,
HAL_EV_BOND_STATE_CHANGED, sizeof(ev), &ev, -1);
}
+static void set_device_bond_state(const bdaddr_t *addr, uint8_t status,
+ int state) {
+
+ struct device *dev = NULL;
+ GSList *l;
+
+ l = g_slist_find_custom(devices, addr, bdaddr_cmp);
+ if (l)
+ dev = l->data;
+
+ if (!dev) {
+ dev = g_new0(struct device, 1);
+ bacpy(&dev->bdaddr, addr);
+ dev->bond_state = HAL_BOND_STATE_NONE;
+ devices = g_slist_prepend(devices, dev);
+ }
+
+ if (dev->bond_state != state) {
+ dev->bond_state = state;
+ send_bond_state_change(&dev->bdaddr, status, state);
+ }
+}
+
static void browse_req_free(struct browse_req *req)
{
g_slist_free_full(req->uuids, g_free);
@@ -497,12 +536,31 @@ static void new_link_key_callback(uint16_t index, uint16_t length,
key->pin_len);
}
- send_bond_state_change(&addr->bdaddr, HAL_STATUS_SUCCESS,
+ set_device_bond_state(&addr->bdaddr, HAL_STATUS_SUCCESS,
HAL_BOND_STATE_BONDED);
browse_remote_sdp(&addr->bdaddr);
}
+static void send_remote_device_name_prop(const bdaddr_t *bdaddr, char *name)
+{
+ struct hal_ev_remote_device_props *ev;
+ uint8_t buf[BASELEN_REMOTE_DEV_PROP + strlen(name)];
+
+ ev = (void *) buf;
+ memset(buf, 0, sizeof(buf));
+
+ ev->status = HAL_STATUS_SUCCESS;
+ bdaddr2android(bdaddr, ev->bdaddr);
+ ev->num_props = 1;
+ ev->props[0].type = HAL_PROP_DEVICE_NAME;
+ ev->props[0].len = strlen(name);
+ memcpy(&ev->props[0].val, name, strlen(name));
+
+ ipc_send(notification_sk, HAL_SERVICE_ID_BLUETOOTH,
+ HAL_EV_REMOTE_DEVICE_PROPS, sizeof(buf), ev, -1);
+}
+
static void pin_code_request_callback(uint16_t index, uint16_t length,
const void *param, void *user_data)
{
@@ -517,6 +575,13 @@ static void pin_code_request_callback(uint16_t index, uint16_t length,
ba2str(&ev->addr.bdaddr, dst);
+ /* Workaround for Android Bluetooth.apk issue: send remote
+ * device property. Lets use address as a name for now */
+ send_remote_device_name_prop(&ev->addr.bdaddr, dst);
+
+ set_device_bond_state(&ev->addr.bdaddr, HAL_STATUS_SUCCESS,
+ HAL_BOND_STATE_BONDING);
+
DBG("%s type %u secure %u", dst, ev->addr.type, ev->secure);
/* TODO name and CoD of remote devices should probably be cached */
@@ -556,6 +621,9 @@ static void user_confirm_request_callback(uint16_t index, uint16_t length,
ba2str(&ev->addr.bdaddr, dst);
DBG("%s confirm_hint %u", dst, ev->confirm_hint);
+ set_device_bond_state(&ev->addr.bdaddr, HAL_STATUS_SUCCESS,
+ HAL_BOND_STATE_BONDING);
+
if (ev->confirm_hint)
send_ssp_request(&ev->addr.bdaddr, HAL_SSP_VARIANT_CONSENT, 0);
else
@@ -577,6 +645,9 @@ static void user_passkey_request_callback(uint16_t index, uint16_t length,
ba2str(&ev->addr.bdaddr, dst);
DBG("%s", dst);
+ set_device_bond_state(&ev->addr.bdaddr, HAL_STATUS_SUCCESS,
+ HAL_BOND_STATE_BONDING);
+
send_ssp_request(&ev->addr.bdaddr, HAL_SSP_VARIANT_ENTRY, 0);
}
@@ -595,8 +666,13 @@ static void user_passkey_notify_callback(uint16_t index, uint16_t length,
DBG("%s entered %u", dst, ev->entered);
/* HAL seems to not support entered characters */
- if (!ev->entered)
- send_ssp_request(&ev->addr.bdaddr, HAL_SSP_VARIANT_NOTIF,
+ if (ev->entered)
+ return;
+
+ set_device_bond_state(&ev->addr.bdaddr, HAL_STATUS_SUCCESS,
+ HAL_BOND_STATE_BONDING);
+
+ send_ssp_request(&ev->addr.bdaddr, HAL_SSP_VARIANT_NOTIF,
ev->passkey);
}
@@ -647,14 +723,6 @@ static void confirm_device_name(const bdaddr_t *addr, uint8_t addr_type)
error("Failed to send confirm name request");
}
-static int bdaddr_cmp(gconstpointer a, gconstpointer b)
-{
- const bdaddr_t *bda = a;
- const bdaddr_t *bdb = b;
-
- return bacmp(bdb, bda);
-}
-
static int fill_device_props(struct hal_property *prop, bdaddr_t *addr,
uint32_t cod, int8_t rssi, char *name)
{
@@ -1838,7 +1906,7 @@ static void pair_device_complete(uint8_t status, uint16_t length,
if (status == MGMT_STATUS_SUCCESS)
return;
- send_bond_state_change(&rp->addr.bdaddr, status_mgmt2hal(status),
+ set_device_bond_state(&rp->addr.bdaddr, status_mgmt2hal(status),
HAL_BOND_STATE_NONE);
}
@@ -1855,7 +1923,7 @@ static bool create_bond(void *buf, uint16_t len)
&cp, pair_device_complete, NULL, NULL) == 0)
return false;
- send_bond_state_change(&cp.addr.bdaddr, HAL_STATUS_SUCCESS,
+ set_device_bond_state(&cp.addr.bdaddr, HAL_STATUS_SUCCESS,
HAL_BOND_STATE_BONDING);
return true;
@@ -1865,12 +1933,18 @@ static bool cancel_bond(void *buf, uint16_t len)
{
struct hal_cmd_cancel_bond *cmd = buf;
struct mgmt_addr_info cp;
+ bool result;
cp.type = BDADDR_BREDR;
android2bdaddr(cmd->bdaddr, &cp.bdaddr);
- return mgmt_reply(mgmt_if, MGMT_OP_CANCEL_PAIR_DEVICE, adapter.index,
+ result = mgmt_reply(mgmt_if, MGMT_OP_CANCEL_PAIR_DEVICE, adapter.index,
sizeof(cp), &cp, NULL, NULL, NULL) > 0;
+ if (result)
+ set_device_bond_state(&cp.bdaddr, HAL_STATUS_SUCCESS,
+ HAL_BOND_STATE_NONE);
+
+ return result;
}
static void unpair_device_complete(uint8_t status, uint16_t length,
@@ -1883,7 +1957,7 @@ static void unpair_device_complete(uint8_t status, uint16_t length,
if (status != MGMT_STATUS_SUCCESS)
return;
- send_bond_state_change(&rp->addr.bdaddr, HAL_STATUS_SUCCESS,
+ set_device_bond_state(&rp->addr.bdaddr, HAL_STATUS_SUCCESS,
HAL_BOND_STATE_NONE);
}
--
1.8.4
^ permalink raw reply related
* [PATCH v4 2/4] android: Cache device name on device list.
From: Lukasz Rymanowski @ 2013-11-14 18:30 UTC (permalink / raw)
To: linux-bluetooth; +Cc: johan.hedberg, szymon.janc, Lukasz Rymanowski
In-Reply-To: <1384453825-19241-1-git-send-email-lukasz.rymanowski@tieto.com>
---
android/bluetooth.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 65 insertions(+), 6 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index f70db5b..ce153c2 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -96,6 +96,7 @@ static struct {
struct device {
bdaddr_t bdaddr;
int bond_state;
+ char *name;
};
struct browse_req {
@@ -330,6 +331,34 @@ static void send_bond_state_change(const bdaddr_t *addr, uint8_t status,
HAL_EV_BOND_STATE_CHANGED, sizeof(ev), &ev, -1);
}
+static void cache_device_name(const bdaddr_t *addr, char *name)
+{
+ struct device *dev = NULL;
+ GSList *l;
+
+ l = g_slist_find_custom(devices, addr, bdaddr_cmp);
+ if (l)
+ dev = l->data;
+
+ if (!dev) {
+ dev = g_new0(struct device, 1);
+ bacpy(&dev->bdaddr, addr);
+ dev->bond_state = HAL_BOND_STATE_NONE;
+ dev->name = g_malloc0(strlen(name) + 1);
+ memcpy(dev->name, name, strlen(name));
+
+ devices = g_slist_prepend(devices, dev);
+ return;
+ }
+
+ if (!g_strcmp0(dev->name, name))
+ return;
+
+ g_free(dev->name);
+ dev->name = g_strdup(name);
+ /*TODO: Do some real caching here */
+}
+
static void set_device_bond_state(const bdaddr_t *addr, uint8_t status,
int state) {
@@ -542,10 +571,35 @@ static void new_link_key_callback(uint16_t index, uint16_t length,
browse_remote_sdp(&addr->bdaddr);
}
-static void send_remote_device_name_prop(const bdaddr_t *bdaddr, char *name)
+static char* get_device_name(const bdaddr_t *addr)
+{
+ GSList *l;
+ struct device *dev;
+
+ l = g_slist_find_custom(devices, addr, bdaddr_cmp);
+ if (l) {
+ dev = l->data;
+ return dev->name;
+ }
+
+ return NULL;
+}
+
+static void send_remote_device_name_prop(const bdaddr_t *bdaddr)
{
struct hal_ev_remote_device_props *ev;
- uint8_t buf[BASELEN_REMOTE_DEV_PROP + strlen(name)];
+ uint8_t *buf;
+ char dst[18];
+ char *name;
+
+ ba2str(bdaddr, dst);
+
+ /* Use cached name or bdaddr string */
+ name = get_device_name(bdaddr);
+ if (!name)
+ name = dst;
+
+ buf = g_malloc0(BASELEN_REMOTE_DEV_PROP + strlen(name));
ev = (void *) buf;
memset(buf, 0, sizeof(buf));
@@ -559,6 +613,8 @@ static void send_remote_device_name_prop(const bdaddr_t *bdaddr, char *name)
ipc_send(notification_sk, HAL_SERVICE_ID_BLUETOOTH,
HAL_EV_REMOTE_DEVICE_PROPS, sizeof(buf), ev, -1);
+
+ g_free(buf);
}
static void pin_code_request_callback(uint16_t index, uint16_t length,
@@ -576,15 +632,16 @@ static void pin_code_request_callback(uint16_t index, uint16_t length,
ba2str(&ev->addr.bdaddr, dst);
/* Workaround for Android Bluetooth.apk issue: send remote
- * device property. Lets use address as a name for now */
- send_remote_device_name_prop(&ev->addr.bdaddr, dst);
+ * device property */
+ send_remote_device_name_prop(&ev->addr.bdaddr);
set_device_bond_state(&ev->addr.bdaddr, HAL_STATUS_SUCCESS,
HAL_BOND_STATE_BONDING);
DBG("%s type %u secure %u", dst, ev->addr.type, ev->secure);
- /* TODO name and CoD of remote devices should probably be cached */
+ /* TODO CoD of remote devices should probably be cached
+ * Name we already send in remote device prop */
memset(&hal_ev, 0, sizeof(hal_ev));
bdaddr2android(&ev->addr.bdaddr, hal_ev.bdaddr);
@@ -799,8 +856,10 @@ static void update_found_device(const bdaddr_t *bdaddr, uint8_t bdaddr_type,
props_size += sizeof(struct hal_property) + sizeof(eir.class);
props_size += sizeof(struct hal_property) + sizeof(rssi);
- if (eir.name)
+ if (eir.name) {
props_size += sizeof(struct hal_property) + strlen(eir.name);
+ cache_device_name(remote, eir.name);
+ }
if (is_new_dev) {
struct hal_ev_device_found *ev = NULL;
--
1.8.4
^ permalink raw reply related
* [PATCH v4 3/4] android: Update bond state on auth and connect failed
From: Lukasz Rymanowski @ 2013-11-14 18:30 UTC (permalink / raw)
To: linux-bluetooth; +Cc: johan.hedberg, szymon.janc, Lukasz Rymanowski
In-Reply-To: <1384453825-19241-1-git-send-email-lukasz.rymanowski@tieto.com>
---
android/bluetooth.c | 57 ++++++++++++++++++++++++++++++++---------------------
1 file changed, 35 insertions(+), 22 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index ce153c2..e75baef 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -996,16 +996,51 @@ static void mgmt_device_disconnected_event(uint16_t index, uint16_t length,
HAL_EV_ACL_STATE_CHANGED, sizeof(hal_ev), &hal_ev, -1);
}
+static uint8_t status_mgmt2hal(uint8_t mgmt)
+{
+ switch (mgmt) {
+ case MGMT_STATUS_SUCCESS:
+ return HAL_STATUS_SUCCESS;
+ case MGMT_STATUS_NO_RESOURCES:
+ return HAL_STATUS_NOMEM;
+ case MGMT_STATUS_BUSY:
+ return HAL_STATUS_BUSY;
+ case MGMT_STATUS_NOT_SUPPORTED:
+ return HAL_STATUS_UNSUPPORTED;
+ case MGMT_STATUS_INVALID_PARAMS:
+ return HAL_STATUS_INVALID;
+ case MGMT_STATUS_AUTH_FAILED:
+ return HAL_STATUS_AUTH_FAILURE;
+ case MGMT_STATUS_NOT_CONNECTED:
+ return HAL_STATUS_REMOTE_DEVICE_DOWN;
+ default:
+ return HAL_STATUS_FAILED;
+ }
+}
+
static void mgmt_connect_failed_event(uint16_t index, uint16_t length,
const void *param, void *user_data)
{
+ const struct mgmt_ev_connect_failed *ev = param;
+
DBG("");
+
+ /* In case security mode 3 pairing we will get connect failed event
+ * in case e.g wrong PIN code entered. Let's check if device is
+ * bonding, if so update bond state */
+ set_device_bond_state(&ev->addr.bdaddr, status_mgmt2hal(ev->status),
+ HAL_BOND_STATE_NONE);
}
static void mgmt_auth_failed_event(uint16_t index, uint16_t length,
const void *param, void *user_data)
{
+ const struct mgmt_ev_auth_failed *ev = param;
+
DBG("");
+
+ set_device_bond_state(&ev->addr.bdaddr, status_mgmt2hal(ev->status),
+ HAL_BOND_STATE_NONE);
}
static void mgmt_device_unpaired_event(uint16_t index, uint16_t length,
@@ -1931,28 +1966,6 @@ static uint8_t set_property(void *buf, uint16_t len)
}
}
-static uint8_t status_mgmt2hal(uint8_t mgmt)
-{
- switch (mgmt) {
- case MGMT_STATUS_SUCCESS:
- return HAL_STATUS_SUCCESS;
- case MGMT_STATUS_NO_RESOURCES:
- return HAL_STATUS_NOMEM;
- case MGMT_STATUS_BUSY:
- return HAL_STATUS_BUSY;
- case MGMT_STATUS_NOT_SUPPORTED:
- return HAL_STATUS_UNSUPPORTED;
- case MGMT_STATUS_INVALID_PARAMS:
- return HAL_STATUS_INVALID;
- case MGMT_STATUS_AUTH_FAILED:
- return HAL_STATUS_AUTH_FAILURE;
- case MGMT_STATUS_NOT_CONNECTED:
- return HAL_STATUS_REMOTE_DEVICE_DOWN;
- default:
- return HAL_STATUS_FAILED;
- }
-}
-
static void pair_device_complete(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
--
1.8.4
^ permalink raw reply related
* [PATCH v4 4/4] android: Change TODO with explaining comment
From: Lukasz Rymanowski @ 2013-11-14 18:30 UTC (permalink / raw)
To: linux-bluetooth; +Cc: johan.hedberg, szymon.janc, Lukasz Rymanowski
In-Reply-To: <1384453825-19241-1-git-send-email-lukasz.rymanowski@tieto.com>
---
android/bluetooth.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index e75baef..2e94e1f 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -654,7 +654,10 @@ static void send_ssp_request(const bdaddr_t *addr, uint8_t variant,
{
struct hal_ev_ssp_request ev;
- /* TODO name and CoD of remote devices should probably be cached */
+ /* It is ok to have empty name and CoD of remote devices here since
+ * those information has been already provided on device_connected event
+ * or during device scaning. Android will use that instead.
+ */
memset(&ev, 0, sizeof(ev));
bdaddr2android(addr, ev.bdaddr);
ev.pairing_variant = variant;
--
1.8.4
^ permalink raw reply related
* RE: [RFC BlueZ v1] doc: Add GATT API
From: Caleb Reinhold @ 2013-11-14 20:13 UTC (permalink / raw)
To: 'Claudio Takahasi', 'Scott James Remnant'; +Cc: linux-bluetooth
In-Reply-To: <CAKT1EBc2d3VkiUF705aNY79YDmL5ZRX75fg=a4a_ZfTPt4zoDA@mail.gmail.com>
Hi Claudio and Scott,
While having minimal familiarity with the workings of BlueZ, I have a fair degree of familiarity with the various health related BTLE specifications.
Because of this, and because of a desire to make use of a more complete GATT API for BlueZ, I thought I might be able to offer some worthwhile insight on useful ways for the API to behave.
I think that while discussing the reading of characteristics, considering the information available to the client side at the time of connection due to advertisements would be useful. Since UUIDs for a given service being included in an advertisement are only at the level of a "should" it may be useful for an application to be able to decide to abort a connection after discovering only the service declarations.
As far as the behavior of enabling Notifications or Indications, while in most circumstances it would be possible to draw appropriate information from the corresponding characteristic declaration's properties, if a situation occurred in which both options were for some reason viable selections it could be quite frustrating for the developer making use of the API. Manual control of the state of the client characteristic configuration descriptors also allows a developer to ensure that data will not be lost due to arriving before the client program is ready to handle it.
Regarding the caching of attributes we were wondering if there is a method for removing the stored data, at least for the purposes of testing.
Regards,
Caleb Reinhold
-----Original Message-----
From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-bluetooth-owner@vger.kernel.org] On Behalf Of Claudio Takahasi
Sent: Tuesday, November 12, 2013 1:49 PM
To: Scott James Remnant
Cc: linux-bluetooth@vger.kernel.org
Subject: Re: [RFC BlueZ v1] doc: Add GATT API
Hi Scott,
On Mon, Nov 11, 2013 at 3:56 PM, Scott James Remnant <keybuk@google.com> wrote:
> On Tue, Oct 15, 2013 at 11:39 AM, Claudio Takahasi
> <claudio.takahasi@openbossa.org> wrote:
>
>> +GATT local and remote services share the same high-level D-Bus API.
>> +Local refers to local GATT based service exported by a BlueZ plugin
>> +or an external application. Remote refers to GATT services exported by the peer.
>
> If this object format also be used to describe the services and
> characteristics of a remote device, how will those be handled? I
> assume that we don't want to get the value of every single
> characteristic on connection - that seems wasteful, and would quite
> rapidly drain the batteries of smaller devices.
Declarations are stored/cached. All attributes are discovered only once in the first connection or after bonding.
When re-connecting, value is read on demand when the user calls Properties Get (if value is not cached).
Another point is: Notification or Indication are automatically enabled after the discovery procedure.
>
>
> How will service changed be handled? How will BlueZ track the set of
> applications, and the set of services etc. defined by those
> applications in a manner that keeps handles consistent? How will it
> handle generating the Services Changed notification in the cases where
> the set of applications and/or services change, or the handles change?
We implemented a hash of declarations. Using the "Id" provided in the options dictionary (see RegisterAgent) we are able to identity if the external service changed its attributes.
However, I don' t think we will upstream this approach soon, Marcel wants a simpler approach: always send ServiceChanged.
If you want to understand more details of the implementation see:
https://db.tt/FkWob6jw
>
>
>> +Characteristic hierarchy
>> +========================
> :
>> +Service org.bluez
>> +Interface org.bluez.Characteristic1 [Experimental]
>> +Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY
>
> This would also need a "Permissions" property akin to the one you have
> for Descriptors - characteristics can be "not accessible", read-only,
> write-only, read/write - and can also require authorization,
> authentication, encryption and minimum encryption key sizes - as with
> descriptors.
It is implemented already, there is an optional "Flags" property :
"array{string} Flags [read-only, optional]"
But this is not enough, there are some cases that the permissions are defined by the external application.
>
>> + array{byte} Value [read-write]
>> +
>> + Cached Value of the characteristic. If present, the
>> + value will be cached by bluetoothd and updated when the
>> + PropertiesChanged signal is emitted.
>> +
>> + External services must emit this signal when the
>> + characteristic supports notification/indication, so
>> + that clients can be notified of the new value.
>
> The PropertiesChanged signal explains how Notification will be handled
> - but how will Indication? How will a service receive the Indication
> Confirmation from the remote devices?
The bluetoothd core manages the Confirmation. In my opinion clients listening for PropertiesChanged don' t need to know the difference between notification and indication.
Allow an external client to manage the Confirmation will insert additional complexity without giving real benefits.
>
>
>> +Application Manager hierarchy
>> +=============================
> :
>> +Service org.bluez
>> +Interface org.bluez.ApplicationManager1 [Experimental]
>> +Object path /org/bluez
>> +
>> +Methods RegisterAgent(object application, dict options)
>
> Shouldn't this be "RegisterApplication" ?
>
> I assume that the object path is the one to which D-Bus Object Manager
> queries are sent, allowing a single process to implement multiple
> "applications"?
The name is still open, but remember that this method might be used to register client and servers.
At the moment "object path" together with DBus BUS id are used for identification only. Multiple GATT services can be registered independently of the application object path.
Application object path can be used to manage *groups* of services exposed by the single process.
>
>> + UnregisterAgent(object application)
>
> Likewise, "UnregisterApplication" ?
>
>> +Application Agent hierarchy
>> +===========================
>> +
>> +Service unique name
>> +Interface org.bluez.ApplicationAgent1 [Experimental]
>> +Object path freely definable
>> +
>
> "Agent" seems unnnecessary here - if the object is an Application,
> then org.bluez.Application1 would be a decent enough name. Thus an
> "Application" consists of multiple Services, each of which consists of
> multiple Characteristics, each of which has multiple Descriptors
IMO "Agent" gives a better association with its functionality, it reminds me org.bluez.Agent1.
Let's wait the opinion of the others developers...
Regards,
Claudio
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* (no subject)
From: Bruno Bruzzano @ 2013-11-14 21:47 UTC (permalink / raw)
To: linux-bluetooth
Hi everyone!
As suggested by vcgomes, I subscribed to this mailing list to report a
possible bug. I hope I'll receive a feedback from you.
I'm using Neard and BlueZ5 and my goal is to try the bluetooth
handover. The steps I followed are: I run the Bluetooth daemon with
experimental arg (-E), run the neard daemon, powered the NFC adapter
and set it up in Polling mode; furthermore, I wrote the MiFare Classic
1k tag with a record to do the pair. In particular, I used a Samsung
S3 to write the tag, using the NXP WriteTag application. So, the last
step (I think!) is to put the tag on the adapter to start the pairing.
Unfortunally, something happens, that is, in my smartphone I receive a
pairing request and I give the 'Ok', but watching the debug of
Bluetooth daemon, I read always:
"bluetoothd[22063]: src/agent.c:agent_unref() 0x89470c8: ref=-87222"
"bluetoothd[22063]: src/adapter.c:btd_adapter_confirm_reply() hci0
addr B0:C4:E7:BC:B9:4A success 0".
This two lines are repeated continuisly, with the 'ref' that increases
up to a certain point. After that the Bluetooth daemon crashes.
Here you can find two pastebin, respectively for BlueZ daemon and Neard daemon.
BlueZ: http://pastebin.com/Z4W0V5NZ
Neard: http://pastebin.com/cNfQ7qi0
Best Regards
br1_21
^ permalink raw reply
* Re: [PATCHv1 07/16] android/hal-sock: Implement Android RFCOMM stack events
From: Marcel Holtmann @ 2013-11-15 0:00 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1384441915-23966-8-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
> Handle events from Android framework. Write everything to real RFCOMM
> socket.
> ---
> android/socket.c | 42 ++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 42 insertions(+)
>
> diff --git a/android/socket.c b/android/socket.c
> index c9ee32f..07743f6 100644
> --- a/android/socket.c
> +++ b/android/socket.c
> @@ -118,6 +118,48 @@ static int get_rfcomm_default_chan(const uint8_t *uuid)
> static gboolean sock_stack_event_cb(GIOChannel *io, GIOCondition cond,
> gpointer data)
> {
> + struct rfcomm_slot *rfslot = data;
> + unsigned char buf[1024] = { 0 };
since why are we doing this { 0 } thing?
> + int len, sent;
> +
> + DBG("rfslot: fd %d real_sock %d chan %u sock %d",
> + rfslot->fd, rfslot->real_sock, rfslot->channel,
> + g_io_channel_unix_get_fd(io));
> +
> + if (!g_list_find(rfcomm_connected_list, rfslot)) {
> + error("rfslot %p not found in the list", rfslot);
> + return FALSE;
> + }
> +
> + if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
> + error("Socket error: sock %d cond %d",
> + g_io_channel_unix_get_fd(io), cond);
> + rfcomm_connected_list = g_list_remove(rfcomm_connected_list,
> + rfslot);
> + cleanup_rfslot(rfslot);
> + return FALSE;
> + }
> +
> + /* FIXME check fd vs sock(io) */
I do not even understand this FIXME. Why not get it right in the fist place.
> + len = recv(rfslot->fd, buf, sizeof(buf), 0);
> + if (len <= 0) {
> + error("recv(): %s", strerror(errno));
> + return FALSE;
> + }
> +
> + DBG("read %d bytes write to %d", len, rfslot->real_sock);
> +
> + sent = send(rfslot->real_sock, buf, len, 0);
> + if (sent < 0) {
> + error("send(): %s", strerror(errno));
> + return FALSE;
> + }
> +
> + if (sent != len) {
> + error("send(): sent %d bytes out of %d", sent, len);
> + return FALSE;
> + }
Only problem is still that we now abort on errors like EINTR or EAGAIN. That is not what we want either.
Regards
Marcel
^ permalink raw reply
* Re: [PATCH 1/2] android: Add PTS PICS for GAP
From: Marcel Holtmann @ 2013-11-15 0:51 UTC (permalink / raw)
To: Jakub Tyszkowski; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1384435587-12427-1-git-send-email-jakub.tyszkowski@tieto.com>
Hi Jakub,
> PTS PICS for GAP, targeting Android 4.4.
>
> ---
> android/pics-gap.txt | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 201 insertions(+)
> create mode 100644 android/pics-gap.txt
>
> diff --git a/android/pics-gap.txt b/android/pics-gap.txt
> new file mode 100644
> index 0000000..bcb64cb
> --- /dev/null
> +++ b/android/pics-gap.txt
> @@ -0,0 +1,201 @@
> +GAP PICS for the PTS tool.
> +
> +* - different than PTS defaults
> +
> ++------------------+------------+
> +| Parameter Name | Selected |
> ++------------------+------------+
> +| TSPC_GAP_0_1 | False |
> +| TSPC_GAP_0_2 | False |
> +| TSPC_GAP_0_3 | True* |
I would go easy on the ASCII Art here. A simple table with tabs should be just fine.
Parameter name Selected Description
-------------------------------------------------------------
TSPC_GAP_0_1 True (*) Short description of what it is
Regards
Marcel
^ permalink raw reply
* [RFC v2 0/5] android: IPC improvements
From: Szymon Janc @ 2013-11-15 1:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
Hi,
This version uses table approach suggested by Johan.
Handlers are registered on service init and unregistered on cleanup.
Service id and opcode are used to select proper handler from tables.
Handlers are declared with expected (or minimum) payload size and this is
verified before calling proper handler.
This only implement HAL library side to demonstrate use. If this approach is
agreed on daemon patches will follow.
Comments are welcome.
--
BR
Szymon Janc
Szymon Janc (5):
android: Add initial code for generic IPC msg handling
android/hal-bluetooth: Use generic IPC message handling for events
android/hal-hidhost: Use generic IPC message handling for events
android/hal-pan: Use generic IPC message handling for events
android/hal-a2dp: Use generic IPC message handling for events
android/Android.mk | 2 +
android/Makefile.am | 5 +-
android/hal-a2dp.c | 41 ++++-----
android/hal-bluetooth.c | 221 ++++++++++++++++++++++++++++++------------------
android/hal-hidhost.c | 76 ++++++++++-------
android/hal-ipc.c | 45 ++--------
android/hal-msg.c | 94 ++++++++++++++++++++
android/hal-msg.h | 14 +++
android/hal-pan.c | 40 ++++-----
android/hal.h | 4 -
android/ipc.c | 1 +
11 files changed, 345 insertions(+), 198 deletions(-)
create mode 100644 android/hal-msg.c
--
1.8.4.3
^ permalink raw reply
* [RFC v2 1/5] android: Add initial code for generic IPC msg handling
From: Szymon Janc @ 2013-11-15 1:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1384479617-15555-1-git-send-email-szymon.janc@tieto.com>
This will allow to register and unregister handlers for IPC messages.
Basic sanity check will be done in common code. Commands with variable
length will be verified against minimum size only.
---
android/Android.mk | 2 ++
android/Makefile.am | 5 +--
android/hal-msg.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++
android/hal-msg.h | 14 ++++++++
android/ipc.c | 1 +
5 files changed, 114 insertions(+), 2 deletions(-)
create mode 100644 android/hal-msg.c
diff --git a/android/Android.mk b/android/Android.mk
index 616a338..23a530f 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -27,6 +27,7 @@ LOCAL_SRC_FILES := \
ipc.c ipc.h \
a2dp.c \
pan.c \
+ hal-msg.c \
../src/log.c \
../src/shared/mgmt.c \
../src/shared/util.c \
@@ -88,6 +89,7 @@ LOCAL_SRC_FILES := \
hal-pan.c \
hal-a2dp.c \
hal-utils.c \
+ hal-msg.c \
LOCAL_C_INCLUDES += \
$(call include-path-for, system-core) \
diff --git a/android/Makefile.am b/android/Makefile.am
index 4e0c9ed..831a3cb 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -8,7 +8,7 @@ noinst_PROGRAMS += android/bluetoothd
android_bluetoothd_SOURCES = android/main.c \
src/log.c \
- android/hal-msg.h \
+ android/hal-msg.h android/hal-msg.c \
android/utils.h \
src/sdpd-database.c src/sdpd-server.c \
src/sdpd-service.c src/sdpd-request.c \
@@ -49,7 +49,8 @@ android_libhal_internal_la_SOURCES = android/hal.h android/hal-bluetooth.c \
android/hardware/hardware.h \
android/cutils/properties.h \
android/hal-log.h \
- android/hal-ipc.h android/hal-ipc.c
+ android/hal-ipc.h android/hal-ipc.c \
+ android/hal-msg.h android/hal-msg.c
android_libhal_internal_la_CPPFLAGS = -I$(srcdir)/android
diff --git a/android/hal-msg.c b/android/hal-msg.c
new file mode 100644
index 0000000..2b5178b
--- /dev/null
+++ b/android/hal-msg.c
@@ -0,0 +1,94 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "hal-msg.h"
+
+struct service_handler {
+ const struct hal_msg_handler *handler;
+ uint8_t size;
+ uint8_t offset;
+};
+
+static struct service_handler services[HAL_SERVICE_ID_MAX + 1];
+
+void hal_msg_register(uint8_t service, const struct hal_msg_handler *handlers,
+ uint8_t size, uint8_t offset)
+{
+ services[service].handler = handlers;
+ services[service].size = size;
+ services[service].offset = offset;
+}
+
+void hal_msg_unregister(uint8_t service)
+{
+ services[service].handler = NULL;
+ services[service].size = 0;
+ services[service].offset = 0;
+}
+
+bool hal_msg_handler(void *buf, ssize_t len, int fd)
+{
+ struct hal_hdr *msg = buf;
+ const struct hal_msg_handler *handler;
+ uint8_t opcode;
+
+ if (len < (ssize_t) sizeof(*msg))
+ return false;
+
+ if (len != (ssize_t) (sizeof(*msg) + msg->len))
+ return false;
+
+ /* if service is valid */
+ if (msg->service_id > HAL_SERVICE_ID_MAX)
+ return false;
+
+ /* if service is registered */
+ if (!services[msg->service_id].handler)
+ return false;
+
+ /* if opcode fit offset (eg. events) */
+ if (msg->opcode < services[msg->service_id].offset)
+ return false;
+
+ opcode = msg->opcode - services[msg->service_id].offset;
+
+ /* if opcode is valid */
+ if (opcode >= services[msg->service_id].size)
+ return false;
+
+ handler = &services[msg->service_id].handler[opcode];
+
+ /* if payload size is valid */
+ if ((handler->var_len && handler->data_len > msg->len) ||
+ (!handler->var_len && handler->data_len != msg->len))
+ return false;
+
+ handler->handler(msg->payload, msg->len, fd);
+
+ return true;
+}
diff --git a/android/hal-msg.h b/android/hal-msg.h
index 44fd5c8..17c0ac4 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -546,3 +546,17 @@ struct hal_ev_a2dp_audio_state {
uint8_t state;
uint8_t bdaddr[6];
} __attribute__((packed));
+
+
+/* HAL message handler helpers */
+
+struct hal_msg_handler {
+ void (*handler) (void *buf, uint16_t len, int fd);
+ bool var_len;
+ size_t data_len;
+};
+
+void hal_msg_register(uint8_t service, const struct hal_msg_handler *handlers,
+ uint8_t size, uint8_t offset);
+void hal_msg_unregister(uint8_t service);
+bool hal_msg_handler(void *buf, ssize_t len, int fd);
diff --git a/android/ipc.c b/android/ipc.c
index 729f157..7526d25 100644
--- a/android/ipc.c
+++ b/android/ipc.c
@@ -28,6 +28,7 @@
#include <stddef.h>
#include <errno.h>
#include <stdint.h>
+#include <stdbool.h>
#include <string.h>
#include <signal.h>
#include <sys/socket.h>
--
1.8.4.3
^ permalink raw reply related
* [RFC v2 2/5] android/hal-bluetooth: Use generic IPC message handling for events
From: Szymon Janc @ 2013-11-15 1:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1384479617-15555-1-git-send-email-szymon.janc@tieto.com>
Register handlers on service init. Since this requires all handlers to
be registered (unknown opcode is considered IPC error) missing handlers
stubs are provided.
---
android/hal-bluetooth.c | 221 ++++++++++++++++++++++++++++++------------------
android/hal-ipc.c | 45 ++--------
android/hal.h | 1 -
3 files changed, 145 insertions(+), 122 deletions(-)
diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 078d537..4176563 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -35,7 +35,7 @@ static const bt_callbacks_t *bt_hal_cbacks = NULL;
*pe = *((uint8_t *) (hal_prop->val)); \
} while (0)
-static void handle_adapter_state_changed(void *buf)
+static void handle_adapter_state_changed(void *buf, uint16_t len, int fd)
{
struct hal_ev_adapter_state_changed *ev = buf;
@@ -45,38 +45,35 @@ static void handle_adapter_state_changed(void *buf)
bt_hal_cbacks->adapter_state_changed_cb(ev->state);
}
-static void adapter_props_to_hal(bt_property_t *send_props,
- struct hal_property *hal_prop,
- uint8_t num_props, void *buff_end)
+static void adapter_props_to_hal(bt_property_t *send_props, void *buf,
+ uint8_t num_props)
{
- void *p = hal_prop;
+ struct hal_property *prop = buf;
uint8_t i;
for (i = 0; i < num_props; i++) {
- if (p + sizeof(*hal_prop) + hal_prop->len > buff_end) {
- error("invalid adapter properties event, aborting");
- exit(EXIT_FAILURE);
- }
-
- send_props[i].type = hal_prop->type;
+ send_props[i].type = prop->type;
- switch (hal_prop->type) {
+ switch (prop->type) {
case HAL_PROP_ADAPTER_TYPE:
- create_enum_prop(send_props[i], hal_prop,
+ create_enum_prop(send_props[i], prop,
bt_device_type_t);
break;
case HAL_PROP_ADAPTER_SCAN_MODE:
- create_enum_prop(send_props[i], hal_prop,
+ create_enum_prop(send_props[i], prop,
bt_scan_mode_t);
break;
case HAL_PROP_ADAPTER_SERVICE_REC:
default:
- send_props[i].len = hal_prop->len;
- send_props[i].val = hal_prop->val;
+ send_props[i].len = prop->len;
+ send_props[i].val = prop->val;
break;
}
DBG("prop[%d]: %s", i, btproperty2str(&send_props[i]));
+
+ buf += sizeof(*prop) + prop->len;
+ prop = buf;
}
}
@@ -96,36 +93,30 @@ static void adapter_hal_props_cleanup(bt_property_t *props, uint8_t num)
}
}
-static void device_props_to_hal(bt_property_t *send_props,
- struct hal_property *hal_prop,
- uint8_t num_props, void *buff_end)
+static void device_props_to_hal(bt_property_t *send_props, void *buf,
+ uint8_t num_props)
{
- void *p = hal_prop;
+ struct hal_property *prop = buf;
uint8_t i;
for (i = 0; i < num_props; i++) {
- if (p + sizeof(*hal_prop) + hal_prop->len > buff_end) {
- error("invalid adapter properties event, aborting");
- exit(EXIT_FAILURE);
- }
-
- send_props[i].type = hal_prop->type;
+ send_props[i].type = prop->type;
- switch (hal_prop->type) {
+ switch (prop->type) {
case HAL_PROP_DEVICE_TYPE:
- create_enum_prop(send_props[i], hal_prop,
+ create_enum_prop(send_props[i], prop,
bt_device_type_t);
break;
case HAL_PROP_DEVICE_SERVICE_REC:
case HAL_PROP_DEVICE_VERSION_INFO:
default:
- send_props[i].len = hal_prop->len;
- send_props[i].val = hal_prop->val;
+ send_props[i].len = prop->len;
+ send_props[i].val = prop->val;
break;
}
- p += sizeof(*hal_prop) + hal_prop->len;
- hal_prop = p;
+ buf += sizeof(*prop) + prop->len;
+ prop = buf;
DBG("prop[%d]: %s", i, btproperty2str(&send_props[i]));
}
@@ -147,24 +138,45 @@ static void device_hal_props_cleanup(bt_property_t *props, uint8_t num)
}
}
-static void handle_adapter_props_changed(void *buf, uint16_t len)
+static void check_props(int num, const struct hal_property *prop, uint16_t len)
+{
+ int i;
+
+ for (i = 0; i < num; i++) {
+ if (sizeof(*prop) + prop->len < len)
+ goto fail;
+
+ len -= sizeof(*prop) + prop->len;
+ }
+
+ if (!len)
+ return;
+
+fail:
+ error("invalid properties event, aborting");
+ exit(EXIT_FAILURE);
+}
+
+static void handle_adapter_props_changed(void *buf, uint16_t len, int fd)
{
struct hal_ev_adapter_props_changed *ev = buf;
bt_property_t props[ev->num_props];
DBG("");
+ check_props(ev->num_props, ev->props, len - sizeof(*ev));
+
if (!bt_hal_cbacks->adapter_properties_cb)
return;
- adapter_props_to_hal(props, ev->props, ev->num_props, buf + len);
+ adapter_props_to_hal(props, ev->props, ev->num_props);
bt_hal_cbacks->adapter_properties_cb(ev->status, ev->num_props, props);
adapter_hal_props_cleanup(props, ev->num_props);
}
-static void handle_bond_state_change(void *buf)
+static void handle_bond_state_change(void *buf, uint16_t len, int fd)
{
struct hal_ev_bond_state_changed *ev = buf;
bt_bdaddr_t *addr = (bt_bdaddr_t *) ev->bdaddr;
@@ -176,7 +188,7 @@ static void handle_bond_state_change(void *buf)
ev->state);
}
-static void handle_pin_request(void *buf)
+static void handle_pin_request(void *buf, uint16_t len, int fd)
{
struct hal_ev_pin_request *ev = buf;
/* Those are declared as packed, so it's safe to assign pointers */
@@ -189,7 +201,7 @@ static void handle_pin_request(void *buf)
bt_hal_cbacks->pin_request_cb(addr, name, ev->class_of_dev);
}
-static void handle_ssp_request(void *buf)
+static void handle_ssp_request(void *buf, uint16_t len, int fd)
{
struct hal_ev_ssp_request *ev = buf;
/* Those are declared as packed, so it's safe to assign pointers */
@@ -221,7 +233,7 @@ static bool interface_ready(void)
return bt_hal_cbacks != NULL;
}
-static void handle_discovery_state_changed(void *buf)
+static void handle_discovery_state_changed(void *buf, uint16_t len, int fd)
{
struct hal_ev_discovery_state_changed *ev = buf;
@@ -231,34 +243,38 @@ static void handle_discovery_state_changed(void *buf)
bt_hal_cbacks->discovery_state_changed_cb(ev->state);
}
-static void handle_device_found(void *buf, uint16_t len)
+static void handle_device_found(void *buf, uint16_t len, int fd)
{
struct hal_ev_device_found *ev = buf;
bt_property_t props[ev->num_props];
DBG("");
+ check_props(ev->num_props, ev->props, len - sizeof(*ev));
+
if (!bt_hal_cbacks->device_found_cb)
return;
- device_props_to_hal(props, ev->props, ev->num_props, buf + len);
+ device_props_to_hal(props, ev->props, ev->num_props);
bt_hal_cbacks->device_found_cb(ev->num_props, props);
device_hal_props_cleanup(props, ev->num_props);
}
-static void handle_device_state_changed(void *buf, uint16_t len)
+static void handle_device_state_changed(void *buf, uint16_t len, int fd)
{
struct hal_ev_remote_device_props *ev = buf;
bt_property_t props[ev->num_props];
DBG("");
+ check_props(ev->num_props, ev->props, len - sizeof(*ev));
+
if (!bt_hal_cbacks->remote_device_properties_cb)
return;
- device_props_to_hal(props, ev->props, ev->num_props, buf + len);
+ device_props_to_hal(props, ev->props, ev->num_props);
bt_hal_cbacks->remote_device_properties_cb(ev->status,
(bt_bdaddr_t *)ev->bdaddr,
@@ -267,7 +283,7 @@ static void handle_device_state_changed(void *buf, uint16_t len)
device_hal_props_cleanup(props, ev->num_props);
}
-static void handle_acl_state_changed(void *buf)
+static void handle_acl_state_changed(void *buf, uint16_t len, int fd)
{
struct hal_ev_acl_state_changed *ev = buf;
bt_bdaddr_t *addr = (bt_bdaddr_t *) ev->bdaddr;
@@ -279,48 +295,82 @@ static void handle_acl_state_changed(void *buf)
ev->state);
}
-/* will be called from notification thread context */
-void bt_notify_adapter(uint8_t opcode, void *buf, uint16_t len)
+static void handle_dut_mode_receive(void *buf, uint16_t len, int fd)
{
- if (!interface_ready())
- return;
-
- DBG("opcode 0x%x", opcode);
+ DBG("");
- switch (opcode) {
- case HAL_EV_ADAPTER_STATE_CHANGED:
- handle_adapter_state_changed(buf);
- break;
- case HAL_EV_ADAPTER_PROPS_CHANGED:
- handle_adapter_props_changed(buf, len);
- break;
- case HAL_EV_DISCOVERY_STATE_CHANGED:
- handle_discovery_state_changed(buf);
- break;
- case HAL_EV_DEVICE_FOUND:
- handle_device_found(buf, len);
- break;
- case HAL_EV_REMOTE_DEVICE_PROPS:
- handle_device_state_changed(buf, len);
- break;
- case HAL_EV_BOND_STATE_CHANGED:
- handle_bond_state_change(buf);
- break;
- case HAL_EV_PIN_REQUEST:
- handle_pin_request(buf);
- break;
- case HAL_EV_SSP_REQUEST:
- handle_ssp_request(buf);
- break;
- case HAL_EV_ACL_STATE_CHANGED:
- handle_acl_state_changed(buf);
- break;
- default:
- DBG("Unhandled callback opcode=0x%x", opcode);
- break;
- }
+ /* TODO */
}
+static void handle_le_test_mode(void *buf, uint16_t len, int fd)
+{
+ DBG("");
+
+ /* TODO */
+}
+
+/* handlers will be called from notification thread context */
+static const struct hal_msg_handler ev_handlers[] = {
+ {
+ .handler = handle_adapter_state_changed,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_adapter_state_changed)
+ },
+ {
+ .handler = handle_adapter_props_changed,
+ .var_len = true,
+ .data_len = sizeof(struct hal_ev_adapter_props_changed) +
+ sizeof(struct hal_property),
+ },
+ {
+ .handler = handle_device_state_changed,
+ .var_len = true,
+ .data_len = sizeof(struct hal_ev_remote_device_props) +
+ sizeof(struct hal_property),
+ },
+ {
+ .handler = handle_device_found,
+ .var_len = true,
+ .data_len = sizeof(struct hal_ev_device_found) +
+ sizeof(struct hal_property),
+ },
+ {
+ .handler = handle_discovery_state_changed,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_discovery_state_changed),
+ },
+ {
+ .handler = handle_pin_request,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_pin_request),
+ },
+ {
+ .handler = handle_ssp_request,
+ .var_len = false,
+ .data_len = sizeof(handle_ssp_request),
+ },
+ {
+ .handler = handle_bond_state_change,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_bond_state_changed),
+ },
+ {
+ .handler = handle_acl_state_changed,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_acl_state_changed),
+ },
+ {
+ .handler = handle_dut_mode_receive,
+ .var_len = true,
+ .data_len = sizeof(struct hal_ev_dut_mode_receive),
+ },
+ {
+ .handler = handle_le_test_mode,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_le_test_mode),
+ },
+};
+
static int init(bt_callbacks_t *callbacks)
{
struct hal_cmd_register_module cmd;
@@ -333,6 +383,10 @@ static int init(bt_callbacks_t *callbacks)
bt_hal_cbacks = callbacks;
+ hal_msg_register(HAL_SERVICE_ID_BLUETOOTH, ev_handlers,
+ sizeof(ev_handlers)/sizeof(ev_handlers[0]),
+ HAL_MINIMUM_EVENT);
+
if (!hal_ipc_init()) {
bt_hal_cbacks = NULL;
return BT_STATUS_FAIL;
@@ -361,6 +415,9 @@ static int init(bt_callbacks_t *callbacks)
fail:
hal_ipc_cleanup();
bt_hal_cbacks = NULL;
+
+ hal_msg_unregister(HAL_SERVICE_ID_BLUETOOTH);
+
return status;
}
@@ -396,6 +453,8 @@ static void cleanup(void)
hal_ipc_cleanup();
bt_hal_cbacks = NULL;
+
+ hal_msg_unregister(HAL_SERVICE_ID_BLUETOOTH);
}
static int get_adapter_properties(void)
diff --git a/android/hal-ipc.c b/android/hal-ipc.c
index e1c8dd7..0ab77bc 100644
--- a/android/hal-ipc.c
+++ b/android/hal-ipc.c
@@ -43,25 +43,6 @@ static pthread_mutex_t cmd_sk_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_t notif_th = 0;
-static void notification_dispatch(struct hal_hdr *msg, int fd)
-{
- switch (msg->service_id) {
- case HAL_SERVICE_ID_BLUETOOTH:
- bt_notify_adapter(msg->opcode, msg->payload, msg->len);
- break;
- case HAL_SERVICE_ID_HIDHOST:
- bt_notify_hidhost(msg->opcode, msg->payload, msg->len);
- break;
- case HAL_SERVICE_ID_A2DP:
- bt_notify_a2dp(msg->opcode, msg->payload, msg->len);
- break;
- default:
- DBG("Unhandled notification service=%d opcode=0x%x",
- msg->service_id, msg->opcode);
- break;
- }
-}
-
static void *notification_handler(void *data)
{
struct msghdr msg;
@@ -69,7 +50,6 @@ static void *notification_handler(void *data)
struct cmsghdr *cmsg;
char cmsgbuf[CMSG_SPACE(sizeof(int))];
char buf[BLUEZ_HAL_MTU];
- struct hal_hdr *ev = (void *) buf;
ssize_t ret;
int fd;
@@ -80,7 +60,7 @@ static void *notification_handler(void *data)
memset(buf, 0, sizeof(buf));
memset(cmsgbuf, 0, sizeof(cmsgbuf));
- iv.iov_base = ev;
+ iv.iov_base = buf;
iv.iov_len = sizeof(buf);
msg.msg_iov = &iv;
@@ -105,24 +85,6 @@ static void *notification_handler(void *data)
exit(EXIT_FAILURE);
}
- if (ret < (ssize_t) sizeof(*ev)) {
- error("Too small notification (%zd bytes), aborting",
- ret);
- exit(EXIT_FAILURE);
- }
-
- if (ev->opcode < HAL_MINIMUM_EVENT) {
- error("Invalid notification (0x%x), aborting",
- ev->opcode);
- exit(EXIT_FAILURE);
- }
-
- if (ret != (ssize_t) (sizeof(*ev) + ev->len)) {
- error("Malformed notification(%zd bytes), aborting",
- ret);
- exit(EXIT_FAILURE);
- }
-
fd = -1;
/* Receive auxiliary data in msg */
@@ -135,7 +97,10 @@ static void *notification_handler(void *data)
}
}
- notification_dispatch(ev, fd);
+ if (!hal_msg_handler(buf, ret, fd)) {
+ error("Notification handler failed, aborting");
+ exit(EXIT_FAILURE);
+ }
}
close(notif_sk);
diff --git a/android/hal.h b/android/hal.h
index 72090fe..67dad5d 100644
--- a/android/hal.h
+++ b/android/hal.h
@@ -26,7 +26,6 @@ bthh_interface_t *bt_get_hidhost_interface(void);
btpan_interface_t *bt_get_pan_interface(void);
btav_interface_t *bt_get_a2dp_interface(void);
-void bt_notify_adapter(uint8_t opcode, void *buf, uint16_t len);
void bt_thread_associate(void);
void bt_thread_disassociate(void);
void bt_notify_hidhost(uint8_t opcode, void *buf, uint16_t len);
--
1.8.4.3
^ permalink raw reply related
* [RFC v2 3/5] android/hal-hidhost: Use generic IPC message handling for events
From: Szymon Janc @ 2013-11-15 1:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1384479617-15555-1-git-send-email-szymon.janc@tieto.com>
Register handlers on service init and unregister on cleanup.
---
android/hal-hidhost.c | 76 +++++++++++++++++++++++++++++----------------------
android/hal.h | 1 -
2 files changed, 44 insertions(+), 33 deletions(-)
diff --git a/android/hal-hidhost.c b/android/hal-hidhost.c
index 2ce17a3..a1726d8 100644
--- a/android/hal-hidhost.c
+++ b/android/hal-hidhost.c
@@ -32,7 +32,7 @@ static bool interface_ready(void)
return cbacks != NULL;
}
-static void handle_conn_state(void *buf)
+static void handle_conn_state(void *buf, uint16_t len, int fd)
{
struct hal_ev_hidhost_conn_state *ev = buf;
@@ -41,7 +41,7 @@ static void handle_conn_state(void *buf)
ev->state);
}
-static void handle_info(void *buf)
+static void handle_info(void *buf, uint16_t len, int fd)
{
struct hal_ev_hidhost_info *ev = buf;
bthh_hid_info_t info;
@@ -60,7 +60,7 @@ static void handle_info(void *buf)
cbacks->hid_info_cb((bt_bdaddr_t *) ev->bdaddr, info);
}
-static void handle_proto_mode(void *buf)
+static void handle_proto_mode(void *buf, uint16_t len, int fd)
{
struct hal_ev_hidhost_proto_mode *ev = buf;
@@ -69,16 +69,21 @@ static void handle_proto_mode(void *buf)
ev->status, ev->mode);
}
-static void handle_get_report(void *buf)
+static void handle_get_report(void *buf, uint16_t len, int fd)
{
struct hal_ev_hidhost_get_report *ev = buf;
+ if (len != sizeof(*ev) + ev->len) {
+ error("invalid get report event, aborting");
+ exit(EXIT_FAILURE);
+ }
+
if (cbacks->get_report_cb)
cbacks->get_report_cb((bt_bdaddr_t *) ev->bdaddr, ev->status,
ev->data, ev->len);
}
-static void handle_virtual_unplug(void *buf)
+static void handle_virtual_unplug(void *buf, uint16_t len, int fd)
{
struct hal_ev_hidhost_virtual_unplug *ev = buf;
@@ -87,33 +92,34 @@ static void handle_virtual_unplug(void *buf)
ev->status);
}
-/* will be called from notification thread context */
-void bt_notify_hidhost(uint8_t opcode, void *buf, uint16_t len)
-{
- if (!interface_ready())
- return;
-
- switch (opcode) {
- case HAL_EV_HIDHOST_CONN_STATE:
- handle_conn_state(buf);
- break;
- case HAL_EV_HIDHOST_INFO:
- handle_info(buf);
- break;
- case HAL_EV_HIDHOST_PROTO_MODE:
- handle_proto_mode(buf);
- break;
- case HAL_EV_HIDHOST_GET_REPORT:
- handle_get_report(buf);
- break;
- case HAL_EV_HIDHOST_VIRTUAL_UNPLUG:
- handle_virtual_unplug(buf);
- break;
- default:
- DBG("Unhandled callback opcode=0x%x", opcode);
- break;
- }
-}
+/* handlers will be called from notification thread context */
+static const struct hal_msg_handler ev_handlers[] = {
+ {
+ .handler = handle_conn_state,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_hidhost_conn_state)
+ },
+ {
+ .handler = handle_info,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_hidhost_info),
+ },
+ {
+ .handler = handle_proto_mode,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_hidhost_proto_mode),
+ },
+ {
+ .handler = handle_get_report,
+ .var_len = true,
+ .data_len = sizeof(struct hal_ev_hidhost_get_report),
+ },
+ {
+ .handler = handle_virtual_unplug,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_hidhost_virtual_unplug),
+ },
+};
static bt_status_t hidhost_connect(bt_bdaddr_t *bd_addr)
{
@@ -362,6 +368,10 @@ static bt_status_t init(bthh_callbacks_t *callbacks)
/* store reference to user callbacks */
cbacks = callbacks;
+ hal_msg_register(HAL_SERVICE_ID_HIDHOST, ev_handlers,
+ sizeof(ev_handlers)/sizeof(ev_handlers[0]),
+ HAL_MINIMUM_EVENT);
+
cmd.service_id = HAL_SERVICE_ID_HIDHOST;
return hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
@@ -383,6 +393,8 @@ static void cleanup(void)
hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
sizeof(cmd), &cmd, 0, NULL, NULL);
+
+ hal_msg_unregister(HAL_SERVICE_ID_HIDHOST);
}
static bthh_interface_t hidhost_if = {
diff --git a/android/hal.h b/android/hal.h
index 67dad5d..58426a9 100644
--- a/android/hal.h
+++ b/android/hal.h
@@ -28,6 +28,5 @@ btav_interface_t *bt_get_a2dp_interface(void);
void bt_thread_associate(void);
void bt_thread_disassociate(void);
-void bt_notify_hidhost(uint8_t opcode, void *buf, uint16_t len);
void bt_notify_a2dp(uint8_t opcode, void *buf, uint16_t len);
void bt_notify_pan(uint8_t opcode, void *buf, uint16_t len);
--
1.8.4.3
^ permalink raw reply related
* [RFC v2 4/5] android/hal-pan: Use generic IPC message handling for events
From: Szymon Janc @ 2013-11-15 1:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1384479617-15555-1-git-send-email-szymon.janc@tieto.com>
Register handlers on service init and unregister on cleanup.
---
android/hal-pan.c | 40 +++++++++++++++++++++-------------------
android/hal.h | 1 -
2 files changed, 21 insertions(+), 20 deletions(-)
diff --git a/android/hal-pan.c b/android/hal-pan.c
index 2bc560e..4190d0b 100644
--- a/android/hal-pan.c
+++ b/android/hal-pan.c
@@ -31,7 +31,7 @@ static bool interface_ready(void)
return cbs != NULL;
}
-static void handle_conn_state(void *buf)
+static void handle_conn_state(void *buf, uint16_t len, int fd)
{
struct hal_ev_pan_conn_state *ev = buf;
@@ -41,7 +41,7 @@ static void handle_conn_state(void *buf)
ev->local_role, ev->remote_role);
}
-static void handle_ctrl_state(void *buf)
+static void handle_ctrl_state(void *buf, uint16_t len, int fd)
{
struct hal_ev_pan_ctrl_state *ev = buf;
@@ -50,23 +50,19 @@ static void handle_ctrl_state(void *buf)
ev->local_role, (char *)ev->name);
}
-void bt_notify_pan(uint8_t opcode, void *buf, uint16_t len)
-{
- if (!interface_ready())
- return;
-
- switch (opcode) {
- case HAL_EV_PAN_CONN_STATE:
- handle_conn_state(buf);
- break;
- case HAL_EV_PAN_CTRL_STATE:
- handle_ctrl_state(buf);
- break;
- default:
- DBG("Unhandled callback opcode=0x%x", opcode);
- break;
- }
-}
+/* handlers will be called from notification thread context */
+static const struct hal_msg_handler ev_handlers[] = {
+ {
+ .handler = handle_conn_state,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_pan_conn_state),
+ },
+ {
+ .handler = handle_ctrl_state,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_pan_ctrl_state),
+ },
+};
static bt_status_t pan_enable(int local_role)
{
@@ -143,6 +139,10 @@ static bt_status_t pan_init(const btpan_callbacks_t *callbacks)
cbs = callbacks;
+ hal_msg_register(HAL_SERVICE_ID_PAN, ev_handlers,
+ sizeof(ev_handlers)/sizeof(ev_handlers[0]),
+ HAL_MINIMUM_EVENT);
+
cmd.service_id = HAL_SERVICE_ID_PAN;
return hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
@@ -164,6 +164,8 @@ static void pan_cleanup()
hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
sizeof(cmd), &cmd, 0, NULL, NULL);
+
+ hal_msg_unregister(HAL_SERVICE_ID_PAN);
}
static btpan_interface_t pan_if = {
diff --git a/android/hal.h b/android/hal.h
index 58426a9..6bd4c5a 100644
--- a/android/hal.h
+++ b/android/hal.h
@@ -29,4 +29,3 @@ btav_interface_t *bt_get_a2dp_interface(void);
void bt_thread_associate(void);
void bt_thread_disassociate(void);
void bt_notify_a2dp(uint8_t opcode, void *buf, uint16_t len);
-void bt_notify_pan(uint8_t opcode, void *buf, uint16_t len);
--
1.8.4.3
^ permalink raw reply related
* [RFC v2 5/5] android/hal-a2dp: Use generic IPC message handling for events
From: Szymon Janc @ 2013-11-15 1:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1384479617-15555-1-git-send-email-szymon.janc@tieto.com>
Register handlers on service init and unregister on cleanup.
---
android/hal-a2dp.c | 41 +++++++++++++++++++++--------------------
android/hal.h | 1 -
2 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/android/hal-a2dp.c b/android/hal-a2dp.c
index e9fadb7..757a8ce 100644
--- a/android/hal-a2dp.c
+++ b/android/hal-a2dp.c
@@ -31,7 +31,7 @@ static bool interface_ready(void)
return cbs != NULL;
}
-static void handle_conn_state(void *buf)
+static void handle_conn_state(void *buf, uint16_t len, int fd)
{
struct hal_ev_a2dp_conn_state *ev = buf;
@@ -40,7 +40,7 @@ static void handle_conn_state(void *buf)
(bt_bdaddr_t *) (ev->bdaddr));
}
-static void handle_audio_state(void *buf)
+static void handle_audio_state(void *buf, uint16_t len, int fd)
{
struct hal_ev_a2dp_audio_state *ev = buf;
@@ -48,24 +48,19 @@ static void handle_audio_state(void *buf)
cbs->audio_state_cb(ev->state, (bt_bdaddr_t *)(ev->bdaddr));
}
-/* will be called from notification thread context */
-void bt_notify_a2dp(uint8_t opcode, void *buf, uint16_t len)
-{
- if (!interface_ready())
- return;
-
- switch (opcode) {
- case HAL_EV_A2DP_CONN_STATE:
- handle_conn_state(buf);
- break;
- case HAL_EV_A2DP_AUDIO_STATE:
- handle_audio_state(buf);
- break;
- default:
- DBG("Unhandled callback opcode=0x%x", opcode);
- break;
- }
-}
+/* handlers will be called from notification thread context */
+static const struct hal_msg_handler ev_handlers[] = {
+ {
+ .handler = handle_conn_state,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_pan_conn_state),
+ },
+ {
+ .handler = handle_audio_state,
+ .var_len = false,
+ .data_len = sizeof(struct hal_ev_pan_ctrl_state),
+ },
+};
static bt_status_t a2dp_connect(bt_bdaddr_t *bd_addr)
{
@@ -105,6 +100,10 @@ static bt_status_t init(btav_callbacks_t *callbacks)
cbs = callbacks;
+ hal_msg_register(HAL_SERVICE_ID_A2DP, ev_handlers,
+ sizeof(ev_handlers)/sizeof(ev_handlers[0]),
+ HAL_MINIMUM_EVENT);
+
cmd.service_id = HAL_SERVICE_ID_A2DP;
return hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
@@ -126,6 +125,8 @@ static void cleanup()
hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
sizeof(cmd), &cmd, 0, NULL, NULL);
+
+ hal_msg_unregister(HAL_SERVICE_ID_A2DP);
}
static btav_interface_t iface = {
diff --git a/android/hal.h b/android/hal.h
index 6bd4c5a..b475411 100644
--- a/android/hal.h
+++ b/android/hal.h
@@ -28,4 +28,3 @@ btav_interface_t *bt_get_a2dp_interface(void);
void bt_thread_associate(void);
void bt_thread_disassociate(void);
-void bt_notify_a2dp(uint8_t opcode, void *buf, uint16_t len);
--
1.8.4.3
^ 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