Skip to content

Commit

Permalink
Changes towards improving ble reliability.
Browse files Browse the repository at this point in the history
  • Loading branch information
kareltucek committed Dec 31, 2024
1 parent ce3a3ce commit ecc43e7
Show file tree
Hide file tree
Showing 14 changed files with 256 additions and 61 deletions.
17 changes: 8 additions & 9 deletions device/src/bt_advertise.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,15 @@ static void setFilters() {
bt_le_filter_accept_list_clear();
if (DEVICE_IS_UHK80_RIGHT) {
if (BtConn_UnusedPeripheralConnectionCount() <= 1 && SelectedHostConnectionId != ConnectionId_Invalid) {
printk("Setting an advertising filter to connection %d\n", SelectedHostConnectionId);
bt_le_filter_accept_list_add(&HostConnection(SelectedHostConnectionId)->bleAddress);
advertisementParams->options = BT_LE_ADV_OPT_FILTER_CONN;
} else {
printk("Setting no advertising filter\n");
advertisementParams->options = BT_LE_ADV_OPT_NONE;
}
}
}

void BtAdvertise_Start(uint8_t adv_type)
uint8_t BtAdvertise_Start(uint8_t adv_type)
{
setFilters();

Expand All @@ -76,26 +74,25 @@ void BtAdvertise_Start(uint8_t adv_type)
err = bt_le_adv_start(BT_LE_ADV_CONN, adHid, ARRAY_SIZE(adHid), sdHid, ARRAY_SIZE(sdHid));
} else {
printk("Attempted to start advertising without any type! Ignoring.\n");
return;
return 0;
}

if (err == 0) {
printk("%s advertising successfully started\n", adv_type_string);
return 0;
} else if (err == -EALREADY) {
printk("%s advertising continued\n", adv_type_string);
return 0;
} else {
printk("%s advertising failed to start (err %d)\n", adv_type_string, err);
BtConn_DisconnectAll();
EventScheduler_Reschedule(CurrentTime + 5000, EventSchedulerEvent_BtStartScanningAndAdvertising, "BtStartAdvertisement");
printk("%s advertising failed to start (err %d), free connections: %d\n", adv_type_string, err, BtConn_UnusedPeripheralConnectionCount());
return err;
}
}

void BtAdvertise_Stop() {
int err = bt_le_adv_stop();
if (err) {
printk("Advertising failed to stop (err %d)\n", err);
} else {
printk("Advertising successfully stopped\n");
}
}

Expand All @@ -121,6 +118,8 @@ uint8_t BtAdvertise_Type() {
return ADVERTISE_NUS | ADVERTISE_HID;
}
} else {
printk("Current slot count %d, not advertising\n", BtConn_UnusedPeripheralConnectionCount());
BtConn_ListCurrentConnections();
return 0;
}
case DeviceId_Uhk_Dongle:
Expand Down
2 changes: 1 addition & 1 deletion device/src/bt_advertise.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

// Functions:

void BtAdvertise_Start(uint8_t adv_type);
uint8_t BtAdvertise_Start(uint8_t adv_type);
void BtAdvertise_Stop();
uint8_t BtAdvertise_Type();

Expand Down
173 changes: 156 additions & 17 deletions device/src/bt_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ bool Bt_NewPairedDevice = false;
#define BLE_ADDR_LEN 6

peer_t Peers[PeerCount] = {
{
.id = PeerIdUnknown,
.name = "unknown",
.connectionId = ConnectionId_Invalid,
},
{
.id = PeerIdLeft,
.name = "left",
Expand Down Expand Up @@ -158,15 +163,14 @@ static void assignPeer(struct bt_conn* conn, uint8_t connectionId, uint8_t conne
if (Peers[peerId].conn) {
printk("Peer slot %d already occupied!\n", peerId);
}
printk("Allocating connectionId %d to peer %d\n", connectionId, peerId);
Peers[peerId].addr = addr;
Peers[peerId].conn = bt_conn_ref(conn);
Peers[peerId].connectionId = connectionId;
Connections[connectionId].peerId = peerId;
Connections_SetState(connectionId, ConnectionState_Connected);
}

void check_connection(struct bt_conn *conn, void *data)
void bt_foreach_list_current_connections(struct bt_conn *conn, void *data)
{
int8_t peerId = GetPeerIdByConn(conn);
if (peerId == PeerIdUnknown) {
Expand All @@ -178,7 +182,7 @@ void check_connection(struct bt_conn *conn, void *data)

void BtConn_ListCurrentConnections() {
printk("Current connections:\n");
bt_conn_foreach(BT_CONN_TYPE_LE, check_connection, NULL);
bt_conn_foreach(BT_CONN_TYPE_LE, bt_foreach_list_current_connections, NULL);
}


Expand All @@ -192,7 +196,140 @@ void BtConn_ListAllBonds() {
bt_foreach_bond(BT_ID_DEFAULT, bt_foreach_print_bond, NULL);
}


// If last available slot is reserved for a selected connection, refuse other connections
static bool isWanted(struct bt_conn *conn, connection_type_t connectionType) {
return
connectionType == ConnectionType_NusLeft ||
BtConn_UnusedPeripheralConnectionCount() > 1 ||
SelectedHostConnectionId == ConnectionId_Invalid ||
BtAddrEq(bt_conn_get_dst(conn), &HostConnection(SelectedHostConnectionId)->bleAddress);
}

static void connectNus(struct bt_conn *conn, connection_id_t connectionId, connection_type_t connectionType) {
int err;

if ( !isWanted(conn, connectionType) ) {
printk("Refusing connenction %d (this is not a selected connection)\n", connectionId);
err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
return;
}

assignPeer(conn, connectionId, connectionType);

printk("Bt connected to %s\n", GetPeerStringByConn(conn));
bt_conn_set_security(conn, BT_SECURITY_L4);
}


static void connectHid(struct bt_conn *conn, connection_id_t connectionId, connection_type_t connectionType) {
int err;

if ( !isWanted(conn, connectionType) ) {
printk("Refusing connenction %d (this is not a selected connection)\n", connectionId);
err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
return;
}

static const struct bt_le_conn_param conn_params = BT_LE_CONN_PARAM_INIT(
6, 9, // keep it low, lowest allowed is 6 (7.5ms), lowest supported widely is 9 (11.25ms)
10, // keeping it higher allows power saving on peripheral when there's nothing to send (keep it under 30 though)
100 // connection timeout (*10ms)
);
bt_conn_le_param_update(conn, &conn_params);
#if DEVICE_IS_UHK80_RIGHT
USB_DisableHid();
#endif

assignPeer(conn, connectionId, connectionType);

printk("Bt connected to %s\n", GetPeerStringByConn(conn));
Connections_SetState(connectionId, ConnectionState_Ready);
}

#define BT_UUID_NUS_VAL BT_UUID_128_ENCODE(0x6e400001, 0xb5a3, 0xf393, 0xe0a9, 0xe50e24dcca9e)
#define BT_UUID_NUS BT_UUID_DECLARE_128(BT_UUID_NUS_VAL)

static uint8_t discover_func(struct bt_conn *conn, const struct bt_gatt_attr *attr, struct bt_gatt_discover_params *params)
{
if (!attr) {
printk("Service discovery completed, connection wasn't matched. Disconnecting!\n");
return BT_GATT_ITER_STOP;
}

if (attr->user_data) {
struct bt_gatt_service_val *service_val = (struct bt_gatt_service_val *)attr->user_data;
if (service_val && service_val->uuid) {
if (service_val->uuid->type == BT_UUID_TYPE_128 && !bt_uuid_cmp(service_val->uuid, BT_UUID_NUS)) {
if (!BtPair_OobPairingInProgress) {
printk("Unknown NUS trying to connect. Refusing!\n");
bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
}
return BT_GATT_ITER_STOP;
}
}
}

return BT_GATT_ITER_CONTINUE;
}

static void connectedUnknown(struct bt_conn *conn) {
int err;

printk("Bt connected to unknown. Starting discovery.\n");
static struct bt_gatt_discover_params discover_params;
discover_params.uuid = NULL; // Will discover all services
discover_params.start_handle = 0x0001;
discover_params.end_handle = 0xFFFF;
discover_params.func = discover_func;
discover_params.type = BT_GATT_DISCOVER_PRIMARY;

err = bt_gatt_discover(conn, &discover_params);
if (err) {
printk("Service discovery failed (err %u)\n", err);
return;
}
}

static void connected(struct bt_conn *conn, uint8_t err) {

{
const bt_addr_le_t * addr = bt_conn_get_dst(conn);
connection_id_t connectionId = Connections_GetConnectionIdByBtAddr(addr);
connection_type_t connectionType = Connections_Type(connectionId);

if (err) {
printk("Failed to connect to %s, err %u\n", GetPeerStringByConn(conn), err);
BtManager_StartScanningAndAdvertising();
return;
}

switch (connectionType) {
case ConnectionType_NusLeft:
case ConnectionType_NusRight:
case ConnectionType_NusDongle:
connectNus(conn, connectionId, connectionType);
break;
case ConnectionType_BtHid:
connectHid(conn, connectionId, connectionType);
break;
case ConnectionType_Unknown:
default:
connectedUnknown(conn);
break;
}

if (DEVICE_IS_UHK80_RIGHT) {
BtManager_StartScanningAndAdvertising();
}
}



return;


/*
const bt_addr_le_t * addr = bt_conn_get_dst(conn);
connection_id_t connectionId = Connections_GetConnectionIdByBtAddr(addr);
connection_type_t connectionType = Connections_Type(connectionId);
Expand Down Expand Up @@ -245,6 +382,7 @@ static void connected(struct bt_conn *conn, uint8_t err) {
if (DEVICE_IS_UHK80_RIGHT) {
BtManager_StartScanningAndAdvertising();
}
*/
}

static void disconnected(struct bt_conn *conn, uint8_t reason) {
Expand Down Expand Up @@ -286,7 +424,7 @@ static void disconnected(struct bt_conn *conn, uint8_t reason) {
}
}

EventScheduler_Schedule(k_uptime_get_32()+50, EventSchedulerEvent_BtStartScanningAndAdvertising, "disconnected");
BtManager_StartScanningAndAdvertisingAsync();
}
}

Expand Down Expand Up @@ -436,28 +574,29 @@ static struct bt_conn_auth_cb conn_auth_callbacks = {
static void pairing_complete(struct bt_conn *conn, bool bonded) {
printk("Pairing completed: %s, bonded %d\n", GetPeerStringByConn(conn), bonded);

uint8_t peerId = GetPeerIdByConn(conn);

// address can change during pairing
bt_addr_le_t addr = *bt_conn_get_dst(conn);
Peers[peerId].addr = addr;

if (BtPair_OobPairingInProgress) {
BtPair_EndPairing(true, "Successfuly bonded!");

connection_id_t connectionId = Connections_GetConnectionIdByBtAddr(&addr);
connection_type_t connectionType = Connections_Type(connectionId);
connectNus(conn, connectionId, connectionType);
} else {
connection_type_t connectionType = Connections_Type(Peers[peerId].connectionId);
bool isUhkPeer = isUhkDeviceConnection(connectionType);
bool isKnown = HostConnections_IsKnownBleAddress(&addr);
printk("- is known: %d, isUhkPeer: %d\n", isKnown, isUhkPeer);
if (!isKnown && !isUhkPeer) {
printk("setting NewPairedDevice\n");
connection_id_t connectionId = Connections_GetConnectionIdByBtAddr(&addr);
connection_type_t connectionType = Connections_Type(connectionId);

if (connectionId == ConnectionId_Invalid) {
connectionId = Connections_GetNewBtHidConnectionId();
connectionType = ConnectionType_BtHid;
HostConnection(connectionId)->bleAddress = addr;
Bt_NewPairedDevice = true;
}

connectHid(conn, connectionId, connectionType);
}

BtConn_ListCurrentConnections();
BtConn_ListAllBonds();
HostConnections_ListKnownBleConnections();
BtManager_StartScanningAndAdvertisingAsync();
}

static void bt_foreach_conn_cb(struct bt_conn *conn, void *user_data) {
Expand Down
6 changes: 3 additions & 3 deletions device/src/bt_conn.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
// please edit this in prj.conf
#define PERIPHERAL_CONNECTION_COUNT CONFIG_BT_CTLR_SDC_PERIPHERAL_COUNT

#define PeerIdUnknown -1
#define PeerIdLeft 0
#define PeerIdRight 1
#define PeerIdUnknown 0
#define PeerIdLeft 1
#define PeerIdRight 2
#define PeerIdFirstHost (PeerIdRight+1)
#define PeerIdLastHost (PeerIdFirstHost+PERIPHERAL_CONNECTION_COUNT-1)
#define PeerCount (PeerIdLastHost+1)
Expand Down
Loading

0 comments on commit ecc43e7

Please sign in to comment.