282 lines
9.7 KiB
C
282 lines
9.7 KiB
C
#include "sdk_common.h"
|
|
|
|
#include "app_error.h"
|
|
#include "ble_conn_state.h"
|
|
#include "ble_gatts.h"
|
|
#include "ble_srv_common.h"
|
|
#include "elite.h"
|
|
#include "nrf_sdh_ble.h"
|
|
|
|
#include "nrf_log.h"
|
|
#include "nrf_log_ctrl.h"
|
|
#include "nrf_log_default_backends.h"
|
|
|
|
#include "FreeRTOS.h"
|
|
#include "semphr.h"
|
|
#include "task.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#if NRF_MODULE_ENABLED(BLE_ELITE_SRV)
|
|
|
|
#define BLE_UUID_ELITE_SERVICE 0xFFF0
|
|
#define BLE_UUID_ELITE_DATA_CHAR 0xFFF1
|
|
#define BLE_UUID_ELITE_INST_CHAR 0xFFF2
|
|
#define BLE_UUID_ELITE_EVENT_CHAR 0xFFF3
|
|
#define BLE_UUID_ELITE_BEGIN_CHAR BLE_UUID_ELITE_DATA_CHAR
|
|
#define BLE_UUID_ELITE_END_CHAR (BLE_UUID_ELITE_EVENT_CHAR + 1)
|
|
|
|
typedef struct
|
|
{
|
|
uint16_t conn_handle;
|
|
uint16_t service_handle;
|
|
ble_gatts_char_handles_t data_char_handle;
|
|
ble_gatts_char_handles_t inst_char_handle;
|
|
ble_gatts_char_handles_t event_char_handle;
|
|
bool data_notify_enable;
|
|
bool inst_notify_enable;
|
|
bool event_notify_enable;
|
|
} elite_context_t;
|
|
|
|
static elite_context_t elite_context = {
|
|
.conn_handle = BLE_CONN_HANDLE_INVALID,
|
|
.data_notify_enable = false,
|
|
.inst_notify_enable = false,
|
|
.event_notify_enable = false,
|
|
};
|
|
|
|
static void on_connect(elite_context_t *p_context, ble_evt_t const *p_ble_evt)
|
|
{
|
|
taskENTER_CRITICAL();
|
|
p_context->conn_handle = p_ble_evt->evt.common_evt.conn_handle;
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
|
|
static void on_disconnect(elite_context_t *p_context, ble_evt_t const *p_ble_evt)
|
|
{
|
|
taskENTER_CRITICAL();
|
|
p_context->conn_handle = BLE_CONN_HANDLE_INVALID;
|
|
p_context->data_notify_enable = false;
|
|
p_context->inst_notify_enable = false;
|
|
p_context->event_notify_enable = false;
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
|
|
static void elite_srv_ccc_update(elite_context_t *p_context, ble_evt_t const *p_ble_evt)
|
|
{
|
|
ble_gatts_evt_write_t const *p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
|
|
if (p_evt_write->handle == p_context->data_char_handle.cccd_handle)
|
|
{
|
|
p_context->data_notify_enable = ble_srv_is_notification_enabled(p_evt_write->data);
|
|
NRF_LOG_INFO("data_notify:%s", p_context->data_notify_enable ? "enable" : "disable");
|
|
return;
|
|
}
|
|
|
|
if (p_evt_write->handle == p_context->inst_char_handle.cccd_handle)
|
|
{
|
|
p_context->inst_notify_enable = ble_srv_is_notification_enabled(p_evt_write->data);
|
|
NRF_LOG_INFO("inst_notify_notify:%s", p_context->inst_notify_enable ? "enable" : "disable");
|
|
return;
|
|
}
|
|
|
|
if (p_evt_write->handle == p_context->event_char_handle.cccd_handle)
|
|
{
|
|
p_context->event_notify_enable = ble_srv_is_notification_enabled(p_evt_write->data);
|
|
NRF_LOG_INFO("event_notify:%s", p_context->event_notify_enable ? "enable" : "disable");
|
|
return;
|
|
}
|
|
}
|
|
|
|
static void on_write(elite_context_t *p_context, ble_evt_t const *p_ble_evt)
|
|
{
|
|
ble_uuid_t uuid = p_ble_evt->evt.gatts_evt.params.write.uuid;
|
|
uint16_t handle = p_ble_evt->evt.gatts_evt.params.write.handle;
|
|
ble_gatts_evt_write_t const *p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
|
|
switch (uuid.uuid)
|
|
{
|
|
case BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG:
|
|
elite_srv_ccc_update(p_context, p_ble_evt);
|
|
break;
|
|
|
|
case BLE_UUID_ELITE_INST_CHAR:
|
|
NRF_LOG_HEXDUMP_INFO(p_evt_write->data, p_evt_write->len);
|
|
elite_instr_send((void *)p_evt_write->data, p_evt_write->len);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void on_hvx_tx_complete(elite_context_t *p_context, ble_evt_t const *p_ble_evt)
|
|
{
|
|
}
|
|
|
|
static void on_ble_evt_handler(ble_evt_t const *p_ble_evt, void *p_context)
|
|
{
|
|
switch (p_ble_evt->header.evt_id)
|
|
{
|
|
case BLE_GAP_EVT_CONNECTED:
|
|
on_connect(p_context, p_ble_evt);
|
|
break;
|
|
case BLE_GAP_EVT_DISCONNECTED:
|
|
on_disconnect(p_context, p_ble_evt);
|
|
break;
|
|
case BLE_GATTS_EVT_WRITE:
|
|
on_write(p_context, p_ble_evt);
|
|
break;
|
|
case BLE_GATTS_EVT_HVN_TX_COMPLETE:
|
|
on_hvx_tx_complete(p_context, p_ble_evt);
|
|
break;
|
|
default:
|
|
// No implementation needed.
|
|
break;
|
|
}
|
|
}
|
|
|
|
static ret_code_t add_characteristic(uint16_t uuid, uint8_t uuid_type, uint32_t val_max_len, void *p_init_val, uint32_t init_len, ble_gatts_char_handles_t *p_handles, bool enable_cccd)
|
|
{
|
|
ble_add_char_params_t add_char_params;
|
|
memset(&add_char_params, 0, sizeof(add_char_params));
|
|
add_char_params.uuid = uuid;
|
|
add_char_params.uuid_type = uuid_type;
|
|
add_char_params.max_len = val_max_len;
|
|
add_char_params.init_len = init_len;
|
|
add_char_params.p_init_value = p_init_val;
|
|
add_char_params.is_value_user = false;
|
|
add_char_params.is_var_len = true;
|
|
add_char_params.write_access = SEC_OPEN;
|
|
add_char_params.char_props.write = 1;
|
|
add_char_params.read_access = SEC_OPEN;
|
|
add_char_params.char_props.read = 1;
|
|
add_char_params.cccd_write_access = SEC_OPEN;
|
|
add_char_params.char_props.notify = enable_cccd;
|
|
ret_code_t err_code = characteristic_add(elite_context.service_handle, &add_char_params, p_handles);
|
|
return err_code;
|
|
}
|
|
|
|
static ret_code_t add_characteristic_ro(uint16_t uuid, uint8_t uuid_type, uint32_t val_max_len, void *p_init_val, uint32_t init_len, ble_gatts_char_handles_t *p_handles, bool enable_cccd)
|
|
{
|
|
ble_add_char_params_t add_char_params;
|
|
memset(&add_char_params, 0, sizeof(add_char_params));
|
|
add_char_params.uuid = uuid;
|
|
add_char_params.uuid_type = uuid_type;
|
|
add_char_params.max_len = val_max_len;
|
|
add_char_params.init_len = init_len;
|
|
add_char_params.p_init_value = p_init_val;
|
|
add_char_params.is_value_user = true;
|
|
add_char_params.is_var_len = true;
|
|
add_char_params.read_access = SEC_OPEN;
|
|
add_char_params.char_props.read = 1;
|
|
add_char_params.cccd_write_access = SEC_OPEN;
|
|
add_char_params.char_props.notify = enable_cccd;
|
|
ret_code_t err_code = characteristic_add(elite_context.service_handle, &add_char_params, p_handles);
|
|
return err_code;
|
|
}
|
|
|
|
static uint32_t elite_srv_init(void)
|
|
{
|
|
ret_code_t err_code;
|
|
ble_uuid_t ble_uuid = {
|
|
.type = BLE_UUID_TYPE_BLE,
|
|
.uuid = BLE_UUID_ELITE_SERVICE,
|
|
};
|
|
|
|
// Adding proprietary service to the SoftDevice
|
|
err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &elite_context.service_handle);
|
|
APP_ERROR_CHECK(err_code);
|
|
|
|
uint8_t init_val[NRF_SDH_BLE_GATT_MAX_MTU_SIZE - 3];
|
|
memset(init_val, 0x00, sizeof(init_val));
|
|
|
|
// Adding data characteristic to the SoftDevice
|
|
err_code = add_characteristic_ro(BLE_UUID_ELITE_DATA_CHAR, ble_uuid.type, sizeof(init_val), init_val, sizeof(init_val), &elite_context.data_char_handle, true);
|
|
APP_ERROR_CHECK(err_code);
|
|
|
|
// Adding instruction characteristic to the SoftDevice
|
|
err_code = add_characteristic(BLE_UUID_ELITE_INST_CHAR, ble_uuid.type, sizeof(init_val), init_val, sizeof(init_val), &elite_context.inst_char_handle, true);
|
|
APP_ERROR_CHECK(err_code);
|
|
|
|
// Adding event characteristic to the SoftDevice
|
|
err_code = add_characteristic_ro(BLE_UUID_ELITE_EVENT_CHAR, ble_uuid.type, sizeof(init_val), init_val, sizeof(init_val), &elite_context.event_char_handle, true);
|
|
APP_ERROR_CHECK(err_code);
|
|
|
|
// Register a handler for BLE events.
|
|
NRF_SDH_BLE_OBSERVER(m_ble_elite_observer, BLE_ELITE_OBSERVER_PRIO, on_ble_evt_handler, &elite_context);
|
|
|
|
NRF_LOG_INFO("+---------------------+------+");
|
|
NRF_LOG_INFO("| data_char_handle | 0x%02x |", elite_context.data_char_handle.value_handle);
|
|
NRF_LOG_INFO("| inst_char_handle | 0x%02x |", elite_context.inst_char_handle.value_handle);
|
|
NRF_LOG_INFO("| event_char_handle | 0x%02x |", elite_context.event_char_handle.value_handle);
|
|
NRF_LOG_INFO("+---------------------+------+");
|
|
|
|
return NRF_SUCCESS;
|
|
}
|
|
|
|
void le_elite_srv_init(void)
|
|
{
|
|
ret_code_t err_code = elite_srv_init();
|
|
APP_ERROR_CHECK(err_code);
|
|
|
|
elite_init();
|
|
}
|
|
|
|
ret_code_t le_data_notify(uint8_t *p_value, uint16_t len)
|
|
{
|
|
ble_gatts_hvx_params_t hvx_params = {
|
|
.handle = elite_context.data_char_handle.value_handle,
|
|
.type = BLE_GATT_HVX_NOTIFICATION,
|
|
.offset = 0,
|
|
.p_len = &len,
|
|
.p_data = p_value,
|
|
};
|
|
return sd_ble_gatts_hvx(elite_context.conn_handle, &hvx_params);
|
|
}
|
|
|
|
ret_code_t le_data_upadate(uint8_t *p_value, uint16_t len)
|
|
{
|
|
static uint8_t values[1 + NRF_SDH_BLE_GATT_MAX_MTU_SIZE - 3];
|
|
|
|
values[0] = len < 20 ? 20 : len;
|
|
|
|
memcpy(&values[1], p_value, len);
|
|
|
|
// update database.
|
|
ble_gatts_value_t gatts_value = {
|
|
.offset = 0,
|
|
.len = values[0] + 1,
|
|
.p_value = values,
|
|
};
|
|
|
|
uint32_t err_code = sd_ble_gatts_value_set(BLE_CONN_HANDLE_INVALID, elite_context.data_char_handle.value_handle, &gatts_value);
|
|
|
|
memset(&values[1], 0x00, len);
|
|
|
|
return err_code;
|
|
}
|
|
|
|
ret_code_t le_event_notify(uint8_t *p_value, uint16_t len)
|
|
{
|
|
ble_gatts_hvx_params_t hvx_params = {
|
|
.handle = elite_context.event_char_handle.value_handle,
|
|
.type = BLE_GATT_HVX_NOTIFICATION,
|
|
.offset = 0,
|
|
.p_len = &len,
|
|
.p_data = p_value,
|
|
};
|
|
return sd_ble_gatts_hvx(elite_context.conn_handle, &hvx_params);
|
|
}
|
|
|
|
ret_code_t le_event_upadate(uint8_t *p_value, uint16_t len)
|
|
{
|
|
// update database.
|
|
ble_gatts_value_t gatts_value = {
|
|
.offset = 0,
|
|
.len = len,
|
|
.p_value = p_value,
|
|
};
|
|
return sd_ble_gatts_value_set(BLE_CONN_HANDLE_INVALID, elite_context.event_char_handle.value_handle, &gatts_value);
|
|
}
|
|
|
|
#endif // NRF_MODULE_ENABLED(BLE_ELITE)
|