mirror of
https://git.kernel.org/pub/scm/bluetooth/bluez.git
synced 2024-12-28 21:33:29 +08:00
core: Add support for storing and reloading connection parameters
This commit is contained in:
parent
922b94115e
commit
7b709307b9
159
src/adapter.c
159
src/adapter.c
@ -126,6 +126,15 @@ struct irk_info {
|
|||||||
uint8_t val[16];
|
uint8_t val[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct conn_param {
|
||||||
|
bdaddr_t bdaddr;
|
||||||
|
uint8_t bdaddr_type;
|
||||||
|
uint16_t min_interval;
|
||||||
|
uint16_t max_interval;
|
||||||
|
uint16_t latency;
|
||||||
|
uint16_t timeout;
|
||||||
|
};
|
||||||
|
|
||||||
struct watch_client {
|
struct watch_client {
|
||||||
struct btd_adapter *adapter;
|
struct btd_adapter *adapter;
|
||||||
char *owner;
|
char *owner;
|
||||||
@ -2430,6 +2439,34 @@ static struct irk_info *get_irk_info(GKeyFile *key_file, const char *peer,
|
|||||||
return irk;
|
return irk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct conn_param *get_conn_param(GKeyFile *key_file, const char *peer,
|
||||||
|
uint8_t bdaddr_type)
|
||||||
|
{
|
||||||
|
struct conn_param *param;
|
||||||
|
|
||||||
|
if (!g_key_file_has_group(key_file, "ConnectionParameters"))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
param = g_new0(struct conn_param, 1);
|
||||||
|
|
||||||
|
param->min_interval = g_key_file_get_integer(key_file,
|
||||||
|
"ConnectionParameters",
|
||||||
|
"MinInterval", NULL);
|
||||||
|
param->max_interval = g_key_file_get_integer(key_file,
|
||||||
|
"ConnectionParameters",
|
||||||
|
"MaxInterval", NULL);
|
||||||
|
param->latency = g_key_file_get_integer(key_file,
|
||||||
|
"ConnectionParameters",
|
||||||
|
"Latency", NULL);
|
||||||
|
param->timeout = g_key_file_get_integer(key_file,
|
||||||
|
"ConnectionParameters",
|
||||||
|
"Timeout", NULL);
|
||||||
|
str2ba(peer, ¶m->bdaddr);
|
||||||
|
param->bdaddr_type = bdaddr_type;
|
||||||
|
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
|
||||||
static void load_link_keys_complete(uint8_t status, uint16_t length,
|
static void load_link_keys_complete(uint8_t status, uint16_t length,
|
||||||
const void *param, void *user_data)
|
const void *param, void *user_data)
|
||||||
{
|
{
|
||||||
@ -2683,6 +2720,62 @@ static void load_irks(struct btd_adapter *adapter, GSList *irks)
|
|||||||
error("Failed to IRKs for hci%u", adapter->dev_id);
|
error("Failed to IRKs for hci%u", adapter->dev_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void load_conn_params_complete(uint8_t status, uint16_t length,
|
||||||
|
const void *param, void *user_data)
|
||||||
|
{
|
||||||
|
struct btd_adapter *adapter = user_data;
|
||||||
|
|
||||||
|
if (status != MGMT_STATUS_SUCCESS) {
|
||||||
|
error("hci%u Load Connection Parameters failed: %s (0x%02x)",
|
||||||
|
adapter->dev_id, mgmt_errstr(status), status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG("Connection Parameters loaded for hci%u", adapter->dev_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load_conn_params(struct btd_adapter *adapter, GSList *params)
|
||||||
|
{
|
||||||
|
struct mgmt_cp_load_conn_param *cp;
|
||||||
|
struct mgmt_conn_param *param;
|
||||||
|
size_t param_count, cp_size;
|
||||||
|
unsigned int id;
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
param_count = g_slist_length(params);
|
||||||
|
|
||||||
|
DBG("hci%u conn params %zu", adapter->dev_id, param_count);
|
||||||
|
|
||||||
|
cp_size = sizeof(*cp) + (param_count * sizeof(*param));
|
||||||
|
|
||||||
|
cp = g_try_malloc0(cp_size);
|
||||||
|
if (cp == NULL) {
|
||||||
|
error("Failed to allocate memory for connection parameters");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cp->param_count = htobs(param_count);
|
||||||
|
|
||||||
|
for (l = params, param = cp->params; l; l = g_slist_next(l), param++) {
|
||||||
|
struct conn_param *info = l->data;
|
||||||
|
|
||||||
|
bacpy(¶m->addr.bdaddr, &info->bdaddr);
|
||||||
|
param->addr.type = info->bdaddr_type;
|
||||||
|
param->min_interval = htobs(info->min_interval);
|
||||||
|
param->max_interval = htobs(info->max_interval);
|
||||||
|
param->latency = htobs(info->latency);
|
||||||
|
param->timeout = htobs(info->timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
id = mgmt_send(adapter->mgmt, MGMT_OP_LOAD_CONN_PARAM, adapter->dev_id,
|
||||||
|
cp_size, cp, load_conn_params_complete, adapter, NULL);
|
||||||
|
|
||||||
|
g_free(cp);
|
||||||
|
|
||||||
|
if (id == 0)
|
||||||
|
error("Load connection parameters failed");
|
||||||
|
}
|
||||||
|
|
||||||
static uint8_t get_le_addr_type(GKeyFile *keyfile)
|
static uint8_t get_le_addr_type(GKeyFile *keyfile)
|
||||||
{
|
{
|
||||||
uint8_t addr_type;
|
uint8_t addr_type;
|
||||||
@ -2711,6 +2804,7 @@ static void load_devices(struct btd_adapter *adapter)
|
|||||||
GSList *keys = NULL;
|
GSList *keys = NULL;
|
||||||
GSList *ltks = NULL;
|
GSList *ltks = NULL;
|
||||||
GSList *irks = NULL;
|
GSList *irks = NULL;
|
||||||
|
GSList *params = NULL;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
|
|
||||||
@ -2732,6 +2826,7 @@ static void load_devices(struct btd_adapter *adapter)
|
|||||||
struct link_key_info *key_info;
|
struct link_key_info *key_info;
|
||||||
GSList *list, *ltk_info;
|
GSList *list, *ltk_info;
|
||||||
struct irk_info *irk_info;
|
struct irk_info *irk_info;
|
||||||
|
struct conn_param *param;
|
||||||
uint8_t bdaddr_type;
|
uint8_t bdaddr_type;
|
||||||
|
|
||||||
if (entry->d_type != DT_DIR || bachk(entry->d_name) < 0)
|
if (entry->d_type != DT_DIR || bachk(entry->d_name) < 0)
|
||||||
@ -2756,6 +2851,10 @@ static void load_devices(struct btd_adapter *adapter)
|
|||||||
if (irk_info)
|
if (irk_info)
|
||||||
irks = g_slist_append(irks, irk_info);
|
irks = g_slist_append(irks, irk_info);
|
||||||
|
|
||||||
|
param = get_conn_param(key_file, entry->d_name, bdaddr_type);
|
||||||
|
if (param)
|
||||||
|
params = g_slist_append(params, param);
|
||||||
|
|
||||||
list = g_slist_find_custom(adapter->devices, entry->d_name,
|
list = g_slist_find_custom(adapter->devices, entry->d_name,
|
||||||
device_address_cmp);
|
device_address_cmp);
|
||||||
if (list) {
|
if (list) {
|
||||||
@ -2801,6 +2900,8 @@ free:
|
|||||||
g_slist_free_full(ltks, g_free);
|
g_slist_free_full(ltks, g_free);
|
||||||
load_irks(adapter, irks);
|
load_irks(adapter, irks);
|
||||||
g_slist_free_full(irks, g_free);
|
g_slist_free_full(irks, g_free);
|
||||||
|
load_conn_params(adapter, params);
|
||||||
|
g_slist_free_full(params, g_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
int btd_adapter_block_address(struct btd_adapter *adapter,
|
int btd_adapter_block_address(struct btd_adapter *adapter,
|
||||||
@ -6038,12 +6139,55 @@ static void new_irk_callback(uint16_t index, uint16_t length,
|
|||||||
btd_device_set_temporary(device, FALSE);
|
btd_device_set_temporary(device, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void store_conn_param(struct btd_adapter *adapter, const bdaddr_t *peer,
|
||||||
|
uint8_t bdaddr_type, uint16_t min_interval,
|
||||||
|
uint16_t max_interval, uint16_t latency,
|
||||||
|
uint16_t timeout)
|
||||||
|
{
|
||||||
|
char adapter_addr[18];
|
||||||
|
char device_addr[18];
|
||||||
|
char filename[PATH_MAX + 1];
|
||||||
|
GKeyFile *key_file;
|
||||||
|
char *store_data;
|
||||||
|
size_t length = 0;
|
||||||
|
|
||||||
|
ba2str(&adapter->bdaddr, adapter_addr);
|
||||||
|
ba2str(peer, device_addr);
|
||||||
|
|
||||||
|
DBG("");
|
||||||
|
|
||||||
|
snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", adapter_addr,
|
||||||
|
device_addr);
|
||||||
|
filename[PATH_MAX] = '\0';
|
||||||
|
|
||||||
|
key_file = g_key_file_new();
|
||||||
|
g_key_file_load_from_file(key_file, filename, 0, NULL);
|
||||||
|
|
||||||
|
g_key_file_set_integer(key_file, "ConnectionParameters",
|
||||||
|
"MinInterval", min_interval);
|
||||||
|
g_key_file_set_integer(key_file, "ConnectionParameters",
|
||||||
|
"MaxInterval", max_interval);
|
||||||
|
g_key_file_set_integer(key_file, "ConnectionParameters",
|
||||||
|
"Latency", latency);
|
||||||
|
g_key_file_set_integer(key_file, "ConnectionParameters",
|
||||||
|
"Timeout", timeout);
|
||||||
|
|
||||||
|
create_file(filename, S_IRUSR | S_IWUSR);
|
||||||
|
|
||||||
|
store_data = g_key_file_to_data(key_file, &length, NULL);
|
||||||
|
g_file_set_contents(filename, store_data, length, NULL);
|
||||||
|
g_free(store_data);
|
||||||
|
|
||||||
|
g_key_file_free(key_file);
|
||||||
|
}
|
||||||
|
|
||||||
static void new_conn_param(uint16_t index, uint16_t length,
|
static void new_conn_param(uint16_t index, uint16_t length,
|
||||||
const void *param, void *user_data)
|
const void *param, void *user_data)
|
||||||
{
|
{
|
||||||
const struct mgmt_ev_new_conn_param *ev = param;
|
const struct mgmt_ev_new_conn_param *ev = param;
|
||||||
struct btd_adapter *adapter = user_data;
|
struct btd_adapter *adapter = user_data;
|
||||||
uint16_t min, max, latency, timeout;
|
uint16_t min, max, latency, timeout;
|
||||||
|
struct btd_device *dev;
|
||||||
char dst[18];
|
char dst[18];
|
||||||
|
|
||||||
|
|
||||||
@ -6061,6 +6205,21 @@ static void new_conn_param(uint16_t index, uint16_t length,
|
|||||||
|
|
||||||
DBG("hci%u %s (%u) min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
|
DBG("hci%u %s (%u) min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
|
||||||
adapter->dev_id, dst, ev->addr.type, min, max, latency, timeout);
|
adapter->dev_id, dst, ev->addr.type, min, max, latency, timeout);
|
||||||
|
|
||||||
|
dev = btd_adapter_get_device(adapter, &ev->addr.bdaddr, ev->addr.type);
|
||||||
|
if (!dev) {
|
||||||
|
error("Unable to get device object for %s", dst);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ev->store_hint) {
|
||||||
|
device_set_conn_param(dev, min, max, latency, timeout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
store_conn_param(adapter, &ev->addr.bdaddr, ev->addr.type,
|
||||||
|
ev->min_interval, ev->max_interval,
|
||||||
|
ev->latency, ev->timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
int adapter_set_io_capability(struct btd_adapter *adapter, uint8_t io_cap)
|
int adapter_set_io_capability(struct btd_adapter *adapter, uint8_t io_cap)
|
||||||
|
Loading…
Reference in New Issue
Block a user