/****************************************************************************** * Function Name: CyBle_AnssSendNotification ***************************************************************************//** * * Sends a notification with the characteristic value, as specified by its charIndex, * to the Client device. * On enabling notification successfully for a service characteristic, if the GATT * server has an updated value to be notified to the GATT Client, it sends out a * 'Handle Value Notification' which results in CYBLE_EVT_ANSC_NOTIFICATION event * at the GATT Client's end. * * \param connHandle: The connection handle. * \param charIndex: The index of the service characteristic of type CYBLE_ANS_CHAR_INDEX_T. * The valid values are, * * CYBLE_ANS_UNREAD_ALERT_STATUS * * CYBLE_ANS_NEW_ALERT * \param attrSize: The size of the characteristic value attribute. * \param attrValue: The pointer to the characteristic value data that should be sent * to the Client device. * * \return * Return value is of type CYBLE_API_RESULT_T. * * CYBLE_ERROR_OK - The function completed successfully. * * CYBLE_ERROR_INVALID_PARAMETER - Validation of input parameter is failed. * * CYBLE_ERROR_INVALID_OPERATION - Operation is invalid for this. * characteristic. * * CYBLE_ERROR_INVALID_STATE - Connection with the client is not established. * * CYBLE_ERROR_MEMORY_ALLOCATION_FAILED - Memory allocation failed. * * CYBLE_ERROR_NTF_DISABLED - Notification is not enabled by the client. * ******************************************************************************/ CYBLE_API_RESULT_T CyBle_AnssSendNotification(CYBLE_CONN_HANDLE_T connHandle, CYBLE_ANS_CHAR_INDEX_T charIndex, uint8 attrSize, uint8 *attrValue) { CYBLE_API_RESULT_T apiResult = CYBLE_ERROR_INVALID_PARAMETER; if((charIndex == CYBLE_ANS_NEW_ALERT) || (charIndex == CYBLE_ANS_UNREAD_ALERT_STATUS)) { /* Send Notification if it is enabled and connected */ if(CYBLE_STATE_CONNECTED != CyBle_GetState()) { apiResult = CYBLE_ERROR_INVALID_STATE; } else if(!CYBLE_IS_NOTIFICATION_ENABLED(cyBle_anss.charInfo[charIndex].descrHandle[CYBLE_ANS_CCCD])) { apiResult = CYBLE_ERROR_NTF_DISABLED; } else { CYBLE_GATTS_HANDLE_VALUE_NTF_T ntfReqParam; /* Fill all fields of write request structure ... */ ntfReqParam.attrHandle = cyBle_anss.charInfo[charIndex].charHandle; ntfReqParam.value.val = attrValue; ntfReqParam.value.len = attrSize; /* Send notification to client using previously filled structure */ apiResult = CyBle_GattsNotification(connHandle, &ntfReqParam); } } return (apiResult); }
/****************************************************************************** ##Function Name: CyBle_HrssSendNotification ******************************************************************************* Summary: Sends notification of a specified Heart Rate Service characteristic value to the Client device. No response is expected. The CYBLE_EVT_HRSC_NOTIFICATION event is received by the peer device, on invoking this function. Parameters: connHandle: The connection handle which consist of the device ID and ATT connection ID. charIndex: The index of a service characteristic. attrSize: The size of the characteristic value attribute. The Heart Rate Measurement characteristic has a 20 byte length (by default). The Body Sensor Location and Control Point characteristic both have 1 byte length. *attrValue: The pointer to the characteristic value data that should be sent to the client device. Return: Return value is of type CYBLE_API_RESULT_T. * CYBLE_ERROR_OK - The request handled successfully * CYBLE_ERROR_INVALID_PARAMETER - Validation of the input parameter failed * CYBLE_ERROR_INVALID_OPERATION - This operation is not permitted * CYBLE_ERROR_INVALID_STATE - Connection with the client is not established * CYBLE_ERROR_MEMORY_ALLOCATION_FAILED - Memory allocation failed. * CYBLE_ERROR_NTF_DISABLED - Notification is not enabled by the client. ******************************************************************************/ CYBLE_API_RESULT_T CyBle_HrssSendNotification(CYBLE_CONN_HANDLE_T connHandle, CYBLE_HRS_CHAR_INDEX_T charIndex, uint8 attrSize, uint8 *attrValue) { CYBLE_API_RESULT_T apiResult; CYBLE_GATTS_HANDLE_VALUE_NTF_T ntfReqParam; /* Send Notification if it is enabled and connected */ if(CYBLE_STATE_CONNECTED != CyBle_GetState()) { apiResult = CYBLE_ERROR_INVALID_STATE; } else if(charIndex >= CYBLE_HRS_CHAR_COUNT) { apiResult = CYBLE_ERROR_INVALID_PARAMETER; } else if((cyBle_hrss.hrmCccdHandle == CYBLE_GATT_INVALID_ATTR_HANDLE_VALUE) || (!CYBLE_IS_NOTIFICATION_ENABLED(cyBle_hrss.hrmCccdHandle))) { apiResult = CYBLE_ERROR_NTF_DISABLED; } else { /* Fill all fields of write request structure ... */ ntfReqParam.attrHandle = cyBle_hrss.charHandle[charIndex]; ntfReqParam.value.val = attrValue; ntfReqParam.value.len = attrSize; /* Send notification to client using previously filled structure */ apiResult = CyBle_GattsNotification(connHandle, &ntfReqParam); } return (apiResult); }
void SendRawADCNotification(uint16 rawADC) { CYBLE_GATTS_HANDLE_VALUE_NTF_T RawADCNotificationHandle; RawADCNotificationHandle.attrHandle = CYBLE_RAW_ADC_SERVICE_RAW_ADC_CHARACTERISTIC_CHAR_HANDLE; RawADCNotificationHandle.value.val = &rawADC; RawADCNotificationHandle.value.len = 2u; CyBle_GattsNotification(cyBle_connHandle, &RawADCNotificationHandle); }
void SendVoltageMeasurementNotification(float32 voltageData) { CYBLE_GATTS_HANDLE_VALUE_NTF_T VoltageMeasurementNotificationHandle; VoltageMeasurementNotificationHandle.attrHandle = CYBLE_VOLTAGE_MEASUREMENT_SERVICE_VOLTAGE_MEASUREMENT_CHARACTERISTIC_CHAR_HANDLE; VoltageMeasurementNotificationHandle.value.val = &voltageData; VoltageMeasurementNotificationHandle.value.len = 4; /* Send notifications. */ CyBle_GattsNotification(cyBle_connHandle, &VoltageMeasurementNotificationHandle); }
/***************************************************************************** * Function Name: _BLE_sendStatusFlags() ****************************************************************************** * Summary: * Send all the status flags. * * Parameters: * None. * * Return: * None. * * Note: * *****************************************************************************/ void _BLE_sendStatusFlags(void) { static uint8 Previous_Status_Ready = 0xFF; static uint8 Previous_Status_Acquiring = 0xFF; static uint8 Previous_Status_NoMoreSpace = 0xFF; static uint8 Previous_Status_DataAcquired = 0xFF; static uint8 Previous_Status_Sending = 0xFF; static uint8 Previous_Status_NoMoreData = 0xFF; uint8 StatusArray[NUM_STATUS]; CYBLE_GATTS_HANDLE_VALUE_NTF_T NotificationHandle; CYBLE_GATTS_HANDLE_VALUE_IND_T IndicationHandle; // Verify if the status changed since the last notification. // If so, send all the current status. if( Previous_Status_Ready != Status_Ready || Previous_Status_Acquiring != Status_Acquiring || Previous_Status_NoMoreSpace != Status_NoMoreSpace || Previous_Status_DataAcquired != Status_DataAcquired || Previous_Status_Sending != Status_Sending || Previous_Status_NoMoreData != Status_NoMoreData ) { // Fill the 'StatusArray' with the current status values. StatusArray[STATUS_READY_BYTE_MASK] = Status_Ready; StatusArray[STATUS_ACQUIRING_BYTE_MASK] = Status_Acquiring; StatusArray[STATUS_NO_MORE_SPACE_BYTE_MASK] = Status_NoMoreSpace; StatusArray[STATUS_DATA_ACQUIRED_BYTE_MASK] = Status_DataAcquired; StatusArray[STATUS_SENDING_BYTE_MASK] = Status_Sending; StatusArray[STATUS_NO_MORE_DATA_BYTE_MASK] = Status_NoMoreData; // Send the Status characteristic values to BLE client. if (sendStatusNotifications) { NotificationHandle.attrHandle = CYBLE_CAPSENSE_STATUS_CHAR_HANDLE; NotificationHandle.value.val = StatusArray; NotificationHandle.value.len = NUM_STATUS; CyBle_GattsNotification(connectionHandle, &NotificationHandle); } else if (sendStatusIndications) { IndicationHandle.attrHandle = CYBLE_CAPSENSE_STATUS_CHAR_HANDLE; IndicationHandle.value.val = StatusArray; IndicationHandle.value.len = NUM_STATUS; CyBle_GattsIndication(connectionHandle, &IndicationHandle); } // Set the 'Previous_*' static variables to the current status values. Previous_Status_Ready = Status_Ready; Previous_Status_Acquiring = Status_Acquiring; Previous_Status_NoMoreSpace = Status_NoMoreSpace; Previous_Status_DataAcquired = Status_DataAcquired; Previous_Status_Sending = Status_Sending; Previous_Status_NoMoreData = Status_NoMoreData; } }
void sendCounterNotification(uint32 data) { // 'notificationHandle' stores Counter notification data parameters CYBLE_GATTS_HANDLE_VALUE_NTF_T handleValueNotify; // Update notification handle with Counter data handleValueNotify.attrHandle = COUNTER_CHAR_HANDLE; handleValueNotify.value.val = (uint8*)&data; handleValueNotify.value.len = sizeof data; // Send the updated handle as part of attribute for notifications CyBle_GattsNotification(connectionHandle, &handleValueNotify); }
/************************************************************************************************************************* * Function Name: SendAltitudeOverNotification ************************************************************************************************************************** * Summary: This function sends the altitude data as BLE notification. * It updates the notification handle with altitude data and triggers the BLE component to send notification. * * Parameters: * void * * Return: * void * *************************************************************************************************************************/ void SendAltitudeOverNotification(void) { /* If stack is not busy, then send the notification */ if(BLEStackStatus == CYBLE_STACK_STATE_FREE) { /* Update notification handle with altitude data */ AltitudeNotificationHandle.attrHandle = CYBLE_BMP180_ALTITUDE_CHAR_HANDLE; AltitudeNotificationHandle.value.val = AltitudeNotificationData; AltitudeNotificationHandle.value.len = sizeof(AltitudeNotificationData); /* Send the updated handle as part of attribute for notifications */ CyBle_GattsNotification(ConnectionHandle, &AltitudeNotificationHandle); } }
/************************************************************************************************************************* * Function Name: SendPressureOverNotification ************************************************************************************************************************** * Summary: This function sends the pressure data as BLE notification. * It updates the notification handle with pressure data and triggers the BLE component to send notification. * * Parameters: * void * * Return: * void * *************************************************************************************************************************/ void SendPressureOverNotification(void) { /* If stack is not busy, then send the notification */ if(BLEStackStatus == CYBLE_STACK_STATE_FREE) { /* Update notification handle with pressure data */ PressureNotificationHandle.attrHandle = CYBLE_BMP180_PRESSURE_CHAR_HANDLE; PressureNotificationHandle.value.val = PressureNotificationData; PressureNotificationHandle.value.len = sizeof(PressureNotificationData); /* Send the updated handle as part of attribute for notifications */ CyBle_GattsNotification(ConnectionHandle, &PressureNotificationHandle); } }
/************************************************************************************************************************* * Function Name: SendTemperatureOverNotification ************************************************************************************************************************** * Summary: This function sends the temperature data as BLE notification. * It updates the notification handle with temperature data and triggers the BLE component to send notification. * * Parameters: * void * * Return: * void * *************************************************************************************************************************/ void SendTemperatureOverNotification(void) { /* If stack is not busy, then send the notification */ if(BLEStackStatus == CYBLE_STACK_STATE_FREE) { /* Update notification handle with temperature data */ TemperatureNotificationHandle.attrHandle = CYBLE_BMP180_TEMPERATURE_CHAR_HANDLE; TemperatureNotificationHandle.value.val = TemperatureNotificationData; TemperatureNotificationHandle.value.len = sizeof(TemperatureNotificationData); /* Send the updated handle as part of attribute for notifications */ CyBle_GattsNotification(ConnectionHandle, &TemperatureNotificationHandle); } }
void updateVoltage(uint16_t voltageInMv) { CYBLE_GATTS_HANDLE_VALUE_NTF_T tempHandle; /* If stack is not busy, then send the notification */ if(_busyStatus == CYBLE_STACK_STATE_FREE) { tempHandle.attrHandle = CYBLE_POVDISPLAY_VOLTAGE_CHAR_HANDLE; tempHandle.value.val = (uint8_t*)&voltageInMv; tempHandle.value.len = 2; CyBle_GattsWriteAttributeValue(&tempHandle,0,&cyBle_connHandle,CYBLE_GATT_DB_LOCALLY_INITIATED ); if (_voltageCCCDValue[0]) { CyBle_GattsNotification(cyBle_connHandle,&tempHandle); } } }
void updateDrawLoopAverage(uint32_t drawTime) { CYBLE_GATTS_HANDLE_VALUE_NTF_T tempHandle; /* If stack is not busy, then send the notification */ if(_busyStatus == CYBLE_STACK_STATE_FREE) { tempHandle.attrHandle = CYBLE_POVDISPLAY_DRAWTIME_CHAR_HANDLE; tempHandle.value.val = (uint8_t*)&drawTime; tempHandle.value.len = 4; CyBle_GattsWriteAttributeValue(&tempHandle,0,&cyBle_connHandle,CYBLE_GATT_DB_LOCALLY_INITIATED ); if (_drawCCCDValue[0]) { CyBle_GattsNotification(cyBle_connHandle,&tempHandle); } } }
/******************************************************************************* * Function Name: Midi_TransferMessages ******************************************************************************** * * Summary: * This function fetches the MIDI messages from the MIDI buffer and triggers * a BLE notification. * * Parameters: * void * * Return: * None * *******************************************************************************/ static void Midi_TransferMessages(void) { uint8 index; /* Parse the buffers and extract messages */ for(index = 0; index < MAX_NUMBER_OF_MIDI_PACKETS; index++) { /* Valid packet is waiting to be scheduled for notification */ if(midiBuffer.midiPacket[index].packetStatus == MIDI_PACKET_VALID && midiBuffer.midiPacket[index].dataIndex > 1) { CYBLE_GATTS_HANDLE_VALUE_NTF_T midiNotification; /* If stack is not busy, then send the notification */ if( CyBle_GattGetBusStatus() == CYBLE_STACK_STATE_FREE && ((midiBuffer.midiPacket[index].dataIndex >= (CYBLE_GATT_MTU - MAX_MIDI_PACKET_LENGTH) ) || CyBle_GetBleSsState() != CYBLE_BLESS_STATE_EVENT_CLOSE) ) { CYBLE_API_RESULT_T result; /* Update notification handle with CapSense slider data*/ midiNotification.attrHandle = CYBLE_MIDI_SERVICE_MIDI_IO_CHARATERISTIC_CHAR_HANDLE; midiNotification.value.val = &(midiBuffer.midiPacket[index].midiNotificationPacket[0]); midiNotification.value.len = midiBuffer.midiPacket[index].dataIndex; /* Send the updated handle as part of attribute for notifications */ result = CyBle_GattsNotification(cyBle_connHandle,&midiNotification); if(result == CYBLE_ERROR_OK) { /* Notification is successfully queued */ midiBuffer.midiPacket[index].packetStatus = MIDI_PACKET_INVALID; midiBuffer.midiPacket[index].dataIndex = 0; } else { break; } } else { break; } } } }
void updateRotationRate(uint32_t rotationRate) { CYBLE_GATTS_HANDLE_VALUE_NTF_T tempHandle; /* If stack is not busy, then send the notification */ if(_busyStatus == CYBLE_STACK_STATE_FREE) { /* Update notification data*/ tempHandle.attrHandle = CYBLE_POVDISPLAY_ROTATIONSPEED_CHAR_HANDLE; tempHandle.value.val = (uint8_t*)&rotationRate; tempHandle.value.len = 4; /* Send the updated handle as part of attribute for notifications */ CyBle_GattsWriteAttributeValue(&tempHandle,0,&cyBle_connHandle,CYBLE_GATT_DB_LOCALLY_INITIATED ); if (_rotationCCCDValue[0]) { CyBle_GattsNotification(cyBle_connHandle,&tempHandle); } } }
/****************************************************************************** ##Function Name: CyBle_BassSendNotification ******************************************************************************* Summary: This function updates the value of the Battery Level characteristic in the GATT database. If the client has configured a notification on the Battery Level characteristic, the function additionally sends this value using a GATT Notification message. The CYBLE_EVT_BASC_NOTIFICATION event is received by the peer device, on invoking this function. Parameters: connHandle: The BLE peer device connection handle serviceIndex: The index of the service instance. e.g. If two Battery Services are supported in your design, then first service will be identified by serviceIndex of 0 and the second by serviceIndex of 1. charIndex: The index of a service characteristic of type CYBLE_BAS_CHAR_INDEX_T. attrSize: The size of the characteristic value attribute. A battery level characteristic has 1 byte length. *attrValue: The pointer to the characteristic value data that should be sent to the Client device. Return: Return value is of type CYBLE_API_RESULT_T. * CYBLE_ERROR_OK - The request handled successfully * CYBLE_ERROR_INVALID_PARAMETER - Validation of the input parameter failed * CYBLE_ERROR_INVALID_OPERATION - This operation is not permitted * CYBLE_ERROR_INVALID_STATE - Connection with the client is not established * CYBLE_ERROR_MEMORY_ALLOCATION_FAILED - Memory allocation failed. * CYBLE_ERROR_NTF_DISABLED - Notification is not enabled by the client. ******************************************************************************/ CYBLE_API_RESULT_T CyBle_BassSendNotification(CYBLE_CONN_HANDLE_T connHandle, uint8 serviceIndex, CYBLE_BAS_CHAR_INDEX_T charIndex, uint8 attrSize, uint8 *attrValue) { CYBLE_API_RESULT_T apiResult; /* Store new data in database */ apiResult = CyBle_BassSetCharacteristicValue(serviceIndex, charIndex, attrSize, attrValue); if(CYBLE_ERROR_OK == apiResult) { /* Send Notification if it is enabled and connected */ if(CYBLE_STATE_CONNECTED != CyBle_GetState()) { apiResult = CYBLE_ERROR_INVALID_STATE; } else if((cyBle_bass[serviceIndex].cccdHandle == CYBLE_GATT_INVALID_ATTR_HANDLE_VALUE) || (!CYBLE_IS_NOTIFICATION_ENABLED(cyBle_bass[serviceIndex].cccdHandle))) { apiResult = CYBLE_ERROR_NTF_DISABLED; } else { CYBLE_GATTS_HANDLE_VALUE_NTF_T ntfReqParam; /* Fill all fields of write request structure ... */ ntfReqParam.attrHandle = cyBle_bass[serviceIndex].batteryLevelHandle; ntfReqParam.value.val = attrValue; ntfReqParam.value.len = attrSize; /* Send notification to client using previously filled structure */ apiResult = CyBle_GattsNotification(connHandle, &ntfReqParam); } } return (apiResult); }
/***************************************************************************** * Function Name: _BLE_sendCapSenseData() ****************************************************************************** * Summary: * Send the whole content of the vectors through BLE notifications * or indications. * * Parameters: * None. * * Return: * 'SUCCESS' if it succeeded. * 'NO_MORE_DATA' if the vector is empty * * Note: * *****************************************************************************/ uint8 _BLE_sendCapSenseData(void) { // Verify the presence of data to send. if ( vectorIsEmpty() ) return NO_MORE_DATA; uint16 rawData[CapSense_TOTAL_SENSOR_COUNT]; uint32 encodedData[CapSense_TOTAL_SENSOR_COUNT]; uint8 numBytes_OneData = sizeof(encodedData[0]); uint8 i; uint8 j; uint8 k; uint16 arrayIterator = 0; CYBLE_GATTS_HANDLE_VALUE_NTF_T NotificationHandle; CYBLE_GATTS_HANDLE_VALUE_IND_T IndicationHandle; uint16 numIterations; uint8 buffer[CYBLE_GATT_MTU]; numIterations = ( (vectorSize() * numBytes_OneData * CapSense_TOTAL_SENSOR_COUNT) < (negotiatedMtu - 3) ) ? vectorSize() : (negotiatedMtu - 3) / numBytes_OneData / CapSense_TOTAL_SENSOR_COUNT; uint16 numBytes_AllData = numIterations * numBytes_OneData * CapSense_TOTAL_SENSOR_COUNT; for( k = 0; k < numIterations; k++) { // Retrieve the front data in the vectors. popOutVector(rawData); // Encode the data with CRC. for (i = 0; i < CapSense_TOTAL_SENSOR_COUNT; i++) encodedData[i] = encodeCRC( rawData[i] ); // Transfer the encoded sensors values into an uint8 array. for (i = 0; i < CapSense_TOTAL_SENSOR_COUNT; i++) for (j = 0; j < numBytes_OneData; j++) buffer[arrayIterator++] = encodedData[i] >> ((numBytes_OneData - 1 - j) * 8) & 0xFF; } // Send the CapSense characteristic values to BLE client. if (sendDataNotifications) { NotificationHandle.attrHandle = CYBLE_CAPSENSE_SENSORS_CHAR_HANDLE; NotificationHandle.value.val = buffer; NotificationHandle.value.len = numBytes_AllData; CyBle_GattsNotification(connectionHandle, &NotificationHandle); } else if (sendDataIndications) { IndicationHandle.attrHandle = CYBLE_CAPSENSE_SENSORS_CHAR_HANDLE; IndicationHandle.value.val = buffer; IndicationHandle.value.len = numBytes_AllData; CyBle_GattsIndication(connectionHandle, &IndicationHandle); } // Verify if the vector is now empty. if ( vectorIsEmpty() ) return NO_MORE_DATA; return SUCCESS; }