Commit 32a384f0 authored by Pierre Guinault's avatar Pierre Guinault
Browse files

ble_dsk : example with click and led switching services

parents
Pipeline #6 skipped
Documentation can be found offline at: <keil_location>/ARM/Pack/NordicSemiconductor//11.0.0-2.alpha/documentation
Documentation can be found online at: http://developer.nordicsemi.com/nRF51_SDK/doc/
\ No newline at end of file
/* =========================================================================
* This module creates a custom bluetooth service and its attached
* characteristics. It can be intentiated multiple times to create multiple
* service and services can have misc read/write/notify characteristics of
* any object size.
* -------------------------------------------------------------------------
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
* You can obtain a non GPL version of this program by contacting me
* on www.disk91.com
* --------------------------------------------------------------------------
* (c) 2015 Paul Pinault / disk91.com
* --------------------------------------------------------------------------
* 2015-12-19 - creation
* ==========================================================================
* usage : ble_dsk_internal contains internal structure and constants
* ==========================================================================
*/
#ifndef __BLE_DSK_INTERNAL__
#define __BLE_DSK_INTERNAL__
#define __BLE_DSK_MAX_SERVICES 10 // maximum number of services the structure can manage
#define __BLE_DSK_MAX_CHARACTERISTICS 5 // maximum characteristics per services the structures can manage
#define __BLE_DSK_MAX_TOTAL_CHARACT 20 // maximum characteristics the library will manage ... overall
#define __BLE_DSK_MAX_STRING_SIZE 64 // maximum size of the String type structures
#define __BLE_DSK_MAX_DATA_SIZE 16 // maximum size of any of the data exchanged over the characteristics
#ifndef APP_TIMER_PRESCALER
#define APP_TIMER_PRESCALER 0 // Value of the RTC1 PRESCALER register.
#endif
#define __BLE_DSK_ERROR_ERROR 0xFF // return value indicating an error
#endif // __BLE_DSK_INTERNAL__
This diff is collapsed.
/* =========================================================================
* This module is initializing a ble_peripherical device from a simple
* given structure and create all the needed services & charcarteristics
* -------------------------------------------------------------------------
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
* You can obtain a non GPL version of this program by contacting me
* on www.disk91.com
* --------------------------------------------------------------------------
* (c) 2015 Paul Pinault / disk91.com
* --------------------------------------------------------------------------
* 2015-12-19 - creation
* ==========================================================================
* usage :
* ==========================================================================
*/
#ifndef __BLE_DSK_PERIPHERICAL__
#define __BLE_DSK_PERIPHERICAL__
// Includes BAS(BAttery Service) - unactivate by setting to 0 in your main file
#ifndef WITH_BAS_SERVICE
#define WITH_BAS_SERVICE 1
#endif
// Includes DIS(Device Information Service) - unactivate by setting to 0 in your main file
#ifndef WITH_DIS_SERVICE
#define WITH_DIS_SERVICE 1
#endif
// Includes DFU(Device Firmware Update) - unactivate by setting to 0 in your main file
#ifndef WITH_DFU_SERVICE
#define WITH_DFU_SERVICE 0
#endif
#include "ble_gattc.h"
#include <stdint.h>
#include <stdbool.h>
#include "ble_dsk_internal.h"
#include "ble_dsk_service.h"
#include "ble.h"
#include "ble_advdata.h"
#include "ble_advertising.h"
#include "ble_conn_params.h"
#include "device_manager.h"
#include "pstorage.h"
#if WITH_BAS_SERVICE == 1
#include "ble_bas.h"
#endif
#if WITH_DIS_SERVICE == 1
#include "ble_dis.h"
#endif
#if WITH_DFU_SERVICE == 1
#include "ble_dfu.h"
#endif
/* ----------------------------------------------------------------------
* Initialization structure - this structure defines how the peripherical
* will be created / initialized ; this structure
* is readonly to be stored in flash
* ----------------------------------------------------------------------
*/
typedef struct ble_dsk_peripherical_s {
char periph_name[__BLE_DSK_MAX_STRING_SIZE]; // Name of the peripherical, will be displays in desc service if activiated
bool add_mac_address; // Add 4 mac address last digit at end on name periphname-MMMM
char manuf_name[__BLE_DSK_MAX_STRING_SIZE]; // Manufacturer name
uint16_t appearance_type; // Type of device see BLE_APPEARANCE_XXX from ble_gap.h
uint8_t basic_service; // BitField with service to be activated on startup use (BLE_DSK_SERVICE_XXX)
bool uuid_128; // True if the UUID to be used will be 128b
ble_uuid128_t nus_base_uuid; // 128b UUID base (only needed if uuid_128 = true) Format = { xx,xx,xx ... x16}
// See - http://www.itu.int/en/ITU-T/asn1/Pages/UUID/generate_uuid.aspx
// for creating your own UUID base
uint16_t config_bitfield; // BitField for different configuration see (BLE_DSK_CONFIG_XXX)
// advertising parameters
uint8_t advertising_mode; // type of advertising (direct (automatically reconnect) / slow (preserve nrj / fast (default))
uint16_t advertising_dir_fast_interval; // Time in ms between two ble advertisement (direct&fast mode)
uint32_t advertising_dir_fast_timeout; // advertisement duration (then stop) in second - 0 for unlimited // # of time if direct mode
uint16_t advertising_slow_interval; // Time in ms between two ble advertisement (second and next of the selected modes)
uint32_t advertising_slow_timeout; // advertisement duration (then stop) in second - 0 for unlimited // # of time if direct mode
void (* on_start_advertizing)(uint8_t adv_mode); // function called when advertizing starts
void (* on_stop_advertizing)(uint8_t adv_mode); // functioncalled when advertising goes back to idle / if NULL -> sleep_mode_enter default behavior
// Security parameter
uint8_t sec_options; // list of possible security options - see BLE_DSK_SEC_OPTIONS_XXX
uint8_t sec_io_capabilities; // indicate if device have I/O capability for managind security see BLE_GAP_IO_XXX
// default BLE_GAP_IO_CAPS_NONE
uint8_t sec_oob_data; // Out of band data - default 0 - none
uint8_t sec_min_key_size; // Minimum encryption key size - default 7
uint8_t sec_max_key_size; // Maximum encryption key size - default 16
// Gap parameters - see https://devzone.nordicsemi.com/question/60/what-is-connection-parameters/
// Min and Max determines data request frequency wish from central ; it can be from 7.5ms to 4s
uint16_t gap_min_cnx_interval; // Minimum connection interval in 1.25ms step - see BLE_GAP_CP_LIMITS in ble_gap.h
uint16_t gap_max_cnx_interval; // Maximum connection interval in 1.25ms step - see BLE_GAP_CP_LIMITS in ble_gap.h
// Slave latency if > 0 is the number of time the slave can decide to not respond to central up to this
// number of time if it have no new data to transmit
uint16_t gap_slave_latency; // Maximum slave latency in number of connection event - see BLE_GAP_CP_LIMITS in ble_gap.h
// Supervisor Link timeout is time until the connection will be concidered as lost if no data has been exchanged
uint16_t gap_cnx_sup_timeout; // Connection Supervision Timeout in 10 ms units - see BLE_GAP_CP_LIMITS in ble_gap.h
// Connection parameter
uint32_t cnx_time_from_connect_to_update; // time in 0.1 seconds between device connection and first call to update function
uint32_t cnx_time_between_update; // time in 0.1 seconds between two call on update function
uint8_t cnx_max_cnx_attempt; // Number of attempts before giving up the negotiation
bool cnx_disconnect_on_fail; // On a failed update we can disconnect of not
// Battery Service - is requiered
uint8_t (* getBatteryInfo)(); // Function that returns battery level on a 8 bits uchar - NULL if unused
// Services description
uint8_t service_count; // Number of service in the following table
const ble_dsk_service_desc_t * services; // List of service description
} ble_dsk_peripherical_t;
/* ----------------------------------------------------------------------
* some default values
* ----------------------------------------------------------------------
*/
#define BLE_DSK_SEC_DEFAULT_OPTIONS (BLE_DSK_SEC_OPTIONS_BONDING | BLE_DSK_SEC_OPTIONS_MITM)
#define BLE_DSK_SEC_DEFAULT_MITM true
#define BLE_DSK_SEC_DEFAULT_IOCAPA BLE_GAP_IO_CAPS_NONE
#define BLE_DSK_SEC_DEFAULT_OOBDATA 0
#define BLE_DSK_SEC_DEFAULT_MINKEYSZ 7
#define BLE_DSK_SEC_DEFAULT_MAXKEYSZ 16
#define BLE_DSK_GAP_DEFAULT_MINCNX MSEC_TO_UNITS(100, UNIT_1_25_MS) // 100 ms
#define BLE_DSK_GAP_DEFAULT_MAXCNX MSEC_TO_UNITS(200, UNIT_1_25_MS) // 200 ms
#define BLE_DSK_GAP_DEFAULT_SLAVLAT 0
#define BLE_DSK_GAP_DEFAULT_CNXSUPTM MSEC_TO_UNITS(4000, UNIT_10_MS) // 4s
#define BLE_DSK_ADV_DEFAULT_INTERVAL 50 // 50ms advertising
#define BLE_DSK_ADV_DEFAULT_TIMEOUT 0 // Never stop advertising
#define BLE_DSK_ADV_DEFAULT_MODE BLE_DSK_ADV_MODE_FAST // Fast Advertizing by default
#define BLE_DSK_CNX_DEFAULT_CNX_TIME 50 // 5 seconds
#define BLE_DSK_CNX_DEFAULT_CNX_UPDATE 300 // 30 seconds
#define BLE_DSK_CNX_DEFAULT_CNX_TRY 3 // 3
#define BLE_DSK_CNX_DEFAULT_DISC_ON_FAIL false // do not disconnect on failed
/* ----------------------------------------------------------------------
* Advertising mode (cumulative) - when multiple are active, the order is
* Direct >> Fast >> Slow >> Idle an event is fired each time one start
* ----------------------------------------------------------------------
*/
#define BLE_DSK_ADV_MODE_IDLE 0 // No advertising
#define BLE_DSK_ADV_MODE_WHITELIST 1 // Try to connect to one of the previous devices
#define BLE_DSK_ADV_MODE_DIRECT_SLOW 2 // try to connect to previous device
#define BLE_DSK_ADV_MODE_DIRECT 4 // Try to connect to previous device
#define BLE_DSK_ADV_MODE_SLOW 8 // Connect any device but preserve energy
#define BLE_DSK_ADV_MODE_FAST 16 // Connect any device with fast advertise (more energy)
/* ----------------------------------------------------------------------
* Peripherical security options
* ----------------------------------------------------------------------
*/
#define BLE_DSK_SEC_OPTIONS_NONE 0
#define BLE_DSK_SEC_OPTIONS_BONDING 2 // security uses bonding (same as encryption)
#define BLE_DSK_SEC_OPTIONS_ENCRYPTION 2 // security uses encryption (same as encryption)
#define BLE_DSK_SEC_OPTIONS_MITM 4 // security against Man in the Middle attack
#define BLE_DSK_SEC_OPTIONS_SIGNING 8 // security requires signature
/* ----------------------------------------------------------------------
* Peripherical configuration switch
* ----------------------------------------------------------------------
*/
#define BLE_DSK_CONFIG_NONE 0
#define BLE_DSK_CONFIG_SERVICE_CHANGE_CHAR 1 // Allows to change the device service list dynamically
/* ----------------------------------------------------------------------
* List default services to instanciate
* ----------------------------------------------------------------------
*/
#define BLE_DSK_SERVICE_NONE 0
#if WITH_BAS_SERVICE == 1
#define BLE_DSK_SERVICE_BAS 1 // BAttery Service
#endif
#if WITH_DIS_SERVICE == 1
#define BLE_DSK_SERVICE_DIS 2 // Device Info Service
#endif
#if WITH_DFU_SERVICE == 1
#define BLE_DSK_SERVICE_DFU 4 // Device Firmware Update
#endif
/* ----------------------------------------------------------------------
* Internal peipherical structure
* ----------------------------------------------------------------------
*/
typedef struct ble_dsk_dyn_peripherical_s {
// configuration
const ble_dsk_peripherical_t * peripherical; // const initialization structure
// device manager
dm_application_instance_t dm_app_handle; // device manager data structure
bool erase_bonds; // flag from device manager to request for erasing
// bonding (encryption) information from pstorage
// advertising data
ble_advdata_t adv_data; // advertising configuration
// Connection
uint16_t m_conn_handle; // Handle of the current connection - set by on_connect event
// uuid data
ble_uuid_t m_adv_uuids[__BLE_DSK_MAX_SERVICES+2];// structure to build the uuid list
uint8_t service_count; // number of service configured
uint8_t uuid_type; // store uuid type created for 128b services or standard one
// Battery Service
#if WITH_BAS_SERVICE == 1
ble_bas_t m_bas;
#endif
// Custom services
uint8_t service_handler[__BLE_DSK_MAX_SERVICES]; // index to the corresponding service dynamic structure
// limited to peripherical->service_count
} ble_dsk_dyn_peripherical_t;
extern ble_dsk_dyn_peripherical_t ble_dsk_dyn_peripherical;
/* -----------------------------------------------------------------------
* External sub functions
* -----------------------------------------------------------------------
*/
void ble_dsk_peripherical_init(const ble_dsk_peripherical_t * _init);
void advertising_init(uint8_t mode, uint16_t dir_fast_interval, uint32_t dir_fast_timeout, uint16_t slow_interval, uint32_t slow_timeout);
/* -----------------------------------------------------------------------
* internal sub functions
* -----------------------------------------------------------------------
*/
static void ble_evt_dispatch(ble_evt_t * p_ble_evt);
static void sys_evt_dispatch(uint32_t sys_evt);
static void on_adv_evt(ble_adv_evt_t ble_adv_evt);
static void on_conn_params_evt(ble_conn_params_evt_t * p_evt);
static void conn_params_error_handler(uint32_t nrf_error);
static uint32_t device_manager_evt_handler(dm_handle_t const * p_handle, dm_event_t const * p_event, ret_code_t event_result);
#endif // __BLE_DSK_PERIPHERICAL__
/* =========================================================================
* This module creates a custom bluetooth service and its attached
* characteristics. It can be intentiated multiple times to create multiple
* service and services can have misc read/write/notify characteristics of
* any object size.
* -------------------------------------------------------------------------
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
* You can obtain a non GPL version of this program by contacting me
* on www.disk91.com
* --------------------------------------------------------------------------
* (c) 2015 Paul Pinault / disk91.com
* --------------------------------------------------------------------------
* 2015-12-19 - creation
* ==========================================================================
* usage :
* ==========================================================================
*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "ble_dsk_peripherical.h"
#include "ble_dsk_service.h"
#include "ble_srv_common.h"
#include "ble_gatts.h"
#include "app_error.h"
/* -----------------------------------------------------------------------
* global structure to store service & characteristics informations
* -----------------------------------------------------------------------
*/
ble_dsk_dyn_service_t ble_dsk_dyn_service[__BLE_DSK_MAX_SERVICES];
ble_dsk_dyn_characteristic_t ble_dsk_dyn_characteristic[__BLE_DSK_MAX_TOTAL_CHARACT];
static int last_service = 0; // index to the last service structure used
static int last_characteristic = 0; // index to the last characteristic used
/* ---------------------------------------------------------------------
* Allocate BLE service structure and associate uuid
* ---------------------------------------------------------------------
*/
uint8_t ble_dsk_service_allocated(const ble_dsk_service_desc_t * _init, ble_uuid_t * _uuid) {
uint8_t ret;
// ---------------------------------------
// Init for service structure
if ( last_service < __BLE_DSK_MAX_SERVICES ) {
ble_dsk_dyn_service_t * _s = &ble_dsk_dyn_service[last_service];
memset(_s, 0, sizeof(ble_dsk_dyn_service_t));
_s->service_desc = _init;
_s->ble_uuid = _uuid;
ret = last_service;
last_service++;
} else ret = __BLE_DSK_ERROR_ERROR;
return ret;
}
/* ---------------------------------------------------------------------
* Allocate BLE characteristic structure
* ---------------------------------------------------------------------
*/
static uint8_t ble_dsk_characteristic_allocated(const ble_dsk_characteristic_desc_t * _init) {
uint8_t ret;
// ---------------------------------------
// Init for characteristic structure
if ( last_characteristic < __BLE_DSK_MAX_TOTAL_CHARACT ) {
ble_dsk_dyn_characteristic_t * _c = &ble_dsk_dyn_characteristic[last_characteristic];
memset(_c, 0, sizeof(ble_dsk_dyn_characteristic_t));
_c->char_desc = _init;
ret = last_characteristic;
last_characteristic++;
} else ret = __BLE_DSK_ERROR_ERROR;
return ret;
}
/* ---------------------------------------------------------------------
* Init all Ble Services
* ---------------------------------------------------------------------
*/
uint8_t ble_dsk_service_init() {
int i,j;
uint32_t err_code;
for ( i = 0 ; i < last_service ; i++ ) {
ble_dsk_dyn_service_t * _s = &ble_dsk_dyn_service[i];
// -----------------------------------------------------------------
// Register service
_s->report_ref_handler = BLE_CONN_HANDLE_INVALID;
err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, _s->ble_uuid ,&_s->service_handler );
APP_ERROR_CHECK(err_code);
// -----------------------------------------------------------------
// Register characteristics
for ( j = 0 ; j < _s->service_desc->num_char ; j++ ) {
int idx_char = ble_dsk_characteristic_allocated(&_s->service_desc->charact[j]);
if ( idx_char != __BLE_DSK_ERROR_ERROR ) {
_s->chars_handler[j] = idx_char;
ble_dsk_dyn_characteristic_t * _c = &ble_dsk_dyn_characteristic[idx_char];
// check if notify is configured
// @ TODO - revoir avec les notions de securit ...
//BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&cccd_md.read_perm); <- a priori ne peut pas etre securis
//BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&cccd_md.write_perm);
if ( (_c->char_desc->char_access_right & BLE_DSK_ACC_NOTIFY) != 0 ) {
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&_c->char_cccd.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&_c->char_cccd.write_perm);
_c->char_cccd.vloc = BLE_GATTS_VLOC_STACK;
_c->char_md.char_props.notify = 1;
_c->char_md.p_cccd_md = &_c->char_cccd;
} else {
_c->char_md.char_props.notify = 0;
_c->char_md.p_cccd_md = NULL;
}
// Create access metadata
if ( (_c->char_desc->char_access_right & BLE_DSK_ACC_READ) != 0 ) {
_c->char_md.char_props.read = 1;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&_c->char_attr.read_perm);
} else {
BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&_c->char_attr.read_perm);
}
if ( (_c->char_desc->char_access_right & BLE_DSK_ACC_WRITE) != 0 ) {
_c->char_md.char_props.write = 1;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&_c->char_attr.write_perm);
} else {
BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&_c->char_attr.write_perm);
}
// Other Misc metdata
_c->char_md.p_char_user_desc = NULL;
_c->char_md.p_char_pf = NULL;
_c->char_md.p_user_desc_md = NULL;
_c->char_md.p_sccd_md = NULL;
// Create attributes
_c->char_attr.vloc = BLE_GATTS_VLOC_STACK;
_c->char_attr.rd_auth = 0;
_c->char_attr.wr_auth = 0;
_c->char_attr.vlen = 0;
_c->char_attr.rd_auth = (_c->char_desc->onRead != NULL)?1:0;
_c->char_attr.wr_auth = 0; // actually not managed
// Create value attribute
BLE_UUID_BLE_ASSIGN(_c->char_uuid, _c->char_desc->char_uuid);
_c->char_value.p_uuid = &_c->char_uuid;
_c->char_value.p_attr_md = &_c->char_attr;
_c->char_value.init_len = _c->char_desc->char_data_len;
_c->char_value.init_offs = 0;
_c->char_value.max_len = _c->char_desc->char_data_len;
memcpy(_c->char_data,_c->char_desc->char_data_init,_c->char_desc->char_data_len);
_c->char_value.p_value = _c->char_data;
// Create characteristic
err_code = sd_ble_gatts_characteristic_add( _s->service_handler, &_c->char_md, &_c->char_value, &_c->char_handler);
APP_ERROR_CHECK(err_code);
} else {
APP_ERROR_CHECK(NRF_ERROR_FORBIDDEN);
}
}
}
return NRF_SUCCESS;
}
/* -----------------------------------------------------------------------------------
* External update request
* -----------------------------------------------------------------------------------
*/
uint32_t ble_dsk_update(const ble_dsk_characteristic_desc_t * _charac, uint8_t * value) {
uint32_t err_code = NRF_SUCCESS;
ble_dsk_dyn_characteristic_t * _c = getCharacteristicByCharDesc(_charac);
if ( _c != NULL ) {
// copy new value
memcpy(_c->char_data,value,_c->char_desc->char_data_len);
// send new value
ble_gatts_value_t _value;
memset(&_value, 0, sizeof(_value));
_value.len = _c->char_desc->char_data_len;
_value.offset = 0;
_value.p_value = _c->char_data;
err_code = sd_ble_gatts_value_set(ble_dsk_dyn_peripherical.m_conn_handle,
_c->char_handler.value_handle,
&_value);
// Notify
if ( ble_dsk_dyn_peripherical.m_conn_handle != BLE_CONN_HANDLE_INVALID
&& ( _c->char_desc->char_access_right & BLE_DSK_ACC_NOTIFY ) != 0 ) {
ble_gatts_hvx_params_t hvx_params;
memset(&hvx_params, 0, sizeof(hvx_params));
hvx_params.handle = _c->char_handler.value_handle;
hvx_params.type = BLE_GATT_HVX_NOTIFICATION;
hvx_params.offset = _value.offset;
hvx_params.p_len = &_value.len;
hvx_params.p_data = _value.p_value;
err_code = sd_ble_gatts_hvx(ble_dsk_dyn_peripherical.m_conn_handle, &hvx_params);
} else {
return NRF_ERROR_INVALID_STATE;
}
} else {
return NRF_ERROR_NULL;
}
return err_code;
}
/* -----------------------------------------------------------------------------------
* Event Management
* -----------------------------------------------------------------------------------
*/
/* ble_dsk_on_event_dispatch
* dispatch the event to the associated callback
*/
void ble_dsk_on_event_dispatch(ble_evt_t * p_ble_evt)
{
switch (p_ble_evt->header.evt_id)
{
case BLE_GATTS_EVT_WRITE:
{
ble_gatts_evt_write_t * p_evt_write = &(p_ble_evt->evt.gatts_evt.params.write);
ble_dsk_dyn_characteristic_t * _c = getCharacteristicByValueHandler(p_evt_write->handle);
if ( _c != NULL ) {
if ( p_evt_write->len == _c->char_desc->char_data_len ) {
memcpy(_c->char_data,p_evt_write->data,_c->char_desc->char_data_len);
_c->char_desc->onWrite(_c->char_data);
}
}
}
break;
// --------------------------------------------------------------------------
// This is a way to manage onRead event firing - request for an authorize
// before any read when the callback is defined. The function will return a
// new value and an authorzation (or not)
case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
{
if ( p_ble_evt->evt.gatts_evt.params.authorize_request.type == BLE_GATTS_AUTHORIZE_TYPE_READ ) {
uint16_t _handler = p_ble_evt->evt.gatts_evt.params.authorize_request.request.read.context.value_handle;
ble_dsk_dyn_characteristic_t * _c = getCharacteristicByValueHandler(_handler);
if ( _c != NULL ) {
ble_gatts_rw_authorize_reply_params_t reply;
memset(&reply,0,sizeof(reply));
reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ;
if (_c->char_desc->onRead(_c->char_data) ) {
reply.params.read.gatt_status = BLE_GATT_STATUS_SUCCESS;
reply.params.read.update = 1;
reply.params.read.offset = 0;
reply.params.read.len = _c->char_desc->char_data_len;
reply.params.read.p_data = _c->char_data;
} else {
reply.params.read.gatt_status = BLE_GATT_STATUS_ATTERR_READ_NOT_PERMITTED;
}
sd_ble_gatts_rw_authorize_reply(ble_dsk_dyn_peripherical.m_conn_handle ,&reply);
}
}
}
break;
default:
// No implementation needed.
break;
}
}
/* -----------------------------------------------------------------------------------
* misc internal function
* -----------------------------------------------------------------------------------
*/
static ble_dsk_dyn_characteristic_t * getCharacteristicByValueHandler(uint16_t _handler) {
int i;
for ( i = 0 ; i < last_characteristic ; i++ ) {
if ( ble_dsk_dyn_characteristic[i].char_handler.value_handle == _handler )
return &ble_dsk_dyn_characteristic[i];
}
return NULL;
}
static ble_dsk_dyn_characteristic_t * getCharacteristicByCharDesc(const ble_dsk_characteristic_desc_t * _caract) {
int i;
for ( i = 0 ; i < last_characteristic ; i++ ) {
if ( ble_dsk_dyn_characteristic[i].char_desc == _caract )
return &ble_dsk_dyn_characteristic[i];
}
return NULL;
}
/* =========================================================================