/*! \file
 * \brief Transport module to connect to devices over HID Pipe.
 *
 * Allows connections to devices using HID Pipe.
 *
 * \copyright
 * COPYRIGHT NOTICE: (c) 2017-2022 Neonode Technologies AB. All rights reserved.
 */

#ifndef TRANSPORT_HIDPIPETRANSPORT_HIDPIPETRANSPORT_H
#define TRANSPORT_HIDPIPETRANSPORT_HIDPIPETRANSPORT_H 1

#ifndef ZFORCECOMMON_H
    #error Please include "zForceCommon.h" before this file.
#endif // ZFORCECOMMON_H

/*!
 * \sa struct HidPipeTransport
 */
typedef struct HidPipeTransport HidPipeTransport;
/*!
 * \brief Struct containing the HidPipeTransport information.
 *
 * HidPipeTransport contains the Transport base, a pointer to the base Transport class.
 */
struct HidPipeTransport
{
    /*!
     * \brief Base pointer to the immediate base Transport class.
     *
     * Base pointer to the immediate base Transport class.
     * If Base is a NULL pointer then it is the base Transport class itself.
     * \n\n
     * Inherited from Transport base class.
     */
    Transport           * Base;

    /*!
     * \brief Each Transport is linked to one Connection.
     *
     * Each Transport is linked to one Connection.
     * \n\n
     * Inherited from Transport base class.
     */
    Connection          * Connection;

    /*!
     * \brief A pointer to the global zForce instance.
     *
     * A pointer to the global zForce instance.
     * \n\n
     * Inherited from Transport base class.
     */
    zForce              * zForce;

    /*!
     * \brief Connection string.
     *
     * Connection string.
     * This string contain the type of transport and the option parameters on the following form:
     * type://port=portOption e.g
     * "serial://port=/dev/ttyACM0".
     * \n\n
     * Inherited from Transport base class.
     */
    char                  ConnectionString [TRANSPORTPROTOCOL_MaxOptionParameterLength + 1];

    /*!
     * \brief A flag indicating if the Transport Read and Write threads should terminate (true) or not (false).
     *
     * A flag indicating if the Transport Read and Write threads should terminate (true) or not (false).
     * \n\n
     * Inherited from Transport base class.
     */
    volatile bool         Terminate;

    /*!
     * \brief A pointer to the Write queue used by EnqueueDataFrame.
     *
     * A pointer to the Write queue used by EnqueueDataFrame.
     * \n\n
     * Inherited from Transport base class.
     */
    Queue               * WriteQueue;

    /*!
     * \brief A flag indicating if the Transport is open (true) or not (false).
     *
     * A flag indicating if the Transport is open (true) or not (false).
     * \n\n
     * Inherited from Transport base class.
     */
    bool                  IsOpen;

    /*!
     * \brief Transport is in Opening phase.
     *
     * Transport is in Opening phase.
     * \n\n
     * Inherited from Transport base class.
     */
    bool                  Opening;

    /*!
     * \brief Write Thread pointer.
     *
     * Write Thread pointer.
     * \n\n
     * Inherited from Transport base class.
     */
    zForceThread        * WriteThread;

    /*!
     * \brief Read Thread pointer.
     *
     * Read Thread pointer.
     * \n\n
     * Inherited from Transport base class.
     */
    zForceThread        * ReadThread;

    /*!
     * \brief Thread is active.
     *
     * Thread is active.
     * \n\n
     * Inherited from Transport base class.
     */
    volatile ReadWriteThreadStatus WriteThreadStatus;

    /*!
     * \brief Thread is active.
     *
     * Thread is active.
     * \n\n
     * Inherited from Transport base class.
     */
    volatile ReadWriteThreadStatus ReadThreadStatus;

    /*!
     * \brief Open the generic Transport.
     *
     * Opens the Transport specified by the ConnectionString.
     * The ConnectionString's options are used.
     * \n\n
     * Inherited from Transport base class.
     * \n\n
     * On failure, errno is set.
     * - ::ETHREADCREATEFAILED - Thread creation failed.
     * - ::EOUTOFMEMORY - Out of memory.
     * - ::EBADTHREAD - Bad thread pointer.
     * - ::EQUEUECREATIONFAILED - Queue creation failed.
     * - ::EOPENFAILED - Could not open file.
     * - ::ENOPORTENTRY - No such file or directory.
     * - ::EALREADYOPEN - Specific transport is already opened.
     * - ::ENODEVICEENTRY - No device with that name.
     *
     * \param self Pointer to the struct itself.
     *
     * \return True if successful, false if not, and errno set accordingly.
     */
    bool        ( * Open) (Transport * self);

    /*!
     * \brief Close the generic Transport.
     *
     * Close the generic Transport.
     * \n\n
     * Inherited from Transport base class.
     * \n\n
     * On failure, errno is set.
     * - ::ENOTOPENED - Transport is not open.
     * - ::ECLOSEFAILED - Closing file descriptor failed.
     * - ::EBADTHREAD - Bad thread pointer, problem with exiting thread.
     *
     * \param self Pointer to the struct itself.
     *
     * \return True if successful, false if not, and errno set accordingly.
     */
    bool        ( * Close) (Transport * self);

    /*!
     * \brief Function pointer to Transport's Read.
     *
     * Function pointer to Transport's Read.
     * \n\n
     * On failure, errno is set.
     * - ::ENOTOPENED - Transport is not open.
     * - ::EREADFAILED - Read failed.
     * - ::EOUTOFMEMORY - Memory allocation failed.
     *
     * \param self Pointer to the struct itself.
     *
     * \return A pointer to the read data frame, NULL either if no data frames exist or an error has occurred.
     *         Upon error see errno.
     */
    DataFrame * ( * Read) (Transport * self);

    /*!
     * \brief Function pointer to Transport's Write.
     *
     * Function pointer to Transport's Write.
     * \n\n
     * Inherited from Transport base class.
     * \n\n
     * On failure, errno is set.
     * - ::EWRITEFAILED - Write failed.
     * - ::EPARTIALWRITE - Not all bytes written.
     * - ::ENOTOPENED - Transport is not open.
     *
     * \param self Pointer to the struct itself.
     * \param payload The payload pointer.
     *
     * \return True if success, false if failed. See errno.
     */
    bool        ( * Write) (Transport * self, DataFrame * payload);

    /*!
     * \brief Function pointer to Transport's GetTimeOutValue.
     *
     * Function pointer to Transport's GetTimeOutValue.
     * \n\n
     * Inherited from Transport base class.
     *
     * \param self Pointer to the struct itself.
     *
     * \return the Transport specific timeout value.
     */
    uint64_t    ( * GetTimeOutValue) (Transport * self);

    /*!
     * \brief Enqueue given dataframe.
     *
     * Enqueue given dataframe.
     * \n\n
     * Inherited from Transport base class.
     * \n\n
     * On failure, errno is set.
     * - ::EENQUEUEFAILED - Generic enqueue error.
     * - ::EOUTOFMEMORY - Memory allocation failed.
     * - ::EBADQUEUE - Bad Queue pointer.
     * - ::ENOTOPENED - Transport is not open.
     *
     * \param self Pointer to the struct itself.
     * \param dataFrame the data frame to be put in the Write queue
     *
     * \return True if successful, false if not, and errno set accordingly.
     */
    bool        ( * EnqueueDataFrame) (Transport * self, DataFrame * dataFrame);

    /*!
     * \brief Destructor frees all the resources that have been allocated.
     *
     * Destructor frees all the resources that have been allocated.
     * \n\n
     * Inherited from Transport base class.
     *
     * \param self Pointer to the struct itself.
     */
    void        ( * Destructor ) (Transport * self);

    /*!
     * \brief Signals the transport that it has been lost and acts accordingly.
     *
     * Signals the transport that it has been lost and acts accordingly.
     * \n\n
     * Inherited from Transport base class.
     *
     * \param self Pointer to the struct itself.
     */
    void        ( * TransportLost) (Transport * self);

    /*!
     * \brief Boolean value that indicates that there is no longer any communication. Internal use only.
     *
     * Boolean value that indicates that there is no longer any communication. Internal use only.
     * \n\n
     * Inherited from Transport base class.
     */
    bool            StopCommunication;

    void * Private;  //!< Private members of HidPipeTransport.
};

#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus

/*!
 * \brief Internal call to add a HidPipeTransport to the list of available transports.
 *
 * This is the method used to add a HidPipeTransport which can be used for communication.
 * \n\n
 * On failure, errno is set.
 * - ::EALREADYADDED - A Transport matching the name and data frame type has already been added.
 * - ::EOUTOFMEMORY - The memory used to store Transport details has been exhausted.
 * - ::EMUTEXLOCKFAILED - We couldn't lock a mutex we need for an internal critical section. This should not happen.
 * - ::EBADMUTEX - We tried to use a mutex internally but it wasn't a valid mutex. This should not happen.
 * - ::EPARAMETERSTRINGTOOLONG - The option parameter string is longer than the MaxOptionParameterLength.
 *
 * \return True if the HidPipeTransport has been added.
 */
DLLINTERNAL bool HidPipeTransport_AddHidPipeTransportEntry (void);

#ifdef __cplusplus
}
#endif // __cplusplus

#endif // TRANSPORT_HIDPIPETRANSPORT_HIDPIPETRANSPORT_H
