2046 lines
65 KiB
Diff
2046 lines
65 KiB
Diff
From 462033c46ff148aa59535545da6973b46e969e89 Mon Sep 17 00:00:00 2001
|
|
From: Yao Xiao <xiaoyao@rock-chips.com>
|
|
Date: Tue, 6 Aug 2024 16:45:02 +0800
|
|
Subject: [PATCH 1/1] bluez: modified only for rockchip
|
|
|
|
---
|
|
plugins/policy.c | 8 +-
|
|
profiles/audio/a2dp.c | 2 +
|
|
profiles/audio/avctp.c | 10 +-
|
|
profiles/audio/avrcp.c | 29 ++-
|
|
profiles/input/manager.c | 2 +-
|
|
profiles/network/manager.c | 2 +-
|
|
src/adapter.c | 100 ++++++--
|
|
src/advertising.c | 2 +-
|
|
src/agent.c | 1 +
|
|
src/bluetooth.conf | 3 +
|
|
src/btd.h | 3 +
|
|
src/device.c | 458 +++++++++++++++++++++++++++++++++----
|
|
src/device.h | 3 +
|
|
src/gatt-client.c | 22 +-
|
|
src/gatt-database.c | 26 ++-
|
|
src/main.c | 23 +-
|
|
src/main.conf | 8 +-
|
|
src/service.c | 6 +-
|
|
src/shared/att.c | 8 +-
|
|
src/shared/gatt-client.c | 4 +
|
|
20 files changed, 619 insertions(+), 101 deletions(-)
|
|
|
|
diff --git a/plugins/policy.c b/plugins/policy.c
|
|
index 9a449da61..e379a87ea 100644
|
|
--- a/plugins/policy.c
|
|
+++ b/plugins/policy.c
|
|
@@ -59,7 +59,7 @@ static const char *default_reconnect[] = {
|
|
A2DP_SINK_UUID, NULL };
|
|
static char **reconnect_uuids = NULL;
|
|
|
|
-static const size_t default_attempts = 7;
|
|
+static const size_t default_attempts = 0;
|
|
static size_t reconnect_attempts = 0;
|
|
|
|
static const int default_intervals[] = { 1, 2, 4, 8, 16, 32, 64 };
|
|
@@ -638,6 +638,8 @@ static void service_cb(struct btd_service *service,
|
|
struct btd_profile *profile = btd_service_get_profile(service);
|
|
struct reconnect_data *reconnect;
|
|
|
|
+ error("uuid: %s, %d -> %d", profile->remote_uuid, old_state, new_state);
|
|
+
|
|
if (g_str_equal(profile->remote_uuid, A2DP_SINK_UUID))
|
|
sink_cb(service, old_state, new_state);
|
|
else if (g_str_equal(profile->remote_uuid, A2DP_SOURCE_UUID))
|
|
@@ -745,7 +747,8 @@ static void disconnect_cb(struct btd_device *dev, uint8_t reason)
|
|
{
|
|
struct reconnect_data *reconnect;
|
|
|
|
- DBG("reason %u", reason);
|
|
+ error("reason %u", reason);
|
|
+ return;
|
|
|
|
/* Only attempt reconnect for the following reasons */
|
|
if (reason != MGMT_DEV_DISCONN_TIMEOUT &&
|
|
@@ -805,6 +808,7 @@ static void conn_fail_cb(struct btd_device *dev, uint8_t status)
|
|
struct reconnect_data *reconnect;
|
|
|
|
DBG("status %u", status);
|
|
+ return;
|
|
|
|
reconnect = reconnect_find(dev);
|
|
if (!reconnect || !reconnect->reconnect)
|
|
diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
|
|
index 43da38051..c939ee539 100644
|
|
--- a/profiles/audio/a2dp.c
|
|
+++ b/profiles/audio/a2dp.c
|
|
@@ -326,6 +326,8 @@ static int error_to_errno(struct avdtp_error *err)
|
|
case EHOSTDOWN:
|
|
case ECONNABORTED:
|
|
case EBADE:
|
|
+ case ECONNREFUSED:
|
|
+ case EACCES:
|
|
return -perr;
|
|
default:
|
|
/*
|
|
diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c
|
|
index 8ad146df1..c08e59f2a 100644
|
|
--- a/profiles/audio/avctp.c
|
|
+++ b/profiles/audio/avctp.c
|
|
@@ -1597,11 +1597,13 @@ static void avctp_confirm_cb(GIOChannel *chan, gpointer data)
|
|
if (session == NULL)
|
|
return;
|
|
|
|
- if (btd_device_get_service(device, AVRCP_REMOTE_UUID) == NULL)
|
|
- btd_device_add_uuid(device, AVRCP_REMOTE_UUID);
|
|
+ if (!device_get_svc_refreshed(device)) {
|
|
+ if (btd_device_get_service(device, AVRCP_REMOTE_UUID) == NULL)
|
|
+ btd_device_add_uuid(device, AVRCP_REMOTE_UUID);
|
|
|
|
- if (btd_device_get_service(device, AVRCP_TARGET_UUID) == NULL)
|
|
- btd_device_add_uuid(device, AVRCP_TARGET_UUID);
|
|
+ if (btd_device_get_service(device, AVRCP_TARGET_UUID) == NULL)
|
|
+ btd_device_add_uuid(device, AVRCP_TARGET_UUID);
|
|
+ }
|
|
|
|
switch (psm) {
|
|
case AVCTP_CONTROL_PSM:
|
|
diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
|
|
index 752e55be3..8a746e051 100644
|
|
--- a/profiles/audio/avrcp.c
|
|
+++ b/profiles/audio/avrcp.c
|
|
@@ -1458,7 +1458,7 @@ static uint8_t player_get_status(struct avrcp_player *player)
|
|
const char *value;
|
|
|
|
if (player == NULL)
|
|
- return AVRCP_PLAY_STATUS_STOPPED;
|
|
+ return AVRCP_PLAY_STATUS_PLAYING;
|
|
|
|
value = player->cb->get_status(player->user_data);
|
|
if (value == NULL)
|
|
@@ -1625,6 +1625,8 @@ static uint8_t avrcp_handle_register_notification(struct avrcp *session,
|
|
if (len != 5)
|
|
goto err;
|
|
|
|
+ DBG("supported_events: 0x%x, event: 0x%x(0x%x)\n", session->supported_events, 1 << pdu->params[0], pdu->params[0]);
|
|
+
|
|
/* Check if event is supported otherwise reject */
|
|
if (!(session->supported_events & (1 << pdu->params[0])))
|
|
goto err;
|
|
@@ -1658,6 +1660,7 @@ static uint8_t avrcp_handle_register_notification(struct avrcp *session,
|
|
break;
|
|
case AVRCP_EVENT_VOLUME_CHANGED:
|
|
volume = media_transport_get_device_volume(dev);
|
|
+ warn("volume: %d", volume);
|
|
if (volume < 0)
|
|
goto err;
|
|
|
|
@@ -3979,7 +3982,7 @@ static gboolean avrcp_get_capabilities_resp(struct avctp *conn, uint8_t code,
|
|
uint8_t event = pdu->params[1 + count];
|
|
|
|
events |= (1 << event);
|
|
-
|
|
+ DBG("count: %d, event: 0x%x\n", count, event);
|
|
switch (event) {
|
|
case AVRCP_EVENT_STATUS_CHANGED:
|
|
case AVRCP_EVENT_TRACK_CHANGED:
|
|
@@ -3992,6 +3995,9 @@ static gboolean avrcp_get_capabilities_resp(struct avctp *conn, uint8_t code,
|
|
if (!session->controller ||
|
|
!session->controller->player)
|
|
break;
|
|
+
|
|
+ if (!btd_device_get_service(session->dev, A2DP_SOURCE_UUID))
|
|
+ break;
|
|
/* fall through */
|
|
case AVRCP_EVENT_VOLUME_CHANGED:
|
|
avrcp_register_notification(session, event);
|
|
@@ -4152,6 +4158,7 @@ static void target_init(struct avrcp *session)
|
|
media_transport_update_device_volume(session->dev, init_volume);
|
|
}
|
|
|
|
+ /* These events below requires a player */
|
|
session->supported_events |= (1 << AVRCP_EVENT_STATUS_CHANGED) |
|
|
(1 << AVRCP_EVENT_TRACK_CHANGED) |
|
|
(1 << AVRCP_EVENT_TRACK_REACHED_START) |
|
|
@@ -4232,6 +4239,10 @@ static void session_init_control(struct avrcp *session)
|
|
|
|
if (btd_device_get_service(session->dev, AVRCP_REMOTE_UUID) != NULL)
|
|
target_init(session);
|
|
+
|
|
+ //Force supported volume change
|
|
+ session->supported_events |=
|
|
+ (1 << AVRCP_EVENT_VOLUME_CHANGED);
|
|
}
|
|
|
|
static void controller_destroy(struct avrcp *session)
|
|
@@ -4517,6 +4528,8 @@ static int avrcp_event(struct avrcp *session, uint8_t id, const void *data)
|
|
uint16_t size;
|
|
int err;
|
|
|
|
+ DBG("registered_events = 0x%x:0x%x", session->registered_events, 1 << id);
|
|
+
|
|
/* Verify that the event is registered */
|
|
if (!(session->registered_events & (1 << id)))
|
|
return -ENOENT;
|
|
@@ -4579,8 +4592,8 @@ int avrcp_set_volume(struct btd_device *dev, int8_t volume, bool notify)
|
|
return -ENOTCONN;
|
|
|
|
if (notify) {
|
|
- if (!session->target)
|
|
- return -ENOTSUP;
|
|
+ //if (!session->target)
|
|
+ // return -ENOTSUP;
|
|
return avrcp_event(session, AVRCP_EVENT_VOLUME_CHANGED,
|
|
&volume);
|
|
}
|
|
@@ -4695,7 +4708,7 @@ static int avrcp_target_server_probe(struct btd_profile *p,
|
|
return -EPROTONOSUPPORT;
|
|
|
|
done:
|
|
- record = avrcp_tg_record(server->browsing);
|
|
+ record = avrcp_ct_record(server->browsing);
|
|
if (!record) {
|
|
error("Unable to allocate new service record");
|
|
avrcp_target_server_remove(p, adapter);
|
|
@@ -4708,7 +4721,7 @@ done:
|
|
sdp_record_free(record);
|
|
return -1;
|
|
}
|
|
- server->tg_record_id = record->handle;
|
|
+ server->ct_record_id = record->handle;
|
|
|
|
return 0;
|
|
}
|
|
@@ -4778,7 +4791,7 @@ static int avrcp_controller_server_probe(struct btd_profile *p,
|
|
return -EPROTONOSUPPORT;
|
|
|
|
done:
|
|
- record = avrcp_ct_record(server->browsing);
|
|
+ record = avrcp_tg_record(server->browsing);
|
|
if (!record) {
|
|
error("Unable to allocate new service record");
|
|
avrcp_controller_server_remove(p, adapter);
|
|
@@ -4791,7 +4804,7 @@ done:
|
|
sdp_record_free(record);
|
|
return -1;
|
|
}
|
|
- server->ct_record_id = record->handle;
|
|
+ server->tg_record_id = record->handle;
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/profiles/input/manager.c b/profiles/input/manager.c
|
|
index f4598bcd4..fe7758b49 100644
|
|
--- a/profiles/input/manager.c
|
|
+++ b/profiles/input/manager.c
|
|
@@ -80,7 +80,7 @@ static int input_init(void)
|
|
GKeyFile *config;
|
|
GError *err = NULL;
|
|
|
|
- config = load_config_file(CONFIGDIR "/input.conf");
|
|
+ config = load_config_file("/etc/input.conf");
|
|
if (config) {
|
|
int idle_timeout;
|
|
gboolean uhid_enabled, classic_bonded_only, auto_sec;
|
|
diff --git a/profiles/network/manager.c b/profiles/network/manager.c
|
|
index a2650d6f0..5fb21b92d 100644
|
|
--- a/profiles/network/manager.c
|
|
+++ b/profiles/network/manager.c
|
|
@@ -158,7 +158,7 @@ static int network_init(void)
|
|
{
|
|
int err;
|
|
|
|
- read_config(CONFIGDIR "/network.conf");
|
|
+ read_config("/etc/network.conf");
|
|
|
|
err = bnep_init();
|
|
if (err) {
|
|
diff --git a/src/adapter.c b/src/adapter.c
|
|
index bb49a1eca..905d9fd4a 100644
|
|
--- a/src/adapter.c
|
|
+++ b/src/adapter.c
|
|
@@ -746,6 +746,7 @@ static void remove_temporary_devices(struct btd_adapter *adapter)
|
|
struct btd_device *dev = l->data;
|
|
|
|
next = g_slist_next(l);
|
|
+ DBG("device_is_temporary: %d", device_is_temporary(dev));
|
|
if (device_is_temporary(dev))
|
|
btd_adapter_remove_device(adapter, dev);
|
|
}
|
|
@@ -784,7 +785,7 @@ static bool set_mode(struct btd_adapter *adapter, uint16_t opcode,
|
|
break;
|
|
}
|
|
|
|
- DBG("sending set mode command for index %u", adapter->dev_id);
|
|
+ DBG("sending set mode command %d for index %u", opcode, adapter->dev_id);
|
|
|
|
data = g_new0(struct set_mode_data, 1);
|
|
data->adapter = adapter;
|
|
@@ -1009,6 +1010,7 @@ struct btd_device *btd_adapter_find_device(struct btd_adapter *adapter,
|
|
struct device_addr_type addr;
|
|
struct btd_device *device;
|
|
GSList *list;
|
|
+ char str[18];
|
|
|
|
if (!adapter)
|
|
return NULL;
|
|
@@ -1016,12 +1018,16 @@ struct btd_device *btd_adapter_find_device(struct btd_adapter *adapter,
|
|
bacpy(&addr.bdaddr, dst);
|
|
addr.bdaddr_type = bdaddr_type;
|
|
|
|
+ ba2str(dst, str);
|
|
+ DBG("find addr: %s, type: %d", str, bdaddr_type);
|
|
+
|
|
list = g_slist_find_custom(adapter->devices, &addr,
|
|
device_addr_type_cmp);
|
|
if (!list)
|
|
return NULL;
|
|
|
|
device = list->data;
|
|
+ DBG("Got it");
|
|
|
|
/*
|
|
* If we're looking up based on public address and the address
|
|
@@ -1089,6 +1095,25 @@ static bool is_supported_uuid(const uuid_t *uuid)
|
|
return true;
|
|
}
|
|
|
|
+static bool uuid_to_string(const uint8_t uuid[16], char *dest, size_t dest_size)
|
|
+{
|
|
+ int n;
|
|
+
|
|
+ n = snprintf(dest, dest_size, "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
|
|
+ "%02x%02x-%02x%02x%02x%02x%02x%02x",
|
|
+ uuid[0], uuid[1], uuid[2], uuid[3],
|
|
+ uuid[4], uuid[5],
|
|
+ uuid[6], uuid[7],
|
|
+ uuid[8], uuid[9],
|
|
+ uuid[10], uuid[11], uuid[12],
|
|
+ uuid[13], uuid[14], uuid[15]);
|
|
+
|
|
+ if (n < 0 || (size_t) n >= dest_size)
|
|
+ return false;
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
static void add_uuid_complete(uint8_t status, uint16_t length,
|
|
const void *param, void *user_data)
|
|
{
|
|
@@ -1117,6 +1142,7 @@ static int add_uuid(struct btd_adapter *adapter, uuid_t *uuid, uint8_t svc_hint)
|
|
struct mgmt_cp_add_uuid cp;
|
|
uuid_t uuid128;
|
|
uint128_t uint128;
|
|
+ char buf[37];
|
|
|
|
if (!is_supported_uuid(uuid)) {
|
|
btd_warn(adapter->dev_id,
|
|
@@ -1129,8 +1155,9 @@ static int add_uuid(struct btd_adapter *adapter, uuid_t *uuid, uint8_t svc_hint)
|
|
ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
|
|
htob128(&uint128, (uint128_t *) cp.uuid);
|
|
cp.svc_hint = svc_hint;
|
|
+ uuid_to_string(cp.uuid, buf, sizeof(buf));
|
|
|
|
- DBG("sending add uuid command for index %u", adapter->dev_id);
|
|
+ DBG("sending add uuid command for index %u uuid: %s", adapter->dev_id, buf);
|
|
|
|
if (mgmt_send(adapter->mgmt, MGMT_OP_ADD_UUID,
|
|
adapter->dev_id, sizeof(cp), &cp,
|
|
@@ -1171,6 +1198,7 @@ static int remove_uuid(struct btd_adapter *adapter, uuid_t *uuid)
|
|
struct mgmt_cp_remove_uuid cp;
|
|
uuid_t uuid128;
|
|
uint128_t uint128;
|
|
+ char buf[37];
|
|
|
|
if (!is_supported_uuid(uuid)) {
|
|
btd_warn(adapter->dev_id,
|
|
@@ -1183,7 +1211,9 @@ static int remove_uuid(struct btd_adapter *adapter, uuid_t *uuid)
|
|
ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
|
|
htob128(&uint128, (uint128_t *) cp.uuid);
|
|
|
|
- DBG("sending remove uuid command for index %u", adapter->dev_id);
|
|
+ uuid_to_string(cp.uuid, buf, sizeof(buf));
|
|
+
|
|
+ DBG("sending remove uuid command for index %u: %s", adapter->dev_id, buf);
|
|
|
|
if (mgmt_send(adapter->mgmt, MGMT_OP_REMOVE_UUID,
|
|
adapter->dev_id, sizeof(cp), &cp,
|
|
@@ -1459,14 +1489,18 @@ struct btd_device *btd_adapter_get_device(struct btd_adapter *adapter,
|
|
uint8_t addr_type)
|
|
{
|
|
struct btd_device *device;
|
|
+ char str[18];
|
|
|
|
if (!adapter)
|
|
return NULL;
|
|
|
|
+ ba2str(addr, str);
|
|
+ DBG("get start %s %d", str, addr_type);
|
|
+
|
|
device = btd_adapter_find_device(adapter, addr, addr_type);
|
|
if (device)
|
|
return device;
|
|
-
|
|
+ DBG("Don't found to create new");
|
|
return adapter_create_device(adapter, addr, addr_type);
|
|
}
|
|
|
|
@@ -1714,6 +1748,7 @@ static void invalidate_rssi_and_tx_power(gpointer a)
|
|
static void discovery_cleanup(struct btd_adapter *adapter, int timeout)
|
|
{
|
|
GSList *l, *next;
|
|
+ DBG("");
|
|
|
|
adapter->discovery_type = 0x00;
|
|
|
|
@@ -1733,7 +1768,10 @@ static void discovery_cleanup(struct btd_adapter *adapter, int timeout)
|
|
struct btd_device *dev = l->data;
|
|
|
|
next = g_slist_next(l);
|
|
-
|
|
+ DBG("device_is_temporary|connectable|connected: %d:%d:%d",
|
|
+ device_is_temporary(dev),
|
|
+ device_is_connectable(dev),
|
|
+ btd_device_is_connected(dev));
|
|
if (device_is_temporary(dev) && !device_is_connectable(dev)
|
|
&& !btd_device_is_connected(dev))
|
|
btd_adapter_remove_device(adapter, dev);
|
|
@@ -3656,7 +3694,7 @@ static void device_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
|
|
struct btd_device *device;
|
|
const char *path;
|
|
|
|
- DBG("%s", gerr ? gerr->message : "");
|
|
+ DBG("connected remote device (%s)", gerr ? gerr->message : "successful");
|
|
|
|
if (gerr)
|
|
goto failed;
|
|
@@ -4275,7 +4313,7 @@ static int set_privacy(struct btd_adapter *adapter, uint8_t privacy)
|
|
}
|
|
|
|
DBG("sending set privacy command for index %u", adapter->dev_id);
|
|
- DBG("setting privacy mode 0x%02x for index %u", cp.privacy,
|
|
+ error("setting privacy mode 0x%02x for index %u", cp.privacy,
|
|
adapter->dev_id);
|
|
|
|
if (mgmt_send(adapter->mgmt, MGMT_OP_SET_PRIVACY,
|
|
@@ -5455,7 +5493,7 @@ void adapter_connect_list_remove(struct btd_adapter *adapter,
|
|
return;
|
|
|
|
if (!g_slist_find(adapter->connect_list, device)) {
|
|
- DBG("device %s is not on the list, ignoring",
|
|
+ error("device %s is not on the list, ignoring",
|
|
device_get_path(device));
|
|
return;
|
|
}
|
|
@@ -7502,7 +7540,7 @@ static void adapter_remove_connection(struct btd_adapter *adapter,
|
|
{
|
|
bool remove_device = false;
|
|
|
|
- DBG("");
|
|
+ DBG("bdaddr_type: %d", bdaddr_type);
|
|
|
|
if (!g_slist_find(adapter->connections, device)) {
|
|
btd_error(adapter->dev_id, "No matching connection for device");
|
|
@@ -7510,6 +7548,7 @@ static void adapter_remove_connection(struct btd_adapter *adapter,
|
|
}
|
|
|
|
device_remove_connection(device, bdaddr_type, &remove_device);
|
|
+ DBG("remove_device flag: %d", remove_device);
|
|
|
|
if (device_is_authenticating(device))
|
|
device_cancel_authentication(device, TRUE);
|
|
@@ -7857,6 +7896,7 @@ int btd_adapter_restore_powered(struct btd_adapter *adapter)
|
|
bool powered;
|
|
|
|
powered = btd_adapter_get_powered(adapter);
|
|
+ DBG("powered %d, 0x%x", powered, adapter->current_settings);
|
|
if (adapter->power_state == ADAPTER_POWER_STATE_OFF_BLOCKED &&
|
|
rfkill_get_blocked(adapter->dev_id) == 0) {
|
|
adapter_set_power_state(adapter,
|
|
@@ -7868,6 +7908,7 @@ int btd_adapter_restore_powered(struct btd_adapter *adapter)
|
|
if (powered)
|
|
return 0;
|
|
|
|
+ DBG("set_mode MGMT_OP_SET_POWERED");
|
|
set_mode(adapter, MGMT_OP_SET_POWERED, 0x01);
|
|
|
|
return 0;
|
|
@@ -8330,6 +8371,7 @@ static void bonding_complete(struct btd_adapter *adapter,
|
|
uint8_t addr_type, uint8_t status)
|
|
{
|
|
struct btd_device *device;
|
|
+ DBG("");
|
|
|
|
if (status == 0)
|
|
device = btd_adapter_get_device(adapter, bdaddr, addr_type);
|
|
@@ -8503,6 +8545,7 @@ static void dev_disconnected(struct btd_adapter *adapter,
|
|
if (device) {
|
|
adapter_remove_connection(adapter, device, addr->type);
|
|
disconnect_notify(device, reason);
|
|
+ device_set_reason(device, addr->type, reason);
|
|
}
|
|
|
|
bonding_attempt_complete(adapter, &addr->bdaddr, addr->type,
|
|
@@ -8568,6 +8611,7 @@ static void auth_failed_callback(uint16_t index, uint16_t length,
|
|
{
|
|
const struct mgmt_ev_auth_failed *ev = param;
|
|
struct btd_adapter *adapter = user_data;
|
|
+ DBG("");
|
|
|
|
if (length < sizeof(*ev)) {
|
|
btd_error(adapter->dev_id, "Too small auth failed mgmt event");
|
|
@@ -8641,8 +8685,8 @@ static void new_link_key_callback(uint16_t index, uint16_t length,
|
|
|
|
ba2str(&addr->bdaddr, dst);
|
|
|
|
- DBG("hci%u new key for %s type %u pin_len %u store_hint %u",
|
|
- adapter->dev_id, dst, ev->key.type, ev->key.pin_len,
|
|
+ DBG("hci%u new key for %s|%d type %u pin_len %u store_hint %u",
|
|
+ adapter->dev_id, dst, addr->type, ev->key.type, ev->key.pin_len,
|
|
ev->store_hint);
|
|
|
|
if (ev->key.pin_len > 16) {
|
|
@@ -8728,6 +8772,7 @@ static void store_longtermkey(struct btd_adapter *adapter, const bdaddr_t *peer,
|
|
uint8_t enc_size, uint16_t ediv,
|
|
uint64_t rand)
|
|
{
|
|
+ DBG("central: %d", central);
|
|
if (central != 0x00 && central != 0x01) {
|
|
error("Unsupported LTK type %u", central);
|
|
return;
|
|
@@ -8767,8 +8812,8 @@ static void new_long_term_key_callback(uint16_t index, uint16_t length,
|
|
|
|
ba2str(&addr->bdaddr, dst);
|
|
|
|
- DBG("hci%u new LTK for %s type %u enc_size %u",
|
|
- adapter->dev_id, dst, ev->key.type, ev->key.enc_size);
|
|
+ DBG("hci%u new LTK for %s|%d type %u enc_size %u, store_hint: %d",
|
|
+ adapter->dev_id, dst, addr->type, ev->key.type, ev->key.enc_size, !!ev->store_hint);
|
|
|
|
device = btd_adapter_get_device(adapter, &addr->bdaddr, addr->type);
|
|
if (!device) {
|
|
@@ -8831,7 +8876,7 @@ static void new_csrk_callback(uint16_t index, uint16_t length,
|
|
|
|
ba2str(&addr->bdaddr, dst);
|
|
|
|
- DBG("hci%u new CSRK for %s type %u", adapter->dev_id, dst,
|
|
+ DBG("hci%u new CSRK for %s|%d type %u", adapter->dev_id, dst, addr->type,
|
|
ev->key.type);
|
|
|
|
device = btd_adapter_get_device(adapter, &addr->bdaddr, addr->type);
|
|
@@ -9440,6 +9485,9 @@ static void connected_callback(uint16_t index, uint16_t length,
|
|
return;
|
|
}
|
|
|
|
+ //workround double device with some addr
|
|
+ device_copy_addr(device, &ev->addr.bdaddr);
|
|
+
|
|
memset(&eir_data, 0, sizeof(eir_data));
|
|
if (eir_len > 0)
|
|
eir_parse(&eir_data, ev->eir, eir_len);
|
|
@@ -9618,6 +9666,8 @@ static void remove_keys(struct btd_adapter *adapter,
|
|
create_filename(filename, PATH_MAX, "/%s/%s/info",
|
|
btd_adapter_get_storage_dir(adapter), device_addr);
|
|
|
|
+ DBG("filename: %s, device_addr: %s", filename, device_addr);
|
|
+
|
|
key_file = g_key_file_new();
|
|
if (!g_key_file_load_from_file(key_file, filename, 0, &gerr)) {
|
|
error("Unable to load key file from %s: (%s)", filename,
|
|
@@ -9660,7 +9710,7 @@ static void unpaired_callback(uint16_t index, uint16_t length,
|
|
|
|
ba2str(&ev->addr.bdaddr, addr);
|
|
|
|
- DBG("hci%u addr %s", index, addr);
|
|
+ DBG("hci%u addr %s, type: %d", index, addr, ev->addr.type);
|
|
|
|
device = btd_adapter_find_device(adapter, &ev->addr.bdaddr,
|
|
ev->addr.type);
|
|
@@ -9672,6 +9722,16 @@ static void unpaired_callback(uint16_t index, uint16_t length,
|
|
|
|
remove_keys(adapter, device, ev->addr.type);
|
|
device_set_unpaired(device, ev->addr.type);
|
|
+
|
|
+ /*
|
|
+ if (ev->addr.type == BDADDR_BREDR)
|
|
+ device->bredr_state.bonded = false;
|
|
+ else
|
|
+ device->le_state.bonded = false;
|
|
+
|
|
+ if (!device->bredr_state.bonded && !device->le_state.bonded)
|
|
+ btd_device_set_temporary(device, true);
|
|
+ */
|
|
}
|
|
|
|
static void clear_devices_complete(uint8_t status, uint16_t length,
|
|
@@ -10223,7 +10283,7 @@ static void read_info_complete(uint8_t status, uint16_t length,
|
|
set_mode(adapter, MGMT_OP_SET_LE, 0x01);
|
|
if (missing_settings & MGMT_SETTING_BREDR)
|
|
set_mode(adapter, MGMT_OP_SET_BREDR, 0x01);
|
|
- if (missing_settings & MGMT_SETTING_SSP)
|
|
+ if (missing_settings & MGMT_SETTING_SSP && btd_opts.ssp)
|
|
set_mode(adapter, MGMT_OP_SET_SSP, 0x01);
|
|
break;
|
|
case BT_MODE_BREDR:
|
|
@@ -10235,7 +10295,7 @@ static void read_info_complete(uint8_t status, uint16_t length,
|
|
|
|
if (missing_settings & MGMT_SETTING_BREDR)
|
|
set_mode(adapter, MGMT_OP_SET_BREDR, 0x01);
|
|
- if (missing_settings & MGMT_SETTING_SSP)
|
|
+ if (missing_settings & MGMT_SETTING_SSP && btd_opts.ssp)
|
|
set_mode(adapter, MGMT_OP_SET_SSP, 0x01);
|
|
if (adapter->current_settings & MGMT_SETTING_LE)
|
|
set_mode(adapter, MGMT_OP_SET_LE, 0x00);
|
|
@@ -10254,6 +10314,11 @@ static void read_info_complete(uint8_t status, uint16_t length,
|
|
break;
|
|
}
|
|
|
|
+ if (btd_opts.ssp == false) {
|
|
+ error("Disable SSP");
|
|
+ set_mode(adapter, MGMT_OP_SET_SSP, 0x00);
|
|
+ }
|
|
+
|
|
if (missing_settings & MGMT_SETTING_SECURE_CONN)
|
|
set_mode(adapter, MGMT_OP_SET_SECURE_CONN,
|
|
btd_opts.secure_conn);
|
|
@@ -10749,6 +10814,7 @@ static void read_version_complete(uint8_t status, uint16_t length,
|
|
static void mgmt_debug(const char *str, void *user_data)
|
|
{
|
|
DBG_IDX(0xffff, "%s", str);
|
|
+ //error("%s", str);
|
|
}
|
|
|
|
int adapter_init(void)
|
|
diff --git a/src/advertising.c b/src/advertising.c
|
|
index bd121e525..28b04e89c 100644
|
|
--- a/src/advertising.c
|
|
+++ b/src/advertising.c
|
|
@@ -760,7 +760,7 @@ static bool parse_discoverable(DBusMessageIter *iter,
|
|
dbus_message_iter_get_basic(iter, &discoverable);
|
|
|
|
if (discoverable)
|
|
- flags = BT_AD_FLAG_GENERAL;
|
|
+ flags = BT_AD_FLAG_GENERAL | BT_AD_FLAG_NO_BREDR;
|
|
else
|
|
flags = 0x00;
|
|
|
|
diff --git a/src/agent.c b/src/agent.c
|
|
index 7d66cf50d..982f3d005 100644
|
|
--- a/src/agent.c
|
|
+++ b/src/agent.c
|
|
@@ -515,6 +515,7 @@ static int pincode_request_new(struct agent_request *req, dbus_bool_t secure)
|
|
{
|
|
struct agent *agent = req->agent;
|
|
const char *path;
|
|
+ error("");
|
|
|
|
/* TODO: Add a new method or a new param to Agent interface to request
|
|
secure pin. */
|
|
diff --git a/src/bluetooth.conf b/src/bluetooth.conf
|
|
index b6c614908..aba15ecb1 100644
|
|
--- a/src/bluetooth.conf
|
|
+++ b/src/bluetooth.conf
|
|
@@ -9,9 +9,12 @@
|
|
|
|
<policy user="root">
|
|
<allow own="org.bluez"/>
|
|
+ <allow own="org.bluez.obex"/>
|
|
<allow send_destination="org.bluez"/>
|
|
+ <allow send_destination="org.bluez.obex"/>
|
|
<allow send_interface="org.bluez.AdvertisementMonitor1"/>
|
|
<allow send_interface="org.bluez.Agent1"/>
|
|
+ <allow send_interface="org.bluez.obex"/>
|
|
<allow send_interface="org.bluez.MediaEndpoint1"/>
|
|
<allow send_interface="org.bluez.MediaPlayer1"/>
|
|
<allow send_interface="org.bluez.Profile1"/>
|
|
diff --git a/src/btd.h b/src/btd.h
|
|
index 383bd7c19..863c11240 100644
|
|
--- a/src/btd.h
|
|
+++ b/src/btd.h
|
|
@@ -153,6 +153,9 @@ struct btd_opts {
|
|
struct btd_advmon_opts advmon;
|
|
|
|
struct btd_csis csis;
|
|
+
|
|
+ char ble_name[32];
|
|
+ bool ssp;
|
|
};
|
|
|
|
extern struct btd_opts btd_opts;
|
|
diff --git a/src/device.c b/src/device.c
|
|
index 097b1fbba..2935fa553 100644
|
|
--- a/src/device.c
|
|
+++ b/src/device.c
|
|
@@ -290,6 +290,9 @@ struct btd_device {
|
|
time_t name_resolve_failed_time;
|
|
|
|
int8_t volume;
|
|
+ uint16_t reason;
|
|
+ uint8_t update_addrtype;
|
|
+ bool duplicate;
|
|
};
|
|
|
|
static const uint16_t uuid_list[] = {
|
|
@@ -301,6 +304,7 @@ static const uint16_t uuid_list[] = {
|
|
|
|
static int device_browse_gatt(struct btd_device *device, DBusMessage *msg);
|
|
static int device_browse_sdp(struct btd_device *device, DBusMessage *msg);
|
|
+static void gatt_client_init(struct btd_device *device);
|
|
|
|
static struct bearer_state *get_state(struct btd_device *dev,
|
|
uint8_t bdaddr_type)
|
|
@@ -718,6 +722,8 @@ static void gatt_cache_cleanup(struct btd_device *device)
|
|
|
|
static void gatt_client_cleanup(struct btd_device *device)
|
|
{
|
|
+ DBG("");
|
|
+
|
|
if (!device->client)
|
|
return;
|
|
|
|
@@ -736,6 +742,7 @@ static void gatt_client_cleanup(struct btd_device *device)
|
|
|
|
static void gatt_server_cleanup(struct btd_device *device)
|
|
{
|
|
+ DBG("");
|
|
if (!device->server)
|
|
return;
|
|
|
|
@@ -748,6 +755,7 @@ static void gatt_server_cleanup(struct btd_device *device)
|
|
|
|
static void attio_cleanup(struct btd_device *device)
|
|
{
|
|
+ DBG("");
|
|
if (device->att_disconn_id)
|
|
bt_att_unregister_disconnect(device->att,
|
|
device->att_disconn_id);
|
|
@@ -1015,6 +1023,41 @@ static gboolean dev_property_get_class(const GDBusPropertyTable *property,
|
|
return TRUE;
|
|
}
|
|
|
|
+static gboolean dev_property_get_info(const GDBusPropertyTable *property,
|
|
+ DBusMessageIter *iter, void *data)
|
|
+{
|
|
+ struct btd_device *dev = data;
|
|
+ dbus_int16_t val = 0;
|
|
+
|
|
+ if (dev->bredr_state.paired)
|
|
+ val |= (1 << 0);
|
|
+ if (dev->bredr_state.connected)
|
|
+ val |= (1 << 1);
|
|
+ if (dev->bredr_state.bonded)
|
|
+ val |= (1 << 2);
|
|
+ if (dev->bredr_state.svc_resolved)
|
|
+ val |= (1 << 3);
|
|
+
|
|
+ if (dev->le_state.paired)
|
|
+ val |= (1 << 8);
|
|
+ if (dev->le_state.connected)
|
|
+ val |= (1 << 9);
|
|
+ if (dev->le_state.bonded)
|
|
+ val |= (1 << 10);
|
|
+ if (dev->le_state.svc_resolved)
|
|
+ val |= (1 << 11);
|
|
+
|
|
+ if (dev->update_addrtype)
|
|
+ val |= (1 << 15);
|
|
+ if (dev->duplicate)
|
|
+ val |= (1 << 14);
|
|
+
|
|
+ DBG("val: 0x%x", val);
|
|
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_INT16, &val);
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
static gboolean get_appearance(const GDBusPropertyTable *property, void *data,
|
|
uint16_t *appearance)
|
|
{
|
|
@@ -1138,6 +1181,28 @@ static gboolean dev_property_get_rssi(const GDBusPropertyTable *property,
|
|
return TRUE;
|
|
}
|
|
|
|
+static gboolean dev_property_get_reason(const GDBusPropertyTable *property,
|
|
+ DBusMessageIter *iter, void *data)
|
|
+{
|
|
+ struct btd_device *dev = data;
|
|
+ dbus_int16_t val = dev->reason;
|
|
+
|
|
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_INT16, &val);
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static gboolean dev_property_get_mtu(const GDBusPropertyTable *property,
|
|
+ DBusMessageIter *iter, void *data)
|
|
+{
|
|
+ struct btd_device *dev = data;
|
|
+ dbus_int16_t val = dev->att_mtu;
|
|
+
|
|
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_INT16, &val);
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
static gboolean dev_property_exists_rssi(const GDBusPropertyTable *property,
|
|
void *data)
|
|
{
|
|
@@ -1717,9 +1782,38 @@ static gboolean dev_property_set_exists(const GDBusPropertyTable *property,
|
|
return !queue_isempty(device->sirks);
|
|
}
|
|
|
|
+static bool disconnect_bredr(gpointer user_data)
|
|
+{
|
|
+ struct btd_device *device = user_data;
|
|
+ DBG("");
|
|
+
|
|
+ device->disconn_timer = 0;
|
|
+
|
|
+ if (device->bredr_state.connected)
|
|
+ btd_adapter_disconnect_device(device->adapter, &device->bdaddr,
|
|
+ BDADDR_BREDR);
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+static bool disconnect_ble(gpointer user_data)
|
|
+{
|
|
+ struct btd_device *device = user_data;
|
|
+ DBG("");
|
|
+
|
|
+ device->disconn_timer = 0;
|
|
+
|
|
+ if (device->le_state.connected)
|
|
+ btd_adapter_disconnect_device(device->adapter, &device->bdaddr,
|
|
+ device->bdaddr_type);
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
static bool disconnect_all(gpointer user_data)
|
|
{
|
|
struct btd_device *device = user_data;
|
|
+ DBG("");
|
|
|
|
device->disconn_timer = 0;
|
|
|
|
@@ -2092,10 +2186,102 @@ static void device_set_auto_connect(struct btd_device *device, gboolean enable)
|
|
adapter_connect_list_add(device->adapter, device);
|
|
}
|
|
|
|
+static void device_request_disconnect_by_type(struct btd_device *device, DBusMessage *msg,
|
|
+ uint8_t bdaddr_type)
|
|
+{
|
|
+ DBG("addr_type %d, %p|%p|%p|%p", bdaddr_type,
|
|
+ device->bonding, device->browse, device->connect, device->watches);
|
|
+
|
|
+ if (device->bonding)
|
|
+ bonding_request_cancel(device->bonding);
|
|
+
|
|
+ if (device->browse)
|
|
+ browse_request_cancel(device->browse);
|
|
+
|
|
+ if (bdaddr_type && device->att_io) {
|
|
+ g_io_channel_shutdown(device->att_io, FALSE, NULL);
|
|
+ g_io_channel_unref(device->att_io);
|
|
+ device->att_io = NULL;
|
|
+ }
|
|
+
|
|
+ if (device->connect) {
|
|
+ DBusMessage *reply = btd_error_failed(device->connect,
|
|
+ ERR_BREDR_CONN_CANCELED);
|
|
+ g_dbus_send_message(dbus_conn, reply);
|
|
+ dbus_message_unref(device->connect);
|
|
+ device->connect = NULL;
|
|
+ }
|
|
+
|
|
+ //device->bredr_state.connected || device->le_state.connected;
|
|
+ if (btd_device_is_connected(device) && msg)
|
|
+ device->disconnects = g_slist_append(device->disconnects,
|
|
+ dbus_message_ref(msg));
|
|
+
|
|
+ if (device->disconn_timer) {
|
|
+ if (msg) {
|
|
+ //g_dbus_send_reply(dbus_conn, msg, DBUS_TYPE_INVALID);
|
|
+ g_dbus_send_error(dbus_conn, msg, "org.bluez.Disconneting", NULL);
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (bdaddr_type == BDADDR_BREDR)
|
|
+ g_slist_foreach(device->services, dev_disconn_service, NULL);
|
|
+
|
|
+ g_slist_free(device->pending);
|
|
+ device->pending = NULL;
|
|
+
|
|
+ while (device->watches) {
|
|
+ struct btd_disconnect_data *data = device->watches->data;
|
|
+
|
|
+ if (data->watch)
|
|
+ /* temporary is set if device is going to be removed */
|
|
+ data->watch(device, device->temporary,
|
|
+ data->user_data);
|
|
+
|
|
+ /* Check if the watch has been removed by callback function */
|
|
+ if (!g_slist_find(device->watches, data))
|
|
+ continue;
|
|
+
|
|
+ device->watches = g_slist_remove(device->watches, data);
|
|
+ g_free(data);
|
|
+ }
|
|
+
|
|
+ if ((bdaddr_type && !device->le_state.connected) ||
|
|
+ (!bdaddr_type && !device->bredr_state.connected)) {
|
|
+ if (msg) {
|
|
+ g_dbus_send_reply(dbus_conn, msg, DBUS_TYPE_INVALID);
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ device->disconn_timer = timeout_add_seconds(DISCONNECT_TIMER,
|
|
+ bdaddr_type ? disconnect_ble : disconnect_bredr,
|
|
+ device, NULL);
|
|
+}
|
|
+
|
|
static DBusMessage *dev_disconnect(DBusConnection *conn, DBusMessage *msg,
|
|
void *user_data)
|
|
{
|
|
struct btd_device *device = user_data;
|
|
+ char *addr_type;
|
|
+ uint8_t bdaddr_type = BDADDR_BREDR;
|
|
+
|
|
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr_type,
|
|
+ DBUS_TYPE_INVALID)) {
|
|
+ return btd_error_invalid_args_str(msg,
|
|
+ ERR_BREDR_CONN_INVALID_ARGUMENTS);
|
|
+ }
|
|
+
|
|
+ DBG("addr_type %s", addr_type);
|
|
+ if (!strcmp(addr_type, "bredr"))
|
|
+ bdaddr_type = BDADDR_BREDR;
|
|
+ else if (!strcmp(addr_type, "public"))
|
|
+ bdaddr_type = BDADDR_LE_PUBLIC;
|
|
+ else if (!strcmp(addr_type, "random"))
|
|
+ bdaddr_type = BDADDR_LE_RANDOM;
|
|
+ else if (!strcmp(addr_type, "auto"))
|
|
+ bdaddr_type = bdaddr_type;
|
|
|
|
/*
|
|
* If device is not trusted disable connections through passive
|
|
@@ -2106,6 +2292,11 @@ static DBusMessage *dev_disconnect(DBusConnection *conn, DBusMessage *msg,
|
|
device_set_auto_connect(device, FALSE);
|
|
}
|
|
|
|
+ if (strcmp(addr_type, "auto")) {
|
|
+ device_request_disconnect_by_type(device, msg, bdaddr_type);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
device_request_disconnect(device, msg);
|
|
|
|
return NULL;
|
|
@@ -2135,7 +2326,9 @@ static void device_profile_connected(struct btd_device *dev,
|
|
struct btd_service *pending;
|
|
GSList *l;
|
|
|
|
- DBG("%s %s (%d)", profile->name, strerror(-err), -err);
|
|
+ DBG("%s %s (%d) state(%d|%d)", profile->name, strerror(-err), -err,
|
|
+ dev->bredr_state.connected,
|
|
+ dev->le_state.connected);
|
|
|
|
if (!err)
|
|
btd_device_set_temporary(dev, false);
|
|
@@ -2152,6 +2345,10 @@ static void device_profile_connected(struct btd_device *dev,
|
|
}
|
|
}
|
|
|
|
+ if (err == -ECONNREFUSED || err == -EACCES) {
|
|
+ DBG("Due to EACCES abort connection");
|
|
+ goto done;
|
|
+ }
|
|
|
|
pending = dev->pending->data;
|
|
l = find_service_with_profile(dev->pending, profile);
|
|
@@ -2188,13 +2385,13 @@ done:
|
|
DBG("returning response to %s", dbus_message_get_sender(dev->connect));
|
|
|
|
if (err) {
|
|
- /* Fallback to LE bearer if supported */
|
|
+ /* Fallback to LE bearer if supported
|
|
if (err == -EHOSTDOWN && dev->le && !dev->le_state.connected) {
|
|
err = device_connect_le(dev);
|
|
if (err == 0)
|
|
return;
|
|
}
|
|
-
|
|
+ */
|
|
g_dbus_send_message(dbus_conn,
|
|
btd_error_failed(dev->connect,
|
|
btd_error_bredr_conn_from_errno(err)));
|
|
@@ -2410,6 +2607,7 @@ static GSList *create_pending_list(struct btd_device *dev, const char *uuid)
|
|
info("service %s is blocked", p->remote_uuid);
|
|
continue;
|
|
}
|
|
+ DBG("create uuid pending: %s|%s|%s", p->name, p->remote_uuid, p->local_uuid);
|
|
|
|
if (g_slist_find(dev->pending, service))
|
|
continue;
|
|
@@ -2457,8 +2655,8 @@ static DBusMessage *connect_profiles(struct btd_device *dev, uint8_t bdaddr_type
|
|
struct bearer_state *state = get_state(dev, bdaddr_type);
|
|
int err;
|
|
|
|
- DBG("%s %s, client %s", dev->path, uuid ? uuid : "(all)",
|
|
- dbus_message_get_sender(msg));
|
|
+ DBG("%s %s, client %s, svc: %d", dev->path, uuid ? uuid : "(all)",
|
|
+ dbus_message_get_sender(msg), state->svc_resolved);
|
|
|
|
if (dev->pending || dev->connect || dev->browse)
|
|
return btd_error_in_progress_str(msg, ERR_BREDR_CONN_BUSY);
|
|
@@ -2571,6 +2769,15 @@ static DBusMessage *dev_connect(DBusConnection *conn, DBusMessage *msg,
|
|
{
|
|
struct btd_device *dev = user_data;
|
|
uint8_t bdaddr_type;
|
|
+ char *addr_type;
|
|
+
|
|
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr_type,
|
|
+ DBUS_TYPE_INVALID)) {
|
|
+ return btd_error_invalid_args_str(msg,
|
|
+ ERR_BREDR_CONN_INVALID_ARGUMENTS);
|
|
+ }
|
|
+
|
|
+ DBG("addr_type %s", addr_type);
|
|
|
|
if (dev->bredr_state.connected) {
|
|
/*
|
|
@@ -2588,6 +2795,15 @@ static DBusMessage *dev_connect(DBusConnection *conn, DBusMessage *msg,
|
|
else
|
|
bdaddr_type = select_conn_bearer(dev);
|
|
|
|
+ if (!strcmp(addr_type, "bredr"))
|
|
+ bdaddr_type = BDADDR_BREDR;
|
|
+ else if (!strcmp(addr_type, "public"))
|
|
+ bdaddr_type = BDADDR_LE_PUBLIC;
|
|
+ else if (!strcmp(addr_type, "random"))
|
|
+ bdaddr_type = BDADDR_LE_RANDOM;
|
|
+ else if (!strcmp(addr_type, "auto"))
|
|
+ bdaddr_type = bdaddr_type;
|
|
+
|
|
if (bdaddr_type != BDADDR_BREDR) {
|
|
int err;
|
|
|
|
@@ -2805,6 +3021,7 @@ static void browse_request_complete(struct browse_req *req, uint8_t type,
|
|
struct btd_device *dev = req->device;
|
|
DBusMessage *reply = NULL;
|
|
DBusMessage *msg;
|
|
+ DBG("");
|
|
|
|
if (req->type != type)
|
|
return;
|
|
@@ -2819,6 +3036,10 @@ static void browse_request_complete(struct browse_req *req, uint8_t type,
|
|
}
|
|
|
|
if (dev->pending_paired) {
|
|
+ dev->update_addrtype = bdaddr_type;
|
|
+ g_dbus_emit_property_changed(dbus_conn, dev->path,
|
|
+ DEVICE_INTERFACE,
|
|
+ "INFO");
|
|
g_dbus_emit_property_changed(dbus_conn, dev->path,
|
|
DEVICE_INTERFACE, "Paired");
|
|
dev->pending_paired = false;
|
|
@@ -2830,13 +3051,16 @@ static void browse_request_complete(struct browse_req *req, uint8_t type,
|
|
}
|
|
|
|
if (err) {
|
|
- /* Fallback to LE bearer if supported */
|
|
+ /* Fallback to LE bearer if supported
|
|
if (err == -EHOSTDOWN && bdaddr_type == BDADDR_BREDR &&
|
|
dev->le && !dev->le_state.connected) {
|
|
err = device_connect_le(dev);
|
|
if (err == 0)
|
|
goto done;
|
|
- }
|
|
+ }*/
|
|
+ DBG("sending back error reason: %s", bdaddr_type == BDADDR_BREDR ?
|
|
+ btd_error_bredr_conn_from_errno(err) :
|
|
+ btd_error_le_conn_from_errno(err));
|
|
reply = btd_error_failed(req->msg,
|
|
bdaddr_type == BDADDR_BREDR ?
|
|
btd_error_bredr_conn_from_errno(err) :
|
|
@@ -2876,6 +3100,11 @@ void device_set_refresh_discovery(struct btd_device *dev, bool refresh)
|
|
dev->refresh_discovery = refresh;
|
|
}
|
|
|
|
+bool device_get_svc_refreshed(struct btd_device *device)
|
|
+{
|
|
+ return device->svc_refreshed;
|
|
+}
|
|
+
|
|
static void device_set_svc_refreshed(struct btd_device *device, bool value)
|
|
{
|
|
if (device->svc_refreshed == value)
|
|
@@ -2908,6 +3137,10 @@ static void device_svc_resolved(struct btd_device *dev, uint8_t browse_type,
|
|
dev->eir_uuids = NULL;
|
|
|
|
if (dev->pending_paired) {
|
|
+ dev->update_addrtype = bdaddr_type;
|
|
+ g_dbus_emit_property_changed(dbus_conn, dev->path,
|
|
+ DEVICE_INTERFACE,
|
|
+ "INFO");
|
|
g_dbus_emit_property_changed(dbus_conn, dev->path,
|
|
DEVICE_INTERFACE, "Paired");
|
|
dev->pending_paired = false;
|
|
@@ -3195,13 +3428,28 @@ static DBusMessage *cancel_pairing(DBusConnection *conn, DBusMessage *msg,
|
|
{
|
|
struct btd_device *device = data;
|
|
struct bonding_req *req = device->bonding;
|
|
+ char *addr_type;
|
|
|
|
- DBG("");
|
|
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr_type,
|
|
+ DBUS_TYPE_INVALID)) {
|
|
+ return btd_error_invalid_args_str(msg,
|
|
+ ERR_BREDR_CONN_INVALID_ARGUMENTS);
|
|
+ }
|
|
+
|
|
+ DBG("req: %p, type: %s", req, addr_type);
|
|
|
|
if (!req) {
|
|
- btd_adapter_remove_bonding(device->adapter, &device->bdaddr,
|
|
+ if (!strcmp(addr_type, "bredr"))
|
|
+ btd_adapter_remove_bonding(device->adapter, &device->bdaddr,
|
|
+ 0);
|
|
+ else if (!strcmp(addr_type, "public"))
|
|
+ btd_adapter_remove_bonding(device->adapter, &device->bdaddr,
|
|
+ 1);
|
|
+ else
|
|
+ btd_adapter_remove_bonding(device->adapter, &device->bdaddr,
|
|
device->bdaddr_type);
|
|
- return btd_error_does_not_exist(msg);
|
|
+ return dbus_message_new_method_return(msg);
|
|
+ //return btd_error_does_not_exist(msg);
|
|
}
|
|
|
|
device_cancel_bonding(device, MGMT_STATUS_CANCELLED);
|
|
@@ -3210,14 +3458,14 @@ static DBusMessage *cancel_pairing(DBusConnection *conn, DBusMessage *msg,
|
|
}
|
|
|
|
static const GDBusMethodTable device_methods[] = {
|
|
- { GDBUS_ASYNC_METHOD("Disconnect", NULL, NULL, dev_disconnect) },
|
|
- { GDBUS_ASYNC_METHOD("Connect", NULL, NULL, dev_connect) },
|
|
+ { GDBUS_ASYNC_METHOD("Disconnect", GDBUS_ARGS({ "ADDR_TYPE", "s" }), NULL, dev_disconnect) },
|
|
+ { GDBUS_ASYNC_METHOD("Connect", GDBUS_ARGS({ "ADDR_TYPE", "s" }), NULL, dev_connect) },
|
|
{ GDBUS_ASYNC_METHOD("ConnectProfile", GDBUS_ARGS({ "UUID", "s" }),
|
|
NULL, connect_profile) },
|
|
{ GDBUS_ASYNC_METHOD("DisconnectProfile", GDBUS_ARGS({ "UUID", "s" }),
|
|
NULL, disconnect_profile) },
|
|
{ GDBUS_ASYNC_METHOD("Pair", NULL, NULL, pair_device) },
|
|
- { GDBUS_METHOD("CancelPairing", NULL, NULL, cancel_pairing) },
|
|
+ { GDBUS_METHOD("CancelPairing", GDBUS_ARGS({ "ADDR_TYPE", "s" }), NULL, cancel_pairing) },
|
|
{ }
|
|
};
|
|
|
|
@@ -3238,6 +3486,9 @@ static const GDBusPropertyTable device_properties[] = {
|
|
{ "Blocked", "b", dev_property_get_blocked, dev_property_set_blocked },
|
|
{ "LegacyPairing", "b", dev_property_get_legacy },
|
|
{ "RSSI", "n", dev_property_get_rssi, NULL, dev_property_exists_rssi },
|
|
+ { "MTU", "n", dev_property_get_mtu, NULL, NULL },
|
|
+ { "Reason", "n", dev_property_get_reason, NULL, NULL },
|
|
+ { "INFO", "n", dev_property_get_info, NULL, NULL },
|
|
{ "Connected", "b", dev_property_get_connected },
|
|
{ "UUIDs", "as", dev_property_get_uuids },
|
|
{ "Modalias", "s", dev_property_get_modalias, NULL,
|
|
@@ -3295,6 +3546,7 @@ void device_add_connection(struct btd_device *dev, uint8_t bdaddr_type,
|
|
uint32_t flags)
|
|
{
|
|
struct bearer_state *state = get_state(dev, bdaddr_type);
|
|
+ char str[18];
|
|
|
|
device_update_last_seen(dev, bdaddr_type, true);
|
|
|
|
@@ -3308,6 +3560,9 @@ void device_add_connection(struct btd_device *dev, uint8_t bdaddr_type,
|
|
bacpy(&dev->conn_bdaddr, &dev->bdaddr);
|
|
dev->conn_bdaddr_type = dev->bdaddr_type;
|
|
|
|
+ ba2str(&dev->bdaddr, str);
|
|
+ DBG("conn addr: %s, type: %d", str, dev->bdaddr_type);
|
|
+
|
|
/* If this is the first connection over this bearer */
|
|
if (bdaddr_type == BDADDR_BREDR)
|
|
device_set_bredr_support(dev);
|
|
@@ -3316,15 +3571,19 @@ void device_add_connection(struct btd_device *dev, uint8_t bdaddr_type,
|
|
|
|
state->connected = true;
|
|
state->initiator = flags & BIT(3);
|
|
+ dev->update_addrtype = bdaddr_type;
|
|
+
|
|
+ g_dbus_emit_property_changed(dbus_conn, dev->path,
|
|
+ DEVICE_INTERFACE,
|
|
+ "INFO");
|
|
+ g_dbus_emit_property_changed(dbus_conn, dev->path, DEVICE_INTERFACE,
|
|
+ "Connected");
|
|
|
|
if (dev->le_state.connected && dev->bredr_state.connected)
|
|
return;
|
|
|
|
/* Remove temporary timer while connected */
|
|
clear_temporary_timer(dev);
|
|
-
|
|
- g_dbus_emit_property_changed(dbus_conn, dev->path, DEVICE_INTERFACE,
|
|
- "Connected");
|
|
}
|
|
|
|
static bool device_service_connected(struct btd_device *dev)
|
|
@@ -3340,6 +3599,7 @@ static bool device_service_connected(struct btd_device *dev)
|
|
static bool device_disappeared(gpointer user_data)
|
|
{
|
|
struct btd_device *dev = user_data;
|
|
+ DBG("alias: %s, %d|%d|%d", dev->alias, dev->bredr, dev->le, device_service_connected(dev));
|
|
|
|
/* If there are services connected restart the timer to give more time
|
|
* for the service to either complete the connection or disconnect.
|
|
@@ -3357,6 +3617,7 @@ static bool device_disappeared(gpointer user_data)
|
|
static void set_temporary_timer(struct btd_device *dev, unsigned int timeout)
|
|
{
|
|
clear_temporary_timer(dev);
|
|
+ DBG("timeout: %d", timeout);
|
|
|
|
if (!timeout)
|
|
return;
|
|
@@ -3373,12 +3634,18 @@ void device_remove_connection(struct btd_device *device, uint8_t bdaddr_type,
|
|
bool remove_device = false;
|
|
bool paired_status_updated = false;
|
|
|
|
+ DBG("con/dis msg: %p|%p %d|%d|%d|%d", device->connect, device->disconnects, bdaddr_type,
|
|
+ device->bredr_state.connected,
|
|
+ device->le_state.connected,
|
|
+ device_is_temporary(device));
|
|
+
|
|
if (!state->connected)
|
|
return;
|
|
|
|
state->connected = false;
|
|
state->initiator = false;
|
|
device->general_connect = FALSE;
|
|
+ device->update_addrtype = bdaddr_type;
|
|
|
|
device_set_svc_refreshed(device, false);
|
|
|
|
@@ -3433,24 +3700,33 @@ void device_remove_connection(struct btd_device *device, uint8_t bdaddr_type,
|
|
paired_status_updated = true;
|
|
}
|
|
|
|
- /* report change only if both bearers are unpaired */
|
|
- if (!device->bredr_state.paired && !device->le_state.paired &&
|
|
- paired_status_updated)
|
|
+ g_dbus_emit_property_changed(dbus_conn, device->path,
|
|
+ DEVICE_INTERFACE,
|
|
+ "INFO");
|
|
+
|
|
+ /* report change only if any bearers are unpaired */
|
|
+ if (paired_status_updated)
|
|
g_dbus_emit_property_changed(dbus_conn, device->path,
|
|
DEVICE_INTERFACE,
|
|
"Paired");
|
|
|
|
+ g_dbus_emit_property_changed(dbus_conn, device->path,
|
|
+ DEVICE_INTERFACE, "Connected");
|
|
+
|
|
if (device->bredr_state.connected || device->le_state.connected)
|
|
return;
|
|
|
|
- device_update_last_seen(device, bdaddr_type, true);
|
|
+ //device_update_last_seen(device, bdaddr_type, true);
|
|
+ state->last_seen = time(NULL);
|
|
+ state->connectable = true;
|
|
+ if (device_is_temporary(device)) {
|
|
+ /* Restart temporary timer */
|
|
+ set_temporary_timer(device, 1);
|
|
+ }
|
|
|
|
g_slist_free_full(device->eir_uuids, g_free);
|
|
device->eir_uuids = NULL;
|
|
|
|
- g_dbus_emit_property_changed(dbus_conn, device->path,
|
|
- DEVICE_INTERFACE, "Connected");
|
|
-
|
|
if (remove_device)
|
|
*remove = remove_device;
|
|
}
|
|
@@ -4255,7 +4531,7 @@ static struct btd_device *device_new(struct btd_adapter *adapter,
|
|
return NULL;
|
|
|
|
device->tx_power = 127;
|
|
- device->volume = -1;
|
|
+ device->volume = 0x7f;
|
|
|
|
device->db = gatt_db_new();
|
|
if (!device->db) {
|
|
@@ -4340,7 +4616,7 @@ struct btd_device *device_create(struct btd_adapter *adapter,
|
|
const char *storage_dir;
|
|
|
|
ba2str(bdaddr, dst);
|
|
- DBG("dst %s", dst);
|
|
+ DBG("dst %s, type: %d", dst, bdaddr_type);
|
|
|
|
device = device_new(adapter, dst);
|
|
if (device == NULL)
|
|
@@ -4482,6 +4758,11 @@ void device_set_class(struct btd_device *device, uint32_t class)
|
|
DEVICE_INTERFACE, "Icon");
|
|
}
|
|
|
|
+void device_copy_addr(struct btd_device *device, const bdaddr_t *bdaddr)
|
|
+{
|
|
+ bacpy(&device->bdaddr, bdaddr);
|
|
+}
|
|
+
|
|
void device_set_rpa(struct btd_device *device, bool value)
|
|
{
|
|
device->rpa = value;
|
|
@@ -4537,9 +4818,13 @@ void device_set_bredr_support(struct btd_device *device)
|
|
|
|
void device_set_le_support(struct btd_device *device, uint8_t bdaddr_type)
|
|
{
|
|
+ char str[18];
|
|
+
|
|
if (btd_opts.mode == BT_MODE_BREDR || device->le)
|
|
return;
|
|
|
|
+ ba2str(&device->bdaddr, str);
|
|
+ DBG("addr %s, type: %d", str, bdaddr_type);
|
|
device->le = true;
|
|
device->bdaddr_type = bdaddr_type;
|
|
|
|
@@ -4604,6 +4889,9 @@ void device_merge_duplicate(struct btd_device *dev, struct btd_device *dup)
|
|
dev->vendor = dup->vendor;
|
|
dev->product = dup->product;
|
|
dev->version = dup->version;
|
|
+ dev->duplicate = true;
|
|
+ g_dbus_emit_property_changed(dbus_conn, dev->path,
|
|
+ DEVICE_INTERFACE, "INFO");
|
|
}
|
|
|
|
uint32_t btd_device_get_class(struct btd_device *device)
|
|
@@ -4733,7 +5021,7 @@ static void device_remove_stored(struct btd_device *device)
|
|
|
|
void device_remove(struct btd_device *device, gboolean remove_stored)
|
|
{
|
|
- DBG("Removing device %s", device->path);
|
|
+ DBG("Removing device %s|%d", device->path, remove_stored);
|
|
|
|
if (device->auto_connect) {
|
|
device->disable_auto_connect = TRUE;
|
|
@@ -4817,8 +5105,19 @@ int device_addr_type_cmp(gconstpointer a, gconstpointer b)
|
|
const struct btd_device *dev = a;
|
|
const struct device_addr_type *addr = b;
|
|
int cmp;
|
|
+ char str0[18];
|
|
+ char str1[18];
|
|
+ char str2[18];
|
|
+
|
|
+ ba2str(&dev->bdaddr, str0);
|
|
+ ba2str(&addr->bdaddr, str1);
|
|
+ ba2str(&dev->conn_bdaddr, str2);
|
|
|
|
cmp = bacmp(&dev->bdaddr, &addr->bdaddr);
|
|
+ DBG("addr: %s|%s|%s, type: %d|%d|%d, bear: %d|%d",
|
|
+ str0, str1, str2,
|
|
+ dev->bdaddr_type, addr->bdaddr_type, dev->conn_bdaddr_type,
|
|
+ dev->le, dev->bredr);
|
|
|
|
/*
|
|
* Address matches and both old and new are public addresses
|
|
@@ -5350,7 +5649,7 @@ send_reply:
|
|
* reply to D-Bus method call.
|
|
*/
|
|
if (err < 0 && device->connect) {
|
|
- DBG("SDP failed during connection");
|
|
+ error("SDP failed during connection and reply to D-Bus method call");
|
|
reply = btd_error_failed(device->connect, strerror(-err));
|
|
g_dbus_send_message(dbus_conn, reply);
|
|
dbus_message_unref(device->connect);
|
|
@@ -5438,8 +5737,9 @@ static void att_disconnected_cb(int err, void *user_data)
|
|
* is connection timeout, remote user terminated connection or local
|
|
* initiated disconnection.
|
|
*/
|
|
- if (err == ETIMEDOUT || err == ECONNRESET || err == ECONNABORTED)
|
|
- adapter_connect_list_add(device->adapter, device);
|
|
+ //ble peripheral no need
|
|
+ //if (err == ETIMEDOUT || err == ECONNRESET || err == ECONNABORTED)
|
|
+ // adapter_connect_list_add(device->adapter, device);
|
|
|
|
done:
|
|
attio_cleanup(device);
|
|
@@ -5472,8 +5772,6 @@ static void register_gatt_services(struct btd_device *device)
|
|
device_add_gatt_services(device);
|
|
}
|
|
|
|
-static void gatt_client_init(struct btd_device *device);
|
|
-
|
|
static void gatt_client_ready_cb(bool success, uint8_t att_ecode,
|
|
void *user_data)
|
|
{
|
|
@@ -5506,6 +5804,7 @@ static void gatt_client_service_changed(uint16_t start_handle,
|
|
static void gatt_debug(const char *str, void *user_data)
|
|
{
|
|
DBG_IDX(0xffff, "%s", str);
|
|
+ //error("%s", str);
|
|
}
|
|
|
|
static void gatt_client_init(struct btd_device *device)
|
|
@@ -5620,6 +5919,16 @@ static bool remote_counter(uint32_t *sign_cnt, void *user_data)
|
|
return true;
|
|
}
|
|
|
|
+static void att_exchange(uint16_t mtu, void *user_data)
|
|
+{
|
|
+ struct btd_device *dev = user_data;
|
|
+
|
|
+ dev->att_mtu = mtu;
|
|
+ DBG("chrc->path %s, mtu: %d", dev->path, mtu);
|
|
+ g_dbus_emit_property_changed(dbus_conn, dev->path,
|
|
+ DEVICE_INTERFACE, "MTU");
|
|
+}
|
|
+
|
|
bool device_attach_att(struct btd_device *dev, GIOChannel *io)
|
|
{
|
|
GError *gerr = NULL;
|
|
@@ -5630,6 +5939,7 @@ bool device_attach_att(struct btd_device *dev, GIOChannel *io)
|
|
struct btd_gatt_database *database;
|
|
const bdaddr_t *dst;
|
|
char dstaddr[18];
|
|
+ int i;
|
|
|
|
bt_io_get(io, &gerr, BT_IO_OPT_SEC_LEVEL, &sec_level,
|
|
BT_IO_OPT_IMTU, &mtu,
|
|
@@ -5658,16 +5968,27 @@ bool device_attach_att(struct btd_device *dev, GIOChannel *io)
|
|
return false;
|
|
}
|
|
|
|
- if (sec_level == BT_IO_SEC_LOW && dev->le_state.paired) {
|
|
- DBG("Elevating security level since LTK is available");
|
|
+ dst = device_get_address(dev);
|
|
+ ba2str(dst, dstaddr);
|
|
+ DBG("dstaddr: %s, state_paired: %d", dstaddr, dev->le_state.paired);
|
|
+ if (0) {//(sec_level == BT_IO_SEC_LOW && dev->le_state.paired) {
|
|
+ error("Elevating security level since LTK is available");
|
|
|
|
sec_level = BT_IO_SEC_MEDIUM;
|
|
- bt_io_set(io, &gerr, BT_IO_OPT_SEC_LEVEL, sec_level,
|
|
- BT_IO_OPT_INVALID);
|
|
- if (gerr) {
|
|
- error("bt_io_set: %s", gerr->message);
|
|
+ for (i = 0; i < 6; i++) {
|
|
+ gerr = NULL;
|
|
+ bt_io_set(io, &gerr, BT_IO_OPT_SEC_LEVEL, sec_level,
|
|
+ BT_IO_OPT_INVALID);
|
|
+ if (!gerr)
|
|
+ break;
|
|
+
|
|
+ if (gerr && (i == 5)) {
|
|
+ error("bt_io_set: %s", gerr->message);
|
|
+ g_error_free(gerr);
|
|
+ return false;
|
|
+ }
|
|
+ error("retry[%d]: bt_io_set: %s", i, gerr->message);
|
|
g_error_free(gerr);
|
|
- return false;
|
|
}
|
|
}
|
|
|
|
@@ -5685,6 +6006,9 @@ bool device_attach_att(struct btd_device *dev, GIOChannel *io)
|
|
|
|
bt_att_ref(dev->att);
|
|
|
|
+ bt_att_register_exchange(dev->att, att_exchange,
|
|
+ dev, NULL);
|
|
+
|
|
bt_att_set_debug(dev->att, BT_ATT_DEBUG, gatt_debug, NULL, NULL);
|
|
|
|
dev->att_disconn_id = bt_att_register_disconnect(dev->att,
|
|
@@ -5708,7 +6032,7 @@ bool device_attach_att(struct btd_device *dev, GIOChannel *io)
|
|
load_gatt_db(dev, btd_adapter_get_storage_dir(dev->adapter),
|
|
dstaddr);
|
|
|
|
- gatt_client_init(dev);
|
|
+ gatt_client_init(dev); //test
|
|
gatt_server_init(dev, database);
|
|
|
|
/*
|
|
@@ -5727,6 +6051,7 @@ static void att_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
|
|
DBusMessage *reply;
|
|
uint8_t io_cap;
|
|
int err = 0;
|
|
+ DBG("");
|
|
|
|
g_io_channel_unref(device->att_io);
|
|
device->att_io = NULL;
|
|
@@ -5755,6 +6080,11 @@ static void att_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
|
|
/* Update connected state */
|
|
device->le_state.connected = true;
|
|
|
|
+ g_dbus_emit_property_changed(dbus_conn, device->path,
|
|
+ DEVICE_INTERFACE, "INFO");
|
|
+ g_dbus_emit_property_changed(dbus_conn, device->path,
|
|
+ DEVICE_INTERFACE, "Connected");
|
|
+
|
|
if (!device_attach_att(device, io))
|
|
goto done;
|
|
|
|
@@ -5861,6 +6191,7 @@ static struct browse_req *browse_request_new(struct btd_device *device,
|
|
DBusMessage *msg)
|
|
{
|
|
struct browse_req *req;
|
|
+ DBG("");
|
|
|
|
if (device->browse)
|
|
return NULL;
|
|
@@ -5892,6 +6223,7 @@ static int device_browse_gatt(struct btd_device *device, DBusMessage *msg)
|
|
{
|
|
struct btd_adapter *adapter = device->adapter;
|
|
struct browse_req *req;
|
|
+ DBG("");
|
|
|
|
req = browse_request_new(device, BROWSE_GATT, msg);
|
|
if (!req)
|
|
@@ -5965,6 +6297,7 @@ static int device_browse_sdp(struct btd_device *device, DBusMessage *msg)
|
|
struct browse_req *req;
|
|
uuid_t uuid;
|
|
int err;
|
|
+ DBG("");
|
|
|
|
req = browse_request_new(device, BROWSE_SDP, msg);
|
|
if (!req)
|
|
@@ -5988,6 +6321,7 @@ static int device_browse_sdp(struct btd_device *device, DBusMessage *msg)
|
|
int device_discover_services(struct btd_device *device)
|
|
{
|
|
int err;
|
|
+ DBG("");
|
|
|
|
if (device->bredr)
|
|
err = device_browse_sdp(device, NULL);
|
|
@@ -6036,6 +6370,7 @@ void btd_device_set_temporary(struct btd_device *device, bool temporary)
|
|
{
|
|
if (!device)
|
|
return;
|
|
+ DBG("temporary %d|%d bear: %d|%d", temporary, device->temporary, device->bredr, device->le);
|
|
|
|
if (device->temporary == temporary)
|
|
return;
|
|
@@ -6108,14 +6443,17 @@ void device_set_bonded(struct btd_device *device, uint8_t bdaddr_type)
|
|
|
|
btd_device_set_temporary(device, false);
|
|
|
|
+ device->update_addrtype = bdaddr_type;
|
|
+ g_dbus_emit_property_changed(dbus_conn, device->path,
|
|
+ DEVICE_INTERFACE, "INFO");
|
|
+ g_dbus_emit_property_changed(dbus_conn, device->path,
|
|
+ DEVICE_INTERFACE, "Bonded");
|
|
+
|
|
/* If the other bearer state was already true we don't need to
|
|
* send any property signals.
|
|
*/
|
|
if (device->bredr_state.bonded == device->le_state.bonded)
|
|
return;
|
|
-
|
|
- g_dbus_emit_property_changed(dbus_conn, device->path,
|
|
- DEVICE_INTERFACE, "Bonded");
|
|
}
|
|
|
|
void device_set_legacy(struct btd_device *device, bool legacy)
|
|
@@ -6270,6 +6608,13 @@ void device_set_rssi(struct btd_device *device, int8_t rssi)
|
|
device_set_rssi_with_delta(device, rssi, RSSI_THRESHOLD);
|
|
}
|
|
|
|
+void device_set_reason(struct btd_device *device, uint8_t bdaddr_type, int16_t reason)
|
|
+{
|
|
+ device->reason = reason << 8 | bdaddr_type;
|
|
+ g_dbus_emit_property_changed(dbus_conn, device->path,
|
|
+ DEVICE_INTERFACE, "Reason");
|
|
+}
|
|
+
|
|
void device_set_tx_power(struct btd_device *device, int8_t tx_power)
|
|
{
|
|
if (!device)
|
|
@@ -6334,23 +6679,29 @@ static bool start_discovery(gpointer user_data)
|
|
void device_set_paired(struct btd_device *dev, uint8_t bdaddr_type)
|
|
{
|
|
struct bearer_state *state = get_state(dev, bdaddr_type);
|
|
+ DBG("bdaddr_type: %d, paired: %d, bonder: %d svc_resolved: %d | path: %s]",
|
|
+ bdaddr_type, state->paired, state->bonded, state->svc_resolved, dev->path);
|
|
|
|
if (state->paired)
|
|
return;
|
|
|
|
state->paired = true;
|
|
+ dev->update_addrtype = bdaddr_type;
|
|
|
|
/* If the other bearer state was already true we don't need to
|
|
* send any property signals.
|
|
*/
|
|
- if (dev->bredr_state.paired == dev->le_state.paired)
|
|
- return;
|
|
+ //if (dev->bredr_state.paired == dev->le_state.paired)
|
|
+ // return;
|
|
|
|
if (!state->svc_resolved) {
|
|
dev->pending_paired = true;
|
|
return;
|
|
}
|
|
|
|
+ g_dbus_emit_property_changed(dbus_conn, dev->path,
|
|
+ DEVICE_INTERFACE,
|
|
+ "INFO");
|
|
g_dbus_emit_property_changed(dbus_conn, dev->path,
|
|
DEVICE_INTERFACE, "Paired");
|
|
}
|
|
@@ -6358,27 +6709,34 @@ void device_set_paired(struct btd_device *dev, uint8_t bdaddr_type)
|
|
void device_set_unpaired(struct btd_device *dev, uint8_t bdaddr_type)
|
|
{
|
|
struct bearer_state *state = get_state(dev, bdaddr_type);
|
|
+ DBG("");
|
|
|
|
if (!state->paired)
|
|
return;
|
|
|
|
state->paired = false;
|
|
+ dev->update_addrtype = bdaddr_type;
|
|
+
|
|
+ g_dbus_emit_property_changed(dbus_conn, dev->path,
|
|
+ DEVICE_INTERFACE,
|
|
+ "INFO");
|
|
+ g_dbus_emit_property_changed(dbus_conn, dev->path,
|
|
+ DEVICE_INTERFACE, "Paired");
|
|
|
|
/*
|
|
* If the other bearer state is still true we don't need to
|
|
* send any property signals or remove device.
|
|
*/
|
|
if (dev->bredr_state.paired != dev->le_state.paired) {
|
|
+ error("TODO disconnect only unpaired bearer if connected %d|%d", state->connected, bdaddr_type);
|
|
/* TODO disconnect only unpaired bearer */
|
|
if (state->connected)
|
|
- device_request_disconnect(dev, NULL);
|
|
+ device_request_disconnect_by_type(dev, NULL, bdaddr_type);
|
|
+ //device_request_disconnect(dev, NULL);
|
|
|
|
return;
|
|
}
|
|
|
|
- g_dbus_emit_property_changed(dbus_conn, dev->path,
|
|
- DEVICE_INTERFACE, "Paired");
|
|
-
|
|
btd_device_set_temporary(dev, true);
|
|
|
|
if (btd_device_is_connected(dev))
|
|
@@ -6417,7 +6775,9 @@ void device_bonding_complete(struct btd_device *device, uint8_t bdaddr_type,
|
|
struct authentication_req *auth = device->authr;
|
|
struct bearer_state *state = get_state(device, bdaddr_type);
|
|
|
|
- DBG("bonding %p status 0x%02x", bonding, status);
|
|
+ DBG("bonding %p status 0x%02x %d:%d:%d:%d:%d", bonding, status,
|
|
+ bdaddr_type, state->svc_resolved, state->paired,
|
|
+ device->bredr_state.connected, device->le_state.connected);
|
|
|
|
if (auth && auth->agent)
|
|
agent_cancel(auth->agent);
|
|
diff --git a/src/device.h b/src/device.h
|
|
index 0794f92d0..803449504 100644
|
|
--- a/src/device.h
|
|
+++ b/src/device.h
|
|
@@ -209,3 +209,6 @@ void btd_device_foreach_ad(struct btd_device *dev, bt_device_ad_func_t func,
|
|
void btd_device_set_conn_param(struct btd_device *device, uint16_t min_interval,
|
|
uint16_t max_interval, uint16_t latency,
|
|
uint16_t timeout);
|
|
+bool device_get_svc_refreshed(struct btd_device *device);
|
|
+void device_set_reason(struct btd_device *device, uint8_t bdaddr_type, int16_t reason);
|
|
+void device_copy_addr(struct btd_device *device, const bdaddr_t *bdaddr);
|
|
diff --git a/src/gatt-client.c b/src/gatt-client.c
|
|
index 8d83a9577..1e646b5d0 100644
|
|
--- a/src/gatt-client.c
|
|
+++ b/src/gatt-client.c
|
|
@@ -791,6 +791,7 @@ static gboolean characteristic_get_notifying(const GDBusPropertyTable *property,
|
|
{
|
|
struct characteristic *chrc = data;
|
|
dbus_bool_t notifying = chrc->notifying ? TRUE : FALSE;
|
|
+ error("");
|
|
|
|
dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, ¬ifying);
|
|
|
|
@@ -1383,7 +1384,7 @@ static void notify_client_disconnect(DBusConnection *conn, void *user_data)
|
|
struct notify_client *client = user_data;
|
|
struct characteristic *chrc = client->chrc;
|
|
|
|
- DBG("owner %s", client->owner);
|
|
+ error("owner %s", client->owner);
|
|
|
|
queue_remove(chrc->notify_clients, client);
|
|
queue_remove(chrc->service->client->all_notify_clients, client);
|
|
@@ -1432,6 +1433,7 @@ static void notify_cb(uint16_t value_handle, const uint8_t *value,
|
|
struct async_dbus_op *op = user_data;
|
|
struct notify_client *client = op->data;
|
|
struct characteristic *chrc = client->chrc;
|
|
+ DBG("client: %p", client);
|
|
|
|
/*
|
|
* Even if the value didn't change, we want to send a PropertiesChanged
|
|
@@ -1461,6 +1463,7 @@ static void register_notify_cb(uint16_t att_ecode, void *user_data)
|
|
struct async_dbus_op *op = user_data;
|
|
struct notify_client *client = op->data;
|
|
struct characteristic *chrc = client->chrc;
|
|
+ error("client: %p", client);
|
|
|
|
if (att_ecode) {
|
|
queue_remove(chrc->notify_clients, client);
|
|
@@ -1592,6 +1595,7 @@ static DBusMessage *characteristic_start_notify(DBusConnection *conn,
|
|
struct async_dbus_op *op;
|
|
struct notify_client *client;
|
|
struct btd_device *device = chrc->service->client->device;
|
|
+ error("");
|
|
|
|
if (device_is_disconnecting(device)) {
|
|
error("Device is disconnecting. StartNotify is not allowed.");
|
|
@@ -1615,6 +1619,7 @@ static DBusMessage *characteristic_start_notify(DBusConnection *conn,
|
|
client = notify_client_create(chrc, sender);
|
|
if (!client)
|
|
return btd_error_failed(msg, "Failed allocate notify session");
|
|
+ error("client: %p", client);
|
|
|
|
queue_push_tail(chrc->notify_clients, client);
|
|
queue_push_tail(chrc->service->client->all_notify_clients, client);
|
|
@@ -1667,6 +1672,7 @@ static DBusMessage *characteristic_stop_notify(DBusConnection *conn,
|
|
struct bt_gatt_client *gatt = chrc->service->client->gatt;
|
|
const char *sender = dbus_message_get_sender(msg);
|
|
struct notify_client *client;
|
|
+ error("");
|
|
|
|
if (chrc->notify_io) {
|
|
destroy_sock(chrc, chrc->notify_io->io);
|
|
@@ -1675,6 +1681,7 @@ static DBusMessage *characteristic_stop_notify(DBusConnection *conn,
|
|
|
|
client = queue_remove_if(chrc->notify_clients, match_notify_sender,
|
|
(void *) sender);
|
|
+ error("client: %p", client);
|
|
if (!client)
|
|
return btd_error_failed(msg, "No notify session started");
|
|
|
|
@@ -1771,7 +1778,7 @@ static void characteristic_free(void *data)
|
|
static void att_exchange(uint16_t mtu, void *user_data)
|
|
{
|
|
struct characteristic *chrc = user_data;
|
|
-
|
|
+ error("chrc->path %s", chrc->path);
|
|
g_dbus_emit_property_changed(btd_get_dbus_connection(), chrc->path,
|
|
GATT_CHARACTERISTIC_IFACE, "MTU");
|
|
}
|
|
@@ -2222,7 +2229,8 @@ static void register_notify(void *data, void *user_data)
|
|
struct btd_gatt_client *client = user_data;
|
|
struct async_dbus_op *op;
|
|
|
|
- DBG("Re-register subscribed notification client");
|
|
+ error("Dis-register subscribed notification client");
|
|
+ goto free;
|
|
|
|
op = new0(struct async_dbus_op, 1);
|
|
op->data = notify_client;
|
|
@@ -2238,6 +2246,7 @@ static void register_notify(void *data, void *user_data)
|
|
|
|
DBG("Failed to re-register notification client");
|
|
|
|
+free:
|
|
queue_remove(notify_client->chrc->notify_clients, notify_client);
|
|
queue_remove(client->all_notify_clients, notify_client);
|
|
|
|
@@ -2262,7 +2271,7 @@ void btd_gatt_client_ready(struct btd_gatt_client *client)
|
|
|
|
client->ready = true;
|
|
|
|
- DBG("GATT client ready");
|
|
+ error("GATT client ready");
|
|
|
|
create_services(client);
|
|
|
|
@@ -2366,7 +2375,7 @@ void btd_gatt_client_connected(struct btd_gatt_client *client)
|
|
return;
|
|
}
|
|
|
|
- DBG("Device connected.");
|
|
+ error("Device connected.");
|
|
|
|
bt_gatt_client_unref(client->gatt);
|
|
client->gatt = bt_gatt_client_clone(gatt);
|
|
@@ -2410,6 +2419,7 @@ void btd_gatt_client_service_removed(struct btd_gatt_client *client,
|
|
static void clear_notify_id(void *data, void *user_data)
|
|
{
|
|
struct notify_client *client = data;
|
|
+ error("");
|
|
|
|
client->notify_id = 0;
|
|
}
|
|
@@ -2424,7 +2434,7 @@ void btd_gatt_client_disconnected(struct btd_gatt_client *client)
|
|
if (!client || !client->gatt)
|
|
return;
|
|
|
|
- DBG("Device disconnected. Cleaning up.");
|
|
+ error("Device disconnected. Cleaning up.");
|
|
|
|
queue_remove_all(client->ios, NULL, NULL, client_shutdown);
|
|
|
|
diff --git a/src/gatt-database.c b/src/gatt-database.c
|
|
index 8472aac59..8cc811ce6 100644
|
|
--- a/src/gatt-database.c
|
|
+++ b/src/gatt-database.c
|
|
@@ -665,7 +665,7 @@ static void connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
|
|
return;
|
|
}
|
|
|
|
- DBG("New incoming %s ATT connection", dst_type == BDADDR_BREDR ?
|
|
+ error("New incoming %s ATT connection", dst_type == BDADDR_BREDR ?
|
|
"BR/EDR" : "LE");
|
|
|
|
adapter = adapter_find(&src);
|
|
@@ -692,7 +692,12 @@ static void gap_device_name_read_cb(struct gatt_db_attribute *attrib,
|
|
|
|
DBG("GAP Device Name read request\n");
|
|
|
|
- device_name = btd_adapter_get_name(database->adapter);
|
|
+ if (btd_opts.ble_name[0])
|
|
+ device_name = btd_opts.ble_name;
|
|
+ else
|
|
+ device_name = btd_adapter_get_name(database->adapter);
|
|
+
|
|
+ error("GAP Device Name read request: %s|%s\n", device_name, btd_adapter_get_name(database->adapter));
|
|
len = strlen(device_name);
|
|
|
|
if (offset > len) {
|
|
@@ -2985,10 +2990,23 @@ static void property_changed_cb(GDBusProxy *proxy, const char *name,
|
|
DBusMessageIter array;
|
|
uint8_t *value = NULL;
|
|
int len = 0;
|
|
+ error("name: %s, svc_c: %p", name, chrc->service->app->database->svc_chngd);
|
|
|
|
- if (strcmp(name, "Value"))
|
|
+ if (strcmp(name, "Value") && strcmp(name, "ServiceChanged"))
|
|
return;
|
|
|
|
+ if (!strcmp(name, "ServiceChanged")) {
|
|
+ uint8_t val[4];
|
|
+ put_le16(0x0001, val);
|
|
+ put_le16(0xffff, val + 2);
|
|
+ if (!gatt_db_attribute_notify(chrc->service->app->database->svc_chngd,
|
|
+ val, sizeof(val), NULL))
|
|
+ error("Failed to notify Service Changed");
|
|
+ else
|
|
+ error("send to notify Service Changed");
|
|
+ return;
|
|
+ }
|
|
+
|
|
if (iter) {
|
|
if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) {
|
|
DBG("Malformed \"Value\" property received");
|
|
@@ -4032,6 +4050,7 @@ struct btd_gatt_database *btd_gatt_database_new(struct btd_adapter *adapter)
|
|
}
|
|
|
|
bredr:
|
|
+#if 0
|
|
/* BR/EDR socket */
|
|
database->bredr_io = bt_io_listen(connect_cb, NULL, NULL, NULL, &gerr,
|
|
BT_IO_OPT_SOURCE_BDADDR, addr,
|
|
@@ -4044,6 +4063,7 @@ bredr:
|
|
g_error_free(gerr);
|
|
goto fail;
|
|
}
|
|
+#endif
|
|
|
|
if (g_dbus_register_interface(btd_get_dbus_connection(),
|
|
adapter_get_path(adapter),
|
|
diff --git a/src/main.c b/src/main.c
|
|
index 62453bffa..4e5b67c38 100644
|
|
--- a/src/main.c
|
|
+++ b/src/main.c
|
|
@@ -90,6 +90,8 @@ static const char *supported_options[] = {
|
|
"Testing",
|
|
"KernelExperimental",
|
|
"RemoteNameRequestRetryDelay",
|
|
+ "BleName",
|
|
+ "SSP",
|
|
NULL
|
|
};
|
|
|
|
@@ -252,7 +254,7 @@ static GKeyFile *load_config(const char *name)
|
|
else
|
|
len = strlen(configdir);
|
|
} else {
|
|
- configdir = CONFIGDIR;
|
|
+ configdir = "/etc"; //CONFIGDIR;
|
|
len = strlen(configdir);
|
|
}
|
|
|
|
@@ -847,8 +849,22 @@ static void parse_privacy(GKeyFile *config)
|
|
{
|
|
char *str = NULL;
|
|
|
|
+ if (parse_config_string(config, "General", "SSP", &str) &&
|
|
+ !strcmp(str, "off"))
|
|
+ btd_opts.ssp = false;
|
|
+ else
|
|
+ btd_opts.ssp = true;
|
|
+
|
|
+ if (!parse_config_string(config, "General", "BleName", &str)) {
|
|
+ DBG("No ble name");
|
|
+ } else {
|
|
+ memset(btd_opts.ble_name, 0, sizeof(btd_opts.ble_name));
|
|
+ strcpy(btd_opts.ble_name, str);
|
|
+ error("ble_name: %s, key_str: %s", btd_opts.ble_name, str);
|
|
+ }
|
|
+
|
|
if (!parse_config_string(config, "General", "Privacy", &str)) {
|
|
- btd_opts.privacy = 0x00;
|
|
+ btd_opts.privacy = 0x00;//test
|
|
btd_opts.device_privacy = true;
|
|
return;
|
|
}
|
|
@@ -879,6 +895,8 @@ static void parse_privacy(GKeyFile *config)
|
|
btd_opts.privacy = 0x00;
|
|
}
|
|
|
|
+ error("Privacy %s, %d", str, btd_opts.privacy);
|
|
+
|
|
g_free(str);
|
|
}
|
|
|
|
@@ -1006,6 +1024,7 @@ static void parse_general(GKeyFile *config)
|
|
{
|
|
parse_config_string(config, "General", "Name", &btd_opts.name);
|
|
parse_config_hex(config, "General", "Class", &btd_opts.class);
|
|
+ error("btd_opts.class: 0x%x", btd_opts.class);
|
|
parse_config_u32(config, "General", "DiscoverableTimeout",
|
|
&btd_opts.discovto,
|
|
0, UINT32_MAX);
|
|
diff --git a/src/main.conf b/src/main.conf
|
|
index 82040b3fa..900841e2f 100644
|
|
--- a/src/main.conf
|
|
+++ b/src/main.conf
|
|
@@ -4,9 +4,13 @@
|
|
# Defaults to 'BlueZ X.YZ'
|
|
#Name = BlueZ
|
|
|
|
+#BleName = Pixoo
|
|
+
|
|
+#SSP = off
|
|
+
|
|
# Default device class. Only the major and minor device class bits are
|
|
# considered. Defaults to '0x000000'.
|
|
-#Class = 0x000100
|
|
+Class = 0x240414
|
|
|
|
# How long to stay in discoverable mode before going back to non-discoverable
|
|
# The value is in seconds. Default is 180, i.e. 3 minutes.
|
|
@@ -100,7 +104,7 @@
|
|
# Specify the policy to the JUST-WORKS repairing initiated by peer
|
|
# Possible values: "never", "confirm", "always"
|
|
# Defaults to "never"
|
|
-#JustWorksRepairing = never
|
|
+JustWorksRepairing = confirm
|
|
|
|
# How long to keep temporary devices around
|
|
# The value is in seconds. Default is 30.
|
|
diff --git a/src/service.c b/src/service.c
|
|
index 7c4dc8fe0..42d58d731 100644
|
|
--- a/src/service.c
|
|
+++ b/src/service.c
|
|
@@ -88,7 +88,7 @@ static void change_state(struct btd_service *service, btd_service_state_t state,
|
|
service->err = err;
|
|
|
|
ba2str(device_get_address(service->device), addr);
|
|
- DBG("%p: device %s profile %s state changed: %s -> %s (%d)", service,
|
|
+ error("%p: device %s profile %s state changed: %s -> %s (%d)", service,
|
|
addr, service->profile->name,
|
|
state2str(old), state2str(state), err);
|
|
|
|
@@ -265,6 +265,8 @@ int btd_service_connect(struct btd_service *service)
|
|
return -ECONNABORTED;
|
|
}
|
|
|
|
+ ba2str(device_get_address(service->device), addr);
|
|
+ error("%s profile connect for %s: %s", profile->name, addr, profile->remote_uuid);
|
|
err = profile->connect(service);
|
|
if (err == 0) {
|
|
service->initiator = true;
|
|
@@ -284,6 +286,8 @@ int btd_service_disconnect(struct btd_service *service)
|
|
struct btd_profile *profile = service->profile;
|
|
char addr[18];
|
|
int err;
|
|
+ error("%s profile disconnect for %s: %p", profile->name, addr,
|
|
+ profile->disconnect);
|
|
|
|
if (!profile->disconnect)
|
|
return -ENOTSUP;
|
|
diff --git a/src/shared/att.c b/src/shared/att.c
|
|
index a45e9c268..ef652d4c4 100644
|
|
--- a/src/shared/att.c
|
|
+++ b/src/shared/att.c
|
|
@@ -551,7 +551,7 @@ static bool can_write_data(struct io *io, void *user_data)
|
|
if (!op)
|
|
return false;
|
|
|
|
- if (!bt_att_chan_write(chan, op->opcode, op->pdu, op->len)) {
|
|
+ if (bt_att_chan_write(chan, op->opcode, op->pdu, op->len) < 0) {
|
|
if (op->callback)
|
|
op->callback(BT_ATT_OP_ERROR_RSP, NULL, 0,
|
|
op->user_data);
|
|
@@ -1092,8 +1092,8 @@ static bool can_read_data(struct io *io, void *user_data)
|
|
/* For all other opcodes notify the upper layer of the PDU and
|
|
* let them act on it.
|
|
*/
|
|
- DBG(att, "(chan %p) ATT PDU received: 0x%02x", chan,
|
|
- opcode);
|
|
+ //DBG(att, "(chan %p) ATT PDU received: 0x%02x", chan,
|
|
+ // opcode);
|
|
handle_notify(chan, pdu, bytes_read);
|
|
break;
|
|
}
|
|
@@ -1425,7 +1425,7 @@ bool bt_att_set_mtu(struct bt_att *att, uint16_t mtu)
|
|
|
|
chan->mtu = mtu;
|
|
chan->buf = buf;
|
|
-
|
|
+ DBG(att, "chan->mtu %d, att mtu: %d", chan->mtu, att->mtu);
|
|
if (chan->mtu > att->mtu) {
|
|
att->mtu = chan->mtu;
|
|
queue_foreach(att->exchange_list, exchange_handler,
|
|
diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
|
|
index b48d739fc..9a2ec32a2 100644
|
|
--- a/src/shared/gatt-client.c
|
|
+++ b/src/shared/gatt-client.c
|
|
@@ -1755,6 +1755,7 @@ static unsigned int register_notify(struct bt_gatt_client *client,
|
|
{
|
|
struct notify_data *notify_data;
|
|
struct notify_chrc *chrc = NULL;
|
|
+ DBG(client, "client: %p", client);
|
|
|
|
/* Check if a characteristic ref count has been started already */
|
|
chrc = queue_find(client->notify_chrcs, match_notify_chrc_value_handle,
|
|
@@ -1885,6 +1886,7 @@ static void service_changed_complete(struct discovery_op *op, bool success,
|
|
uint16_t start_handle = op->start;
|
|
uint16_t end_handle = op->end;
|
|
const struct queue_entry *entry;
|
|
+ DBG(client, "service_changed_complete");
|
|
|
|
client->in_svc_chngd = false;
|
|
|
|
@@ -2069,6 +2071,7 @@ static void init_complete(struct discovery_op *op, bool success,
|
|
uint8_t att_ecode)
|
|
{
|
|
struct bt_gatt_client *client = op->client;
|
|
+ DBG(client, "init_complete");
|
|
|
|
client->in_init = false;
|
|
|
|
@@ -2649,6 +2652,7 @@ static void cancel_pending(void *data)
|
|
|
|
bool bt_gatt_client_cancel_all(struct bt_gatt_client *client)
|
|
{
|
|
+ DBG(client, "client: %p", client);
|
|
if (!client || !client->att)
|
|
return false;
|
|
|
|
--
|
|
2.34.1
|
|
|