Android will cancel ongoing discovery after some period of time so there
is no need for another timeout inside the daemon itself.
---
android/adapter.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 107 insertions(+), 1 deletion(-)
diff --git a/android/adapter.c b/android/adapter.c
index 02f356d..a12ccb3 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -26,8 +26,9 @@
#include <glib.h>
#include "lib/bluetooth.h"
-#include "src/shared/mgmt.h"
+#include "lib/sdp.h"
#include "lib/mgmt.h"
+#include "src/shared/mgmt.h"
#include "log.h"
#include "hal-msg.h"
#include "ipc.h"
@@ -52,6 +53,8 @@ struct bt_adapter {
uint32_t supported_settings;
uint32_t current_settings;
+
+ bool discovering;
};
static struct bt_adapter *adapter;
@@ -349,6 +352,35 @@ static void user_passkey_notify_callback(uint16_t index, uint16_t length,
ev->passkey);
}
+static void mgmt_discovering_event(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
+{
+ const struct mgmt_ev_discovering *ev = param;
+ struct hal_ev_discovery_state_changed cp;
+
+ if (length < sizeof(*ev)) {
+ error("Too small discovering event");
+ return;
+ }
+
+ DBG("hci%u type %u discovering %u", adapter->index, ev->type,
+ ev->discovering);
+
+ if (adapter->discovering == !!ev->discovering)
+ return;
+
+ adapter->discovering = !!ev->discovering;
+
+ DBG("new discovering state %u", ev->discovering);
+
+ cp.state = adapter->discovering ? HAL_DISCOVERY_STATE_STARTED :
+ HAL_DISCOVERY_STATE_STOPPED;
+
+ ipc_send(notification_io, HAL_SERVICE_ID_BLUETOOTH,
+ HAL_EV_DISCOVERY_STATE_CHANGED,
+ sizeof(cp), &cp, -1);
+}
+
static void register_mgmt_handlers(void)
{
mgmt_register(adapter->mgmt, MGMT_EV_NEW_SETTINGS, adapter->index,
@@ -379,6 +411,10 @@ static void register_mgmt_handlers(void)
mgmt_register(adapter->mgmt, MGMT_EV_PASSKEY_NOTIFY, adapter->index,
user_passkey_notify_callback, NULL, NULL);
+ mgmt_register(adapter->mgmt, MGMT_EV_DISCOVERING, adapter->index,
+ mgmt_discovering_event,
+ NULL, NULL);
+
}
static void load_link_keys_complete(uint8_t status, uint16_t length,
@@ -551,6 +587,7 @@ void bt_adapter_init(uint16_t index, struct mgmt *mgmt, bt_adapter_ready cb)
adapter->mgmt = mgmt_ref(mgmt);
adapter->index = index;
+ adapter->discovering = false;
adapter->ready = cb;
if (mgmt_send(mgmt, MGMT_OP_READ_INFO, index, 0, NULL,
@@ -624,6 +661,46 @@ static bool get_property(void *buf, uint16_t len)
}
}
+static bool start_discovery(void)
+{
+ struct mgmt_cp_start_discovery cp;
+ uint8_t type = 1 << BDADDR_BREDR;
+
+ if (adapter->current_settings & type)
+ cp.type = type;
+ else
+ cp.type = 0;
+
+ DBG("type=0x%x", type);
+
+ if (mgmt_send(adapter->mgmt, MGMT_OP_START_DISCOVERY, adapter->index,
+ sizeof(cp), &cp, NULL, NULL, NULL) > 0)
+ return true;
+
+ error("Failed to start discovery");
+ return false;
+}
+
+static bool stop_discovery(void)
+{
+ struct mgmt_cp_stop_discovery cp;
+ uint8_t type = 1 << BDADDR_BREDR;
+
+ if (adapter->current_settings & type)
+ cp.type = type;
+ else
+ cp.type = 0;
+
+ DBG("type=0x%x", type);
+
+ if (mgmt_send(adapter->mgmt, MGMT_OP_STOP_DISCOVERY, adapter->index,
+ sizeof(cp), &cp, NULL, NULL, NULL) > 0)
+ return true;
+
+ error("Failed to start discovery");
+ return false;
+}
+
static uint8_t set_scan_mode(void *buf, uint16_t len)
{
uint8_t *mode = buf;
@@ -987,6 +1064,35 @@ void bt_adapter_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf,
status = ssp_reply(buf, len);
if (status != HAL_STATUS_SUCCESS)
goto error;
+ break;
+ case HAL_OP_START_DISCOVERY:
+ if (adapter->discovering) {
+ status = HAL_STATUS_DONE;
+ goto error;
+ }
+
+ if (!(adapter->current_settings & MGMT_SETTING_POWERED)) {
+ status = HAL_STATUS_NOT_READY;
+ goto error;
+ }
+
+ if (!start_discovery())
+ goto error;
+
+ break;
+ case HAL_OP_CANCEL_DISCOVERY:
+ if (!adapter->discovering) {
+ status = HAL_STATUS_DONE;
+ goto error;
+ }
+
+ if (!(adapter->current_settings & MGMT_SETTING_POWERED)) {
+ status = HAL_STATUS_NOT_READY;
+ goto error;
+ }
+
+ if (!stop_discovery())
+ goto error;
break;
default:
--
1.8.4.1
Hi Jakub,
On Thu, Oct 31, 2013, Jakub Tyszkowski wrote:
> Android will cancel ongoing discovery after some period of time so there
> is no need for another timeout inside the daemon itself.
>
> ---
> android/adapter.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 107 insertions(+), 1 deletion(-)
All five patches have been applied. Thanks.
Johan
Add define for adapter and remote device name property.
---
android/hal-msg.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/android/hal-msg.h b/android/hal-msg.h
index b792411..8a344d8 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -89,6 +89,8 @@ struct hal_cmd_get_adapter_prop {
uint8_t type;
} __attribute__((packed));
+#define HAL_MAX_NAME_LENGTH 249
+
#define HAL_PROP_ADAPTER_NAME 0x01
#define HAL_PROP_ADAPTER_ADDR 0x02
#define HAL_PROP_ADAPTER_UUIDS 0x03
--
1.8.4.1
---
android/adapter.c | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/android/adapter.c b/android/adapter.c
index e72e45b..10d4a8e 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -390,6 +390,28 @@ static void mgmt_discovering_event(uint16_t index, uint16_t length,
sizeof(cp), &cp, -1);
}
+static void confirm_name_complete(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ if (status != MGMT_STATUS_SUCCESS)
+ error("Failed to confirm name: %s (0x%02x)",
+ mgmt_errstr(status), status);
+}
+
+static void confirm_device_name(const bdaddr_t *addr, uint8_t addr_type)
+{
+ struct mgmt_cp_confirm_name cp;
+
+ memset(&cp, 0, sizeof(cp));
+ bacpy(&cp.addr.bdaddr, addr);
+ cp.addr.type = addr_type;
+
+ if (mgmt_reply(adapter->mgmt, MGMT_OP_CONFIRM_NAME, adapter->index,
+ sizeof(cp), &cp, confirm_name_complete,
+ NULL, NULL) == 0)
+ error("Failed to send confirm name request");
+}
+
static int bdaddr_cmp(gconstpointer a, gconstpointer b)
{
const bdaddr_t *bda = a;
@@ -519,7 +541,13 @@ static void update_found_device(const bdaddr_t *bdaddr, uint8_t bdaddr_type,
g_free(buf);
}
- /* TODO: name confirmation */
+ if (confirm) {
+ char addr[18];
+
+ ba2str(bdaddr, addr);
+ info("Device %s needs name confirmation.", addr);
+ confirm_device_name(bdaddr, bdaddr_type);
+ }
eir_data_free(&eir);
}
--
1.8.4.1
This patch adds remote device found and remote device properties changed
notifications passing using IPC.
---
android/adapter.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 82 insertions(+), 2 deletions(-)
diff --git a/android/adapter.c b/android/adapter.c
index 154dd06..e72e45b 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -398,11 +398,45 @@ static int bdaddr_cmp(gconstpointer a, gconstpointer 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)
+{
+ uint8_t num_props = 0;
+
+ /* fill cod */
+ prop->type = HAL_PROP_DEVICE_CLASS;
+ prop->len = sizeof(cod);
+ memcpy(prop->val, &cod, prop->len);
+ prop = ((void *) prop) + sizeof(*prop) + sizeof(cod);
+ num_props++;
+
+ /* fill rssi */
+ prop->type = HAL_PROP_DEVICE_RSSI;
+ prop->len = sizeof(rssi);
+ memcpy(prop->val, &rssi, prop->len);
+ prop = ((void *) prop) + sizeof(*prop) + sizeof(rssi);
+ num_props++;
+
+ /* fill name */
+ if (name) {
+ prop->type = HAL_PROP_DEVICE_NAME;
+ prop->len = HAL_MAX_NAME_LENGTH;
+ strncpy((char *) prop->val, name, HAL_MAX_NAME_LENGTH - 1);
+ prop = ((void *) prop) + sizeof(*prop) + HAL_MAX_NAME_LENGTH;
+ num_props++;
+ }
+
+ return num_props;
+}
+
static void update_found_device(const bdaddr_t *bdaddr, uint8_t bdaddr_type,
int8_t rssi, bool confirm,
const uint8_t *data, uint8_t data_len)
{
bool is_new_dev = false;
+ size_t props_size = 0;
+ size_t buff_size = 0;
+ void *buf;
struct eir_data eir;
GSList *l;
bdaddr_t *remote = NULL;
@@ -433,10 +467,56 @@ static void update_found_device(const bdaddr_t *bdaddr, uint8_t bdaddr_type,
DBG("New device found: %s", addr);
}
+ props_size += sizeof(struct hal_property) + sizeof(eir.class);
+ props_size += sizeof(struct hal_property) + sizeof(rssi);
+
+ if (eir.name)
+ props_size += sizeof(struct hal_property) + HAL_MAX_NAME_LENGTH;
+
if (is_new_dev) {
- /* TODO: notify device found */
+ struct hal_ev_device_found *ev = NULL;
+ struct hal_property *prop = NULL;
+
+ /* with new device we also send bdaddr prop */
+ props_size += sizeof(struct hal_property) + sizeof(eir.addr);
+
+ buff_size = sizeof(struct hal_ev_device_found) + props_size;
+ buf = g_new0(char, buff_size);
+ ev = buf;
+ prop = ev->props;
+
+ /* fill first prop with bdaddr */
+ prop->type = HAL_PROP_DEVICE_ADDR;
+ prop->len = sizeof(bdaddr_t);
+ bdaddr2android(bdaddr, prop->val);
+ prop = ((void *) prop) + sizeof(*prop) + sizeof(bdaddr_t);
+ ev->num_props += 1;
+
+ /* fill eir, name, and cod props */
+ ev->num_props += fill_device_props(prop, remote, eir.class,
+ rssi, eir.name);
+
+ ipc_send(notification_io, HAL_SERVICE_ID_BLUETOOTH,
+ HAL_EV_DEVICE_FOUND,
+ buff_size, ev, -1);
+ g_free(buf);
} else {
- /* TODO: notify device state changed */
+ struct hal_ev_remote_device_props *ev = NULL;
+
+ buff_size = sizeof(*ev) + props_size;
+ buf = g_new0(char, buff_size);
+ ev = buf;
+
+ ev->num_props = fill_device_props(ev->props, remote, eir.class,
+ rssi, eir.name);
+
+ ev->status = HAL_STATUS_SUCCESS;
+ bdaddr2android(bdaddr, ev->bdaddr);
+
+ ipc_send(notification_io, HAL_SERVICE_ID_BLUETOOTH,
+ HAL_EV_REMOTE_DEVICE_PROPS,
+ buff_size, ev, -1);
+ g_free(buf);
}
/* TODO: name confirmation */
--
1.8.4.1
This patch provides basic handling of device found events from management
interface. Temporary device adress list is being used to determine which
devices has already been reported and device property changed event should
be sent instead of device found event.
---
android/Android.mk | 2 +
android/Makefile.am | 2 +
android/adapter.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 111 insertions(+), 2 deletions(-)
diff --git a/android/Android.mk b/android/Android.mk
index e47f4a9..ef9ebf3 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -32,6 +32,8 @@ LOCAL_SRC_FILES := \
../src/sdpd-service.c \
../src/sdpd-request.c \
../src/sdpd-server.c \
+ ../src/glib-helper.c \
+ ../src/eir.c \
../lib/sdp.c \
../lib/bluetooth.c \
../lib/hci.c \
diff --git a/android/Makefile.am b/android/Makefile.am
index 05a124e..989b54d 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -7,6 +7,8 @@ android_bluetoothd_SOURCES = android/main.c \
android/utils.h \
src/sdpd-database.c src/sdpd-server.c \
src/sdpd-service.c src/sdpd-request.c \
+ src/glib-helper.h src/glib-helper.c \
+ src/eir.h src/eir.c \
src/shared/util.h src/shared/util.c \
src/shared/mgmt.h src/shared/mgmt.c \
android/adapter.h android/adapter.c \
diff --git a/android/adapter.c b/android/adapter.c
index a12ccb3..154dd06 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -29,6 +29,8 @@
#include "lib/sdp.h"
#include "lib/mgmt.h"
#include "src/shared/mgmt.h"
+#include "src/glib-helper.h"
+#include "src/eir.h"
#include "log.h"
#include "hal-msg.h"
#include "ipc.h"
@@ -58,6 +60,7 @@ struct bt_adapter {
};
static struct bt_adapter *adapter;
+static GSList *found_devices = NULL;
static void mgmt_local_name_changed_event(uint16_t index, uint16_t length,
const void *param, void *user_data)
@@ -373,14 +376,113 @@ static void mgmt_discovering_event(uint16_t index, uint16_t length,
DBG("new discovering state %u", ev->discovering);
- cp.state = adapter->discovering ? HAL_DISCOVERY_STATE_STARTED :
- HAL_DISCOVERY_STATE_STOPPED;
+ if (adapter->discovering) {
+ cp.state = HAL_DISCOVERY_STATE_STARTED;
+ } else {
+ g_slist_free_full(found_devices, g_free);
+ found_devices = NULL;
+
+ cp.state = HAL_DISCOVERY_STATE_STOPPED;
+ }
ipc_send(notification_io, HAL_SERVICE_ID_BLUETOOTH,
HAL_EV_DISCOVERY_STATE_CHANGED,
sizeof(cp), &cp, -1);
}
+static int bdaddr_cmp(gconstpointer a, gconstpointer b)
+{
+ const bdaddr_t *bda = a;
+ const bdaddr_t *bdb = b;
+
+ return bacmp(bdb, bda);
+}
+
+static void update_found_device(const bdaddr_t *bdaddr, uint8_t bdaddr_type,
+ int8_t rssi, bool confirm,
+ const uint8_t *data, uint8_t data_len)
+{
+ bool is_new_dev = false;
+ struct eir_data eir;
+ GSList *l;
+ bdaddr_t *remote = NULL;
+ int err;
+
+ memset(&eir, 0, sizeof(eir));
+
+ err = eir_parse(&eir, data, data_len);
+ if (err < 0) {
+ error("Error parsing EIR data: %s (%d)", strerror(-err), -err);
+ return;
+ }
+
+ l = g_slist_find_custom(found_devices, bdaddr, bdaddr_cmp);
+ if (l)
+ remote = l->data;
+
+ if (!remote) {
+ char addr[18];
+
+ remote = g_new0(bdaddr_t, 1);
+ bacpy(remote, bdaddr);
+
+ found_devices = g_slist_prepend(found_devices, remote);
+ is_new_dev = true;
+
+ ba2str(remote, addr);
+ DBG("New device found: %s", addr);
+ }
+
+ if (is_new_dev) {
+ /* TODO: notify device found */
+ } else {
+ /* TODO: notify device state changed */
+ }
+
+ /* TODO: name confirmation */
+
+ eir_data_free(&eir);
+}
+
+static void mgmt_device_found_event(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
+{
+ const struct mgmt_ev_device_found *ev = param;
+ const uint8_t *eir;
+ uint16_t eir_len;
+ uint32_t flags;
+ bool confirm_name;
+ char addr[18];
+
+ if (length < sizeof(*ev)) {
+ error("Too short device found event (%u bytes)", length);
+ return;
+ }
+
+ eir_len = btohs(ev->eir_len);
+ if (length != sizeof(*ev) + eir_len) {
+ error("Device found event size mismatch (%u != %zu)",
+ length, sizeof(*ev) + eir_len);
+ return;
+ }
+
+ if (eir_len == 0)
+ eir = NULL;
+ else
+ eir = ev->eir;
+
+ flags = btohl(ev->flags);
+
+ ba2str(&ev->addr.bdaddr, addr);
+ DBG("hci%u addr %s, rssi %d flags 0x%04x eir_len %u eir %u",
+ index, addr, ev->rssi, flags, eir_len, *eir);
+
+ confirm_name = flags & MGMT_DEV_FOUND_CONFIRM_NAME;
+
+ update_found_device(&ev->addr.bdaddr, ev->addr.type, ev->rssi,
+ confirm_name, eir, eir_len);
+}
+
static void register_mgmt_handlers(void)
{
mgmt_register(adapter->mgmt, MGMT_EV_NEW_SETTINGS, adapter->index,
@@ -415,6 +517,9 @@ static void register_mgmt_handlers(void)
mgmt_discovering_event,
NULL, NULL);
+ mgmt_register(adapter->mgmt, MGMT_EV_DEVICE_FOUND,
+ adapter->index, mgmt_device_found_event,
+ NULL, NULL);
}
static void load_link_keys_complete(uint8_t status, uint16_t length,
--
1.8.4.1