Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Flipper-Zero/STM32CubeWB.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Projects/P-NUCLEO-WB55.Nucleo/Applications/BLE/BLE_HeartRate_ANCS/STM32_WPAN/App/ancs_client_app.c')
-rw-r--r--Projects/P-NUCLEO-WB55.Nucleo/Applications/BLE/BLE_HeartRate_ANCS/STM32_WPAN/App/ancs_client_app.c2236
1 files changed, 2236 insertions, 0 deletions
diff --git a/Projects/P-NUCLEO-WB55.Nucleo/Applications/BLE/BLE_HeartRate_ANCS/STM32_WPAN/App/ancs_client_app.c b/Projects/P-NUCLEO-WB55.Nucleo/Applications/BLE/BLE_HeartRate_ANCS/STM32_WPAN/App/ancs_client_app.c
new file mode 100644
index 000000000..fe9127b34
--- /dev/null
+++ b/Projects/P-NUCLEO-WB55.Nucleo/Applications/BLE/BLE_HeartRate_ANCS/STM32_WPAN/App/ancs_client_app.c
@@ -0,0 +1,2236 @@
+/**
+ ******************************************************************************
+ * @file ancs_client_app.c
+ * @author MCD Application Team
+ * @brief ANCS client Application
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2018 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under Ultimate Liberty license
+ * SLA0044, the "License"; You may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * www.st.com/SLA0044
+ *
+ ******************************************************************************
+ */
+
+
+/* Includes ------------------------------------------------------------------*/
+#include "app_common.h"
+#include "dbg_trace.h"
+
+#include "ble.h"
+#include "app_ble.h"
+#include "ancs_client_app.h"
+
+#include "stm32_seq.h"
+
+/* Private defines -----------------------------------------------------------*/
+
+#define GET_ACTION_ID_FROM_UART 0
+
+/* MAX Number of entry in the context lists */
+#define MAX_NMB_NOTIFY 128
+#define MAX_DISPLAY_NAME_LEN 128
+#define MAX_DATA_LIST_LEN 0xFF
+#define MAX_DATA_LEN 0x0128
+
+/**
+ * The default GAP command timeout is set to 30s
+ */
+#define GAP_DEFAULT_TIMEOUT (30000)
+
+/**
+ * The default GATT command timeout is set to 30s
+ */
+#define GATT_DEFAULT_TIMEOUT (30000)
+
+
+/* Invalid Notify Entry */
+#define INVALID_NOTIFY_ENTRY 0xFFFF
+
+#define UNPACK_2_BYTE_PARAMETER(ptr) \
+ (uint16_t)((uint16_t)(*((uint8_t *)ptr))) | \
+ (uint16_t)((((uint16_t)(*((uint8_t *)ptr + 1))) << 8))
+
+/* copy UUID to tab */
+#define COPY_UUID_128(uuid_struct, uuid_15, uuid_14, uuid_13, uuid_12, uuid_11, uuid_10, uuid_9, uuid_8, uuid_7, uuid_6, uuid_5, uuid_4, uuid_3, uuid_2, uuid_1, uuid_0) \
+do {\
+ uuid_struct[0] = uuid_0; uuid_struct[1] = uuid_1; uuid_struct[2] = uuid_2; uuid_struct[3] = uuid_3; \
+ uuid_struct[4] = uuid_4; uuid_struct[5] = uuid_5; uuid_struct[6] = uuid_6; uuid_struct[7] = uuid_7; \
+ uuid_struct[8] = uuid_8; uuid_struct[9] = uuid_9; uuid_struct[10] = uuid_10; uuid_struct[11] = uuid_11; \
+ uuid_struct[12] = uuid_12; uuid_struct[13] = uuid_13; uuid_struct[14] = uuid_14; uuid_struct[15] = uuid_15; \
+}while(0)
+
+/* UUIDs list for ANCS service and characteristics*/
+#define COPY_ANCS_SERVICE_UUID(uuid_struct) COPY_UUID_128(uuid_struct, 0x79, 0x05, 0xF4, 0x31, 0xB5, 0xCE, 0x4E, 0x99, 0xA4, 0x0F, 0x4B, 0x1E, 0x12, 0x2D, 0x00, 0xD0)
+#define COPY_ANCS_NOTIFICATION_SOURCE_UUID(uuid_struct) COPY_UUID_128(uuid_struct, 0x9F, 0xBF, 0x12, 0x0D, 0x63, 0x01, 0x42, 0xD9, 0x8C, 0x58, 0x25, 0xE6, 0x99, 0xA2, 0x1D, 0xBD)
+#define COPY_ANCS_DATA_SOURCE_UUID(uuid_struct) COPY_UUID_128(uuid_struct, 0x22, 0xEA, 0xC6, 0xE9, 0x24, 0xD6, 0x4B, 0xB5, 0xBE, 0x44, 0xB3, 0x6A, 0xCE, 0x7C, 0x7B, 0xFB)
+#define COPY_ANCS_CONTROL_POINT_UUID(uuid_struct) COPY_UUID_128(uuid_struct, 0x69, 0xD1, 0xD8, 0xF3, 0x45, 0xE1, 0x49, 0xA8, 0x98, 0x21, 0x9B, 0xBD, 0xFD, 0xAA, 0xD9, 0xD9)
+
+/* Private typedef -----------------------------------------------------------*/
+typedef enum
+{
+ GAP_PROC_TERMINATE_CONNECTION,
+ GAP_PROC_SLAVE_SECURITY_REQ,
+ GAP_PROC_PASS_KEY_RESPONSE,
+ GAP_PROC_NUMERIC_COMPARISON_VALUE_CONFIRM,
+ GAP_PROC_ALLOW_REBOND,
+} GapProcId_t;
+
+typedef enum
+{
+ GATT_PROC_MTU_UPDATE,
+ GATT_PROC_DISC_ANCS_SERVICE,
+ GATT_PROC_DISC_ALL_PRIMARY_SERVICES,
+ GATT_PROC_DISC_ALL_CHARS,
+ GATT_PROC_DISC_ALL_DESCS,
+ GATT_PROC_ENABLE_ALL_NOTIFICATIONS,
+} GattProcId_t;
+
+typedef enum
+{
+ ANCS_PROC_GET_NOTIFICATION_ATTRIBUTE,
+ ANCS_PROC_GET_APP_ATTRIBUTE,
+ ANCS_PROC_PERFORM_NOTIFICATION_ACTION,
+} AncsProcId_t;
+
+/**
+ * structure of fields for GATT notication source characteristic
+ */
+typedef struct notifyListS {
+ uint8_t used; /*flag to indicate notification processed or not*/
+ EventID evID;
+ EventFlags evFlag;
+ CategoryID catID;
+ uint8_t catCount;
+ uint32_t notifUID;
+} notifyList_type;
+
+/**
+ * structure of ANCS context (containing all needed settings: events state, handlers, inputs...)
+ */
+typedef struct ancs_contextS {
+
+ ANCS_ProfileState state;
+ uint16_t connection_handle;
+
+ uint8_t Peer_Bonded;
+ uint8_t Security_Mode;
+ uint8_t Security_Level;
+ uint8_t Peer_Address_Type;
+ uint8_t Peer_Address[6];
+
+ uint8_t appDisplayName_len;
+ uint8_t appDisplayName[MAX_DISPLAY_NAME_LEN];
+ uint8_t AppIdentifierLength;
+ uint8_t AppIdentifier[MAX_DISPLAY_NAME_LEN];
+ uint8_t list[MAX_DATA_LIST_LEN];
+
+ notifyList_type notifyList[MAX_NMB_NOTIFY];
+
+ uint16_t notifyEntry; /* index of input notification */
+ uint8_t notifyShowed; /* flag to indicate notification has already been displayed */
+ uint32_t startTime;
+ uint8_t genericFlag; /* action done after notification */
+
+ uint16_t ALLServiceStartHandle;
+ uint16_t ALLServiceEndHandle;
+
+ uint16_t GAPServiceStartHandle;
+ uint16_t GAPServiceEndHandle;
+
+ uint16_t GAPCentralAddressResolutionCharStartHdle;
+ uint16_t GAPCentralAddressResolutionCharValueHdle;
+ uint16_t GAPCentralAddressResolutionCharDescHdle;
+ uint16_t GAPCentralAddressResolutionCharEndHdle;
+
+ uint16_t GATTServiceStartHandle;
+ uint16_t GATTServiceEndHandle;
+
+ uint16_t ServiceChangedCharStartHdle;
+ uint16_t ServiceChangedCharValueHdle;
+ uint16_t ServiceChangedCharDescHdle;
+ uint16_t ServiceChangedCharEndHdle;
+
+ uint16_t ANCSServiceStartHandle;
+ uint16_t ANCSServiceEndHandle;
+
+ uint16_t ANCSNotificationSourceCharStartHdle;
+ uint16_t ANCSControlPointCharStartHdle;
+ uint16_t ANCSDataSourceCharStartHdle;
+
+ uint16_t ANCSNotificationSourceCharValueHdle;
+ uint16_t ANCSControlPointCharValueHdle;
+ uint16_t ANCSDataSourceCharValueHdle;
+
+ uint16_t ANCSNotificationSourceCharDescHdle;
+ uint16_t ANCSControlPointCharDescHdle;
+ uint16_t ANCSDataSourceCharDescHdle;
+
+} ancs_context_type;
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+PLACE_IN_SECTION("BLE_APP_CONTEXT") static ancs_context_type ancs_context;
+
+/* Global variables ----------------------------------------------------------*/
+uint16_t gCharUUID=0,gCharStartHandle=0,gCharValueHandle=0,gCharDescriptorHandle=0;
+
+#if (GET_ACTION_ID_FROM_UART == 1)
+extern UART_HandleTypeDef huart1;
+#endif
+/* Private function prototypes -----------------------------------------------*/
+static void gap_cmd_resp_wait(uint32_t timeout);
+static void gap_cmd_resp_release(uint32_t flag);
+static void GapProcReq(GapProcId_t GapProcId);
+static void gatt_cmd_resp_wait(uint32_t timeout);
+static void gatt_cmd_resp_release(uint32_t flag);
+static void GattProcReq(GattProcId_t GattProcId);
+static void GattParseServicesByUUID(aci_att_find_by_type_value_resp_event_rp0 *pr);
+static void GattParseServices(aci_att_read_by_group_type_resp_event_rp0 *pr);
+static void GattParseChars(aci_att_read_by_type_resp_event_rp0 *pr);
+static void GattParseDescs(aci_att_find_info_resp_event_rp0 *pr);
+static void GattParseNotification(aci_gatt_notification_event_rp0 *pr);
+
+#if (GET_ACTION_ID_FROM_UART == 1)
+static uint8_t ANCS_App_Get_Char(void);
+static ActionID ANCS_App_Get_ActionID(void)
+#endif
+static void ANCS_App_Update_Service( void );
+static SVCCTL_EvtAckStatus_t ANCS_Client_Event_Handler( void *Event );
+
+void ANCS_Notification_Check(EventFlags EventFlagMask);
+void ANCS_Client_Reset( void );
+static void AncsProcReq(AncsProcId_t AncsProcId);
+
+
+/* Functions Definition ------------------------------------------------------*/
+/* Private functions ----------------------------------------------------------*/
+/**
+ * Display Event ID notified in ANCS notification source characteristic
+ */
+static void ANCS_Show_EventID(EventID evID)
+{
+ switch(evID) {
+ case EventIDNotificationAdded:
+ printf("** EventID: Added\r\n");
+ break;
+ case EventIDNotificationModified:
+ printf("** EventID: Modified\r\n");
+ break;
+ case EventIDNotificationRemoved:
+ printf("** EventID: Removed\r\n");
+ break;
+ }
+}
+
+/**
+ * Display Event Flag notified in ANCS notification source characteristic
+ */
+static void ANCS_Show_EventFlag(EventFlags evFlag)
+{
+ switch (evFlag) {
+ case EventFlagSilent:
+ printf("** EventFlag: Silent\r\n");
+ break;
+ case EventFlagImportant:
+ printf("** EventFlag: Important\r\n");
+ break;
+ case EventFlagPreExisting:
+ printf("** EventFlag: Pre Existing\r\n");
+ break;
+ case EventFlagPositiveAction:
+ printf("** EventFlag: Positive Action\r\n");
+ break;
+ case EventFlagNegativeAction:
+ printf("** EventFlag: Negative Action\r\n");
+ break;
+ }
+
+ printf("** EventFlags:");
+ if ((evFlag & EventFlagSilent) == EventFlagSilent) printf(" Silent");
+ if ((evFlag & EventFlagImportant) == EventFlagImportant) printf(" Important");
+ if ((evFlag & EventFlagPreExisting) == EventFlagPreExisting) printf(" PreExisting");
+ if ((evFlag & EventFlagPositiveAction) == EventFlagPositiveAction) printf(" PositiveAction");
+ if ((evFlag & EventFlagNegativeAction) == EventFlagNegativeAction) printf(" NegativeAction");
+ printf("\n\r");
+
+}
+
+/**
+ * Display CategoryID notified in ANCS notification source characteristic
+ */
+static void ANCS_Show_CategoryID(CategoryID catID)
+{
+ switch (catID) {
+ case CategoryIDOther:
+ printf("** CategoryID: Other\r\n");
+ break;
+ case CategoryIDIncomingCall:
+ printf("** CategoryID: Incoming Call\r\n");
+ break;
+ case CategoryIDMissedCall:
+ printf("** CategoryID: Missed Call\r\n");
+ break;
+ case CategoryIDVoicemail:
+ printf("** CategoryID: Voice Mail\r\n");
+ break;
+ case CategoryIDSocial:
+ printf("** CategoryID: Social\r\n");
+ break;
+ case CategoryIDSchedule:
+ printf("** CategoryID: Schedule\r\n");
+ break;
+ case CategoryIDEmail:
+ printf("** CategoryID: Email\r\n");
+ break;
+ case CategoryIDNews:
+ printf("** CategoryID: News\r\n");
+ break;
+ case CategoryIDHealthAndFitness:
+ printf("** CategoryID: Healt and Fitness\r\n");
+ break;
+ case CategoryIDBusinessAndFinance:
+ printf("** CategoryID: Business and Finance\r\n");
+ break;
+ case CategoryIDLocation:
+ printf("** CategoryID: Location\r\n");
+ break;
+ case CategoryIDEntertainment:
+ printf("** CategoryID: Entertainment\r\n");
+ break;
+ }
+}
+
+/**
+ * Display Notification AttributeID for Get Notification Attributes command from NC
+ */
+static void ANCS_Show_Attr(NotificationAttributeID attrID)
+{
+ switch (attrID) {
+ case NotificationAttributeIDAppIdentifier:
+ printf("** AppIdentifier: ");
+ break;
+ case NotificationAttributeIDTitle:
+ printf("** Title: ");
+ break;
+ case NotificationAttributeIDSubtitle:
+ printf("** SubTitle: ");
+ break;
+ case NotificationAttributeIDMessage:
+ printf("** Message: ");
+ break;
+ case NotificationAttributeIDMessageSize:
+ printf("** MessageSize: ");
+ break;
+ case NotificationAttributeIDDate:
+ printf("** Date: ");
+ break;
+ case NotificationAttributeIDPositiveActionLabel:
+ printf("** PositiveActionLabel: ");
+ break;
+ case NotificationAttributeIDNegativeActionLabel:
+ printf("** NegativeActionLabel: ");
+ break;
+ }
+}
+
+/**
+ * Display App AttributeID used in Get App Attributes command from NC
+ */
+static void ANCS_Show_AppAttr(AppAttributeID appAttrID)
+{
+ printf("\r\n*************** App Attribute Infomation Received **********************\r\n");
+ switch (appAttrID) {
+ case AppAttributeIDDisplayName:
+ printf("** DisplayName: ");
+ break;
+ }
+}
+
+/**
+ * Display different fields for GATT notication source characteristic received
+ */
+static void ANCS_Show_Notification(uint16_t index)
+{
+ printf("\r\n*************** Data Source Detail Infomation Received **********************\r\n");
+ ANCS_Show_EventID((EventID)ancs_context.notifyList[index].evID);
+ ANCS_Show_EventFlag((EventFlags)ancs_context.notifyList[index].evFlag);
+ ANCS_Show_CategoryID((CategoryID)ancs_context.notifyList[index].catID);
+ printf("** CategoryCount: %d\r\n", ancs_context.notifyList[index].catCount);
+ printf("** NotificationUID: 0x%08x\r\n", (int)ancs_context.notifyList[index].notifUID);
+}
+
+/**
+ * create Get Notification Attributes command to NP from UID notification and action flags inputs
+ */
+static void ANCS_Cmd_GetNotificationAttr(notificationAttr_type attr)
+{
+ tBleStatus result = BLE_STATUS_SUCCESS;
+ uint8_t CmdSize = 0;
+ uint8_t CmdGetNotificationAtt[19]={CommandIDGetNotificationAttributes,
+ 0x00,0x00,0x00,0x00,
+ NotificationAttributeIDAppIdentifier,
+ NotificationAttributeIDTitle,0xFF,0xFF,
+ NotificationAttributeIDSubtitle,0xFF,0xFF,
+ NotificationAttributeIDMessage,0xFF,0xFF,
+ NotificationAttributeIDMessageSize,
+ NotificationAttributeIDDate,
+ NotificationAttributeIDPositiveActionLabel,
+ NotificationAttributeIDNegativeActionLabel};
+
+ CmdGetNotificationAtt[CmdSize++] = CommandIDGetNotificationAttributes;
+
+ CmdGetNotificationAtt[CmdSize++] = (uint8_t)((attr.UID >> 0) & 0xFF);
+ CmdGetNotificationAtt[CmdSize++] = (uint8_t)((attr.UID >> 8) & 0xFF);
+ CmdGetNotificationAtt[CmdSize++] = (uint8_t)((attr.UID >> 16) & 0xFF);
+ CmdGetNotificationAtt[CmdSize++] = (uint8_t)((attr.UID >> 24) & 0xFF);
+
+ if (attr.appID_flag == TRUE)
+ {
+ CmdGetNotificationAtt[CmdSize++] = NotificationAttributeIDAppIdentifier;
+ }
+
+ if ( (attr.title_flag == TRUE) && (attr.title_max_size != 0x00) )
+ {
+ CmdGetNotificationAtt[CmdSize++] = NotificationAttributeIDTitle;
+ CmdGetNotificationAtt[CmdSize++] = (uint8_t)((attr.title_max_size >> 0) & 0xFF);
+ CmdGetNotificationAtt[CmdSize++] = (uint8_t)((attr.title_max_size >> 8) & 0xFF);
+ }
+
+ if ( (attr.subtitle_flag == TRUE) && (attr.subtitle_max_size!= 0x00) )
+ {
+ CmdGetNotificationAtt[CmdSize++] = NotificationAttributeIDSubtitle;
+ CmdGetNotificationAtt[CmdSize++] = (uint8_t)((attr.subtitle_max_size >> 0) & 0xFF);
+ CmdGetNotificationAtt[CmdSize++] = (uint8_t)((attr.subtitle_max_size >> 8) & 0xFF);
+ }
+
+ if ( (attr.message_flag == TRUE) && (attr.message_max_size != 0x00) )
+ {
+ CmdGetNotificationAtt[CmdSize++] = NotificationAttributeIDMessage;
+ CmdGetNotificationAtt[CmdSize++] = (uint8_t)((attr.message_max_size >> 0) & 0xFF);
+ CmdGetNotificationAtt[CmdSize++] = (uint8_t)((attr.message_max_size >> 8) & 0xFF);
+ }
+
+ if (attr.messageSize_flag == TRUE)
+ {
+ CmdGetNotificationAtt[CmdSize++] = NotificationAttributeIDMessageSize;
+ }
+
+ if (attr.date_flag == TRUE)
+ {
+ CmdGetNotificationAtt[CmdSize++] = NotificationAttributeIDDate;
+ }
+
+ if (attr.positiveAction_flag == TRUE)
+ {
+ CmdGetNotificationAtt[CmdSize++] = NotificationAttributeIDPositiveActionLabel;
+ }
+
+ if (attr.negativeAction_flag == TRUE)
+ {
+ CmdGetNotificationAtt[CmdSize++] = NotificationAttributeIDNegativeActionLabel;
+ }
+
+ result = aci_gatt_write_char_value( ancs_context.connection_handle,
+ ancs_context.ANCSControlPointCharValueHdle,
+ CmdSize,
+ (uint8_t *)CmdGetNotificationAtt);
+ gatt_cmd_resp_wait(GATT_DEFAULT_TIMEOUT);
+ if (result != BLE_STATUS_SUCCESS)
+ {
+ APP_DBG_MSG(" aci_gatt_write_char_value cmd NOK status =0x%02X \n",result);
+ }
+
+}
+
+
+/**
+ * create Perform Notification Action command from UID notification received and desired action ID
+ */
+static void ANCS_Cmd_PerformNotificationAction(uint32_t notificationUID, ActionID actID)
+{
+ tBleStatus result = BLE_STATUS_SUCCESS;
+ uint8_t CmdSize = 0;
+ uint8_t CmdPerformNotificationAction[6]={CommandIDPerformNotificationAction,
+ 0x00,0x00,0x00,0x00,
+ ActionIDPositive };
+
+ CmdPerformNotificationAction[CmdSize++] = CommandIDPerformNotificationAction;
+ CmdPerformNotificationAction[CmdSize++] = (uint8_t)((notificationUID >> 0) & 0xFF);
+ CmdPerformNotificationAction[CmdSize++] = (uint8_t)((notificationUID >> 8) & 0xFF);
+ CmdPerformNotificationAction[CmdSize++] = (uint8_t)((notificationUID >> 16) & 0xFF);
+ CmdPerformNotificationAction[CmdSize++] = (uint8_t)((notificationUID >> 24) & 0xFF);
+ CmdPerformNotificationAction[CmdSize++] = actID;
+
+ result = aci_gatt_write_char_value(ancs_context.connection_handle,
+ ancs_context.ANCSControlPointCharValueHdle,
+ CmdSize,
+ (uint8_t *)CmdPerformNotificationAction);
+ gatt_cmd_resp_wait(GATT_DEFAULT_TIMEOUT);
+ if (result != BLE_STATUS_SUCCESS)
+ {
+ APP_DBG_MSG(" aci_gatt_write_char_value cmd NOK status =0x%02X \n",result);
+ }
+}
+
+/**
+ * create Get App Attributes command to NP for number of wanted AppIdentifiers input
+ */
+static void ANCS_Cmd_GetAppAttr(uint8_t AppIdentifierLength, char *AppIdentifier/* NULL Terminated*/)
+{
+ tBleStatus result = BLE_STATUS_SUCCESS;
+ uint8_t CmdSize = 0;
+ uint8_t CmdGetAppAtt[128]={0};
+
+ CmdGetAppAtt[CmdSize++] = CommandIDGetAppAttributes;
+
+ /*Number of wanted App Identifiers*/
+ for (int idx=0;idx<AppIdentifierLength;idx++)
+ CmdGetAppAtt[CmdSize++] = AppIdentifier[idx];
+
+ CmdGetAppAtt[CmdSize++] = AppAttributeIDDisplayName;
+
+ result = aci_gatt_write_char_value( ancs_context.connection_handle,
+ ancs_context.ANCSControlPointCharValueHdle,
+ CmdSize,
+ (uint8_t *)CmdGetAppAtt);
+ gatt_cmd_resp_wait(GATT_DEFAULT_TIMEOUT);
+ if (result != BLE_STATUS_SUCCESS)
+ {
+ APP_DBG_MSG(" aci_gatt_write_char_value cmd NOK status =0x%02X \n",result);
+ }
+}
+
+/**
+* Parser of response for Get Notification Attributes command
+* number of received attributes and attributes list input
+*/
+static void ANCS_Parse_GetNotificationAttr_Resp(uint8_t commandID, uint16_t attrLen, uint8_t *attrList)
+{
+ uint8_t appId,PositiveActionLabel,NegativeActionLabel;
+ uint16_t len, index;
+
+ appId = FALSE;
+ PositiveActionLabel = FALSE;
+ NegativeActionLabel = FALSE;
+ index = 0;
+
+ if(commandID == CommandIDGetNotificationAttributes)
+ {
+ /* loop on number of attribute IDs */
+ while (index < attrLen)
+ {
+ /* attrList[index+0] corresponding to AttributeID x*/
+ Osal_MemCpy(&len, &attrList[index+1], 2); /* AttributeID x Value Length */
+ if (len == 0) /* Empty */
+ {
+ index += 3;
+ }
+ else
+ {
+ /* AttributeID x */
+ if (!ancs_context.notifyShowed) {
+ ANCS_Show_Notification(ancs_context.notifyEntry);
+ ancs_context.notifyShowed = TRUE;
+ }
+ ANCS_Show_Attr((NotificationAttributeID)attrList[index]); /* Notification AttributeID x*/
+
+ /* AttributeID for Application identifier */
+ if (attrList[index] == NotificationAttributeIDAppIdentifier)
+ {
+ appId = TRUE;
+ }
+ else if (attrList[index] == NotificationAttributeIDPositiveActionLabel)
+ {
+ PositiveActionLabel = TRUE;
+ }
+ else if (attrList[index] == NotificationAttributeIDNegativeActionLabel)
+ {
+ NegativeActionLabel = TRUE;
+ }
+
+ /* AttributeID x Value */
+ index++;
+ if (len <= sizeof(ancs_context.list))
+ {
+ Osal_MemCpy(ancs_context.list, &attrList[index+2], len);
+ ancs_context.list[len] = '\0';
+ }
+ else
+ {
+ APP_DBG_MSG("cut the AttributeID x Value len=%d <= sizeof(ancs_context.list)=%d \n\r",len,sizeof(ancs_context.list));
+ Osal_MemCpy(ancs_context.list, &attrList[index+2], sizeof(ancs_context.list)-1);
+ ancs_context.list[sizeof(ancs_context.list)-1] = '\0';
+ }
+
+ index += 2 + len; /* 2 Bytes Length of AttributeID x Value + Value Length*/
+ if (appId)
+ {
+ if ((len+1) <= MAX_DISPLAY_NAME_LEN)
+ {
+ Osal_MemCpy(ancs_context.AppIdentifier, ancs_context.list, len+1);
+ ancs_context.AppIdentifierLength = len + 1;
+ } else {
+ Osal_MemCpy(ancs_context.AppIdentifier, ancs_context.list, MAX_DISPLAY_NAME_LEN);
+ ancs_context.AppIdentifierLength = MAX_DISPLAY_NAME_LEN;
+ }
+
+ ancs_context.state = ANCS_GET_APP_ATTRIBUTE; /* 3.2 Get APP Attributes (Detail Infomation about the App, Now only support to Get Name of App) */
+ appId = FALSE;
+ }
+
+ if (len > 0)
+ printf(" %s\r\n", ancs_context.list);
+ }
+ }// while
+
+ if(ancs_context.state == ANCS_GET_APP_ATTRIBUTE)
+ {
+ APP_DBG_MSG(" 3.2 Get APP Attributes (Detail Infomation about the App, Now only support to Get Name of App) => ANCS_GET_APP_ATTRIBUTE \n\r");
+ }
+ else
+ {
+ /* Note, there is no AppIdentifier, so we only perform active action, but you also can perform negtive action */
+ if( (PositiveActionLabel == TRUE) || (NegativeActionLabel == TRUE) )
+ {
+ ancs_context.state = ANCS_PERFORM_NOTIFICATION_ACTION; /* 3.2 Perform Notification Action */
+ APP_DBG_MSG(" 3.2 Perform Notification Action => ANCS_PERFORM_NOTIFICATION_ACTION \n\r");
+ }
+ else
+ {
+ ancs_context.state = ANCS_IDLE; /* 3.2 Perform Notification Action */
+ APP_DBG_MSG(" No AppIdentifier & PositiveActionLabel & NegativeActionLabel ==> ANCS_IDLE \n\r");
+ }
+ }
+ }// commandID
+}
+
+/**
+* Parser of response for Get App Attributes command
+* number of received attributes and attributes list input
+*/
+static void ANCS_Parse_GetAppAttr_Resp(uint8_t commandID, uint16_t attrLen, uint8_t *attrList)
+{
+ uint8_t appId;
+ uint16_t len, index;
+
+ index = 0;
+ if(commandID == CommandIDGetAppAttributes)
+ {
+ /* loop on number of attribute IDs */
+ while (index < attrLen)
+ {
+ /* attrList[index+0] corresponding to AttributeID x*/
+ Osal_MemCpy(&len, &attrList[index+1], 2); /* AttributeID x Value Length */
+ if (len == 0) /* Empty */
+ {
+ index += 3;
+ }
+ else
+ {
+ /* AttributeID x */
+ ANCS_Show_AppAttr((AppAttributeID)attrList[index]); /* App AttributeID x */
+
+ /* AttributeID for Application identifier */
+ if (attrList[index] == AppAttributeIDDisplayName)
+ {
+ appId = TRUE;
+ } else {
+ appId = FALSE;
+ }
+
+ /* AttributeID x Value */
+ index++;
+ if (len <= sizeof(ancs_context.list))
+ {
+ Osal_MemCpy(ancs_context.list, &attrList[index+2], len);
+ ancs_context.list[len] = '\0';
+ }
+ else
+ {
+ APP_DBG_MSG("cut the AttributeID x Value len=%d <= sizeof(ancs_context.list)=%d \n\r",len,sizeof(ancs_context.list));
+ Osal_MemCpy(ancs_context.list, &attrList[index+2], sizeof(ancs_context.list)-1);
+ ancs_context.list[sizeof(ancs_context.list)-1] = '\0';
+ }
+
+ index += 2 + len; /* 2 Bytes Length of AttributeID x Value + Value Length*/
+ if (appId)
+ {
+ if ((len+1) <= MAX_DISPLAY_NAME_LEN)
+ {
+ Osal_MemCpy(ancs_context.appDisplayName, ancs_context.list, len+1);
+ ancs_context.appDisplayName_len = len + 1;
+ } else {
+ Osal_MemCpy(ancs_context.appDisplayName, ancs_context.list, MAX_DISPLAY_NAME_LEN);
+ ancs_context.appDisplayName_len = MAX_DISPLAY_NAME_LEN;
+ }
+ } // appId
+
+ if (len > 0)
+ printf(" %s\r\n", ancs_context.list);
+ }
+ }// while
+
+ if( (ancs_context.notifyList[ancs_context.notifyEntry].catID == CategoryIDIncomingCall) ||
+ (ancs_context.notifyList[ancs_context.notifyEntry].catID == CategoryIDSchedule) ) /* depends on different Category */
+ /* if( ((ancs_context.notifyList[ancs_context.notifyEntry].evFlag & EventFlagPositiveAction) == EventFlagPositiveAction) ||
+ ((ancs_context.notifyList[ancs_context.notifyEntry].evFlag & EventFlagNegativeAction) == EventFlagNegativeAction) )*//* depends on action type */
+ {
+ ancs_context.genericFlag = TRUE;
+ ancs_context.state = ANCS_PERFORM_NOTIFICATION_ACTION; /* 3.4 Perform Notification Action */
+ APP_DBG_MSG(" 3.4 Perform Notification Action => ANCS_PERFORM_NOTIFICATION_ACTION \n\r");
+ } else {
+ APP_DBG_MSG("CommandIDGetAppAttributes notifyEntry=%d Removed\n\r", ancs_context.notifyEntry);
+ ancs_context.notifyList[ancs_context.notifyEntry].used = FALSE;
+ ancs_context.state = ANCS_CHECK_NOTIFICATION;
+ }
+ }// commandID
+}
+/**
+* Parser of ANCS Notification Source characteristic received
+* to fill ancs_context.notifyList elements
+*/
+static void ANCS_Notification_Source_Received_event(
+ EventID evID,
+ EventFlags evFlag,
+ CategoryID catID,
+ uint8_t catCount,
+ uint32_t notifUID)
+{
+ uint16_t i;
+
+ printf("*************** Notification Source Basic Infomation Received **********************\r\n");
+ ANCS_Show_EventID(evID);
+ ANCS_Show_EventFlag(evFlag);
+ ANCS_Show_CategoryID(catID);
+ printf("** CategoryCount: %d \r\n", catCount);
+ printf("** NotificationUID: 0x%08x \r\n", notifUID);
+
+ //ancs_context.notifyEntry = INVALID_NOTIFY_ENTRY;
+
+ if (evID == EventIDNotificationRemoved)
+ {
+ for (i=0; i < MAX_NMB_NOTIFY; i++)
+ {
+ if (ancs_context.notifyList[i].notifUID == notifUID)
+ {
+ ancs_context.notifyList[i].used = FALSE;
+ printf("** notifyEntry: %d Removed\r\n", i);
+ break;
+ }
+ }
+ }
+ else
+ {
+ for (i=0; i < MAX_NMB_NOTIFY; i++)
+ {
+ if (!ancs_context.notifyList[i].used)
+ {
+ ancs_context.notifyList[i].used = TRUE;
+ ancs_context.notifyList[i].evID = evID;
+ ancs_context.notifyList[i].evFlag = evFlag;
+ ancs_context.notifyList[i].catID = catID;
+ ancs_context.notifyList[i].catCount = catCount;
+ ancs_context.notifyList[i].notifUID = notifUID;
+ printf("** notifyEntry: %d Added\r\n", i);
+ break;
+ }
+ }
+ }
+}
+
+/**
+* check event flag from ANCS Notification Source characteristic received
+* to fill ancs_context and filter silent event flags
+*/
+void ANCS_Notification_Check(EventFlags EventFlagMask)
+{
+ ancs_context.notifyEntry = INVALID_NOTIFY_ENTRY;
+ for (uint8_t idx=0; idx<MAX_NMB_NOTIFY; idx++)
+ {
+ if (ancs_context.notifyList[idx].used)
+ {
+
+ if((ancs_context.notifyList[idx].evFlag & EventFlagMask) == EventFlagMask)
+ {
+ ancs_context.notifyEntry = idx;
+ ancs_context.notifyShowed = FALSE;
+ ancs_context.state = ANCS_GET_NOTIFICATION_ATTRIBUTE;
+ APP_DBG_MSG("2. Get More Detail Infomations notifyEntry=%d ==> ANCS_GET_NOTIFICATION_ATTRIBUTE \n\r",ancs_context.notifyEntry);
+ break;
+ }
+ }
+ }
+ if (ancs_context.notifyEntry == INVALID_NOTIFY_ENTRY)
+ {
+ APP_DBG_MSG(" ancs_context.notifyEntry == INVALID_NOTIFY_ENTRY => ANCS_IDLE \n\r");
+ ancs_context.state = ANCS_IDLE;
+ }
+}
+
+/* Public functions ----------------------------------------------------------*/
+
+/****************************************************************/
+/* */
+/* GATT CLIENT PART */
+/****************************************************************/
+/**
+* Reset all ancs_context fields to default values
+*/
+ void ANCS_Client_Reset( void )
+{
+ memset(&ancs_context, 0x00, sizeof(ancs_context));
+
+ for (uint8_t i=0; i < MAX_NMB_NOTIFY; i++)
+ {
+ ancs_context.notifyList[i].used = 0x00;
+ //ancs_context.notifyList[i].evID = 0x00;
+ //ancs_context.notifyList[i].evFlag = 0x00;
+ //ancs_context.notifyList[i].catID = 0x00;
+ //ancs_context.notifyList[i].catCount = 0x00;
+ //ancs_context.notifyList[i].notifUID = 0x00;
+ }
+
+ ancs_context.state = ANCS_UNINITIALIZED;
+ ancs_context.connection_handle = 0xFFFF;
+ ancs_context.notifyEntry = INVALID_NOTIFY_ENTRY;
+
+ APP_DBG_MSG("ANCS CLIENT RESET \n\r");
+
+ return;
+}
+/**
+* function used to set task ANCS_App_Update_Service when processed ANCS_Client_Event_Handler
+*/
+static void Ancs_Mgr( void )
+{
+ UTIL_SEQ_SetTask(1 << CFG_TASK_APP_ANCS_DISCOVERY_ID, CFG_SCH_PRIO_0);
+ return;
+}
+
+/**
+* function of ANCS service and characteristics init
+*/
+void ANCS_Client_App_Init( void )
+{
+ /* register ANCS_Client_Event_Handler to BLE Controller initialization*/
+ SVCCTL_RegisterCltHandler(ANCS_Client_Event_Handler);
+
+ UTIL_SEQ_RegTask(1<<CFG_TASK_APP_ANCS_DISCOVERY_ID, UTIL_SEQ_RFU, ANCS_App_Update_Service);
+
+ /* reset ANCS context */
+ ANCS_Client_Reset();
+
+ APP_DBG_MSG("-- ANCS CLIENT INITIALIZED \n\r");
+
+ return;
+}
+
+static void gap_cmd_resp_release(uint32_t flag)
+{
+ UTIL_SEQ_SetEvt(1 << CFG_IDLEEVT_GAP_PROC_COMPLETE);
+ return;
+}
+
+static void gap_cmd_resp_wait(uint32_t timeout)
+{
+ UTIL_SEQ_WaitEvt(1 << CFG_IDLEEVT_GAP_PROC_COMPLETE);
+ return;
+}
+
+static void gatt_cmd_resp_release(uint32_t flag)
+{
+ UTIL_SEQ_SetEvt(1 << CFG_IDLEEVT_GATT_PROC_COMPLETE);
+ return;
+}
+
+static void gatt_cmd_resp_wait(uint32_t timeout)
+{
+ UTIL_SEQ_WaitEvt(1 << CFG_IDLEEVT_GATT_PROC_COMPLETE);
+ return;
+}
+
+/**
+* function of GATT service parse by UUID
+*/
+static void GattParseServicesByUUID(aci_att_find_by_type_value_resp_event_rp0 *pr)
+{
+ APP_DBG_MSG("EVT_BLUE_ATT_FIND_BY_TYPE_VAL_RESP - Connection_Handle=0x%04X,Num_of_Handle_Pair=%d\n\r",
+ pr->Connection_Handle,
+ pr->Num_of_Handle_Pair);
+ for(uint8_t NumPair=0;NumPair<pr->Num_of_Handle_Pair;NumPair++)
+ {
+ APP_DBG_MSG("EVT_BLUE_ATT_FIND_BY_TYPE_VAL_RESP - NumPair=%d Found_Attribute_Handle=0x%04X,Group_End_Handle=0x%04X\n\r",
+ NumPair,
+ pr->Attribute_Group_Handle_Pair[NumPair].Found_Attribute_Handle,
+ pr->Attribute_Group_Handle_Pair[NumPair].Group_End_Handle);
+ }
+ /* complete ancs_context fields */
+ if(ancs_context.state == ANCS_DISCOVER_ANCS_SERVICE)
+ {
+ ancs_context.ANCSServiceStartHandle = pr->Attribute_Group_Handle_Pair[0].Found_Attribute_Handle;
+ ancs_context.ANCSServiceEndHandle = pr->Attribute_Group_Handle_Pair[0].Group_End_Handle;
+ APP_DBG_MSG("EVT_BLUE_ATT_FIND_BY_TYPE_VAL_RESP - Found ANCSServiceStartHandle=0x%04X,ANCSServiceEndHandle=0x%04X\n\r",
+ ancs_context.ANCSServiceStartHandle,
+ ancs_context.ANCSServiceEndHandle);
+ }
+}
+
+
+/**
+* function of GATT service parse
+*/
+static void GattParseServices(aci_att_read_by_group_type_resp_event_rp0 *pr)
+{
+ uint16_t uuid,ServiceStartHandle,ServiceEndHandle;
+ uint8_t uuid_offset,uuid_size,uuid_short_offset;
+ uint8_t i,idx,numServ;
+
+ APP_DBG_MSG("EVT_BLUE_ATT_READ_BY_GROUP_TYPE_RESP - Connection_Handle=0x%04X,Attribute_Data_Length=%d,Data_Length=%d !\n",
+ pr->Connection_Handle,
+ pr->Attribute_Data_Length,
+ pr->Data_Length);
+
+ /* check connection handle related to response before processing */
+ if (ancs_context.connection_handle == pr->Connection_Handle)
+ {
+ /* Number of attribute value tuples */
+ numServ = (pr->Data_Length) / pr->Attribute_Data_Length;
+
+ /* event data in Attribute_Data_List contains:
+ * 2 bytes for start handle
+ * 2 bytes for end handle
+ * 2 or 16 bytes data for UUID
+ */
+ if (pr->Attribute_Data_Length == 20) /* we are interested in the UUID is 128 bit.*/
+ {
+ idx = 16; /*UUID index of 2 bytes read part in Attribute_Data_List */
+ uuid_offset = 4; /*UUID offset in bytes in Attribute_Data_List */
+ uuid_size = 16; /*UUID size in bytes */
+ uuid_short_offset = 12; /*UUID offset of 2 bytes read part in UUID field*/
+ }
+ if (pr->Attribute_Data_Length == 6) /* we are interested in the UUID is 16 bit.*/
+ {
+ idx = 4;
+ uuid_offset = 4;
+ uuid_size = 2;
+ uuid_short_offset = 0;
+ }
+ UNUSED(idx);
+ UNUSED(uuid_size);
+
+ /* Loop on number of attribute value tuples */
+ for (i = 0; i < numServ; i++)
+ {
+ ServiceStartHandle = UNPACK_2_BYTE_PARAMETER(&pr->Attribute_Data_List[uuid_offset - 4]);
+ ServiceEndHandle = UNPACK_2_BYTE_PARAMETER(&pr->Attribute_Data_List[uuid_offset - 2]);
+ uuid = UNPACK_2_BYTE_PARAMETER(&pr->Attribute_Data_List[uuid_offset + uuid_short_offset]);
+ APP_DBG_MSG("numServ=%d/%d,short UUID=0x%04X ServiceHandle [0x%04X - 0x%04X] \n\r",
+ i, numServ, uuid, ServiceStartHandle,ServiceEndHandle);
+
+ /* complete ancs_context fields */
+ if ( (ancs_context.ALLServiceStartHandle == 0x0000) || (ServiceStartHandle < ancs_context.ALLServiceStartHandle) )
+ {
+ ancs_context.ALLServiceStartHandle = ServiceStartHandle;
+ }
+ if ( (ancs_context.ALLServiceEndHandle== 0x0000) || (ServiceEndHandle > ancs_context.ALLServiceEndHandle) )
+ {
+ ancs_context.ALLServiceEndHandle = ServiceEndHandle;
+ }
+
+
+ if(uuid == GAP_SERVICE_UUID) /* 0x1800 */ {
+
+ ancs_context.GAPServiceStartHandle = ServiceStartHandle;
+ ancs_context.GAPServiceEndHandle = ServiceEndHandle;
+
+ APP_DBG_MSG("GAP_SERVICE_UUID=0x%04X found [%04X %04X]!\n",uuid,ServiceStartHandle,ServiceEndHandle);
+ } else if (uuid == GENERIC_ATTRIBUTE_SERVICE_UUID) /* 0x1801 */ {
+
+ ancs_context.GATTServiceStartHandle = ServiceStartHandle;
+ ancs_context.GATTServiceEndHandle = ServiceEndHandle;
+
+ APP_DBG_MSG("GENERIC_ATTRIBUTE_SERVICE_UUID=0x%04X found [%04X %04X]!\n",uuid,ServiceStartHandle,ServiceEndHandle);
+ /*******************************************************************************************************************/
+ } else if (uuid == IMMEDIATE_ALERT_SERVICE_UUID) /* 0x1802 */ {
+ APP_DBG_MSG("AMS_SERVICE_UUID=0x%04X found [%04X %04X]!\n",uuid,ServiceStartHandle,ServiceEndHandle);
+ } else if (uuid == LINK_LOSS_SERVICE_UUID) /* 0x1803 */ {
+ APP_DBG_MSG("LINK_LOSS_SERVICE_UUID=0x%04X found [%04X %04X]!\n",uuid,ServiceStartHandle,ServiceEndHandle);
+ } else if (uuid == TX_POWER_SERVICE_UUID) /* 0x1804 */ {
+ APP_DBG_MSG("TX_POWER_SERVICE_UUID=0x%04X found [%04X %04X]!\n",uuid,ServiceStartHandle,ServiceEndHandle);
+ } else if (uuid == CURRENT_TIME_SERVICE_UUID) /* 0x1805 */ {
+ APP_DBG_MSG("CURRENT_TIME_SERVICE_UUID=0x%04X found [%04X %04X]!\n",uuid,ServiceStartHandle,ServiceEndHandle);
+ } else if (uuid == REFERENCE_UPDATE_TIME_SERVICE_UUID) /* 0x1806 */ {
+ APP_DBG_MSG("REFERENCE_UPDATE_TIME_SERVICE_UUID=0x%04X found [%04X %04X]!\n",uuid,ServiceStartHandle,ServiceEndHandle);
+ } else if (uuid == NEXT_DST_CHANGE_SERVICE_UUID) /* 0x1807 */ {
+ APP_DBG_MSG("NEXT_DST_CHANGE_SERVICE_UUID=0x%04X found [%04X %04X]!\n",uuid,ServiceStartHandle,ServiceEndHandle);
+ } else if (uuid == GLUCOSE_SERVICE_UUID) /* 0x1808 */ {
+ APP_DBG_MSG("GLUCOSE_SERVICE_UUID=0x%04X found [%04X %04X]!\n",uuid,ServiceStartHandle,ServiceEndHandle);
+ } else if (uuid == HEALTH_THERMOMETER_SERVICE_UUID) /* 0x1809 */ {
+ APP_DBG_MSG("HEALTH_THERMOMETER_SERVICE_UUID=0x%04X found [%04X %04X]!\n",uuid,ServiceStartHandle,ServiceEndHandle);
+ } else if (uuid == DEVICE_INFORMATION_SERVICE_UUID) /* 0x180A */ {
+ APP_DBG_MSG("DEVICE_INFORMATION_SERVICE_UUID=0x%04X found [%04X %04X]!\n",uuid,ServiceStartHandle,ServiceEndHandle);
+ } else if (uuid == 0x180B) /* 0x180B */ {
+ APP_DBG_MSG("Unkown UUID=0x%04X found [%04X %04X]!\n",uuid,ServiceStartHandle,ServiceEndHandle);
+ } else if (uuid == 0x180C) /* 0x180C */ {
+ APP_DBG_MSG("Unkown UUID=0x%04X found [%04X %04X]!\n",uuid,ServiceStartHandle,ServiceEndHandle);
+ } else if (uuid == HEART_RATE_SERVICE_UUID) /* 0x180D */ {
+ APP_DBG_MSG("AMS_SERVICE_UUID=0x%04X found [%04X %04X]!\n",uuid,ServiceStartHandle,ServiceEndHandle);
+ } else if (uuid == PHONE_ALERT_SERVICE_UUID) /* 0x180E */ {
+ APP_DBG_MSG("PHONE_ALERT_SERVICE_UUID=0x%04X found [%04X %04X]!\n",uuid,ServiceStartHandle,ServiceEndHandle);
+ } else if (uuid == BATTERY_SERVICE_UUID) /* 0x180F */ {
+ APP_DBG_MSG("BATTERY_SERVICE_UUID=0x%04X found [%04X %04X]!\n",uuid,ServiceStartHandle,ServiceEndHandle);
+ /*******************************************************************************************************************/
+ } else if (uuid == ANCS_SERVICE_UUID) {
+
+ ancs_context.ANCSServiceStartHandle = ServiceStartHandle;
+ ancs_context.ANCSServiceEndHandle = ServiceEndHandle;
+
+ APP_DBG_MSG("ANCS_SERVICE_UUID=0x%04X found [%04X %04X]!\n",uuid,ServiceStartHandle,ServiceEndHandle);
+ } else if (uuid == AMS_SERVICE_UUID) {
+ APP_DBG_MSG("AMS_SERVICE_UUID=0x%04X found [%04X %04X]!\n",uuid,ServiceStartHandle,ServiceEndHandle);
+ } else {
+ APP_DBG_MSG("invalid UUID=0x%04X found [%04X %04X]!\n",uuid,ServiceStartHandle,ServiceEndHandle);
+ }
+
+ uuid_offset += pr->Attribute_Data_Length;
+ }//numServ
+ }
+ else
+ {
+ APP_DBG_MSG("EVT_BLUE_ATT_READ_BY_GROUP_TYPE_RESP, failed no free index in connection table !\n\r");
+ }
+}
+
+/**
+* function of GATT characteristics parse
+*/
+static void GattParseChars(aci_att_read_by_type_resp_event_rp0 *pr)
+{
+ uint16_t uuid,CharStartHandle,CharValueHandle;
+ uint8_t uuid_offset,uuid_size,uuid_short_offset;
+ uint8_t i,idx,numHdleValuePair;
+ uint8_t CharProperties;
+
+ APP_DBG_MSG("EVT_BLUE_ATT_READ_BY_TYPE_RESP - Connection_Handle=0x%x,Handle_Value_Pair_Length=%d,Data_Length=%d\n\r",
+ pr->Connection_Handle,
+ pr->Handle_Value_Pair_Length,
+ pr->Data_Length);
+
+ if (ancs_context.connection_handle == pr->Connection_Handle)
+ {
+ /* event data in Attribute_Data_List contains:
+ * 2 bytes for start handle
+ * 1 byte char properties
+ * 2 bytes handle
+ * 2 or 16 bytes data for UUID
+ */
+
+ /* Number of attribute value tuples */
+ numHdleValuePair = pr->Data_Length / pr->Handle_Value_Pair_Length;
+
+ if (pr->Handle_Value_Pair_Length == 21) /* we are interested in 128 bit UUIDs */
+ {
+ idx = 17; /*UUID index of 2 bytes read part in Attribute_Data_List */
+ uuid_offset = 5; /*UUID offset in bytes in Attribute_Data_List */
+ uuid_size = 16; /*UUID size in bytes */
+ uuid_short_offset = 12; /*UUID offset of 2 bytes read part in UUID field*/
+ }
+ if (pr->Handle_Value_Pair_Length == 7) /* we are interested in 16 bit UUIDs */
+ {
+ idx = 5;
+ uuid_offset = 5;
+ uuid_size = 2;
+ uuid_short_offset = 0;
+ }
+ UNUSED(idx);
+ UNUSED(uuid_size);
+
+ pr->Data_Length -= 1;
+
+ /* Loop on number of attribute value tuples */
+ for (i = 0; i < numHdleValuePair; i++)
+ {
+ CharStartHandle = UNPACK_2_BYTE_PARAMETER(&pr->Handle_Value_Pair_Data[uuid_offset-5]);
+ CharProperties = pr->Handle_Value_Pair_Data[uuid_offset-3];
+ CharValueHandle = UNPACK_2_BYTE_PARAMETER(&pr->Handle_Value_Pair_Data[uuid_offset-2]);
+ uuid = UNPACK_2_BYTE_PARAMETER(&pr->Handle_Value_Pair_Data[uuid_offset+uuid_short_offset]);
+
+ if ( (uuid != 0x0) && (CharProperties != 0x0) && (CharStartHandle != 0x0) && (CharValueHandle !=0) )
+ {
+ APP_DBG_MSG("-- GATT : numHdleValuePair=%d,short UUID=0x%04X FOUND CharProperties=0x%04X CharHandle [0x%04X - 0x%04X]\n",
+ i, uuid, CharProperties, CharStartHandle,CharValueHandle);
+
+ /* complete ancs_context fields */
+ if (uuid == DEVICE_NAME_UUID) /* 0x2A00 */ {
+ APP_DBG_MSG("GAP DEVICE_NAME_UUID=0x%04X found [%04X %04X]!\n",uuid,CharStartHandle,CharValueHandle);
+ } else if (uuid == APPEARANCE_UUID) /* 0x2A01 */ {
+ APP_DBG_MSG("GAP APPEARANCE_UUID=0x%04X found [%04X %04X]!\n",uuid,CharStartHandle,CharValueHandle);
+ } else if (uuid == PERIPHERAL_PRIVACY_FLAG_UUID) /* 0x2A02 */ {
+ APP_DBG_MSG("GAP PERIPHERAL_PRIVACY_FLAG_UUID=0x%04X found [%04X %04X]!\n",uuid,CharStartHandle,CharValueHandle);
+ } else if (uuid == RECONNECTION_ADDR_UUID) /* 0x2A03 */ {
+ APP_DBG_MSG("GAP APPEARANCE_UUID=0x%04X found [%04X %04X]!\n",uuid,CharStartHandle,CharValueHandle);
+ } else if (uuid == PERIPHERAL_PREFERRED_CONN_PARAMS_UUID) /* 0x2A04 */ {
+ APP_DBG_MSG("GAP APPEARANCE_UUID=0x%04X found [%04X %04X]!\n",uuid,CharStartHandle,CharValueHandle);
+ /*******************************************************************************************************************/
+ }else if (uuid == SERVICE_CHANGED_CHARACTERISTIC_UUID) /* 0x2A05 */ {
+
+ ancs_context.ServiceChangedCharStartHdle = CharStartHandle;
+ ancs_context.ServiceChangedCharValueHdle = CharValueHandle;
+ APP_DBG_MSG("GATT SERVICE_CHANGED_CHARACTERISTIC_UUID=0x%04X found [%04X %04X]!\n",uuid,CharStartHandle,CharValueHandle);
+ /*******************************************************************************************************************/
+ } else if (uuid == BATTERY_LEVEL_CHAR_UUID) /* 0x2A19 */ {
+ APP_DBG_MSG("BATTERY_LEVEL_CHAR_UUID=0x%04X found [%04X %04X]!\n",uuid,CharStartHandle,CharValueHandle);
+ /*******************************************************************************************************************/
+ } else if (uuid == CURRENT_TIME_CHAR_UUID) /* 0x2A2B */ {
+ APP_DBG_MSG("CURRENT_TIME_CHAR_UUID=0x%04X found [%04X %04X]!\n",uuid,CharStartHandle,CharValueHandle);
+ } else if (uuid == LOCAL_TIME_INFORMATION_CHAR_UUID) /* 0x2A0F */ {
+ APP_DBG_MSG("LOCAL_TIME_INFORMATION_CHAR_UUID=0x%04X found [%04X %04X]!\n",uuid,CharStartHandle,CharValueHandle);
+ /*******************************************************************************************************************/
+ } else if (uuid == MANUFACTURER_NAME_UUID) /* 0x2A29 */ {
+ APP_DBG_MSG("DeviceInformationService MANUFACTURER_NAME_UUID=0x%04X found [%04X %04X]!\n",uuid,CharStartHandle,CharValueHandle);
+ } else if (uuid == MODEL_NUMBER_UUID) /* 0x2A24 */ {
+ APP_DBG_MSG("DeviceInformationService MODEL_NUMBER_UUID=0x%04X found [%04X %04X]!\n",uuid,CharStartHandle,CharValueHandle);
+ /*******************************************************************************************************************/
+ } else if (uuid == ANCS_NOTIFICATION_SOURCE_CHAR_UUID) {
+
+ ancs_context.ANCSNotificationSourceCharStartHdle = CharStartHandle;
+ ancs_context.ANCSNotificationSourceCharValueHdle = CharValueHandle;
+
+ APP_DBG_MSG("ANCS_NOTIFICATION_SOURCE_CHAR_UUID=0x%04X found [%04X %04X]!\n",uuid,CharStartHandle,CharValueHandle);
+ } else if (uuid == ANCS_CONTROL_POINT_CHAR_UUID) {
+
+ ancs_context.ANCSControlPointCharStartHdle = CharStartHandle;
+ ancs_context.ANCSControlPointCharValueHdle = CharValueHandle;
+
+ APP_DBG_MSG("ANCS_CONTROL_POINT_CHAR_UUID=0x%04X found [%04X %04X]!\n",uuid,CharStartHandle,CharValueHandle);
+ } else if (uuid == ANCS_DATA_SOURCE_CHAR_UUID) {
+
+ ancs_context.ANCSDataSourceCharStartHdle = CharStartHandle;
+ ancs_context.ANCSDataSourceCharValueHdle = CharValueHandle;
+
+ APP_DBG_MSG("ANCS_DATA_SOURCE_CHAR_UUID=0x%04X found [%04X %04X]!\n",uuid,CharStartHandle,CharValueHandle);
+
+ } else if (uuid == CENTRAL_ADDRESS_RESOLUTION_UUID) {
+
+ ancs_context.GAPCentralAddressResolutionCharStartHdle = CharStartHandle;
+ ancs_context.GAPCentralAddressResolutionCharValueHdle = CharValueHandle;
+
+ APP_DBG_MSG("CENTRAL_ADDRESS_RESOLUTION_UUID=0x%04X found [%04X %04X]!\n",uuid,CharStartHandle,CharValueHandle);
+ } else {
+ APP_DBG_MSG("Unknown_char UUID=0x%04X found [%04X %04X]!\n",uuid,CharStartHandle,CharValueHandle);
+ }
+
+ }
+ uuid_offset += pr->Handle_Value_Pair_Length;
+ }// numHdleValuePair
+ }
+ else
+ APP_DBG_MSG("EVT_BLUE_ATT_READ_BY_TYPE_RESP, failed handle not found in connection table !\n\r");
+}
+/**
+* function of GATT descriptor parse
+*/
+static void GattParseDescs(aci_att_find_info_resp_event_rp0 *pr)
+{
+ uint16_t uuid,handle;
+ uint8_t uuid_offset,uuid_size,uuid_short_offset;
+ uint8_t i,numDesc,handle_uuid_pair_size;
+
+ APP_DBG_MSG("EVT_BLUE_ATT_FIND_INFORMATION_RESP - Connection_Handle=0x%x,Format=%d,Event_Data_Length=%d\n\r",
+ pr->Connection_Handle,
+ pr->Format,
+ pr->Event_Data_Length);
+
+ if (ancs_context.connection_handle == pr->Connection_Handle)
+ {
+ /* event data in Attribute_Data_List contains:
+ * 2 bytes handle
+ * 2 or 16 bytes data for UUID
+ */
+ if (pr->Format == UUID_TYPE_16)
+ {
+ uuid_size = 2;
+ uuid_offset = 2;
+ uuid_short_offset = 0;
+ handle_uuid_pair_size = 4;
+ }
+ if (pr->Format == UUID_TYPE_128)
+ {
+ uuid_size = 16;
+ uuid_offset = 2;
+ uuid_short_offset = 12;
+ handle_uuid_pair_size = 18;
+ }
+ UNUSED(uuid_size);
+
+ /* Number of handle uuid pairs */
+ numDesc = (pr->Event_Data_Length) / handle_uuid_pair_size;
+
+ for (i = 0; i < numDesc; i++)
+ {
+ handle = UNPACK_2_BYTE_PARAMETER(&pr->Handle_UUID_Pair[uuid_offset-2]);
+ uuid = UNPACK_2_BYTE_PARAMETER(&pr->Handle_UUID_Pair[uuid_offset+uuid_short_offset]);
+
+ /* 1. primary serice handle + primary serice UUID */
+ if(uuid == PRIMARY_SERVICE_UUID)
+ {
+ APP_DBG_MSG("PRIMARY_SERVICE_UUID=0x%04X handle=0x%04X\n\r",uuid,handle);
+ }/* 1. primary serice handle + primary serice UUID */
+
+ /* 2. char handle + char UUID */
+ else if(uuid == CHARACTERISTIC_UUID)
+ {
+ /* reset UUID & handle */
+ gCharUUID = 0;
+ gCharStartHandle = 0;
+ gCharValueHandle = 0;
+ gCharDescriptorHandle = 0;
+
+ gCharStartHandle = handle;
+ APP_DBG_MSG("reset CHARACTERISTIC_UUID=0x%04X CharStartHandle=0x%04X\n\r",uuid,handle);
+ }/* 2. char handle + char UUID */
+
+ /* 3. char desc handle + char desc UUID */
+ else if( (uuid == CHAR_EXTENDED_PROPERTIES_DESCRIPTOR_UUID) /* 0x2900 */
+ || (uuid == CLIENT_CHAR_CONFIG_DESCRIPTOR_UUID) )/* 0x2902 */
+ {
+ gCharDescriptorHandle = handle;
+ if (gCharValueHandle == ancs_context.ServiceChangedCharValueHdle){
+
+ ancs_context.ServiceChangedCharDescHdle = handle;
+ APP_DBG_MSG("uuid=0x%04X handle=0x%04X-0x%04X-0x%04X\n\r\n\r", uuid,gCharStartHandle,gCharValueHandle,handle);
+ } else if (gCharValueHandle == ancs_context.ANCSNotificationSourceCharValueHdle){
+
+ ancs_context.ANCSNotificationSourceCharDescHdle = handle;
+ APP_DBG_MSG("uuid=0x%04X handle=0x%04X-0x%04X-0x%04X\n\r\n\r", uuid,gCharStartHandle,gCharValueHandle,handle);
+ } else if (gCharValueHandle == ancs_context.ANCSDataSourceCharValueHdle){
+
+ ancs_context.ANCSDataSourceCharDescHdle = handle;
+ APP_DBG_MSG("uuid=0x%04X handle=0x%04X-0x%04X-0x%04X\n\r\n\r", uuid,gCharStartHandle,gCharValueHandle,handle);
+ } else if (gCharValueHandle == ancs_context.ANCSControlPointCharValueHdle){
+
+ ancs_context.ANCSControlPointCharDescHdle = handle;
+ APP_DBG_MSG("uuid=0x%04X handle=0x%04X-0x%04X-0x%04X\n\r\n\r", uuid,gCharStartHandle,gCharValueHandle,handle);
+ } else {
+ APP_DBG_MSG(" unkown_char_desc UUID=0x%04X handle=0x%04X-0x%04X-0x%04X \n\r",uuid,gCharStartHandle,gCharValueHandle,handle);
+ }
+ }// 3. char desc handle + char desc UUID
+
+ /* 4. char value handle + char UUID */
+ else
+ {
+ gCharUUID = uuid;
+ gCharValueHandle = handle;
+ if (uuid == DEVICE_NAME_UUID) /* 0x2A00 */ {
+ APP_DBG_MSG("GAP DEVICE_NAME_UUID=0x%04X found [%04X]!\n",uuid,handle);
+ } else if (uuid == APPEARANCE_UUID) /* 0x2A01 */ {
+ APP_DBG_MSG("GAP APPEARANCE_UUID=0x%04X found [%04X]!\n",uuid,handle);
+ } else if (uuid == PERIPHERAL_PRIVACY_FLAG_UUID) /* 0x2A02 */ {
+ APP_DBG_MSG("GAP PERIPHERAL_PRIVACY_FLAG_UUID=0x%04X found [%04X]!\n",uuid,handle);
+ } else if (uuid == RECONNECTION_ADDR_UUID) /* 0x2A03 */ {
+ APP_DBG_MSG("GAP APPEARANCE_UUID=0x%04X found [%04X]!\n",uuid,handle);
+ } else if (uuid == PERIPHERAL_PREFERRED_CONN_PARAMS_UUID) /* 0x2A04 */ {
+ APP_DBG_MSG("GAP APPEARANCE_UUID=0x%04X found [%04X]!\n",uuid,handle);
+ /*******************************************************************************************************************/
+ } else if (uuid == SERVICE_CHANGED_CHARACTERISTIC_UUID) /* 0x2A05 */ {
+ APP_DBG_MSG(" SERVICE_CHANGED_CHARACTERISTIC_UUID=0x%04X CharValueHandle [%04X]\n",uuid,handle);
+ /*******************************************************************************************************************/
+ } else if (uuid == BATTERY_LEVEL_CHAR_UUID) /* 0x2A19 */ {
+ APP_DBG_MSG("BATTERY_LEVEL_CHAR_UUID=0x%04X found [%04X]!\n",uuid,handle);
+ /*******************************************************************************************************************/
+ } else if (uuid == CURRENT_TIME_CHAR_UUID) /* 0x2A2B */ {
+ APP_DBG_MSG("CURRENT_TIME_CHAR_UUID=0x%04X found [%04X]!\n",uuid,handle);
+ } else if (uuid == LOCAL_TIME_INFORMATION_CHAR_UUID) /* 0x2A0F */ {
+ APP_DBG_MSG("LOCAL_TIME_INFORMATION_CHAR_UUID=0x%04X found [%04X]!\n",uuid,handle);
+ /*******************************************************************************************************************/
+ } else if (uuid == MANUFACTURER_NAME_UUID) /* 0x2A29 */ {
+ APP_DBG_MSG("DeviceInformationService MANUFACTURER_NAME_UUID=0x%04X found [%04X]!\n",uuid,handle);
+ } else if (uuid == MODEL_NUMBER_UUID) /* 0x2A24 */ {
+ APP_DBG_MSG("DeviceInformationService MODEL_NUMBER_UUID=0x%04X found [%04X]!\n",uuid,handle);
+ /*******************************************************************************************************************/
+ } else if (uuid == ANCS_NOTIFICATION_SOURCE_CHAR_UUID) {
+ APP_DBG_MSG(" ANCS_NOTIFICATION_SOURCE_CHAR_UUID=0x%04X CharValueHandle [%04X]!\n",uuid,handle);
+ } else if (uuid == ANCS_CONTROL_POINT_CHAR_UUID) {
+ APP_DBG_MSG(" ANCS_CONTROL_POINT_CHAR_UUID=0x%04X CharValueHandle [%04X]!\n",uuid,handle);
+ } else if (uuid == ANCS_DATA_SOURCE_CHAR_UUID) {
+ APP_DBG_MSG(" ANCS_DATA_SOURCE_CHAR_UUID=0x%04X CharValueHandle [%04X]!\n",uuid,handle);
+ } else if (uuid == CENTRAL_ADDRESS_RESOLUTION_UUID) {
+ APP_DBG_MSG(" CENTRAL_ADDRESS_RESOLUTION_UUID=0x%04X CharValueHandle [%04X]!\n",uuid,handle);
+ } else {
+ APP_DBG_MSG(" invalid char value UUID=0x%04X CharValueHandle [%04X]!\n",uuid,handle);
+ }
+ }// 4. char value handle + char UUID
+
+ uuid_offset += handle_uuid_pair_size;
+ }
+ }
+ else
+ APP_DBG_MSG("EVT_BLUE_ATT_FIND_INFORMATION_RESP, failed handle not found in connection table !\n\r");
+}
+
+static void GattParseNotification(aci_gatt_notification_event_rp0 *pr)
+{
+ APP_DBG_MSG("EVT_BLUE_GATT_NOTIFICATION - Connection_Handle=0x%x,Attribute_Handle=0x%04X,Attribute_Value_Length=%d\n\r",
+ pr->Connection_Handle,
+ pr->Attribute_Handle,
+ pr->Attribute_Value_Length);
+
+ if (ancs_context.connection_handle == pr->Connection_Handle)
+ {
+ // 1. Incomming Nofification
+ if (pr->Attribute_Handle == ancs_context.ANCSNotificationSourceCharValueHdle)
+ {
+ APP_DBG_MSG("1. Incomming Nofification received BASIC information : \n\r");
+ EventID evID = (EventID)pr->Attribute_Value[0];
+ EventFlags evFlag = (EventFlags)pr->Attribute_Value[1];
+ CategoryID catID = (CategoryID)pr->Attribute_Value[2];
+ uint8_t catCount = pr->Attribute_Value[3];
+ uint32_t notifUID = (uint32_t)(*((uint32_t *)&pr->Attribute_Value[4]));
+ ANCS_Notification_Source_Received_event(evID, evFlag, catID, catCount, notifUID);
+
+ // 2. Get More Detail Infomations
+ if( (evID == EventIDNotificationAdded) )
+ {
+ if((evFlag & EventFlagSilent) != EventFlagSilent)
+ {
+ ANCS_Notification_Check(evFlag);
+ Ancs_Mgr();
+ }
+ }
+ }// ANCSNotificationSourceCharValueHdle
+
+ // 3. Parse Detail Infomations, Perform Notification Action or Get APP Attributes
+ if (pr->Attribute_Handle == ancs_context.ANCSDataSourceCharValueHdle)
+ {
+ CommandID cmdID = (CommandID)pr->Attribute_Value[0];
+ uint32_t notifUID = (uint32_t)0x00000000;
+
+ uint16_t AttributeLength;
+ uint8_t *AttributeList;
+
+ char AppIdentifier[128]={0};
+ uint16_t AppIdentifierLength;
+
+ /***********************************************************************************/
+ if (cmdID == CommandIDGetNotificationAttributes)
+ {
+ APP_DBG_MSG("3.1 Parse Detail Infomation of Notification Attribute, CommandIDGetNotificationAttributes Response: \n\r");
+ notifUID = (uint32_t)(*((uint32_t *)&pr->Attribute_Value[1]));
+ AttributeLength = pr->Attribute_Value_Length - (1+4);
+ AttributeList = (uint8_t *)&pr->Attribute_Value[1+4];
+
+ // 3.1 Parse Detail Infomation of Notification Attribute
+ ANCS_Parse_GetNotificationAttr_Resp(cmdID,AttributeLength,AttributeList);
+ }
+ UNUSED(notifUID);
+
+ if (cmdID == CommandIDGetAppAttributes)
+ {
+ APP_DBG_MSG("3.3 Parse Detail Infomation of APP Attribute, CommandIDGetAppAttributes Response: \n\r");
+ strcpy(AppIdentifier,(char *)&pr->Attribute_Value[1]);
+ AppIdentifierLength = strlen((char *)&pr->Attribute_Value[1]);
+ AttributeLength = pr->Attribute_Value_Length - (1+AppIdentifierLength+1);
+ AttributeList = (uint8_t *)&pr->Attribute_Value[1+AppIdentifierLength+1];
+
+ // 3.3 Parse Detail Infomation of App Attribute
+ ANCS_Parse_GetAppAttr_Resp(cmdID,AttributeLength,AttributeList);
+ }
+
+ Ancs_Mgr();
+ /***********************************************************************************/
+ }/* ANCSDataSourceCharValueHdle */
+ }
+ else
+ APP_DBG_MSG("EVT_BLUE_GATT_NOTIFICATION, failed handle not found in connection table !\n\r");
+}
+
+/**
+ * @brief ANCS Event handler
+ * @param Event: Address of the buffer holding the Event
+ * @retval Ack: Return whether the Event has been managed or not
+ */
+static SVCCTL_EvtAckStatus_t ANCS_Client_Event_Handler( void *Event )
+{
+ SVCCTL_EvtAckStatus_t return_value;
+ hci_event_pckt * event_pckt;
+ evt_blue_aci * blue_evt;
+ Connection_Context_t Notification;
+
+ return_value = SVCCTL_EvtAckFlowEnable;
+ event_pckt = (hci_event_pckt *) (((hci_uart_pckt*) Event)->data);
+
+ switch (event_pckt->evt)
+ {
+ case EVT_VENDOR:
+ {
+ blue_evt = (evt_blue_aci*) event_pckt->data;
+ switch (blue_evt->ecode)
+ {
+ case EVT_BLUE_ATT_READ_BY_GROUP_TYPE_RESP:
+ {
+ aci_att_read_by_group_type_resp_event_rp0 *pr = (void*) blue_evt->data;
+
+ APP_DBG_MSG(" EVT_BLUE_ATT_READ_BY_GROUP_TYPE_RESP\n");
+ GattParseServices((aci_att_read_by_group_type_resp_event_rp0 *)pr);
+ }
+ break;
+ case EVT_BLUE_ATT_READ_BY_TYPE_RESP:
+ {
+ aci_att_read_by_type_resp_event_rp0 *pr = (void*) blue_evt->data;
+ APP_DBG_MSG(" EVT_BLUE_ATT_READ_BY_TYPE_RESP\n");
+ GattParseChars((aci_att_read_by_type_resp_event_rp0 *)pr);
+ }
+ break;
+ case EVT_BLUE_ATT_FIND_INFORMATION_RESP:
+ {
+ aci_att_find_info_resp_event_rp0 *pr = (void*) blue_evt->data;
+ APP_DBG_MSG(" EVT_BLUE_ATT_FIND_INFORMATION_RESP\n");
+ GattParseDescs((aci_att_find_info_resp_event_rp0 *)pr);
+ }
+ break; /*EVT_BLUE_ATT_FIND_INFORMATION_RESP*/
+
+ case EVT_BLUE_GATT_DISC_READ_CHAR_BY_UUID_RESP:
+ {
+ APP_DBG_MSG(" EVT_BLUE_GATT_DISC_READ_CHAR_BY_UUID_RESP\n");
+ }
+ break;
+
+ case EVT_BLUE_ATT_FIND_BY_TYPE_VAL_RESP:
+ {
+ aci_att_find_by_type_value_resp_event_rp0 *pr = (void*) blue_evt->data;
+ APP_DBG_MSG(" EVT_BLUE_ATT_FIND_BY_TYPE_VAL_RESP\n");
+ GattParseServicesByUUID((aci_att_find_by_type_value_resp_event_rp0 *)pr);
+ }
+ break;
+
+ case EVT_BLUE_GATT_NOTIFICATION:
+ {
+ aci_gatt_notification_event_rp0 *pr = (void*) blue_evt->data;
+ GattParseNotification((aci_gatt_notification_event_rp0 *)pr);
+ }
+ break;/* end EVT_BLUE_GATT_NOTIFICATION */
+
+ case EVT_BLUE_GATT_ATTRIBUTE_MODIFIED:
+ {
+ aci_gatt_attribute_modified_event_rp0 *attribute_modified = (aci_gatt_attribute_modified_event_rp0*) blue_evt->data;
+ APP_DBG_MSG("EVT_BLUE_GATT_ATTRIBUTE_MODIFIED Attr_Handle=0x%04X Offset=0x%04X Attr_Data_Length=0x%04X \n\r",
+ attribute_modified->Attr_Handle,
+ attribute_modified->Offset,
+ attribute_modified->Attr_Data_Length);
+ }/* end EVT_BLUE_GATT_ATTRIBUTE_MODIFIED */
+ break;
+
+ case EVT_BLUE_ATT_EXCHANGE_MTU_RESP:
+ {
+ aci_att_exchange_mtu_resp_event_rp0 * exchange_mtu_resp;
+ exchange_mtu_resp = (aci_att_exchange_mtu_resp_event_rp0 *)blue_evt->data;
+ APP_DBG_MSG("EVT_BLUE_ATT_EXCHANGE_MTU_RESP Connection_Handle=0x%04X Server_RX_MTU = %d ==> ANCS_MTU_EXCHANGE_COMPLETE \n",
+ exchange_mtu_resp->Connection_Handle,
+ exchange_mtu_resp->Server_RX_MTU );
+
+ Notification.Evt_Opcode = ANCS_MTU_EXCHANGE_COMPLETE;
+ Notification.connection_handle = exchange_mtu_resp->Connection_Handle;
+ ANCS_App_Notification(&Notification);
+ }
+ break;
+
+ case EVT_BLUE_GATT_PROCEDURE_COMPLETE:
+ {
+ aci_gatt_proc_complete_event_rp0 *pr = (void*) blue_evt->data;
+ if(pr->Error_Code != ERR_CMD_SUCCESS)
+ {
+ APP_DBG_MSG("EVT_BLUE_GATT_PROCEDURE_COMPLETE - Connection_Handle=0x%04x,Error_Code=0x%02X (0x41: Failed)\n\r", pr->Connection_Handle,pr->Error_Code);
+ }
+
+ if (ancs_context.connection_handle == pr->Connection_Handle)
+ {
+ gatt_cmd_resp_release(0);
+ }
+ else
+ APP_DBG_MSG("EVT_BLUE_GATT_PROCEDURE_COMPLETE, failed handle not found in connection table !\n\r");
+ }/*EVT_BLUE_GATT_PROCEDURE_COMPLETE*/
+ break;
+ case EVT_BLUE_GATT_ERROR_RESP:
+ {
+ aci_gatt_error_resp_event_rp0 *error_resp= (void*) blue_evt->data;
+ APP_DBG_MSG("EVT_BLUE_GATT_ERROR_RESP Connection_Handle=0x%04X Req_Opcode=0x%02X Attribute_Handle=0x%04X Error_Code=0x%02X (0x05: Insufficient authentication,0x0A: Attribute not found)\n",
+ error_resp->Connection_Handle,error_resp->Req_Opcode,error_resp->Attribute_Handle,error_resp->Error_Code);
+ }/*EVT_BLUE_GATT_ERROR_RESP*/
+ break;
+
+ default:
+ APP_DBG_MSG("invalid ecode 0x%04X\n",blue_evt->ecode);
+ return_value = SVCCTL_EvtNotAck;
+ break;
+ }
+ }
+ break; /* EVT_VENDOR */
+
+ default:
+ return_value = SVCCTL_EvtNotAck;
+ break;
+ }
+
+ return (return_value);
+}/* end BLE_CTRL_Event_Acknowledged_Status_t */
+
+void ANCS_App_KeyButton1Action(void)
+{
+ APP_DBG_MSG("\n\r ** Term CONNECTION ** \n\r");
+ aci_gap_terminate(ancs_context.connection_handle, 0x13);
+}
+void ANCS_App_KeyButton2Action(void)
+{
+ APP_DBG_MSG("Review the PreExisted Notification \n\r");
+ Connection_Context_t Notification;
+ Notification.Evt_Opcode = ANCS_CHECK_NOTIFICATION;
+ Notification.connection_handle = ancs_context.connection_handle;
+ ANCS_App_Notification(&Notification);
+}
+void ANCS_App_KeyButton3Action(void)
+{
+ APP_DBG_MSG(" aci_gap_clear_security_db & aci_gap_remove_bonded_device & aci_gap_terminate \n\r");
+ aci_gap_remove_bonded_device(ancs_context.Peer_Address_Type,ancs_context.Peer_Address);
+ aci_gap_clear_security_db();
+ aci_gap_terminate(ancs_context.connection_handle, 0x13);
+}
+
+#if (GET_ACTION_ID_FROM_UART == 1)
+static uint8_t ANCS_App_Get_Char(void)
+{
+ uint8_t ch;
+ HAL_UART_Receive(&huart1, (uint8_t*)&ch, 1,HAL_MAX_DELAY);
+
+ /* Echo character back to console */
+ HAL_UART_Transmit_DMA(&huart1, (uint8_t*)&ch, 1);
+
+ /* And cope with Windows */
+ if(ch == '\r'){
+ uint8_t ret = '\n';
+ HAL_UART_Transmit_DMA(&huart1, (uint8_t*)&ret, 1);
+ }
+
+ return ch;
+}
+#endif
+
+static ActionID ANCS_App_Get_ActionID(void)
+{
+ ActionID actID = ActionIDPositive;
+
+ #if (GET_ACTION_ID_FROM_UART == 1)
+ uint8_t performAction;
+ uint32_t StartTime = HAL_GetTick();
+ uint32_t ActionTimeout = 5000;
+
+ APP_DBG_MSG("** Notification Action. Press on the keyboard: A=Accept or R=Reject\r\n");
+ APP_DBG_MSG("** Waiting 5 sec....\r\n");
+
+ performAction = ANCS_App_Get_Char();
+
+ if ((HAL_GetTick() - StartTime) >= ActionTimeout) {
+ APP_DBG_MSG("** Action Timeout\r\n");
+ }
+ else
+ {
+ if ((performAction == 'A') || (performAction == 'a')) {
+ actID = ActionIDPositive;
+ APP_DBG_MSG("** Positive Action %c \n\r",performAction);
+ }else if ((performAction == 'R') || (performAction == 'r')) {
+ actID = ActionIDNegative;
+ APP_DBG_MSG("** Reject Action %c \n\r",performAction);
+ }
+ }
+ #endif
+
+ return actID;
+}
+void ANCS_App_Remove_Bonding_Info(void)
+{
+ APP_DBG_MSG(" aci_gap_clear_security_db & aci_gap_remove_bonded_device \n\r");
+ aci_gap_remove_bonded_device(ancs_context.Peer_Address_Type,ancs_context.Peer_Address);
+ aci_gap_clear_security_db();
+}
+
+void ANCS_App_Peer_Bonded_Check(uint16_t Connection_Handle, uint8_t Peer_Address_Type, uint8_t Peer_Address[6])
+{
+ tBleStatus result = BLE_STATUS_SUCCESS;
+
+ ancs_context.connection_handle = Connection_Handle;
+
+ ancs_context.Peer_Address_Type = Peer_Address_Type;
+ ancs_context.Peer_Address[5] = Peer_Address[5];
+ ancs_context.Peer_Address[4] = Peer_Address[4];
+ ancs_context.Peer_Address[3] = Peer_Address[3];
+ ancs_context.Peer_Address[2] = Peer_Address[2];
+ ancs_context.Peer_Address[1] = Peer_Address[1];
+ ancs_context.Peer_Address[0] = Peer_Address[0];
+
+ result = aci_gap_is_device_bonded(ancs_context.Peer_Address_Type,ancs_context.Peer_Address);
+ if (result == BLE_STATUS_SUCCESS)
+ {
+ ancs_context.Peer_Bonded = 0x01;
+ }
+ else
+ {
+ ancs_context.Peer_Bonded = 0x00;
+ }
+
+ uint8_t Security_Mode, Security_Level;
+
+ result = aci_gap_get_security_level(ancs_context.connection_handle,&Security_Mode,&Security_Level);
+ ancs_context.Security_Mode = Security_Mode;
+ ancs_context.Security_Level = Security_Level;
+ if (result == BLE_STATUS_SUCCESS)
+ {
+ APP_DBG_MSG("Peer_Bonded=%d Security_Mode= %d, Security_Level= %d \n\r", ancs_context.Peer_Bonded, Security_Mode, Security_Level);
+ }
+
+}
+
+void ANCS_App_Update_Service( )
+{
+ switch(ancs_context.state)
+ {
+ case ANCS_NUMERIC_COMPARISON_VALUE_CONFIRM:
+ {
+ GapProcReq(GAP_PROC_NUMERIC_COMPARISON_VALUE_CONFIRM);
+ }
+ break;
+
+ case ANCS_ALLOW_REBOND:
+ {
+ GapProcReq(GAP_PROC_ALLOW_REBOND);
+ }
+ break;
+
+ case ANCS_MTU_UPDATE:
+ {
+ GattProcReq(GATT_PROC_MTU_UPDATE);
+ }
+ break;
+
+ case ANCS_DISCOVER_ANCS_SERVICE:
+ {
+ /* GattProcReq(GATT_PROC_MTU_UPDATE); */ /* enable it if you want to set ATT_MTU */
+ GattProcReq(GATT_PROC_DISC_ANCS_SERVICE);
+ GattProcReq(GATT_PROC_DISC_ALL_PRIMARY_SERVICES);
+ GattProcReq(GATT_PROC_DISC_ALL_CHARS);
+ GattProcReq(GATT_PROC_DISC_ALL_DESCS);
+
+ APP_DBG_MSG("Peer_Bonded=%d Security_Mode= %d, Security_Level= %d \n\r", ancs_context.Peer_Bonded, ancs_context.Security_Mode,ancs_context.Security_Level);
+ if ( (ancs_context.ANCSServiceStartHandle != 0x0000) && (ancs_context.ANCSServiceEndHandle != 0x0000) )
+ {
+ if( (ancs_context.Peer_Bonded == 0x00) ||
+ ( (ancs_context.Peer_Bonded == 0x01) && (ancs_context.Security_Mode == 0x01) && (ancs_context.Security_Level == 0x01) )
+ )
+ {
+ GapProcReq(GAP_PROC_SLAVE_SECURITY_REQ);
+
+ APP_DBG_MSG("waiting for EVT_BLUE_GAP_PAIRING_CMPLT \n\r");
+ gap_cmd_resp_wait(GAP_DEFAULT_TIMEOUT);/* waiting for EVT_BLUE_GAP_PAIRING_CMPLT */
+ APP_DBG_MSG("waited for EVT_BLUE_GAP_PAIRING_CMPLT \n\r");
+ }
+ }
+
+ GattProcReq(GATT_PROC_ENABLE_ALL_NOTIFICATIONS);
+ }
+ break;
+
+
+ case ANCS_GET_NOTIFICATION_ATTRIBUTE:
+ {
+ AncsProcReq(ANCS_PROC_GET_NOTIFICATION_ATTRIBUTE);
+ }
+ break;
+
+ case ANCS_GET_APP_ATTRIBUTE:
+ {
+ AncsProcReq(ANCS_PROC_GET_APP_ATTRIBUTE);
+ }
+ break;
+
+ case ANCS_PERFORM_NOTIFICATION_ACTION:
+ {
+ AncsProcReq(ANCS_PROC_PERFORM_NOTIFICATION_ACTION);
+ }
+ break;
+
+ default:
+ {
+ APP_DBG_MSG("invalid ancs_context.state=%d \n\r",ancs_context.state);
+ }
+ break;
+ }
+}
+
+static void GapProcReq(GapProcId_t GapProcId)
+{
+ tBleStatus status;
+ uint8_t Security_Mode, Security_Level;
+
+ switch(GapProcId)
+ {
+ case GAP_PROC_SLAVE_SECURITY_REQ:
+ {
+ ancs_context.state = ANCS_SECURITY_REQUEST;
+ status = aci_gap_get_security_level(ancs_context.connection_handle,&Security_Mode,&Security_Level);
+ if (status == BLE_STATUS_SUCCESS)
+ {
+ APP_DBG_MSG("ANCS_SECURITY_REQUEST Security_Mode= %d, Security_Level= %d \n", Security_Mode, Security_Level);
+ status = aci_gap_slave_security_req(ancs_context.connection_handle);
+ if (status != BLE_STATUS_SUCCESS)
+ {
+ APP_DBG_MSG("ANCS_SECURITY_REQUEST aci_gap_slave_security_req status=0x%02x \n\r",status);
+ }
+
+ APP_DBG_MSG("ANCS_SECURITY_REQUEST waiting for EVT_BLUE_GAP_SLAVE_SECURITY_INITIATED \n\r");
+ gap_cmd_resp_wait(GAP_DEFAULT_TIMEOUT);/* waiting for EVT_BLUE_GAP_SLAVE_SECURITY_INITIATED */
+ APP_DBG_MSG("ANCS_SECURITY_REQUEST waited for EVT_BLUE_GAP_SLAVE_SECURITY_INITIATED \n\r");
+ }
+ }
+ break;
+
+ case GAP_PROC_PASS_KEY_RESPONSE:
+ {
+ ancs_context.state = ANCS_PASS_KEY_RESPONSE;
+ APP_DBG_MSG("ANCS_PASS_KEY_RESPONSE \n\r");
+ aci_gap_pass_key_resp(ancs_context.connection_handle, CFG_FIXED_PIN);/* response for EVT_BLUE_GAP_PASS_KEY_REQUEST */
+ }
+ break;
+
+ case GAP_PROC_ALLOW_REBOND:
+ {
+ ancs_context.state = ANCS_ALLOW_REBOND;
+ APP_DBG_MSG("ANCS_ALLOW_REBOND aci_gap_allow_rebond(0x%04X)\n\r",ancs_context.connection_handle);
+ aci_gap_allow_rebond(ancs_context.connection_handle);/* response for EVT_BLUE_GAP_BOND_LOST */
+ }
+ break;
+
+ case GAP_PROC_NUMERIC_COMPARISON_VALUE_CONFIRM:
+ {
+ ancs_context.state = ANCS_NUMERIC_COMPARISON_VALUE_CONFIRM;
+ aci_gap_numeric_comparison_value_confirm_yesno(ancs_context.connection_handle, 1); /* CONFIRM_YES = 1 */
+
+ APP_DBG_MSG("GAP_PROC_NUMERIC_COMPARISON_VALUE_CONFIRM ** aci_gap_numeric_comparison_value_confirm_yesno-->YES \n");
+ }
+ break;
+
+ case GAP_PROC_TERMINATE_CONNECTION:
+ {
+ APP_DBG_MSG("terminate connection \n");
+ ancs_context.state = ANCS_DISCONNECTING;
+ status = aci_gap_terminate(ancs_context.connection_handle,0x13);
+ if (status != BLE_STATUS_SUCCESS)
+ {
+ APP_DBG_MSG("Term Connection cmd failure: 0x%x\n", status);
+ }
+ gap_cmd_resp_wait(GAP_DEFAULT_TIMEOUT);
+
+ APP_DBG_MSG("GAP_PROC_TERMINATE_CONNECTION complete event received\n");
+ }
+ break;
+
+ default:
+ break;
+ }
+ return;
+}
+
+static void GattProcReq(GattProcId_t GattProcId)
+{
+ tBleStatus result = BLE_STATUS_SUCCESS;
+
+ switch (GattProcId)
+ {
+ case GATT_PROC_MTU_UPDATE:
+ {
+ ancs_context.state = ANCS_SET_DATA_LENGTH;
+ result = hci_le_set_data_length(ancs_context.connection_handle,CFG_BLE_MAX_ATT_MTU,CFG_BLE_MAX_ATT_MTU_TX_TIME);
+ if (result == BLE_STATUS_SUCCESS)
+ {
+ APP_DBG_MSG("ANCS_SET_DATA_LENGTH set data length %d %d ok ==>aci_gatt_exchange_config \n",CFG_BLE_MAX_ATT_MTU,CFG_BLE_MAX_ATT_MTU_TX_TIME);
+ ancs_context.state = ANCS_MTU_UPDATE;
+ result = aci_gatt_exchange_config(ancs_context.connection_handle);
+ gatt_cmd_resp_wait(GATT_DEFAULT_TIMEOUT);
+ if (result == BLE_STATUS_SUCCESS)
+ {
+ APP_DBG_MSG("aci_gatt_exchange_config cmd ok \n\r");
+ }
+ else
+ {
+ APP_DBG_MSG("aci_gatt_exchange_config cmd KO result=0x%02x \n\r",result);
+ }
+ }
+ }
+ break; /* GATT_PROC_MTU_UPDATE */
+
+ case GATT_PROC_DISC_ANCS_SERVICE:
+ {
+ ancs_context.state = ANCS_DISCOVER_ANCS_SERVICE;
+ /* discover ancs service for discover notification source / data source / control point characteristic */
+ UUID_t ancs_service_uuid;
+ COPY_ANCS_SERVICE_UUID(ancs_service_uuid.UUID_128);
+ result = aci_gatt_disc_primary_service_by_uuid(ancs_context.connection_handle,UUID_TYPE_128,(UUID_t *)&ancs_service_uuid);
+ if (result == BLE_STATUS_SUCCESS)
+ {
+ APP_DBG_MSG("GATT_PROC_DISC_ANCS_SERVICE aci_gatt_disc_primary_service_by_uuid cmd ok\n");
+ }
+ else
+ {
+ APP_DBG_MSG("GATT_PROC_DISC_ANCS_SERVICE aci_gatt_disc_primary_service_by_uuid cmd NOK status =0x%02X \n",result);
+ }
+
+ gatt_cmd_resp_wait(GATT_DEFAULT_TIMEOUT);
+ if ( (ancs_context.ANCSServiceStartHandle == 0x0000) && (ancs_context.ANCSServiceEndHandle == 0x0000) )
+ {
+ APP_DBG_MSG("GATT_PROC_DISC_ANCS_SERVICE ANCS Service is NOT found !!! ==> connected to Android Phone/Pad \n\r");
+ }
+ else if ( (ancs_context.ANCSServiceStartHandle != 0x0000) && (ancs_context.ANCSServiceEndHandle != 0x0000) )
+ {
+ APP_DBG_MSG("GATT_PROC_DISC_ANCS_SERVICE ANCS Service [0x%04X - 0x%04X] is found !!! ==> connected to iOS Phone/Pad \n\r",ancs_context.ANCSServiceStartHandle,ancs_context.ANCSServiceEndHandle);
+ }
+ }
+ break; /* GATT_PROC_DISC_ANCS_SERVICE */
+
+ case GATT_PROC_DISC_ALL_PRIMARY_SERVICES:
+ {
+ ancs_context.state = ANCS_DISCOVER_ALL_SERVICES;
+ /* discover all services */
+ result = aci_gatt_disc_all_primary_services(ancs_context.connection_handle);
+ gatt_cmd_resp_wait(GATT_DEFAULT_TIMEOUT);
+ if (result == BLE_STATUS_SUCCESS)
+ {
+ APP_DBG_MSG("GATT_PROC_DISC_ALL_PRIMARY_SERVICES ALL services discovered Successfully \n");
+ }
+ else
+ {
+ APP_DBG_MSG("GATT_PROC_DISC_ALL_PRIMARY_SERVICES aci_gatt_disc_all_primary_services cmd NOK status =0x%02X \n",result);
+ }
+
+ if ( (ancs_context.ANCSServiceStartHandle == 0x0000) && (ancs_context.ANCSServiceEndHandle == 0x0000) )
+ {
+ APP_DBG_MSG("GATT_PROC_DISC_ALL_PRIMARY_SERVICES ANCS Service is NOT found !!! \n\r");
+ }
+ else if ( (ancs_context.ANCSServiceStartHandle != 0x0000) && (ancs_context.ANCSServiceEndHandle != 0x0000) )
+ {
+ APP_DBG_MSG("GATT_PROC_DISC_ALL_PRIMARY_SERVICES ANCS Service [0x%04X - 0x%04X] is found !!! \n\r",ancs_context.ANCSServiceStartHandle,ancs_context.ANCSServiceEndHandle);
+ APP_DBG_MSG("GATT_PROC_DISC_ALL_PRIMARY_SERVICES GATT Service [0x%04X - 0x%04X] is found !!! \n\r",ancs_context.GATTServiceStartHandle,ancs_context.GATTServiceEndHandle);
+ }
+ }
+ break; /* GATT_PROC_DISC_ALL_PRIMARY_SERVICES */
+
+ case GATT_PROC_DISC_ALL_CHARS:
+ {
+ ancs_context.state = ANCS_DISCOVER_ALL_CHARS;
+ APP_DBG_MSG("ANCS_DISCOVER_ALL_CHARS connection_handle=0x%04X ALLServiceHandle[%04X - %04X] ANCSServiceHandle[%04X - %04X]\n",
+ ancs_context.connection_handle,
+ ancs_context.ALLServiceStartHandle, ancs_context.ALLServiceEndHandle,
+ ancs_context.ANCSServiceStartHandle, ancs_context.ANCSServiceStartHandle);
+
+ result = aci_gatt_disc_all_char_of_service(
+ ancs_context.connection_handle,
+ ancs_context.ALLServiceStartHandle,
+ ancs_context.ALLServiceEndHandle);
+ gatt_cmd_resp_wait(GATT_DEFAULT_TIMEOUT);
+ if (result == BLE_STATUS_SUCCESS)
+ {
+ APP_DBG_MSG("ALL characteristics discovered Successfully \n\r");
+ }
+ else
+ {
+ APP_DBG_MSG("ALL characteristics discovery Failed \n\r");
+ }
+
+ if( (ancs_context.ANCSNotificationSourceCharStartHdle != 0x0000) && (ancs_context.ANCSNotificationSourceCharValueHdle != 0x0000) )
+ {
+ APP_DBG_MSG("GATT_PROC_DISC_ALL_CHARS ANCSNotificationSourceCharStartHdle=0x%04X ANCSNotificationSourceCharValueHdle=0x%04X \n\r",ancs_context.ANCSNotificationSourceCharStartHdle,ancs_context.ANCSNotificationSourceCharValueHdle);
+ }
+ if( (ancs_context.ANCSDataSourceCharStartHdle!= 0x0000) && (ancs_context.ANCSDataSourceCharValueHdle != 0x0000) )
+ {
+ APP_DBG_MSG("GATT_PROC_DISC_ALL_CHARS ANCSDataSourceCharStartHdle=0x%04X ANCSDataSourceCharValueHdle=0x%04X \n\r",ancs_context.ANCSDataSourceCharStartHdle,ancs_context.ANCSDataSourceCharValueHdle);
+ }
+ if( (ancs_context.ANCSControlPointCharStartHdle!= 0x0000) && (ancs_context.ANCSControlPointCharValueHdle != 0x0000) )
+ {
+ APP_DBG_MSG("GATT_PROC_DISC_ALL_CHARS ANCSControlPointCharStartHdle=0x%04X ANCSControlPointCharValueHdle=0x%04X \n\r",ancs_context.ANCSControlPointCharStartHdle,ancs_context.ANCSControlPointCharValueHdle);
+ }
+ if( (ancs_context.ServiceChangedCharStartHdle != 0x0000) && (ancs_context.ServiceChangedCharValueHdle != 0x0000) )
+ {
+ APP_DBG_MSG("GATT_PROC_DISC_ALL_CHARS ServiceChangedCharStartHdle=0x%04X ServiceChangedCharValueHdle=0x%04X \n\r",ancs_context.ServiceChangedCharStartHdle,ancs_context.ServiceChangedCharValueHdle);
+ }
+ }
+ break; /* GATT_PROC_DISC_ALL_CHARS */
+
+ case GATT_PROC_DISC_ALL_DESCS:
+ {
+ ancs_context.state = ANCS_DISCOVER_ALL_CHAR_DESCS;
+ APP_DBG_MSG("ANCS_DISCOVER_ALL_CHAR_DESCS [%04X - %04X]\n",
+ ancs_context.ALLServiceStartHandle,
+ ancs_context.ALLServiceEndHandle);
+ result = aci_gatt_disc_all_char_desc(
+ ancs_context.connection_handle,
+ ancs_context.ALLServiceStartHandle,
+ ancs_context.ALLServiceEndHandle);
+ gatt_cmd_resp_wait(GATT_DEFAULT_TIMEOUT);
+ if (result == BLE_STATUS_SUCCESS)
+ {
+ APP_DBG_MSG("All characteristic descriptors discovered Successfully \n\r");
+ }
+ else
+ {
+ APP_DBG_MSG("All characteristic descriptors discovery Failed \n\r");
+ }
+
+ if( (ancs_context.ANCSNotificationSourceCharDescHdle!= 0x0000) )
+ {
+ APP_DBG_MSG("GATT_PROC_DISC_ALL_DESCS ANCSNotificationSourceCharDescHdle=0x%04X \n\r",ancs_context.ANCSNotificationSourceCharDescHdle);
+ }
+ if( (ancs_context.ANCSControlPointCharDescHdle!= 0x0000) )
+ {
+ APP_DBG_MSG("GATT_PROC_DISC_ALL_DESCS ANCSControlPointCharDescHdle=0x%04X \n\r",ancs_context.ANCSControlPointCharDescHdle);
+ }
+ if( (ancs_context.ANCSDataSourceCharDescHdle!= 0x0000) )
+ {
+ APP_DBG_MSG("GATT_PROC_DISC_ALL_DESCS ANCSDataSourceCharDescHdle=0x%04X \n\r",ancs_context.ANCSDataSourceCharDescHdle);
+ }
+ if( (ancs_context.ServiceChangedCharDescHdle != 0x0000) )
+ {
+ APP_DBG_MSG("GATT_PROC_DISC_ALL_DESCS ServiceChangedCharDescHdle=0x%04X \n\r",ancs_context.ServiceChangedCharDescHdle);
+ }
+ }
+ break; /* GATT_PROC_DISC_ALL_DESCS */
+
+ case GATT_PROC_ENABLE_ALL_NOTIFICATIONS:
+ {
+ uint16_t enable = 0x0001;
+
+ if(ancs_context.ServiceChangedCharDescHdle != 0x0000)
+ {
+ ancs_context.state = ANCS_ENABLE_NOTIFICATION_SERVICE_CHANGED_DESC;
+ result = aci_gatt_write_char_desc(
+ ancs_context.connection_handle,
+ ancs_context.ServiceChangedCharDescHdle,
+ 2,
+ (uint8_t *) &enable);
+ gatt_cmd_resp_wait(GATT_DEFAULT_TIMEOUT);
+ if (result == BLE_STATUS_SUCCESS)
+ {
+ APP_DBG_MSG("ServiceChangedCharDescHdle=0x%04X notification enabled Successfully \n\r",ancs_context.ServiceChangedCharDescHdle);
+ }
+ else
+ {
+ APP_DBG_MSG("ServiceChangedCharDescHdle=0x%04X notification enabled Failed BLE_STATUS_NOT_ALLOWED=0x%02x result=0x%02X\n",
+ ancs_context.ServiceChangedCharDescHdle,BLE_STATUS_NOT_ALLOWED,result);
+ }
+ }
+
+ if(ancs_context.ANCSDataSourceCharDescHdle != 0x0000)
+ {
+ ancs_context.state = ANCS_ENABLE_NOTIFICATION_DATA_SOURCE_DESC;
+ APP_DBG_MSG("ANCS_ENABLE_NOTIFICATION_DATA_SOURCE_DESC 0x%04X 0x%04X \n",
+ ancs_context.connection_handle,
+ ancs_context.ANCSDataSourceCharDescHdle);
+ result = aci_gatt_write_char_desc(
+ ancs_context.connection_handle,
+ ancs_context.ANCSDataSourceCharDescHdle,
+ 2,
+ (uint8_t *) &enable);
+ gatt_cmd_resp_wait(GATT_DEFAULT_TIMEOUT);
+ if (result == BLE_STATUS_SUCCESS)
+ {
+ APP_DBG_MSG("ANCSDataSourceCharDescHdle notification enabled Successfully \n\r");
+ }
+ else
+ {
+ APP_DBG_MSG("ANCSDataSourceCharDescHdle=0x%04X notification enabled Failed BLE_STATUS_NOT_ALLOWED=0x%02x result=0x%02X\n",
+ ancs_context.ANCSDataSourceCharDescHdle,BLE_STATUS_NOT_ALLOWED,result);
+ }
+ }
+
+ if(ancs_context.ANCSNotificationSourceCharDescHdle != 0x0000)
+ {
+ ancs_context.state = ANCS_ENABLE_NOTIFICATION_NOTIFICATION_SOURCE_DESC;
+ APP_DBG_MSG("ANCS_ENABLE_NOTIFICATION_NOTIFICATION_SOURCE_DESC 0x%04X 0x%04X \n",
+ ancs_context.connection_handle,
+ ancs_context.ANCSNotificationSourceCharDescHdle);
+ result = aci_gatt_write_char_desc(
+ ancs_context.connection_handle,
+ ancs_context.ANCSNotificationSourceCharDescHdle,
+ 2,
+ (uint8_t *) &enable);
+ gatt_cmd_resp_wait(GATT_DEFAULT_TIMEOUT);
+ if (result == BLE_STATUS_SUCCESS)
+ {
+ APP_DBG_MSG("ANCSNotificationSourceCharDescHdle notification enabled Successfully \n\r");
+ ancs_context.state = ANCS_INITIALIZED;
+ }
+ else
+ {
+ APP_DBG_MSG("ANCSNotificationSourceCharDescHdle notification enabled Failed result=0x%02X\n",result);
+ }
+ }
+ }
+ break; /* GATT_PROC_ENABLE_ALL_NOTIFICATIONS */
+
+ default:
+ break;
+ }
+}
+
+static void AncsProcReq(AncsProcId_t AncsProcId)
+{
+ switch (AncsProcId)
+ {
+
+ case ANCS_PROC_GET_NOTIFICATION_ATTRIBUTE:
+ {
+ ancs_context.state = ANCS_GET_NOTIFICATION_ATTRIBUTE;
+ if ( (ancs_context.notifyEntry == INVALID_NOTIFY_ENTRY) || (ancs_context.notifyEntry >= MAX_NMB_NOTIFY) )
+ {
+ APP_DBG_MSG("ANCS_GET_NOTIFICATION_ATTRIBUTE INVALID_NOTIFY_ENTRY %d \n\r",ancs_context.notifyEntry);
+ break;
+ }
+ else
+ {
+ APP_DBG_MSG("ANCS_GET_NOTIFICATION_ATTRIBUTE interact with iOS NotificationID 0x%08x, retrieve more information\n\r",
+ ancs_context.notifyList[ancs_context.notifyEntry].notifUID);
+ }
+
+ notificationAttr_type attr;
+ attr.UID = ancs_context.notifyList[ancs_context.notifyEntry].notifUID;
+ attr.appID_flag = TRUE;
+ attr.title_flag = TRUE;
+ attr.title_max_size = MAX_DATA_LEN;
+ attr.subtitle_flag = TRUE;
+ attr.subtitle_max_size = MAX_DATA_LEN;
+ attr.message_flag = TRUE;
+ attr.message_max_size = MAX_DATA_LEN;
+ attr.messageSize_flag = TRUE;
+ attr.date_flag = TRUE;
+ attr.positiveAction_flag = TRUE;
+ attr.negativeAction_flag = TRUE;
+
+ ANCS_Cmd_GetNotificationAttr(attr);
+ }
+ break; /* ANCS_PROC_GET_NOTIFICATION_ATTRIBUTE */
+
+ case ANCS_PROC_GET_APP_ATTRIBUTE:
+ {
+ ancs_context.state = ANCS_GET_APP_ATTRIBUTE;
+ APP_DBG_MSG("ANCS_GET_APP_ATTRIBUTE AppIdentifierLength=%d AppIdentifier:%s \n\r",
+ ancs_context.AppIdentifierLength,ancs_context.AppIdentifier);
+ ANCS_Cmd_GetAppAttr(ancs_context.AppIdentifierLength, (char*)ancs_context.AppIdentifier);
+ }
+ break; /* ANCS_PROC_GET_APP_ATTRIBUTE */
+
+ case ANCS_PROC_PERFORM_NOTIFICATION_ACTION:
+ {
+ ancs_context.state = ANCS_PERFORM_NOTIFICATION_ACTION;
+ ActionID actID = ActionIDPositive;
+ if ( (ancs_context.notifyEntry == INVALID_NOTIFY_ENTRY) || (ancs_context.notifyEntry >= MAX_NMB_NOTIFY) )
+ {
+ APP_DBG_MSG("ANCS_PERFORM_NOTIFICATION_ACTION INVALID_NOTIFY_ENTRY %d \n\r",ancs_context.notifyEntry);
+ break;
+ }
+ else
+ {
+ APP_DBG_MSG("ANCS_PERFORM_NOTIFICATION_ACTION notifyEntry=%d NotificationID 0x%08x actID=%d \n\r",
+ ancs_context.notifyEntry,ancs_context.notifyList[ancs_context.notifyEntry].notifUID,actID);
+ }
+
+ /*Here you can add interface to get actionID through UART input or button press */
+ actID = ANCS_App_Get_ActionID();
+ ANCS_Cmd_PerformNotificationAction(ancs_context.notifyList[ancs_context.notifyEntry].notifUID,actID);
+
+ APP_DBG_MSG("ANCS_PERFORM_NOTIFICATION_ACTION notifyEntry=%d Removed\n\r", ancs_context.notifyEntry);
+ ancs_context.notifyList[ancs_context.notifyEntry].used = FALSE;
+ }
+ break; /* ANCS_PROC_PERFORM_NOTIFICATION_ACTION */
+
+ default:
+ break;
+ }
+}
+
+void ANCS_App_Notification( Connection_Context_t *pNotification )
+{
+ uint8_t status = BLE_STATUS_SUCCESS;
+
+ switch (pNotification->Evt_Opcode)
+ {
+ case ANCS_CONNECTED:
+ {
+ ancs_context.connection_handle = pNotification->connection_handle; /* register */
+ ancs_context.state = ANCS_DISCOVER_ANCS_SERVICE;
+ APP_DBG_MSG("ANCS_CONNECTED ==> ANCS_DISCOVER_ANCS_SERVICE \n\r");
+
+ Ancs_Mgr();
+ }
+ break;
+
+ case ANCS_DISCONN_COMPLETE:
+ {
+ APP_DBG_MSG("ANCS_DISCONN_COMPLETE \n\r");
+ if(ancs_context.state == ANCS_DISCONNECTING)
+ gap_cmd_resp_release(0);
+
+ ancs_context.state = ANCS_DISCONN_COMPLETE;
+ ANCS_Client_Reset();
+ }
+ break;
+
+ case ANCS_PASS_KEY_REQUEST:
+ {
+ ancs_context.state = ANCS_PASS_KEY_RESPONSE;
+ APP_DBG_MSG("ANCS_PASS_KEY_REQUEST ==> ANCS_PASS_KEY_RESPONSE \n\r");
+ Ancs_Mgr();
+ }
+ break;
+
+ case ANCS_NUMERIC_COMPARISON_VALUE_CONFIRM:
+ {
+ ancs_context.state = ANCS_NUMERIC_COMPARISON_VALUE_CONFIRM;
+ APP_DBG_MSG("ANCS_NUMERIC_COMPARISON_VALUE_CONFIRM \n\r");
+ Ancs_Mgr();
+ }
+ break;
+
+ case ANCS_SECURITY_INITIATED:
+ {
+ ancs_context.state = ANCS_SECURITY_INITIATED;
+ APP_DBG_MSG("ANCS_SECURITY_INITIATED \n\r");
+ gap_cmd_resp_release(0);
+ }
+ break;
+
+ case ANCS_PAIRING_COMPLETE:
+ {
+ uint8_t Security_Mode, Security_Level;
+
+ status = aci_gap_get_security_level(ancs_context.connection_handle,&Security_Mode,&Security_Level);
+ if (status == BLE_STATUS_SUCCESS)
+ {
+ APP_DBG_MSG("ANCS_PAIRING_COMPLETE Peer_Bonded=%d Security_Mode=%d Security_Level=%d \n",ancs_context.Peer_Bonded, Security_Mode, Security_Level);
+ }
+
+ if (ancs_context.Peer_Bonded == 0x00)/* only for the first paring complete*/
+ {
+ status = aci_gap_is_device_bonded(ancs_context.Peer_Address_Type,ancs_context.Peer_Address);
+ if (status == BLE_STATUS_SUCCESS)
+ {
+ ancs_context.Peer_Bonded = 0x01;
+ }
+ else
+ {
+ ancs_context.Peer_Bonded = 0x00;
+ }
+
+ APP_DBG_MSG("ANCS_PAIRING_COMPLETE Peer_Bonded from 0x00 ==> %d Term Connection for the first pairing complete to save bonding infomation !!! \n\r",ancs_context.Peer_Bonded);
+
+ for (int loop=0;loop<10;loop++) /* */
+ {
+ /* hci_disconnection_complete_event event will be generated when the link is disconnected.
+ It is important to leave an 100 ms blank window before sending any new command (including system hardware reset),
+ since immediately after @ref hci_disconnection_complete_event event, system could save important information in non volatile memory. */
+ int cnt = 1000000;
+ while(cnt--);
+ printf(".\n\r");
+ }
+
+ status = aci_gap_terminate(ancs_context.connection_handle, 0x13);
+ if (status == BLE_STATUS_SUCCESS)
+ {
+ if ( (ancs_context.ANCSServiceStartHandle != 0x0000) && (ancs_context.ANCSServiceEndHandle != 0x0000) )
+ {
+ ANCS_Client_Reset();
+ gap_cmd_resp_release(0);
+ }
+ }
+ }
+ else if(ancs_context.Peer_Bonded == 0x01)
+ {
+ if( (ancs_context.Security_Mode == 0x01) && (ancs_context.Security_Level == 0x01) )
+ {
+ if( (Security_Mode == 0x01) && (Security_Level >= 0x02) )
+ {
+ APP_DBG_MSG("ANCS_PAIRING_COMPLETE Security_Level=%d ==> Security_Level=%d \n\r",ancs_context.Security_Level,Security_Level);
+ ancs_context.Security_Level = Security_Level;
+ ancs_context.Security_Mode = Security_Mode;
+ }
+ }
+
+ if ( (ancs_context.ANCSServiceStartHandle != 0x0000) && (ancs_context.ANCSServiceEndHandle != 0x0000) )
+ gap_cmd_resp_release(0);
+ }
+ }
+ break; /* ANCS_PAIRING_COMPLETE */
+
+ case ANCS_ALLOW_REBOND:
+ {
+ ancs_context.state = ANCS_ALLOW_REBOND;
+ APP_DBG_MSG("ANCS_ALLOW_REBOND \n\r");
+ Ancs_Mgr();
+ }
+ break;
+
+ case ANCS_MTU_UPDATE:
+ {
+ APP_DBG_MSG("ANCS_MTU_UPDATE \n\r");
+ ancs_context.state = ANCS_MTU_UPDATE;
+ Ancs_Mgr();
+ }
+ break;
+
+ case ANCS_MTU_EXCHANGE_COMPLETE:
+ {
+ APP_DBG_MSG("ANCS_MTU_EXCHANGE_COMPLETE \n\r");
+ if(ancs_context.state == ANCS_MTU_UPDATE)
+ gatt_cmd_resp_release(0);
+
+ ancs_context.state = ANCS_MTU_EXCHANGE_COMPLETE;
+ }
+ break;
+
+ case ANCS_DISCOVER_ANCS_SERVICE:
+ {
+ APP_DBG_MSG("ANCS_DISCOVER_ANCS_SERVICE \n\r");
+ ancs_context.state = ANCS_DISCOVER_ANCS_SERVICE;
+ Ancs_Mgr();
+ }
+ break;
+
+ case ANCS_CHECK_NOTIFICATION:
+ {
+ ancs_context.state = ANCS_CHECK_NOTIFICATION;
+ APP_DBG_MSG(" ==> ANCS_CHECK_NOTIFICATION \n\r");
+
+ for (uint8_t idx=0; idx<MAX_NMB_NOTIFY; idx++)
+ {
+ if (ancs_context.notifyList[idx].used)
+ {
+ ANCS_Notification_Check(ancs_context.notifyList[idx].evFlag);
+ Ancs_Mgr();
+ break;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+
+ }
+ return;
+}
+
+
+
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/