Compilation fix for newer mbed-os
Fork of X_NUCLEO_IDB0XA1 by
Revision 276:a20f4cad1d61, committed 2016-09-15
- Comitter:
- Vincent Coubard
- Date:
- Thu Sep 15 10:51:40 2016 +0100
- Branch:
- sync_with_github
- Parent:
- 275:cb9a052c769b
- Parent:
- 272:4639da7705e1
- Child:
- 277:8da7a954664d
- Commit message:
- Sync with e6d00ca1d1860d23ec86287a3d7ff17abad1cb06
Merge 83c30f290087a6f5a503812f507492e725a3b717 into 4f8db2b28527e45a5d1505c0ca5711af74175909
2016-07-20 10:24:40+02:00: Andrea Palmieri
Merge branch 'workshop-july'
Signed-off-by: Andrea Palmieri <andrea.palmieri@st.com>
Changed in this revision
source/BlueNRGGap.cpp | Show annotated file Show diff for this revision Revisions of this file |
x-nucleo-idb0xa1/BlueNRGGap.h | Show annotated file Show diff for this revision Revisions of this file |
--- a/source/BlueNRGDevice.cpp Thu Sep 15 10:51:38 2016 +0100 +++ b/source/BlueNRGDevice.cpp Thu Sep 15 10:51:40 2016 +0100 @@ -181,11 +181,9 @@ callback.call(&context); return BLE_ERROR_ALREADY_INITIALIZED; } - - /* ToDo: Clear memory contents, reset the SD, etc. */ + // Init the BlueNRG/BlueNRG-MS stack - // By default, we set the device GAP role to PERIPHERAL - btleInit(BlueNRGGap::getInstance().getIsSetAddress(), GAP_PERIPHERAL_ROLE_IDB04A1); + btleInit(); isInitialized = true; BLE::InitializationCompleteCallbackContext context = { @@ -468,4 +466,4 @@ void BlueNRGDevice::enable_irq() { irq_.enable_irq(); -} +} \ No newline at end of file
--- a/source/BlueNRGDiscoveredCharacteristic.cpp Thu Sep 15 10:51:38 2016 +0100 +++ b/source/BlueNRGDiscoveredCharacteristic.cpp Thu Sep 15 10:51:40 2016 +0100 @@ -62,3 +62,7 @@ props._indicate = propsIn.indicate(); props._authSignedWrite = propsIn.authSignedWrite(); } + + void BlueNRGDiscoveredCharacteristic::setLastHandle(GattAttribute::Handle_t lastHandleIn) { + lastHandle = lastHandleIn; + } \ No newline at end of file
--- a/source/BlueNRGGap.cpp Thu Sep 15 10:51:38 2016 +0100 +++ b/source/BlueNRGGap.cpp Thu Sep 15 10:51:40 2016 +0100 @@ -17,7 +17,7 @@ /** ****************************************************************************** - * @file BlueNRGGap.cpp + * @file BlueNRGGap.cpp * @author STMicroelectronics * @brief Implementation of BLE_API Gap Class ****************************************************************************** @@ -44,15 +44,11 @@ #include "Utils.h" #include "debug.h" -//Local Variables -//const char *local_name = NULL; -//uint8_t local_name_length = 0; - /* * Utility to process GAP specific events (e.g., Advertising timeout) */ void BlueNRGGap::Process(void) -{ +{ if(AdvToFlag) { stopAdvertising(); } @@ -61,7 +57,7 @@ /**************************************************************************/ /*! - @brief Sets the advertising parameters and payload for the device. + @brief Sets the advertising parameters and payload for the device. Note: Some data types give error when their adv data is updated using aci_gap_update_adv_data() API @params[in] advData @@ -95,7 +91,7 @@ */ /**************************************************************************/ ble_error_t BlueNRGGap::setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) -{ +{ PRINTF("BlueNRGGap::setAdvertisingData\n\r"); /* Make sure we don't exceed the advertising payload length */ if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD) { @@ -103,18 +99,8 @@ return BLE_ERROR_BUFFER_OVERFLOW; } - // Reset the length of the ADV payload each time - // since we get fields of argument 'advData' iteratively - AdvLen = 0; - /* Make sure we have a payload! */ - if (advData.getPayloadLen() == 0) { - PRINTF("advData.getPayloadLen() == 0\n\r"); - //return BLE_ERROR_PARAM_OUT_OF_RANGE; - local_name_length = 0; - txPowLevSet = 0; - servUuidlength = 0; - } else { + if (advData.getPayloadLen() != 0) { PayloadPtr loadPtr(advData.getPayload(), advData.getPayloadLen()); /* Align the GAP Service Appearance Char value coherently @@ -125,88 +111,17 @@ setAppearance((GapAdvertisingData::Appearance)(deviceAppearance[1]<<8|deviceAppearance[0])); - for(uint8_t index=0; index<loadPtr.getPayloadUnitCount(); index++) { + for(uint8_t index=0; index<loadPtr.getPayloadUnitCount(); index++) { loadPtr.getUnitAtIndex(index); PRINTF("adData[%d].length=%d\n\r", index,(uint8_t)(*loadPtr.getUnitAtIndex(index).getLenPtr())); - PRINTF("adData[%d].AdType=0x%x\n\r", index,(uint8_t)(*loadPtr.getUnitAtIndex(index).getAdTypePtr())); - + PRINTF("adData[%d].AdType=0x%x\n\r", index,(uint8_t)(*loadPtr.getUnitAtIndex(index).getAdTypePtr())); + switch(*loadPtr.getUnitAtIndex(index).getAdTypePtr()) { - case GapAdvertisingData::FLAGS: /* ref *Flags */ - { - PRINTF("Advertising type: FLAGS\n\r"); - //Check if Flags are OK. BlueNRG only supports LE Mode. - uint8_t *flags = loadPtr.getUnitAtIndex(index).getDataPtr(); - if((*flags & GapAdvertisingData::BREDR_NOT_SUPPORTED) != GapAdvertisingData::BREDR_NOT_SUPPORTED) { - PRINTF("BlueNRG does not support BR/EDR Mode"); - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - - break; - } - case GapAdvertisingData::INCOMPLETE_LIST_16BIT_SERVICE_IDS: /**< Incomplete list of 16-bit Service IDs */ - case GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS: /**< Complete list of 16-bit Service IDs */ - case GapAdvertisingData::INCOMPLETE_LIST_128BIT_SERVICE_IDS: /**< Incomplete list of 128-bit Service IDs */ - case GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS: /**< Complete list of 128-bit Service IDs */ + /**< TX Power Level (in dBm) */ + case GapAdvertisingData::TX_POWER_LEVEL: { - PRINTF("Advertising type: INCOMPLETE_LIST SERVICE_IDS/COMPLETE_LIST SERVICE_IDS\n\r"); - - uint8_t buffSize = *loadPtr.getUnitAtIndex(index).getLenPtr()-1; - // The total lenght should include the Data Type Value - if(buffSize>UUID_BUFFER_SIZE-1) { - return BLE_ERROR_INVALID_PARAM; - } - - servUuidlength = buffSize+1; // +1 to include the Data Type Value - servUuidData[0] = (uint8_t)(*loadPtr.getUnitAtIndex(index).getAdTypePtr()); //Data Type Value - - PRINTF("servUuidlength=%d servUuidData[0]=%d buffSize=%d\n\r", servUuidlength, servUuidData[0], buffSize); - // Save the Service UUID list just after the Data Type Value field - memcpy(servUuidData+1, loadPtr.getUnitAtIndex(index).getDataPtr(), buffSize); -#ifdef DEBUG - for(unsigned i=0; i<servUuidlength; i++) { - PRINTF("servUuidData[%d] = 0x%x\n\r", i, servUuidData[i]); - } - - for(unsigned i=0; i<buffSize; i++) { - PRINTF("loadPtr.getUnitAtIndex(index).getDataPtr()[%d] = 0x%x\n\r", - i, loadPtr.getUnitAtIndex(index).getDataPtr()[i]); - } -#endif /* DEBUG */ - break; - } - case GapAdvertisingData::INCOMPLETE_LIST_32BIT_SERVICE_IDS: /**< Incomplete list of 32-bit Service IDs (not relevant for Bluetooth 4.0) */ - { - PRINTF("Advertising type: INCOMPLETE_LIST_32BIT_SERVICE_IDS\n\r"); - return BLE_ERROR_NOT_IMPLEMENTED; - } - case GapAdvertisingData::COMPLETE_LIST_32BIT_SERVICE_IDS: /**< Complete list of 32-bit Service IDs (not relevant for Bluetooth 4.0) */ - { - PRINTF("Advertising type: COMPLETE_LIST_32BIT_SERVICE_IDS\n\r"); - return BLE_ERROR_NOT_IMPLEMENTED; - } - case GapAdvertisingData::SHORTENED_LOCAL_NAME: /**< Shortened Local Name */ - { - break; - } - case GapAdvertisingData::COMPLETE_LOCAL_NAME: /**< Complete Local Name */ - { - PRINTF("Advertising type: COMPLETE_LOCAL_NAME\n\r"); - loadPtr.getUnitAtIndex(index).printDataAsString(); - local_name_length = *loadPtr.getUnitAtIndex(index).getLenPtr()-1; - // The total length should include the Data Type Value - if(local_name_length>ADV_DATA_MAX_SIZE-1) { - return BLE_ERROR_INVALID_PARAM; - } - local_name[0] = (uint8_t)(*loadPtr.getUnitAtIndex(index).getAdTypePtr()); //Data Type Value - memcpy(local_name+1, (uint8_t*)loadPtr.getUnitAtIndex(index).getDataPtr(), local_name_length-1); - PRINTF("Advertising type: COMPLETE_LOCAL_NAME local_name=%s local_name_length=%d\n\r", local_name+1, local_name_length); - - break; - } - case GapAdvertisingData::TX_POWER_LEVEL: /**< TX Power Level (in dBm) */ - { - PRINTF("Advertising type: TX_POWER_LEVEL\n\r"); + PRINTF("Advertising type: TX_POWER_LEVEL\n\r"); int8_t enHighPower = 0; int8_t paLevel = 0; @@ -218,47 +133,11 @@ #endif if(ret == BLE_STATUS_SUCCESS) { aci_hal_set_tx_power_level(enHighPower, paLevel); - txPowLevSet = 1; } break; } - case GapAdvertisingData::DEVICE_ID: /**< Device ID */ - { - break; - } - case GapAdvertisingData::SLAVE_CONNECTION_INTERVAL_RANGE: /**< Slave :Connection Interval Range */ - { - PRINTF("Advertising type: SLAVE_CONNECTION_INTERVAL_RANGE\n\r"); - uint8_t *ptr = loadPtr.getUnitAtIndex(index).getDataPtr(); - slaveConnIntervMin = ptr[0]|ptr[1]<<8; - slaveConnIntervMax = ptr[2]|ptr[3]<<8; - - break; - } - case GapAdvertisingData::SERVICE_DATA: /**< Service Data */ - { - PRINTF("Advertising type: SERVICE_DATA\n\r"); - uint8_t buffSize = *loadPtr.getUnitAtIndex(index).getLenPtr()-1; - PRINTF("Advertising type: SERVICE_DATA (buffSize=%d)\n\r", buffSize); - // the total ADV DATA LEN should include two more bytes: the buffer size byte; and the Service Data Type Value byte - if(buffSize>ADV_DATA_MAX_SIZE-2) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } -#ifdef DEBUG - for(int i=0; i<buffSize+1; i++) { - PRINTF("Advertising type: SERVICE_DATA loadPtr.getUnitAtIndex(index).getDataPtr()[%d] = 0x%x\n\r", - i, loadPtr.getUnitAtIndex(index).getDataPtr()[i]); - } -#endif - // the total ADV DATA LEN should include two more bytes: the buffer size byte; and the Service Data Type Value byte - AdvData[AdvLen++] = buffSize+1; // the fisrt byte is the data buffer size (type+data) - AdvData[AdvLen++] = AD_TYPE_SERVICE_DATA; - memcpy(&AdvData[AdvLen], loadPtr.getUnitAtIndex(index).getDataPtr(), buffSize); - AdvLen += buffSize; - break; - } - - case GapAdvertisingData::APPEARANCE: /**< Appearance */ + /**< Appearance */ + case GapAdvertisingData::APPEARANCE: { PRINTF("Advertising type: APPEARANCE\n\r"); @@ -273,70 +152,15 @@ break; } - case GapAdvertisingData::ADVERTISING_INTERVAL: /**< Advertising Interval */ - { - printf("Advertising type: ADVERTISING_INTERVAL\n\r"); - uint8_t buffSize = *loadPtr.getUnitAtIndex(index).getLenPtr()-1; - AdvData[AdvLen++] = buffSize+1; // the fisrt byte is the data buffer size (type+data) - AdvData[AdvLen++] = AD_TYPE_ADVERTISING_INTERVAL; - memcpy(&AdvData[AdvLen], loadPtr.getUnitAtIndex(index).getDataPtr(), buffSize); - AdvLen += buffSize; - break; - } - case GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA: /**< Manufacturer Specific Data */ - { - PRINTF("Advertising type: MANUFACTURER_SPECIFIC_DATA\n\r"); - uint8_t buffSize = *loadPtr.getUnitAtIndex(index).getLenPtr()-1; - PRINTF("Advertising type: MANUFACTURER_SPECIFIC_DATA (buffSize=%d)\n\r", buffSize); - // the total ADV DATA LEN should include two more bytes: - // the buffer size byte; - // and the Manufacturer Specific Data Type Value byte - if(buffSize>ADV_DATA_MAX_SIZE-2) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } -#ifdef DBEUG - for(int i=0; i<buffSize+1; i++) { - PRINTF("Advertising type: MANUFACTURER_SPECIFIC_DATA loadPtr.getUnitAtIndex(index).getDataPtr()[%d] = 0x%x\n\r", - i, loadPtr.getUnitAtIndex(index).getDataPtr()[i]); - } -#endif - // the total ADV DATA LEN should include two more bytes: the buffer size byte; and the Manufacturer Specific Data Type Value byte - AdvData[AdvLen++] = buffSize+1; // the fisrt byte is the data buffer size (type+data) - AdvData[AdvLen++] = AD_TYPE_MANUFACTURER_SPECIFIC_DATA; - memcpy(&AdvData[AdvLen], loadPtr.getUnitAtIndex(index).getDataPtr(), buffSize); - AdvLen += buffSize; - break; - } } // end switch } //end for - //Set the SCAN_RSP Payload - if(scanResponse.getPayloadLen() > 0) { - scan_response_payload = scanResponse.getPayload(); - scan_rsp_length = scanResponse.getPayloadLen(); - } + } - // Update the ADV data if we are already in ADV mode - if(AdvLen > 0 && state.advertising == 1) { - - tBleStatus ret = aci_gap_update_adv_data(AdvLen, AdvData); - if(BLE_STATUS_SUCCESS!=ret) { - PRINTF("error occurred while adding adv data (ret=0x%x)\n", ret); - switch (ret) { - case BLE_STATUS_TIMEOUT: - return BLE_STACK_BUSY; - case ERR_INVALID_HCI_CMD_PARAMS: - case BLE_STATUS_INVALID_PARAMS: - return BLE_ERROR_INVALID_PARAM; - case BLE_STATUS_FAILED: - return BLE_ERROR_PARAM_OUT_OF_RANGE; - default: - return BLE_ERROR_UNSPECIFIED; - } - } - } - } + _advData = advData; + _scanResponse = scanResponse; + return BLE_ERROR_NONE; } @@ -354,40 +178,40 @@ static void advTimeoutCB(void) { Gap::GapState_t state; - + state = BlueNRGGap::getInstance().getState(); if (state.advertising == 1) { - + BlueNRGGap::getInstance().stopAdvertising(); - + } } #else static void advTimeoutCB(void) { Gap::GapState_t state; - + state = BlueNRGGap::getInstance().getState(); if (state.advertising == 1) { - + BlueNRGGap::getInstance().setAdvToFlag(); - + Timeout t = BlueNRGGap::getInstance().getAdvTimeout(); t.detach(); /* disable the callback from the timeout */ } } #endif /* AST_FOR_MBED_OS */ - + /**************************************************************************/ /*! @brief Starts the BLE HW, initialising any services that were added before this function was called. - + @param[in] params Basic advertising details, including the advertising delay, timeout and how the device should be advertised - + @note All services must be added before calling this function! @returns ble_error_t @@ -406,7 +230,7 @@ ble_error_t BlueNRGGap::startAdvertising(const GapAdvertisingParams ¶ms) { tBleStatus ret; - ble_error_t rc; + int err; /* Make sure we support the advertising type */ if (params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) { @@ -475,8 +299,8 @@ params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED) { /* set scan response data */ - PRINTF(" setting scan response data (scan_rsp_length=%u)\n", scan_rsp_length); - ret = hci_le_set_scan_resp_data(scan_rsp_length, scan_response_payload); + PRINTF(" setting scan response data (_scanResponseLen=%u)\n", _scanResponse.getPayloadLen()); + ret = hci_le_set_scan_resp_data(_scanResponse.getPayloadLen(), _scanResponse.getPayload()); if(BLE_STATUS_SUCCESS!=ret) { PRINTF(" error while setting scan response data (ret=0x%x)\n", ret); @@ -491,54 +315,42 @@ hci_le_set_scan_resp_data(0, NULL); } - //advInterval = params.getIntervalInADVUnits(); setAdvParameters(); PRINTF("advInterval=%d advType=%d\n\r", advInterval, params.getAdvertisingType()); - /* Setting discoverable mode */ - ret = aci_gap_set_discoverable(params.getAdvertisingType(), // AdvType - advInterval, // AdvIntervMin - advInterval, // AdvIntervMax - addr_type, // OwnAddrType - advFilterPolicy, // AdvFilterPolicy - local_name_length, // LocalNameLen - (const char*)local_name, // LocalName - servUuidlength, // ServiceUUIDLen - servUuidData, // ServiceUUIDList - slaveConnIntervMin, // SlaveConnIntervMin - slaveConnIntervMax); // SlaveConnIntervMax + err = hci_le_set_advertising_data(_advData.getPayloadLen(), _advData.getPayload()); - - PRINTF("!!!setting discoverable (servUuidlength=0x%x)\n\r", servUuidlength); - if(BLE_STATUS_SUCCESS!=ret) { - PRINTF("error occurred while setting discoverable (ret=0x%x)\n\r", ret); - switch (ret) { - case BLE_STATUS_INVALID_PARAMS: - case ERR_INVALID_HCI_CMD_PARAMS: - return BLE_ERROR_INVALID_PARAM; - case ERR_COMMAND_DISALLOWED: - return BLE_ERROR_OPERATION_NOT_PERMITTED; - case ERR_UNSUPPORTED_FEATURE: - return BLE_ERROR_NOT_IMPLEMENTED; - case BLE_STATUS_TIMEOUT: - return BLE_STACK_BUSY; - default: - return BLE_ERROR_UNSPECIFIED; - } + if (err) { + PRINTF("error while setting the payload\r\n"); + return BLE_ERROR_UNSPECIFIED; } - // Since AD_TYPE_TX_POWER_LEVEL has not been set by application, we delete it - if(!txPowLevSet) { - PRINTF("Deleting TX POW LEV\n"); - aci_gap_delete_ad_type(AD_TYPE_TX_POWER_LEVEL); - txPowLevSet = 0; + tBDAddr dummy_addr = { 0 }; + uint16_t advIntervalMin = advInterval == GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX ? advInterval - 1 : advInterval; + uint16_t advIntervalMax = advIntervalMin + 1; + + err = hci_le_set_advertising_parameters( + advIntervalMin, + advIntervalMax, + params.getAdvertisingType(), + addr_type, + 0x00, + dummy_addr, + /* all channels */ 7, + advFilterPolicy + ); + + if (err) { + PRINTF("impossible to set advertising parameters\n\r"); + PRINTF("advInterval min: %u, advInterval max: %u\n\r", advInterval, advInterval + 1); + PRINTF("advType: %u, advFilterPolicy: %u\n\r", params.getAdvertisingType(), advFilterPolicy); + return BLE_ERROR_INVALID_PARAM; } - // Stop Advertising if an error occurs while updating ADV data - rc = updateAdvertisingData(); - if(rc != BLE_ERROR_NONE) { - aci_gap_set_non_discoverable(); - return rc; + err = hci_le_set_advertise_enable(0x01); + if (err) { + PRINTF("impossible to start advertising\n\r"); + return BLE_ERROR_UNSPECIFIED; } state.advertising = 1; @@ -554,76 +366,9 @@ } return BLE_ERROR_NONE; + } -ble_error_t BlueNRGGap::updateAdvertisingData(void) -{ - tBleStatus ret; - - // Before updating the ADV data, delete COMPLETE_LOCAL_NAME field - if(AdvLen > 0) { - if(local_name_length > 0) { - ret = aci_gap_delete_ad_type(AD_TYPE_COMPLETE_LOCAL_NAME); - if (BLE_STATUS_SUCCESS!=ret){ - PRINTF("aci_gap_delete_ad_type failed return=%d\n", ret); - switch (ret) { - case BLE_STATUS_TIMEOUT: - return BLE_STACK_BUSY; - case ERR_COMMAND_DISALLOWED: - return BLE_ERROR_OPERATION_NOT_PERMITTED; - case ERR_INVALID_HCI_CMD_PARAMS: - return BLE_ERROR_INVALID_PARAM; - default: - return BLE_ERROR_UNSPECIFIED; - } - } - } - - // ...and TX_POWER_LEVEL field to make the needed room in ADV payload - if(txPowLevSet) { - ret = aci_gap_delete_ad_type(AD_TYPE_TX_POWER_LEVEL); - if (BLE_STATUS_SUCCESS!=ret){ - PRINTF("aci_gap_delete_ad_type failed return=%d\n", ret); - switch (ret) { - case BLE_STATUS_TIMEOUT: - return BLE_STACK_BUSY; - case ERR_COMMAND_DISALLOWED: - return BLE_ERROR_OPERATION_NOT_PERMITTED; - case ERR_INVALID_HCI_CMD_PARAMS: - return BLE_ERROR_INVALID_PARAM; - default: - return BLE_ERROR_UNSPECIFIED; - } - } - } - - ret = aci_gap_update_adv_data(AdvLen, AdvData); - if(BLE_STATUS_SUCCESS!=ret) { - PRINTF("error occurred while adding adv data (ret=0x%x)\n\r", ret); - switch (ret) { - case BLE_STATUS_TIMEOUT: - return BLE_STACK_BUSY; - case ERR_INVALID_HCI_CMD_PARAMS: - case BLE_STATUS_INVALID_PARAMS: - return BLE_ERROR_INVALID_PARAM; - case BLE_STATUS_FAILED: - return BLE_ERROR_PARAM_OUT_OF_RANGE; - default: - return BLE_ERROR_UNSPECIFIED; - } - } - - } // AdvLen>0 - - if(deviceAppearance != 0) { - uint8_t appearance[] = {3, AD_TYPE_APPEARANCE, deviceAppearance[0], deviceAppearance[1]}; - // just ignore error code while setting appearance - aci_gap_update_adv_data(4, appearance); - } - - return BLE_ERROR_NONE; - -} /**************************************************************************/ /*! @@ -643,28 +388,19 @@ /**************************************************************************/ ble_error_t BlueNRGGap::stopAdvertising(void) { - tBleStatus ret; if(state.advertising == 1) { - //Set non-discoverable to stop advertising - ret = aci_gap_set_non_discoverable(); - - if (BLE_STATUS_SUCCESS!=ret){ - PRINTF("Error in stopping advertisement (ret=0x%x)!!\n\r", ret) ; - switch (ret) { - case ERR_COMMAND_DISALLOWED: - return BLE_ERROR_OPERATION_NOT_PERMITTED; - case BLE_STATUS_TIMEOUT: - return BLE_STACK_BUSY; - default: - return BLE_ERROR_UNSPECIFIED; - } + + int err = hci_le_set_advertise_enable(0); + if (err) { + return BLE_ERROR_OPERATION_NOT_PERMITTED; } + PRINTF("Advertisement stopped!!\n\r") ; //Set GapState_t::advertising state state.advertising = 0; } - + return BLE_ERROR_NONE; } @@ -674,7 +410,7 @@ @param[in] reason Disconnection Reason - + @returns ble_error_t @retval BLE_ERROR_NONE @@ -704,7 +440,7 @@ return BLE_ERROR_UNSPECIFIED; } } - + return BLE_ERROR_NONE; } @@ -714,7 +450,7 @@ @param[in] reason Disconnection Reason - + @returns ble_error_t @retval BLE_ERROR_NONE @@ -735,10 +471,10 @@ /**************************************************************************/ /*! @brief Sets the 16-bit connection handle - + @param[in] conn_handle Connection Handle which is set in the Gap Instance - + @returns void */ /**************************************************************************/ @@ -750,9 +486,9 @@ /**************************************************************************/ /*! @brief Gets the 16-bit connection handle - + @param[in] void - + @returns uint16_t Connection Handle of the Gap Instance */ @@ -769,10 +505,10 @@ @param[in] type Type of Address - + @param[in] address[6] Value of the Address to be set - + @returns ble_error_t @section EXAMPLE @@ -784,26 +520,47 @@ /**************************************************************************/ ble_error_t BlueNRGGap::setAddress(AddressType_t type, const BLEProtocol::AddressBytes_t address) { - tBleStatus ret; - if (type > BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } - - addr_type = type; - // If Address Type is other than PUBLIC, the given Address is ignored - if(addr_type == BLEProtocol::AddressType::PUBLIC){ - ret = aci_hal_write_config_data(CONFIG_DATA_PUBADDR_OFFSET, - CONFIG_DATA_PUBADDR_LEN, - address); + if(type == BLEProtocol::AddressType::PUBLIC){ + tBleStatus ret = aci_hal_write_config_data( + CONFIG_DATA_PUBADDR_OFFSET, + CONFIG_DATA_PUBADDR_LEN, + address + ); if(ret != BLE_STATUS_SUCCESS) { return BLE_ERROR_OPERATION_NOT_PERMITTED; } + } else if (type == BLEProtocol::AddressType::RANDOM_STATIC) { + // ensure that the random static address is well formed + if ((address[5] & 0xC0) != 0xC0) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + // thanks to const correctness of the API ... + tBDAddr random_address = { 0 }; + memcpy(random_address, address, sizeof(random_address)); + int err = hci_le_set_random_address(random_address); + if (err) { + return BLE_ERROR_OPERATION_NOT_PERMITTED; + } + + // It is not possible to get the bluetooth address when it is set + // store it locally in class data member + memcpy(bdaddr, address, sizeof(bdaddr)); } else { - return BLE_ERROR_OPERATION_NOT_PERMITTED; + // FIXME random addresses are not supported yet + // BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE + // BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE + return BLE_ERROR_NOT_IMPLEMENTED; } - + + // if we're here then the address was correctly set + // commit it inside the addr_type + addr_type = type; + isSetAddress = true; return BLE_ERROR_NONE; } @@ -811,7 +568,7 @@ /*! @brief Returns boolean if the address of the device has been set or not - + @returns bool @section EXAMPLE @@ -821,9 +578,9 @@ @endcode */ /**************************************************************************/ -bool BlueNRGGap::getIsSetAddress() +bool BlueNRGGap::getIsSetAddress() { - return isSetAddress; + return isSetAddress; } /**************************************************************************/ @@ -844,24 +601,31 @@ uint8_t bdaddr[BDADDR_SIZE]; uint8_t data_len_out; - if (addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE || - addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) { - return BLE_ERROR_OPERATION_NOT_PERMITTED; - } - - if(typeP != NULL) { - *typeP = addr_type; + // precondition, check that pointers in input are valid + if (typeP == NULL || address == NULL) { + return BLE_ERROR_INVALID_PARAM; } - tBleStatus ret = aci_hal_read_config_data(CONFIG_DATA_RANDOM_ADDRESS_IDB05A1, BDADDR_SIZE, &data_len_out, bdaddr); - if(ret != BLE_STATUS_SUCCESS) { - return BLE_ERROR_UNSPECIFIED; + if (addr_type == BLEProtocol::AddressType::PUBLIC) { + tBleStatus ret = aci_hal_read_config_data(CONFIG_DATA_PUBADDR_OFFSET, BDADDR_SIZE, &data_len_out, bdaddr); + if(ret != BLE_STATUS_SUCCESS || data_len_out != BDADDR_SIZE) { + return BLE_ERROR_UNSPECIFIED; + } + } else if (addr_type == BLEProtocol::AddressType::RANDOM_STATIC) { + // FIXME hci_read_bd_addr and + // aci_hal_read_config_data CONFIG_DATA_RANDOM_ADDRESS_IDB05A1 + // does not work, use the address stored in class data member + memcpy(bdaddr, this->bdaddr, sizeof(bdaddr)); + } else { + // FIXME: should be implemented with privacy features + // BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE + // BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE + return BLE_ERROR_NOT_IMPLEMENTED; } - if(address != NULL) { - memcpy(address, bdaddr, BDADDR_SIZE); - } - + *typeP = addr_type; + memcpy(address, bdaddr, BDADDR_SIZE); + return BLE_ERROR_NONE; } @@ -878,12 +642,39 @@ @endcode */ /**************************************************************************/ -ble_error_t BlueNRGGap::getPreferredConnectionParams(ConnectionParams_t *params) +ble_error_t BlueNRGGap::getPreferredConnectionParams(ConnectionParams_t *params) { - /* avoid compiler warnings about unused variables */ - (void)params; + static const size_t parameter_size = 2; + + if (!g_preferred_connection_parameters_char_handle) { + return BLE_ERROR_OPERATION_NOT_PERMITTED; + } + + // Peripheral preferred connection parameters are an array of 4 uint16_t + uint8_t parameters_packed[parameter_size * 4]; + uint16_t bytes_read = 0; - return BLE_ERROR_NOT_IMPLEMENTED; + tBleStatus err = aci_gatt_read_handle_value( + g_preferred_connection_parameters_char_handle + BlueNRGGattServer::CHAR_VALUE_HANDLE, + sizeof(parameters_packed), + &bytes_read, + parameters_packed + ); + + PRINTF("getPreferredConnectionParams err=0x%02x (bytes_read=%u)\n\r", err, bytes_read); + + // check that the read succeed and the result have the expected length + if (err || bytes_read != sizeof(parameters_packed)) { + return BLE_ERROR_UNSPECIFIED; + } + + // memcpy field by field + memcpy(¶ms->minConnectionInterval, parameters_packed, parameter_size); + memcpy(¶ms->maxConnectionInterval, ¶meters_packed[parameter_size], parameter_size); + memcpy(¶ms->slaveLatency, ¶meters_packed[2 * parameter_size], parameter_size); + memcpy(¶ms->connectionSupervisionTimeout, ¶meters_packed[3 * parameter_size], parameter_size); + + return BLE_ERROR_NONE; } @@ -900,12 +691,63 @@ @endcode */ /**************************************************************************/ -ble_error_t BlueNRGGap::setPreferredConnectionParams(const ConnectionParams_t *params) +ble_error_t BlueNRGGap::setPreferredConnectionParams(const ConnectionParams_t *params) { - /* avoid compiler warnings about unused variables */ - (void)params; + static const size_t parameter_size = 2; + uint8_t parameters_packed[parameter_size * 4]; + + // ensure that parameters are correct + // see BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part C] + // section 12.3 PERIPHERAL PREFERRED CONNECTION PARAMETERS CHARACTERISTIC + if (((0x0006 > params->minConnectionInterval) || (params->minConnectionInterval > 0x0C80)) && + params->minConnectionInterval != 0xFFFF) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + if (((params->minConnectionInterval > params->maxConnectionInterval) || (params->maxConnectionInterval > 0x0C80)) && + params->maxConnectionInterval != 0xFFFF) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + if (params->slaveLatency > 0x01F3) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + if (((0x000A > params->connectionSupervisionTimeout) || (params->connectionSupervisionTimeout > 0x0C80)) && + params->connectionSupervisionTimeout != 0xFFFF) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } - return BLE_ERROR_NOT_IMPLEMENTED; + // copy the parameters inside the byte array + memcpy(parameters_packed, ¶ms->minConnectionInterval, parameter_size); + memcpy(¶meters_packed[parameter_size], ¶ms->maxConnectionInterval, parameter_size); + memcpy(¶meters_packed[2 * parameter_size], ¶ms->slaveLatency, parameter_size); + memcpy(¶meters_packed[3 * parameter_size], ¶ms->connectionSupervisionTimeout, parameter_size); + + tBleStatus err = aci_gatt_update_char_value( + g_gap_service_handle, + g_preferred_connection_parameters_char_handle, + /* offset */ 0, + sizeof(parameters_packed), + parameters_packed + ); + + if (err) { + PRINTF("setPreferredConnectionParams failed (err=0x%x)!!\n\r", err) ; + switch (err) { + case BLE_STATUS_INVALID_HANDLE: + case BLE_STATUS_INVALID_PARAMETER: + return BLE_ERROR_INVALID_PARAM; + case BLE_STATUS_INSUFFICIENT_RESOURCES: + return BLE_ERROR_NO_MEM; + case BLE_STATUS_TIMEOUT: + return BLE_STACK_BUSY; + default: + return BLE_ERROR_UNSPECIFIED; + } + } + + return BLE_ERROR_NONE; } /**************************************************************************/ @@ -923,16 +765,43 @@ /**************************************************************************/ ble_error_t BlueNRGGap::updateConnectionParams(Handle_t handle, const ConnectionParams_t *params) { - /* avoid compiler warnings about unused variables */ - (void) handle; - (void)params; + tBleStatus ret = BLE_STATUS_SUCCESS; + + if(gapRole == Gap::CENTRAL) { + ret = aci_gap_start_connection_update(handle, + params->minConnectionInterval, + params->maxConnectionInterval, + params->slaveLatency, + params->connectionSupervisionTimeout, + CONN_L1, CONN_L2); + } else { + ret = aci_l2cap_connection_parameter_update_request(handle, + params->minConnectionInterval, + params->maxConnectionInterval, + params->slaveLatency, + params->connectionSupervisionTimeout); + } + + if (BLE_STATUS_SUCCESS != ret){ + PRINTF("updateConnectionParams failed (ret=0x%x)!!\n\r", ret) ; + switch (ret) { + case ERR_INVALID_HCI_CMD_PARAMS: + case BLE_STATUS_INVALID_PARAMETER: + return BLE_ERROR_INVALID_PARAM; + case ERR_COMMAND_DISALLOWED: + case BLE_STATUS_NOT_ALLOWED: + return BLE_ERROR_OPERATION_NOT_PERMITTED; + default: + return BLE_ERROR_UNSPECIFIED; + } + } return BLE_ERROR_NONE; } /**************************************************************************/ /*! - @brief Sets the Device Name Characteristic + @brief Sets the Device Name Characteristic @param[in] deviceName pointer to device name to be set @@ -949,11 +818,11 @@ @endcode */ /**************************************************************************/ -ble_error_t BlueNRGGap::setDeviceName(const uint8_t *deviceName) +ble_error_t BlueNRGGap::setDeviceName(const uint8_t *deviceName) { tBleStatus ret; - uint8_t nameLen = 0; - + uint8_t nameLen = 0; + nameLen = strlen((const char*)deviceName); PRINTF("DeviceName Size=%d\n\r", nameLen); @@ -983,13 +852,13 @@ /**************************************************************************/ /*! - @brief Gets the Device Name Characteristic + @brief Gets the Device Name Characteristic @param[in] deviceName - pointer to device name + pointer to device name @param[in] lengthP - pointer to device name length + pointer to device name length @returns ble_error_t @@ -1021,10 +890,10 @@ /**************************************************************************/ /*! - @brief Sets the Device Appearance Characteristic + @brief Sets the Device Appearance Characteristic @param[in] appearance - device appearance + device appearance @returns ble_error_t @@ -1043,9 +912,9 @@ tBleStatus ret; uint8_t deviceAppearance[2]; - STORE_LE_16(deviceAppearance, appearance); + STORE_LE_16(deviceAppearance, appearance); PRINTF("setAppearance= 0x%x 0x%x\n\r", deviceAppearance[1], deviceAppearance[0]); - + ret = aci_gatt_update_char_value(g_gap_service_handle, g_appearance_char_handle, 0, 2, (uint8_t *)deviceAppearance); @@ -1072,7 +941,7 @@ @brief Gets the Device Appearance Characteristic @param[in] appearance - pointer to device appearance value + pointer to device appearance value @returns ble_error_t @@ -1161,7 +1030,7 @@ default: type = GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED; } - + PRINTF("data_length=%d adv peerAddr[%02x %02x %02x %02x %02x %02x] \r\n", *data_length, addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]); if(!_connecting) { @@ -1170,7 +1039,7 @@ PRINTF("!!!After processAdvertisementReport\n\r"); } break; - + case DISCOVERY_COMPLETE: // The discovery is complete. If this is due to a stop scanning (i.e., the device // we are interested in has been found) and a connection has been requested @@ -1199,7 +1068,7 @@ ble_error_t BlueNRGGap::startRadioScan(const GapScanningParams &scanningParams) { - + tBleStatus ret = BLE_STATUS_SUCCESS; // Stop ADV before scanning @@ -1256,13 +1125,13 @@ PRINTF("stopScan\n\r"); ret = aci_gap_terminate_gap_procedure(GAP_OBSERVATION_PROC); - + if (ret != BLE_STATUS_SUCCESS) { PRINTF("GAP Terminate Gap Procedure failed(ret=0x%x)\n", ret); - return BLE_ERROR_UNSPECIFIED; + return BLE_ERROR_UNSPECIFIED; } else { PRINTF("Discovery Procedure Terminated\n"); - return BLE_ERROR_NONE; + return BLE_ERROR_NONE; } } @@ -1276,7 +1145,7 @@ ble_error_t BlueNRGGap::setTxPower(int8_t txPower) { tBleStatus ret; - + int8_t enHighPower = 0; int8_t paLevel = 0; @@ -1285,7 +1154,7 @@ return BLE_ERROR_PARAM_OUT_OF_RANGE; } - PRINTF("enHighPower=%d, paLevel=%d\n\r", enHighPower, paLevel); + PRINTF("enHighPower=%d, paLevel=%d\n\r", enHighPower, paLevel); ret = aci_hal_set_tx_power_level(enHighPower, paLevel); if(ret!=BLE_STATUS_SUCCESS) { return BLE_ERROR_PARAM_OUT_OF_RANGE; @@ -1298,7 +1167,7 @@ /*! @brief get permitted Tx power values @param[in] values pointer to pointer to permitted power values - @param[in] num number of values + @param[in] num number of values */ /**************************************************************************/ void BlueNRGGap::getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP) { @@ -1324,6 +1193,8 @@ if(state.connected == 1) { advIntMS = (conn_min_interval*1.25)-GUARD_INT; advInterval = _advParams.MSEC_TO_ADVERTISEMENT_DURATION_UNITS(advIntMS); + + PRINTF("conn_min_interval is equal to %u\r\n", conn_min_interval); } else { advInterval = _advParams.getIntervalInADVUnits(); } @@ -1391,8 +1262,8 @@ setConnectionParameters(); /* - Scan_Interval, Scan_Window, Peer_Address_Type, Peer_Address, Own_Address_Type, Conn_Interval_Min, - Conn_Interval_Max, Conn_Latency, Supervision_Timeout, Conn_Len_Min, Conn_Len_Max + Scan_Interval, Scan_Window, Peer_Address_Type, Peer_Address, Own_Address_Type, Conn_Interval_Min, + Conn_Interval_Max, Conn_Latency, Supervision_Timeout, Conn_Len_Min, Conn_Len_Max */ ret = aci_gap_create_connection(scanInterval, scanWindow, @@ -1403,7 +1274,7 @@ SUPERV_TIMEOUT, CONN_L1, CONN_L1); //_connecting = false; - + if (ret != BLE_STATUS_SUCCESS) { PRINTF("Error while starting connection (ret=0x%02X).\n\r", ret); return BLE_ERROR_UNSPECIFIED; @@ -1421,7 +1292,12 @@ { /* avoid compiler warnings about unused variables */ (void)connectionParams; - (void)scanParams; + + setScanParams(scanParams->getInterval(), + scanParams->getWindow(), + scanParams->getTimeout(), + scanParams->getActiveScanning() + ); // Save the peer address for(int i=0; i<BDADDR_SIZE; i++) { @@ -1437,7 +1313,7 @@ PRINTF("Calling createConnection from connect()\n\r"); return createConnection(); } - + return BLE_ERROR_NONE; } @@ -1528,14 +1404,19 @@ /* Clear derived class members */ m_connectionHandle = BLE_CONN_HANDLE_INVALID; - memset(deviceAppearance, 0, sizeof(deviceAppearance)); - memset(local_name, 0, LOCAL_NAME_MAX_SIZE); - memset(local_name, 0, UUID_BUFFER_SIZE); - memset(AdvData, 0, ADV_DATA_MAX_SIZE); - /* Set the whitelist policy filter modes to IGNORE_WHITELIST */ advertisingPolicyMode = Gap::ADV_POLICY_IGNORE_WHITELIST; scanningPolicyMode = Gap::SCAN_POLICY_IGNORE_WHITELIST; return BLE_ERROR_NONE; } + +void BlueNRGGap::setConnectionInterval(uint16_t interval) { + conn_min_interval = interval; + conn_max_interval = interval; +} + +void BlueNRGGap::setGapRole(Role_t role) +{ + gapRole = role; +}
--- a/source/BlueNRGGattClient.cpp Thu Sep 15 10:51:38 2016 +0100 +++ b/source/BlueNRGGattClient.cpp Thu Sep 15 10:51:40 2016 +0100 @@ -15,7 +15,7 @@ */ /** ****************************************************************************** - * @file BlueNRGGattServer.cpp + * @file BlueNRGGattServer.cpp * @author STMicroelectronics * @brief Implementation of BlueNRG BLE_API GattServer Class ****************************************************************************** @@ -29,13 +29,13 @@ * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * * <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2> - */ - + */ + /** @defgroup BlueNRGGATTClient * @brief BlueNRG BLE_API GattClient Adaptation * @{ */ - + #include "BlueNRGGattClient.h" #include "mbed-drivers/mbed.h" #include "BlueNRGGap.h" @@ -59,10 +59,10 @@ _currentState = GATT_IDLE; return; } - + // Service Discovery complete /* - if(_currentState != GATT_IDLE && + if(_currentState != GATT_IDLE && _currentState != GATT_DISCOVERY_TERMINATED && _currentState != GATT_WRITE_CHAR && _currentState != GATT_READ_CHAR) { @@ -72,6 +72,13 @@ } if(_currentState == GATT_CHAR_DESC_DISCOVERY) { + if(charDescTerminationCallback != NULL) { + CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = { + _characteristic, + BLE_ERROR_NONE + }; + charDescTerminationCallback(¶ms); + } _currentState = GATT_IDLE; } @@ -86,7 +93,7 @@ _currentState = GATT_IDLE; } } - + void BlueNRGGattClient::primaryServicesCB(Gap::Handle_t connectionHandle, uint8_t event_data_length, uint8_t attribute_data_length, @@ -107,13 +114,13 @@ // UUID Type if (attribute_data_length == 6) { - + PRINTF("UUID_TYPE_16\n\r"); uuid = attribute_data_list[offset+5]<<8|attribute_data_list[offset+4]; PRINTF("S UUID-%X attrs[%u %u]\r\n", uuid.getShortUUID(), startHandle, endHandle); - + } else { - + PRINTF("UUID_TYPE_128\n\r"); uuid.setupLong(attribute_data_list+offset+4, UUID::LSB); @@ -125,17 +132,12 @@ } #endif PRINTF(" attrs[%u %u]\r\n", startHandle, endHandle); - + } - + PRINTF("Setup serviceIndex = %d\n\r", _numServices); discoveredService[_numServices].setup(uuid, startHandle, endHandle); - - if(serviceDiscoveryCallback) { - if(_matchingServiceUUID == BLE_UUID_UNKNOWN || _matchingServiceUUID == discoveredService[_numServices].getUUID()) { - serviceDiscoveryCallback(&discoveredService[_numServices]); - } - } + _numServices++; offset += attribute_data_length; @@ -181,12 +183,9 @@ } discoveredService[i].setup(uuid, startHandle, endHandle); - - if(serviceDiscoveryCallback) { - serviceDiscoveryCallback(&discoveredService[_numServices]); - } + _numServices++; - + offset += 4; } } @@ -225,10 +224,10 @@ PRINTF("\r\n"); #endif } - + // Properties DiscoveredCharacteristic::Properties_t p; - + p._broadcast = (props_mask[0] & handle_value_pair[offset+2]); p._read = (props_mask[1] & handle_value_pair[offset+2])>>1; p._writeWoResp = (props_mask[2] & handle_value_pair[offset+2])>>2; @@ -263,9 +262,14 @@ valueHandle, lastHandle); - if(characteristicDiscoveryCallback) { - characteristicDiscoveryCallback(&discoveredChar[_numChars]); + if (_numChars != 0) { + discoveredChar[_numChars - 1].setLastHandle(declHandle - 1); + + if(characteristicDiscoveryCallback) { + characteristicDiscoveryCallback(&discoveredChar[_numChars - 1]); + } } + _numChars++; offset += handle_value_pair_length; @@ -280,9 +284,9 @@ // Charac Properties(1), Charac Value Handle(2), Charac UUID(2/16) GattAttribute::Handle_t declHandle, valueHandle, lastHandle; UUID uuid; - + PRINTF("serviceCharByUUIDCB\n\r"); - + // UUID Type if (event_data_length == 7) { PRINTF("Char UUID_TYPE_16\n\r"); @@ -303,7 +307,7 @@ // Properties DiscoveredCharacteristic::Properties_t p; - + p._broadcast = (props_mask[0] & attr_value[0]); p._read = (props_mask[1] & attr_value[0])>>1; p._writeWoResp = (props_mask[2] & attr_value[0])>>2; @@ -336,7 +340,7 @@ declHandle, valueHandle, lastHandle); - + if(characteristicDiscoveryCallback) { characteristicDiscoveryCallback(&discoveredChar[_numChars]); } @@ -346,24 +350,37 @@ ble_error_t BlueNRGGattClient::findServiceChars(Gap::Handle_t connectionHandle) { PRINTF("findServiceChars\n\r"); - + tBleStatus ret; uint8_t uuid_type = UUID_TYPE_16; uint8_t short_uuid[2]; uint8_t *uuid = NULL; - + DiscoveredService *service; - + + // complete the discovery of the last characteristic of the previous service. + // Its last handle wasn't known before this point + // update the handle and call the characteristic discovery callback. + if (_servIndex != 0 && _numChars != 0) { + discoveredChar[_numChars - 1].setLastHandle(discoveredService[_servIndex - 1].getEndHandle()); + + if(characteristicDiscoveryCallback) { + characteristicDiscoveryCallback(&discoveredChar[_numChars - 1]); + } + } + + _numChars = 0; + // We finished chars discovery for all services if(_servIndex >= _numServices) { PRINTF("!!!We finished chars discovery for all services!!!\n\r"); //_currentState = GATT_CHARS_DISCOVERY_COMPLETE; - + terminateServiceDiscovery(); - + return BLE_ERROR_NONE; } - + service = &discoveredService[_servIndex]; /* if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) { @@ -377,55 +394,59 @@ PRINTF("\r\n"); } */ - + + if(serviceDiscoveryCallback) { + serviceDiscoveryCallback(service); + } + PRINTF("findServiceChars (_servIndex=%d)\n\r", _servIndex); //ret = aci_gatt_disc_all_charac_of_serv(connectionHandle, service->getStartHandle(), service->getEndHandle()); - if(_matchingCharacteristicUUIDIn == BLE_UUID_UNKNOWN) { - PRINTF("findServiceChars (BLE_UUID_UNKNOWN)\n\r"); - ret = aci_gatt_disc_all_charac_of_serv(connectionHandle, service->getStartHandle(), service->getEndHandle()); - } else { - - uint8_t type = _matchingCharacteristicUUIDIn.shortOrLong(); - - if(type == UUID::UUID_TYPE_SHORT) { - STORE_LE_16(short_uuid, _matchingCharacteristicUUIDIn.getShortUUID()); - - uuid_type = UUID_TYPE_16; - uuid = short_uuid; + if(_matchingCharacteristicUUIDIn == BLE_UUID_UNKNOWN) { + PRINTF("findServiceChars (BLE_UUID_UNKNOWN)\n\r"); + ret = aci_gatt_disc_all_charac_of_serv(connectionHandle, service->getStartHandle(), service->getEndHandle()); + } else { + + uint8_t type = _matchingCharacteristicUUIDIn.shortOrLong(); + + if(type == UUID::UUID_TYPE_SHORT) { + STORE_LE_16(short_uuid, _matchingCharacteristicUUIDIn.getShortUUID()); + + uuid_type = UUID_TYPE_16; + uuid = short_uuid; #ifdef DEBUG - PRINTF("findServiceChars C UUID-"); - for(unsigned i = 0; i < 2; i++) { - PRINTF("%02X", short_uuid[i]); - } - PRINTF("\n\r"); + PRINTF("findServiceChars C UUID-"); + for(unsigned i = 0; i < 2; i++) { + PRINTF("%02X", short_uuid[i]); + } + PRINTF("\n\r"); #endif - } else if(type==UUID::UUID_TYPE_LONG) { - - uuid_type = UUID_TYPE_128; - uuid = (unsigned char*)_matchingCharacteristicUUIDIn.getBaseUUID(); + } else if(type==UUID::UUID_TYPE_LONG) { + + uuid_type = UUID_TYPE_128; + uuid = (unsigned char*)_matchingCharacteristicUUIDIn.getBaseUUID(); #ifdef DEBUG - PRINTF("(findServiceChars) C UUID-"); - for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) { - PRINTF("%02X", uuid[i]); - } - PRINTF("\r\n"); + PRINTF("(findServiceChars) C UUID-"); + for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) { + PRINTF("%02X", uuid[i]); + } + PRINTF("\r\n"); #endif + } + + ret = aci_gatt_disc_charac_by_uuid(connectionHandle, + service->getStartHandle(), + service->getEndHandle(), + uuid_type, + uuid); } - ret = aci_gatt_disc_charac_by_uuid(connectionHandle, - service->getStartHandle(), - service->getEndHandle(), - uuid_type, - uuid); - } - if(ret == BLE_STATUS_SUCCESS) { _servIndex++; } - + PRINTF("findServiceChars ret=%d\n\r", ret); - + return BLE_ERROR_NONE; } @@ -436,7 +457,7 @@ const UUID &matchingCharacteristicUUIDIn) { PRINTF("launchServiceDiscovery\n\r"); - + tBleStatus ret; uint8_t uuid_type = UUID_TYPE_16; uint8_t short_uuid[2]; @@ -466,17 +487,17 @@ for(j = 0; j < BLE_TOTAL_DISCOVERED_SERVICES; j++) { discoveredService[j].setup(BLE_UUID_UNKNOWN, GattAttribute::INVALID_HANDLE, GattAttribute::INVALID_HANDLE); } - + if(matchingServiceUUID == BLE_UUID_UNKNOWN) { - + // Wildcard: search for all services ret = aci_gatt_disc_all_prim_services((uint16_t)connectionHandle); - + } else { - + uint8_t type = matchingServiceUUID.shortOrLong(); //PRINTF("AddService(): Type:%d\n\r", type); - + if(type == UUID::UUID_TYPE_SHORT) { STORE_LE_16(short_uuid, matchingServiceUUID.getShortUUID()); #ifdef DEBUG @@ -486,10 +507,10 @@ } PRINTF("\n\r"); #endif - + uuid_type = UUID_TYPE_16; uuid = short_uuid; - + } else if(type==UUID::UUID_TYPE_LONG) { uuid_type = UUID_TYPE_128; @@ -503,18 +524,18 @@ PRINTF("\n\r"); #endif } - + // search for specific service by UUID ret = aci_gatt_disc_prim_service_by_uuid((uint16_t)connectionHandle, uuid_type, uuid); //ret = aci_gatt_disc_all_prim_services((uint16_t)connectionHandle); } - + if(ret == BLE_STATUS_SUCCESS) { _currentState = GATT_SERVICE_DISCOVERY; } - + PRINTF("launchServiceDiscovery ret=%d\n\r", ret); - + return BLE_ERROR_NONE; } @@ -558,7 +579,7 @@ _currentState == GATT_WRITE_CHAR ) { return false; } - + return true; */ } @@ -566,7 +587,7 @@ void BlueNRGGattClient::terminateServiceDiscovery(void) { _currentState = GATT_IDLE;//GATT_DISCOVERY_TERMINATED; - + if (terminationCallback) { terminationCallback(_connectionHandle); } @@ -590,18 +611,18 @@ (void)offset; tBleStatus ret; - + BlueNRGGattClient *gattc = const_cast<BlueNRGGattClient*>(this); - - // Save the attribute_handle not provided by evt_att_read_resp + + // Save the attribute_handle not provided by evt_att_read_resp gattc->readCBParams.handle = attributeHandle; - + // FIXME: We need to wait for a while before starting a read // due to BlueNRG process queue handling Clock_Wait(100); ret = aci_gatt_read_charac_val(connHandle, attributeHandle); - + if(ret == BLE_STATUS_SUCCESS) { gattc->_currentState = GATT_READ_CHAR; return BLE_ERROR_NONE; @@ -639,7 +660,7 @@ (void)event_data_length; writeCBParams.connHandle = connHandle; - + BlueNRGGattClient::getInstance().processWriteResponse(&writeCBParams); } @@ -653,9 +674,9 @@ (void)cmd; tBleStatus ret; - + BlueNRGGattClient *gattc = const_cast<BlueNRGGattClient*>(this); - + // We save the write response params (used by the callback) because // when the aci_gatt_write_charac_value() is used the only event received is the EVT_BLUE_GATT_PROCEDURE_COMPLETE gattc->writeCBParams.connHandle = connHandle; @@ -664,10 +685,10 @@ gattc->writeCBParams.offset = 0; gattc->writeCBParams.len = length; gattc->writeCBParams.data = value; - + ret = aci_gatt_write_charac_value(connHandle, attributeHandle, length, const_cast<uint8_t *>(value)); //ret = aci_gatt_write_charac_reliable(connHandle, attributeHandle, 0, length, const_cast<uint8_t *>(value)); - + if (ret == BLE_STATUS_SUCCESS) { gattc->_currentState = GATT_WRITE_CHAR; return BLE_ERROR_NONE; @@ -694,21 +715,25 @@ handle_uuid_length = 18; //Handle + UUID_128 numCharacDesc = (event_data_length - 1) / handle_uuid_length; - + offset = 0; + PRINTF("\r\ncharacteristic descriptor discovered: data length %u, format %u\r\n", + event_data_length, format); + + for (i=0; i<numCharacDesc; i++) { - attHandle = handle_uuid_pair[offset]; + memcpy(&attHandle, handle_uuid_pair + offset, sizeof(attHandle)); // UUID Type if (handle_uuid_length == 4) { - + PRINTF("UUID_TYPE_16\n\r"); uuid = handle_uuid_pair[offset+3]<<8|handle_uuid_pair[offset+2]; PRINTF("D UUID-%X attHandle=%u\r\n", uuid.getShortUUID(), attHandle); - + } else { - + PRINTF("UUID_TYPE_128\n\r"); uuid.setupLong(handle_uuid_pair+offset+2, UUID::LSB); #ifdef DEBUG @@ -737,15 +762,6 @@ offset += handle_uuid_length; } - - if(charDescTerminationCallback != NULL) { - CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = { - _characteristic, - BLE_ERROR_NONE - }; - charDescTerminationCallback(¶ms); - } - } ble_error_t BlueNRGGattClient::discoverCharacteristicDescriptors( @@ -766,7 +782,7 @@ GattAttribute::Handle_t valueHandle = characteristic.getValueHandle(); GattAttribute::Handle_t lastHandle = characteristic.getLastHandle(); - PRINTF("Starting aci_gatt_disc_all_charac_descriptors...\n\r"); + PRINTF("Starting aci_gatt_disc_all_charac_descriptors... [%u : %u]\n\r", valueHandle, lastHandle); ret = aci_gatt_disc_all_charac_descriptors(connHandle, valueHandle, lastHandle); if (ret == BLE_STATUS_SUCCESS) { @@ -812,5 +828,4 @@ memset(discoveredChar, 0, sizeof(discoveredChar)); return BLE_ERROR_NONE; -} - +} \ No newline at end of file
--- a/source/BlueNRGGattServer.cpp Thu Sep 15 10:51:38 2016 +0100 +++ b/source/BlueNRGGattServer.cpp Thu Sep 15 10:51:40 2016 +0100 @@ -15,7 +15,7 @@ */ /** ****************************************************************************** - * @file BlueNRGGattServer.cpp + * @file BlueNRGGattServer.cpp * @author STMicroelectronics * @brief Implementation of BlueNRG BLE_API GattServer Class ****************************************************************************** @@ -30,12 +30,12 @@ * * <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2> */ - + /** @defgroup BlueNRGGATTSERVER * @brief BlueNRG BLE_API GattServer Adaptation * @{ */ - + #include "BlueNRGGattServer.h" #include "mbed-drivers/mbed.h" #include "BlueNRGGap.h" @@ -48,7 +48,7 @@ @params[in] service Pointer to instance of the Gatt Server to add - + @returns ble_error_t @retval BLE_ERROR_NONE @@ -66,7 +66,7 @@ /* ToDo: Make sure we don't overflow the array, etc. */ /* ToDo: Make sure this service UUID doesn't already exist (?) */ /* ToDo: Basic validation */ - + tBleStatus ret; uint8_t type; uint16_t short_uuid; @@ -75,26 +75,33 @@ uint8_t char_base_uuid[16]; const uint8_t *base_uuid; const uint8_t *base_char_uuid; - - uint8_t charsCount = 0; - uint8_t maxAttrRecords = 0; + + uint8_t charsCount = service.getCharacteristicCount(); + const uint8_t available_characteristics = BLE_TOTAL_CHARACTERISTICS - characteristicCount; + + // check that there is enough characteristics left in the + // characteristic array. + if (charsCount > available_characteristics) { + PRINTF("charCount = %u and characteristicCount = %u\r\n", charsCount, available_characteristics); + return BLE_ERROR_NO_MEM; + } + + const uint16_t maxAttrRecords = computeAttributesRecord(service); type = (service.getUUID()).shortOrLong(); PRINTF("AddService(): Type:%d\n\r", type); - + /* Add the service to the BlueNRG */ short_uuid = (service.getUUID()).getShortUUID(); STORE_LE_16(primary_short_uuid, short_uuid); - + if(type==UUID::UUID_TYPE_LONG) { - base_uuid = (service.getUUID()).getBaseUUID(); - + base_uuid = (service.getUUID()).getBaseUUID(); + COPY_UUID_128(primary_base_uuid, base_uuid[15],base_uuid[14],primary_short_uuid[1],primary_short_uuid[0],base_uuid[11],base_uuid[10],base_uuid[9],base_uuid[8],base_uuid[7],base_uuid[6],base_uuid[5],base_uuid[4],base_uuid[3],base_uuid[2],base_uuid[1],base_uuid[0]); } - charsCount = service.getCharacteristicCount(); - //1(service record)+2records*char+1record*char_desc - maxAttrRecords = 1+3*charsCount; + ret = BLE_STATUS_SUCCESS; if(type==UUID::UUID_TYPE_SHORT) { ret = aci_gatt_add_serv(UUID_TYPE_16, @@ -102,9 +109,9 @@ PRIMARY_SERVICE, maxAttrRecords/*7*/, &servHandle); - PRINTF("aci_gatt_add_serv UUID_TYPE_LONG ret=%d\n\r", ret); - } - else if(type==UUID::UUID_TYPE_LONG) { + PRINTF("aci_gatt_add_serv UUID_TYPE_SHORT ret=%d\n\r", ret); + + } else if(type==UUID::UUID_TYPE_LONG) { ret = aci_gatt_add_serv(UUID_TYPE_128, primary_base_uuid, PRIMARY_SERVICE, @@ -112,12 +119,31 @@ &servHandle); PRINTF("aci_gatt_add_serv UUID_TYPE_LONG ret=%d\n\r", ret); } - + + switch (ret) { + case BLE_STATUS_SUCCESS: + break; + + case BLE_STATUS_INVALID_PARAMETER: + return BLE_ERROR_INVALID_PARAM; + + case BLE_STATUS_OUT_OF_HANDLE: + case BLE_STATUS_INSUFFICIENT_RESOURCES: + case ERR_UNSPECIFIED_ERROR: + return BLE_ERROR_NO_MEM; + + case BLE_STATUS_ERROR: + default: + return BLE_ERROR_INTERNAL_STACK_FAILURE; + } + + + service.setHandle(servHandle); //serviceHandleVector.push_back(servHandle); PRINTF("added servHandle handle =%u\n\r", servHandle); uint16_t bleCharacteristic; - + //iterate to include all characteristics for (uint8_t i = 0; i < charsCount; i++) { GattCharacteristic *p_char = service.getCharacteristic(i); @@ -138,7 +164,7 @@ #endif COPY_UUID_128(char_base_uuid,base_char_uuid[15],base_char_uuid[14],int_8_uuid[1],int_8_uuid[0],base_char_uuid[11],base_char_uuid[10],base_char_uuid[9],base_char_uuid[8],base_char_uuid[7],base_char_uuid[6],base_char_uuid[5],base_char_uuid[4],base_char_uuid[3],base_char_uuid[2],base_char_uuid[1],base_char_uuid[0]); } - + PRINTF("Char Properties 0x%x\n\r", p_char->getProperties()); /* * Gatt_Evt_Mask -> HardCoded (0) @@ -151,13 +177,13 @@ (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE| GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE))) { PRINTF("Setting up Gatt GATT_NOTIFY_ATTRIBUTE_WRITE Mask\n\r"); - Gatt_Evt_Mask = Gatt_Evt_Mask | GATT_NOTIFY_ATTRIBUTE_WRITE; + Gatt_Evt_Mask = Gatt_Evt_Mask | GATT_NOTIFY_ATTRIBUTE_WRITE | GATT_NOTIFY_WRITE_REQ_AND_WAIT_FOR_APPL_RESP; } if((p_char->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ| GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY| GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE))) { PRINTF("Setting up Gatt GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP Mask\n\r"); - Gatt_Evt_Mask = Gatt_Evt_Mask | GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP; + Gatt_Evt_Mask = Gatt_Evt_Mask | GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP; } //This will support also GATT_SERVER_ATTR_READ_WRITE since it will be covered by previous if() check. if(type==UUID::UUID_TYPE_SHORT) { @@ -171,7 +197,7 @@ 16 /*Encryption_Key_Size*/, 1 /*isVariable*/, &bleCharacteristic); - + PRINTF("aci_gatt_add_char UUID_TYPE_16 props=%d MaxLength=%d ret=%d\n\r", p_char->getProperties(), p_char->getValueAttribute().getMaxLength(), ret); @@ -186,36 +212,85 @@ 16 /*Encryption_Key_Size*/, 1 /*isVariable*/, &bleCharacteristic); - + PRINTF("aci_gatt_add_char UUID_TYPE_128 props=%d MaxLength=%d ret=%d\n\r", p_char->getProperties(), p_char->getValueAttribute().getMaxLength(), ret); } - + + switch (ret) { + case BLE_STATUS_SUCCESS: + break; + + case ERR_UNSPECIFIED_ERROR: + case BLE_STATUS_INSUFFICIENT_RESOURCES: + case BLE_STATUS_OUT_OF_HANDLE: + // TODO remove characteristics and the service previously added. + // remove service in the stack by using: Aci_Gatt_Del_Service + // remove characteristics in the stack by using: Aci_Gatt_Del_Char + // update service counter + // destroy registered characteristic and updat echaracteristic counter + return BLE_ERROR_NO_MEM; + + case BLE_STATUS_INVALID_HANDLE: + case BLE_STATUS_INVALID_PARAMETER: + case BLE_STATUS_CHARAC_ALREADY_EXISTS: + // TODO remove characteristics and the service previously added. + // remove service in the stack by using: Aci_Gatt_Del_Service + // remove characteristics in the stack by using: Aci_Gatt_Del_Char + // update service counter + // destroy registered characteristic and updat echaracteristic counter + return BLE_ERROR_INVALID_PARAM; + + case BLE_STATUS_ERROR: + default: + // TODO remove characteristics and the service previously added. + // remove service in the stack by using: Aci_Gatt_Del_Service + // remove characteristics in the stack by using: Aci_Gatt_Del_Char + // update service counter + // destroy registered characteristic and updat echaracteristic counter + return BLE_ERROR_INTERNAL_STACK_FAILURE; + } + bleCharHandleMap.insert(std::pair<uint16_t, uint16_t>(bleCharacteristic, servHandle)); - + p_characteristics[characteristicCount++] = p_char; /* Set the characteristic value handle */ p_char->getValueAttribute().setHandle(bleCharacteristic+BlueNRGGattServer::CHAR_VALUE_HANDLE); PRINTF("added bleCharacteristic (value handle =%u)\n\r", p_char->getValueAttribute().getHandle()); if ((p_char->getValueAttribute().getValuePtr() != NULL) && (p_char->getValueAttribute().getLength() > 0)) { - write(p_char->getValueAttribute().getHandle(), + ble_error_t err = write(p_char->getValueAttribute().getHandle(), p_char->getValueAttribute().getValuePtr(), p_char->getValueAttribute().getLength(), false /* localOnly */); + if (err) { + PRINTF("ERROR HERE !!!!\r\n"); + return err; + } } // add descriptors now uint16_t descHandle = 0; PRINTF("p_char->getDescriptorCount()=%d\n\r", p_char->getDescriptorCount()); - + for(uint8_t descIndex=0; descIndex<p_char->getDescriptorCount(); descIndex++) { GattAttribute *descriptor = p_char->getDescriptor(descIndex); - uint16_t shortUUID = descriptor->getUUID().getShortUUID(); - const uint8_t uuidArray[] = {(uint8_t)((shortUUID>>8)&0xFF), (uint8_t)((shortUUID&0xFF))}; + uint8_t desc_uuid[16] = { 0 }; + + + uint8_t desc_uuid_type = CHAR_DESC_TYPE_16_BIT; + STORE_LE_16(desc_uuid, descriptor->getUUID().getShortUUID()); + + if((descriptor->getUUID()).shortOrLong() == UUID::UUID_TYPE_LONG) { + desc_uuid_type = CHAR_DESC_TYPE_128_BIT; + const uint8_t* base_desc_uuid = descriptor->getUUID().getBaseUUID(); + + COPY_UUID_128(desc_uuid, base_desc_uuid[15], base_desc_uuid[14],base_desc_uuid[13],base_desc_uuid[12], base_desc_uuid[11], base_desc_uuid[10], base_desc_uuid[9], base_desc_uuid[8], base_desc_uuid[7], base_desc_uuid[6], base_desc_uuid[5], base_desc_uuid[4], base_desc_uuid[3], base_desc_uuid[2], base_desc_uuid[1], base_desc_uuid[0]); + } + ret = aci_gatt_add_char_desc(service.getHandle(), bleCharacteristic, - CHAR_DESC_TYPE_16_BIT, - uuidArray, + desc_uuid_type, + desc_uuid, descriptor->getMaxLength(), descriptor->getLength(), descriptor->getValuePtr(), @@ -226,19 +301,52 @@ CHAR_ATTRIBUTE_LEN_IS_FIXED, &descHandle); PRINTF("Adding Descriptor descriptor handle=%d ret=%d\n\r", descHandle, ret); - if(ret==(tBleStatus)0) { - PRINTF("Descriptor added successfully, descriptor handle=%d\n\r", descHandle); - descriptor->setHandle(descHandle); + + switch (ret) { + case BLE_STATUS_SUCCESS: + PRINTF("Descriptor added successfully, descriptor handle=%d\n\r", descHandle); + descriptor->setHandle(descHandle); + break; + + case ERR_UNSPECIFIED_ERROR: + case BLE_STATUS_INSUFFICIENT_RESOURCES: + case BLE_STATUS_OUT_OF_HANDLE: + // TODO remove characteristics and the service previously added. + // remove service in the stack by using: Aci_Gatt_Del_Service + // remove characteristics in the stack by using: Aci_Gatt_Del_Char + // update service counter + // destroy registered characteristic and updat echaracteristic counter + return BLE_ERROR_NO_MEM; + + case BLE_STATUS_INVALID_HANDLE: + case BLE_STATUS_INVALID_PARAMETER: + // TODO remove characteristics and the service previously added. + // remove service in the stack by using: Aci_Gatt_Del_Service + // remove characteristics in the stack by using: Aci_Gatt_Del_Char + // update service counter + // destroy registered characteristic and updat echaracteristic counter + return BLE_ERROR_INVALID_PARAM; + + case BLE_STATUS_INVALID_OPERATION: + return BLE_ERROR_OPERATION_NOT_PERMITTED; + + case BLE_STATUS_ERROR: + default: + // TODO remove characteristics and the service previously added. + // remove service in the stack by using: Aci_Gatt_Del_Service + // remove characteristics in the stack by using: Aci_Gatt_Del_Char + // update service counter + // destroy registered characteristic and updat echaracteristic counter + return BLE_ERROR_INTERNAL_STACK_FAILURE; } } + } - } - serviceCount++; - - //FIXME: There is no GattService pointer array in GattServer. + + //FIXME: There is no GattService pointer array in GattServer. // There should be one? (Only the user is aware of GattServices!) Report to forum. - + return BLE_ERROR_NONE; } @@ -269,7 +377,7 @@ ble_error_t BlueNRGGattServer::read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) { tBleStatus ret; - uint16_t charHandle = attributeHandle-BlueNRGGattServer::CHAR_VALUE_HANDLE; + uint16_t charHandle = attributeHandle; ret = aci_gatt_read_handle_value(charHandle, *lengthP, lengthP, buffer); @@ -335,38 +443,91 @@ return BLE_ERROR_NONE; } - + ble_error_t BlueNRGGattServer::write(GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly) { /* avoid compiler warnings about unused variables */ (void)localOnly; - tBleStatus ret; - - uint16_t charHandle = attributeHandle-BlueNRGGattServer::CHAR_VALUE_HANDLE; - - PRINTF("updating bleCharacteristic valueHandle=%u,\ - corresponding serviceHandle=%u len=%d\n\r", - attributeHandle, bleCharHandleMap.find(charHandle)->second, len); - - /* - * If notifications (or indications) are enabled on that characteristic, a notification (or indication) - * will be sent to the client after sending this command to the BlueNRG. - */ - ret = aci_gatt_update_char_value(bleCharHandleMap.find(charHandle)->second, charHandle, 0, len, buffer); - - if (ret != BLE_STATUS_SUCCESS){ - PRINTF("Error while updating characteristic (ret=0x%x).\n\r", ret); - switch (ret) { - case BLE_STATUS_INVALID_HANDLE: - case BLE_STATUS_INVALID_PARAMETER: - return BLE_ERROR_INVALID_PARAM; - default: - return BLE_STACK_BUSY; - } + // check that the len of the data to write are compatible with the characteristic + GattCharacteristic* characteristic = getCharacteristicFromHandle(attributeHandle); + if (!characteristic) { + PRINTF("characteristic not found\r\n"); + return BLE_ERROR_INVALID_PARAM; } - return BLE_ERROR_NONE; + // if the attribute handle is the attribute handle of the characteristic value then + // write the value + if (attributeHandle == characteristic->getValueHandle()) { + // assert the len in input is correct for this characteristic + const GattAttribute& value_attribute = characteristic->getValueAttribute(); + + // reject write if the lenght exceed the maximum lenght of this attribute + if (value_attribute.getMaxLength() < len) { + PRINTF("invalid variable length: %u, max length is: %u\r\n", len, value_attribute.getMaxLength()); + return BLE_ERROR_INVALID_PARAM; + } + + // reject write if the attribute size is fixed and the lenght in input is different than the + // length of the attribute. + if (value_attribute.hasVariableLength() == false && value_attribute.getMaxLength() != len) { + PRINTF("invalid fixed length: %u, len should be %u\r\n", len, value_attribute.getMaxLength()); + return BLE_ERROR_INVALID_PARAM; + } + + tBleStatus ret; + + uint16_t charHandle = characteristic->getValueHandle() - BlueNRGGattServer::CHAR_VALUE_HANDLE; + + PRINTF("updating bleCharacteristic valueHandle=%u,\ + corresponding serviceHandle=%u len=%d\n\r", + attributeHandle, bleCharHandleMap.find(charHandle)->second, len); + + /* + * If notifications (or indications) are enabled on that characteristic, a notification (or indication) + * will be sent to the client after sending this command to the BlueNRG. + */ + ret = aci_gatt_update_char_value(bleCharHandleMap.find(charHandle)->second, charHandle, 0, len, buffer); + + if (ret != BLE_STATUS_SUCCESS){ + PRINTF("Error while updating characteristic (ret=0x%x).\n\r", ret); + switch (ret) { + case BLE_STATUS_INVALID_HANDLE: + case BLE_STATUS_INVALID_PARAMETER: + return BLE_ERROR_INVALID_PARAM; + default: + return BLE_STACK_BUSY; + } + } + + return BLE_ERROR_NONE; + } else { + // write this handle has a descriptor handle + uint16_t charHandle = characteristic->getValueHandle() - BlueNRGGattServer::CHAR_VALUE_HANDLE; + uint16_t service_handle = bleCharHandleMap.find(charHandle)->second; + + tBleStatus ret = aci_gatt_set_desc_value( + service_handle, + charHandle, + attributeHandle, + 0, + len, + buffer + ); + + if (ret != BLE_STATUS_SUCCESS){ + PRINTF("Error while updating characteristic descriptor (ret=0x%x).\n\r", ret); + switch (ret) { + case BLE_STATUS_INVALID_HANDLE: + case BLE_STATUS_INVALID_PARAMETER: + return BLE_ERROR_INVALID_PARAM; + default: + return BLE_STACK_BUSY; + } + } + + return BLE_ERROR_NONE; + } } /**************************************************************************/ @@ -391,22 +552,58 @@ ble_error_t BlueNRGGattServer::Read_Request_CB(uint16_t attributeHandle) { uint16_t gapConnectionHandle = BlueNRGGap::getInstance().getConnectionHandle(); - + GattReadCallbackParams readParams; readParams.handle = attributeHandle; //PRINTF("readParams.handle = %d\n\r", readParams.handle); HCIDataReadEvent(&readParams); - + //EXIT: if(gapConnectionHandle != 0){ //PRINTF("Calling aci_gatt_allow_read\n\r"); aci_gatt_allow_read(gapConnectionHandle); } - + return BLE_ERROR_NONE; } +// ask if the write request should be accepted of rejected +// return 0 in case of success or an ATT error response in +// case of faillure +uint8_t BlueNRGGattServer::Write_Request_CB( + uint16_t connection_handle, uint16_t attr_handle, uint8_t data_length, + const uint8_t* data) { + + GattCharacteristic* characteristic = getCharacteristicFromHandle(attr_handle); + if(!characteristic) { + return AUTH_CALLBACK_REPLY_ATTERR_INVALID_HANDLE & 0xFF; + } + + // check if the data length is in range + if (characteristic->getValueAttribute().getMaxLength() < data_length) { + return AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH & 0xFF; + } + + // if the length of the characteristic value is fixed + // then the data in input should be of that length + if (characteristic->getValueAttribute().hasVariableLength() == false && + characteristic->getValueAttribute().getMaxLength() != data_length) { + return AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH & 0xFF; + } + + GattWriteAuthCallbackParams params = { + connection_handle, + attr_handle, + /* offset */ 0, + data_length, + data, + /* authorizationReply */ AUTH_CALLBACK_REPLY_ATTERR_WRITE_NOT_PERMITTED + }; + + return characteristic->authorizeWrite(¶ms) & 0xFF; +} + /**************************************************************************/ /*! @brief Returns the GattCharacteristic according to the handle provided @@ -444,7 +641,7 @@ p_char = p_characteristics[i]; PRINTF("Found Characteristic Properties 0x%x (handle=%d)\n\r",p_char->getProperties(), handle); break; - } + } } else { handle_1 = p_characteristics[i+1]->getValueAttribute().getHandle()-BlueNRGGattServer::CHAR_VALUE_HANDLE; @@ -464,7 +661,7 @@ void BlueNRGGattServer::HCIDataWrittenEvent(const GattWriteCallbackParams *params) { this->handleDataWrittenEvent(params); } - + void BlueNRGGattServer::HCIDataReadEvent(const GattReadCallbackParams *params) { PRINTF("Called HCIDataReadEvent\n\r"); this->handleDataReadEvent(params); @@ -478,10 +675,10 @@ this->handleDataSentEvent(count); } - + ble_error_t BlueNRGGattServer::initializeGATTDatabase(void) { - // <TODO> - return (ble_error_t)0; + // <TODO> + return (ble_error_t)0; } /**************************************************************************/ @@ -509,3 +706,44 @@ return BLE_ERROR_NONE; } + + +/// compute the number of attributes needed by this service. +uint16_t BlueNRGGattServer::computeAttributesRecord(GattService& service) { + uint16_t attribute_records = 1; + + for (uint8_t characteristic_index = 0; characteristic_index < service.getCharacteristicCount(); ++characteristic_index) { + // add two attributes, one for the characteristic declaration + // and the other for the characteristic value. + attribute_records += 2; + + const GattCharacteristic* characteristic = service.getCharacteristic(characteristic_index); + const uint8_t properties = characteristic->getProperties(); + // if notify or indicate are present, two attributes are + // needed + if ((properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) || + (properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE)) { + attribute_records += 2; + } + + // if broadcast is set, two attributes are needed + if (properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_BROADCAST) { + attribute_records += 2; + } + + // if extended properties flag is set, two attributes are needed + if (properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_EXTENDED_PROPERTIES) { + attribute_records += 2; + } + + attribute_records += characteristic->getDescriptorCount(); + } + + // for some reason, if there is just a service, this value should + // be equal to 5 + if (attribute_records == 1) { + attribute_records = 5; + } + + return attribute_records; +} \ No newline at end of file
--- a/source/platform/btle.cpp Thu Sep 15 10:51:38 2016 +0100 +++ b/source/platform/btle.cpp Thu Sep 15 10:51:40 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,16 +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);*/ + // update the peripheral preferred conenction parameters handle + // This value is hardcoded at the moment. + g_preferred_connection_parameters_char_handle = 10; + + #ifdef AST_FOR_MBED_OS minar::Scheduler::postCallback(btle_handler); #endif @@ -214,7 +199,7 @@ @brief mbedOS @param[in] void - + @returns */ /**************************************************************************/ @@ -274,7 +259,7 @@ @brief Not Used @param[in] void - + @returns */ void SPI_Poll(void) @@ -282,7 +267,7 @@ //HAL_GPIO_EXTI_Callback_Poll(BNRG_SPI_EXTI_PIN); return; } - + void Attribute_Modified_CB(evt_blue_aci *blue_evt) { uint16_t conn_handle; @@ -323,7 +308,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) { @@ -332,21 +317,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(); @@ -355,17 +341,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); + } } } @@ -380,39 +380,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; @@ -420,12 +420,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; @@ -439,7 +446,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 @@ -452,7 +459,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, @@ -462,17 +471,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, @@ -484,14 +493,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"); @@ -500,16 +535,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 @@ -518,8 +553,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"); @@ -604,12 +639,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, @@ -619,28 +684,28 @@ &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 ; } #ifdef __cplusplus } -#endif +#endif \ No newline at end of file
--- a/x-nucleo-idb0xa1/BlueNRGDiscoveredCharacteristic.h Thu Sep 15 10:51:38 2016 +0100 +++ b/x-nucleo-idb0xa1/BlueNRGDiscoveredCharacteristic.h Thu Sep 15 10:51:40 2016 +0100 @@ -30,7 +30,7 @@ GattAttribute::Handle_t declHandleIn, GattAttribute::Handle_t valueHandleIn, GattAttribute::Handle_t lastHandleIn); - + void setup(BlueNRGGattClient *gattcIn, Gap::Handle_t connectionHandleIn, UUID uuidIn, @@ -38,6 +38,9 @@ GattAttribute::Handle_t declHandleIn, GattAttribute::Handle_t valueHandleIn, GattAttribute::Handle_t lastHandleIn); + + + void setLastHandle(GattAttribute::Handle_t lastHandleIn); }; -#endif /* __BLUENRG_DISCOVERED_CHARACTERISTIC_H__ */ +#endif /* __BLUENRG_DISCOVERED_CHARACTERISTIC_H__ */ \ No newline at end of file
--- a/x-nucleo-idb0xa1/BlueNRGGap.h Thu Sep 15 10:51:38 2016 +0100 +++ b/x-nucleo-idb0xa1/BlueNRGGap.h Thu Sep 15 10:51:40 2016 +0100 @@ -16,7 +16,7 @@ /** ****************************************************************************** - * @file BlueNRGGap.h + * @file BlueNRGGap.h * @author STMicroelectronics * @brief Header file for BlueNRG BLE_API Gap Class ****************************************************************************** @@ -30,8 +30,8 @@ * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * * <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2> - */ - + */ + #ifndef __BLUENRG_GAP_H__ #define __BLUENRG_GAP_H__ @@ -66,10 +66,6 @@ #define MAX_INT_CONN 0x0C80 //=>4000msec #define DEF_INT_CONN 0x0140 //=>400msec (default value for connection interval) -#define LOCAL_NAME_MAX_SIZE 9 //8 + 1(AD_DATA_TYPE) -#define UUID_BUFFER_SIZE 17 //Either 8*2(16-bit UUIDs) or 4*4(32-bit UUIDs) or 1*16(128-bit UUIDs) +1(AD_DATA_TYPE) -#define ADV_DATA_MAX_SIZE 31 - /**************************************************************************/ /*! \brief @@ -88,7 +84,7 @@ DEVICE_FOUND, DISCOVERY_COMPLETE }; - + /* Functions that must be implemented from Gap */ virtual ble_error_t setAddress(addr_type_t type, const BLEProtocol::AddressBytes_t address); virtual ble_error_t getAddress(BLEProtocol::AddressType_t *typeP, BLEProtocol::AddressBytes_t address); @@ -136,9 +132,9 @@ void setConnectionHandle(uint16_t con_handle); uint16_t getConnectionHandle(void); - + bool getIsSetAddress(); - + Timeout getAdvTimeout(void) const { return advTimeout; } @@ -146,15 +142,19 @@ return AdvToFlag; } void setAdvToFlag(void); - + void Process(void); GapScanningParams* getScanningParams(void); virtual ble_error_t startRadioScan(const GapScanningParams &scanningParams); + void setConnectionInterval(uint16_t interval); + void setGapRole(Role_t role); + private: uint16_t m_connectionHandle; + Role_t gapRole; AddressType_t addr_type; Address_t _peerAddr; AddressType_t _peerAddrType; @@ -164,23 +164,9 @@ bool isSetAddress; uint8_t deviceAppearance[2]; - uint8_t local_name_length; - uint8_t local_name[ADV_DATA_MAX_SIZE];//LOCAL_NAME_MAX_SIZE]; - - uint8_t servUuidlength; - uint8_t servUuidData[UUID_BUFFER_SIZE]; - - uint8_t AdvLen; - uint8_t AdvData[ADV_DATA_MAX_SIZE]; - - uint8_t txPowLevSet; - Timeout advTimeout; bool AdvToFlag; - const uint8_t *scan_response_payload; - uint8_t scan_rsp_length; - static uint16_t SCAN_DURATION_UNITS_TO_MSEC(uint16_t duration) { return (duration * 625) / 1000; } @@ -202,7 +188,7 @@ ble_error_t updateAdvertisingData(void); - BlueNRGGap(): txPowLevSet(0) { + BlueNRGGap() { m_connectionHandle = BLE_CONN_HANDLE_INVALID; addr_type = BLEProtocol::AddressType::RANDOM_STATIC; @@ -216,6 +202,9 @@ BlueNRGGap(BlueNRGGap const &); void operator=(BlueNRGGap const &); + + GapAdvertisingData _advData; + GapAdvertisingData _scanResponse; }; #endif // ifndef __BLUENRG_GAP_H__ \ No newline at end of file
--- a/x-nucleo-idb0xa1/BlueNRGGattServer.h Thu Sep 15 10:51:38 2016 +0100 +++ b/x-nucleo-idb0xa1/BlueNRGGattServer.h Thu Sep 15 10:51:40 2016 +0100 @@ -15,7 +15,7 @@ */ /** ****************************************************************************** - * @file BlueNRGGattServer.cpp + * @file BlueNRGGattServer.cpp * @author STMicroelectronics * @brief Header file for BLE_API GattServer Class ****************************************************************************** @@ -30,7 +30,7 @@ * * <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2> */ - + #ifndef __BLUENRG_GATT_SERVER_H__ #define __BLUENRG_GATT_SERVER_H__ @@ -53,13 +53,13 @@ static BlueNRGGattServer m_instance; return m_instance; } - + enum HandleEnum_t { CHAR_HANDLE = 0, CHAR_VALUE_HANDLE, CHAR_DESC_HANDLE }; - + /* Functions that must be implemented from GattServer */ virtual ble_error_t addService(GattService &); virtual ble_error_t read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP); @@ -67,24 +67,33 @@ virtual ble_error_t write(GattAttribute::Handle_t, const uint8_t[], uint16_t, bool localOnly = false); virtual ble_error_t write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t, const uint8_t[], uint16_t, bool localOnly = false); virtual ble_error_t initializeGATTDatabase(void); - + virtual bool isOnDataReadAvailable() const { return true; } virtual ble_error_t reset(void); - + /* BlueNRG Functions */ void eventCallback(void); //void hwCallback(void *pckt); ble_error_t Read_Request_CB(uint16_t attributeHandle); + uint8_t Write_Request_CB( + uint16_t connection_handle, uint16_t attr_handle, + uint8_t data_length, const uint8_t* data + ); GattCharacteristic* getCharacteristicFromHandle(uint16_t charHandle); void HCIDataWrittenEvent(const GattWriteCallbackParams *params); void HCIDataReadEvent(const GattReadCallbackParams *params); void HCIEvent(GattServerEvents::gattEvent_e type, uint16_t charHandle); void HCIDataSentEvent(unsigned count); - + private: + + // compute the number of attribute record needed by a service + static uint16_t computeAttributesRecord(GattService& service); + + static const int MAX_SERVICE_COUNT = 10; uint8_t serviceCount; uint8_t characteristicCount; @@ -101,12 +110,12 @@ BlueNRGGattServer(BlueNRGGattServer const &); void operator=(BlueNRGGattServer const &); - - static const int CHAR_DESC_TYPE_16_BIT=0x01; - static const int CHAR_DESC_TYPE_128_BIT=0x02; + + static const int CHAR_DESC_TYPE_16_BIT=0x01; + static const int CHAR_DESC_TYPE_128_BIT=0x02; static const int CHAR_DESC_SECURITY_PERMISSION=0x00; - static const int CHAR_DESC_ACCESS_PERMISSION=0x03; - static const int CHAR_ATTRIBUTE_LEN_IS_FIXED=0x00; + static const int CHAR_DESC_ACCESS_PERMISSION=0x03; + static const int CHAR_ATTRIBUTE_LEN_IS_FIXED=0x00; }; -#endif +#endif \ No newline at end of file
--- a/x-nucleo-idb0xa1/bluenrg-hci/debug.h Thu Sep 15 10:51:38 2016 +0100 +++ b/x-nucleo-idb0xa1/bluenrg-hci/debug.h Thu Sep 15 10:51:40 2016 +0100 @@ -1,6 +1,6 @@ /** ****************************************************************************** - * @file debug.h + * @file debug.h * @author CL * @version V1.0.0 * @date 04-July-2014 @@ -41,7 +41,7 @@ #ifdef __cplusplus extern "C" { -#endif +#endif /* Includes ------------------------------------------------------------------*/ #include <string.h> @@ -56,7 +56,7 @@ #endif /* Print the data travelling over the SPI in the .csv format for the GUI*/ -//#define PRINT_CSV_FORMAT +//#define PRINT_CSV_FORMAT #ifdef PRINT_CSV_FORMAT #include <stdio.h> #define PRINT_CSV(...) printf(__VA_ARGS__) @@ -70,4 +70,4 @@ #endif /* __DEBUG_H */ -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ \ No newline at end of file
--- a/x-nucleo-idb0xa1/platform/btle.h Thu Sep 15 10:51:38 2016 +0100 +++ b/x-nucleo-idb0xa1/platform/btle.h Thu Sep 15 10:51:40 2016 +0100 @@ -25,20 +25,21 @@ #include <stdio.h> #include <string.h> - + #include "hci.h" -#include "bluenrg_aci.h" -#include "hci_const.h" +#include "bluenrg_aci.h" +#include "hci_const.h" #include "bluenrg_hal_aci.h" -#include "stm32_bluenrg_ble.h" +#include "stm32_bluenrg_ble.h" #include "bluenrg_gap.h" #include "bluenrg_gatt_server.h" extern uint16_t g_gap_service_handle; extern uint16_t g_appearance_char_handle; extern uint16_t g_device_name_char_handle; - -void btleInit(bool isSetAddress, uint8_t role); +extern uint16_t g_preferred_connection_parameters_char_handle; + +void btleInit(void); void SPI_Poll(void); void User_Process(void); void setConnectable(void); @@ -58,4 +59,4 @@ } #endif -#endif +#endif \ No newline at end of file