当某个特性具有写、读、通知等多个功能时,目前我们6621E的服务以及接口是每次写数据的时候,会更新底层该特性的有效值的长度信息,也就是这次主机写100字节,下次主机读取的时候,从机就会回100字节。如果主机写50字节,那么主机再读的时候,从机就会回50字节。但是考虑到有些客户的需求是,假设当主机写100字节的时候,主机调用读特性的时候,从机可以回1字节,也可以回17字节,而不是回100字节。那么这种不定长数据应该怎么修改呢?
具体的修改方法如下:
1、新增读接口回调函数: void ble_set_read_calblack(void (*callback)(co_msg_id_t id, co_layer_id_t dst, co_layer_id_t src, void *param)) { co_msg_register(LAYER_L2CAP, callback); } 2、main函数注册读接口回调函数: ble_set_read_calblack(l2cap_msg_process_handle_wrapper); 该函数在softdevice_ble_evt_handler_set(on_ble_evt);后面执行就可以 3、读接口回调函数如下: void l2cap_msg_process_handle_wrapper(co_msg_id_t id, co_layer_id_t dst, co_layer_id_t src, void * param) { if ((dst == LAYER_L2CAP) && (src == LAYER_LL) && (id == MSG_ACL_DATA) && param) { msg_acl_t* acl_data = (msg_acl_t*)param; uint8_t pb = ((acl_data->conhdl & 0x3000) >> 12); if (pb == 0x02) { // First packet uint8_t* p = acl_data->pdata; p += sizeof(uint16_t); uint16_t cid = p[0] + (p[1] << 8); if(cid == 0x04) { uint8_t * data = acl_data->pdata; uint8_t att_opcode = data[4]; if (att_opcode == 0xA) { // read request uint16_t att_handle = data[5] + (data[6] << 8); log_debug("Read ATT handle: 0x%02X\n", att_handle); // TODO: do something if (att_handle == 0x17) { att_db_t* att_db = ((att_db_t*(*)(uint16_t, uint16_t))0x001096cd)(att_handle, 0x0A); att_db->value_len = 2;//user define } } } } } void l2cap_msg_process_handle(co_msg_id_t id, co_layer_id_t dst, co_layer_id_t src, void * param); l2cap_msg_process_handle(id, dst, src, param); } 注意:上文中的if (att_handle == 0x17)只是做举例,实际使用应该根据客户需求,修改对应的句柄值,也就是if (att_handle == 0xxxxx),这个0xxxxx就是用户实际需要的句柄。这个0xxxxx应该是我们在注册蓝牙服务,添加特性时,会返回一个存储句柄信息的结构体handles,而我们想要操作的句柄是:handles.value_handle。om_ble_gatts_characteristic_add(m_start_handle, &char_md, &attr_char_value, &handles); 。把自己想传的字节长度赋值给att_db->value_len。
|