Ejemplo n.º 1
0
/******************************************************************************
##Function Name: CyBle_WptscSetCharacteristicDescriptor
*******************************************************************************

Summary:
 This function is used to write the characteristic descriptor to the server,
 which is identified by charIndex and descrIndex.

Parameters:
 connHandle:      The connection handle.
 charIndex:       The index of a service characteristic of type
                  CYBLE_WPTS_CHAR_INDEX_T.
 descrIndex:      The index of a service characteristic descriptor of type
                  CYBLE_WPTS_DESCR_INDEX_T.
 attrSize:        The size of the characteristic value attribute.
 *attrValue:      The pointer to the characteristic descriptor value data that
                  should be sent to the server device.

Return:
 A return value is of type CYBLE_API_RESULT_T.
 * CYBLE_ERROR_OK - The request was sent successfully.
 * CYBLE_ERROR_INVALID_PARAMETER - Validation of the input parameters failed.
 * CYBLE_ERROR_INVALID_STATE - The state is not valid.
 * CYBLE_ERROR_MEMORY_ALLOCATION_FAILED - Memory allocation failed.
 * CYBLE_ERROR_INVALID_OPERATION - This operation is not permitted on
                                   the specified attribute.

******************************************************************************/
CYBLE_API_RESULT_T CyBle_WptscSetCharacteristicDescriptor(CYBLE_CONN_HANDLE_T connHandle,
    CYBLE_WPTS_CHAR_INDEX_T charIndex, CYBLE_WPTS_DESCR_INDEX_T descrIndex, uint8 attrSize, uint8 *attrValue)
{
    CYBLE_API_RESULT_T apiResult;
    CYBLE_GATTC_WRITE_REQ_T writeReqParam;

    if(CyBle_GetClientState() != CYBLE_CLIENT_STATE_DISCOVERED)
    {
        apiResult = CYBLE_ERROR_INVALID_STATE;
    }
    else if((charIndex >= CYBLE_WPTS_CHAR_COUNT) || (descrIndex >= CYBLE_WPTS_DESCR_COUNT))
    {
        apiResult = CYBLE_ERROR_INVALID_PARAMETER;
    }
    else
    {
        /* Fill all fields of write request structure ... */
        writeReqParam.attrHandle = cyBle_wptsc.charInfo[charIndex].descrHandle[descrIndex];
        writeReqParam.value.val = attrValue;
        writeReqParam.value.len = attrSize;

        /* ... and send request to server's device. */
        apiResult = CyBle_GattcWriteCharacteristicDescriptors(connHandle, &writeReqParam);

        /* Save handle to support service specific read response from device */
        if(apiResult == CYBLE_ERROR_OK)
        {
            cyBle_wptscReqHandle = writeReqParam.attrHandle;
        }
    }

    return (apiResult);
}
Ejemplo n.º 2
0
/******************************************************************************
* Function Name: CyBle_AnscSetCharacteristicDescriptor
***************************************************************************//**
* 
*  Sends a request to the peer device to set the characteristic descriptor of the 
*  specified characteristic of Alert Notification Service.
*
*  Internally, Write Request is sent to the GATT Server and on successful 
*  execution of the request on the Server side the following events can be 
*  generated: 
*  * CYBLE_EVT_ANSS_NOTIFICATION_ENABLED 
*  * CYBLE_EVT_ANSS_NOTIFICATION_DISABLED
* 
*  \param connHandle: The BLE peer device connection handle.
*  \param charIndex: The index of the ANS characteristic.
*  \param descrIndex: The index of the ANS characteristic descriptor.
*  \param attrSize: The size of the characteristic descriptor attribute.
*  \param attrValue: Pointer to the characteristic descriptor value data that should be 
*              sent to the server device. 
* 
* \return
*  Return value is of type CYBLE_API_RESULT_T.
*   * CYBLE_ERROR_OK - The  request was sent successfully.
*   * CYBLE_ERROR_INVALID_STATE - The component in in invalid state for current
*                                  operation.
*   * CYBLE_ERROR_INVALID_PARAMETER - Validation of the input parameters failed.
*   * CYBLE_ERROR_MEMORY_ALLOCATION_FAILED - Memory allocation failed.
*   * CYBLE_ERROR_INVALID_OPERATION - Operation is invalid for this
*                                      characteristic.
*
* \events
*  In case of successful execution (return value = CYBLE_ERROR_OK)
*  the next events can appear: \n
*   If the ANS service-specific callback is registered 
*      (with CyBle_AnsRegisterAttrCallback):
*  * CYBLE_EVT_ANSC_WRITE_DESCR_RESPONSE - in case if the requested attribute is
*                                successfully wrote on the peer device,
*                                the details (char index, descr index etc.) are 
*                                provided with event parameter structure
*                                of type CYBLE_ANS_DESCR_VALUE_T.
*  .
*   Otherwise (if the ANS service-specific callback is not registered):
*  * CYBLE_EVT_GATTC_WRITE_RSP - in case if the requested attribute is 
*                                successfully wrote on the peer device.
*  * CYBLE_EVT_GATTC_ERROR_RSP - in case if there some trouble with the 
*                                requested attribute on the peer device,
*                                the details are provided with event parameters 
*                                structure (CYBLE_GATTC_ERR_RSP_PARAM_T).
*
******************************************************************************/
CYBLE_API_RESULT_T CyBle_AnscSetCharacteristicDescriptor(CYBLE_CONN_HANDLE_T connHandle,
                                                        CYBLE_ANS_CHAR_INDEX_T charIndex,
                                                        CYBLE_ANS_DESCR_INDEX_T descrIndex,
                                                        uint8 attrSize,
                                                        uint8 *attrValue)
{
    CYBLE_API_RESULT_T apiResult = CYBLE_ERROR_INVALID_PARAMETER;
    
    if(CyBle_GetClientState() != CYBLE_CLIENT_STATE_DISCOVERED)
    {
        apiResult = CYBLE_ERROR_INVALID_STATE;
    }
    else if((attrValue != NULL) && (descrIndex == CYBLE_ANS_CCCD) && (attrSize == CYBLE_CCCD_LEN))
    {
        if((charIndex == CYBLE_ANS_NEW_ALERT) || (charIndex == CYBLE_ANS_UNREAD_ALERT_STATUS))
        {
            CYBLE_GATTC_WRITE_REQ_T writeReqParam;
            
            /* Fill all fields of write request structure ... */
            writeReqParam.value.val = attrValue;
            writeReqParam.value.len = attrSize;
            
            if(charIndex == CYBLE_ANS_NEW_ALERT)
            {
                writeReqParam.attrHandle =
                    cyBle_ansc.characteristics[CYBLE_ANS_NEW_ALERT].descriptors[CYBLE_ANS_CCCD];
            }
            else
            {
                writeReqParam.attrHandle =
                    cyBle_ansc.characteristics[CYBLE_ANS_UNREAD_ALERT_STATUS].descriptors[CYBLE_ANS_CCCD];
            }

            /* ... and send request to server device. */        
            apiResult = CyBle_GattcWriteCharacteristicDescriptors(connHandle, &writeReqParam);
            
            if(apiResult == CYBLE_ERROR_OK)
            {
                cyBle_anscReqHandle = writeReqParam.attrHandle;
            }
        }
    }
    else
    {
        /* Characteristic has not been discovered or has invalid fields */   
    }

    return(apiResult);
}
Ejemplo n.º 3
0
/****************************************************************************** 
##Function Name: CyBle_HrscSetCharacteristicDescriptor
*******************************************************************************

Summary:
 This function is used to write the characteristic Value to the server, which
 is identified by charIndex.

 This function call can result in generation of the following events based on
 the response from the server device:
 * CYBLE_EVT_HRSC_WRITE_DESCR_RESPONSE
 * CYBLE_EVT_GATTC_ERROR_RSP

 One of the following events is received by the peer device, on invoking 
 this function:
 * CYBLE_EVT_HRSS_NOTIFICATION_ENABLED
 * CYBLE_EVT_HRSS_NOTIFICATION_DISABLED

Parameters:
 connHandle: The connection handle.
 charIndex: The index of the service characteristic.
 descrIndex: The index of the service characteristic descriptor.
 attrSize: The size of the characteristic descriptor value attribute.
 *attrValue: The pointer to the characteristic descriptor value data that
              should be sent to the server device. 

Return:
 Return value is of type CYBLE_API_RESULT_T.
 * CYBLE_ERROR_OK - The request was sent successfully
 * CYBLE_ERROR_INVALID_PARAMETER - Validation of the input parameters failed
 * CYBLE_ERROR_INVALID_STATE - The state is not valid
 * CYBLE_ERROR_MEMORY_ALLOCATION_FAILED - Memory allocation failed
 * CYBLE_ERROR_GATT_DB_INVALID_ATTR_HANDLE - The peer device doesn't have
                                              the particular characteristic
 * CYBLE_ERROR_INVALID_OPERATION - This operation is not permitted on 
                                    the specified attribute

******************************************************************************/
CYBLE_API_RESULT_T CyBle_HrscSetCharacteristicDescriptor(CYBLE_CONN_HANDLE_T connHandle, 
    CYBLE_HRS_CHAR_INDEX_T charIndex, CYBLE_HRS_DESCR_INDEX_T descrIndex, uint8 attrSize, uint8 * attrValue)
{
    CYBLE_API_RESULT_T apiResult;
    CYBLE_GATTC_WRITE_REQ_T writeReqParam;

    if(CyBle_GetClientState() != CYBLE_CLIENT_STATE_DISCOVERED)
    {
        apiResult = CYBLE_ERROR_INVALID_STATE;
    }
    else if((charIndex >= CYBLE_HRS_CHAR_COUNT)
         || (descrIndex >= CYBLE_HRS_DESCR_COUNT)
         || (attrSize != CYBLE_CCCD_LEN))
    {
        apiResult = CYBLE_ERROR_INVALID_PARAMETER;
    }
	else if(charIndex != CYBLE_HRS_HRM)
    {
        apiResult = CYBLE_ERROR_INVALID_OPERATION;
    }
    else if(CYBLE_GATT_INVALID_ATTR_HANDLE_VALUE == cyBle_hrsc.hrmCccdHandle)
    {
		apiResult = CYBLE_ERROR_GATT_DB_INVALID_ATTR_HANDLE;
	}
    else
    {
        /* Fill all fields of write request structure ... */
        writeReqParam.attrHandle = cyBle_hrsc.hrmCccdHandle;
        writeReqParam.value.val = attrValue;
        writeReqParam.value.len = CYBLE_CCCD_LEN;

        /* ... and send request to server device. */
        apiResult = CyBle_GattcWriteCharacteristicDescriptors(connHandle, &writeReqParam);
        
        /* Save handle to support service specific read response from device */
        if(apiResult == CYBLE_ERROR_OK)
        {
            cyBle_hrscReqHandle = cyBle_hrsc.hrmCccdHandle;
        }
    }

    return (apiResult);
}
Ejemplo n.º 4
0
/*******************************************************************************
* Function Name: Ancs_EventHandler()
********************************************************************************
* Summary:
* Event handler for the Apple Notification Center Service.
*
* Parameters:
* uint32 eventCode: The event to be processed
* void * eventParam: Pointer to hold the additional information associated 
*                    with an event
*
* Return:
* None
*
* Theory:
* This function is responsible for the discovery of the ANCS service, its 
* characteristics, and the characteristic descriptors. 
* Three characteristics are identified - 
*   1. Notification source
*   2. Control Point
*   3. Data source
* All other characteristics (if present) are ignored. 
* The CCCD of Notification Source and Data Source characteristics are identified.
* All other descriptors (if present) are ignored.
*
* Once the discovery procedure is complete, this function writes to the CCCDs 
* of the Notification Source and Data Source characteristics to enable GATT
* notifications on those characteristics.
* It also subscribes to the Service Changed indication on the GATT service for
* any future service change.
*
*******************************************************************************/
void Ancs_EventHandler(uint32 eventCode, void * eventParam)
{
    uint16 counter;
    uint16 dataLength;
    uint16 attributeLength;
    
    SERVICE_DATA_STRUCT * serviceData;
    CHAR_DATA_STRUCT characteristicData;
    DESC_DATA_STRUCT * descriptorData;
    
    CYBLE_GATTC_READ_BY_GRP_RSP_PARAM_T * readByGroupResponse;
    CYBLE_GATTC_READ_BY_TYPE_RSP_PARAM_T * readByTypeResponse;
    CYBLE_GATTC_FIND_INFO_RSP_PARAM_T * findInfoResponse;
    CYBLE_GATTC_ERR_RSP_PARAM_T * errorResponse;
    
    switch(eventCode)
    {
        /* Case to discover services */
        case CYBLE_EVT_GATTC_READ_BY_GROUP_TYPE_RSP:
            /* Typecast the event paramter for Read by Group Response data */ 
            readByGroupResponse = (CYBLE_GATTC_READ_BY_GRP_RSP_PARAM_T *)eventParam;
            dataLength = readByGroupResponse->attrData.length;
            attributeLength = readByGroupResponse->attrData.attrLen;
            
            /* Search for ANCS service within Services with 128-bit UUID only */
            if((dataLength == CYBLE_DISC_SRVC_INFO_128_LEN) && (ancsDiscoveryStatus == ANCS_DISC_NONE_DISCOVERED))
            {
                for(counter = 0; counter < attributeLength; counter += dataLength)
                {
                    /* Read by Group response data consists of rows of 
                     * {Service Handle range, Service UUID}.
                     * So typecast the relevant data into that structure.
                     */
                    serviceData = (SERVICE_DATA_STRUCT *)(readByGroupResponse->attrData.attrValue + counter);
                    
                    /* Check whether the Service UUID matches that of ANCS */
                    if(memcmp(serviceData->uuid.value, ancsServiceUuid, CYBLE_GATT_128_BIT_UUID_SIZE) == 0)
                    {
                        /* Match! ANCS Service found. */
                        ancsServiceRange.startHandle = serviceData->range.startHandle;
                        ancsServiceRange.endHandle = serviceData->range.endHandle;
                        ancsDiscoveryStatus = ANCS_DISC_SERVICE_DISCOVERED;
                        break;
                    }
                }
            }
            break;

            
        /* Case to discover characteristics */
        case CYBLE_EVT_GATTC_READ_BY_TYPE_RSP:
            if(ANCS_DISC_SERVICE_DISCOVERED == ancsDiscoveryStatus)
            {
                /* Typecast the event paramter for Read by Type Response data */ 
                readByTypeResponse = (CYBLE_GATTC_READ_BY_TYPE_RSP_PARAM_T *)eventParam;
                dataLength = readByTypeResponse->attrData.length;
                attributeLength = readByTypeResponse->attrData.attrLen;
                
                /* Search for ANCS characteristics (128-bit UUID) in the data */
                if(dataLength == CYBLE_DISC_CHAR_INFO_128_LEN)
                {
                    for(counter = 0; counter < attributeLength; counter += dataLength)
                    {
                        /* Cache the characteristic UUID in a buffer */
                        characteristicData.valueHandle = CyBle_Get16ByPtr(readByTypeResponse->attrData.attrValue + counter + 3);
                        memcpy(characteristicData.uuid.value, (uint8 *)(readByTypeResponse->attrData.attrValue + counter + 5), CYBLE_GATT_128_BIT_UUID_SIZE);
                        
                        /* Compare the UUID with known UUIDs for ANCS */
                        if(memcmp(characteristicData.uuid.value, ancsNotifSourceCharUuid, CYBLE_GATT_128_BIT_UUID_SIZE) == 0)
                        {
                            /* Match! ANCS Notification Source characteristic */
                            ancsNotifSourceCharHandle = characteristicData.valueHandle;
                        }
                        else if(memcmp(characteristicData.uuid.value, ancsControlPointCharUuid, CYBLE_GATT_128_BIT_UUID_SIZE) == 0)
                        {
                            /* Match! ANCS Control Point characteristic */
                            ancsControlPointCharHandle = characteristicData.valueHandle;
                        }
                        else if(memcmp(characteristicData.uuid.value, ancsDataSourceCharUuid, CYBLE_GATT_128_BIT_UUID_SIZE) == 0)
                        {
                            /* Match! ANCS Data Source characteristic */
                            ancsDataSourceCharHandle = characteristicData.valueHandle;
                        }
                        else
                        {
                            /* Unknown characteristic */
                        }
                    }
                }
            }
            break;

            
        /* Case to discover characteristic descriptors */
        case CYBLE_EVT_GATTC_FIND_INFO_RSP:
            if(ANCS_DISC_CHAR_DISCOVERED == ancsDiscoveryStatus)
            {
                /* Typecast the event paramter for Find Info Response data */ 
                findInfoResponse = (CYBLE_GATTC_FIND_INFO_RSP_PARAM_T *)eventParam;
                dataLength = CYBLE_DB_ATTR_HANDLE_LEN + CYBLE_GATT_16_BIT_UUID_SIZE;
                attributeLength = findInfoResponse->handleValueList.byteCount;
                
                /* Search within the descriptors with 16-bit UUID */
                if(findInfoResponse->uuidFormat == CYBLE_GATT_16_BIT_UUID_FORMAT)
                {
                    for(counter = 0; counter < attributeLength; counter += dataLength)
                    {
                        /* Find Info Response data consists of rows of 
                         * {Handle, UUID} of descriptors. So typecast the 
                         * relevant data into that structure.
                         */
                        descriptorData = (DESC_DATA_STRUCT *)(findInfoResponse->handleValueList.list + counter);
                        
                        /* Search for CCCD descriptors in the data */
                        if(descriptorData->uuid == CCCD_UUID_16BIT)
                        {
                            /* Found the CCCD descriptor; now check which 
                             * characteristic it belongs to.
                             */
                            if((descriptorData->descHandle < ancsNotifSourceCharHandle) && 
                               (descriptorData->descHandle < ancsDataSourceCharHandle))
                            {
                                /* Unknown CCCD; ignore */
                            }
                            else if((descriptorData->descHandle > ancsNotifSourceCharHandle) && 
                                    (descriptorData->descHandle < ancsDataSourceCharHandle))
                            {
                                /* This belongs to the Notification source 
                                 * characteristic.
                                 */
                                ancsNotifSourceCccdHandle = descriptorData->descHandle;
                            }
                            else if((descriptorData->descHandle < ancsNotifSourceCharHandle) && 
                                    (descriptorData->descHandle > ancsDataSourceCharHandle))
                            {
                                /* This belongs to the Data source 
                                 * characteristic.
                                 */
                                ancsDataSourceCccdHandle = descriptorData->descHandle;
                            }
                            else if((descriptorData->descHandle > ancsNotifSourceCharHandle) && 
                                    (descriptorData->descHandle > ancsDataSourceCharHandle))
                            {
                                /* Check if the CCCD is within range of the 
                                 * ANCS service. 
                                 */
                                if(descriptorData->descHandle <= ancsServiceRange.endHandle)
                                {
                                    /* Need to know whether Notification source 
                                     * char handle is more or Data source char. 
                                     */
                                    if(ancsNotifSourceCharHandle < ancsDataSourceCharHandle)
                                    {
                                        /* Data source CCCD */
                                        ancsDataSourceCccdHandle = descriptorData->descHandle;
                                    }
                                    else if(ancsNotifSourceCharHandle > ancsDataSourceCharHandle)
                                    {
                                        /* Notification source CCCD */
                                        ancsNotifSourceCccdHandle = descriptorData->descHandle;
                                    }
                                }
                                else
                                {
                                    /* Unknown CCCD; ignore */
                                }
                            }
                            else
                            {
                                /* Invalid data; ignore */
                            }
                        }
                        
                        if(descriptorData->descHandle == descriptorHandleRange.endHandle)
                        {
                            /* Descriptor discovery is complete */
                            ancsDiscoveryStatus = ANCS_DISC_DESC_DISCOVERED;
                            
                            /* Service discovery procedure complete; subscribe to the GATT
                             * Service changed indication by writing 0x02 to its CCCD.
                             */
                            if((serviceChangedCccdWriteStatus == SERVICE_CHANGED_CCCD_WRITE_REQ_NOT_SENT) && 
                              (cyBle_gattc.serviceChanged.valueHandle != CYBLE_GATT_INVALID_ATTR_HANDLE_VALUE))
                            {
                                serviceChangedCccdPacket.value = cccdIndFlagSetStruct;
                                serviceChangedCccdPacket.attrHandle = cyBle_gattc.cccdHandle;
                                CyBle_GattcWriteCharacteristicDescriptors(cyBle_connHandle, &serviceChangedCccdPacket);
                            }
                            serviceChangedCccdWriteStatus = SERVICE_CHANGED_CCCD_WRITE_REQ_SENT;
                            
                            break;
                        }
                    }
                }
            }
            break;

            
        case CYBLE_EVT_GATTC_WRITE_RSP:
            /* Service changed CCCD set to 0x02 to enable indications */
            if(serviceChangedCccdWriteStatus == SERVICE_CHANGED_CCCD_WRITE_REQ_SENT)
            {
                serviceChangedCccdWriteStatus = SERVICE_CHANGED_CCCD_WRITE_RESP_RECEIVED;
                
                /* Enable Notification source characteristic notifications */
                if(ancsDiscoveryStatus == ANCS_DISC_DESC_DISCOVERED)
                {
                    ancsNotificationSourceCccdPacket.value = cccdNotifFlagSetStruct;
                    ancsNotificationSourceCccdPacket.attrHandle = ancsNotifSourceCccdHandle;
                    CyBle_GattcWriteCharacteristicDescriptors(cyBle_connHandle, &ancsNotificationSourceCccdPacket);
                    ancsDiscoveryStatus = ANCS_DISC_NOTIF_SOURCE_CCCD_SET;
                }
            }
            /* ANCS Notification source characteristic CCCD set to 0x01
             * to enable notifications 
             */
            else if((ancsDiscoveryStatus == ANCS_DISC_NOTIF_SOURCE_CCCD_SET) &&
                    (ancsDataSourceCccdHandle != 0))
            {
                ancsDataSourceCccdPacket.value = cccdNotifFlagSetStruct;
                ancsDataSourceCccdPacket.attrHandle = ancsDataSourceCccdHandle;
                CyBle_GattcWriteCharacteristicDescriptors(cyBle_connHandle, &ancsDataSourceCccdPacket);
                ancsDiscoveryStatus = ANCS_DISC_DATA_SOURCE_CCCD_SET;
            }
            /* ANCS Data source characteristic CCCD set to 0x01 to enable
             * notifications.
             */
            else if(ancsDiscoveryStatus == ANCS_DISC_DATA_SOURCE_CCCD_SET)
            {
                ancsDiscoveryStatus = ANCS_DISC_WRITE_COMPLETE;
            }
            break;

            
        case CYBLE_EVT_GATTC_ERROR_RSP:
            errorResponse = (CYBLE_GATTC_ERR_RSP_PARAM_T *)eventParam;
            
            /* Check if the ANCS characteristic discovery is complete.
             * Initiate descriptor discovery if it is done.
             */
            if(ancsDiscoveryStatus == ANCS_DISC_SERVICE_DISCOVERED)
            {
                if((errorResponse->opCode == CYBLE_GATT_READ_BY_TYPE_REQ) && 
                   (errorResponse->errorCode == CYBLE_GATT_ERR_ATTRIBUTE_NOT_FOUND) &&
                   (errorResponse->attrHandle == ancsServiceRange.endHandle) &&
                   (cyBle_clientState != CYBLE_CLIENT_STATE_CHAR_DISCOVERING))
                {
                    ancsDiscoveryStatus = ANCS_DISC_CHAR_DISCOVERED;
                    descriptorHandleRange.startHandle = (ancsNotifSourceCharHandle < ancsDataSourceCharHandle) ? 
                                                        (ancsNotifSourceCharHandle + 1) : 
                                                        (ancsDataSourceCharHandle + 1);
                    descriptorHandleRange.endHandle = ancsServiceRange.endHandle;
                    CyBle_GattcDiscoverAllCharacteristicDescriptors(cyBle_connHandle, &descriptorHandleRange);
                }
            }
            break;
            
            
        default:
            break;
    }
}
Ejemplo n.º 5
0
/*******************************************************************************
* Function Name: enableNotifications
********************************************************************************
*
* Summary:
*  This function enables notfications from servers. 
*
* Parameters:
*  None.
*
* Return:
*   None.
*
*******************************************************************************/
void enableNotifications()
{     
    enableNotificationReqParam.attrHandle = txCharDescHandle;   
    CyBle_GattcWriteCharacteristicDescriptors(cyBle_connHandle, (CYBLE_GATTC_WRITE_REQ_T *)(&enableNotificationReqParam));
}
Ejemplo n.º 6
0
/*******************************************************************************
* Function Name: StackEventHandler()
********************************************************************************
* Summary:
* Event handler for the BLE events processing.
*
* Parameters:
* uint32 eventCode: The event to be processed
* void * eventParam: Pointer to hold the additional information associated 
*                    with an event
*
* Return:
* None
*
* Theory:
* The function is responsible for handling the events generated by the stack.
* It first starts advertisement once the stack is initialized. 
* Upon advertisement timeout or disconnect events, this function sets a flag
* to indicate to the main() function that it should enter Hibernate mode.
* 
* Once the device is connected, this function initiates an authentication 
* request. It displays a 6-digit passkey on the UART output on a PC and asks
* the user to enter this key on the iOS device (NP) side.
* Once the authentication is complete, the function starts the discovery 
* procedure to know whether ANCS service is supported by the peer device.
*
* When the automated service discovery is complete, the function starts a manual
* discovery procedure for the ANCS service (since the BLE component does not 
* handle discovery of custom services yet - that will be added as part of 
* Creator 3.2).
*
* When the automated service discovery is complete and the ANCS service is not 
* found, the function subscribes to the Service Changed characteristic 
* indication to know if and when the iOS device adds ANCS support later.
*
* Once the ANCS service is found and a new GATT Notification comes for any of 
* the ANCS characteristic, it calls the corresponding function in ANCS.c.
*
*******************************************************************************/
void StackEventHandler(uint32 eventCode, void * eventParam)
{
    CYBLE_GATTC_HANDLE_VALUE_NTF_PARAM_T * handleValueNotification;
    
    switch(eventCode)
    {
        case CYBLE_EVT_STACK_ON:
            /* Minor change in ADV packet for service solicitation */
            cyBle_discoveryData.advData[10] = 0x15;
            
            /* Start advertisement after stack is initialized */
            UART_UartPutString("\n\rAdvertising.");
            CyBle_GappStartAdvertisement(CYBLE_ADVERTISING_FAST);
            break;

            
        case CYBLE_EVT_GAPP_ADVERTISEMENT_START_STOP:
            if(authState != AUTHENTICATION_BONDING_REMOVE_WAITING_EVENT)
            {
                if(CyBle_GetState() == CYBLE_STATE_DISCONNECTED)
                {
                    UART_UartPutString("\n\rAdvertisement timed out. ");
                    UART_UartPutString("Going to Hibernate mode.");
                    
                    /* Enter hibernate mode upon advertisement timeout */
                    enterHibernateFlag = true;
                }
            }
            else
            {
                UART_UartPutString("\n\rAdvertisement stopped. ");
                authState = AUTHENTICATION_BONDING_REMOVE_GO_AHEAD;
            }
            break;
            
            
        case CYBLE_EVT_GAP_DEVICE_DISCONNECTED:
            /* Enter Hibernate mode upon disconnect 
             * Previous state is erased.
             */
            if(authState != AUTHENTICATION_BONDING_REMOVE_WAITING_EVENT)
            {
                UART_UartPutString("\n\rDisconnected. Going to Hibernate mode.");
                enterHibernateFlag = true;
            }
            else
            {
                UART_UartPutString("\n\rDisconnected. ");
                authState = AUTHENTICATION_BONDING_REMOVE_GO_AHEAD;
            }
            Ancs_Reset();
            break;
            
            
        case CYBLE_EVT_GAP_DEVICE_CONNECTED:
            UART_UartPutString("\n\rConnected to a peer device.");
            
            /* Send authentication request upon connection */
            CyBle_GapAuthReq(cyBle_connHandle.bdHandle, &cyBle_authInfo);
            break;
            
            
        case CYBLE_EVT_GAP_PASSKEY_DISPLAY_REQUEST:
            UART_UartPutString("\n\rEnter this passkey in your iPhone: ");
            UART_UartPutChar(HexToDecimal(*(uint32 *)eventParam, 5));
            UART_UartPutChar(HexToDecimal(*(uint32 *)eventParam, 4));
            UART_UartPutChar(HexToDecimal(*(uint32 *)eventParam, 3));
            UART_UartPutChar(HexToDecimal(*(uint32 *)eventParam, 2));
            UART_UartPutChar(HexToDecimal(*(uint32 *)eventParam, 1));
            UART_UartPutChar(HexToDecimal(*(uint32 *)eventParam, 0));
            break;
            
            
        case CYBLE_EVT_GAP_AUTH_COMPLETE:
            /* Authentication complete; initiate service discovery procedure */
            UART_UartPutString("\n\rAuthentication complete. ");
            authState = AUTHENTICATION_COMPLETE_BONDING_REQD;
            CyBle_GattcStartDiscovery(cyBle_connHandle);
            break;
            
            
        case CYBLE_EVT_GAP_AUTH_FAILED:
            /* Authentication failed; enter Hibernate mode */
            UART_UartPutString("\n\rAuthentication failed. Going to Hibernate mode.");
            enterHibernateFlag = true;

            /* Update authentication state so that bond information could be 
             * removed later.
             */
            authState = AUTHENTICATION_BONDING_COMPLETE;
            break;
            
            
        case CYBLE_EVT_GATTC_INDICATION:
            /* Server's services changed; restart service discovery */
            UART_UartPutString("\n\rService changed indication. Redo service discovery.");
            Ancs_Reset();
            CyBle_GattcStartDiscovery(cyBle_connHandle);
            break;
            
            
        case CYBLE_EVT_GATTC_DISCOVERY_COMPLETE:
            /* Automatic discovery does not cover discovery of service snd
             * characteristics with custom 128-bit UUIDs. This has to be done
             * manually. The Read by Group response for Service discovery covers
             * the ANCS custom service. For the ANCS service characteristics, the
             * Read by Type Request has to be sent by the application.
             */
            if(ANCS_DISC_SERVICE_DISCOVERED == ancsDiscoveryStatus)
            {
                CyBle_GattcDiscoverAllCharacteristics(cyBle_connHandle, ancsServiceRange);
            }
            else if(ANCS_DISC_NONE_DISCOVERED == ancsDiscoveryStatus)
            {
                UART_UartPutString("\n\rANCS service not found. ");
                
                /* Service discovery procedure complete; subscribe to the GATT
                 * Service changed indication by writing 0x02 to its CCCD.
                 */
                if((serviceChangedCccdWriteStatus == SERVICE_CHANGED_CCCD_WRITE_REQ_NOT_SENT) && 
                  (cyBle_gattc.serviceChanged.valueHandle != CYBLE_GATT_INVALID_ATTR_HANDLE_VALUE))
                {
                    serviceChangedCccdPacket.value = cccdIndFlagSetStruct;
                    serviceChangedCccdPacket.attrHandle = cyBle_gattc.cccdHandle;
                    CyBle_GattcWriteCharacteristicDescriptors(cyBle_connHandle, &serviceChangedCccdPacket);
                }
                
                /* Internal state machine tracking the CCCD status */
                serviceChangedCccdWriteStatus = SERVICE_CHANGED_CCCD_WRITE_REQ_SENT;
            }
            else
            {
                /* Other conditions need not be handled; they are handled
                 * in the event handler in ANCS.c.
                 */
            }
            break;
            
            
        case CYBLE_EVT_GATTC_READ_BY_GROUP_TYPE_RSP:
        case CYBLE_EVT_GATTC_READ_BY_TYPE_RSP:
        case CYBLE_EVT_GATTC_FIND_INFO_RSP:
        case CYBLE_EVT_GATTC_WRITE_RSP:
        case CYBLE_EVT_GATTC_ERROR_RSP:
            /* See if the events are for ANCS */
            Ancs_EventHandler(eventCode, eventParam);
            break;
            
            
        case CYBLE_EVT_GATTC_HANDLE_VALUE_NTF:
            /* See if the notification packet is for any ANCS characteristic */
            handleValueNotification = (CYBLE_GATTC_HANDLE_VALUE_NTF_PARAM_T *)eventParam;
            if(handleValueNotification->handleValPair.attrHandle == ancsNotifSourceCharHandle)
            {
                /* Notification source characteristic has a new notification */
                Ancs_HandleNotifications(handleValueNotification->handleValPair.value.val);
            }
            else if(handleValueNotification->handleValPair.attrHandle == ancsDataSourceCharHandle)
            {
                /* Data source characteristic has a new notification */
                Ancs_HandleData(handleValueNotification->handleValPair.value.val);
            }
            else
            {
                /* Some other characteristic notification; ignore */
            }
            break;
            
            
        default: 
            break;
    }
}