From 70daef58f820f313c0bc3dc06ef9bf39e001e17f Mon Sep 17 00:00:00 2001 From: leo Date: Sat, 24 Jun 2023 15:49:34 +0200 Subject: [PATCH] Init --- BLEh.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++ CMakeLists.txt | 5 ++ include/BLEh.h | 2 + 3 files changed, 167 insertions(+) create mode 100644 BLEh.c create mode 100644 CMakeLists.txt create mode 100644 include/BLEh.h diff --git a/BLEh.c b/BLEh.c new file mode 100644 index 0000000..718f537 --- /dev/null +++ b/BLEh.c @@ -0,0 +1,160 @@ +#include +#include +#include + +#include "esp_log.h" +#include "nimble/nimble_port.h" +#include "nimble/nimble_port_freertos.h" + +#include "host/ble_gap.h" +#include "host/ble_gatt.h" + +#include "services/gap/ble_svc_gap.h" +#include "services/gatt/ble_svc_gatt.h" + +#include "BLEh.h" + +#define TAG "BLEh" + +static uint16_t conn_handle; + +static struct ble_gatt_svc_def* gatt_svr_svcs; +static uint16_t svcs_num; +static uint16_t* svcs_sizes; +static uint16_t** att_handle; +static uint8_t** notify_state; + +static struct ble_hs_adv_fields adv_fields = { + .tx_pwr_lvl_is_present = 1, + .tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO, + .flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP, + .name = (uint8_t*)&"Power Profiler"[0], + .name_len = 15, + .name_is_complete = 1, +}; + +static struct ble_gap_adv_params adv_params = { + .conn_mode = BLE_GAP_CONN_MODE_UND, + .disc_mode = BLE_GAP_DISC_MODE_GEN, +}; + +static void ble_on_sync(void){ + ble_advertise(); +} +static void ble_on_reset(int p){ + +} + +static uint8_t* get_notify_state(uint16_t handle){ + for(int i = 0; i < svcs_num; i++){ + for(int j = 0; j < svcs_sizes[i]; j++){ + if(att_handle[i][j] == handle){ + return ¬ify_state[i][j]; + } + } + } + + return NULL; +} + +static int ble_gap_event(struct ble_gap_event *event, void* arg){ + switch(event->type){ + case BLE_GAP_EVENT_CONNECT: + if(event->connect.status) + ble_advertise(); + else + conn_handle = event->connect.conn_handle; + break; + case BLE_GAP_EVENT_DISCONNECT: + ble_advertise(); + break; + case BLE_GAP_EVENT_SUBSCRIBE: + ESP_LOGI(TAG, "Subscribe %d", event->subscribe.attr_handle); + uint8_t* target_state = get_notify_state(event->subscribe.attr_handle); + if(target_state == NULL) + ESP_LOGE(TAG, "Unknown notification requested"); + *target_state = event->subscribe.cur_notify; + break; + } + + return ESP_OK; +} + +static void gatt_svr_init(void){ + ble_svc_gap_init(); + + ble_svc_gatt_init(); + + ESP_ERROR_CHECK(ble_gatts_count_cfg(gatt_svr_svcs)); + ESP_ERROR_CHECK(ble_gatts_add_svcs(gatt_svr_svcs)); +} + +static void ble_host_task(){ + nimble_port_run(); + nimble_port_freertos_deinit(); +} + +void ble_advertise(void){ + ESP_ERROR_CHECK(ble_gap_adv_set_fields(&adv_fields)); + ESP_ERROR_CHECK(ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER, &adv_params, ble_gap_event, NULL)); +} + +void set_gatt_services(struct ble_gatt_svc_def* svcs, uint16_t num){ + gatt_svr_svcs = svcs; + svcs_num = num; + + // map our attributes handle to the services + // first get the sizes of each services to know the size to allocate + struct ble_gatt_svc_def svc = svcs[0]; + + for(int svc_ind = 0; svc_ind < svcs_num; svc_ind++){ + struct ble_gatt_chr_def chr = svc.characteristics[0]; + + svcs_sizes = realloc(svcs_sizes, svc_ind * sizeof(uint16_t)); + + int chr_ind; + for(chr_ind = 0; chr.uuid != NULL; chr_ind++) ; + svcs_sizes[svc_ind] = chr_ind - 1; + } + + //then we allocate + att_handle = malloc(svcs_num * sizeof(uint16_t*)); + notify_state = malloc(svcs_num * sizeof(uint8_t*)); + + // finally we populate the handles + svc = svcs[0]; + + int svc_ind; + for(svc_ind = 0; svc_ind < svcs_num; svc_ind++){ + att_handle[svc_ind] = malloc(svcs_sizes[svc_ind] * sizeof(uint16_t)); + notify_state[svc_ind] = malloc(svcs_sizes[svc_ind] * sizeof(uint8_t)); + + for(int chr_ind = 0; chr_ind < svcs_sizes[svc_ind]; chr_ind++){ + struct ble_gatt_chr_def chr = svcs[svc_ind].characteristics[chr_ind]; + chr.val_handle = &att_handle[svc_ind][chr_ind]; + } + + svc = svcs[svc_ind]; + } +} + +void initBLE(char* name){ + nimble_port_init(); + + ble_hs_cfg.sync_cb = ble_on_sync; + ble_hs_cfg.reset_cb = ble_on_reset; + + gatt_svr_init(); + ESP_ERROR_CHECK(ble_svc_gap_device_name_set(name)); + nimble_port_freertos_init(ble_host_task); +} + +void deinitBLE(){ + // TODO: deinit all nimble and freertos stuff + + for(int i = 0; i < svcs_num; i++){ + free(att_handle[i]); + } + free(svcs_sizes); + free(notify_state); +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..a259982 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,5 @@ +idf_component_register( + SRCS "BLEh.c" + INCLUDE_DIRS "include" + REQUIRES bt +) diff --git a/include/BLEh.h b/include/BLEh.h new file mode 100644 index 0000000..7bb7340 --- /dev/null +++ b/include/BLEh.h @@ -0,0 +1,2 @@ +void initBLE(char* name); +void ble_advertise(void); \ No newline at end of file