BLE芯片DA145XX系列:自定义GATT服务配置

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,
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值