#ifndef PHSTBIPC_H    /* Multi-include protection.   <FILENAME>_H */
#define PHSTBIPC_H


/*****************************************************************************/
/* Copyright (c) 2009 NXP B.V.                                               */
/*                                                                           */
/* This library is free software; you can redistribute it and/or             */
/* modify it under the terms of the GNU Lesser General Public                */
/* License as published by the Free Software Foundation, using               */
/* version 2.1 of the License.                                               */
/*                                                                           */
/* This library is distributed in the hope that it will be useful,           */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU          */
/* Lesser General Public License for more details.                           */
/*                                                                           */
/* You should have received a copy of the GNU Lesser General Public          */
/* License along with this library; if not, write to the Free Software       */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA   */
/*                                                                           */
/*****************************************************************************/
/**
    @file   phStbIpc.h
    @brief  Interprocessor communication between a host and server.

@b  Component:  phStbIpc

    A server address is a string containing three parts: "PROTOCOL://HOST:PORT".

    PROTOCOL is "tcpip".

    For protocol "tcpip", HOST can be:
    - "mips1" to indicate the control/main MIPS
    - "mips2" to indicate the dsp/audio MIPS
    - "AAA.BBB.CCC.DDD" to indicate a specific IP address
    - "127.0.0.1" to indicate the current host.

    PORT is a numeric port ID, e.g. "1234".

    Example server addresses:
    - "tcpip://mips2:1234"
    - "tcpip://127.0.0.1:1234"
    - "tcpip://192.168.0.2:1234"

    @note Addresses should be registered in file phStbIpc_Services.h .
*//*

Rev Date       Author      Comments
--------------------------------------------------------------------------------
  1 20060927   batelaan    Initial
  2 20060928   batelaan    Crosscheck fixes.
  3 20061004   batelaan    Implementation.
  4 20061010   batelaan    Crosscheck fixes.
  5 20061213   A.West      Fix for KERNEL build
  6 20070103   batelaan    Add PH_STBIPC_SYSTEM_CALL_ERR
  7 20070214   raiyat      Fixing messy comments ;-)
  8 20071217   hutch       Merge in EB's changes.
  9 20080221   batelaan    Add PH_ERR_STBIPC_IO
 10 20080326   batelaan    Update documentation
 11 20080411   batelaan    Update documentation
 12 20080603   batelaan    Add PH_ERR_STBIPC_ADDRESS_LOOKUP
 13 20080714   raiyat      Allow use of pphStbIpc_Connection_t as socket handle.
 14 20090121   batelaan    Update license header
--------------------------------------------------------------------------------
    For consistency and standardisation retain the Section Separators.
*/


/*******************
* INCLUDE FILES    *
********************/

#include <tmNxTypes.h>
#include <tmNxCompId.h>
#if TMFL_OS_IS_LINUX && !TMFL_MODE_KERNEL
    #include <sys/types.h>
#endif

#ifdef __cplusplus
extern "C"
{
#endif

/**************************************************************************
* EXPORTED MACROS                          PH_STBIPC_<_WORD>+             *
***************************************************************************/

/** If defined, then tcpip protocol is enabled.
    @see #PH_STBIPC_TCPIP_ADDRESS_PREFIX
*/
#define PH_STBIPC_TCPIP_ENABLED

/** If defined, then tipc protocol is enabled.
    @todo Implement and enable this.
    @see #PH_STBIPC_TIPC_ADDRESS_PREFIX
*/
#undef PH_STBIPC_TIPC_ENABLED

/** Protocol indicator for tcp/ip.
    @see #PH_STBIPC_TCPIP_ENABLED
*/
#define PH_STBIPC_TCPIP_ADDRESS_PREFIX "tcpip://"

/** Protocol indicator for tipc.
 @see #PH_STBIPC_TIPC_ENABLED
*/
#define PH_STBIPC_TIPC_ADDRESS_PREFIX  "tipc://"

/* Maximum length of a handshake message string (excluding NUL byte)
   for use in phStbIpc_ClientHandShake() and phStbIpc_ServerHandShake().
*/
#define PH_STBIPC_HANDSHAKE_MAX_MSG 64U

/** Address is non-conformant.
    @see phStbIpc_ClientCreate()
    @see phStbIpc_ServerCreate()
    @todo Offset all error code with unique component ID (CID).
*/
#define PH_ERR_STBIPC_ADDRESS_FORMAT 1UL

/** System call error.
    Error code should be right-shifted #PH_STBIPC_SYSTEM_CALL_RETURN_VALUE_SHIFT bits
    to obtain system call return value.
    @see PH_STBIPC_SYSTEM_CALL_ERR
*/
#define PH_ERR_STBIPC_SYSTEM_CALL 2UL

/** Handshake error on client side. Message received is incorrect.
    @see phStbIpc_ClientHandShake()
*/
#define PH_ERR_STBIPC_HANDSHAKE_CLIENT 3UL

/** Handshake error on server side. Message received is incorrect.
    @see phStbIpc_ServerHandShake()
*/
#define PH_ERR_STBIPC_HANDSHAKE_SERVER 4UL

/** Handshake message too long.
    @see phStbIpc_ClientHandShake()
    @see phStbIpc_ServerHandShake()
    @see #PH_STBIPC_HANDSHAKE_MAX_MSG
*/
#define PH_ERR_STBIPC_HANDSHAKE_LEN 5UL

/** Protocol of server address is not enabled. */
#define PH_ERR_STBIPC_PROTOCOL_NOT_ENABLED 6UL

/** Read/write error.
    Possibly the socket was closed by the other party.
    @see phStbIpc_ReadExactly()
    @see phStbIpc_WriteExactly()
*/
#define PH_ERR_STBIPC_IO 7UL

/** Name to address translation error.
    @see phStbIpc_ServerCreate()
    @see phStbIpc_ClientCreate()
*/
#define PH_ERR_STBIPC_ADDRESS_LOOKUP 8UL

/** Right-shift needed on error code to obtain system call return value.
   @see #PH_ERR_STBIPC_SYSTEM_CALL
*/
#define PH_STBIPC_SYSTEM_CALL_RETURN_VALUE_SHIFT 16U

/** Error return value in case a phStbIpc API call encounters
    a system call failure. The return value encodes the errno value.
    @see PH_ERR_STBIPC_SYSTEM_CALL
*/
#define PH_STBIPC_SYSTEM_CALL_ERR(errno) \
    ((((tmErrorCode_t)(errno)) << PH_STBIPC_SYSTEM_CALL_RETURN_VALUE_SHIFT) | PH_ERR_STBIPC_SYSTEM_CALL)

/*********************************************************************
* EXPORTED TYPEDEFS                      [p]phStbIpc_<Word>+_t       *
**********************************************************************/

/** Opaque handle to a server. */
typedef struct phStbIpc_Server *pphStbIpc_Server_t;

/** Opaque handle to a connection. 
  In user space (only), this is actually the socket handle. You can use it as a file
  descriptor with select(). However other direct usage as a socket is not supported. */
typedef struct phStbIpc_Connection *pphStbIpc_Connection_t;

/** Indication of big/little endianness. */
typedef enum phStbIpc_Endianness {
    phStbIpc_Endianness_Big = 'B',
    phStbIpc_Endianness_Little = 'L'
} phStbIpc_Endianness_t;

/**************************************************************************
* EXPORTED DATA                     g[k|p|kp|pk|kpk]phStbIpc_<Word>+      *
***************************************************************************/

/****************************************************************************
* EXPORTED FUNCTION PROTOTYPES                    phStbIpc[_<Word>+]        *
*****************************************************************************/


/******************************************************************************/
/******************************************************************************/
/*                               S E R V E R                                  */
/******************************************************************************/
/******************************************************************************/

/** Creates a server for IPC requests.
    After this call phStbIpc_ServerAccept() to get a new connection.

    @param pServerAddress @b IN  Address that the server should listen on.
    Addresses should be registered in file phStbIpc_Services.h .
    @param pServer        @b OUT Handle that represents the server.

    @return TM_OK on success, otherwise an error code.
*/

tmErrorCode_t phStbIpc_ServerCreate(
    char               *pServerAddress,
    pphStbIpc_Server_t *pServer
);

/******************************************************************************/
/** Destroys a server for IPC requests.

    @param server @b IN Handle that represents the server,
                        created by phStbIpc_ServerCreate().

    @return TM_OK on success, otherwise an error code.
*/

tmErrorCode_t phStbIpc_ServerDestroy(
    pphStbIpc_Server_t server
);

/******************************************************************************/
/** Accepts a new connection on a server.
    After this call phStbIpc_Read(), phStbIpc_Write() etc
    can be called on the new connection.

    @param server      @b IN  Server handle as returned from phStbIpc_ServerCreate().
    @param pConnection @b OUT Handle for the connection.

    @return TM_OK on success, otherwise an error code.
*/

tmErrorCode_t phStbIpc_ServerAccept(
    pphStbIpc_Server_t      server,
    pphStbIpc_Connection_t *pConnection
);

/******************************************************************************/
/** Performs a handshake with a client. This means:
    - waiting for a message on the connection;
    - checking the message contains: "client: <message>";
    - sending back a message containing "server: <message>".

    @param server      @b IN  Server handle as returned from phStbIpc_ServerCreate().
    @param connection  @b IN  Handle for the connection to use for the handshake,
                              as returned from phStbIpc_ServerAccept().
                              May be NULL, in which case this function will create a connection temporarily
                              for the handshake.
    @param message     @b IN  Message to use for the handshake.
    @param pEndianness @b OUT Endian of the client.

    @return TM_OK on success, otherwise an error code.
    @see phStbIpc_ClientHandShake()
*/

tmErrorCode_t phStbIpc_ServerHandShake(
    pphStbIpc_Server_t      server,
    pphStbIpc_Connection_t  connection,
    char                   *message,
    phStbIpc_Endianness_t  *pEndianness
);

/******************************************************************************/
/******************************************************************************/
/*                               C L I E N T                                  */
/******************************************************************************/
/******************************************************************************/


/** Creates a client connection for IPC requests.
    After this call phStbIpc_Read(), phStbIpc_Write() etc
    can be called on the new connection.

    @param pServerAddress @b IN  Address that the client should contact
                                 (see phStbIpc_ServerCreate()).
    Addresses are registered in file phStbIpc_Services.h .
    @param pConnection    @b OUT Handle for the connection.

    @return TM_OK on success, otherwise an error code.
*/

tmErrorCode_t phStbIpc_ClientCreate(
    char                   *pServerAddress,
    pphStbIpc_Connection_t *pConnection
);

/******************************************************************************/
/** Performs a handshake with a server. This means:
    - sending a message containing "client: <message>".
    - waiting for a message on the connection;
    - checking the message contains: "server: <message>";

    @param pServerAddress @b IN  Server address (in case of a NULL connection arg.)
    @param connection     @b IN  Handle for the connection to use for the handshake,
                                 as returned from phStbIpc_ClientCreate().
                                 May be NULL, in which case this function will create a connection temporarily
                                 for the handshake using pServerAddress.
    @param pEndianness    @b OUT Endian of the server.

    @return TM_OK on success, otherwise an error code.
    @see phStbIpc_ServerHandShake()
*/

tmErrorCode_t phStbIpc_ClientHandShake(
    char *pServerAddress,
    pphStbIpc_Connection_t connection,
    char *message,
    phStbIpc_Endianness_t *pEndianness
);

/******************************************************************************/
/******************************************************************************/
/*                               C O M M O N                                  */
/******************************************************************************/
/******************************************************************************/


/******************************************************************************/
/** Attempts to read len bytes from a connection.
    Less than len bytes may be read, this not considered an error.
    (for example connection is closed).

    @param connection @b IN  Handle for the connection,
                             as returned from phStbIpc_ServerAccept() or phStbIpc_ClientCreate().
    @param len        @b IN  Number of bytes to read.
    @param pBuffer    @b IN  Buffer to read bytes into.
    @param pLenRead   @b OUT Number of bytes read.

    @return TM_OK on success, otherwise an error code.
*/

tmErrorCode_t phStbIpc_Read(
    pphStbIpc_Connection_t connection,
    size_t   len,
    uint8_t *pBuffer,
    size_t  *pLenRead
);

/******************************************************************************/
/** Reads exactly len bytes from a connection.
    Less than len bytes may be read, if an error condition occurs
    (for example connection is closed).

    @param connection @b IN  Handle for the connection,
                             as returned from phStbIpc_ServerAccept() or phStbIpc_ClientCreate().

    @param pBuffer    @b IN  Buffer to read bytes into.
    @param len        @b IN  Number of bytes to try to read.
    @param pLenRead   @b OUT Number of bytes read.

    @return TM_OK on success, otherwise an error code.
*/

tmErrorCode_t phStbIpc_ReadExactly(
    pphStbIpc_Connection_t connection,
    uint8_t *pBuffer,
    size_t len,
    size_t *pLenRead
);

/******************************************************************************/
/** Attempts to write len bytes to a connection.
    Less than len bytes may be written, if an error condition occurs
    (for example connection is closed).

    @param connection  @b IN  Handle for the connection,
                              as returned from phStbIpc_ServerAccept() or phStbIpc_ClientCreate()..
    @param pBuffer     @b IN  Buffer to read bytes from.
    @param len         @b IN  Number of bytes to write.
    @param pLenWritten @b OUT Number of bytes written.

    @return TM_OK on success, otherwise an error code.
*/

tmErrorCode_t phStbIpc_Write(
    pphStbIpc_Connection_t connection,
    uint8_t *pBuffer,
    size_t len,
    size_t *pLenWritten
);

/******************************************************************************/
/** Writes exactly len bytes to a connection.
    Less than len bytes may be written, if an error condition occurs
    (for example connection is closed).

    @param connection  @b IN  Handle for the connection,
                              as returned from phStbIpc_ServerAccept() or phStbIpc_ClientCreate()..
    @param pBuffer     @b IN  Buffer to read bytes from.
    @param len         @b IN  Number of bytes to write.
    @param pLenWritten @b OUT Number of bytes written.

    @return TM_OK on success, otherwise an error code.
*/

tmErrorCode_t phStbIpc_WriteExactly(
    pphStbIpc_Connection_t connection,
    uint8_t *pBuffer,
    size_t len,
    size_t *pLenWritten
);

/******************************************************************************/
/** Closes (destroys) a connection.

    @param connection @b IN Handle for the connection,
    as returned from phStbIpc_ServerAccept() or phStbIpc_ClientConnCreate()..

    @return TM_OK on success, otherwise an error code.
*/

tmErrorCode_t phStbIpc_Close(
    pphStbIpc_Connection_t connection
);

/******************************************************************************/
#ifdef __cplusplus
}
#endif

#endif /* PHSTBIPC_H      Do not add any thing below this line */
