Dialog的DA145XX系列BLE芯片可以配置通用GATT服务以及自定义GATT服务,下面主要说明如何实现GATT服务的配置。
自定义GATT服务参数配置:
自定义服务配置文件在SDK的user_custom_profile目录下的
user_cust_config.c和user_cust1_def.c以及相应的头文件(.h文件)默认最多支持2个自定义UUID的服务。
通过user_cust_config.c文件可以看出宏BLE_CUSTOM1_SERVER和BLE_CUSTOM2_SERVER是是否开启对应服务编译的开关:
const struct cust_prf_func_callbacks cust_prf_funcs[] =
{
#if (BLE_CUSTOM1_SERVER)
{ TASK_ID_CUSTS1,
custs1_att_db,
CUSTS1_IDX_NB,
#if (BLE_APP_PRESENT)
app_custs1_create_db, NULL,
#else
NULL, NULL,
#endif
NULL, NULL,
},
#endif
#if (BLE_CUSTOM2_SERVER)
{ TASK_ID_CUSTS2,
NULL,
0,
#if (BLE_APP_PRESENT)
app_custs2_create_db, NULL,
#else
NULL, NULL,
#endif
NULL, NULL,
},
#endif
{TASK_ID_INVALID, NULL, 0, NULL, NULL, NULL, NULL}, // DO NOT MOVE. Must always be last
};
user_cust1_def.c文件定义了指定的服务下面的特征值和相关参数:
参照示例可以完成自定义BLE服务的创建,并指定服务的特性和UUID。
// Service 1 of the custom server 1
static const att_svc_desc128_t custs1_svc1 = DEF_SVC1_UUID_128;
static const uint8_t SVC1_WRITE_VAL_1_UUID_128[ATT_UUID_128_LEN] = DEF_SVC1_WRITE_VAL_1_UUID_128;
// Attribute specifications
static const uint16_t att_decl_svc = ATT_DECL_PRIMARY_SERVICE;
static const uint16_t att_decl_char = ATT_DECL_CHARACTERISTIC;
static const uint16_t att_desc_cfg = ATT_DESC_CLIENT_CHAR_CFG;
/*
* GLOBAL VARIABLE DEFINITIONS
****************************************************************************************
*/
const uint8_t custs1_services[] = {SVC1_IDX_SVC, CUSTS1_IDX_NB};
const uint8_t custs1_services_size = ARRAY_LEN(custs1_services) - 1;
const uint16_t custs1_att_max_nb = CUSTS1_IDX_NB;
/// Full CUSTS1 Database Description - Used to add attributes into the database
const struct attm_desc_128 custs1_att_db[CUSTS1_IDX_NB] =
{
/*************************
* Service 1 configuration
*************************
*/
// Service 1 Declaration
[SVC1_IDX_SVC] = {(uint8_t*)&att_decl_svc, ATT_UUID_128_LEN, PERM(RD, ENABLE),
sizeof(custs1_svc1), sizeof(custs1_svc1), (uint8_t*)&custs1_svc1},
// Value 1 Characteristic Declaration
[SVC1_WRITE_1_CHAR] = {(uint8_t*)&att_decl_char, ATT_UUID_16_LEN, PERM(RD, ENABLE) , 0, 0, NULL},
// Value 1 Characteristic Value
[SVC1_WRITE_1_VAL] = {SVC1_WRITE_VAL_1_UUID_128, ATT_UUID_128_LEN, PERM(RD, ENABLE) |PERM(WR, ENABLE) | PERM(WRITE_REQ, ENABLE) | PERM(NTF, ENABLE),
DEF_SVC1_WRITE_VAL_1_CHAR_LEN, 0, NULL},
// Value 1 Client Characteristic Configuration Descriptor
[SVC1_WRITE_1_NTF_CFG] = {(uint8_t*)&att_desc_cfg, ATT_UUID_16_LEN, PERM(RD, ENABLE) | PERM(WR, ENABLE) | PERM(WRITE_REQ, ENABLE),
sizeof(uint16_t), 0, NULL},
};
上述代码配置了服务1的的特性:READ、WRITE、NOTIFY,即可读、可写、可通知回复。
custs1_svc1和SVC1_WRITE_VAL_1_UUID_128定义了服务的UUID和服务下Characteristic的UUID。
SVC1_WRITE_1_NTF_CFG(2902)配置了服务通知(NOTIFY)是否开启的说明,可以供client端查看。
自定义服务回调函数:
配置完成服务参数后,需要配置服务的回调函数。
1、在user_callback_config.h里定义回调函数指向
/*
* "app_process_catch_rest_cb" symbol handling:
* - Use #define if "user_catch_rest_hndl" is defined by the user
* - Use const declaration if "user_catch_rest_hndl" is NULL
*/
#define app_process_catch_rest_cb user_catch_rest_hndl
实现自定义回调函数:
//BLE事件处理回调函数
void user_catch_rest_hndl(ke_msg_id_t const msgid,
void const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
switch(msgid)
{
//服务1写数据事件
case CUSTS1_VAL_WRITE_IND:
{
struct custs1_val_write_ind const *msg_param = (struct custs1_val_write_ind const *)(param);
switch( msg_param->handle)
{
case SVC1_WRITE_1_VAL: //服务1写事件
break;
}
} break;
case CUSTS1_ATT_INFO_REQ:
{
struct custs1_att_info_req const *msg_param = (struct custs1_att_info_req const *)param;
switch (msg_param->att_idx)
{
case SVC1_WRITE_1_VAL:
{
struct custs1_att_info_rsp *rsp = KE_MSG_ALLOC(CUSTS1_ATT_INFO_RSP, src_id, dest_id, custs1_att_info_rsp);
// Provide the connection index.
rsp->conidx = app_env[msg_param->conidx].conidx;
// Provide the attribute index.
rsp->att_idx = msg_param->att_idx;
// Provide the current length of the attribute.
rsp->length = 0;
// Provide the ATT error code.
rsp->status = ATT_ERR_NO_ERROR;
ke_msg_send(rsp);
break;
}
default:
{
struct custs1_att_info_rsp *rsp = KE_MSG_ALLOC(CUSTS1_ATT_INFO_RSP,
src_id,
dest_id,
custs1_att_info_rsp);
// Provide the connection index.
rsp->conidx = app_env[msg_param->conidx].conidx;
// Provide the attribute index.
rsp->att_idx = msg_param->att_idx;
// Force current length to zero.
rsp->length = 0;
// Provide the ATT error code.
rsp->status = ATT_ERR_WRITE_NOT_PERMITTED;
ke_msg_send(rsp);
break;
}
}
} break;
case GAPC_PARAM_UPDATED_IND:
{
// Cast the "param" pointer to the appropriate message structure
struct gapc_param_updated_ind const *msg_param = (struct gapc_param_updated_ind const *)(param);
// Check if updated Conn Params filled to preferred ones
if ((msg_param->con_interval >= user_connection_param_conf.intv_min) &&
(msg_param->con_interval <= user_connection_param_conf.intv_max) &&
(msg_param->con_latency == user_connection_param_conf.latency) &&
(msg_param->sup_to == user_connection_param_conf.time_out))
{
}
} break;
case GATTC_CMP_EVT: //GATT Command Complete event
{
struct gattc_cmp_evt const* evt = (struct gattc_cmp_evt const *)(param);
switch(evt->operation)
{
case GATTC_SDP_DISC_SVC_ALL: // Search for all services
break;
case GATTC_WRITE: //写GATT数据完成
break;
case GATTC_READ: //读取GATT数据完成
break;
}
} break;
case GATTC_EVENT_IND: // peer device triggers an event (notification)
break;
case GAPM_CMP_EVT: //GAP Command Complete event
{
struct gapm_cmp_evt const* evt = (struct gapm_cmp_evt const *)(param);
if(evt->operation == GAPM_CANCEL)
{
}
} break;
case GATTC_SDP_SVC_IND: // Service Discovery indicate that a service has been found.
break;
case GATTC_READ_IND: //收到读取回复
{
struct gattc_read_ind const *ind = (struct gattc_read_ind const*)param;
} break;
}
}
BLE数据接收:
CUSTS1_VAL_WRITE_IND:配置服务写事件,外围设备(如APP)下发BLE指令后,在此处可以收到指令。
BLE数据发送:
通过ke_msg_send向内核发送消息通知BLE发送数据给外围设备,带上发送数据段和长度即可。
//BLE发送数据
void app_ble_send_timer_cb(void)
{
struct custs1_val_ntf_ind_req *req = KE_MSG_ALLOC_DYN(CUSTS1_VAL_NTF_REQ,
prf_get_task_from_id(TASK_ID_CUSTS1),
TASK_APP,
custs1_val_ntf_ind_req,
DEF_SVC1_WRITE_VAL_1_CHAR_LEN);
// Send response
req->handle = SVC1_WRITE_1_VAL;
req->notification = true;
req->length = BLE_data_tosend_len;
memcpy(req->value, BLE_send_data_cache, BLE_data_tosend_len);
BLE_data_tosend_len = 0;
ke_msg_send(req);
}
BLE4.2规范之前,一个BLE数据包不能超过20字节。DA14531可配置超过20字节的数据包(最大不超过247)。
在user_config.h文件下,修改gapm_configuration user_gapm_conf 结构体中的max_mtu 的值,即可配置一个BLE数据包的最大长度。
/// Maximal MTU. Shall be set to 23 if Legacy Pairing is used, 65 if Secure Connection is used,
/// more if required by the application
.max_mtu = 140,