/*! *********************************************************************************
 * \defgroup GATT_CLIENT GATT - Client APIs
 * @{
 ********************************************************************************** */
/*! *********************************************************************************
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
* 
* \file
*
* SPDX-License-Identifier: BSD-3-Clause
********************************************************************************** */

#ifndef GATT_CLIENT_INTERFACE_H
#define GATT_CLIENT_INTERFACE_H

/************************************************************************************
*************************************************************************************
* Include
*************************************************************************************
************************************************************************************/
#include "gatt_interface.h"

/************************************************************************************
*************************************************************************************
* Macros
*************************************************************************************
************************************************************************************/
/*! *********************************************************************************
* \brief  Executes the basic Characteristic Write operation (with server confirmation).
*
* \param[in] deviceId       Device ID of the connected GATT Server.
* \param[in] pChar          Pointer to the Characteristic being written.
* \param[in] valueLength    Size in bytes of the value to be written.
* \param[in] aValue         Array of bytes to be written.
*
* \return  gBleSuccess_c or error.
*
********************************************************************************** */
#define GattClient_SimpleCharacteristicWrite(deviceId, pChar, valueLength, aValue) \
    GattClient_WriteCharacteristicValue\
        (deviceId, pChar, valueLength, aValue, FALSE, FALSE, FALSE, NULL)

/*! *********************************************************************************
* \brief  Executes the Characteristic Write Without Response operation.
*
* \param[in] deviceId       Device ID of the connected GATT Server.
* \param[in] pChar          Pointer to the Characteristic being written.
* \param[in] valueLength    Size in bytes of the value to be written.
* \param[in] aValue         Array of bytes to be written.
*
* \return  gBleSuccess_c or error.
*
********************************************************************************** */
#define GattClient_CharacteristicWriteWithoutResponse(deviceId, pChar, valueLength, aValue) \
    GattClient_WriteCharacteristicValue\
        (deviceId, pChar, valueLength, aValue, TRUE, FALSE, FALSE, NULL)

/*! *********************************************************************************
* \brief  Executes the Characteristic Signed Write Without Response operation.
*
* \param[in] deviceId       Device ID of the connected GATT Server.
* \param[in] pChar          Pointer to the Characteristic being written.
* \param[in] valueLength    Size in bytes of the value to be written.
* \param[in] aValue         Array of bytes to be written.
* \param[in] aCsrk          CSRK to be used for data signing.
*
* \return  gBleSuccess_c or error.
*
********************************************************************************** */
#define GattClient_CharacteristicSignedWrite(deviceId, pChar, valueLength, aValue, aCsrk) \
    GattClient_WriteCharacteristicValue\
        (deviceId, pChar, valueLength, aValue, TRUE, TRUE, FALSE, aCsrk)

/************************************************************************************
*************************************************************************************
* Public type definitions
*************************************************************************************
************************************************************************************/
/*! GATT Client Procedure type */
typedef enum {
    gGattProcExchangeMtu_c                          = 0x00U, /*!< MTU Exchange */
    gGattProcDiscoverAllPrimaryServices_c           = 0x01U, /*!< Primary Service Discovery */
    gGattProcDiscoverPrimaryServicesByUuid_c        = 0x02U, /*!< Discovery of Services by UUID */
    gGattProcFindIncludedServices_c                 = 0x03U, /*!< Discovery of Included Services within a Service range */
    gGattProcDiscoverAllCharacteristics_c           = 0x04U, /*!< Characteristic Discovery within Service range */
    gGattProcDiscoverCharacteristicByUuid_c         = 0x05U, /*!< Characteristic Discovery by UUID */
    gGattProcDiscoverAllCharacteristicDescriptors_c = 0x06U, /*!< Characteristic Descriptor Discovery */
    gGattProcReadCharacteristicValue_c              = 0x07U, /*!< Characteristic Reading using Value handle */
    gGattProcReadUsingCharacteristicUuid_c          = 0x08U, /*!< Characteristic Reading by UUID */
    gGattProcReadMultipleCharacteristicValues_c     = 0x09U, /*!< Reading multiple Characteristics at once */
    gGattProcWriteCharacteristicValue_c             = 0x0AU, /*!< Characteristic Writing */
    gGattProcReadCharacteristicDescriptor_c         = 0x0BU, /*!< Reading Characteristic Descriptors */
    gGattProcWriteCharacteristicDescriptor_c        = 0x0CU, /*!< Writing Characteristic Descriptors */
} gattProcedureType_t;

/*! GATT Client Procedure Result type */
typedef enum {
    gGattProcSuccess_c,     /*!< The procedure was completed successfully. */
    gGattProcError_c        /*!< The procedure was terminated due to an error. */
} gattProcedureResult_t;

/*! GATT Client Procedure Callback type */
typedef void (*gattClientProcedureCallback_t)
(
    deviceId_t              deviceId,           /*!< Device ID identifying the active connection. */
    gattProcedureType_t     procedureType,      /*!< The type of the procedure that was completed. */
    gattProcedureResult_t   procedureResult,    /*!< The result of the completed procedure. */
    bleResult_t             error               /*!< If procedureResult is not gGattProcSuccess_c, this contains the error that terminated the procedure. */
); 

/*! GATT Client Notification Callback prototype */
typedef void (*gattClientNotificationCallback_t)
(
    deviceId_t  deviceId,                   /*!< Device ID identifying the active connection. */
    uint16_t    characteristicValueHandle,  /*!< Handle of the Characteristic Value attribute to be notified. */
    uint8_t*    aValue,                     /*!< The Characteristic value array. */
    uint16_t    valueLength                 /*!< Value array size. */
);

/*! GATT Client Indication Callback prototype */
typedef gattClientNotificationCallback_t gattClientIndicationCallback_t;

/************************************************************************************
*************************************************************************************
* Public prototypes
*************************************************************************************
************************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/*
 *
 * Local Client Configuration
 *
 */

/*! *********************************************************************************
* \brief  Initializes the GATT Client functionality.
*
* \remarks This should be called once at device startup, if necessary.
*
* \remarks This function executes synchronously.
*
********************************************************************************** */
bleResult_t GattClient_Init(void);

/*! *********************************************************************************
* \brief  Resets any ongoing GATT Client Procedure.
*
* \remarks This function should be called if an ongoing Client procedure
* needs to be stopped.
*
********************************************************************************** */
bleResult_t GattClient_ResetProcedure(void);

/*! *********************************************************************************
* \brief  Installs the application callback for the GATT Client module Procedures.
*
* \param[in] callback   Application defined callback to be triggered by this module.
*
* \return  gBleSuccess_c or error.
*
* \remarks This function executes synchronously.
*
********************************************************************************** */
bleResult_t GattClient_RegisterProcedureCallback
(
    gattClientProcedureCallback_t callback
);

/*! *********************************************************************************
* \brief  Installs the application callback for Server Notifications.
*
* \param[in] callback   Application defined callback to be triggered by this module.
*
* \return  gBleSuccess_c or error.
*
* \remarks This function executes synchronously.
*
********************************************************************************** */
bleResult_t GattClient_RegisterNotificationCallback
(
    gattClientNotificationCallback_t callback
);

/*! *********************************************************************************
* \brief  Installs the application callback for Server Indications.
*
* \param[in] callback   Application defined callback to be triggered by this module.
*
* \return  gBleSuccess_c or error.
*
* \remarks This function executes synchronously.
*
********************************************************************************** */
bleResult_t GattClient_RegisterIndicationCallback
(
    gattClientIndicationCallback_t callback
);


/* 
 * 
 * GATT Client Procedures 
 *
 */

/*! *********************************************************************************
* \brief  Initializes the MTU Exchange procedure.
*
* \param[in] deviceId       Device ID of the connected peer.
*
* \return  gBleSuccess_c or error.
*
* \remarks If gBleSuccess_c is returned, the completion of this procedure is signalled
* by the Client Procedure callback.
*
********************************************************************************** */
bleResult_t GattClient_ExchangeMtu
(
    deviceId_t      deviceId
);

/*! *********************************************************************************
* \brief  Initializes the Primary Service Discovery procedure.
*
* \param[in]  deviceId              Device ID of the connected peer.
* \param[out] aOutPrimaryServices   Statically allocated array of gattService_t. The GATT 
*                                   module fills each Service's handle range and UUID.
* \param[in]  maxServiceCount       Maximum number of services to be filled.
* \param[out] pOutDiscoveredCount   The actual number of services discovered.
*
* \return  gBleSuccess_c or error.
*
* \remarks If gBleSuccess_c is returned, the completion of this procedure is signalled
* by the Client Procedure callback.
*
********************************************************************************** */
bleResult_t GattClient_DiscoverAllPrimaryServices
(
    deviceId_t      deviceId,
    gattService_t*  aOutPrimaryServices, 
    uint8_t         maxServiceCount,
    uint8_t*        pOutDiscoveredCount
);

/*! *********************************************************************************
* \brief  Initializes the Primary Service Discovery By UUID procedure.
*
* \param[in]  deviceId              Device ID of the connected peer.
* \param[in]  uuidType              Service UUID type.
* \param[in]  pUuid                 Service UUID.
* \param[out] aOutPrimaryServices   Statically allocated array of gattService_t. The GATT
*                                   module fills each Service's handle range.
* \param[in]  maxServiceCount       Maximum number of services to be filled.
* \param[out] pOutDiscoveredCount   The actual number of services discovered.
*
* \return  gBleSuccess_c or error.
*
* \remarks If gBleSuccess_c is returned, the completion of this procedure is signalled
* by the Client Procedure callback.
*
********************************************************************************** */
bleResult_t GattClient_DiscoverPrimaryServicesByUuid
(
    deviceId_t         deviceId,
    bleUuidType_t      uuidType,
    const bleUuid_t*   pUuid,
    gattService_t*     aOutPrimaryServices,
    uint8_t            maxServiceCount,
    uint8_t*           pOutDiscoveredCount
);

/*! *********************************************************************************
* \brief  Initializes the Find Included Services procedure.
*
* \param[in]  deviceId              Device ID of the connected peer.
* \param[inout]  pIoService         The service within which inclusions should be searched.
*                                   The GATT module uses the Service's handle range and fills
*                                   the included Services' handle ranges, UUID types and
*                                   the UUIDs if they are 16-bit UUIDs.
* \param[in]  maxServiceCount       Maximum number of included services to be filled.
*
* \return  gBleSuccess_c or error.
*
* \remarks If gBleSuccess_c is returned, the completion of this procedure is signalled
* by the Client Procedure callback.
*
********************************************************************************** */
bleResult_t GattClient_FindIncludedServices
(
    deviceId_t      deviceId,
    gattService_t*  pIoService,
    uint8_t         maxServiceCount
);

/*! *********************************************************************************
* \brief  Initializes the Characteristic Discovery procedure for a given Service.
*
* \param[in]    deviceId                  Device ID of the connected peer.
* \param[inout] pIoService                The service within which characteristics should be searched.
*                                         The GATT module uses the Characteristic's range.
* \param[in]    maxCharacteristicCount    Maximum number of characteristics to be filled.
*
* \return  gBleSuccess_c or error.
*
* \remarks If gBleSuccess_c is returned, the completion of this procedure is signalled
* by the Client Procedure callback.
*
********************************************************************************** */
bleResult_t GattClient_DiscoverAllCharacteristicsOfService
(
    deviceId_t      deviceId,
    gattService_t*  pIoService,
    uint8_t         maxCharacteristicCount
);

/*! *********************************************************************************
* \brief  Initializes the Characteristic Discovery procedure for a given Service, with a given UUID.
*
* \param[in]  deviceId                  Device ID of the connected peer.
* \param[in]  uuidType                  Characteristic UUID type.
* \param[in]  pUuid                     Characteristic UUID.
* \param[in]  pService                  The service within which characteristics should be searched.
* \param[out] aOutCharacteristics       The allocated array of Characteristics to be filled.
* \param[in]  maxCharacteristicCount    Maximum number of characteristics to be filled.
* \param[out] pOutDiscoveredCount       The actual number of characteristics discovered.
*
* \return  gBleSuccess_c or error.
*
* \remarks If gBleSuccess_c is returned, the completion of this procedure is signalled
* by the Client Procedure callback.
*
********************************************************************************** */
bleResult_t GattClient_DiscoverCharacteristicOfServiceByUuid
(
    deviceId_t              deviceId,
    bleUuidType_t           uuidType,
    const bleUuid_t*        pUuid,
    const gattService_t*    pService,
    gattCharacteristic_t*   aOutCharacteristics,
    uint8_t                 maxCharacteristicCount,
    uint8_t*                pOutDiscoveredCount
);

/*! *********************************************************************************
* \brief  Initializes the Characteristic Descriptor Discovery procedure for a given Characteristic.
*
* \param[in]  deviceId                  Device ID of the connected peer.
* \param[inout]  pIoCharacteristic      The characteristic within which descriptors should be searched.
*                                       The GATT module uses the Characteristic's handle and fills each
*                                       descriptor's handle and UUID.
* \param[in]  endingHandle              The last handle of the Characteristic.
* \param[in]  maxDescriptorCount        Maximum number of descriptors to be filled.
*
* \return  gBleSuccess_c or error.
*
* \remarks If gBleSuccess_c is returned, the completion of this procedure is signalled
* by the Client Procedure callback. The endingHandle parameter should be known by the
* application if Characteristic Discovery was performed, i.e., if the next Characteristic
* declaration handle is known, then subtract 1 to obtain the endingHandle for the current Characteristic.
* If the last handle of the Characteristic is still unknown, set the endingHandle parameter to 0xFFFF.
*
********************************************************************************** */
bleResult_t GattClient_DiscoverAllCharacteristicDescriptors
(
    deviceId_t              deviceId,
    gattCharacteristic_t*   pIoCharacteristic,
    uint16_t                endingHandle,
    uint8_t                 maxDescriptorCount
);

/*! *********************************************************************************
* \brief  Initializes the Characteristic Read procedure for a given Characteristic.
*
* \param[in]  deviceId                  Device ID of the connected peer.
* \param[inout]  pIoCharacteristic      The characteristic whose value must be read.
*                                       The GATT module uses the value handle and
*                                       fills the value and length.
* \param[in]  maxReadBytes              Maximum number of bytes to be read.
*
* \return  gBleSuccess_c or error.
*
* \remarks If gBleSuccess_c is returned, the completion of this procedure is signalled
* by the Client Procedure callback.
*
********************************************************************************** */
bleResult_t GattClient_ReadCharacteristicValue
(
    deviceId_t              deviceId,
    gattCharacteristic_t*   pIoCharacteristic,
    uint16_t                maxReadBytes
);

/*! *********************************************************************************
* \brief  Initializes the Characteristic Read By UUID procedure.
*
* \param[in]  deviceId                  Device ID of the connected peer.
* \param[in]  uuidType                  Characteristic UUID type.
* \param[in]  pUuid                     Characteristic UUID.
* \param[in]  pHandleRange              Handle range for the search or NULL. If
*                                       this is NULL, the search range is 0x0001-0xffff.
* \param[out] aOutBuffer                The allocated buffer to read into.
* \param[in]  maxReadBytes              Maximum number of bytes to be read.
* \param[out] pOutActualReadBytes       The actual number of bytes read.
*
* \return  gBleSuccess_c or error.
*
* \remarks This procedure returns the Characteristics found within the specified range
* with the specified UUID. aOutBuffer will contain the Handle-Value pair length (1 byte),
* then Handle-Value pairs for all Characteristic Values found with the specified UUID.
*
* \remarks If gBleSuccess_c is returned, the completion of this procedure is signalled
* by the Client Procedure callback.
*
********************************************************************************** */
bleResult_t GattClient_ReadUsingCharacteristicUuid
(
    deviceId_t                deviceId,
    bleUuidType_t             uuidType,
    const bleUuid_t*          pUuid,
    const gattHandleRange_t*  pHandleRange,
    uint8_t*                  aOutBuffer,
    uint16_t                  maxReadBytes,
    uint16_t*                 pOutActualReadBytes
);

/*! *********************************************************************************
* \brief  Initializes the Characteristic Read Multiple procedure.
*
* \param[in]    deviceId                  Device ID of the connected peer.
* \param[inout] aIoCharacteristics        Array of the characteristics whose values are to be read.
*                                         The GATT module uses each Characteristic's value handle and maxValueLength
*                                         fills each value and length.
* \param[in]    cNumCharacteristics       Number of characteristics in the array.
*
* \return  gBleSuccess_c or error.
*
* \remarks If gBleSuccess_c is returned, the completion of this procedure is signalled
* by the Client Procedure callback.
*
********************************************************************************** */
bleResult_t GattClient_ReadMultipleCharacteristicValues
(
    deviceId_t              deviceId,
    uint8_t                 cNumCharacteristics,
    gattCharacteristic_t*   aIoCharacteristics
);

/*! *********************************************************************************
* \brief  Initializes the Characteristic Write procedure for a given Characteristic.
*
* \param[in]  deviceId                  Device ID of the connected peer.
* \param[in]  pCharacteristic           The characteristic whose value must be written.
*                                       The GATT module uses the value handle.
* \param[in]  valueLength               Number of bytes to be written.
* \param[in]  aValue                    Array of bytes to be written.
* \param[in]  withoutResponse           Indicates if a Write Command is used.
* \param[in]  signedWrite               Indicates if a Signed Write is performed.
* \param[in]  doReliableLongCharWrites  Indicates Reliable Long Writes.
* \param[in]  aCsrk                     The CSRK (gcCsrkSize_d bytes) if signedWrite is TRUE, ignored otherwise.
*
* \return  gBleSuccess_c or error.
*
* \remarks If gBleSuccess_c is returned, the completion of this procedure is signalled
* by the Client Procedure callback.
*
********************************************************************************** */
bleResult_t GattClient_WriteCharacteristicValue
(
    deviceId_t                    deviceId,
    const gattCharacteristic_t*   pCharacteristic,
    uint16_t                      valueLength,
    const uint8_t*                aValue,
    bool_t                        withoutResponse,
    bool_t                        signedWrite,
    bool_t                        doReliableLongCharWrites,
    const uint8_t*                aCsrk
);

/*! *********************************************************************************
* \brief  Initializes the Characteristic Descriptor Read procedure for a given Characteristic Descriptor.
*
* \param[in]  deviceId                  Device ID of the connected peer.
* \param[inout]  pIoDescriptor          The characteristic descriptor whose value must be read.
*                                       The GATT module uses the attribute's handle and fills
*                                       the attribute's value and length.
* \param[in]  maxReadBytes              Maximum number of bytes to be read.
*
* \return  gBleSuccess_c or error.
*
* \remarks If gBleSuccess_c is returned, the completion of this procedure is signalled
* by the Client Procedure callback.
*
********************************************************************************** */
bleResult_t GattClient_ReadCharacteristicDescriptor
(
    deviceId_t          deviceId,
    gattAttribute_t*    pIoDescriptor,
    uint16_t            maxReadBytes
);

/*! *********************************************************************************
* \brief  Initializes the Characteristic Descriptor Write procedure for a given Characteristic Descriptor.
*
* \param[in]  deviceId                  Device ID of the connected peer.
* \param[in]  pDescriptor               The characteristic descriptor whose value must be written.
*                                       The GATT module uses the attribute's handle.
* \param[in]  valueLength               Number of bytes to be written.
* \param[in]  aValue                    Array of bytes to be written.
*
* \return  gBleSuccess_c or error.
*
* \remarks If gBleSuccess_c is returned, the completion of this procedure is signalled
* by the Client Procedure callback.
*
********************************************************************************** */
bleResult_t GattClient_WriteCharacteristicDescriptor
(
    deviceId_t                deviceId,
    const gattAttribute_t*    pDescriptor,
    uint16_t                  valueLength,
    const uint8_t*            aValue
);

#ifdef __cplusplus
}
#endif 

#endif /* GATT_CLIENT_INTERFACE_H */

/*! *********************************************************************************
* @}
********************************************************************************** */
