/*
 *
 *   Copyright (C) 2016 Texas Instruments Incorporated
 *
 *   All rights reserved. Property of Texas Instruments Incorporated.
 *   Restricted rights to use, duplicate or disclose this code are
 *   granted through contract.
 *
 *   The program may not be used without the written permission of
 *   Texas Instruments Incorporated or against the terms and conditions
 *   stipulated in the agreement under which this program has been supplied,
 *   and under no circumstances can it be used with non-TI connectivity device.
 *
 */

#ifndef __SL_OSI_H__
#define __SL_OSI_H__


//#include "datatypes.h"
#define WIN32_LEAN_AND_MEAN //prevents windows including winsock1.h

#include <windows.h>
#include "stdlib.h"



#ifdef  __cplusplus
extern "C" {
#endif


#define OSI_WAIT_FOREVER            0xFFFFFFFF
#define OSI_NO_WAIT                 0

#define CLOCK_RATE                      80000000
#define NUM_OF_CLOCK_CYCLES_IN_uSEC     (CLOCK_RATE / 1000000)

/*******************************************************************************
    Types and Constants
********************************************************************************/

typedef enum
{
  OSI_OK,
  OSI_OPERATION_FAILED,
  OSI_ABORTED,
  OSI_INVALID_PARAMS,
  OSI_MEMORY_ALLOCATION_FAILURE,
  OSI_TIMEOUT
}OsiReturnVal_e;

// TODO: Verify and fix defines
typedef unsigned int GpInputEvent_t;

typedef unsigned int GpPort_e;

typedef unsigned int GpOutput_t;

#define ENTER_CRITICAL_SECTION
#define EXIT_CRITICAL_SECTION

typedef void* OsiMsgQ_t;

/*!
    \brief  type definition for a spawn entry callback

    the spawn mechanism enable to run a function on different context.
    This mechanism allow to transfer the execution context from interrupt context to thread context
    or changing the context from an unknown user thread to general context.
    The implementation of the spawn mechanism depends on the user's system requirements and could varies
    from implementation of serialized execution using single thread to creating thread per call

    \note   The stack size of the execution thread must be at least of TBD bytes!
*/
typedef void (*P_OSI_SPAWN_ENTRY)(void* pValue);

typedef void (*P_OSI_EVENT_HANDLER)(void* pValue);

typedef void (*P_OSI_TASK_ENTRY)(void* pValue);

typedef void (*P_OSI_INTR_ENTRY)(void);

typedef void* OsiTaskHandle;


/*!
    \brief type definition for a time value

    \note   On each porting or platform the type could be whatever is needed - integer, pointer to structure etc.
*/
typedef unsigned int OsiTime_t;


int osi_Sleep(UINT32 Duration);

/*!
    \brief  type definition for a sync object container

    Sync object is object used to synchronize between two threads or thread and interrupt handler.
    One thread is waiting on the object and the other thread send a signal, which then
    release the waiting thread.
    The signal must be able to be sent from interrupt context.
    This object is generally implemented by binary semaphore or events.

    \note   On each porting or platform the type could be whatever is needed - integer, structure etc.
*/
typedef HANDLE OsiSyncObj_t;

/*!
    \brief  type definition for a locking object container

    Locking object are used to protect a resource from mutual accesses of two or more threads.
    The locking object should suppurt reentrant locks by a signal thread.
    This object is generally implemented by mutex semaphore

    \note   On each porting or platform the type could be whatever is needed - integer, structure etc.
*/
typedef HANDLE OsiLockObj_t;

/*!
    \brief  type definition for a spawn entry callback

    the spawn mechanism enable to run a function on different context.
    This mechanism allow to transfer the execution context from interrupt context to thread context
    or changing teh context from an unknown user thread to general context.
    The implementation of the spawn mechanism depends on the user's system reqeuirements and could varies
    from implementation of serialized execution using signle thread to creating thread per call

    \note   The stack size of the execution thread must be at least of TBD bytes!
*/
typedef short (*_SlSpawnEntryFunc_t)(void *);
typedef void (*P_OSI_SPAWN)(void *);

/*!
    \brief  This is the API to create SL spawn task and create the SL queue

    \param  uxPriority      -   task priority

    \return void
    \note
    \warning
*/
OsiReturnVal_e VStartSimpleLinkSpawnTask(unsigned long uxPriority);

/*!
    \brief  This function creates a Task.

    Creates a new Task and add it to the last of tasks that are ready to run

    \param  pEntry  -   pointer to the Task Function
    \param  pcName  -   Task Name String
    \param  usStackDepth    -   Stack Size Stack Size in 32-bit long words
    \param  pvParameters    -   pointer to structure to be passed to the Task Function
    \param  uxPriority  -   Task Priority

    \return upon successful unlocking the function should return 0
            Otherwise, a negative value indicating the error code shall be returned
    \note
    \warning
*/
OsiReturnVal_e osi_TaskCreate(P_OSI_TASK_ENTRY pEntry,const signed char * const pcName,unsigned short usStackDepth,void *pvParameters,unsigned long uxPriority,OsiTaskHandle *pTaskHandle);

/*!
    \brief  This function creates a sync object

    The sync object is used for synchronization between diffrent thread or ISR and
    a thread.

    \param  pSyncObj    -   pointer to the sync object control block

    \return upon successful creation the function should return 0
            Otherwise, a negative value indicating the error code shall be returned
    \note
    \warning
*/
int osi_SyncObjCreate(OsiSyncObj_t* pSyncObj);

/*!
    \brief  This function deletes a sync object

    \param  pSyncObj    -   pointer to the sync object control block

    \return upon successful deletion the function should return 0
            Otherwise, a negative value indicating the error code shall be returned
    \note
    \warning
*/
int osi_SyncObjDelete(OsiSyncObj_t* pSyncObj);

/*!
    \brief      This function generates a sync signal for the object.

    All suspended threads waiting on this sync object are resumed

    \param      pSyncObj    -   pointer to the sync object control block

    \return     upon successful signaling the function should return 0
                Otherwise, a negative value indicating the error code shall be returned
    \note       the function could be called from ISR context
    \warning
*/
int osi_SyncObjSignal(OsiSyncObj_t* pSyncObj);

/*!
    \brief  This function waits for a sync signal of the specific sync object

    \param  pSyncObj    -   pointer to the sync object control block
    \param  Timeout     -   numeric value specifies the maximum number of mSec to
                            stay suspended while waiting for the sync signal
                            Currently, the simple link driver uses only two values:
                                - OSI_WAIT_FOREVER
                                - OSI_NO_WAIT

    \return upon successful reception of the signal within the timeout window return 0
            Otherwise, a negative value indicating the error code shall be returned
    \note
    \warning
*/
int osi_SyncObjWait(OsiSyncObj_t* pSyncObj , OsiTime_t Timeout);

/*!
    \brief  This function clears a sync object

    \param  pSyncObj    -   pointer to the sync object control block

    \return upon successful clearing the function should return 0
            Otherwise, a negative value indicating the error code shall be returned
    \note
    \warning
*/
int osi_SyncObjClear(OsiSyncObj_t* pSyncObj);

/*!
    \brief  This function creates a locking object.

    The locking object is used for protecting a shared resources between different
    threads.

    \param  pLockObj    -   pointer to the locking object control block

    \return upon successful creation the function should return 0
            Otherwise, a negative value indicating the error code shall be returned
    \note
    \warning
*/
int osi_LockObjCreate(OsiLockObj_t* pLockObj, char* pName);

/*!
    \brief  This function deletes a locking object.

    \param  pLockObj    -   pointer to the locking object control block

    \return upon successful deletion the function should return 0
            Otherwise, a negative value indicating the error code shall be returned
    \note
    \warning
*/
int osi_LockObjDelete(OsiLockObj_t* pLockObj);

/*!
    \brief  This function locks a locking object.

    All other threads that call this function before this thread calls
    the osi_LockObjUnlock would be suspended

    \param  pLockObj    -   pointer to the locking object control block
    \param  Timeout     -   numeric value specifies the maximum number of mSec to
                            stay suspended while waiting for the locking object
                            Currently, the simple link driver uses only two values:
                                - OSI_WAIT_FOREVER
                                - OSI_NO_WAIT


    \return upon successful reception of the locking object the function should return 0
            Otherwise, a negative value indicating the error code shall be returned
    \note
    \warning
*/
int osi_LockObjLock(OsiLockObj_t* pLockObj , OsiTime_t Timeout);

/*!
    \brief  This function unlock a locking object.

    \param  pLockObj    -   pointer to the locking object control block

    \return upon successful unlocking the function should return 0
            Otherwise, a negative value indicating the error code shall be returned
    \note
    \warning
*/
int osi_LockObjUnlock(OsiLockObj_t* pLockObj);


/*!
    \brief  This function call the pEntry callback from a different context

    \param  pEntry      -   pointer to the entry callback function

    \param  pValue      -   pointer to any type of memory structure that would be
                            passed to pEntry callback from the execution thread.

    \param  flags       -   execution flags - reserved for future usage

    \return upon successful registration of the spawn the function should return 0
            (the function is not blocked till the end of the execution of the function
            and could be returned before the execution is actually completed)
            Otherwise, a negative value indicating the error code shall be returned
    \note
    \warning
*/


extern int osi_Spawn(_SlSpawnEntryFunc_t pEntry , void* pValue , unsigned long flags);
extern int osi_Execute(_SlSpawnEntryFunc_t pEntry , void* pValue , unsigned long flags);

/*!
    \brief  This function waits for the task to complete.
    \param  - void
    \return - void
    \note
    \warning
*/
void osi_start();

/*!
    \brief  This function returns the values of the system clock in mSec.
                    The system clock is set to 0 during initialization.

        \return system clock in mSec
    \note
    \warning
*/

unsigned long osi_GetTime();


/*******************************************************************************

This function creates a message queue that is typically used for inter thread
communication.

Parameters:

    pMsgQ       -   pointer to the message queue control block
    pMsgQName   -   pointer to the name of the message queue
    MsgSize     -   the size of the message.

            NOTICE: THE MESSGAE SIZE MUST BE SMALLER THAN 16

    MaxMsgs     -   maximum number of messages.

Please note that this function allocates the entire memory required
for the maximum number of messages (MsgSize * MaxMsgs).

********************************************************************************/
OsiReturnVal_e osi_MsgQCreate(OsiMsgQ_t*        pMsgQ ,
                              char*             pMsgQName,
                              unsigned long         MsgSize,
                              unsigned long         MaxMsgs);

/*******************************************************************************

This function writes a message to a specific message queue.

Notice that the message is copied to the queue from the memory area specified
by pMsg pointer.

--------------------------------------------------------------------------------
THIS FUNCTION COULD BE CALLED FROM ISR AS LONG AS THE TIMEOUT PARAMETER IS
SET TO "OSI_NO_WAIT"
--------------------------------------------------------------------------------

Parameters:

    pMsgQ       -   pointer to the message queue control block
    pMsg        -   pointer to the message
    Timeout     -   numeric value specifies the maximum number of mSec to stay
                    suspended while waiting for available space for the message

********************************************************************************/
OsiReturnVal_e osi_MsgQWrite(OsiMsgQ_t* pMsgQ, void* pMsg , OsiTime_t Timeout);

/*******************************************************************************

This function retrieves a message from the specified message queue. The
retrieved message is copied from the queue into the memory area specified by
the pMsg pointer

Parameters:

    pMsgQ       -   pointer to the message queue control block
    pMsg        -   pointer that specify the location where to copy the message
    Timeout     -   numeric value specifies the maximum number of mSec to stay
                    suspended while waiting for a message to be available

********************************************************************************/
OsiReturnVal_e osi_MsgQRead(OsiMsgQ_t* pMsgQ, void* pMsg , OsiTime_t Timeout);

/*******************************************************************************

This function deletes a specific message queue.
All threads suspended waiting for a message from this queue are resumed with
an error return value.

Parameters:

    pMsgQ       -   pointer to the message queue control block

********************************************************************************/
OsiReturnVal_e osi_MsgQDelete(OsiMsgQ_t* pMsgQ);


#ifdef  __cplusplus
}
#endif // __cplusplus

#endif
