2016-01-11 14:27:50 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2016 Intel Corporation
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
2016-02-09 12:22:21 +02:00
|
|
|
#include <atomic.h>
|
|
|
|
#include <misc/util.h>
|
|
|
|
|
2016-01-11 14:27:50 +02:00
|
|
|
#include <bluetooth/bluetooth.h>
|
|
|
|
#include <bluetooth/conn.h>
|
2016-02-09 12:22:21 +02:00
|
|
|
#include <bluetooth/log.h>
|
|
|
|
|
|
|
|
#include "gap_internal.h"
|
|
|
|
#include "conn_internal.h"
|
|
|
|
|
|
|
|
static struct bt_conn conns[CONFIG_BLUETOOTH_MAX_CONN];
|
2016-02-09 19:39:36 +02:00
|
|
|
static struct bt_conn_cb *callback_list;
|
2016-02-09 12:22:21 +02:00
|
|
|
|
|
|
|
static struct bt_conn *conn_new(void)
|
|
|
|
{
|
|
|
|
struct bt_conn *conn = NULL;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(conns); i++) {
|
|
|
|
if (!atomic_get(&conns[i].ref)) {
|
|
|
|
conn = &conns[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!conn) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(conn, 0, sizeof(*conn));
|
|
|
|
|
|
|
|
atomic_set(&conn->ref, 1);
|
|
|
|
|
|
|
|
return conn;
|
|
|
|
}
|
|
|
|
|
2016-01-11 14:27:50 +02:00
|
|
|
struct bt_conn *bt_conn_ref(struct bt_conn *conn)
|
|
|
|
{
|
2016-02-09 12:22:21 +02:00
|
|
|
atomic_inc(&conn->ref);
|
|
|
|
|
|
|
|
BT_DBG("handle %u ref %u", conn->handle, atomic_get(&conn->ref));
|
|
|
|
|
|
|
|
return conn;
|
2016-01-11 14:27:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void bt_conn_unref(struct bt_conn *conn)
|
|
|
|
{
|
2016-02-09 12:22:21 +02:00
|
|
|
atomic_dec(&conn->ref);
|
|
|
|
|
|
|
|
BT_DBG("handle %u ref %u", conn->handle, atomic_get(&conn->ref));
|
|
|
|
}
|
|
|
|
|
|
|
|
struct bt_conn *bt_conn_lookup_handle(uint16_t handle)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(conns); i++) {
|
|
|
|
if (!atomic_get(&conns[i].ref)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (conns[i].handle == handle) {
|
|
|
|
return bt_conn_ref(&conns[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
2016-01-11 14:27:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
struct bt_conn *bt_conn_lookup_addr_le(const bt_addr_le_t *peer)
|
|
|
|
{
|
2016-02-09 19:13:11 +02:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(conns); i++) {
|
|
|
|
if (!atomic_get(&conns[i].ref)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!bt_addr_le_cmp(peer, &conns[i].dst)) {
|
|
|
|
return bt_conn_ref(&conns[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-11 14:27:50 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
const bt_addr_le_t *bt_conn_get_dst(const struct bt_conn *conn)
|
|
|
|
{
|
2016-02-09 19:23:18 +02:00
|
|
|
return &conn->dst;
|
2016-01-11 14:27:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int bt_conn_get_info(const struct bt_conn *conn, struct bt_conn_info *info)
|
|
|
|
{
|
2016-02-09 19:23:18 +02:00
|
|
|
memset(info, 0, sizeof(*info));
|
|
|
|
|
|
|
|
info->type = BT_CONN_TYPE_LE;
|
2016-02-15 12:39:29 +02:00
|
|
|
info->role = conn->role;
|
2016-02-09 19:23:18 +02:00
|
|
|
info->le.dst = &conn->dst;
|
2016-02-15 12:39:29 +02:00
|
|
|
info->le.interval = conn->interval;
|
|
|
|
info->le.latency = conn->latency;
|
|
|
|
info->le.timeout = conn->timeout;
|
2016-02-09 19:23:18 +02:00
|
|
|
|
|
|
|
return 0;
|
2016-01-11 14:27:50 +02:00
|
|
|
}
|
|
|
|
|
2016-02-02 12:48:42 +01:00
|
|
|
int bt_conn_le_param_update(struct bt_conn *conn,
|
|
|
|
const struct bt_le_conn_param *param)
|
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
2016-01-11 14:27:50 +02:00
|
|
|
int bt_conn_disconnect(struct bt_conn *conn, uint8_t reason)
|
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer,
|
|
|
|
const struct bt_le_conn_param *param)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int bt_conn_security(struct bt_conn *conn, bt_security_t sec)
|
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t bt_conn_enc_key_size(struct bt_conn *conn)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void bt_conn_cb_register(struct bt_conn_cb *cb)
|
|
|
|
{
|
2016-02-09 19:39:36 +02:00
|
|
|
cb->_next = callback_list;
|
|
|
|
callback_list = cb;
|
2016-01-11 14:27:50 +02:00
|
|
|
}
|
2016-01-14 18:16:51 +02:00
|
|
|
|
|
|
|
int bt_le_set_auto_conn(bt_addr_le_t *addr,
|
|
|
|
const struct bt_le_conn_param *param)
|
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
2016-01-14 23:08:34 +02:00
|
|
|
struct bt_conn *bt_conn_create_slave_le(const bt_addr_le_t *peer,
|
|
|
|
const struct bt_le_adv_param *param)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-01-14 22:12:28 +02:00
|
|
|
int bt_conn_auth_cb_register(const struct bt_conn_auth_cb *cb)
|
2016-01-14 18:16:51 +02:00
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
2016-01-14 22:12:28 +02:00
|
|
|
int bt_conn_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey)
|
2016-01-14 18:16:51 +02:00
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
2016-01-14 22:12:28 +02:00
|
|
|
int bt_conn_auth_cancel(struct bt_conn *conn)
|
2016-01-14 18:16:51 +02:00
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
2016-01-14 22:12:28 +02:00
|
|
|
int bt_conn_auth_passkey_confirm(struct bt_conn *conn, bool match)
|
2016-01-14 18:16:51 +02:00
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
2016-02-09 12:22:21 +02:00
|
|
|
|
|
|
|
/* Connection related events */
|
|
|
|
|
2016-02-09 19:39:36 +02:00
|
|
|
static void notify_connected(struct bt_conn *conn)
|
|
|
|
{
|
|
|
|
struct bt_conn_cb *cb;
|
|
|
|
|
|
|
|
for (cb = callback_list; cb; cb = cb->_next) {
|
|
|
|
if (cb->connected) {
|
|
|
|
cb->connected(conn, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void notify_disconnected(struct bt_conn *conn)
|
|
|
|
{
|
|
|
|
struct bt_conn_cb *cb;
|
|
|
|
|
|
|
|
for (cb = callback_list; cb; cb = cb->_next) {
|
|
|
|
if (cb->disconnected) {
|
|
|
|
cb->disconnected(conn, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-12 15:47:05 +02:00
|
|
|
void on_nble_gap_connect_evt(const struct nble_gap_connect_evt *ev)
|
2016-02-09 12:22:21 +02:00
|
|
|
{
|
|
|
|
struct bt_conn *conn;
|
|
|
|
|
2016-02-15 12:39:29 +02:00
|
|
|
BT_DBG("handle %u role %u", ev->conn_handle, ev->role);
|
2016-02-09 12:22:21 +02:00
|
|
|
|
2016-02-09 19:11:00 +02:00
|
|
|
conn = conn_new();
|
2016-02-09 12:22:21 +02:00
|
|
|
if (!conn) {
|
2016-02-09 19:11:00 +02:00
|
|
|
BT_ERR("Unable to create new bt_conn object");
|
2016-02-09 12:22:21 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
conn->handle = ev->conn_handle;
|
2016-02-15 12:39:29 +02:00
|
|
|
conn->role = ev->role;
|
|
|
|
conn->interval = ev->conn_values.interval;
|
|
|
|
conn->latency = ev->conn_values.latency;
|
|
|
|
conn->timeout = ev->conn_values.supervision_to;
|
2016-02-09 19:13:11 +02:00
|
|
|
bt_addr_le_copy(&conn->dst, &ev->peer_bda);
|
2016-02-09 19:39:36 +02:00
|
|
|
|
|
|
|
notify_connected(conn);
|
2016-02-09 12:22:21 +02:00
|
|
|
}
|
|
|
|
|
2016-02-12 15:47:05 +02:00
|
|
|
void on_nble_gap_disconnect_evt(const struct nble_gap_disconnect_evt *ev)
|
2016-02-09 12:22:21 +02:00
|
|
|
{
|
|
|
|
struct bt_conn *conn;
|
|
|
|
|
|
|
|
conn = bt_conn_lookup_handle(ev->conn_handle);
|
|
|
|
if (!conn) {
|
|
|
|
BT_ERR("Unable to find conn for handle %u", ev->conn_handle);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BT_DBG("conn %p handle %u", conn, ev->conn_handle);
|
|
|
|
|
2016-02-09 19:39:36 +02:00
|
|
|
notify_disconnected(conn);
|
|
|
|
|
2016-02-09 19:17:16 +02:00
|
|
|
/* Drop the reference given by lookup_handle() */
|
2016-02-09 12:22:21 +02:00
|
|
|
bt_conn_unref(conn);
|
2016-02-09 19:17:16 +02:00
|
|
|
/* Drop the initial reference from conn_new() */
|
2016-02-09 12:22:21 +02:00
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
|
|
|
|
2016-02-12 15:47:05 +02:00
|
|
|
void on_nble_gap_conn_update_evt(const struct nble_gap_conn_update_evt *ev)
|
2016-02-09 12:22:21 +02:00
|
|
|
{
|
|
|
|
struct bt_conn *conn;
|
|
|
|
|
|
|
|
conn = bt_conn_lookup_handle(ev->conn_handle);
|
|
|
|
if (!conn) {
|
|
|
|
BT_ERR("Unable to find conn for handle %u", ev->conn_handle);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BT_DBG("conn %p handle %u", conn, ev->conn_handle);
|
|
|
|
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|