예제 #1
0
        public J2534Err WriteMsgs(int channelId, ref PassThruMsg msg, ref int numMsgs, int timeout)
        {
            UnsafePassThruMsg uMsg = ConvertPassThruMsg(msg);

            // TODO: change function to accept a list? of PassThruMsg
            return((J2534Err)m_wrapper.WriteMsgs(channelId, ref uMsg, ref numMsgs, timeout));
        }
예제 #2
0
        public static IntPtr ToIntPtr(this PassThruMsg msg)
        {
            IntPtr msgPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(PassThruMsg)));

            Marshal.StructureToPtr(msg, msgPtr, true);
            return(msgPtr);
        }
예제 #3
0
        public J2534Err FastInit(int channelId, PassThruMsg txMsg, ref PassThruMsg rxMsg)
        {
            IntPtr      input  = IntPtr.Zero;
            IntPtr      output = IntPtr.Zero;
            PassThruMsg uRxMsg = new PassThruMsg();

            Marshal.StructureToPtr(txMsg, input, true);
            Marshal.StructureToPtr(uRxMsg, output, true);

            J2534Err returnValue = (J2534Err)m_wrapper.Ioctl(channelId, (int)Ioctl.FAST_INIT, input, output);

            if (returnValue == J2534Err.STATUS_NOERROR)
            {
                Marshal.PtrToStructure(output, rxMsg);
            }

            return(returnValue);
        }
예제 #4
0
        private static PassThruMsg ConvertPassThruMsg(UnsafePassThruMsg uMsg)
        {
            PassThruMsg msg = new PassThruMsg();

            msg.ProtocolID     = (ProtocolID)uMsg.ProtocolID;
            msg.RxStatus       = (RxStatus)uMsg.RxStatus;
            msg.Timestamp      = uMsg.Timestamp;
            msg.TxFlags        = (TxFlag)uMsg.TxFlags;
            msg.ExtraDataIndex = uMsg.ExtraDataIndex;
            msg.Data           = new byte[uMsg.DataSize];
            unsafe
            {
                for (int i = 0; i < uMsg.DataSize; i++)
                {
                    msg.Data[i] = uMsg.Data[i];
                }
            }
            return(msg);
        }
예제 #5
0
        private UnsafePassThruMsg ConvertPassThruMsg(PassThruMsg msg)
        {
            UnsafePassThruMsg uMsg = new UnsafePassThruMsg();

            uMsg.ProtocolID     = (int)msg.ProtocolID;
            uMsg.RxStatus       = (int)msg.RxStatus;
            uMsg.Timestamp      = msg.Timestamp;
            uMsg.TxFlags        = (int)msg.TxFlags;
            uMsg.ExtraDataIndex = msg.ExtraDataIndex;
            uMsg.DataSize       = msg.Data.Length;
            unsafe
            {
                for (int i = 0; i < msg.Data.Length; i++)
                {
                    uMsg.Data[i] = msg.Data[i];
                }
            }

            return(uMsg);
        }
예제 #6
0
        public J2534Err StartMsgFilter
        (
            int channelid,
            FilterType filterType,
            ref PassThruMsg maskMsg,
            ref PassThruMsg patternMsg,
            ref int filterId
        )
        {
            int nada = 0;
            UnsafePassThruMsg uMaskMsg    = ConvertPassThruMsg(maskMsg);
            UnsafePassThruMsg uPatternMsg = ConvertPassThruMsg(patternMsg);

            return((J2534Err)m_wrapper.StartPassBlockMsgFilter
                   (
                       channelid,
                       (int)filterType,
                       ref uMaskMsg,
                       ref uPatternMsg,
                       nada,
                       ref filterId
                   ));
        }
예제 #7
0
        public J2534Err StartMsgFilter
        (
            int channelid,
            FilterType filterType,
            ref PassThruMsg maskMsg,
            ref PassThruMsg patternMsg,
            ref PassThruMsg flowControlMsg,
            ref int filterId
        )
        {
            UnsafePassThruMsg uMaskMsg        = ConvertPassThruMsg(maskMsg);
            UnsafePassThruMsg uPatternMsg     = ConvertPassThruMsg(patternMsg);
            UnsafePassThruMsg uFlowControlMsg = ConvertPassThruMsg(flowControlMsg);

            return((J2534Err)m_wrapper.StartMsgFilter
                   (
                       channelid,
                       (int)filterType,
                       ref uMaskMsg,
                       ref uPatternMsg,
                       ref uFlowControlMsg,
                       ref filterId
                   ));
        }
예제 #8
0
파일: Form1.cs 프로젝트: GeorgyPorgy/VMPT
        /*
         * 
         *  Example 2:
         *      Use the J2534 protocol to send and receive a message (w/o error checking)
         * 
         */
        private void SendReceiveNoErrorChecking(object sender, EventArgs e)
        {
            J2534 passThru = new J2534();

            // Find all of the installed J2534 passthru devices
            List<J2534Device> availableJ2534Devices = J2534Detect.ListDevices();

            // We will always choose the first J2534 device in the list, if there are multiple devices
            //   installed, you should do something more intelligent.
            passThru.LoadLibrary(availableJ2534Devices[0]);

            // Attempt to open a communication link with the pass thru device
            int deviceId = 0;
            passThru.Open(ref deviceId);

            // Open a new channel configured for ISO15765 (CAN)
            int channelId = 0;
            passThru.Connect(deviceId, ProtocolID.ISO15765, ConnectFlag.NONE, BaudRate.ISO15765, ref channelId);

            // Set up a message filter to watch for response messages
            int filterId = 0;
            PassThruMsg maskMsg = new PassThruMsg(
                ProtocolID.ISO15765,
                TxFlag.ISO15765_FRAME_PAD,
                new byte[] { 0xff, 0xff, 0xff, 0xff });
            PassThruMsg patternMsg = new PassThruMsg(
                ProtocolID.ISO15765,
                TxFlag.ISO15765_FRAME_PAD,
                new byte[] { 0x00, 0x00, 0x07, 0xE8});
            PassThruMsg flowControlMsg = new PassThruMsg(
                ProtocolID.ISO15765,
                TxFlag.ISO15765_FRAME_PAD,
                new byte[] { 0x00, 0x00, 0x07, 0xE0});
            passThru.StartMsgFilter(channelId, FilterType.FLOW_CONTROL_FILTER, ref maskMsg, ref patternMsg, ref flowControlMsg, ref filterId);

            // Clear out the response buffer so we know we're getting the freshest possible data
            passThru.ClearRxBuffer(channelId);

            // Finally we can send the message!
            PassThruMsg txMsg = new PassThruMsg(
                ProtocolID.ISO15765,
                TxFlag.ISO15765_FRAME_PAD,
                new byte[] { 0x00, 0x00, 0x07, 0xdf, 0x01, 0x00 });
            int numMsgs = 1;
            passThru.WriteMsgs(channelId, ref txMsg, ref numMsgs, 50);

            // Read messages in a loop until we either timeout or we receive data
            List<PassThruMsg> rxMsgs = new List<PassThruMsg>();
            J2534Err status = J2534Err.STATUS_NOERROR;
            numMsgs = 1;
            while (J2534Err.STATUS_NOERROR == status)
                status = passThru.ReadMsgs(channelId, ref rxMsgs, ref numMsgs, 200);

            // If we received data, we want to extract the data of interest.  I'm removing the reflection of the transmitted message.
            List<byte> responseData;
            if ((J2534Err.ERR_BUFFER_EMPTY == status || J2534Err.ERR_TIMEOUT == status) && rxMsgs.Count > 1)
            {
                responseData = rxMsgs[rxMsgs.Count - 1].Data.ToList();
                responseData.RemoveRange(0, txMsg.Data.Length);
            }

            //
            //
            // Now do something with the data!
            //
            //

            // Disconnect this channel
            passThru.Disconnect(channelId);

            // When we are done with the device, we can free the library.
            passThru.FreeLibrary();
        }
예제 #9
0
파일: Form1.cs 프로젝트: mkelly/J2534DotNet
        /*
         *
         *  Example 2:
         *      Use the J2534 protocol to send and receive a message (w/o error checking)
         *
         */
        private void SendReceiveNoErrorChecking(object sender, EventArgs e)
        {
            J2534Extended passThru = new J2534Extended();

            // Find all of the installed J2534 passthru devices
            List<J2534Device> availableJ2534Devices = J2534Detect.ListDevices();

            J2534Device j2534Device;
            var sd = new SelectDevice();
            if (sd.ShowDialog() == DialogResult.OK)
            {
                j2534Device = sd.Device;
            }
            else
            {
                return;
            }

            // We will always choose the first J2534 device in the list, if there are multiple devices
            //   installed, you should do something more intelligent.
            passThru.LoadLibrary(j2534Device);

            // Attempt to open a communication link with the pass thru device
            int deviceId = 0;
            passThru.PassThruOpen(IntPtr.Zero, ref deviceId);

            // Open a new channel configured for ISO15765 (CAN)
            int channelId = 0;
            passThru.PassThruConnect(deviceId, ProtocolID.ISO15765, ConnectFlag.NONE, BaudRate.ISO15765, ref channelId);

            // Set up a message filter to watch for response messages
            int filterId = 0;
            PassThruMsg maskMsg = new PassThruMsg(
                ProtocolID.ISO15765,
                TxFlag.ISO15765_FRAME_PAD,
                new byte[] { 0xff, 0xff, 0xff, 0xff });
            PassThruMsg patternMsg = new PassThruMsg(
                ProtocolID.ISO15765,
                TxFlag.ISO15765_FRAME_PAD,
                new byte[] { 0x00, 0x00, 0x07, 0xE8 });
            PassThruMsg flowControlMsg = new PassThruMsg(
                ProtocolID.ISO15765,
                TxFlag.ISO15765_FRAME_PAD,
                new byte[] { 0x00, 0x00, 0x07, 0xE0 });

            IntPtr maskMsgPtr = maskMsg.ToIntPtr();
            IntPtr patternMsgPtr = patternMsg.ToIntPtr();
            IntPtr flowControlMsgPtr = flowControlMsg.ToIntPtr();
            passThru.PassThruStartMsgFilter(channelId, FilterType.FLOW_CONTROL_FILTER, maskMsgPtr, patternMsgPtr, flowControlMsgPtr, ref filterId);

            // Clear out the response buffer so we know we're getting the freshest possible data
            passThru.ClearRxBuffer(channelId);

            // Finally we can send the message!
            PassThruMsg txMsg = new PassThruMsg(
                ProtocolID.ISO15765,
                TxFlag.ISO15765_FRAME_PAD,
                new byte[] { 0x00, 0x00, 0x07, 0xdf, 0x01, 0x00 });
            var txMsgPtr = txMsg.ToIntPtr();
            int numMsgs = 1;
            passThru.PassThruWriteMsgs(channelId, txMsgPtr, ref numMsgs, 50);

            // Read messages in a loop until we either timeout or we receive data
            numMsgs = 1;
            IntPtr rxMsgs = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(PassThruMsg)) * numMsgs);
            J2534Err status = J2534Err.STATUS_NOERROR;
            while (J2534Err.STATUS_NOERROR == status)
                status = passThru.PassThruReadMsgs(channelId, rxMsgs, ref numMsgs, 200);

            // If we received data, we want to extract the data of interest.  I'm removing the reflection of the transmitted message.
            if ((J2534Err.ERR_BUFFER_EMPTY == status || J2534Err.ERR_TIMEOUT == status) && numMsgs > 0)
            {
                foreach (PassThruMsg msg in rxMsgs.AsList<PassThruMsg>(numMsgs))
                {
                    //
                    //
                    // Now do something with the data!
                    //
                    //
                }
            }

            // Disconnect this channel
            passThru.PassThruDisconnect(channelId);

            // When we are done with the device, we can free the library.
            passThru.FreeLibrary();
        }
예제 #10
0
파일: J2534.cs 프로젝트: GeorgyPorgy/VMPT
 public J2534Err WriteMsgs(int channelId, ref PassThruMsg msg, ref int numMsgs, int timeout)
 {
     UnsafePassThruMsg uMsg = ConvertPassThruMsg(msg);
     // TODO: change function to accept a list? of PassThruMsg
     return (J2534Err)m_wrapper.WriteMsgs(channelId, ref uMsg, ref numMsgs, timeout);
 }
예제 #11
0
파일: ObdComm.cs 프로젝트: GeorgyPorgy/VMPT
        private bool ReadObdPid(byte mode, byte pid, ProtocolID protocolId, ref List<byte> value)
        {
            List<PassThruMsg> rxMsgs = new List<PassThruMsg>();
            PassThruMsg txMsg = new PassThruMsg();
            int timeout;

            txMsg.ProtocolID = protocolId;
	        switch (protocolId)
	        {
		        case ProtocolID.ISO15765:
                    txMsg.TxFlags = TxFlag.ISO15765_FRAME_PAD;
                    if (mode == 0x03 || mode == 0x04)
                    {
                        txMsg.Data = new byte[] { 0x00, 0x00, 0x07, 0xdf, mode};
                    }
                    else
                    {
                        txMsg.Data = new byte[] { 0x00, 0x00, 0x07, 0xdf, mode, pid };
                    }
                    timeout = 50;
			        break;
		        case ProtocolID.J1850PWM:
                case ProtocolID.J1850VPW:
		        case ProtocolID.ISO9141:
                case ProtocolID.ISO14230:
                    byte protocolByte = (byte)((protocolId == ProtocolID.J1850PWM) ? 0x61 : 0x68);
                    txMsg.TxFlags = TxFlag.NONE;
                    txMsg.Data = new byte[]{protocolByte, 0x6A, 0xF1, mode, pid};
			        timeout = 100;
			        break;
		        default:
			        return false;
	        }

	        m_j2534Interface.ClearRxBuffer(m_channelId);

	        int numMsgs = 1;
            m_status = m_j2534Interface.WriteMsgs(m_channelId, ref txMsg, ref numMsgs, timeout);
            if (J2534Err.STATUS_NOERROR != m_status)
            {
                return false;
            }

            numMsgs = 1;
            while (J2534Err.STATUS_NOERROR == m_status)
	        {
                m_status = m_j2534Interface.ReadMsgs(m_channelId, ref rxMsgs, ref numMsgs, timeout * 4);
	        }

            if (J2534Err.ERR_BUFFER_EMPTY == m_status || J2534Err.ERR_TIMEOUT == m_status)
            {
                if (rxMsgs.Count > 1)
                {
                    // Select the last value
                    value = rxMsgs[rxMsgs.Count - 1].Data.ToList();
                    value.RemoveRange(0, txMsg.Data.Length);
                    return true;
                }
                return false;
            }
            return false;
        }
예제 #12
0
        public J2534Err StartPeriodicMsg(int channelId, ref PassThruMsg msg, ref int msgId, int timeInterval)
        {
            UnsafePassThruMsg uMsg = ConvertPassThruMsg(msg);

            return((J2534Err)m_wrapper.StartPeriodicMsg(channelId, ref uMsg, ref msgId, timeInterval));
        }
예제 #13
0
파일: J2534.cs 프로젝트: GeorgyPorgy/VMPT
        public J2534Err FastInit(int channelId, PassThruMsg txMsg, ref PassThruMsg rxMsg)
        {
            IntPtr input = IntPtr.Zero;
            IntPtr output = IntPtr.Zero;
            UnsafePassThruMsg uTxMsg = ConvertPassThruMsg(txMsg);
            UnsafePassThruMsg uRxMsg = new UnsafePassThruMsg();

            Marshal.StructureToPtr(uTxMsg, input, true);
            Marshal.StructureToPtr(uRxMsg, output, true);

            J2534Err returnValue = (J2534Err)m_wrapper.Ioctl(channelId, (int)Ioctl.FAST_INIT, input, output);
            if (returnValue == J2534Err.STATUS_NOERROR)
            {
                Marshal.PtrToStructure(output, uRxMsg);
            }

            rxMsg = ConvertPassThruMsg(uRxMsg);
            return returnValue;
        }
예제 #14
0
파일: J2534.cs 프로젝트: GeorgyPorgy/VMPT
 public J2534Err StartMsgFilter
 (
     int channelid,
     FilterType filterType,
     ref PassThruMsg maskMsg,
     ref PassThruMsg patternMsg,
     ref int filterId
 )
 {
     int nada = 0;
     UnsafePassThruMsg uMaskMsg = ConvertPassThruMsg(maskMsg);
     UnsafePassThruMsg uPatternMsg = ConvertPassThruMsg(patternMsg);
     return (J2534Err)m_wrapper.StartPassBlockMsgFilter
             (
                 channelid,
                 (int)filterType,
                 ref uMaskMsg,
                 ref uPatternMsg,
                 nada,
                 ref filterId
             );
 }
예제 #15
0
파일: J2534.cs 프로젝트: GeorgyPorgy/VMPT
 public J2534Err StartMsgFilter
 (
     int channelid,
     FilterType filterType,
     ref PassThruMsg maskMsg,
     ref PassThruMsg patternMsg,
     ref PassThruMsg flowControlMsg,
     ref int filterId
 )
 {
     UnsafePassThruMsg uMaskMsg = ConvertPassThruMsg(maskMsg);
     UnsafePassThruMsg uPatternMsg = ConvertPassThruMsg(patternMsg);
     UnsafePassThruMsg uFlowControlMsg = ConvertPassThruMsg(flowControlMsg);
     return (J2534Err)m_wrapper.StartMsgFilter
             (
                 channelid, 
                 (int)filterType,
                 ref uMaskMsg,
                 ref uPatternMsg,
                 ref uFlowControlMsg, 
                 ref filterId
             );
 }
예제 #16
0
파일: J2534.cs 프로젝트: GeorgyPorgy/VMPT
 public J2534Err StartPeriodicMsg(int channelId, ref PassThruMsg msg, ref int msgId, int timeInterval)
 {
     UnsafePassThruMsg uMsg = ConvertPassThruMsg(msg);
     return (J2534Err)m_wrapper.StartPeriodicMsg(channelId, ref uMsg, ref msgId, timeInterval);
 }
예제 #17
0
        public bool ConnectIso15765()
        {
            List<byte> value = new List<byte>();

            m_status = m_j2534Interface.PassThruConnect(m_deviceId, ProtocolID.ISO15765, ConnectFlag.NONE, BaudRate.ISO15765, ref m_channelId);
            if (J2534Err.STATUS_NOERROR != m_status)
            {
                return false;
            }

            int filterId = 0;

            byte i;

            for (i = 0; i < 1; i++)
            {
                PassThruMsg maskMsg = new PassThruMsg(ProtocolID.ISO15765, TxFlag.ISO15765_FRAME_PAD, new byte[] { 0xff, 0xff, 0xff, 0xff });
                PassThruMsg patternMsg = new PassThruMsg(ProtocolID.ISO15765, TxFlag.ISO15765_FRAME_PAD, new byte[] { 0x00, 0x00, 0x07, (byte)(0xE8 + i) });
                PassThruMsg flowControlMsg = new PassThruMsg(ProtocolID.ISO15765, TxFlag.ISO15765_FRAME_PAD, new byte[] { 0x00, 0x00, 0x07, (byte)(0xE0 + i) });

                m_status = m_j2534Interface.PassThruStartMsgFilter(
                    m_channelId,
                    FilterType.FLOW_CONTROL_FILTER,
                    maskMsg.ToIntPtr(),
                    patternMsg.ToIntPtr(),
                    flowControlMsg.ToIntPtr(),
                    ref filterId);

                if (J2534Err.STATUS_NOERROR != m_status)
                {
                    m_j2534Interface.PassThruDisconnect(m_channelId);
                    return false;
                }
            }

            if(!ReadObdPid(0x01,0x00,ProtocolID.ISO15765, ref value))
            {
                m_j2534Interface.PassThruDisconnect(m_channelId);
                return false;
            }
            return true;
        }
예제 #18
0
파일: J2534.cs 프로젝트: GeorgyPorgy/VMPT
        private UnsafePassThruMsg ConvertPassThruMsg(PassThruMsg msg)
        {
            UnsafePassThruMsg uMsg = new UnsafePassThruMsg();

            uMsg.ProtocolID = (int)msg.ProtocolID;
            uMsg.RxStatus = (int)msg.RxStatus;
            uMsg.Timestamp = msg.Timestamp;
            uMsg.TxFlags = (int)msg.TxFlags;
            uMsg.ExtraDataIndex = msg.ExtraDataIndex;
            uMsg.DataSize = msg.Data.Length;
            unsafe
            {
                for (int i = 0; i < msg.Data.Length; i++)
                {
                    uMsg.Data[i] = msg.Data[i];
                }
            }

            return uMsg;
        }
예제 #19
0
파일: ObdComm.cs 프로젝트: GeorgyPorgy/VMPT
        public bool ConnectIso15765()
        {
            List<byte> value = new List<byte>();

            m_status = m_j2534Interface.Connect(m_deviceId, ProtocolID.ISO15765, ConnectFlag.NONE, BaudRate.ISO15765, ref m_channelId);
            if (J2534Err.STATUS_NOERROR != m_status)
            {
                return false;
            }

            PassThruMsg maskMsg = new PassThruMsg();
            PassThruMsg patternMsg = new PassThruMsg();
            PassThruMsg flowControlMsg = new PassThruMsg();
            int filterId = 0;

	        byte i;
	        //for (i=0; i < 8; i++)
            for (i = 0; i < 1; i++)
	        {
                maskMsg.ProtocolID = ProtocolID.ISO15765;
                maskMsg.TxFlags = TxFlag.ISO15765_FRAME_PAD;
                maskMsg.Data = new byte[]{0xff,0xff,0xff,0xff};

                patternMsg.ProtocolID = ProtocolID.ISO15765;
                patternMsg.TxFlags = TxFlag.ISO15765_FRAME_PAD;
                patternMsg.Data = new byte[]{0x00,0x00,0x07,(byte)(0xE8 + i)};

                flowControlMsg.ProtocolID = ProtocolID.ISO15765;
                flowControlMsg.TxFlags = TxFlag.ISO15765_FRAME_PAD;
                flowControlMsg.Data = new byte[]{0x00,0x00,0x07,(byte)(0xE0 + i)};

                m_status = m_j2534Interface.StartMsgFilter(m_channelId, FilterType.FLOW_CONTROL_FILTER, ref maskMsg, ref patternMsg, ref flowControlMsg, ref filterId);
                if (J2534Err.STATUS_NOERROR != m_status)
                {
                    m_j2534Interface.Disconnect(m_channelId);
                    return false;
                }
	        }
            
            if(!ReadObdPid(0x01,0x00,ProtocolID.ISO15765, ref value))
            {
                m_j2534Interface.Disconnect(m_channelId);
		        return false;
	        }
	        return true;
        }
예제 #20
0
파일: J2534.cs 프로젝트: GeorgyPorgy/VMPT
        private static PassThruMsg ConvertPassThruMsg(UnsafePassThruMsg uMsg)
        {
            PassThruMsg msg = new PassThruMsg();

            msg.ProtocolID = (ProtocolID)uMsg.ProtocolID;
            msg.RxStatus = (RxStatus)uMsg.RxStatus;
            msg.Timestamp = uMsg.Timestamp;
            msg.TxFlags = (TxFlag)uMsg.TxFlags;
            msg.ExtraDataIndex = uMsg.ExtraDataIndex;
            msg.Data = new byte[uMsg.DataSize];
            unsafe
            {
                for (int i = 0; i < uMsg.DataSize; i++)
                {
                    msg.Data[i] = uMsg.Data[i];
                }
            }

            return msg;
        }
예제 #21
0
        private bool ReadObdPid(byte mode, byte pid, ProtocolID protocolId, ref List<byte> value)
        {
            PassThruMsg txMsg = new PassThruMsg();
            int timeout;

            txMsg.ProtocolID = protocolId;
            switch (protocolId)
            {
                case ProtocolID.ISO15765:
                    txMsg.TxFlags = TxFlag.ISO15765_FRAME_PAD;
                    if (mode == 0x03 || mode == 0x04)
                    {
                        txMsg.SetBytes(new byte[] { 0x00, 0x00, 0x07, 0xdf, mode});
                    }
                    else
                    {
                        txMsg.SetBytes(new byte[] { 0x00, 0x00, 0x07, 0xdf, mode, pid });
                    }
                    timeout = 50;
                    break;
                case ProtocolID.J1850PWM:
                case ProtocolID.J1850VPW:
                case ProtocolID.ISO9141:
                case ProtocolID.ISO14230:
                    byte protocolByte = (byte)((protocolId == ProtocolID.J1850PWM) ? 0x61 : 0x68);
                    txMsg.TxFlags = TxFlag.NONE;
                    txMsg.SetBytes(new byte[]{protocolByte, 0x6A, 0xF1, mode, pid});
                    timeout = 100;
                    break;
                default:
                    return false;
            }

            m_j2534Interface.ClearRxBuffer(m_channelId);

            int numMsgs = 1;
            m_status = m_j2534Interface.PassThruWriteMsgs(m_channelId, txMsg.ToIntPtr(), ref numMsgs, timeout);
            if (J2534Err.STATUS_NOERROR != m_status)
            {
                return false;
            }

            IntPtr rxMsgs = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(PassThruMsg)) * numMsgs);
            numMsgs = 1;
            while (J2534Err.STATUS_NOERROR == m_status)
            {
                m_status = m_j2534Interface.PassThruReadMsgs(m_channelId, rxMsgs, ref numMsgs, timeout * 4);
            }

            if (J2534Err.ERR_BUFFER_EMPTY == m_status || J2534Err.ERR_TIMEOUT == m_status)
            {
                if (numMsgs > 0)
                {
                    // Select the last value
                    PassThruMsg msg = rxMsgs.AsMsgList(numMsgs).Last();
                    value = msg.GetBytes().ToList();
                    value.RemoveRange(0, txMsg.GetBytes().Length);
                    return true;
                }
                return false;
            }
            return false;
        }