Skip to content

Commit e05bdc9

Browse files
committed
implement BLECharacteristic long write #91,#220
1 parent 457456a commit e05bdc9

File tree

6 files changed

+113
-11
lines changed

6 files changed

+113
-11
lines changed

cores/nRF5/utility/debug.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ static void dump_str_line(uint8_t const* buf, uint16_t count)
169169

170170
void dbgDumpMemory(void const *buf, uint8_t size, uint16_t count, bool printOffset)
171171
{
172-
if ( !buf )
172+
if ( !buf || !count )
173173
{
174174
printf("NULL\n");
175175
return;

libraries/Bluefruit52Lib/src/BLECharacteristic.cpp

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ void BLECharacteristic::_init(void)
5858
_handles.sccd_handle = BLE_GATT_HANDLE_INVALID;
5959
_handles.cccd_handle = BLE_GATT_HANDLE_INVALID;
6060

61+
_long_wr.buffer = NULL;
62+
_long_wr.bufsize = 0;
63+
_long_wr.count = 0;
64+
6165
_rd_authorize_cb = NULL;
6266
_wr_authorize_cb = NULL;
6367
_wr_cb = NULL;
@@ -337,15 +341,84 @@ err_t BLECharacteristic::addDescriptor(BLEUuid bleuuid, void const * content, ui
337341
*/
338342
void BLECharacteristic::_eventHandler(ble_evt_t* event)
339343
{
344+
uint16_t const conn_hdl = event->evt.common_evt.conn_handle;
345+
340346
switch(event->header.evt_id)
341347
{
342348
case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
343349
{
344350
ble_gatts_evt_rw_authorize_request_t * request = &event->evt.gatts_evt.params.authorize_request;
345351

346-
if ( (request->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) && (_wr_authorize_cb != NULL))
352+
if (request->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
347353
{
348-
_wr_authorize_cb(*this, &request->request.write);
354+
ble_gatts_evt_write_t * wr_req = &request->request.write;
355+
356+
switch(wr_req->op)
357+
{
358+
case BLE_GATTS_OP_PREP_WRITE_REQ:
359+
{
360+
// Prepare Long Write
361+
if ( !_long_wr.buffer )
362+
{
363+
// Allocate long write buffer if not previously
364+
_long_wr.bufsize = 1024; // TODO bufsize is 10x MTU
365+
_long_wr.buffer = (uint8_t*) rtos_malloc(_long_wr.bufsize);
366+
_long_wr.count = 0;
367+
}
368+
369+
ble_gatts_rw_authorize_reply_params_t reply = { .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE };
370+
371+
if ( wr_req->offset + wr_req->len > _long_wr.bufsize )
372+
{
373+
reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_PREPARE_QUEUE_FULL;
374+
}else
375+
{
376+
reply.params.write = ((ble_gatts_authorize_params_t) {
377+
.gatt_status = BLE_GATT_STATUS_SUCCESS,
378+
.update = 1,
379+
.offset = wr_req->offset,
380+
.len = wr_req->len,
381+
.p_data = wr_req->data
382+
});
383+
384+
memcpy(_long_wr.buffer+wr_req->offset, wr_req->data, wr_req->len);
385+
_long_wr.count = max16(_long_wr.count, wr_req->offset + wr_req->len);
386+
}
387+
388+
sd_ble_gatts_rw_authorize_reply(conn_hdl, &reply);
389+
}
390+
break;
391+
392+
case BLE_GATTS_OP_EXEC_WRITE_REQ_NOW:
393+
// Execute Long Write
394+
if ( _long_wr.buffer )
395+
{
396+
ble_gatts_rw_authorize_reply_params_t reply = { .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE };
397+
reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
398+
399+
sd_ble_gatts_rw_authorize_reply(conn_hdl, &reply);
400+
401+
// Long write complete, call write callback if set
402+
if (_wr_cb) _wr_cb(*this, _long_wr.buffer, _long_wr.count, 0);
403+
404+
// free up memory
405+
rtos_free(_long_wr.buffer);
406+
_long_wr.buffer = NULL;
407+
_long_wr.bufsize = _long_wr.count = 0;
408+
}
409+
break;
410+
411+
case BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL:
412+
// Cancel Long Write
413+
break;
414+
415+
case BLE_GATTS_OP_WRITE_REQ:
416+
// Write Request with authorization
417+
if (_wr_authorize_cb != NULL) _wr_authorize_cb(*this, &request->request.write);
418+
break;
419+
420+
default: break;
421+
}
349422
}
350423

351424
if ( (request->type == BLE_GATTS_AUTHORIZE_TYPE_READ) && (_rd_authorize_cb != NULL))
@@ -359,12 +432,12 @@ void BLECharacteristic::_eventHandler(ble_evt_t* event)
359432
{
360433
ble_gatts_evt_write_t* request = &event->evt.gatts_evt.params.write;
361434

435+
LOG_LV2_BUFFER(NULL, request->data, request->len);
436+
362437
// Value write
363438
if (request->handle == _handles.value_handle)
364439
{
365440
LOG_LV2("GATTS", "attr's value, uuid = 0x%04X", request->uuid.uuid);
366-
LOG_LV2_BUFFER(NULL, request->data, request->len);
367-
368441
// TODO Ada callback
369442
if (_wr_cb)
370443
{
@@ -385,7 +458,6 @@ void BLECharacteristic::_eventHandler(ble_evt_t* event)
385458
if ( request->handle == _handles.cccd_handle )
386459
{
387460
LOG_LV2("GATTS", "attr's cccd");
388-
LOG_LV2_BUFFER(NULL, request->data, request->len);
389461

390462
// Invoke callback if set
391463
if (_cccd_wr_cb)

libraries/Bluefruit52Lib/src/BLECharacteristic.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,12 @@ class BLECharacteristic
178178
ble_gatts_attr_md_t _attr_meta;
179179
ble_gatts_char_handles_t _handles;
180180

181+
struct {
182+
uint8_t* buffer;
183+
uint16_t bufsize;
184+
uint16_t count;
185+
}_long_wr;
186+
181187
/*------------- Callback pointers -------------*/
182188
read_authorize_cb_t _rd_authorize_cb;
183189
write_authorize_cb_t _wr_authorize_cb;

libraries/Bluefruit52Lib/src/BLEClientCharacteristic.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -461,15 +461,15 @@ void BLEClientCharacteristic::_eventHandler(ble_evt_t* evt)
461461
{
462462
// len is known to be zero for WRITE_REQ
463463
_adamsg.complete();
464-
}else if ( wr_rsp->write_op == BLE_GATT_OP_PREP_WRITE_REQ)
464+
}
465+
else if ( wr_rsp->write_op == BLE_GATT_OP_PREP_WRITE_REQ)
465466
{
466467
uint16_t const max_payload = Bluefruit.Gap.getMTU( _service->connHandle() ) - 3;
467468
uint16_t packet_len = min16(_adamsg.remaining, max_payload-2);
468469

469-
// still has data, continue to prepare
470470
if ( packet_len )
471471
{
472-
// Long Write Prepare
472+
// still has data, continue to prepare Long Write sequence
473473
ble_gattc_write_params_t param =
474474
{
475475
.write_op = BLE_GATT_OP_PREP_WRITE_REQ,
@@ -487,7 +487,7 @@ void BLEClientCharacteristic::_eventHandler(ble_evt_t* evt)
487487
}
488488
}else
489489
{
490-
// Long Write Execute
490+
// All data is prepared, execute Long Write
491491
ble_gattc_write_params_t param =
492492
{
493493
.write_op = BLE_GATT_OP_EXEC_WRITE_REQ,

libraries/Bluefruit52Lib/src/BLEGatt.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,25 @@ void BLEGatt::_eventHandler(ble_evt_t* evt)
124124
BLECharacteristic* chr = _server.chr_list[i];
125125
uint16_t req_handle = BLE_GATT_HANDLE_INVALID;
126126

127+
// BLE_GATTS_OP_EXEC_WRITE_REQ_NOW has no handle, uuid only command op
128+
bool exec_write_now = false;
129+
127130
switch (evt_id)
128131
{
129132
case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
133+
{
130134
// Handle has the same offset for read & write request
131135
req_handle = evt->evt.gatts_evt.params.authorize_request.request.read.handle;
136+
137+
if ( evt->evt.gatts_evt.params.authorize_request.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE )
138+
{
139+
ble_gatts_evt_write_t * wr_req = &evt->evt.gatts_evt.params.authorize_request.request.write;
140+
if ( wr_req->op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW )
141+
{
142+
exec_write_now = true;
143+
}
144+
}
145+
}
132146
break;
133147

134148
case BLE_GATTS_EVT_WRITE:
@@ -139,7 +153,8 @@ void BLEGatt::_eventHandler(ble_evt_t* evt)
139153
}
140154

141155
// invoke characteristic handler if matched
142-
if ((req_handle != BLE_GATT_HANDLE_INVALID) && (req_handle == chr->handles().value_handle || req_handle == chr->handles().cccd_handle ))
156+
if ( exec_write_now ||
157+
((req_handle != BLE_GATT_HANDLE_INVALID) && (req_handle == chr->handles().value_handle || req_handle == chr->handles().cccd_handle)) )
143158
{
144159
chr->_eventHandler(evt);
145160

libraries/Bluefruit52Lib/src/bluefruit.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,15 @@ void AdafruitBluefruit::_ble_handler(ble_evt_t* evt)
816816
sd_ble_gatts_sys_attr_set(_conn_hdl, NULL, 0, 0);
817817
break;
818818

819+
case BLE_EVT_USER_MEM_REQUEST:
820+
// We will handle Long Write sequence (RW Authorize PREP_WRITE_REQ)
821+
sd_ble_user_mem_reply(evt_conn_hdl, NULL);
822+
break;
823+
824+
case BLE_EVT_USER_MEM_RELEASE:
825+
// nothing to do
826+
break;
827+
819828
default: break;
820829
}
821830
}

0 commit comments

Comments
 (0)