From 9697a95c0d7807c560ca00275893211004ab4f3f Mon Sep 17 00:00:00 2001 From: rohitrathnam Date: Wed, 7 Aug 2024 12:06:39 +0530 Subject: [PATCH 01/13] add scan with default params --- source/application/bluetooth.c | 84 ++++++++++++++++++++++++++++++++-- source/memory_layout.ld | 2 +- 2 files changed, 82 insertions(+), 4 deletions(-) diff --git a/source/application/bluetooth.c b/source/application/bluetooth.c index 9388dbd0..81e9c97d 100644 --- a/source/application/bluetooth.c +++ b/source/application/bluetooth.c @@ -84,6 +84,36 @@ bool flash_write_in_progress = false; uint16_t ble_negotiated_mtu; +#define APP_BLE_CONN_CFG_TAG 1 +// NRF_BLE_SCAN_SCAN_INTERVAL - Scanning interval. Determines the scan interval in units of 0.625 millisecond. +#define NRF_BLE_SCAN_SCAN_INTERVAL 160 +// NRF_BLE_SCAN_SCAN_DURATION - Duration of a scanning session in units of 10 ms. Range: 0x0001 - 0xFFFF (10 ms to 10.9225 ms). If set to 0x0000, the scanning continues until it is explicitly disabled. +#define NRF_BLE_SCAN_SCAN_DURATION 0 +// NRF_BLE_SCAN_SCAN_WINDOW - Scanning window. Determines the scanning window in units of 0.625 millisecond. +#define NRF_BLE_SCAN_SCAN_WINDOW 80 +#define NRF_BLE_SCAN_BUFFER 255 + +// NRF_BLE_SCAN_SUPERVISION_TIMEOUT - Determines the supervision time-out in units of 10 millisecond. +#define NRF_BLE_SCAN_SUPERVISION_TIMEOUT 6200 +// NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL - Determines minimum connection interval in milliseconds. +#define NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL 100 +// NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL - Determines maximum connection interval in milliseconds. +#define NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL 500 +// NRF_BLE_SCAN_SLAVE_LATENCY - Determines the slave latency in counts of connection events. +#define NRF_BLE_SCAN_SLAVE_LATENCY 5 + +#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) + +enum +{ + UNIT_0_625_MS = 625, /**< Number of microseconds in 0.625 milliseconds. */ + UNIT_1_25_MS = 1250, /**< Number of microseconds in 1.25 milliseconds. */ + UNIT_10_MS = 10000 /**< Number of microseconds in 10 milliseconds. */ +}; + +static ble_data_t scan_buffer; +static uint8_t scan_buffer_data[NRF_BLE_SCAN_BUFFER]; + static void softdevice_assert_handler(uint32_t id, uint32_t pc, uint32_t info) { error_with_message("Softdevice crashed"); @@ -347,6 +377,25 @@ void SD_EVT_IRQHandler(void) break; } + case BLE_GAP_EVT_ADV_REPORT: + { + LOG("Advertisement report: %x %x %x %x %x %x", + ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr[0], + ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr[1], + ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr[2], + ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr[3], + ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr[4], + ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr[5] + ); + break; + } + + case BLE_GAP_EVT_TIMEOUT: + { + LOG("Scan timed out"); + break; + } + default: { LOG("Unhandled BLE event: %u", ble_evt->header.evt_id); @@ -367,13 +416,15 @@ void bluetooth_setup(bool factory_reset) // Add GAP configuration to the BLE stack ble_cfg_t cfg; cfg.conn_cfg.conn_cfg_tag = 1; - cfg.conn_cfg.params.gap_conn_cfg.conn_count = 1; + cfg.conn_cfg.params.gap_conn_cfg.conn_count = 2; cfg.conn_cfg.params.gap_conn_cfg.event_length = 300; check_error(sd_ble_cfg_set(BLE_CONN_CFG_GAP, &cfg, ram_start)); // Set BLE role to peripheral only memset(&cfg, 0, sizeof(cfg)); cfg.gap_cfg.role_count_cfg.periph_role_count = 1; + cfg.gap_cfg.role_count_cfg.central_role_count = 1; + cfg.gap_cfg.role_count_cfg.central_sec_count = 1; check_error(sd_ble_cfg_set(BLE_GAP_CFG_ROLE_COUNT, &cfg, ram_start)); // Set max MTU size @@ -403,11 +454,11 @@ void bluetooth_setup(bool factory_reset) cfg.gatts_cfg.service_changed.service_changed = 0; check_error(sd_ble_cfg_set(BLE_GATTS_CFG_SERVICE_CHANGED, &cfg, ram_start)); + LOG("Softdevice using 0x%lx bytes of RAM", ram_start - 0x20000000); + // Start the Softdevice check_error(sd_ble_enable(&ram_start)); - LOG("Softdevice using 0x%lx bytes of RAM", ram_start - 0x20000000); - // Set device name ble_gap_conn_sec_mode_t write_permission; BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&write_permission); @@ -564,6 +615,33 @@ void bluetooth_setup(bool factory_reset) // Start advertising check_error(sd_ble_gap_adv_start(ble_handles.advertising, 1)); + + ble_gap_scan_params_t scan_params; + memset(&scan_params, 0, sizeof(scan_params)); + ble_gap_conn_params_t conn_params; + memset(&conn_params, 0, sizeof(conn_params)); + + scan_params.active = 1; + scan_params.interval = NRF_BLE_SCAN_SCAN_INTERVAL; + scan_params.window = NRF_BLE_SCAN_SCAN_WINDOW; + scan_params.timeout = NRF_BLE_SCAN_SCAN_DURATION; + scan_params.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL; + scan_params.scan_phys = BLE_GAP_PHY_1MBPS; + scan_params.extended = 1; + + conn_params.conn_sup_timeout = + (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_SUPERVISION_TIMEOUT, UNIT_10_MS); + conn_params.min_conn_interval = + (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL, UNIT_1_25_MS); + conn_params.max_conn_interval = + (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL, UNIT_1_25_MS); + conn_params.slave_latency = + (uint16_t)NRF_BLE_SCAN_SLAVE_LATENCY; + + scan_buffer.p_data = &scan_buffer_data; + scan_buffer.len = sizeof(scan_buffer_data); + + check_error(sd_ble_gap_scan_start(&scan_params, &scan_buffer)); } bool bluetooth_is_connected(void) diff --git a/source/memory_layout.ld b/source/memory_layout.ld index 749b5919..ca09bf6b 100644 --- a/source/memory_layout.ld +++ b/source/memory_layout.ld @@ -51,7 +51,7 @@ ENTRY(Reset_Handler) MEMORY { APPLICATION_FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0xCE000 - APPLICATION_RAM (rwx) : ORIGIN = 0x20002A08, LENGTH = 256K - 0x2A08 + APPLICATION_RAM (rwx) : ORIGIN = 0x20003c00, LENGTH = 256K - 0x3c00 BOOTLOADER_FLASH (rx) : ORIGIN = 0xF5000, LENGTH = 0x9000 BOOTLOADER_RAM (rwx) : ORIGIN = 0x20002AE8, LENGTH = 256K - 0x2AE8 From b1bbe80f86760a84be97ba9a9e0575098786f170 Mon Sep 17 00:00:00 2001 From: rohitrathnam Date: Tue, 20 Aug 2024 14:35:28 +0530 Subject: [PATCH 02/13] wip scan and list lua func --- source/application/bluetooth.c | 31 +++++++++++---- source/application/bluetooth.h | 7 ++++ source/application/lua_libraries/bluetooth.c | 41 ++++++++++++++++++++ 3 files changed, 71 insertions(+), 8 deletions(-) diff --git a/source/application/bluetooth.c b/source/application/bluetooth.c index 81e9c97d..2266b4e4 100644 --- a/source/application/bluetooth.c +++ b/source/application/bluetooth.c @@ -84,11 +84,11 @@ bool flash_write_in_progress = false; uint16_t ble_negotiated_mtu; -#define APP_BLE_CONN_CFG_TAG 1 +#define APP_BLE_CONN_CFG_TAG 2 // NRF_BLE_SCAN_SCAN_INTERVAL - Scanning interval. Determines the scan interval in units of 0.625 millisecond. #define NRF_BLE_SCAN_SCAN_INTERVAL 160 // NRF_BLE_SCAN_SCAN_DURATION - Duration of a scanning session in units of 10 ms. Range: 0x0001 - 0xFFFF (10 ms to 10.9225 ms). If set to 0x0000, the scanning continues until it is explicitly disabled. -#define NRF_BLE_SCAN_SCAN_DURATION 0 +#define NRF_BLE_SCAN_SCAN_DURATION 300 // NRF_BLE_SCAN_SCAN_WINDOW - Scanning window. Determines the scanning window in units of 0.625 millisecond. #define NRF_BLE_SCAN_SCAN_WINDOW 80 #define NRF_BLE_SCAN_BUFFER 255 @@ -111,8 +111,7 @@ enum UNIT_10_MS = 10000 /**< Number of microseconds in 10 milliseconds. */ }; -static ble_data_t scan_buffer; -static uint8_t scan_buffer_data[NRF_BLE_SCAN_BUFFER]; +uint8_t scan_buffer_data[NRF_BLE_SCAN_BUFFER]; static void softdevice_assert_handler(uint32_t id, uint32_t pc, uint32_t info) { @@ -387,6 +386,23 @@ void SD_EVT_IRQHandler(void) ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr[4], ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr[5] ); + + bool is_unique = true; + for (size_t i=0; ievt.gap_evt.params.adv_report.peer_addr.addr, + scanned_addresses[i].addr, BLE_GAP_ADDR_LEN) == 0) { + is_unique = false; + break; + } + } + + if (is_unique) { + memcpy(&scanned_addresses[scanned_addresses_count].addr, + ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr, + BLE_GAP_ADDR_LEN); + scanned_addresses_count++; + } break; } @@ -616,9 +632,7 @@ void bluetooth_setup(bool factory_reset) // Start advertising check_error(sd_ble_gap_adv_start(ble_handles.advertising, 1)); - ble_gap_scan_params_t scan_params; memset(&scan_params, 0, sizeof(scan_params)); - ble_gap_conn_params_t conn_params; memset(&conn_params, 0, sizeof(conn_params)); scan_params.active = 1; @@ -638,10 +652,11 @@ void bluetooth_setup(bool factory_reset) conn_params.slave_latency = (uint16_t)NRF_BLE_SCAN_SLAVE_LATENCY; - scan_buffer.p_data = &scan_buffer_data; + scan_buffer.p_data = &scan_buffer_data[0]; scan_buffer.len = sizeof(scan_buffer_data); - check_error(sd_ble_gap_scan_start(&scan_params, &scan_buffer)); + memset(&scanned_addresses, 0, sizeof(scanned_addresses)); + scanned_addresses_count = 0; } bool bluetooth_is_connected(void) diff --git a/source/application/bluetooth.h b/source/application/bluetooth.h index b8a919dd..ea029c74 100644 --- a/source/application/bluetooth.h +++ b/source/application/bluetooth.h @@ -27,10 +27,17 @@ #include #include #include +#include "ble.h" #define BLE_PREFERRED_MAX_MTU 256 extern uint16_t ble_negotiated_mtu; +extern ble_gap_scan_params_t scan_params; +extern ble_data_t scan_buffer; +extern ble_gap_conn_params_t conn_params; +extern ble_gap_addr_t scanned_addresses[10]; +extern uint8_t scanned_addresses_count; + void bluetooth_setup(bool factory_reset); bool bluetooth_is_connected(void); diff --git a/source/application/lua_libraries/bluetooth.c b/source/application/lua_libraries/bluetooth.c index 78b19412..1f5a4461 100644 --- a/source/application/lua_libraries/bluetooth.c +++ b/source/application/lua_libraries/bluetooth.c @@ -142,6 +142,41 @@ static int lua_bluetooth_receive_callback(lua_State *L) return 0; } +ble_data_t scan_buffer; +ble_gap_scan_params_t scan_params; +ble_gap_conn_params_t conn_params; + +static int lua_bluetooth_start_scan(lua_State *L) { + uint16_t timeout = luaL_checkinteger(L, 1); + if (timeout <= 0) { + luaL_error(L, "timeout must be greater than 0"); + } + if (timeout <= 0) { + luaL_error(L, "timeout must be less than 10000"); + } + scan_params.timeout = timeout; + // check_error(sd_ble_gap_scan_stop()); + check_error(sd_ble_gap_scan_start(&scan_params, &scan_buffer)); + LOG("Starting scan"); + return 1; +} + +ble_gap_addr_t scanned_addresses[10]; +uint8_t scanned_addresses_count; +static int lua_bluetooth_scan_list(lua_State *L) { + for (size_t i=0; i %x:%x:%x:%x:%x:%x", + i, + scanned_addresses[i].addr[0], + scanned_addresses[i].addr[1], + scanned_addresses[i].addr[2], + scanned_addresses[i].addr[3], + scanned_addresses[i].addr[4], + scanned_addresses[i].addr[5]); + } + return 1; +} + void lua_open_bluetooth_library(lua_State *L) { lua_getglobal(L, "frame"); @@ -163,6 +198,12 @@ void lua_open_bluetooth_library(lua_State *L) lua_pushcfunction(L, lua_bluetooth_receive_callback); lua_setfield(L, -2, "receive_callback"); + lua_pushcfunction(L, lua_bluetooth_start_scan); + lua_setfield(L, -2, "start_scan"); + + lua_pushcfunction(L, lua_bluetooth_scan_list); + lua_setfield(L, -2, "scan_list"); + lua_setfield(L, -2, "bluetooth"); lua_pop(L, 1); From 1e51ba90ec1ffd85445b9564a9e4ef9351e5ce81 Mon Sep 17 00:00:00 2001 From: rohitrathnam Date: Thu, 22 Aug 2024 15:16:57 +0530 Subject: [PATCH 03/13] list mac and name of scanned devices --- source/application/bluetooth.c | 73 +++++++++----------- source/application/bluetooth.h | 57 +++++++++++++-- source/application/lua_libraries/bluetooth.c | 33 ++++----- 3 files changed, 100 insertions(+), 63 deletions(-) diff --git a/source/application/bluetooth.c b/source/application/bluetooth.c index 2266b4e4..93404544 100644 --- a/source/application/bluetooth.c +++ b/source/application/bluetooth.c @@ -378,37 +378,36 @@ void SD_EVT_IRQHandler(void) case BLE_GAP_EVT_ADV_REPORT: { - LOG("Advertisement report: %x %x %x %x %x %x", - ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr[0], - ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr[1], - ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr[2], - ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr[3], - ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr[4], - ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr[5] - ); - + ble_gap_evt_adv_report_t *adv_report = &ble_evt->evt.gap_evt.params.adv_report; bool is_unique = true; - for (size_t i=0; ievt.gap_evt.params.adv_report.peer_addr.addr, - scanned_addresses[i].addr, BLE_GAP_ADDR_LEN) == 0) { - is_unique = false; - break; - } + bool has_name = (adv_report->data.p_data[1] == BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME + || adv_report->data.p_data[1] == BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME); + for (size_t i=0; ipeer_addr.addr, scan_data.address[i].addr, BLE_GAP_ADDR_LEN) == 0) { + is_unique = false; + break; + } } - if (is_unique) { - memcpy(&scanned_addresses[scanned_addresses_count].addr, - ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr, + if (is_unique && has_name) { + memcpy(&scan_data.address[scan_data.len].addr, + adv_report->peer_addr.addr, BLE_GAP_ADDR_LEN); - scanned_addresses_count++; + + // offset 2 to exclude packet size and ad_type + scan_data.name_len[scan_data.len] = adv_report->data.len - 3; + + memcpy(&scan_data.name[scan_data.len], + adv_report->data.p_data+2, + scan_data.name_len[scan_data.len]); + + scan_data.len++; } break; } case BLE_GAP_EVT_TIMEOUT: { - LOG("Scan timed out"); break; } @@ -632,31 +631,27 @@ void bluetooth_setup(bool factory_reset) // Start advertising check_error(sd_ble_gap_adv_start(ble_handles.advertising, 1)); - memset(&scan_params, 0, sizeof(scan_params)); - memset(&conn_params, 0, sizeof(conn_params)); + memset(&scan_data, 0, sizeof(scan_data)); - scan_params.active = 1; - scan_params.interval = NRF_BLE_SCAN_SCAN_INTERVAL; - scan_params.window = NRF_BLE_SCAN_SCAN_WINDOW; - scan_params.timeout = NRF_BLE_SCAN_SCAN_DURATION; - scan_params.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL; - scan_params.scan_phys = BLE_GAP_PHY_1MBPS; - scan_params.extended = 1; + scan_data.scan_params.active = 1; + scan_data.scan_params.interval = NRF_BLE_SCAN_SCAN_INTERVAL; + scan_data.scan_params.window = NRF_BLE_SCAN_SCAN_WINDOW; + scan_data.scan_params.timeout = NRF_BLE_SCAN_SCAN_DURATION; + scan_data.scan_params.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL; + scan_data.scan_params.scan_phys = BLE_GAP_PHY_1MBPS; + scan_data.scan_params.extended = 0; - conn_params.conn_sup_timeout = + scan_data.conn_params.conn_sup_timeout = (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_SUPERVISION_TIMEOUT, UNIT_10_MS); - conn_params.min_conn_interval = + scan_data.conn_params.min_conn_interval = (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL, UNIT_1_25_MS); - conn_params.max_conn_interval = + scan_data.conn_params.max_conn_interval = (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL, UNIT_1_25_MS); - conn_params.slave_latency = + scan_data.conn_params.slave_latency = (uint16_t)NRF_BLE_SCAN_SLAVE_LATENCY; - scan_buffer.p_data = &scan_buffer_data[0]; - scan_buffer.len = sizeof(scan_buffer_data); - - memset(&scanned_addresses, 0, sizeof(scanned_addresses)); - scanned_addresses_count = 0; + scan_data.scan_buffer.p_data = (uint8_t *) &scan_buffer_data; + scan_data.scan_buffer.len = sizeof(scan_buffer_data); } bool bluetooth_is_connected(void) diff --git a/source/application/bluetooth.h b/source/application/bluetooth.h index ea029c74..449bc940 100644 --- a/source/application/bluetooth.h +++ b/source/application/bluetooth.h @@ -32,14 +32,59 @@ #define BLE_PREFERRED_MAX_MTU 256 extern uint16_t ble_negotiated_mtu; -extern ble_gap_scan_params_t scan_params; -extern ble_data_t scan_buffer; -extern ble_gap_conn_params_t conn_params; -extern ble_gap_addr_t scanned_addresses[10]; -extern uint8_t scanned_addresses_count; +#define SCAN_LIST_SIZE 10 +struct scan_data_t { + ble_data_t scan_buffer; + ble_gap_scan_params_t scan_params; + ble_gap_conn_params_t conn_params; + ble_gap_addr_t address[SCAN_LIST_SIZE]; + char name[SCAN_LIST_SIZE][32]; + uint8_t name_len[SCAN_LIST_SIZE]; + uint8_t len; +}; + +extern struct scan_data_t scan_data; void bluetooth_setup(bool factory_reset); bool bluetooth_is_connected(void); -bool bluetooth_send_data(const uint8_t *data, size_t length); \ No newline at end of file +bool bluetooth_send_data(const uint8_t *data, size_t length); + +/* BLE_GAP_AD_TYPE_DEFINITIONS GAP Advertising and Scan Response Data format + * Found at https://www.bluetooth.org/Technical/AssignedNumbers/generic_access_profile.htm + */ +#define BLE_GAP_AD_TYPE_FLAGS 0x01 /**< Flags for discoverability. */ +#define BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE 0x02 /**< Partial list of 16 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE 0x03 /**< Complete list of 16 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE 0x04 /**< Partial list of 32 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_COMPLETE 0x05 /**< Complete list of 32 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE 0x06 /**< Partial list of 128 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE 0x07 /**< Complete list of 128 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME 0x08 /**< Short local device name. */ +#define BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME 0x09 /**< Complete local device name. */ +#define BLE_GAP_AD_TYPE_TX_POWER_LEVEL 0x0A /**< Transmit power level. */ +#define BLE_GAP_AD_TYPE_CLASS_OF_DEVICE 0x0D /**< Class of device. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_HASH_C 0x0E /**< Simple Pairing Hash C. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R 0x0F /**< Simple Pairing Randomizer R. */ +#define BLE_GAP_AD_TYPE_SECURITY_MANAGER_TK_VALUE 0x10 /**< Security Manager TK Value. */ +#define BLE_GAP_AD_TYPE_SECURITY_MANAGER_OOB_FLAGS 0x11 /**< Security Manager Out Of Band Flags. */ +#define BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE 0x12 /**< Slave Connection Interval Range. */ +#define BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT 0x14 /**< List of 16-bit Service Solicitation UUIDs. */ +#define BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT 0x15 /**< List of 128-bit Service Solicitation UUIDs. */ +#define BLE_GAP_AD_TYPE_SERVICE_DATA 0x16 /**< Service Data - 16-bit UUID. */ +#define BLE_GAP_AD_TYPE_PUBLIC_TARGET_ADDRESS 0x17 /**< Public Target Address. */ +#define BLE_GAP_AD_TYPE_RANDOM_TARGET_ADDRESS 0x18 /**< Random Target Address. */ +#define BLE_GAP_AD_TYPE_APPEARANCE 0x19 /**< Appearance. */ +#define BLE_GAP_AD_TYPE_ADVERTISING_INTERVAL 0x1A /**< Advertising Interval. */ +#define BLE_GAP_AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS 0x1B /**< LE Bluetooth Device Address. */ +#define BLE_GAP_AD_TYPE_LE_ROLE 0x1C /**< LE Role. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_HASH_C256 0x1D /**< Simple Pairing Hash C-256. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R256 0x1E /**< Simple Pairing Randomizer R-256. */ +#define BLE_GAP_AD_TYPE_SERVICE_DATA_32BIT_UUID 0x20 /**< Service Data - 32-bit UUID. */ +#define BLE_GAP_AD_TYPE_SERVICE_DATA_128BIT_UUID 0x21 /**< Service Data - 128-bit UUID. */ +#define BLE_GAP_AD_TYPE_LESC_CONFIRMATION_VALUE 0x22 /**< LE Secure Connections Confirmation Value */ +#define BLE_GAP_AD_TYPE_LESC_RANDOM_VALUE 0x23 /**< LE Secure Connections Random Value */ +#define BLE_GAP_AD_TYPE_URI 0x24 /**< URI */ +#define BLE_GAP_AD_TYPE_3D_INFORMATION_DATA 0x3D /**< 3D Information Data. */ +#define BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA 0xFF /**< Manufacturer Specific Data. */ \ No newline at end of file diff --git a/source/application/lua_libraries/bluetooth.c b/source/application/lua_libraries/bluetooth.c index 1f5a4461..c1785553 100644 --- a/source/application/lua_libraries/bluetooth.c +++ b/source/application/lua_libraries/bluetooth.c @@ -31,6 +31,8 @@ #include "lua.h" #include "luaport.h" +struct scan_data_t scan_data; + static int lua_bluetooth_is_connected(lua_State *L) { lua_pushboolean(L, bluetooth_is_connected()); @@ -142,10 +144,6 @@ static int lua_bluetooth_receive_callback(lua_State *L) return 0; } -ble_data_t scan_buffer; -ble_gap_scan_params_t scan_params; -ble_gap_conn_params_t conn_params; - static int lua_bluetooth_start_scan(lua_State *L) { uint16_t timeout = luaL_checkinteger(L, 1); if (timeout <= 0) { @@ -154,25 +152,24 @@ static int lua_bluetooth_start_scan(lua_State *L) { if (timeout <= 0) { luaL_error(L, "timeout must be less than 10000"); } - scan_params.timeout = timeout; - // check_error(sd_ble_gap_scan_stop()); - check_error(sd_ble_gap_scan_start(&scan_params, &scan_buffer)); - LOG("Starting scan"); + scan_data.scan_params.timeout = timeout; + check_error(sd_ble_gap_scan_start(&scan_data.scan_params, &scan_data.scan_buffer)); return 1; } -ble_gap_addr_t scanned_addresses[10]; -uint8_t scanned_addresses_count; static int lua_bluetooth_scan_list(lua_State *L) { - for (size_t i=0; i %x:%x:%x:%x:%x:%x", + for (size_t i=0; i %x:%x:%x:%x:%x:%x - %.*s", i, - scanned_addresses[i].addr[0], - scanned_addresses[i].addr[1], - scanned_addresses[i].addr[2], - scanned_addresses[i].addr[3], - scanned_addresses[i].addr[4], - scanned_addresses[i].addr[5]); + scan_data.address[i].addr[5], + scan_data.address[i].addr[4], + scan_data.address[i].addr[3], + scan_data.address[i].addr[2], + scan_data.address[i].addr[1], + scan_data.address[i].addr[0], + scan_data.name_len[i], + scan_data.name[i] + ); } return 1; } From f94fd328fc08832317019900984170ccd658d2fb Mon Sep 17 00:00:00 2001 From: rohitrathnam Date: Mon, 26 Aug 2024 09:47:07 +0530 Subject: [PATCH 04/13] wip add central cfg tag and connect function --- source/application/bluetooth.c | 40 +++++--------------- source/application/bluetooth.h | 17 +++++++++ source/application/lua_libraries/bluetooth.c | 11 ++++++ source/memory_layout.ld | 2 +- 4 files changed, 39 insertions(+), 31 deletions(-) diff --git a/source/application/bluetooth.c b/source/application/bluetooth.c index 93404544..6369d7e1 100644 --- a/source/application/bluetooth.c +++ b/source/application/bluetooth.c @@ -84,33 +84,6 @@ bool flash_write_in_progress = false; uint16_t ble_negotiated_mtu; -#define APP_BLE_CONN_CFG_TAG 2 -// NRF_BLE_SCAN_SCAN_INTERVAL - Scanning interval. Determines the scan interval in units of 0.625 millisecond. -#define NRF_BLE_SCAN_SCAN_INTERVAL 160 -// NRF_BLE_SCAN_SCAN_DURATION - Duration of a scanning session in units of 10 ms. Range: 0x0001 - 0xFFFF (10 ms to 10.9225 ms). If set to 0x0000, the scanning continues until it is explicitly disabled. -#define NRF_BLE_SCAN_SCAN_DURATION 300 -// NRF_BLE_SCAN_SCAN_WINDOW - Scanning window. Determines the scanning window in units of 0.625 millisecond. -#define NRF_BLE_SCAN_SCAN_WINDOW 80 -#define NRF_BLE_SCAN_BUFFER 255 - -// NRF_BLE_SCAN_SUPERVISION_TIMEOUT - Determines the supervision time-out in units of 10 millisecond. -#define NRF_BLE_SCAN_SUPERVISION_TIMEOUT 6200 -// NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL - Determines minimum connection interval in milliseconds. -#define NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL 100 -// NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL - Determines maximum connection interval in milliseconds. -#define NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL 500 -// NRF_BLE_SCAN_SLAVE_LATENCY - Determines the slave latency in counts of connection events. -#define NRF_BLE_SCAN_SLAVE_LATENCY 5 - -#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) - -enum -{ - UNIT_0_625_MS = 625, /**< Number of microseconds in 0.625 milliseconds. */ - UNIT_1_25_MS = 1250, /**< Number of microseconds in 1.25 milliseconds. */ - UNIT_10_MS = 10000 /**< Number of microseconds in 10 milliseconds. */ -}; - uint8_t scan_buffer_data[NRF_BLE_SCAN_BUFFER]; static void softdevice_assert_handler(uint32_t id, uint32_t pc, uint32_t info) @@ -395,7 +368,7 @@ void SD_EVT_IRQHandler(void) BLE_GAP_ADDR_LEN); // offset 2 to exclude packet size and ad_type - scan_data.name_len[scan_data.len] = adv_report->data.len - 3; + scan_data.name_len[scan_data.len] = adv_report->data.len - 4; memcpy(&scan_data.name[scan_data.len], adv_report->data.p_data+2, @@ -428,14 +401,21 @@ void bluetooth_setup(bool factory_reset) // Enable softdevice interrupt check_error(sd_nvic_EnableIRQ((IRQn_Type)SD_EVT_IRQn)); - // Add GAP configuration to the BLE stack + // Add GAP configuration for peripheral to the BLE stack ble_cfg_t cfg; cfg.conn_cfg.conn_cfg_tag = 1; cfg.conn_cfg.params.gap_conn_cfg.conn_count = 2; cfg.conn_cfg.params.gap_conn_cfg.event_length = 300; check_error(sd_ble_cfg_set(BLE_CONN_CFG_GAP, &cfg, ram_start)); - // Set BLE role to peripheral only + // Add GAP configuration for central to the BLE stack + memset(&cfg, 0, sizeof(cfg)); + cfg.conn_cfg.conn_cfg_tag = 2; + cfg.conn_cfg.params.gap_conn_cfg.conn_count = 1; + cfg.conn_cfg.params.gap_conn_cfg.event_length = BLE_GAP_EVENT_LENGTH_DEFAULT; + check_error(sd_ble_cfg_set(BLE_CONN_CFG_GAP, &cfg, ram_start)); + + // Set BLE role memset(&cfg, 0, sizeof(cfg)); cfg.gap_cfg.role_count_cfg.periph_role_count = 1; cfg.gap_cfg.role_count_cfg.central_role_count = 1; diff --git a/source/application/bluetooth.h b/source/application/bluetooth.h index 449bc940..9c84d182 100644 --- a/source/application/bluetooth.h +++ b/source/application/bluetooth.h @@ -51,6 +51,23 @@ bool bluetooth_is_connected(void); bool bluetooth_send_data(const uint8_t *data, size_t length); +#define NRF_BLE_SCAN_SCAN_INTERVAL 160 // scan interval in units of 0.625 millisecond +#define NRF_BLE_SCAN_SCAN_DURATION 300 // duration of a scanning session in units of 10 ms +#define NRF_BLE_SCAN_SCAN_WINDOW 80 // scanning window in units of 0.625 millisecond +#define NRF_BLE_SCAN_BUFFER 255 // ble scan buffer size +#define NRF_BLE_SCAN_SUPERVISION_TIMEOUT 6200 // supervision time-out in units of 10 millisecond +#define NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL 100 // minimum connection interval in milliseconds +#define NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL 500 // maximum connection interval in milliseconds +#define NRF_BLE_SCAN_SLAVE_LATENCY 5 // slave latency in counts of connection events + +#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) +enum +{ + UNIT_0_625_MS = 625, /**< Number of microseconds in 0.625 milliseconds. */ + UNIT_1_25_MS = 1250, /**< Number of microseconds in 1.25 milliseconds. */ + UNIT_10_MS = 10000 /**< Number of microseconds in 10 milliseconds. */ +}; + /* BLE_GAP_AD_TYPE_DEFINITIONS GAP Advertising and Scan Response Data format * Found at https://www.bluetooth.org/Technical/AssignedNumbers/generic_access_profile.htm */ diff --git a/source/application/lua_libraries/bluetooth.c b/source/application/lua_libraries/bluetooth.c index c1785553..6f4e79e6 100644 --- a/source/application/lua_libraries/bluetooth.c +++ b/source/application/lua_libraries/bluetooth.c @@ -174,6 +174,14 @@ static int lua_bluetooth_scan_list(lua_State *L) { return 1; } +static int lua_bluetooth_connect(lua_State *L) { + uint8_t index = luaL_checkinteger(L, 1); + + check_error(sd_ble_gap_connect(&scan_data.address[index], &scan_data.scan_params, &scan_data.conn_params, 2)); + + return 1; +} + void lua_open_bluetooth_library(lua_State *L) { lua_getglobal(L, "frame"); @@ -201,6 +209,9 @@ void lua_open_bluetooth_library(lua_State *L) lua_pushcfunction(L, lua_bluetooth_scan_list); lua_setfield(L, -2, "scan_list"); + lua_pushcfunction(L, lua_bluetooth_connect); + lua_setfield(L, -2, "connect"); + lua_setfield(L, -2, "bluetooth"); lua_pop(L, 1); diff --git a/source/memory_layout.ld b/source/memory_layout.ld index ca09bf6b..36ec6e1e 100644 --- a/source/memory_layout.ld +++ b/source/memory_layout.ld @@ -51,7 +51,7 @@ ENTRY(Reset_Handler) MEMORY { APPLICATION_FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0xCE000 - APPLICATION_RAM (rwx) : ORIGIN = 0x20003c00, LENGTH = 256K - 0x3c00 + APPLICATION_RAM (rwx) : ORIGIN = 0x20003CA0, LENGTH = 256K - 0x3CA0 BOOTLOADER_FLASH (rx) : ORIGIN = 0xF5000, LENGTH = 0x9000 BOOTLOADER_RAM (rwx) : ORIGIN = 0x20002AE8, LENGTH = 256K - 0x2AE8 From eba8061e5ef8ec180e210fdc548446402d839e77 Mon Sep 17 00:00:00 2001 From: rohitrathnam Date: Tue, 27 Aug 2024 14:32:48 +0530 Subject: [PATCH 05/13] wip central works --- source/application/bluetooth.c | 200 +++++++++++++------ source/application/bluetooth.h | 20 +- source/application/lua_libraries/bluetooth.c | 23 +-- 3 files changed, 154 insertions(+), 89 deletions(-) diff --git a/source/application/bluetooth.c b/source/application/bluetooth.c index 6369d7e1..8669590b 100644 --- a/source/application/bluetooth.c +++ b/source/application/bluetooth.c @@ -39,13 +39,13 @@ nrf_nvic_state_t nrf_nvic_state = {{0}, 0}; extern uint32_t __ram_start; static uint32_t ram_start = (uint32_t)&__ram_start; -static struct ble_handles_t +static struct ble_peripheral_handles_t { uint16_t connection; uint8_t advertising; ble_gatts_char_handles_t repl_rx_write; ble_gatts_char_handles_t repl_tx_notification; -} ble_handles = { +} ble_peripheral_handles = { .connection = BLE_CONN_HANDLE_INVALID, .advertising = BLE_GAP_ADV_SET_HANDLE_NOT_SET, }; @@ -80,6 +80,25 @@ static struct bond_information_t }, }; +typedef struct { + ble_data_t scan_buffer; + ble_gap_scan_params_t scan_params; + ble_gap_conn_params_t conn_params; + ble_gap_addr_t address[SCAN_LIST_SIZE]; + char name[SCAN_LIST_SIZE][32]; + uint8_t name_len[SCAN_LIST_SIZE]; + uint8_t len; +} scan_data_t; + +static struct ble_central_handles_t +{ + uint16_t connection; + scan_data_t scan_data; + ble_data_t rx_data; +} ble_central_handles = { + .connection = BLE_CONN_HANDLE_INVALID, +}; + bool flash_write_in_progress = false; uint16_t ble_negotiated_mtu; @@ -138,41 +157,60 @@ void SD_EVT_IRQHandler(void) case BLE_GAP_EVT_CONNECTED: { - ble_handles.connection = ble_evt - ->evt - .gap_evt - .conn_handle; + if (ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_CENTRAL) + { + ble_central_handles.connection = ble_evt->evt.gap_evt.conn_handle; + } - ble_gap_conn_params_t conn_params; + else + { + ble_peripheral_handles.connection = ble_evt + ->evt + .gap_evt + .conn_handle; - check_error(sd_ble_gap_ppcp_get(&conn_params)); + ble_gap_conn_params_t conn_params; - check_error(sd_ble_gap_conn_param_update(ble_handles.connection, - &conn_params)); + check_error(sd_ble_gap_ppcp_get(&conn_params)); - check_error(sd_ble_gatts_sys_attr_set(ble_handles.connection, - NULL, - 0, - 0)); + check_error(sd_ble_gap_conn_param_update(ble_peripheral_handles.connection, + &conn_params)); - check_error(sd_ble_gap_authenticate(ble_handles.connection, - &bond.sec_param)); + check_error(sd_ble_gatts_sys_attr_set(ble_peripheral_handles.connection, + NULL, + 0, + 0)); + + check_error(sd_ble_gap_authenticate(ble_peripheral_handles.connection, + &bond.sec_param)); + } break; } case BLE_GAP_EVT_DISCONNECTED: { - ble_handles.connection = BLE_CONN_HANDLE_INVALID; + // TODO: need to check disconnect reason? + if (ble_evt->evt.gap_evt.conn_handle == ble_central_handles.connection) + { + ble_central_handles.connection = BLE_CONN_HANDLE_INVALID; - check_error(sd_ble_gap_adv_start(ble_handles.advertising, 1)); + memset(&ble_central_handles.rx_data, 0, sizeof(ble_central_handles.rx_data)); + } + + else if (ble_evt->evt.gap_evt.conn_handle == ble_peripheral_handles.connection) + { + ble_peripheral_handles.connection = BLE_CONN_HANDLE_INVALID; + + check_error(sd_ble_gap_adv_start(ble_peripheral_handles.advertising, 1)); + } break; } case BLE_GAP_EVT_AUTH_KEY_REQUEST: { - check_error(sd_ble_gap_auth_key_reply(ble_handles.connection, + check_error(sd_ble_gap_auth_key_reply(ble_peripheral_handles.connection, BLE_GAP_AUTH_KEY_TYPE_NONE, NULL)); } @@ -201,7 +239,7 @@ void SD_EVT_IRQHandler(void) .client_rx_mtu; // Respond with our max MTU size - sd_ble_gatts_exchange_mtu_reply(ble_handles.connection, + sd_ble_gatts_exchange_mtu_reply(ble_peripheral_handles.connection, BLE_PREFERRED_MAX_MTU); // Choose the smaller MTU as the final length we'll use @@ -217,7 +255,7 @@ void SD_EVT_IRQHandler(void) { // If REPL service if (ble_evt->evt.gatts_evt.params.write.handle == - ble_handles.repl_rx_write.value_handle) + ble_peripheral_handles.repl_rx_write.value_handle) { // Handle raw data if (ble_evt->evt.gatts_evt.params.write.data[0] == 0x01) @@ -250,7 +288,7 @@ void SD_EVT_IRQHandler(void) case BLE_GATTS_EVT_TIMEOUT: { check_error(sd_ble_gap_disconnect( - ble_handles.connection, + ble_peripheral_handles.connection, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION)); break; @@ -258,7 +296,7 @@ void SD_EVT_IRQHandler(void) case BLE_GATTS_EVT_SYS_ATTR_MISSING: { - check_error(sd_ble_gatts_sys_attr_set(ble_handles.connection, + check_error(sd_ble_gatts_sys_attr_set(ble_peripheral_handles.connection, NULL, 0, 0)); @@ -268,7 +306,7 @@ void SD_EVT_IRQHandler(void) case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: { - check_error(sd_ble_gap_data_length_update(ble_handles.connection, + check_error(sd_ble_gap_data_length_update(ble_peripheral_handles.connection, NULL, NULL)); @@ -292,7 +330,7 @@ void SD_EVT_IRQHandler(void) if (bonded == sizeof(bond.keyset.keys_own.p_enc_key->enc_info.ltk)) { check_error(sd_ble_gap_sec_params_reply( - ble_handles.connection, + ble_peripheral_handles.connection, BLE_GAP_SEC_STATUS_SUCCESS, &bond.sec_param, &bond.keyset)); @@ -301,13 +339,13 @@ void SD_EVT_IRQHandler(void) else { check_error(sd_ble_gap_sec_params_reply( - ble_handles.connection, + ble_peripheral_handles.connection, BLE_GAP_SEC_STATUS_AUTH_REQ, NULL, NULL)); check_error(sd_ble_gap_disconnect( - ble_handles.connection, + ble_peripheral_handles.connection, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION)); } @@ -317,7 +355,7 @@ void SD_EVT_IRQHandler(void) case BLE_GAP_EVT_SEC_INFO_REQUEST: { check_error(sd_ble_gap_sec_info_reply( - ble_handles.connection, + ble_peripheral_handles.connection, &bond.keyset.keys_own.p_enc_key->enc_info, NULL, NULL)); @@ -355,26 +393,26 @@ void SD_EVT_IRQHandler(void) bool is_unique = true; bool has_name = (adv_report->data.p_data[1] == BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME || adv_report->data.p_data[1] == BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME); - for (size_t i=0; ipeer_addr.addr, scan_data.address[i].addr, BLE_GAP_ADDR_LEN) == 0) { + for (size_t i=0; ipeer_addr.addr, ble_central_handles.scan_data.address[i].addr, BLE_GAP_ADDR_LEN) == 0) { is_unique = false; break; } } if (is_unique && has_name) { - memcpy(&scan_data.address[scan_data.len].addr, + memcpy(&ble_central_handles.scan_data.address[ble_central_handles.scan_data.len].addr, adv_report->peer_addr.addr, BLE_GAP_ADDR_LEN); // offset 2 to exclude packet size and ad_type - scan_data.name_len[scan_data.len] = adv_report->data.len - 4; + ble_central_handles.scan_data.name_len[ble_central_handles.scan_data.len] = adv_report->data.len - 4; - memcpy(&scan_data.name[scan_data.len], + memcpy(&ble_central_handles.scan_data.name[ble_central_handles.scan_data.len], adv_report->data.p_data+2, - scan_data.name_len[scan_data.len]); + ble_central_handles.scan_data.name_len[ble_central_handles.scan_data.len]); - scan_data.len++; + ble_central_handles.scan_data.len++; } break; } @@ -384,6 +422,24 @@ void SD_EVT_IRQHandler(void) break; } + case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: + { + check_error(sd_ble_gap_conn_param_update(ble_evt->evt.gap_evt.conn_handle, + &ble_evt->evt.gap_evt.params.conn_param_update_request.conn_params)); + break; + } + + case BLE_GATTC_EVT_HVX: + { + LOG("Notification: %u, %x", ble_evt->evt.gattc_evt.params.hvx.len, + ble_evt->evt.gattc_evt.params.hvx.data[0]); + + memcpy(&ble_central_handles.rx_data, &ble_evt->evt.gattc_evt.params.hvx.data, + ble_evt->evt.gattc_evt.params.hvx.len); + + break; + } + default: { LOG("Unhandled BLE event: %u", ble_evt->header.evt_id); @@ -559,12 +615,12 @@ void bluetooth_setup(bool factory_reset) check_error(sd_ble_gatts_characteristic_add(repl_service_handle, &rx_char_md, &rx_attr, - &ble_handles.repl_rx_write)); + &ble_peripheral_handles.repl_rx_write)); check_error(sd_ble_gatts_characteristic_add(repl_service_handle, &tx_char_md, &tx_attr, - &ble_handles.repl_tx_notification)); + &ble_peripheral_handles.repl_tx_notification)); // Add name to advertising payload adv.payload[adv.length++] = strlen((const char *)device_name) + 1; @@ -604,56 +660,56 @@ void bluetooth_setup(bool factory_reset) adv_params.interval = (20 * 1000) / 625; // Configure the advertising set - check_error(sd_ble_gap_adv_set_configure(&ble_handles.advertising, + check_error(sd_ble_gap_adv_set_configure(&ble_peripheral_handles.advertising, &adv_data, &adv_params)); // Start advertising - check_error(sd_ble_gap_adv_start(ble_handles.advertising, 1)); + check_error(sd_ble_gap_adv_start(ble_peripheral_handles.advertising, 1)); - memset(&scan_data, 0, sizeof(scan_data)); + memset(&ble_central_handles.scan_data, 0, sizeof(ble_central_handles.scan_data)); - scan_data.scan_params.active = 1; - scan_data.scan_params.interval = NRF_BLE_SCAN_SCAN_INTERVAL; - scan_data.scan_params.window = NRF_BLE_SCAN_SCAN_WINDOW; - scan_data.scan_params.timeout = NRF_BLE_SCAN_SCAN_DURATION; - scan_data.scan_params.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL; - scan_data.scan_params.scan_phys = BLE_GAP_PHY_1MBPS; - scan_data.scan_params.extended = 0; + ble_central_handles.scan_data.scan_params.active = 1; + ble_central_handles.scan_data.scan_params.interval = NRF_BLE_SCAN_SCAN_INTERVAL; + ble_central_handles.scan_data.scan_params.window = NRF_BLE_SCAN_SCAN_WINDOW; + ble_central_handles.scan_data.scan_params.timeout = NRF_BLE_SCAN_SCAN_DURATION; + ble_central_handles.scan_data.scan_params.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL; + ble_central_handles.scan_data.scan_params.scan_phys = BLE_GAP_PHY_1MBPS; + ble_central_handles.scan_data.scan_params.extended = 0; - scan_data.conn_params.conn_sup_timeout = + ble_central_handles.scan_data.conn_params.conn_sup_timeout = (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_SUPERVISION_TIMEOUT, UNIT_10_MS); - scan_data.conn_params.min_conn_interval = + ble_central_handles.scan_data.conn_params.min_conn_interval = (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL, UNIT_1_25_MS); - scan_data.conn_params.max_conn_interval = + ble_central_handles.scan_data.conn_params.max_conn_interval = (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL, UNIT_1_25_MS); - scan_data.conn_params.slave_latency = + ble_central_handles.scan_data.conn_params.slave_latency = (uint16_t)NRF_BLE_SCAN_SLAVE_LATENCY; - scan_data.scan_buffer.p_data = (uint8_t *) &scan_buffer_data; - scan_data.scan_buffer.len = sizeof(scan_buffer_data); + ble_central_handles.scan_data.scan_buffer.p_data = (uint8_t *) &scan_buffer_data; + ble_central_handles.scan_data.scan_buffer.len = sizeof(scan_buffer_data); } bool bluetooth_is_connected(void) { - return ble_handles.connection == BLE_CONN_HANDLE_INVALID ? false : true; + return ble_peripheral_handles.connection == BLE_CONN_HANDLE_INVALID ? false : true; } bool bluetooth_send_data(const uint8_t *data, size_t length) { - if (ble_handles.connection == BLE_CONN_HANDLE_INVALID) + if (ble_peripheral_handles.connection == BLE_CONN_HANDLE_INVALID) { return true; } // Initialise the handle value parameters ble_gatts_hvx_params_t hvx_params = {0}; - hvx_params.handle = ble_handles.repl_tx_notification.value_handle; + hvx_params.handle = ble_peripheral_handles.repl_tx_notification.value_handle; hvx_params.p_data = data; hvx_params.p_len = (uint16_t *)&length; hvx_params.type = BLE_GATT_HVX_NOTIFICATION; - uint32_t status = sd_ble_gatts_hvx(ble_handles.connection, &hvx_params); + uint32_t status = sd_ble_gatts_hvx(ble_peripheral_handles.connection, &hvx_params); if (status == NRF_SUCCESS) { @@ -662,3 +718,33 @@ bool bluetooth_send_data(const uint8_t *data, size_t length) return true; } + +void blueotooth_start_scan(uint16_t timeout) +{ + ble_central_handles.scan_data.scan_params.timeout = timeout; + check_error(sd_ble_gap_scan_start(&ble_central_handles.scan_data.scan_params, + &ble_central_handles.scan_data.scan_buffer)); +} + +void bluetooth_scan_list() +{ + for (size_t i=0; i %x:%x:%x:%x:%x:%x - %.*s", + i, + ble_central_handles.scan_data.address[i].addr[5], + ble_central_handles.scan_data.address[i].addr[4], + ble_central_handles.scan_data.address[i].addr[3], + ble_central_handles.scan_data.address[i].addr[2], + ble_central_handles.scan_data.address[i].addr[1], + ble_central_handles.scan_data.address[i].addr[0], + ble_central_handles.scan_data.name_len[i], + ble_central_handles.scan_data.name[i] + ); + } +} + +void bluetooth_central_connect(uint8_t index) +{ + check_error(sd_ble_gap_connect(&ble_central_handles.scan_data.address[index], + &ble_central_handles.scan_data.scan_params, &ble_central_handles.scan_data.conn_params, 2)); +} \ No newline at end of file diff --git a/source/application/bluetooth.h b/source/application/bluetooth.h index 9c84d182..e6a8a56e 100644 --- a/source/application/bluetooth.h +++ b/source/application/bluetooth.h @@ -32,25 +32,13 @@ #define BLE_PREFERRED_MAX_MTU 256 extern uint16_t ble_negotiated_mtu; -#define SCAN_LIST_SIZE 10 -struct scan_data_t { - ble_data_t scan_buffer; - ble_gap_scan_params_t scan_params; - ble_gap_conn_params_t conn_params; - ble_gap_addr_t address[SCAN_LIST_SIZE]; - char name[SCAN_LIST_SIZE][32]; - uint8_t name_len[SCAN_LIST_SIZE]; - uint8_t len; -}; - -extern struct scan_data_t scan_data; - void bluetooth_setup(bool factory_reset); bool bluetooth_is_connected(void); bool bluetooth_send_data(const uint8_t *data, size_t length); +#define SCAN_LIST_SIZE 10 #define NRF_BLE_SCAN_SCAN_INTERVAL 160 // scan interval in units of 0.625 millisecond #define NRF_BLE_SCAN_SCAN_DURATION 300 // duration of a scanning session in units of 10 ms #define NRF_BLE_SCAN_SCAN_WINDOW 80 // scanning window in units of 0.625 millisecond @@ -104,4 +92,8 @@ enum #define BLE_GAP_AD_TYPE_LESC_RANDOM_VALUE 0x23 /**< LE Secure Connections Random Value */ #define BLE_GAP_AD_TYPE_URI 0x24 /**< URI */ #define BLE_GAP_AD_TYPE_3D_INFORMATION_DATA 0x3D /**< 3D Information Data. */ -#define BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA 0xFF /**< Manufacturer Specific Data. */ \ No newline at end of file +#define BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA 0xFF /**< Manufacturer Specific Data. */ + +void blueotooth_start_scan(uint16_t timeout); +void bluetooth_scan_list(); +void bluetooth_central_connect(uint8_t index); \ No newline at end of file diff --git a/source/application/lua_libraries/bluetooth.c b/source/application/lua_libraries/bluetooth.c index 6f4e79e6..b6494a85 100644 --- a/source/application/lua_libraries/bluetooth.c +++ b/source/application/lua_libraries/bluetooth.c @@ -31,8 +31,6 @@ #include "lua.h" #include "luaport.h" -struct scan_data_t scan_data; - static int lua_bluetooth_is_connected(lua_State *L) { lua_pushboolean(L, bluetooth_is_connected()); @@ -152,32 +150,21 @@ static int lua_bluetooth_start_scan(lua_State *L) { if (timeout <= 0) { luaL_error(L, "timeout must be less than 10000"); } - scan_data.scan_params.timeout = timeout; - check_error(sd_ble_gap_scan_start(&scan_data.scan_params, &scan_data.scan_buffer)); + return 1; } static int lua_bluetooth_scan_list(lua_State *L) { - for (size_t i=0; i %x:%x:%x:%x:%x:%x - %.*s", - i, - scan_data.address[i].addr[5], - scan_data.address[i].addr[4], - scan_data.address[i].addr[3], - scan_data.address[i].addr[2], - scan_data.address[i].addr[1], - scan_data.address[i].addr[0], - scan_data.name_len[i], - scan_data.name[i] - ); - } + + bluetooth_scan_list(); + return 1; } static int lua_bluetooth_connect(lua_State *L) { uint8_t index = luaL_checkinteger(L, 1); - check_error(sd_ble_gap_connect(&scan_data.address[index], &scan_data.scan_params, &scan_data.conn_params, 2)); + bluetooth_central_connect(index); return 1; } From b624ebe799350339e6673b270770c338f32dcc1b Mon Sep 17 00:00:00 2001 From: rohitrathnam Date: Wed, 28 Aug 2024 12:21:01 +0530 Subject: [PATCH 06/13] Revert "wip central works" This reverts commit eba8061e5ef8ec180e210fdc548446402d839e77. --- source/application/bluetooth.c | 200 ++++++------------- source/application/bluetooth.h | 20 +- source/application/lua_libraries/bluetooth.c | 23 ++- 3 files changed, 89 insertions(+), 154 deletions(-) diff --git a/source/application/bluetooth.c b/source/application/bluetooth.c index 8669590b..6369d7e1 100644 --- a/source/application/bluetooth.c +++ b/source/application/bluetooth.c @@ -39,13 +39,13 @@ nrf_nvic_state_t nrf_nvic_state = {{0}, 0}; extern uint32_t __ram_start; static uint32_t ram_start = (uint32_t)&__ram_start; -static struct ble_peripheral_handles_t +static struct ble_handles_t { uint16_t connection; uint8_t advertising; ble_gatts_char_handles_t repl_rx_write; ble_gatts_char_handles_t repl_tx_notification; -} ble_peripheral_handles = { +} ble_handles = { .connection = BLE_CONN_HANDLE_INVALID, .advertising = BLE_GAP_ADV_SET_HANDLE_NOT_SET, }; @@ -80,25 +80,6 @@ static struct bond_information_t }, }; -typedef struct { - ble_data_t scan_buffer; - ble_gap_scan_params_t scan_params; - ble_gap_conn_params_t conn_params; - ble_gap_addr_t address[SCAN_LIST_SIZE]; - char name[SCAN_LIST_SIZE][32]; - uint8_t name_len[SCAN_LIST_SIZE]; - uint8_t len; -} scan_data_t; - -static struct ble_central_handles_t -{ - uint16_t connection; - scan_data_t scan_data; - ble_data_t rx_data; -} ble_central_handles = { - .connection = BLE_CONN_HANDLE_INVALID, -}; - bool flash_write_in_progress = false; uint16_t ble_negotiated_mtu; @@ -157,60 +138,41 @@ void SD_EVT_IRQHandler(void) case BLE_GAP_EVT_CONNECTED: { - if (ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_CENTRAL) - { - ble_central_handles.connection = ble_evt->evt.gap_evt.conn_handle; - } - - else - { - ble_peripheral_handles.connection = ble_evt - ->evt - .gap_evt - .conn_handle; + ble_handles.connection = ble_evt + ->evt + .gap_evt + .conn_handle; - ble_gap_conn_params_t conn_params; + ble_gap_conn_params_t conn_params; - check_error(sd_ble_gap_ppcp_get(&conn_params)); + check_error(sd_ble_gap_ppcp_get(&conn_params)); - check_error(sd_ble_gap_conn_param_update(ble_peripheral_handles.connection, - &conn_params)); + check_error(sd_ble_gap_conn_param_update(ble_handles.connection, + &conn_params)); - check_error(sd_ble_gatts_sys_attr_set(ble_peripheral_handles.connection, - NULL, - 0, - 0)); + check_error(sd_ble_gatts_sys_attr_set(ble_handles.connection, + NULL, + 0, + 0)); - check_error(sd_ble_gap_authenticate(ble_peripheral_handles.connection, - &bond.sec_param)); - } + check_error(sd_ble_gap_authenticate(ble_handles.connection, + &bond.sec_param)); break; } case BLE_GAP_EVT_DISCONNECTED: { - // TODO: need to check disconnect reason? - if (ble_evt->evt.gap_evt.conn_handle == ble_central_handles.connection) - { - ble_central_handles.connection = BLE_CONN_HANDLE_INVALID; + ble_handles.connection = BLE_CONN_HANDLE_INVALID; - memset(&ble_central_handles.rx_data, 0, sizeof(ble_central_handles.rx_data)); - } - - else if (ble_evt->evt.gap_evt.conn_handle == ble_peripheral_handles.connection) - { - ble_peripheral_handles.connection = BLE_CONN_HANDLE_INVALID; - - check_error(sd_ble_gap_adv_start(ble_peripheral_handles.advertising, 1)); - } + check_error(sd_ble_gap_adv_start(ble_handles.advertising, 1)); break; } case BLE_GAP_EVT_AUTH_KEY_REQUEST: { - check_error(sd_ble_gap_auth_key_reply(ble_peripheral_handles.connection, + check_error(sd_ble_gap_auth_key_reply(ble_handles.connection, BLE_GAP_AUTH_KEY_TYPE_NONE, NULL)); } @@ -239,7 +201,7 @@ void SD_EVT_IRQHandler(void) .client_rx_mtu; // Respond with our max MTU size - sd_ble_gatts_exchange_mtu_reply(ble_peripheral_handles.connection, + sd_ble_gatts_exchange_mtu_reply(ble_handles.connection, BLE_PREFERRED_MAX_MTU); // Choose the smaller MTU as the final length we'll use @@ -255,7 +217,7 @@ void SD_EVT_IRQHandler(void) { // If REPL service if (ble_evt->evt.gatts_evt.params.write.handle == - ble_peripheral_handles.repl_rx_write.value_handle) + ble_handles.repl_rx_write.value_handle) { // Handle raw data if (ble_evt->evt.gatts_evt.params.write.data[0] == 0x01) @@ -288,7 +250,7 @@ void SD_EVT_IRQHandler(void) case BLE_GATTS_EVT_TIMEOUT: { check_error(sd_ble_gap_disconnect( - ble_peripheral_handles.connection, + ble_handles.connection, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION)); break; @@ -296,7 +258,7 @@ void SD_EVT_IRQHandler(void) case BLE_GATTS_EVT_SYS_ATTR_MISSING: { - check_error(sd_ble_gatts_sys_attr_set(ble_peripheral_handles.connection, + check_error(sd_ble_gatts_sys_attr_set(ble_handles.connection, NULL, 0, 0)); @@ -306,7 +268,7 @@ void SD_EVT_IRQHandler(void) case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: { - check_error(sd_ble_gap_data_length_update(ble_peripheral_handles.connection, + check_error(sd_ble_gap_data_length_update(ble_handles.connection, NULL, NULL)); @@ -330,7 +292,7 @@ void SD_EVT_IRQHandler(void) if (bonded == sizeof(bond.keyset.keys_own.p_enc_key->enc_info.ltk)) { check_error(sd_ble_gap_sec_params_reply( - ble_peripheral_handles.connection, + ble_handles.connection, BLE_GAP_SEC_STATUS_SUCCESS, &bond.sec_param, &bond.keyset)); @@ -339,13 +301,13 @@ void SD_EVT_IRQHandler(void) else { check_error(sd_ble_gap_sec_params_reply( - ble_peripheral_handles.connection, + ble_handles.connection, BLE_GAP_SEC_STATUS_AUTH_REQ, NULL, NULL)); check_error(sd_ble_gap_disconnect( - ble_peripheral_handles.connection, + ble_handles.connection, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION)); } @@ -355,7 +317,7 @@ void SD_EVT_IRQHandler(void) case BLE_GAP_EVT_SEC_INFO_REQUEST: { check_error(sd_ble_gap_sec_info_reply( - ble_peripheral_handles.connection, + ble_handles.connection, &bond.keyset.keys_own.p_enc_key->enc_info, NULL, NULL)); @@ -393,26 +355,26 @@ void SD_EVT_IRQHandler(void) bool is_unique = true; bool has_name = (adv_report->data.p_data[1] == BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME || adv_report->data.p_data[1] == BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME); - for (size_t i=0; ipeer_addr.addr, ble_central_handles.scan_data.address[i].addr, BLE_GAP_ADDR_LEN) == 0) { + for (size_t i=0; ipeer_addr.addr, scan_data.address[i].addr, BLE_GAP_ADDR_LEN) == 0) { is_unique = false; break; } } if (is_unique && has_name) { - memcpy(&ble_central_handles.scan_data.address[ble_central_handles.scan_data.len].addr, + memcpy(&scan_data.address[scan_data.len].addr, adv_report->peer_addr.addr, BLE_GAP_ADDR_LEN); // offset 2 to exclude packet size and ad_type - ble_central_handles.scan_data.name_len[ble_central_handles.scan_data.len] = adv_report->data.len - 4; + scan_data.name_len[scan_data.len] = adv_report->data.len - 4; - memcpy(&ble_central_handles.scan_data.name[ble_central_handles.scan_data.len], + memcpy(&scan_data.name[scan_data.len], adv_report->data.p_data+2, - ble_central_handles.scan_data.name_len[ble_central_handles.scan_data.len]); + scan_data.name_len[scan_data.len]); - ble_central_handles.scan_data.len++; + scan_data.len++; } break; } @@ -422,24 +384,6 @@ void SD_EVT_IRQHandler(void) break; } - case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: - { - check_error(sd_ble_gap_conn_param_update(ble_evt->evt.gap_evt.conn_handle, - &ble_evt->evt.gap_evt.params.conn_param_update_request.conn_params)); - break; - } - - case BLE_GATTC_EVT_HVX: - { - LOG("Notification: %u, %x", ble_evt->evt.gattc_evt.params.hvx.len, - ble_evt->evt.gattc_evt.params.hvx.data[0]); - - memcpy(&ble_central_handles.rx_data, &ble_evt->evt.gattc_evt.params.hvx.data, - ble_evt->evt.gattc_evt.params.hvx.len); - - break; - } - default: { LOG("Unhandled BLE event: %u", ble_evt->header.evt_id); @@ -615,12 +559,12 @@ void bluetooth_setup(bool factory_reset) check_error(sd_ble_gatts_characteristic_add(repl_service_handle, &rx_char_md, &rx_attr, - &ble_peripheral_handles.repl_rx_write)); + &ble_handles.repl_rx_write)); check_error(sd_ble_gatts_characteristic_add(repl_service_handle, &tx_char_md, &tx_attr, - &ble_peripheral_handles.repl_tx_notification)); + &ble_handles.repl_tx_notification)); // Add name to advertising payload adv.payload[adv.length++] = strlen((const char *)device_name) + 1; @@ -660,56 +604,56 @@ void bluetooth_setup(bool factory_reset) adv_params.interval = (20 * 1000) / 625; // Configure the advertising set - check_error(sd_ble_gap_adv_set_configure(&ble_peripheral_handles.advertising, + check_error(sd_ble_gap_adv_set_configure(&ble_handles.advertising, &adv_data, &adv_params)); // Start advertising - check_error(sd_ble_gap_adv_start(ble_peripheral_handles.advertising, 1)); + check_error(sd_ble_gap_adv_start(ble_handles.advertising, 1)); - memset(&ble_central_handles.scan_data, 0, sizeof(ble_central_handles.scan_data)); + memset(&scan_data, 0, sizeof(scan_data)); - ble_central_handles.scan_data.scan_params.active = 1; - ble_central_handles.scan_data.scan_params.interval = NRF_BLE_SCAN_SCAN_INTERVAL; - ble_central_handles.scan_data.scan_params.window = NRF_BLE_SCAN_SCAN_WINDOW; - ble_central_handles.scan_data.scan_params.timeout = NRF_BLE_SCAN_SCAN_DURATION; - ble_central_handles.scan_data.scan_params.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL; - ble_central_handles.scan_data.scan_params.scan_phys = BLE_GAP_PHY_1MBPS; - ble_central_handles.scan_data.scan_params.extended = 0; + scan_data.scan_params.active = 1; + scan_data.scan_params.interval = NRF_BLE_SCAN_SCAN_INTERVAL; + scan_data.scan_params.window = NRF_BLE_SCAN_SCAN_WINDOW; + scan_data.scan_params.timeout = NRF_BLE_SCAN_SCAN_DURATION; + scan_data.scan_params.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL; + scan_data.scan_params.scan_phys = BLE_GAP_PHY_1MBPS; + scan_data.scan_params.extended = 0; - ble_central_handles.scan_data.conn_params.conn_sup_timeout = + scan_data.conn_params.conn_sup_timeout = (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_SUPERVISION_TIMEOUT, UNIT_10_MS); - ble_central_handles.scan_data.conn_params.min_conn_interval = + scan_data.conn_params.min_conn_interval = (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL, UNIT_1_25_MS); - ble_central_handles.scan_data.conn_params.max_conn_interval = + scan_data.conn_params.max_conn_interval = (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL, UNIT_1_25_MS); - ble_central_handles.scan_data.conn_params.slave_latency = + scan_data.conn_params.slave_latency = (uint16_t)NRF_BLE_SCAN_SLAVE_LATENCY; - ble_central_handles.scan_data.scan_buffer.p_data = (uint8_t *) &scan_buffer_data; - ble_central_handles.scan_data.scan_buffer.len = sizeof(scan_buffer_data); + scan_data.scan_buffer.p_data = (uint8_t *) &scan_buffer_data; + scan_data.scan_buffer.len = sizeof(scan_buffer_data); } bool bluetooth_is_connected(void) { - return ble_peripheral_handles.connection == BLE_CONN_HANDLE_INVALID ? false : true; + return ble_handles.connection == BLE_CONN_HANDLE_INVALID ? false : true; } bool bluetooth_send_data(const uint8_t *data, size_t length) { - if (ble_peripheral_handles.connection == BLE_CONN_HANDLE_INVALID) + if (ble_handles.connection == BLE_CONN_HANDLE_INVALID) { return true; } // Initialise the handle value parameters ble_gatts_hvx_params_t hvx_params = {0}; - hvx_params.handle = ble_peripheral_handles.repl_tx_notification.value_handle; + hvx_params.handle = ble_handles.repl_tx_notification.value_handle; hvx_params.p_data = data; hvx_params.p_len = (uint16_t *)&length; hvx_params.type = BLE_GATT_HVX_NOTIFICATION; - uint32_t status = sd_ble_gatts_hvx(ble_peripheral_handles.connection, &hvx_params); + uint32_t status = sd_ble_gatts_hvx(ble_handles.connection, &hvx_params); if (status == NRF_SUCCESS) { @@ -718,33 +662,3 @@ bool bluetooth_send_data(const uint8_t *data, size_t length) return true; } - -void blueotooth_start_scan(uint16_t timeout) -{ - ble_central_handles.scan_data.scan_params.timeout = timeout; - check_error(sd_ble_gap_scan_start(&ble_central_handles.scan_data.scan_params, - &ble_central_handles.scan_data.scan_buffer)); -} - -void bluetooth_scan_list() -{ - for (size_t i=0; i %x:%x:%x:%x:%x:%x - %.*s", - i, - ble_central_handles.scan_data.address[i].addr[5], - ble_central_handles.scan_data.address[i].addr[4], - ble_central_handles.scan_data.address[i].addr[3], - ble_central_handles.scan_data.address[i].addr[2], - ble_central_handles.scan_data.address[i].addr[1], - ble_central_handles.scan_data.address[i].addr[0], - ble_central_handles.scan_data.name_len[i], - ble_central_handles.scan_data.name[i] - ); - } -} - -void bluetooth_central_connect(uint8_t index) -{ - check_error(sd_ble_gap_connect(&ble_central_handles.scan_data.address[index], - &ble_central_handles.scan_data.scan_params, &ble_central_handles.scan_data.conn_params, 2)); -} \ No newline at end of file diff --git a/source/application/bluetooth.h b/source/application/bluetooth.h index e6a8a56e..9c84d182 100644 --- a/source/application/bluetooth.h +++ b/source/application/bluetooth.h @@ -32,13 +32,25 @@ #define BLE_PREFERRED_MAX_MTU 256 extern uint16_t ble_negotiated_mtu; +#define SCAN_LIST_SIZE 10 +struct scan_data_t { + ble_data_t scan_buffer; + ble_gap_scan_params_t scan_params; + ble_gap_conn_params_t conn_params; + ble_gap_addr_t address[SCAN_LIST_SIZE]; + char name[SCAN_LIST_SIZE][32]; + uint8_t name_len[SCAN_LIST_SIZE]; + uint8_t len; +}; + +extern struct scan_data_t scan_data; + void bluetooth_setup(bool factory_reset); bool bluetooth_is_connected(void); bool bluetooth_send_data(const uint8_t *data, size_t length); -#define SCAN_LIST_SIZE 10 #define NRF_BLE_SCAN_SCAN_INTERVAL 160 // scan interval in units of 0.625 millisecond #define NRF_BLE_SCAN_SCAN_DURATION 300 // duration of a scanning session in units of 10 ms #define NRF_BLE_SCAN_SCAN_WINDOW 80 // scanning window in units of 0.625 millisecond @@ -92,8 +104,4 @@ enum #define BLE_GAP_AD_TYPE_LESC_RANDOM_VALUE 0x23 /**< LE Secure Connections Random Value */ #define BLE_GAP_AD_TYPE_URI 0x24 /**< URI */ #define BLE_GAP_AD_TYPE_3D_INFORMATION_DATA 0x3D /**< 3D Information Data. */ -#define BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA 0xFF /**< Manufacturer Specific Data. */ - -void blueotooth_start_scan(uint16_t timeout); -void bluetooth_scan_list(); -void bluetooth_central_connect(uint8_t index); \ No newline at end of file +#define BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA 0xFF /**< Manufacturer Specific Data. */ \ No newline at end of file diff --git a/source/application/lua_libraries/bluetooth.c b/source/application/lua_libraries/bluetooth.c index b6494a85..6f4e79e6 100644 --- a/source/application/lua_libraries/bluetooth.c +++ b/source/application/lua_libraries/bluetooth.c @@ -31,6 +31,8 @@ #include "lua.h" #include "luaport.h" +struct scan_data_t scan_data; + static int lua_bluetooth_is_connected(lua_State *L) { lua_pushboolean(L, bluetooth_is_connected()); @@ -150,21 +152,32 @@ static int lua_bluetooth_start_scan(lua_State *L) { if (timeout <= 0) { luaL_error(L, "timeout must be less than 10000"); } - + scan_data.scan_params.timeout = timeout; + check_error(sd_ble_gap_scan_start(&scan_data.scan_params, &scan_data.scan_buffer)); return 1; } static int lua_bluetooth_scan_list(lua_State *L) { - - bluetooth_scan_list(); - + for (size_t i=0; i %x:%x:%x:%x:%x:%x - %.*s", + i, + scan_data.address[i].addr[5], + scan_data.address[i].addr[4], + scan_data.address[i].addr[3], + scan_data.address[i].addr[2], + scan_data.address[i].addr[1], + scan_data.address[i].addr[0], + scan_data.name_len[i], + scan_data.name[i] + ); + } return 1; } static int lua_bluetooth_connect(lua_State *L) { uint8_t index = luaL_checkinteger(L, 1); - bluetooth_central_connect(index); + check_error(sd_ble_gap_connect(&scan_data.address[index], &scan_data.scan_params, &scan_data.conn_params, 2)); return 1; } From e40fd904fbccb42e2c479443402b1065cf32757b Mon Sep 17 00:00:00 2001 From: rohitrathnam Date: Wed, 28 Aug 2024 12:29:06 +0530 Subject: [PATCH 07/13] wrap peripheral events in if --- source/application/bluetooth.c | 78 ++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/source/application/bluetooth.c b/source/application/bluetooth.c index 6369d7e1..22063012 100644 --- a/source/application/bluetooth.c +++ b/source/application/bluetooth.c @@ -39,13 +39,13 @@ nrf_nvic_state_t nrf_nvic_state = {{0}, 0}; extern uint32_t __ram_start; static uint32_t ram_start = (uint32_t)&__ram_start; -static struct ble_handles_t +static struct ble_peripheral_handles_t { uint16_t connection; uint8_t advertising; ble_gatts_char_handles_t repl_rx_write; ble_gatts_char_handles_t repl_tx_notification; -} ble_handles = { +} ble_peripheral_handles = { .connection = BLE_CONN_HANDLE_INVALID, .advertising = BLE_GAP_ADV_SET_HANDLE_NOT_SET, }; @@ -138,41 +138,47 @@ void SD_EVT_IRQHandler(void) case BLE_GAP_EVT_CONNECTED: { - ble_handles.connection = ble_evt - ->evt - .gap_evt - .conn_handle; + if (ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_PERIPH) + { + ble_peripheral_handles.connection = ble_evt + ->evt + .gap_evt + .conn_handle; - ble_gap_conn_params_t conn_params; + ble_gap_conn_params_t conn_params; - check_error(sd_ble_gap_ppcp_get(&conn_params)); + check_error(sd_ble_gap_ppcp_get(&conn_params)); - check_error(sd_ble_gap_conn_param_update(ble_handles.connection, - &conn_params)); + check_error(sd_ble_gap_conn_param_update(ble_peripheral_handles.connection, + &conn_params)); - check_error(sd_ble_gatts_sys_attr_set(ble_handles.connection, - NULL, - 0, - 0)); + check_error(sd_ble_gatts_sys_attr_set(ble_peripheral_handles.connection, + NULL, + 0, + 0)); - check_error(sd_ble_gap_authenticate(ble_handles.connection, - &bond.sec_param)); + check_error(sd_ble_gap_authenticate(ble_peripheral_handles.connection, + &bond.sec_param)); + } break; } case BLE_GAP_EVT_DISCONNECTED: { - ble_handles.connection = BLE_CONN_HANDLE_INVALID; + if (ble_evt->evt.gap_evt.conn_handle == ble_peripheral_handles.connection) + { + ble_peripheral_handles.connection = BLE_CONN_HANDLE_INVALID; - check_error(sd_ble_gap_adv_start(ble_handles.advertising, 1)); + check_error(sd_ble_gap_adv_start(ble_peripheral_handles.advertising, 1)); + } break; } case BLE_GAP_EVT_AUTH_KEY_REQUEST: { - check_error(sd_ble_gap_auth_key_reply(ble_handles.connection, + check_error(sd_ble_gap_auth_key_reply(ble_peripheral_handles.connection, BLE_GAP_AUTH_KEY_TYPE_NONE, NULL)); } @@ -201,7 +207,7 @@ void SD_EVT_IRQHandler(void) .client_rx_mtu; // Respond with our max MTU size - sd_ble_gatts_exchange_mtu_reply(ble_handles.connection, + sd_ble_gatts_exchange_mtu_reply(ble_peripheral_handles.connection, BLE_PREFERRED_MAX_MTU); // Choose the smaller MTU as the final length we'll use @@ -217,7 +223,7 @@ void SD_EVT_IRQHandler(void) { // If REPL service if (ble_evt->evt.gatts_evt.params.write.handle == - ble_handles.repl_rx_write.value_handle) + ble_peripheral_handles.repl_rx_write.value_handle) { // Handle raw data if (ble_evt->evt.gatts_evt.params.write.data[0] == 0x01) @@ -250,7 +256,7 @@ void SD_EVT_IRQHandler(void) case BLE_GATTS_EVT_TIMEOUT: { check_error(sd_ble_gap_disconnect( - ble_handles.connection, + ble_peripheral_handles.connection, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION)); break; @@ -258,7 +264,7 @@ void SD_EVT_IRQHandler(void) case BLE_GATTS_EVT_SYS_ATTR_MISSING: { - check_error(sd_ble_gatts_sys_attr_set(ble_handles.connection, + check_error(sd_ble_gatts_sys_attr_set(ble_peripheral_handles.connection, NULL, 0, 0)); @@ -268,7 +274,7 @@ void SD_EVT_IRQHandler(void) case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: { - check_error(sd_ble_gap_data_length_update(ble_handles.connection, + check_error(sd_ble_gap_data_length_update(ble_peripheral_handles.connection, NULL, NULL)); @@ -292,7 +298,7 @@ void SD_EVT_IRQHandler(void) if (bonded == sizeof(bond.keyset.keys_own.p_enc_key->enc_info.ltk)) { check_error(sd_ble_gap_sec_params_reply( - ble_handles.connection, + ble_peripheral_handles.connection, BLE_GAP_SEC_STATUS_SUCCESS, &bond.sec_param, &bond.keyset)); @@ -301,13 +307,13 @@ void SD_EVT_IRQHandler(void) else { check_error(sd_ble_gap_sec_params_reply( - ble_handles.connection, + ble_peripheral_handles.connection, BLE_GAP_SEC_STATUS_AUTH_REQ, NULL, NULL)); check_error(sd_ble_gap_disconnect( - ble_handles.connection, + ble_peripheral_handles.connection, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION)); } @@ -317,7 +323,7 @@ void SD_EVT_IRQHandler(void) case BLE_GAP_EVT_SEC_INFO_REQUEST: { check_error(sd_ble_gap_sec_info_reply( - ble_handles.connection, + ble_peripheral_handles.connection, &bond.keyset.keys_own.p_enc_key->enc_info, NULL, NULL)); @@ -559,12 +565,12 @@ void bluetooth_setup(bool factory_reset) check_error(sd_ble_gatts_characteristic_add(repl_service_handle, &rx_char_md, &rx_attr, - &ble_handles.repl_rx_write)); + &ble_peripheral_handles.repl_rx_write)); check_error(sd_ble_gatts_characteristic_add(repl_service_handle, &tx_char_md, &tx_attr, - &ble_handles.repl_tx_notification)); + &ble_peripheral_handles.repl_tx_notification)); // Add name to advertising payload adv.payload[adv.length++] = strlen((const char *)device_name) + 1; @@ -604,12 +610,12 @@ void bluetooth_setup(bool factory_reset) adv_params.interval = (20 * 1000) / 625; // Configure the advertising set - check_error(sd_ble_gap_adv_set_configure(&ble_handles.advertising, + check_error(sd_ble_gap_adv_set_configure(&ble_peripheral_handles.advertising, &adv_data, &adv_params)); // Start advertising - check_error(sd_ble_gap_adv_start(ble_handles.advertising, 1)); + check_error(sd_ble_gap_adv_start(ble_peripheral_handles.advertising, 1)); memset(&scan_data, 0, sizeof(scan_data)); @@ -636,24 +642,24 @@ void bluetooth_setup(bool factory_reset) bool bluetooth_is_connected(void) { - return ble_handles.connection == BLE_CONN_HANDLE_INVALID ? false : true; + return ble_peripheral_handles.connection == BLE_CONN_HANDLE_INVALID ? false : true; } bool bluetooth_send_data(const uint8_t *data, size_t length) { - if (ble_handles.connection == BLE_CONN_HANDLE_INVALID) + if (ble_peripheral_handles.connection == BLE_CONN_HANDLE_INVALID) { return true; } // Initialise the handle value parameters ble_gatts_hvx_params_t hvx_params = {0}; - hvx_params.handle = ble_handles.repl_tx_notification.value_handle; + hvx_params.handle = ble_peripheral_handles.repl_tx_notification.value_handle; hvx_params.p_data = data; hvx_params.p_len = (uint16_t *)&length; hvx_params.type = BLE_GATT_HVX_NOTIFICATION; - uint32_t status = sd_ble_gatts_hvx(ble_handles.connection, &hvx_params); + uint32_t status = sd_ble_gatts_hvx(ble_peripheral_handles.connection, &hvx_params); if (status == NRF_SUCCESS) { From de88c735c952bb1b542c632dfeecb388862fc06e Mon Sep 17 00:00:00 2001 From: rohitrathnam Date: Wed, 28 Aug 2024 14:08:03 +0530 Subject: [PATCH 08/13] handle hvx and param update --- source/application/bluetooth.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/source/application/bluetooth.c b/source/application/bluetooth.c index 22063012..134d694f 100644 --- a/source/application/bluetooth.c +++ b/source/application/bluetooth.c @@ -161,6 +161,9 @@ void SD_EVT_IRQHandler(void) &bond.sec_param)); } + if (ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_CENTRAL) + LOG("central connected"); + break; } @@ -390,6 +393,21 @@ void SD_EVT_IRQHandler(void) break; } + case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: + { + sd_ble_gap_conn_param_update(ble_evt->evt.gap_evt.conn_handle, + &ble_evt->evt.gap_evt.params.conn_param_update_request.conn_params); + + break; + } + + case BLE_GATTC_EVT_HVX: + { + LOG("data: %.2x %.2x", ble_evt->evt.gattc_evt.params.hvx.data[0], ble_evt->evt.gattc_evt.params.hvx.data[0]); + + break; + } + default: { LOG("Unhandled BLE event: %u", ble_evt->header.evt_id); From 64e3595d513d11f80eb68ad4f4c1aaef73fc3044 Mon Sep 17 00:00:00 2001 From: rohitrathnam Date: Wed, 28 Aug 2024 14:58:44 +0530 Subject: [PATCH 09/13] return scanned list from lua --- source/application/lua_libraries/bluetooth.c | 35 ++++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/source/application/lua_libraries/bluetooth.c b/source/application/lua_libraries/bluetooth.c index 6f4e79e6..1b6ec72b 100644 --- a/source/application/lua_libraries/bluetooth.c +++ b/source/application/lua_libraries/bluetooth.c @@ -158,19 +158,40 @@ static int lua_bluetooth_start_scan(lua_State *L) { } static int lua_bluetooth_scan_list(lua_State *L) { + + lua_newtable(L); + + char mac_address[18]; + char name[32]; + for (size_t i=0; i %x:%x:%x:%x:%x:%x - %.*s", + + lua_newtable(L); + + { + sprintf(mac_address, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", scan_data.address[i].addr[5], + scan_data.address[i].addr[4], scan_data.address[i].addr[3], scan_data.address[i].addr[2], + scan_data.address[i].addr[1], scan_data.address[i].addr[0]); + + sprintf(name, "%.*s", scan_data.name_len[i], scan_data.name[i]); + + lua_pushstring(L, mac_address); + lua_setfield(L, -2, "mac"); + + lua_pushstring(L, name); + lua_setfield(L, -2, "name"); + } + + lua_seti(L, -2, i); + + LOG("%d -> %.17s - %.*s", i, - scan_data.address[i].addr[5], - scan_data.address[i].addr[4], - scan_data.address[i].addr[3], - scan_data.address[i].addr[2], - scan_data.address[i].addr[1], - scan_data.address[i].addr[0], + mac_address, scan_data.name_len[i], scan_data.name[i] ); } + return 1; } From f9dabc53b61632e4199050ce6d42db9708fb66e7 Mon Sep 17 00:00:00 2001 From: rohitrathnam Date: Wed, 28 Aug 2024 14:59:03 +0530 Subject: [PATCH 10/13] retry connection --- source/application/bluetooth.c | 9 ++++++++- source/application/bluetooth.h | 2 ++ source/application/lua_libraries/bluetooth.c | 19 ++++++++++++++++++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/source/application/bluetooth.c b/source/application/bluetooth.c index 134d694f..1cc367b1 100644 --- a/source/application/bluetooth.c +++ b/source/application/bluetooth.c @@ -162,7 +162,9 @@ void SD_EVT_IRQHandler(void) } if (ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_CENTRAL) - LOG("central connected"); + { + central_conn_handle = ble_evt->evt.gap_evt.conn_handle; + } break; } @@ -176,6 +178,11 @@ void SD_EVT_IRQHandler(void) check_error(sd_ble_gap_adv_start(ble_peripheral_handles.advertising, 1)); } + if (ble_evt->evt.gap_evt.conn_handle == central_conn_handle) + { + central_conn_handle = BLE_CONN_HANDLE_INVALID; + } + break; } diff --git a/source/application/bluetooth.h b/source/application/bluetooth.h index 9c84d182..7af5e122 100644 --- a/source/application/bluetooth.h +++ b/source/application/bluetooth.h @@ -45,6 +45,8 @@ struct scan_data_t { extern struct scan_data_t scan_data; +extern uint16_t central_conn_handle; + void bluetooth_setup(bool factory_reset); bool bluetooth_is_connected(void); diff --git a/source/application/lua_libraries/bluetooth.c b/source/application/lua_libraries/bluetooth.c index 1b6ec72b..521c4214 100644 --- a/source/application/lua_libraries/bluetooth.c +++ b/source/application/lua_libraries/bluetooth.c @@ -25,6 +25,7 @@ #include #include "ble_gap.h" #include "bluetooth.h" +#include "nrfx_systick.h" #include "error_logging.h" #include "frame_lua_libraries.h" #include "lauxlib.h" @@ -32,6 +33,7 @@ #include "luaport.h" struct scan_data_t scan_data; +uint16_t central_conn_handle = BLE_CONN_HANDLE_INVALID; static int lua_bluetooth_is_connected(lua_State *L) { @@ -196,9 +198,24 @@ static int lua_bluetooth_scan_list(lua_State *L) { } static int lua_bluetooth_connect(lua_State *L) { + uint8_t retry_count = 3; uint8_t index = luaL_checkinteger(L, 1); - check_error(sd_ble_gap_connect(&scan_data.address[index], &scan_data.scan_params, &scan_data.conn_params, 2)); + while (retry_count > 0) + { + check_error(sd_ble_gap_connect(&scan_data.address[index], + &scan_data.scan_params, &scan_data.conn_params, 2)); + + nrfx_systick_delay_ms(500); + + if (central_conn_handle != BLE_CONN_HANDLE_INVALID) + break; + else + retry_count--; + } + + if (retry_count == 0) + luaL_error(L, "failed to connect"); return 1; } From 5cf6f3ce38b981d5c940d6e212f111c5a101df68 Mon Sep 17 00:00:00 2001 From: rohitrathnam Date: Thu, 29 Aug 2024 11:55:36 +0530 Subject: [PATCH 11/13] central rx callback --- source/application/bluetooth.c | 7 +- source/application/lua_libraries/bluetooth.c | 100 ++++++++++++++---- .../lua_libraries/frame_lua_libraries.h | 3 +- tests/test_api.py | 4 +- tests/test_bluetooth_callback_api.py | 2 +- 5 files changed, 91 insertions(+), 25 deletions(-) diff --git a/source/application/bluetooth.c b/source/application/bluetooth.c index 1cc367b1..bab924fb 100644 --- a/source/application/bluetooth.c +++ b/source/application/bluetooth.c @@ -238,7 +238,7 @@ void SD_EVT_IRQHandler(void) // Handle raw data if (ble_evt->evt.gatts_evt.params.write.data[0] == 0x01) { - lua_bluetooth_data_interrupt( + lua_bluetooth_peripheral_data_interrupt( ble_evt->evt.gatts_evt.params.write.data + 1, ble_evt->evt.gatts_evt.params.write.len - 1); } @@ -410,7 +410,10 @@ void SD_EVT_IRQHandler(void) case BLE_GATTC_EVT_HVX: { - LOG("data: %.2x %.2x", ble_evt->evt.gattc_evt.params.hvx.data[0], ble_evt->evt.gattc_evt.params.hvx.data[0]); + + lua_bluetooth_central_data_interrupt( + ble_evt->evt.gattc_evt.params.hvx.data, + ble_evt->evt.gattc_evt.params.hvx.len); break; } diff --git a/source/application/lua_libraries/bluetooth.c b/source/application/lua_libraries/bluetooth.c index 521c4214..4cf3c042 100644 --- a/source/application/lua_libraries/bluetooth.c +++ b/source/application/lua_libraries/bluetooth.c @@ -86,24 +86,26 @@ static int lua_bluetooth_send(lua_State *L) return 0; } -static struct lua_bluetooth_callback +struct lua_bluetooth_callback { int function; uint8_t data[BLE_PREFERRED_MAX_MTU]; size_t length; -} lua_bluetooth_callback = { +}; + +static struct lua_bluetooth_callback lua_bluetooth_peripheral_callback = { .function = 0, }; -static void lua_bluetooth_receive_callback_handler(lua_State *L, lua_Debug *ar) +static void lua_bluetooth_peripheral_receive_callback_handler(lua_State *L, lua_Debug *ar) { lua_sethook(L, NULL, 0, 0); - lua_rawgeti(L, LUA_REGISTRYINDEX, lua_bluetooth_callback.function); + lua_rawgeti(L, LUA_REGISTRYINDEX, lua_bluetooth_peripheral_callback.function); lua_pushlstring(L, - (char *)lua_bluetooth_callback.data, - lua_bluetooth_callback.length); + (char *)lua_bluetooth_peripheral_callback.data, + lua_bluetooth_peripheral_callback.length); if (lua_pcall(L, 1, 0, 0) != LUA_OK) { @@ -111,33 +113,33 @@ static void lua_bluetooth_receive_callback_handler(lua_State *L, lua_Debug *ar) } } -void lua_bluetooth_data_interrupt(uint8_t *data, size_t length) +void lua_bluetooth_peripheral_data_interrupt(uint8_t *data, size_t length) { - if (lua_bluetooth_callback.function == 0) + if (lua_bluetooth_peripheral_callback.function == 0) { return; } - memcpy(lua_bluetooth_callback.data, data, length); - lua_bluetooth_callback.length = length; + memcpy(lua_bluetooth_peripheral_callback.data, data, length); + lua_bluetooth_peripheral_callback.length = length; lua_sethook(L_global, - lua_bluetooth_receive_callback_handler, + lua_bluetooth_peripheral_receive_callback_handler, LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE | LUA_MASKCOUNT, 1); } -static int lua_bluetooth_receive_callback(lua_State *L) +static int lua_bluetooth_peripheral_receive_callback(lua_State *L) { if (lua_isnil(L, 1)) { - lua_bluetooth_callback.function = 0; + lua_bluetooth_peripheral_callback.function = 0; return 0; } if (lua_isfunction(L, 1)) { - lua_bluetooth_callback.function = luaL_ref(L, LUA_REGISTRYINDEX); + lua_bluetooth_peripheral_callback.function = luaL_ref(L, LUA_REGISTRYINDEX); return 0; } @@ -198,7 +200,7 @@ static int lua_bluetooth_scan_list(lua_State *L) { } static int lua_bluetooth_connect(lua_State *L) { - uint8_t retry_count = 3; + uint8_t retry_count = 5; uint8_t index = luaL_checkinteger(L, 1); while (retry_count > 0) @@ -206,10 +208,12 @@ static int lua_bluetooth_connect(lua_State *L) { check_error(sd_ble_gap_connect(&scan_data.address[index], &scan_data.scan_params, &scan_data.conn_params, 2)); - nrfx_systick_delay_ms(500); + nrfx_systick_delay_ms(1000); - if (central_conn_handle != BLE_CONN_HANDLE_INVALID) + if (central_conn_handle != BLE_CONN_HANDLE_INVALID) { + LOG("connected"); break; + } else retry_count--; } @@ -220,6 +224,61 @@ static int lua_bluetooth_connect(lua_State *L) { return 1; } +static struct lua_bluetooth_callback lua_bluetooth_central_callback = { + .function = 0, +}; + +static void lua_bluetooth_central_receive_callback_handler(lua_State *L, lua_Debug *ar) +{ + lua_sethook(L, NULL, 0, 0); + + lua_rawgeti(L, LUA_REGISTRYINDEX, lua_bluetooth_central_callback.function); + + lua_pushlstring(L, + (char *)lua_bluetooth_central_callback.data, + lua_bluetooth_central_callback.length); + + if (lua_pcall(L, 1, 0, 0) != LUA_OK) + { + luaL_error(L, "%s", lua_tostring(L, -1)); + } +} + +void lua_bluetooth_central_data_interrupt(uint8_t *data, size_t length) +{ + if (lua_bluetooth_central_callback.function == 0) + { + return; + } + + memcpy(lua_bluetooth_central_callback.data, data, length); + lua_bluetooth_central_callback.length = length; + + lua_sethook(L_global, + lua_bluetooth_central_receive_callback_handler, + LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE | LUA_MASKCOUNT, + 1); +} + +static int lua_bluetooth_central_receive_callback(lua_State *L) +{ + if (lua_isnil(L, 1)) + { + lua_bluetooth_central_callback.function = 0; + return 0; + } + + if (lua_isfunction(L, 1)) + { + lua_bluetooth_central_callback.function = luaL_ref(L, LUA_REGISTRYINDEX); + return 0; + } + + luaL_error(L, "expected nil or function"); + + return 0; +} + void lua_open_bluetooth_library(lua_State *L) { lua_getglobal(L, "frame"); @@ -238,8 +297,8 @@ void lua_open_bluetooth_library(lua_State *L) lua_pushcfunction(L, lua_bluetooth_send); lua_setfield(L, -2, "send"); - lua_pushcfunction(L, lua_bluetooth_receive_callback); - lua_setfield(L, -2, "receive_callback"); + lua_pushcfunction(L, lua_bluetooth_peripheral_receive_callback); + lua_setfield(L, -2, "peripheral_receive_callback"); lua_pushcfunction(L, lua_bluetooth_start_scan); lua_setfield(L, -2, "start_scan"); @@ -250,6 +309,9 @@ void lua_open_bluetooth_library(lua_State *L) lua_pushcfunction(L, lua_bluetooth_connect); lua_setfield(L, -2, "connect"); + lua_pushcfunction(L, lua_bluetooth_central_receive_callback); + lua_setfield(L, -2, "central_receive_callback"); + lua_setfield(L, -2, "bluetooth"); lua_pop(L, 1); diff --git a/source/application/lua_libraries/frame_lua_libraries.h b/source/application/lua_libraries/frame_lua_libraries.h index 599912ae..49af268b 100644 --- a/source/application/lua_libraries/frame_lua_libraries.h +++ b/source/application/lua_libraries/frame_lua_libraries.h @@ -29,7 +29,8 @@ extern lua_State *L_global; -void lua_bluetooth_data_interrupt(uint8_t *data, size_t length); +void lua_bluetooth_peripheral_data_interrupt(uint8_t *data, size_t length); +void lua_bluetooth_central_data_interrupt(uint8_t *data, size_t length); void lua_open_bluetooth_library(lua_State *L); void lua_open_camera_library(lua_State *L); diff --git a/tests/test_api.py b/tests/test_api.py index 9012cf6e..f84ceb8e 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -93,10 +93,10 @@ async def main(): ## Send and receive callback await test.lua_send( - "frame.bluetooth.receive_callback((function(d)frame.bluetooth.send(d)end))" + "frame.bluetooth.peripheral_receive_callback((function(d)frame.bluetooth.send(d)end))" ) await test.data_equal(b"test", b"test") - await test.lua_send("frame.bluetooth.receive_callback(nil)") + await test.lua_send("frame.bluetooth.peripheral_receive_callback(nil)") ## MTU size max_length = test.max_data_payload() diff --git a/tests/test_bluetooth_callback_api.py b/tests/test_bluetooth_callback_api.py index f7e581a7..430cc765 100644 --- a/tests/test_bluetooth_callback_api.py +++ b/tests/test_bluetooth_callback_api.py @@ -12,7 +12,7 @@ async def main(): await bluetooth.send_reset_signal() await bluetooth.send_lua("function ble_event(d)frame.bluetooth.send(d)end") - await bluetooth.send_lua("frame.bluetooth.receive_callback(ble_event)") + await bluetooth.send_lua("frame.bluetooth.peripheral_receive_callback(ble_event)") await bluetooth.send_lua("for i=1,10 do print(i); frame.sleep(1) end") await asyncio.sleep(1) From 51192f7d5ee83238299ad7cf56084ece78232e4f Mon Sep 17 00:00:00 2001 From: rohitrathnam Date: Thu, 29 Aug 2024 16:26:54 +0530 Subject: [PATCH 12/13] cleanup --- source/application/bluetooth.c | 72 ++++++++++++++------ source/application/bluetooth.h | 19 +----- source/application/lua_libraries/bluetooth.c | 27 +++++--- 3 files changed, 70 insertions(+), 48 deletions(-) diff --git a/source/application/bluetooth.c b/source/application/bluetooth.c index bab924fb..a31af7d4 100644 --- a/source/application/bluetooth.c +++ b/source/application/bluetooth.c @@ -91,6 +91,28 @@ static void softdevice_assert_handler(uint32_t id, uint32_t pc, uint32_t info) error_with_message("Softdevice crashed"); } +static uint8_t find_ad_type(uint16_t ad_type, uint8_t* p_data, uint8_t data_len, uint8_t* offset) +{ + size_t i=0; + uint16_t this_ad_type; + uint8_t ad_type_len = 0; + + while (i+1 < data_len) + { + ad_type_len = p_data[i]; + this_ad_type = p_data[i+1]; + + if (this_ad_type == ad_type) + { + *offset = i+2; + return ad_type_len-1; + } + else i += ad_type_len+1; // +1 offset for ad_type_len + } + + return 0; +} + void SD_EVT_IRQHandler(void) { uint32_t evt_id; @@ -369,25 +391,31 @@ void SD_EVT_IRQHandler(void) { ble_gap_evt_adv_report_t *adv_report = &ble_evt->evt.gap_evt.params.adv_report; bool is_unique = true; - bool has_name = (adv_report->data.p_data[1] == BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME - || adv_report->data.p_data[1] == BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME); - for (size_t i=0; ipeer_addr.addr, scan_data.address[i].addr, BLE_GAP_ADDR_LEN) == 0) { + + uint8_t name_offset = 0; + uint8_t name_len = find_ad_type(BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME, + adv_report->data.p_data, adv_report->data.len, &name_offset); + + for (size_t i=0; ipeer_addr.addr, + scan_data.address[i].addr, BLE_GAP_ADDR_LEN) == 0) { is_unique = false; break; } } - if (is_unique && has_name) { + if (is_unique && name_len != 0) + { memcpy(&scan_data.address[scan_data.len].addr, adv_report->peer_addr.addr, BLE_GAP_ADDR_LEN); - // offset 2 to exclude packet size and ad_type - scan_data.name_len[scan_data.len] = adv_report->data.len - 4; + scan_data.name_len[scan_data.len] = name_len; + // offset +2 to exclude packet size and ad_type memcpy(&scan_data.name[scan_data.len], - adv_report->data.p_data+2, + &adv_report->data.p_data[name_offset], scan_data.name_len[scan_data.len]); scan_data.len++; @@ -400,6 +428,13 @@ void SD_EVT_IRQHandler(void) break; } + case BLE_GAP_EVT_SEC_REQUEST: + { + // TODO: handle security request + LOG("unhandled BLE_GAP_EVT_SEC_REQUEST"); + break; + } + case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: { sd_ble_gap_conn_param_update(ble_evt->evt.gap_evt.conn_handle, @@ -648,22 +683,17 @@ void bluetooth_setup(bool factory_reset) memset(&scan_data, 0, sizeof(scan_data)); scan_data.scan_params.active = 1; - scan_data.scan_params.interval = NRF_BLE_SCAN_SCAN_INTERVAL; - scan_data.scan_params.window = NRF_BLE_SCAN_SCAN_WINDOW; - scan_data.scan_params.timeout = NRF_BLE_SCAN_SCAN_DURATION; + scan_data.scan_params.interval = 160; + scan_data.scan_params.window = 80; + scan_data.scan_params.timeout = 300; scan_data.scan_params.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL; scan_data.scan_params.scan_phys = BLE_GAP_PHY_1MBPS; - scan_data.scan_params.extended = 0; - - scan_data.conn_params.conn_sup_timeout = - (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_SUPERVISION_TIMEOUT, UNIT_10_MS); - scan_data.conn_params.min_conn_interval = - (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL, UNIT_1_25_MS); - scan_data.conn_params.max_conn_interval = - (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL, UNIT_1_25_MS); - scan_data.conn_params.slave_latency = - (uint16_t)NRF_BLE_SCAN_SLAVE_LATENCY; + scan_data.scan_params.extended = 1; + scan_data.conn_params.conn_sup_timeout = 620; + scan_data.conn_params.min_conn_interval = 80; + scan_data.conn_params.max_conn_interval = 400; + scan_data.conn_params.slave_latency = 5; scan_data.scan_buffer.p_data = (uint8_t *) &scan_buffer_data; scan_data.scan_buffer.len = sizeof(scan_buffer_data); } diff --git a/source/application/bluetooth.h b/source/application/bluetooth.h index 7af5e122..0cb82617 100644 --- a/source/application/bluetooth.h +++ b/source/application/bluetooth.h @@ -32,6 +32,8 @@ #define BLE_PREFERRED_MAX_MTU 256 extern uint16_t ble_negotiated_mtu; +#define NRF_BLE_SCAN_BUFFER 255 + #define SCAN_LIST_SIZE 10 struct scan_data_t { ble_data_t scan_buffer; @@ -53,23 +55,6 @@ bool bluetooth_is_connected(void); bool bluetooth_send_data(const uint8_t *data, size_t length); -#define NRF_BLE_SCAN_SCAN_INTERVAL 160 // scan interval in units of 0.625 millisecond -#define NRF_BLE_SCAN_SCAN_DURATION 300 // duration of a scanning session in units of 10 ms -#define NRF_BLE_SCAN_SCAN_WINDOW 80 // scanning window in units of 0.625 millisecond -#define NRF_BLE_SCAN_BUFFER 255 // ble scan buffer size -#define NRF_BLE_SCAN_SUPERVISION_TIMEOUT 6200 // supervision time-out in units of 10 millisecond -#define NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL 100 // minimum connection interval in milliseconds -#define NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL 500 // maximum connection interval in milliseconds -#define NRF_BLE_SCAN_SLAVE_LATENCY 5 // slave latency in counts of connection events - -#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) -enum -{ - UNIT_0_625_MS = 625, /**< Number of microseconds in 0.625 milliseconds. */ - UNIT_1_25_MS = 1250, /**< Number of microseconds in 1.25 milliseconds. */ - UNIT_10_MS = 10000 /**< Number of microseconds in 10 milliseconds. */ -}; - /* BLE_GAP_AD_TYPE_DEFINITIONS GAP Advertising and Scan Response Data format * Found at https://www.bluetooth.org/Technical/AssignedNumbers/generic_access_profile.htm */ diff --git a/source/application/lua_libraries/bluetooth.c b/source/application/lua_libraries/bluetooth.c index 4cf3c042..90593933 100644 --- a/source/application/lua_libraries/bluetooth.c +++ b/source/application/lua_libraries/bluetooth.c @@ -187,18 +187,20 @@ static int lua_bluetooth_scan_list(lua_State *L) { } lua_seti(L, -2, i); - - LOG("%d -> %.17s - %.*s", - i, - mac_address, - scan_data.name_len[i], - scan_data.name[i] - ); } return 1; } +static int lua_bluetooth_scan_clear(lua_State *L) { + memset(&scan_data.address, 0, sizeof(scan_data.address)); + memset(&scan_data.name, 0, sizeof(scan_data.name)); + memset(&scan_data.name_len, 0, sizeof(scan_data.name_len)); + scan_data.len = 0; + + return 1; +} + static int lua_bluetooth_connect(lua_State *L) { uint8_t retry_count = 5; uint8_t index = luaL_checkinteger(L, 1); @@ -210,12 +212,14 @@ static int lua_bluetooth_connect(lua_State *L) { nrfx_systick_delay_ms(1000); - if (central_conn_handle != BLE_CONN_HANDLE_INVALID) { - LOG("connected"); + if (central_conn_handle != BLE_CONN_HANDLE_INVALID) + { break; } - else + else + { retry_count--; + } } if (retry_count == 0) @@ -306,6 +310,9 @@ void lua_open_bluetooth_library(lua_State *L) lua_pushcfunction(L, lua_bluetooth_scan_list); lua_setfield(L, -2, "scan_list"); + lua_pushcfunction(L, lua_bluetooth_scan_clear); + lua_setfield(L, -2, "scan_clear"); + lua_pushcfunction(L, lua_bluetooth_connect); lua_setfield(L, -2, "connect"); From 3056b70cfb3bb0af330104271a09b01aed77546f Mon Sep 17 00:00:00 2001 From: rohitrathnam Date: Mon, 2 Sep 2024 17:35:45 +0530 Subject: [PATCH 13/13] ble central with sec works --- source/application/bluetooth.c | 111 ++++++++++++++++++++++++--------- 1 file changed, 80 insertions(+), 31 deletions(-) diff --git a/source/application/bluetooth.c b/source/application/bluetooth.c index a31af7d4..f36f289e 100644 --- a/source/application/bluetooth.c +++ b/source/application/bluetooth.c @@ -80,6 +80,40 @@ static struct bond_information_t }, }; +ble_gap_sec_params_t central_sec_param = { + .bond = 1, + .keypress = 0, + .io_caps = BLE_GAP_IO_CAPS_NONE, + .min_key_size = 7, + .max_key_size = 16, + .kdist_own.enc = 1, + .kdist_own.id = 1, + .kdist_peer.enc = 1, + .kdist_peer.id = 1, +}; + +ble_gap_enc_key_t own_enc_key; /**< Encryption Key, or NULL. */ +ble_gap_id_key_t own_id_key; /**< Identity Key, or NULL. */ +ble_gap_sign_info_t own_sign_key; /**< Signing Key, or NULL. */ +ble_gap_lesc_p256_pk_t own_pk; + +ble_gap_enc_key_t peer_enc_key; /**< Encryption Key, or NULL. */ +ble_gap_id_key_t peer_id_key; /**< Identity Key, or NULL. */ +ble_gap_sign_info_t peer_sign_key; /**< Signing Key, or NULL. */ +ble_gap_lesc_p256_pk_t peer_pk; + +ble_gap_sec_keyset_t central_keyset = { + .keys_own.p_enc_key = &own_enc_key, + .keys_own.p_id_key = &own_id_key, + .keys_own.p_sign_key = &own_sign_key, + .keys_own.p_pk = &own_pk, + + .keys_peer.p_enc_key = &peer_enc_key, + .keys_peer.p_id_key = &peer_id_key, + .keys_peer.p_sign_key = &peer_sign_key, + .keys_peer.p_pk = &peer_pk, +}; + bool flash_write_in_progress = false; uint16_t ble_negotiated_mtu; @@ -315,38 +349,51 @@ void SD_EVT_IRQHandler(void) case BLE_GAP_EVT_SEC_PARAMS_REQUEST: { - size_t bonded = 0; - - for (size_t i = 0; - i < sizeof(bond.keyset.keys_own.p_enc_key->enc_info.ltk); - i++) + if (ble_evt->evt.gap_evt.conn_handle == ble_peripheral_handles.connection) { - if (bond.keyset.keys_own.p_enc_key->enc_info.ltk[i] == 0xff) + size_t bonded = 0; + + for (size_t i = 0; + i < sizeof(bond.keyset.keys_own.p_enc_key->enc_info.ltk); + i++) { - bonded++; + if (bond.keyset.keys_own.p_enc_key->enc_info.ltk[i] == 0xff) + { + bonded++; + } } - } - if (bonded == sizeof(bond.keyset.keys_own.p_enc_key->enc_info.ltk)) - { - check_error(sd_ble_gap_sec_params_reply( - ble_peripheral_handles.connection, - BLE_GAP_SEC_STATUS_SUCCESS, - &bond.sec_param, - &bond.keyset)); + if (bonded == sizeof(bond.keyset.keys_own.p_enc_key->enc_info.ltk)) + { + check_error(sd_ble_gap_sec_params_reply( + ble_peripheral_handles.connection, + BLE_GAP_SEC_STATUS_SUCCESS, + &bond.sec_param, + &bond.keyset)); + } + + else + { + check_error(sd_ble_gap_sec_params_reply( + ble_peripheral_handles.connection, + BLE_GAP_SEC_STATUS_AUTH_REQ, + NULL, + NULL)); + + check_error(sd_ble_gap_disconnect( + ble_peripheral_handles.connection, + BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION)); + } } - else + if (ble_evt->evt.gap_evt.conn_handle == central_conn_handle) { check_error(sd_ble_gap_sec_params_reply( - ble_peripheral_handles.connection, - BLE_GAP_SEC_STATUS_AUTH_REQ, + central_conn_handle, + BLE_GAP_SEC_STATUS_SUCCESS, NULL, - NULL)); - - check_error(sd_ble_gap_disconnect( - ble_peripheral_handles.connection, - BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION)); + ¢ral_keyset + )); } break; @@ -365,13 +412,16 @@ void SD_EVT_IRQHandler(void) case BLE_GAP_EVT_AUTH_STATUS: { - if (ble_evt->evt.gap_evt.params.auth_status.auth_status == - BLE_GAP_SEC_STATUS_SUCCESS) + if (ble_evt->evt.gap_evt.conn_handle == ble_peripheral_handles.connection) { - flash_write( - bond_storage, - (uint32_t *)&bond.keyset.keys_own.p_enc_key->enc_info, - sizeof(bond.keyset.keys_own.p_enc_key->enc_info)); + if (ble_evt->evt.gap_evt.params.auth_status.auth_status == + BLE_GAP_SEC_STATUS_SUCCESS) + { + flash_write( + bond_storage, + (uint32_t *)&bond.keyset.keys_own.p_enc_key->enc_info, + sizeof(bond.keyset.keys_own.p_enc_key->enc_info)); + } } break; @@ -430,8 +480,7 @@ void SD_EVT_IRQHandler(void) case BLE_GAP_EVT_SEC_REQUEST: { - // TODO: handle security request - LOG("unhandled BLE_GAP_EVT_SEC_REQUEST"); + uint32_t error = sd_ble_gap_authenticate(ble_evt->evt.gap_evt.conn_handle, ¢ral_sec_param); break; }