Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of X_NUCLEO_IDB0XA1 by
Diff: source/platform/btle.cpp
- Branch:
- dc54644b61c51990e49672e5bbce3b95124d6364
- Revision:
- 273:00205952d841
- Parent:
- 264:1e754a01869e
- Parent:
- 272:4639da7705e1
- Child:
- 293:5a1f577bf92f
--- a/source/platform/btle.cpp Thu Sep 15 10:51:26 2016 +0100 +++ b/source/platform/btle.cpp Thu Sep 15 10:51:36 2016 +0100 @@ -17,7 +17,7 @@ /** ****************************************************************************** - * @file btle.cpp + * @file btle.cpp * @author STMicroelectronics * @brief Implementation BlueNRG Init and helper functions. ****************************************************************************** @@ -31,7 +31,7 @@ * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * * <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2> - */ + */ #include "btle.h" @@ -81,6 +81,7 @@ uint16_t g_gap_service_handle = 0; uint16_t g_appearance_char_handle = 0; uint16_t g_device_name_char_handle = 0; +uint16_t g_preferred_connection_parameters_char_handle = 0; /* Private variables ---------------------------------------------------------*/ volatile uint8_t set_connectable = 1; @@ -91,17 +92,13 @@ /**************************************************************************/ /*! @brief Init the BTLE stack with the specified role - @param isSetAddress boolean if address has been set - @param role The device role @returns void */ /**************************************************************************/ -void btleInit(bool isSetAddress, uint8_t role) +void btleInit(void) { PRINTF("btleInit>>\n\r"); - /* Avoid compiler warnings about unused variables. */ - (void)isSetAddress; - + int ret; uint8_t hwVersion; uint16_t fwVersion; @@ -113,7 +110,7 @@ /* get the BlueNRG HW and FW versions */ getBlueNRGVersion(&hwVersion, &fwVersion); - /* + /* * Reset BlueNRG again otherwise we won't * be able to change its MAC address. * aci_hal_write_config_data() must be the first @@ -135,33 +132,6 @@ &stackMode); } - /* The Nucleo board must be configured as SERVER */ - //check if isSetAddress is set then set address. -#if 0 - if(isSetAddress) - { - Gap::Address_t bleAddr; - Gap::AddressType_t addr_type; - - BlueNRGGap::getInstance().getAddress(&addr_type, bleAddr); - - ret = aci_hal_write_config_data(CONFIG_DATA_PUBADDR_OFFSET, - CONFIG_DATA_PUBADDR_LEN, - bleAddr); - } else { - - const Gap::Address_t BLE_address_BE = {0xFD,0x66,0x05,0x13,0xBE,0xBA}; - BlueNRGGap::getInstance().setAddress(BLEProtocol::AddressType::RANDOM_STATIC, BLE_address_BE); - - ret = aci_hal_write_config_data(CONFIG_DATA_PUBADDR_OFFSET, - CONFIG_DATA_PUBADDR_LEN, - BLE_address_BE); - } -#endif - - const Gap::Address_t BLE_address_BE = {0xFD,0x66,0x05,0x13,0xBE,0xBA}; - BlueNRGGap::getInstance().setAddress(BLEProtocol::AddressType::RANDOM_STATIC, BLE_address_BE); - ret = aci_gatt_init(); if(ret != BLE_STATUS_SUCCESS){ PRINTF("GATT_Init failed.\n"); @@ -174,9 +144,19 @@ &dev_name_char_handle, &appearance_char_handle); } else { - ret = aci_gap_init_IDB04A1(role, &service_handle, &dev_name_char_handle, &appearance_char_handle); + // IDB04A1 is configured as peripheral by default + ret = aci_gap_init_IDB04A1(GAP_PERIPHERAL_ROLE_IDB04A1, &service_handle, &dev_name_char_handle, &appearance_char_handle); } - + + // read the default static address and inject it into the GAP object + { + Gap::Address_t BLE_address_BE = { 0 }; + uint8_t data_len_out; + aci_hal_read_config_data(CONFIG_DATA_RANDOM_ADDRESS_IDB05A1, BDADDR_SIZE, &data_len_out, BLE_address_BE); + // FIXME error handling of this function + BlueNRGGap::getInstance().setAddress(BLEProtocol::AddressType::RANDOM_STATIC, BLE_address_BE); + } + if(ret != BLE_STATUS_SUCCESS){ PRINTF("GAP_Init failed.\n"); } @@ -193,17 +173,21 @@ if (ret != BLE_STATUS_SUCCESS) { PRINTF("Auth Req set failed.\n"); } - + aci_hal_set_tx_power_level(1,4); - + g_gap_service_handle = service_handle; g_appearance_char_handle = appearance_char_handle; - g_device_name_char_handle = dev_name_char_handle; - //Device Name is set from Accumulate Adv Data Payload or through setDeviceName API + g_device_name_char_handle = dev_name_char_handle; + //Device Name is set from Accumulate Adv Data Payload or through setDeviceName API /*ret = aci_gatt_update_char_value(service_handle, dev_name_char_handle, 0, strlen(name), (tHalUint8 *)name);*/ signalEventsToProcess(); + // update the peripheral preferred conenction parameters handle + // This value is hardcoded at the moment. + g_preferred_connection_parameters_char_handle = 10; + return; } @@ -212,7 +196,7 @@ @brief mbedOS @param[in] void - + @returns */ /**************************************************************************/ @@ -271,7 +255,7 @@ @brief Not Used @param[in] void - + @returns */ void SPI_Poll(void) @@ -279,7 +263,7 @@ //HAL_GPIO_EXTI_Callback_Poll(BNRG_SPI_EXTI_PIN); return; } - + void Attribute_Modified_CB(evt_blue_aci *blue_evt) { uint16_t conn_handle; @@ -320,7 +304,7 @@ currentHandle = BlueNRGGattServer::CHAR_DESC_HANDLE; } PRINTF("currentHandle %d\n\r", currentHandle); - if((p_char->getProperties() & + if((p_char->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE)) && currentHandle == BlueNRGGattServer::CHAR_DESC_HANDLE) { @@ -329,21 +313,22 @@ PRINTF("*****NOTIFICATION CASE\n\r"); //Now Check if data written in Enable or Disable if((uint16_t)att_data[0]==1) { - //PRINTF("Notify ENABLED\n\r"); + //PRINTF("Notify ENABLED\n\r"); BlueNRGGattServer::getInstance().HCIEvent(GattServerEvents::GATT_EVENT_UPDATES_ENABLED, charDescHandle); } else { - //PRINTF("Notify DISABLED\n\r"); + //PRINTF("Notify DISABLED\n\r"); BlueNRGGattServer::getInstance().HCIEvent(GattServerEvents::GATT_EVENT_UPDATES_DISABLED, charDescHandle); } + return; } - + //Check if attr handle property is WRITEABLE, in the case generate GATT_EVENT_DATA_WRITTEN Event if((p_char->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE)) && currentHandle == BlueNRGGattServer::CHAR_VALUE_HANDLE) { - + PRINTF("*****WRITE CASE\n\r"); - + GattWriteCallbackParams writeParams; writeParams.connHandle = conn_handle; writeParams.handle = p_char->getValueAttribute().getHandle(); @@ -352,17 +337,31 @@ writeParams.data = att_data; writeParams.offset = offset; - BlueNRGGattServer::getInstance().HCIDataWrittenEvent(&writeParams); - //BlueNRGGattServer::getInstance().handleEvent(GattServerEvents::GATT_EVENT_DATA_WRITTEN, attr_handle); //Write the actual Data to the Attr Handle? (uint8_1[])att_data contains the data if ((p_char->getValueAttribute().getValuePtr() != NULL) && (p_char->getValueAttribute().getLength() > 0)) { - BlueNRGGattServer::getInstance().write(p_char->getValueAttribute().getHandle(), - (uint8_t*)att_data, - data_length, - false); + BlueNRGGattServer::getInstance().write( + p_char->getValueAttribute().getHandle(), + (uint8_t*)att_data, + data_length, + false + ); } - } + + BlueNRGGattServer::getInstance().HCIDataWrittenEvent(&writeParams); + } else { + PRINTF("*****WRITE DESCRIPTOR CASE\n\r"); + + GattWriteCallbackParams writeParams; + writeParams.connHandle = conn_handle; + writeParams.handle = attr_handle; + writeParams.writeOp = GattWriteCallbackParams::OP_WRITE_REQ;//Where to find this property in BLUENRG? + writeParams.len = data_length; + writeParams.data = att_data; + writeParams.offset = offset; + + BlueNRGGattServer::getInstance().HCIDataWrittenEvent(&writeParams); + } } } @@ -377,39 +376,39 @@ @param[in] pckt Event Packet sent by the stack to be decoded - + @returns */ /**************************************************************************/ extern void HCI_Event_CB(void *pckt) { hci_uart_pckt *hci_pckt = (hci_uart_pckt*)pckt; hci_event_pckt *event_pckt = (hci_event_pckt*)hci_pckt->data; - + if(hci_pckt->type != HCI_EVENT_PKT) return; switch(event_pckt->evt){ - + case EVT_DISCONN_COMPLETE: { PRINTF("EVT_DISCONN_COMPLETE\n"); - + evt_disconn_complete *evt = (evt_disconn_complete*)event_pckt->data; - + BlueNRGGap::getInstance().processDisconnectionEvent(evt->handle, (Gap::DisconnectionReason_t)evt->reason); } break; - + case EVT_LE_META_EVENT: { PRINTF("EVT_LE_META_EVENT\n"); - + evt_le_meta_event *evt = (evt_le_meta_event *)event_pckt->data; - + switch(evt->subevent){ case EVT_LE_CONN_COMPLETE: - { + { PRINTF("EVT_LE_CONN_COMPLETE\n"); Gap::Address_t ownAddr; Gap::AddressType_t ownAddrType; @@ -417,12 +416,19 @@ Gap::AddressType_t peerAddrType = BLEProtocol::AddressType::RANDOM_STATIC; Gap::Role_t role; - + evt_le_connection_complete *cc = (evt_le_connection_complete *)evt->data; - + BlueNRGGap::getInstance().setConnectionHandle(cc->handle); - BlueNRGGap::ConnectionParams_t connectionParams; - BlueNRGGap::getInstance().getPreferredConnectionParams(&connectionParams); + BlueNRGGap::ConnectionParams_t connectionParams = { + /* minConnectionInterval = */ cc->interval, + /* maxConnectionInterval = */ cc->interval, + /* slaveLatency = */ cc->latency, + /* connectionSupervisionTimeout = */ cc->supervision_timeout + }; + + BlueNRGGap::getInstance().setConnectionInterval(cc->interval); + switch (cc->peer_bdaddr_type) { case PUBLIC_ADDR: peerAddrType = BLEProtocol::AddressType::PUBLIC; @@ -436,7 +442,7 @@ case NON_RESOLVABLE_PRIVATE_ADDR: peerAddrType = BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE; break; - } + } //PRINTF("EVT_LE_CONN_COMPLETE LL role=%d\n", cc->role); switch (cc->role) { case 0: //master @@ -449,7 +455,9 @@ role = Gap::PERIPHERAL; break; } - //PRINTF("EVT_LE_CONN_COMPLETE GAP role=%d\n", role); + + BlueNRGGap::getInstance().setGapRole(role); + BlueNRGGap::getInstance().processConnectionEvent(cc->handle, role, peerAddrType, @@ -459,17 +467,17 @@ &connectionParams); } break; - + case EVT_LE_ADVERTISING_REPORT: PRINTF("EVT_LE_ADVERTISING_REPORT\n\r"); /* FIXME: comment this otherwise it will be obscure and error prone if BlueNRG FW will be updated */ // This event is generated only by X-NUCLEO-IDB05A1 version but not by X-NUCLEO-IDB04A1 (which generates DEVICE_FOUND EVT) // Formally the structure related to both events are identical except that for the ADV REPORT // there is one more field (number of reports) which is not forwarded to upper layer. - // Thus we need to move one byte over (((uint8_t*)evt->data)+1) before persing the ADV REPORT. + // Thus we need to move one byte over (((uint8_t*)evt->data)+1) before persing the ADV REPORT. le_advertising_info *pr = (le_advertising_info*) (((uint8_t*)evt->data)+1); PRINTF("EVT_LE_ADVERTISING_REPORT evt_type=%d\n\r", pr->evt_type); - + BlueNRGGap::getInstance().Discovery_CB(BlueNRGGap::DEVICE_FOUND, pr->evt_type, pr->bdaddr_type, @@ -481,14 +489,40 @@ } } break; - + case EVT_VENDOR: - { + { evt_blue_aci *blue_evt = (evt_blue_aci*)event_pckt->data; //PRINTF("EVT_VENDOR %d\n", blue_evt->ecode); - + switch(blue_evt->ecode){ - + + case EVT_BLUE_GATT_WRITE_PERMIT_REQ: + { + PRINTF("EVT_BLUE_GATT_WRITE_PERMIT_REQ\r\n"); + evt_gatt_write_permit_req* write_req = (evt_gatt_write_permit_req*)blue_evt->data; + + // ask the local server if the write operation is authorized + uint8_t err_code = BlueNRGGattServer::getInstance().Write_Request_CB( + write_req->conn_handle, + write_req->attr_handle, + write_req->data_length, + write_req->data + ); + uint8_t write_status = err_code == 0 ? 0 : 1; + + // reply to the shield + aci_gatt_write_response( + write_req->conn_handle, + write_req->attr_handle, + write_status, + err_code, + write_req->data_length, + write_req->data + ); + } + break; + case EVT_BLUE_GATT_READ_PERMIT_REQ: { PRINTF("EVT_BLUE_GATT_READ_PERMIT_REQ_OK\n\r"); @@ -497,16 +531,16 @@ BlueNRGGattServer::getInstance().Read_Request_CB(pr->attr_handle); } break; - - case EVT_BLUE_GATT_ATTRIBUTE_MODIFIED: + + case EVT_BLUE_GATT_ATTRIBUTE_MODIFIED: { PRINTF("EVT_BLUE_GATT_ATTRIBUTE_MODIFIED\n\r"); /* this callback is invoked when a GATT attribute is modified extract callback data and pass to suitable handler function */ Attribute_Modified_CB(blue_evt); } - break; - + break; + //Any cases for Data Sent Notifications? case EVT_BLUE_GATT_NOTIFICATION: //This is only relevant for Client Side Event @@ -515,8 +549,8 @@ case EVT_BLUE_GATT_INDICATION: //This is only relevant for Client Side Event PRINTF("EVT_BLUE_GATT_INDICATION"); - break; - + break; + case EVT_BLUE_ATT_READ_BY_GROUP_TYPE_RESP: { PRINTF("EVT_BLUE_ATT_READ_BY_GROUP_TYPE_RESP\n\r"); @@ -601,12 +635,42 @@ BlueNRGGattClient::getInstance().gattProcedureCompleteCB(evt->conn_handle, evt->error_code); } break; - + + case EVT_BLUE_L2CAP_CONN_UPD_REQ: + { + PRINTF("EVT_BLUE_L2CAP_CONN_UPD_REQ\r\n"); + evt_l2cap_conn_upd_req *evt = (evt_l2cap_conn_upd_req*)blue_evt->data; + if(bnrg_expansion_board == IDB05A1) { + // we assume the application accepts the request from the slave + aci_l2cap_connection_parameter_update_response_IDB05A1(evt->conn_handle, + evt->interval_min, + evt->interval_max, + evt->slave_latency, + evt->timeout_mult, + CONN_L1, CONN_L2, + evt->identifier, + 0x0000); + } + } + break; + + case EVT_BLUE_L2CAP_CONN_UPD_RESP: + { + PRINTF("EVT_BLUE_L2CAP_CONN_UPD_RESP\r\n"); + } + break; + + case EVT_LE_CONN_UPDATE_COMPLETE: + { + PRINTF("EVT_LE_CONN_UPDATE_COMPLETE\r\n"); + } + break; + case EVT_BLUE_GAP_DEVICE_FOUND: { evt_gap_device_found *pr = (evt_gap_device_found*)blue_evt->data; PRINTF("EVT_BLUE_GAP_DEVICE_FOUND evt_type=%d\n\r", pr->evt_type); - + BlueNRGGap::getInstance().Discovery_CB(BlueNRGGap::DEVICE_FOUND, pr->evt_type, pr->bdaddr_type, @@ -616,24 +680,24 @@ &pr->data_RSSI[pr->data_length]); } break; - + case EVT_BLUE_GAP_PROCEDURE_COMPLETE: { evt_gap_procedure_complete *pr = (evt_gap_procedure_complete*)blue_evt->data; //PRINTF("EVT_BLUE_GAP_PROCEDURE_COMPLETE (code=0x%02X)\n\r", pr->procedure_code); - + switch(pr->procedure_code) { case GAP_OBSERVATION_PROC_IDB05A1: - + BlueNRGGap::getInstance().Discovery_CB(BlueNRGGap::DISCOVERY_COMPLETE, 0, 0, NULL, NULL, NULL, NULL); break; } } - break; + break; } } break; - } + } return ; }