public bool CAN_GetMessage(ref caCANFrame frame, uint timeout)
        {
            if (timeout > 0 && !frame_event.WaitOne((int)timeout))
            {
                // timeout expired
                return(false);
            }

            frame_lock.WaitOne();
            bool ret = false;

            if (frame_queue.Count > 0)
            {
                // get oldest frame
                frame = (caCANFrame)frame_queue.Dequeue();
                ret   = true;
            }

            // reset the event if no more messages
            if (frame_queue.Count < 1)
            {
                frame_event.Reset();
            }

            frame_lock.ReleaseMutex();
            return(ret);
        }
        public void CAN_SendMessage(ref caCANFrame frame)
        {
            try
            {
                byte[] cmd_data = new byte[15];
                Debug.Assert(cmd_data != null);

                // format command data
                BitConverter.GetBytes(frame.id).CopyTo(cmd_data, 0);
                BitConverter.GetBytes(frame.data).CopyTo(cmd_data, 4);
                cmd_data[12] = frame.length;
                cmd_data[13] = frame.is_extended;
                cmd_data[14] = frame.is_remote;

                // send message; NB; adapter won't answer!
                send_command(cmd_can_txframe, cmd_data, 0, packet_timeout);
            }
            // handle exceptions
            catch (Exception e) {
                throw new Exception("Failed to send CAN message:" + e.Message);
            }
        }
        protected override void process_usb()
        {
            int byte_i;

            while (usb_queue.Count >= caPacket.min_size)
            {
                if (!pack_incomplete)
                {
                    // read packet header
                    in_pack.cmd_code = (byte)usb_queue.Dequeue();
                    in_pack.data_len =
                        (ushort)(((byte)usb_queue.Dequeue() << 8) | (byte)usb_queue.Dequeue());
                }

                if (usb_queue.Count <= in_pack.data_len)
                {
                    // incomplete packet
                    pack_incomplete = true;
                    return;
                }

                if (in_pack.data_len > 0)
                {
                    // read data block
                    in_pack.data = new byte[in_pack.data_len];
                    Debug.Assert(in_pack.data != null);

                    for (byte_i = 0; byte_i < in_pack.data_len; ++byte_i)
                    {
                        in_pack.data[byte_i] = (byte)usb_queue.Dequeue();
                    }
                }

                // teminator
                in_pack.term    = (byte)usb_queue.Dequeue();
                pack_incomplete = false;

                // got CAN frame
                if (in_pack.cmd_code == cmd_can_frame)
                {
                    if (in_pack.data_len == 15)
                    {
                        // fill frame structure
                        caCANFrame can_frame = new caCANFrame();
                        can_frame.id          = (uint)BitConverter.ToInt32(in_pack.data, 0);
                        can_frame.data        = (ulong)BitConverter.ToInt64(in_pack.data, 4);
                        can_frame.length      = in_pack.data[12];
                        can_frame.is_extended = in_pack.data[13];
                        can_frame.is_remote   = in_pack.data[14];

                        frame_lock.WaitOne();

                        // store frame in queue and notify waiting threads
                        frame_queue.Enqueue(can_frame);
                        frame_event.Set();

                        frame_lock.ReleaseMutex();
                    }
                }

                // got command response
                else
                {
                    response_lock.WaitOne();

                    // save response packet and notify waiting threads
                    caPacket new_pack = new caPacket();
                    new_pack.cmd_code = in_pack.cmd_code;
                    new_pack.data     = in_pack.data_len != 0 ? (byte[])in_pack.data.Clone() : null;
                    new_pack.data_len = in_pack.data_len;
                    new_pack.term     = in_pack.term;
                    response_queue.Enqueue(new_pack);
                    response_event.Set();

                    response_lock.ReleaseMutex();
                }
            }
        }
        protected override void process_usb()
        {
            int byte_i;

            while (usb_queue.Count >= caPacket.min_size) {
                if (!pack_incomplete)
                {
                    // read packet header
                    in_pack.cmd_code = (byte)usb_queue.Dequeue();
                    in_pack.data_len =
                        (ushort)(((byte)usb_queue.Dequeue() << 8) | (byte)usb_queue.Dequeue());
                }

                if (usb_queue.Count <= in_pack.data_len)
                {
                    // incomplete packet
                    pack_incomplete = true;
                    return;
                }

                if (in_pack.data_len > 0)
                {
                    // read data block
                    in_pack.data = new byte[in_pack.data_len];
                    Debug.Assert(in_pack.data != null);

                    for (byte_i = 0; byte_i < in_pack.data_len; ++byte_i)
                    {
                        in_pack.data[byte_i] = (byte)usb_queue.Dequeue();
                    }
                }

                // teminator
                in_pack.term = (byte)usb_queue.Dequeue();
                pack_incomplete = false;

                // got CAN frame
                if(in_pack.cmd_code == cmd_can_frame)
                {
                    if(in_pack.data_len == 15)
                    {
                        // fill frame structure
                        caCANFrame can_frame = new caCANFrame();
                        can_frame.id = (uint)BitConverter.ToInt32(in_pack.data, 0);
                        can_frame.data = (ulong)BitConverter.ToInt64(in_pack.data, 4);
                        can_frame.length = in_pack.data[12];
                        can_frame.is_extended = in_pack.data[13];
                        can_frame.is_remote = in_pack.data[14];

                        frame_lock.WaitOne();

                        // store frame in queue and notify waiting threads
                        frame_queue.Enqueue(can_frame);
                        frame_event.Set();

                        frame_lock.ReleaseMutex();
                    }
                }

                // got command response
                else
                {
                    response_lock.WaitOne();

                    // save response packet and notify waiting threads
                    caPacket new_pack = new caPacket();
                    new_pack.cmd_code = in_pack.cmd_code;
                    new_pack.data = in_pack.data_len != 0 ? (byte[])in_pack.data.Clone() : null;
                    new_pack.data_len = in_pack.data_len;
                    new_pack.term = in_pack.term;
                    response_queue.Enqueue(new_pack);
                    response_event.Set();

                    response_lock.ReleaseMutex();
                }
            }
        }
        public void CAN_SendMessage(ref caCANFrame frame)
        {
            try
            {
                byte[] cmd_data = new byte[15];
                Debug.Assert (cmd_data != null);

                // format command data
                BitConverter.GetBytes(frame.id).CopyTo(cmd_data,0);
                BitConverter.GetBytes(frame.data).CopyTo(cmd_data,4);
                cmd_data[12] = frame.length;
                cmd_data[13] = frame.is_extended;
                cmd_data[14] = frame.is_remote;

                // send message; NB; adapter won't answer!
                send_command (cmd_can_txframe, cmd_data, 0, packet_timeout);
            }
            // handle exceptions
            catch (Exception e) {
                throw new Exception("Failed to send CAN message:" + e.Message);
            }
        }
        public bool CAN_GetMessage(ref caCANFrame frame, uint timeout)
        {
            if (timeout > 0 && !frame_event.WaitOne ((int)timeout)) {
                // timeout expired
                return false;
            }

            frame_lock.WaitOne ();
            bool ret = false;
            if (frame_queue.Count > 0) {
                // get oldest frame
                frame = (caCANFrame)frame_queue.Dequeue();
                ret = true;
            }

            // reset the event if no more messages
            if (frame_queue.Count < 1)
            {
                frame_event.Reset();
            }

            frame_lock.ReleaseMutex();
            return ret;
        }