Hello nordicers,
I'm stucked with long writes (android central to nrf52 peripheral)
I'm using SDK 12.3 and S132 v300. Android as the client central (RxAndroidBle libary).
before writing:
- I have read ALL the topics on long/queued writes
- I have read the MSCs in the doc.
- I tried VLOC stack and VLOC user
- I tried to mimic the HRS long write example
below is my on_write evt handler (for catching BLE_GATTS_OP_WRITE_REQ and BLE_GATTS_OP_EXEC_WRITE_REQ_NOW )
static void on_write(ble_tds_t * p_tds, ble_evt_t * p_ble_evt){
ble_gatts_evt_write_t* p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
uint16_t handle = *(uint16_t*)mem_buffer.p_mem;
uint16_t len = *(uint16_t*)(mem_buffer.p_mem+2);
uint8_t* buffer = (uint8_t *) (mem_buffer.p_mem+4);
switch (p_evt_write->op){
case BLE_GATTS_OP_WRITE_REQ:
NRF_LOG_DEBUG("BLE_GATTS_OP_WRITE_REQ\r\n");
if (p_evt_write->handle == p_tds->mode_handles.cccd_handle) {
NRF_LOG_DEBUG("mode stats register\r\n");
on_mode_cccd_write(p_tds, p_evt_write);
}
else if (p_evt_write->handle == p_tds->schedule_cal_handles.value_handle) {
NRF_LOG_DEBUG("schedule cal partial write\r\n");
}
else{
NRF_LOG_DEBUG("--> Do Nothing. This event is not relevant for tds::on_write.\n");
}
break;
case BLE_GATTS_OP_EXEC_WRITE_REQ_NOW:
NRF_LOG_DEBUG("BLE_GATTS_OP_EXEC_WRITE_REQ_NOW\r\n");
if(handle == p_tds->schedule_cal_handles.value_handle) {
p_tds->schedule_cal_write_handler(buffer, len);
} else if(handle == p_tds->schedule_pump_handles.value_handle) {
p_tds->schedule_pump_write_handler(buffer, len);
} else{
NRF_LOG_DEBUG("--> Do Nothing. This event is not relevant for tds::on_write.\n");
}
break;
default:
NRF_LOG_DEBUG("--> Do Nothing. This event is not relevant for tds::on_write. the op type is:\n");
// Do Nothing. This event is not relevant for this service.
print_gatts_write_op(p_evt_write->op);
break;
}
}
below is my service ble evt handler (for catching BLE_EVT_USER_MEM_REQUEST and call sd_ble_user_mem_reply)
void ble_tds_on_ble_evt(ble_tds_t * p_tds, ble_evt_t * p_ble_evt)
{
switch (p_ble_evt->header.evt_id) {
case BLE_EVT_USER_MEM_REQUEST:
NRF_LOG_DEBUG("BLE_EVT_USER_MEM_REQUEST\r\n");
mem_buffer.len = BLE_TDS_MAX_LONG_WRITE;
mem_buffer.p_mem = &qwr_buffer[0];
uint32_t err_code;
err_code = sd_ble_user_mem_reply(p_tds->conn_handle, &mem_buffer);
if (err_code != NRF_SUCCESS) {
printf("ERROR sd_ble_user_mem_reply: %u\r\n", (unsigned int)err_code);
} else {
printf("USER_MEM_REQUEST OK\r\n");
}
break; //BLE_EVT_USER_MEM_REQUEST
case BLE_EVT_USER_MEM_RELEASE:
printf("BLE_EVT_USER_MEM_RELEASE\r\n");
if ((p_ble_evt->evt.common_evt.params.user_mem_release.mem_block.p_mem == mem_buffer.p_mem)&&(p_ble_evt->evt.common_evt.params.user_mem_release.mem_block.len == mem_buffer.len)) {
//memory released do nothing.
printf("mem_buffer RELEASE. do nothing\r\n");
}
break;
default:
// No implementation needed.
break;
}
}
below is my add_char function:
static uint32_t schedule_cal_char_add(ble_tds_t * p_tds,
const ble_tds_init_t * p_tds_init)
{
ble_gatts_char_md_t char_md;
ble_gatts_attr_t attr_char_value;
ble_uuid_t ble_uuid;
ble_gatts_attr_md_t attr_md;
memset(&char_md, 0, sizeof(char_md));
char_md.char_props.write = 1; // this will lead to successive WRITE_REQs... but never receive the WRITE_REQ_NOW
// char_md.char_props.write_wo_resp = 1; //this will lead to successive WRITE_CMDs
char_md.p_char_user_desc = NULL;
char_md.p_char_pf = NULL;
char_md.p_user_desc_md = NULL;
char_md.p_cccd_md = NULL;
char_md.p_sccd_md = NULL;
memset(&ble_uuid, 0, sizeof(ble_uuid));
ble_uuid.type = p_tds->uuid_type;
ble_uuid.uuid = BLE_UUID_TDS_SCHEDULE_CAL_CHAR;
memset(&attr_md, 0, sizeof(attr_md));
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
attr_md.vloc = BLE_GATTS_VLOC_USER;
attr_md.rd_auth = 0;
attr_md.wr_auth = 0; //this sends a BLE rw auth request which I can manage in my service evt_handler
attr_md.vlen = 1;
memset(&attr_char_value, 0, sizeof(attr_char_value));
attr_char_value.p_uuid = &ble_uuid;
attr_char_value.p_attr_md = &attr_md;
attr_char_value.init_len = 0;
attr_char_value.init_offs = 0;
attr_char_value.max_len = BLE_TDS_MAX_LONG_WRITE;
return sd_ble_gatts_characteristic_add(p_tds->service_handle,
&char_md,
&attr_char_value,
&p_tds->schedule_cal_handles);
}
I'm stucked with the following problem: if only I tune correctly the char params (like above), I can receive from the SD a burst of BLE_GATTS_OP_WRITE_REQ that correspond to the partial data write. but I never received the BLE_GATTS_OP_EXEC_WRITE_REQ_NOW
And I never receive BLE_EVT_USER_MEM_REQUEST anyway. by the way I also tried to solve my probleme using the QWR library. and I cant' even see the WRITE REQ...
after several days of struggle. any help is appreciated.
thanks