2019-07-17 01:17 AM
HI, while learning how to use IDB05A1 shield with nucleo n053r8 I've stumbled over a problem. I've modified SensorDemo_BLESensor-App (from package X-CUBE-BLE 1.4.40) code to create my own server with 2 characteristics:
/**
* @brief Add the SW Feature service using a vendor specific profile
* @param None
* @retval tBleStatus Status
*/
tBleStatus Add_RX_TX_service(void)
{
tBleStatus ret;
int32_t NumberOfRecords=1;
uint8_t uuid[16];
COPY_NOYAK_SERVICE_UUID(uuid);
BLUENRG_memcpy(&service_uuid.Service_UUID_128, uuid, 16);
ret = aci_gatt_add_serv(
UUID_TYPE_128,
service_uuid.Service_UUID_128,
PRIMARY_SERVICE,
6, // liczba rekordow (3 * liczba charakterystyk ?)
&RXTX_Service_handle);
if (ret != BLE_STATUS_SUCCESS) {
goto fail;
}
COPY_TX_UUID(uuid);
BLUENRG_memcpy(&char_uuid.Char_UUID_128, uuid, 16);
ret = aci_gatt_add_char(
RXTX_Service_handle,
UUID_TYPE_128, char_uuid.Char_UUID_128,
20,
CHAR_PROP_READ,
ATTR_PERMISSION_NONE | CHAR_PROP_NOTIFY,
GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP,
20,
0,
&TX_handle);
if (ret != BLE_STATUS_SUCCESS) {
goto fail;
}
PRINTF("TX characteristick initialized\n");
COPY_RX_UUID(uuid);
BLUENRG_memcpy(&char_uuid.Char_UUID_128, uuid, 16);
ret = aci_gatt_add_char(
RXTX_Service_handle,
UUID_TYPE_128, char_uuid.Char_UUID_128,
20,
CHAR_PROP_WRITE | CHAR_PROP_WRITE_WITHOUT_RESP,
ATTR_PERMISSION_NONE,
GATT_NOTIFY_ATTRIBUTE_WRITE,
20,
1,
&RX_handle);
if (ret != BLE_STATUS_SUCCESS) {
PRINTF("ret error: %02X", ret);
goto fail;
}
PRINTF("RX characteristick initialized\n");
return BLE_STATUS_SUCCESS;
fail:
return BLE_STATUS_ERROR;
}
And that works fine.
Next, I've started working on RX characteristic - first simple task was to print everything received from the PC to uart debug console:
Event callback:
/**
* @brief Callback processing the ACI events.
* @note Inside this function each event must be identified and correctly
* parsed.
* @param void* Pointer to the ACI packet
* @retval None
*/
void user_notify(void * pData)
{
hci_uart_pckt *hci_pckt = pData;
/* obtain event packet */
hci_event_pckt *event_pckt = (hci_event_pckt*)hci_pckt->data;
if(hci_pckt->type != HCI_EVENT_PKT)
return;
PRINTF("HCI EVENT: 0x%02X\n", event_pckt->evt);
switch(event_pckt->evt){
case EVT_DISCONN_COMPLETE:
{
GAP_DisconnectionComplete_CB();
}
break;
case EVT_LE_META_EVENT:
{
evt_le_meta_event *evt = (void *)event_pckt->data;
switch(evt->subevent){
case EVT_LE_CONN_COMPLETE:
{
evt_le_connection_complete *cc = (void *)evt->data;
GAP_ConnectionComplete_CB(cc->peer_bdaddr, cc->handle);
}
break;
}
}
break;
case EVT_VENDOR:
{
evt_blue_aci *blue_evt = (void*)event_pckt->data;
PRINTF("event code 0x%04X\n", blue_evt->ecode);
switch(blue_evt->ecode){
case EVT_BLUE_GATT_READ_PERMIT_REQ:
{
PRINTF("EVENT notify");
evt_gatt_read_permit_req *pr = (void*)blue_evt->data;
Read_Request_CB(pr->attr_handle);
}
break;
/*********************** MY CODE ***********************/
case EVT_BLUE_GATT_ATTRIBUTE_MODIFIED:
{
evt_gatt_attr_modified_IDB05A1 *event = (evt_gatt_attr_modified_IDB05A1*)event_pckt->data;
PRINTF("connection handle: %04X\n"
"attribute handle : %04X\n"
"data lenth : : %02X\n"
"offset : %04X\n",
event->conn_handle,
event->attr_handle,
event->data_length,
event->offset);
PRINTF("RX <-");
for(int i=0; i< event->data_length + 6; i++){
PRINTF(" %02X", event->att_data[i]);
}
PRINTF("\n");
break;
}
/***********************end of MY CODE ***********************/
}
}
break;
}
}
problems: :
I use GNU Arm Embedded Toolchain on windows 10 with makefile generated from CubeMx for compiling my source code. CubeMX project attached.
Can someone confirm if all those things are bugs to be reported
2019-07-17 01:46 AM
PS I test my software using Bluetooth LE explorer: https://www.microsoft.com/en-us/p/bluetooth-le-explorer/9n0ztkf1qd98?activetab=pivot:overviewtab
2019-07-18 12:30 AM
Hi Kayon,
This is interesting.
I think probably the stack has been updated and ACI_GATT_ATTRIBUTE_MODIFIED_EVENT format shall be the same as BlueNRG-1/2:
In this case, please try to modify evt_gatt_attr_modified_IDB05A1 structure like:
typedef __packed struct _evt_gatt_attr_modified_IDB05A1{
uint16_t conn_handle;
uint16_t attr_handle;
uint16_t offset; //4th 5th byte
uint8_t data_length; //6th byte
uint8_t att_data[VARIABLE_SIZE];
} PACKED evt_gatt_attr_modified_IDB05A1;
When you saw event->data_length always being 0x10, i guess it was because bit 15 in real offset was 1 to indicate other events will follow for the remaining value.
And you saw event->offset having data length, because low byte in real offset (5th byte) is 0, which accidentally makes your offset having high byte equal to 0 and low byte equal to real data_length (6th byte).
These shall explain the length and offset fields.
Although it is still tricky because high byte of offset is supposed to be at 5th byte not 4th byte, which instead shall make your offset 0x0410 meaning 4 , and 0x1410 meaning 20.
But i cannot explain the dummy 2 bytes (00 00) in front of the data. I think it is probably safe to just ignore the 2 bytes.
Thus in the end, the structure will need to be:
typedef __packed struct _evt_gatt_attr_modified_IDB05A1{
uint16_t conn_handle;
uint16_t attr_handle;
uint16_t offset;
uint8_t data_length;
uint16_t dummy;
uint8_t att_data[VARIABLE_SIZE];
} PACKED evt_gatt_attr_modified_IDB05A1;
Thank you.
Best Regards,
Winfred