/*****************************************************************************
        *
        *    acCanWrite
        *
        *    Purpose:
        *        Write can msg
        *
        *
        *    Arguments:
        *        msgWrite              - managed buffer for write
        *        nWriteCount           - msg number for write
        *        pulNumberofWritten    - real msgs have written
        *
        *    Returns:
        *        =0 SUCCESS; or <0 failure
        *
        *****************************************************************************/

        private int acCanWrite(Can.CanDriver.canmsg_t[] msgWrite, uint nWriteCount, ref uint pulNumberofWritten)
        {
            bool flag;
            int  nRet;
            uint dwErr;

            if (nWriteCount > MaxWriteMsgNumber)
            {
                nWriteCount = MaxWriteMsgNumber;
            }
            pulNumberofWritten = 0;
            flag = CanDriver.WriteFile(hDevice, msgWrite, nWriteCount, out pulNumberofWritten, this.txOvr.memPtr);
            if (flag)
            {
                if (nWriteCount > pulNumberofWritten)
                {
                    nRet = TIME_OUT;                          //Sending data timeout
                }
                else
                {
                    nRet = SUCCESS;                               //Sending data ok
                }
            }
            else
            {
                dwErr = (uint)Marshal.GetLastWin32Error();
                if (dwErr == CanDriver.ERROR_IO_PENDING)
                {
                    if (CanDriver.GetOverlappedResult(hDevice, this.txOvr.memPtr, out pulNumberofWritten, true))
                    {
                        if (nWriteCount > pulNumberofWritten)
                        {
                            nRet = TIME_OUT;                    //Sending data timeout
                        }
                        else
                        {
                            nRet = SUCCESS;                         //Sending data ok
                        }
                    }
                    else
                    {
                        nRet = OPERATION_ERROR;                         //Sending data error
                    }
                }
                else
                {
                    nRet = OPERATION_ERROR;                            //Sending data error
                }
            }
            return(nRet);
        }
        /*****************************************************************************
        *
        *    acWaitEvent
        *
        *    Purpose:
        *        Wait can message or error of the CAN Controller.
        *
        *
        *    Arguments:
        *        msgRead           - managed buffer for read
        *        nReadCount        - msg number that unmanaged buffer can preserve
        *        pulNumberofRead   - real msgs have read
        *        ErrorCode         - return error code when the CAN Controller has error
        *
        *    Returns:
        *        =0 SUCCESS; or <0 failure
        *
        *****************************************************************************/
        private int acWaitEvent(Can.CanDriver.canmsg_t[] msgRead, uint nReadCount, ref uint pulNumberofRead, ref uint ErrorCode)
        {
            int nRet = OPERATION_ERROR;

            ErrorCode       = 0;
            pulNumberofRead = 0;
            if (CanDriver.WaitCommEvent(hDevice, this.events.evPtr, this.events.olPtr) == true)
            {
                EventCode = (uint)Marshal.ReadInt32(this.events.evPtr, 0);
                if ((EventCode & CanDriver.EV_RXCHAR) != 0)
                {
                    nRet = acCanRead(msgRead, nReadCount, ref pulNumberofRead);
                }
                if ((EventCode & CanDriver.EV_ERR) != 0)
                {
                    nRet = OPERATION_ERROR;
                    acClearCommError(ref ErrorCode);
                }
            }
            else
            {
                int err = Marshal.GetLastWin32Error();
                if (CanDriver.ERROR_IO_PENDING == err)
                {
                    if (CanDriver.GetOverlappedResult(hDevice, this.eventOvr.memPtr, out pulNumberofRead, true))
                    {
                        EventCode = (uint)Marshal.ReadInt32(this.events.evPtr, 0);
                        if ((EventCode & CanDriver.EV_RXCHAR) != 0)
                        {
                            nRet = acCanRead(msgRead, nReadCount, ref pulNumberofRead);
                        }
                        if ((EventCode & CanDriver.EV_ERR) != 0)
                        {
                            nRet = OPERATION_ERROR;
                            acClearCommError(ref ErrorCode);
                        }
                    }
                    else
                    {
                        nRet = OPERATION_ERROR;
                    }
                }
                else
                {
                    nRet = OPERATION_ERROR;
                }
            }

            return(nRet);
        }
        /*****************************************************************************
        *
        *    acCanRead
        *
        *    Purpose:
        *        Read can message.
        *
        *
        *    Arguments:
        *        msgRead           - managed buffer for read
        *        nReadCount        - msg number that unmanaged buffer can preserve
        *        pulNumberofRead   - real msgs have read
        *
        *    Returns:
        *        =0 SUCCESS; or <0 failure
        *
        *****************************************************************************/
        private int acCanRead(Can.CanDriver.canmsg_t[] msgRead, uint nReadCount, ref uint pulNumberofRead)
        {
            bool flag;
            int  nRet;
            uint i;

            if (nReadCount > MaxReadMsgNumber)
            {
                nReadCount = MaxReadMsgNumber;
            }
            pulNumberofRead = 0;
            flag            = CanDriver.ReadFile(hDevice, orgReadBuf, nReadCount, out pulNumberofRead, this.rxOvr.memPtr);
            if (flag)
            {
                if (pulNumberofRead == 0)
                {
                    nRet = TIME_OUT;
                }
                else
                {
                    for (i = 0; i < pulNumberofRead; i++)
                    {
                        if (OS_TYPE == 8)
                        {
                            msgRead[i] = (CanDriver.canmsg_t)(Marshal.PtrToStructure(new IntPtr(orgReadBuf.ToInt64() + CanDriver.CAN_MSG_LENGTH * i), typeof(CanDriver.canmsg_t)));
                        }
                        else
                        {
                            msgRead[i] = (CanDriver.canmsg_t)(Marshal.PtrToStructure(new IntPtr(orgReadBuf.ToInt32() + CanDriver.CAN_MSG_LENGTH * i), typeof(CanDriver.canmsg_t)));
                        }
                    }
                    nRet = SUCCESS;
                }
            }
            else
            {
                if (CanDriver.GetOverlappedResult(hDevice, this.rxOvr.memPtr, out pulNumberofRead, true))
                {
                    if (pulNumberofRead == 0)
                    {
                        nRet = TIME_OUT;                               //Package receiving timeout
                    }
                    else
                    {
                        for (i = 0; i < pulNumberofRead; i++)
                        {
                            if (OS_TYPE == 8)
                            {
                                msgRead[i] = (CanDriver.canmsg_t)(Marshal.PtrToStructure(new IntPtr(orgReadBuf.ToInt64() + CanDriver.CAN_MSG_LENGTH * i), typeof(CanDriver.canmsg_t)));
                            }
                            else
                            {
                                msgRead[i] = (CanDriver.canmsg_t)(Marshal.PtrToStructure(new IntPtr(orgReadBuf.ToInt32() + CanDriver.CAN_MSG_LENGTH * i), typeof(CanDriver.canmsg_t)));
                            }
                        }
                        nRet = SUCCESS;
                    }
                }
                else
                {
                    nRet = OPERATION_ERROR;                                    //Package receiving error
                }
            }
            return(nRet);
        }