This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

long write: receiving partial data only

hello,

I'm trying to send long (73B) data on a given characteristic using Android client as the central.

I well received:

  • USER_MEM_REQUEST OK
>     #define BLE_TDS_MAX_LONG_WRITE    256
> 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 = (uint8_t *) malloc(BLE_TDS_MAX_LONG_WRITE);
    >     > 
    >     > 		uint32_t err_code = sd_ble_user_mem_reply(p_tds->conn_handle, &mem_buffer);
  • BLE_GATTS_OP_EXEC_WRITE_REQ_NOW

    	case BLE_GATTS_OP_EXEC_WRITE_REQ_NOW:
    		NRF_LOG_DEBUG("BLE_GATTS_OP_EXEC_WRITE_REQ_NOW\r\n");
    
    		handle = *(uint16_t*) mem_buffer.p_mem;
    //		offset = *(uint16_t*) (mem_buffer.p_mem+2);
    		len = *(uint16_t*) (mem_buffer.p_mem+4);
    		buffer = (uint8_t *) (mem_buffer.p_mem+6);
    

when reading mem_buffer, the handle is correct but the len is only 18 bytes.

NB: the first 18B in the buffer are correct.

And I dont understand why I dont see the intermediate BLE_GATTS_OP_WRITE_REQ

  • the char description:

    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; 
                        char_md.char_props.notify         	= 1;
                	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_STACK;
                	attr_md.rd_auth 					= 0;
                	attr_md.wr_auth    					= 0;
                    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);
                }
    
  • What do you expect the length to be? 73? This is just the first write, if you have done several writes you should find the next write after the first.

    See this for user memory layout for Queued Writes.

  • hello peter,

    I have the intuition that the problem is on the central side again.

    I think I manage correctly the user memory:

    handle = *(uint16_t*) mem_buffer.p_mem;
    //        offset = *(uint16_t*) (mem_buffer.p_mem+2);
          len = *(uint16_t*) (mem_buffer.p_mem+4);
          buffer = (uint8_t *) (mem_buffer.p_mem+6);
    

    AFAIK I should receive first the successive BLE_GATTS_OP_WRITE_REQ and then, when the transfer is finalized, the BLE_GATTS_OP_EXEC_WRITE_REQ_NOW. isn't it ?

  • It seems to me you are doing this, then you will only receive BLE_EVT_USER_MEM_REQUEST and BLE_GATTS_EVT_WRITE with BLE_GATTS_OP_EXEC_WRITE_REQ_NOW.

    The stack will receive ATT Prepare Write requests, but these will not be notified to the application.

  • yes this is what I (try to) do. ok thanks, then it is normal I dont receive the ATT Prepare Write requests at the app level. I will investigate the central side. thx

Related