
#define SIO_C

/* ------------- */
/* - Includes. - */
/* ------------- */

#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <stdlib.h>
#include "sio.h"
#include "mlMouse.h"

/* ------------ */
/* - Globals. - */
/* ------------ */

SIO_Vars_t sioVars;
#define SIO_DataMutex(x) x

SIO_DataMutex(
HANDLE mutex;
)

HANDLE g_hSIOThread = NULL;

DWORD SIOThread(LPVOID lpvoid);

extern tQuatPacket qData;

/* -------------- */
/* - Functions. - */
/* -------------- */
/**********************************************************************/
/*                                                                    */
/* Function Name: getQuatData                                         */
/*                                                                    */
/*   Description: Parse rx data buffer to get Quaternion              */
/*                                                                    */
/*    Parameters: qData - parsed Quaternion data                      */
/*                                                                    */
/*       Returns: Return code.                                        */
/*                                                                    */
/**********************************************************************/
int getQuatData(tQuatPacket *qData)
{

    int retCode;
    int i;

    unsigned char rxBuffer[SIO_RBUFF_SIZE];

    retCode = SIOReadBuffer(SIO_RBUFF_SIZE, (unsigned char) 1, rxBuffer);
	
    if ((rxBuffer[1] != 2) && (rxBuffer[1] != 10))
	return retCode;

#if 0
    for(int i=0; i<42; i++)
    {
        printf("0x%02X ", (unsigned char)rxBuffer[i]);
    }
    printf("\n");
#endif

    if (rxBuffer[1] == 2)
    {
	//Parse MPU Data
	qData->mlQuaternion[0] = (long) ((((unsigned long) rxBuffer[2]) << 8)
					 + ((unsigned long) rxBuffer[3]));

	qData->mlQuaternion[1] = (long) ((((unsigned long) rxBuffer[4]) << 8)
					 + ((unsigned long) rxBuffer[5]));

	qData->mlQuaternion[2] = (long) ((((unsigned long) rxBuffer[6]) << 8)
					 + ((unsigned long) rxBuffer[7]));

	qData->mlQuaternion[3] = (long) ((((unsigned long) rxBuffer[8]) << 8)
					 + ((unsigned long) rxBuffer[9]));
	qData->button = rxBuffer[10];
	qData->packetCnt = (unsigned int)rxBuffer[11];

    }
    else if (rxBuffer[1] == 10)
    {
	//Parse MPU Data
	qData->mlQuaternion[0] = (long) ((((unsigned long) rxBuffer[32]) << 8)
					 + ((unsigned long) rxBuffer[33]));

	qData->mlQuaternion[1] = (long) ((((unsigned long) rxBuffer[34]) << 8)
					 + ((unsigned long) rxBuffer[35]));

	qData->mlQuaternion[2] = (long) ((((unsigned long) rxBuffer[36]) << 8)
					 + ((unsigned long) rxBuffer[37]));

	qData->mlQuaternion[3] = (long) ((((unsigned long) rxBuffer[38]) << 8)
					 + ((unsigned long) rxBuffer[39]));

	qData->button = 0;
	qData->packetCnt = (unsigned int)((((unsigned int)rxBuffer[2]) << 8)
					  + ((unsigned int)rxBuffer[3]));
	qData->motion = rxBuffer[4];
    }

    for( i = 0; i < 4; i++ )
    {
        if( qData->mlQuaternion[i] > 32767 )
        {
            qData->mlQuaternion[i] -= 65536;
        }
        qData->quat[i] = ((float) qData->mlQuaternion[i]) / 16384.0f;
    }


#if 0
    for(int i=0; i<4; i++)
    {
        printf("0x%08X ", qData->mlQuaternion[i]);
    }
    printf("\n");
#endif

    return retCode;
}
/**********************************************************************/
/*                                                                    */
/* Function Name: SIOSetCom                                           */
/*                                                                    */
/*   Description: SIO Set Com.                                        */
/*                                                                    */
/*    Parameters: nPort  - port number                                */
/*                dwBaud - baud                                       */
/*                                                                    */
/*       Returns: nPort                                               */
/*                                                                    */
/**********************************************************************/
unsigned short SIOSetCom(unsigned short nPort, unsigned int dwBaud)
{
    if( nPort && dwBaud )
    {
        sioVars.port = nPort;
        sioVars.baud = dwBaud;
    }

    return nPort;
}

/**********************************************************************/
/*                                                                    */
/* Function Name: SIOInit                                             */
/*                                                                    */
/*   Description: SIO Init.                                           */
/*                                                                    */
/*    Parameters: nPort  - port number                                */
/*                dwBaud - baud                                       */
/*                                                                    */
/*       Returns: Return code.                                        */
/*                                                                    */
/**********************************************************************/
int SIOInit(int nPort, DWORD dwBaud)
{
    DCB PortDCB;
    COMMTIMEOUTS CommTimeouts;
    DWORD dwError;
    char comStr[12] =
    {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    };
    TCHAR g_pUartPortName[16];

    _stprintf_s(g_pUartPortName,
                sizeof(g_pUartPortName)/sizeof(g_pUartPortName[0]),
                _T("\\\\.\\COM%d"),
                nPort);

    sioVars.hDevice = CreateFile(g_pUartPortName, GENERIC_READ | GENERIC_WRITE,
                                 0, NULL, OPEN_EXISTING, 0, NULL);
    // If it fails to open the port, return FALSE.
    if( INVALID_HANDLE_VALUE == sioVars.hDevice )
    {
        // Could not open the port.
        MessageBox(NULL, TEXT("Unable to open the port"), TEXT("Error"), MB_OK);
        dwError = GetLastError();
        return SIO_ERROR;
    }

    PortDCB.DCBlength = sizeof(DCB);

    // Get the default port setting information.
    GetCommState(sioVars.hDevice, &PortDCB);

    // Change the DCB structure settings.

    PortDCB.BaudRate = dwBaud; // Current baud
    PortDCB.fBinary = TRUE; // Binary mode; no EOF check
    PortDCB.fParity = FALSE; // Enable parity checking
    PortDCB.fOutxCtsFlow = FALSE; // No CTS output flow control
    PortDCB.fOutxDsrFlow = FALSE; // No DSR output flow control
    PortDCB.fDtrControl = DTR_CONTROL_DISABLE;
    // DTR flow control type
    PortDCB.fDsrSensitivity = FALSE; // DSR sensitivity
    PortDCB.fTXContinueOnXoff = TRUE; // XOFF continues Tx
    PortDCB.fOutX = FALSE; // No XON/XOFF out flow control
    PortDCB.fInX = FALSE; // No XON/XOFF in flow control
    PortDCB.fErrorChar = FALSE; // Disable error replacement
    PortDCB.fNull = FALSE; // Disable null stripping
    PortDCB.fRtsControl = RTS_CONTROL_DISABLE;
    // RTS flow control
    PortDCB.fAbortOnError = FALSE; // Do not abort reads/writes on
    // error
    PortDCB.ByteSize = 8; // Number of bits/byte, 4-8
    PortDCB.Parity = NOPARITY; // 0-4=no,odd,even,mark,space
    PortDCB.StopBits = ONESTOPBIT; // 0,1,2 = 1, 1.5, 2

    // Configure the port according to the specifications of the DCB
    // structure.
    if( FALSE == SetCommState(sioVars.hDevice, &PortDCB) )
    {
        // Could not create the read thread.
        MessageBox(NULL, TEXT("Unable to configure the serial port"),
                   TEXT("Error"), MB_OK);
        dwError = GetLastError();
        return SIO_ERROR;
    }

    // Retrieve the time-out parameters for all read and write operations
    // on the port.
    GetCommTimeouts(sioVars.hDevice, &CommTimeouts);

    // Change the COMMTIMEOUTS structure settings.
    CommTimeouts.ReadIntervalTimeout = MAXDWORD;
    CommTimeouts.ReadTotalTimeoutMultiplier = 0;
    CommTimeouts.ReadTotalTimeoutConstant = 0;
    CommTimeouts.WriteTotalTimeoutMultiplier = 10;
    CommTimeouts.WriteTotalTimeoutConstant = 1000;

    // Set the time-out parameters for all read and write operations
    // on the port.
    if( FALSE == SetCommTimeouts(sioVars.hDevice, &CommTimeouts) )
    {
        // Could not create the read thread.
        MessageBox(NULL, TEXT("Unable to set the time-out parameters"),
                   TEXT("Error"), MB_OK);
        dwError = GetLastError();
        return SIO_ERROR;
    }

    return SIO_SUCCESS;
}


/**********************************************************************/
/*                                                                    */
/* Function Name: SIOUartGetQStatus                                   */
/*                                                                    */
/*   Description: SIO Get Uart Queue Status.                          */
/*                                                                    */
/*    Parameters: None.                                               */
/*                                                                    */
/*       Returns: cbInQue value.                                      */
/*                                                                    */
/**********************************************************************/
/**
 * @brief SIO Get Uart Queue Status
 */
unsigned long SIOUartGetQStatus(void)
{
    COMSTAT stat;
    DWORD dwErrors;
    if( !ClearCommError(sioVars.hDevice, &dwErrors, &stat) )
    {
        //TRACE(_T("Failed in call to ClearCommError\n"));
        //AfxThrowSerialException();
    }

    return (unsigned long) (stat.cbInQue);
}

/**********************************************************************/
/*                                                                    */
/* Function Name: SIOOpen                                             */
/*                                                                    */
/*   Description: SIO Open Function.                                  */
/*                                                                    */
/*    Parameters: autoProcess - Non-Zero:process data in thrread      */
/*                createThread - create thread to receive data        */
/*                                                                    */
/*       Returns: Return code.                                        */
/*                                                                    */
/**********************************************************************/
int SIOOpen(unsigned char autoProcess, unsigned char createThread)
{

    LPCWSTR lpszDevKey = TEXT("SIO");
    DWORD dwThreadID, dwError;
	char writedata[1];
    if( SIOInit(sioVars.port, sioVars.baud) == SIO_ERROR )
    {
        return SIO_ERROR;
    }

    sioVars.autoProcess = autoProcess;

    /* Check if buffer size has been set, else use default of the max size. */
    if( !sioVars.rBuffMax )
    {
        SIOSetBufferSize(SIO_RBUFF_MAX);
    }

#if SIO_RBUFF_DYNAMIC
    /* Allocate space for the buffer. */
    sioVars.rBuff = MLOSMalloc(sioVars.rBuffNumBytes);
    //	printf("sio.c module - sioVars.rBuff = %x\r\n", sioVars.rBuff);
#endif

    if( createThread )
    {

        SIO_DataMutex(SIOCreateMutex();)

        sioVars.runThread = 1;

        // Create SIO thread
        g_hSIOThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SIOThread,
                                    0, 0, &dwThreadID);
        if( g_hSIOThread == NULL )
        {
            dwError = GetLastError();
            printf("Can't create SIO thread (ERR1): %x\r\n", dwError);
            exit(SIO_ERROR);
        }

        SetThreadPriority((HANDLE) g_hSIOThread, (int) THREAD_PRIORITY_HIGHEST);
    }
	
    writedata[0] = 't';
    SIOWrite(writedata, 1);
    return SIO_SUCCESS;
}

/**********************************************************************/
/*                                                                    */
/* Function Name: SIOClose                                            */
/*                                                                    */
/*   Description: SIO Close Function.                                 */
/*                                                                    */
/*    Parameters: None.                                               */
/*                                                                    */
/*       Returns: Return code.                                        */
/*                                                                    */
/**********************************************************************/
int SIOClose(void)
{

    if( sioVars.runThread )
    {

        sioVars.runThread = 0;
        Sleep(25);

        CloseHandle(g_hSIOThread);

        SIO_DataMutex(CloseHandle(mutex);)

    }

    CloseHandle(sioVars.hDevice);

#if SIO_RBUFF_DYNAMIC
    /* Deallocate buffer space. */
    MLOSFree(sioVars.rBuff);
#endif

    return SIO_SUCCESS;

}

/**********************************************************************/
/*                                                                    */
/* Function Name: SIORead                                             */
/*                                                                    */
/*   Description: SIO Read Function.                                  */
/*                                                                    */
/*    Parameters: None.                                               */
/*                                                                    */
/*       Returns: Return code.                                        */
/*                                                                    */
/**********************************************************************/
/**
 * @brief SIORead
 */
int SIORead(void)
{

    LPCWSTR lpszDevKey = TEXT("SIO");

    BOOL boolRetCode;
    unsigned char *readBuffer;
    DWORD nNumberOfBytesToRead;
    DWORD nNumberOfBytesRead;

    //	DWORD         cnt;

    // =============================================
    // SIO Read
    // =============================================

    nNumberOfBytesToRead = 1; // Size of readBuffer

    readBuffer = sioVars.readBuffer;

    boolRetCode = ReadFile(sioVars.hDevice, // HANDLE hFile,
                           sioVars.readBuffer, // LPVOID lpBuffer,
                           nNumberOfBytesToRead, // DWORD nNumberOfBytesToRead,
                           &nNumberOfBytesRead, // LPDWORD lpNumberOfBytesRead,
                           NULL // LPOVERLAPPED lpOverlapped
                    );

    if( !boolRetCode )
    {
        printf("Can't read SIO driver (ERR2)\r\n");
        sioVars.readBuffer[0] = 'E'; // ERROR...
        return SIO_ERROR;
    }

    if( sioVars.readBuffer[0] != '$' )
    {
        return SIO_ERROR;
    }
    nNumberOfBytesToRead = SIO_RBUFF_SIZE - 1;

    boolRetCode = ReadFile(sioVars.hDevice, // HANDLE hFile,
                           &(sioVars.readBuffer[1]), // LPVOID lpBuffer,
                           nNumberOfBytesToRead, // DWORD nNumberOfBytesToRead,
                           &nNumberOfBytesRead, // LPDWORD lpNumberOfBytesRead,
                           NULL // LPOVERLAPPED lpOverlapped
                    );

    if( !boolRetCode )
    {
        printf("Can't read SIO driver (ERR3)\r\n");
        sioVars.readBuffer[0] = 'E'; // ERROR...
        return SIO_ERROR;
    }

    return SIO_SUCCESS;

}

/**********************************************************************/
/*                                                                    */
/* Function Name: SIOWrite                                            */
/*                                                                    */
/*   Description: SIO Write Function.                                 */
/*                                                                    */
/*    Parameters: None.                                               */
/*                                                                    */
/*       Returns: Return code.                                        */
/*                                                                    */
/**********************************************************************/
/**
 * @brief SIOWrite
 */
int SIOWrite(char *data, int len)
{

    LPCWSTR lpszDevKey = TEXT("SIO");

    BOOL boolRetCode;
    unsigned char *writeBuffer;

    DWORD nNumberOfBytesToRead;
    DWORD nNumberOfBytesRead;

    // =============================================
    // SIO Write Test.................
    // =============================================

	nNumberOfBytesToRead = len; // Size of write buffer
    writeBuffer = sioVars.writeBuffer;

    memcpy(writeBuffer, data, len);
	//writeBuffer[0] = "t"; // Write Cmd
    
    boolRetCode = WriteFile(sioVars.hDevice, // HANDLE hFile,
                            sioVars.writeBuffer, // LPVOID lpBuffer,
                            nNumberOfBytesToRead, // DWORD nNumberOfBytesToRead,
                            &nNumberOfBytesRead, // LPDWORD lpNumberOfBytesRead,
                            NULL // LPOVERLAPPED lpOverlapped
                    );

    if( !boolRetCode )
    {
        printf("Can't write SIO driver (ERR4)\r\n");
    }

    return SIO_SUCCESS;

}

/**********************************************************************/
/*                                                                    */
/* Function Name: SIOSetBufferSize                                    */
/*                                                                    */
/*   Description: Set SIO Buffer Size Function.                       */
/*                                                                    */
/*    Parameters: bufferSize - SIO buffer size.                       */
/*                                                                    */
/*       Returns: Return code.                                        */
/*                                                                    */
/**********************************************************************/
/**
 * @brief SIOSetBufferSize
 */
int SIOSetBufferSize(unsigned short bufferSize)
{

    /* Set SIO buffer size. */
    if( (bufferSize >= 1) && (bufferSize <= SIO_RBUFF_MAX) )
    {
        sioVars.rBuffMax = bufferSize;
    }
    else
    {
        sioVars.rBuffMax = SIO_RBUFF_MAX;
    }

    /* Calculate size in bytes. */
    sioVars.rBuffNumBytes = sioVars.rBuffMax * (unsigned short) SIO_RBUFF_SIZE;

    //	printf("sio.c module - sioVars.rBuffNumBytes = %x\r\n", sioVars.rBuffNumBytes);

    return SIO_SUCCESS;
}

/**********************************************************************/
/*                                                                    */
/* Function Name: SIOUpdateBuffer                                     */
/*                                                                    */
/*   Description: SIO Update Buffer Function.                         */
/*                                                                    */
/*    Parameters: None.                                               */
/*                                                                    */
/*       Returns: Return code.                                        */
/*                                                                    */
/**********************************************************************/
/**
 * @brief SIOUpdateBuffer
 */
int SIOUpdateBuffer(void)
{
    U16 index;
#if SIO_RBUFF_DYNAMIC
    U16 rBuffIndex;
#endif

    if( sioVars.readBuffer[0] == '$' )
    {

        // Mutex Lock
        SIO_DataMutex(SIOLockMutex();)

        // Buffer the data.
        for( index = 0; index < SIO_RBUFF_SIZE; ++index )
        {

#if !SIO_RBUFF_DYNAMIC
            sioVars.rBuff[sioVars.rBuffWIndex][index] = sioVars.readBuffer[index];
#else
            rBuffIndex = (sioVars.rBuffWIndex * (U16)SIO_RBUFF_SIZE) + index;
            sioVars.rBuff[rBuffIndex] = sioVars.readBuffer[index];
#endif

        }

        // Adjust the read and write index.
        ++sioVars.rBuffWIndex;
        if( sioVars.rBuffWIndex >= sioVars.rBuffMax )
        {
            sioVars.rBuffWIndex = 0;
        }
        if( sioVars.rBuffWIndex == sioVars.rBuffRIndex )
        {

            ++sioVars.rBuffRIndex;
            if( sioVars.rBuffRIndex >= sioVars.rBuffMax )
            {
                sioVars.rBuffRIndex = 0;
            }

        }

        // Mutex Unlock
        SIO_DataMutex(SIOUnlockMutex();)
    }


    return SIO_SUCCESS;
}

/**********************************************************************/
/*                                                                    */
/* Function Name: SIOHandler                                          */
/*                                                                    */
/*   Description: SIO Handler Function.                               */
/*                                                                    */
/*    Parameters: None.                                               */
/*                                                                    */
/*       Returns: Return code.                                        */
/*                                                                    */
/**********************************************************************/
int SIOHandler(void)
{

    int byteCnt;
    int loopCnt;

    /* Read SIO data. */
    byteCnt = SIOUartGetQStatus();
    if( byteCnt > 2048 )
        printf("******** serial buffer has %d bytes\n", byteCnt);

    loopCnt = byteCnt / SIO_RBUFF_SIZE;

    while( loopCnt )
    {
        /* SIO Read. */
        SIORead();

        /* Update Buffer. */
        SIOUpdateBuffer();

        --loopCnt;
    }

    /* Exit. */
    return SIO_SUCCESS;
}
/**********************************************************************/
/*                                                                    */
/* Function Name: SIOThread                                           */
/*                                                                    */
/*   Description: SIO Thread.                                         */
/*                                                                    */
/*    Parameters:                                                     */
/*                                                                    */
/*       Returns:                                                     */
/*                                                                    */
/**********************************************************************/
/**
 * @brief SIOThread
 */
DWORD SIOThread(LPVOID lpvoid)
{
    unsigned short pktsInBuffer;
    int i;
    static float Quaternion[4];

    while( sioVars.runThread )
    {
        SIOHandler();

        if( sioVars.autoProcess )
        {

            //Process data in buffer
            SIOPktsInBuffer(&pktsInBuffer);

            for( i = 0; i < pktsInBuffer; i++ )
            {
                getQuatData(&qData);
                IMUgetQuaternion(&qData);
//                Sleep(1);
//                Sleep(4);
            }
			Sleep(2);
        }
    }

    return SIO_SUCCESS;
}

/**********************************************************************/
/*                                                                    */
/* Function Name: SIOReadBuffer                                       */
/*                                                                    */
/*   Description: SIO Read Buffer                                     */
/*                                                                    */
/*    Parameters: cnt - read data size                                */
/*                buffermode - Zero: read direct                      */
/*                             Non-Zero: read under lock              */
/*                rBuff - pointer of read buffer                      */
/*                                                                    */
/*       Returns: Return code.                                        */
/*                                                                    */
/*       Returns:                                                     */
/*                                                                    */
/**********************************************************************/
int SIOReadBuffer(unsigned short cnt, unsigned char bufferMode,
                  unsigned char *rBuff)
{

    int retCode;
    U16 index;
#if SIO_RBUFF_DYNAMIC
    U16 rBuffIndex;
#endif

    retCode = SIO_SUCCESS;

    if( !bufferMode )
    {

        // Get the data.
        for( index = 0; index < cnt; ++index )
        {
            rBuff[index] = sioVars.readBuffer[index];
        }

        return retCode;

    }

    // Mutex Lock.
    SIO_DataMutex(SIOLockMutex();)

    // Get data from buffer.
    if( sioVars.rBuffWIndex != sioVars.rBuffRIndex )
    {

        // Get the data from the buffer.
        for( index = 0; index < cnt; ++index )
        {

#if !SIO_RBUFF_DYNAMIC
            rBuff[index] = sioVars.rBuff[sioVars.rBuffRIndex][index];
#else
            rBuffIndex = (sioVars.rBuffRIndex * (U16)SIO_RBUFF_SIZE) + index;
            rBuff[index] = sioVars.rBuff[rBuffIndex];
#endif

        }

        // Adjust the read index.
        ++sioVars.rBuffRIndex;
        if( sioVars.rBuffRIndex >= sioVars.rBuffMax )
        {
            sioVars.rBuffRIndex = 0;
        }

        if( rBuff[0] != '$' )
        {
            retCode = SIO_ERROR;
        }

    }
    else
    {
        retCode = SIO_ERROR;
    }

    // Mutex Unlock
    SIO_DataMutex(SIOUnlockMutex();)

    return retCode;
}

/**********************************************************************/
/*                                                                    */
/* Function Name: SIOEmptyBuffer                                      */
/*                                                                    */
/*   Description: SIO EmptyBuffer                                     */
/*                                                                    */
/*    Parameters:                                                     */
/*                                                                    */
/*       Returns:                                                     */
/*                                                                    */
/**********************************************************************/
/**
 * @brief SIOEmptyBuffer
 */
int SIOEmptyBuffer(void)
{
    // Mutex Lock.
    SIO_DataMutex(SIOLockMutex();)

    // Empty the buffer.
    if( sioVars.rBuffWIndex != sioVars.rBuffRIndex )
    {
        sioVars.rBuffWIndex = 0;
        sioVars.rBuffRIndex = 0;
    }

    // Mutex Unlock
    SIO_DataMutex(SIOUnlockMutex();)

    return SIO_SUCCESS;
}

/**********************************************************************/
/*                                                                    */
/* Function Name: SIOPktsInBuffer                                     */
/*                                                                    */
/*   Description: SIOPktsInBuffer                                     */
/*                                                                    */
/*    Parameters: pktsInBuffer - pointer to store packet num          */
/*                                                                    */
/*       Returns:                                                     */
/*                                                                    */
/**********************************************************************/
int SIOPktsInBuffer(unsigned short *pktsInBuffer)
{

    if( !sioVars.runThread )
    {

        *pktsInBuffer = 0;
        return SIO_SUCCESS;

    }

    // Mutex Lock.
    SIO_DataMutex(SIOLockMutex();)

    // Get number of packets in buffer.
    if( sioVars.rBuffWIndex != sioVars.rBuffRIndex )
    {

        if( sioVars.rBuffWIndex > sioVars.rBuffRIndex )
        {

            *pktsInBuffer = (sioVars.rBuffWIndex - 1) - sioVars.rBuffRIndex;

        }
        else
        {

            *pktsInBuffer = (sioVars.rBuffWIndex + sioVars.rBuffMax)
                            - sioVars.rBuffRIndex;
        }

    }
    else
    {

        *pktsInBuffer = 0;
    }


    // Mutex Unlock
    SIO_DataMutex(SIOUnlockMutex();)

    return SIO_SUCCESS;
}

/**********************************************************************/
/*                                                                    */
/* Function Name: SIOCreateMutex                                      */
/*                                                                    */
/*   Description: SIO mutex create function.                          */
/*                                                                    */
/*    Parameters:                                                     */
/*                                                                    */
/*       Returns:                                                     */
/*                                                                    */
/**********************************************************************/
/**
 * @brief SIOCreateMutex
 */
int SIOCreateMutex(void)
{

    SIO_DataMutex(
        mutex = CreateMutex(0,FALSE,0);
    )

    return SIO_SUCCESS;
}

/**********************************************************************/
/*                                                                    */
/* Function Name: SIOLockMutex                                        */
/*                                                                    */
/*   Description: SIO mutex lock function                             */
/*                                                                    */
/*    Parameters:                                                     */
/*                                                                    */
/*       Returns:                                                     */
/*                                                                    */
/**********************************************************************/
/**
 * @brief SIOLockMutex
 */
int SIOLockMutex(void)
{

    DWORD rc;

    SIO_DataMutex(
        // Mutex Lock.
        if ((rc = WaitForSingleObject(mutex, INFINITE)) == WAIT_FAILED)
        {
            //   return RC_LOCK_ERROR ;
        }
    )

    return SIO_SUCCESS;
}

/**********************************************************************/
/*                                                                    */
/* Function Name: SIOUnlockMutex                                      */
/*                                                                    */
/*   Description: SIO mutex unlock function.                          */
/*                                                                    */
/*    Parameters:                                                     */
/*                                                                    */
/*       Returns:                                                     */
/*                                                                    */
/**********************************************************************/
/**
 * @brief SIOMutexUnlock
 */
int SIOUnlockMutex(void)
{

    SIO_DataMutex(
        // Mutex Unlock
        if (!ReleaseMutex(mutex))
        {
            //  rc = GetLastError();
            //  return RC_UNLOCK_ERROR;
        }
    )

    return SIO_SUCCESS;
}


/********************/
/**\}*//* defgroup */
/********************/
