///  <summary>
        ///  Sends an Output report, then may retrieve an Input report.
        ///  </summary>

        private byte[] ExchangeInputAndOutputReports(byte[] outputReportBuffer, bool doOutputReport, bool doInputReport, int expectedInputReportID, EventHandler <AsyncInputReportArgs> readCompleteHandler)
        {
            StringBuilder byteValue = null;
            int           count     = 0;

            byte[] inputReportBuffer = null;
            bool   success           = false;

            try
            {
                success = false;

                //  Don't attempt to exchange reports if valid handles aren't available
                //  (as for a mouse or keyboard under Windows 2000/XP.)

                if (!readHandle.IsInvalid && !writeHandle.IsInvalid)
                {
                    //  Don't attempt to send an Output report if the HID has no Output report.

                    if (doOutputReport && MyHid.Capabilities.OutputReportByteLength > 0)
                    {
                        //  Write a report.

                        if ((UseControlTransfersOnly) == true)
                        {
                            //  Use a control transfer to send the report,
                            //  even if the HID has an interrupt OUT endpoint.

                            Hid.OutputReportViaControlTransfer myOutputReport = new Hid.OutputReportViaControlTransfer();
                            success = myOutputReport.Write(outputReportBuffer, writeHandle);
                        }
                        else
                        {
                            //  Use WriteFile to send the report.
                            //  If the HID has an interrupt OUT endpoint, WriteFile uses an
                            //  interrupt transfer to send the report.
                            //  If not, WriteFile uses a control transfer.

                            Hid.OutputReportViaInterruptTransfer myOutputReport = new Hid.OutputReportViaInterruptTransfer();
                            success = myOutputReport.Write(outputReportBuffer, writeHandle);
                        }

                        if (success)
                        {
                            ;

                            /*
                             * byteValue = new StringBuilder();
                             * byteValue.AppendFormat("An Output report has been written. Output Report ID: {0:X02}\r\n Output Report Data: ", outputReportBuffer[0]);
                             *
                             * for (count = 0; count <= outputReportBuffer.Length - 1; count++)
                             * {
                             *  //  Display bytes as 2-character hex strings.
                             *  byteValue.AppendFormat("{0:X02} ", outputReportBuffer[count]);
                             * }
                             * Tracer.Trace(byteValue.ToString());
                             */
                        }
                        else
                        {
                            Tracer.Error("The attempt to write an Output report has failed.");
                        }
                    }
                    else
                    {
                        //Tracer.Trace("No attempt to send an Output report was made.");
                        if (doOutputReport)
                        {
                            Tracer.Error("The HID doesn't have an Output report, but it was requested.");
                        }
                    }

                    //  Read an Input report.

                    //  Don't attempt to send an Input report if the HID has no Input report.
                    //  (The HID spec requires all HIDs to have an interrupt IN endpoint,
                    //  which suggests that all HIDs must support Input reports.)

                    if (doInputReport && MyHid.Capabilities.InputReportByteLength > 0)
                    {
                        success = false;

                        //  Set the size of the Input report buffer.

                        inputReportBuffer = new byte[MyHid.Capabilities.InputReportByteLength];

                        if (UseControlTransfersOnly || readCompleteHandler == null)
                        {
                            //  Read a report using a control transfer.

                            Hid.InputReportViaControlTransfer myInputReport = new Hid.InputReportViaControlTransfer();

                            //  Read the report via HidD_GetInputReport  http://www.osronline.com/DDKx/intinput/hidfunc_3hgy.htm
                            // - "If the top-level collection includes report IDs, the caller must set the first byte of the buffer to a nonzero report ID; otherwise the caller must set the first byte to zero."
                            inputReportBuffer[0] = (byte)expectedInputReportID;

                            myInputReport.Read(hidHandle, readHandle, writeHandle, ref myDeviceDetected, ref inputReportBuffer, ref success);

                            if (success)
                            {
                                ;

                                /*
                                 * byteValue = new StringBuilder();
                                 * byteValue.AppendFormat("ExchangeInputAndOutputReports(): An Input report has been read via ControlTransfer. Input Report ID: {0:X02}\r\n Input Report Data: ", inputReportBuffer[0]);
                                 *
                                 * for (count = 0; count <= inputReportBuffer.Length - 1; count++)
                                 * {
                                 *  //  Display bytes as 2-character Hex strings.
                                 *  byteValue.AppendFormat("{0:X02} ", inputReportBuffer[count]);
                                 * }
                                 * Tracer.Trace(byteValue.ToString());
                                 */
                            }
                            else
                            {
                                Tracer.Error("ExchangeInputAndOutputReports(): The attempt to read an Input report has failed.");
                            }
                        }
                        else
                        {
                            //  Read a report using interrupt transfers.
                            //  To enable reading a report without blocking the main thread, this
                            //  application uses an asynchronous delegate.

                            //Tracer.Trace("IP: Arranging asyncronous read via Interrupt Transfer");

                            IAsyncResult ar = null;
                            Hid.InputReportViaInterruptTransfer myInputReport = new Hid.InputReportViaInterruptTransfer();
                            if (readCompleteHandler != null)
                            {
                                myInputReport.HasReadData += readCompleteHandler;
                            }

                            //  Define a delegate for the Read method of myInputReport.

                            ReadInputReportDelegate MyReadInputReportDelegate = new ReadInputReportDelegate(myInputReport.Read);

                            //  The BeginInvoke method calls myInputReport.Read to attempt to read a report.
                            //  The method has the same parameters as the Read function,
                            //  plus two additional parameters:
                            //  GetInputReportData is the callback procedure that executes when the Read function returns.
                            //  MyReadInputReportDelegate is the asynchronous delegate object.
                            //  The last parameter can optionally be an object passed to the callback.

                            ar = MyReadInputReportDelegate.BeginInvoke(hidHandle, readHandle, writeHandle, ref myDeviceDetected, ref inputReportBuffer, ref success, new AsyncCallback(GetInputReportData), MyReadInputReportDelegate);
                        }
                    }
                    else
                    {
                        //Tracer.Trace("No attempt to read an Input report was made.");
                        if (doInputReport)
                        {
                            Tracer.Error("The HID doesn't have an Input report, but it was requested.");
                        }
                    }
                }
                else
                {
                    Tracer.Error("Invalid handle. The device is probably a system mouse or keyboard.");
                    Tracer.Error("No attempt to write an Output report or read an Input report was made.");
                }

                return(inputReportBuffer);   // may still be null
            }
            catch (Exception ex)
            {
                Tracer.Error(ex);
                throw;
            }
        }
            public bool FillRxBuffer()
            {
                Byte[] inputReportBuffer = null;
                Boolean success = false;

                readBuffer.Clear();
                this.readBuffer.Clear();
                this.ReadFinished = false;
                this.ReadStart = 0;

                //Thread.Sleep(10);
                /*
                if (readHandle.IsClosed)
                {
                    Console.Out.WriteLine("readHandle closed");
                }
                */

                if (!readHandle.IsClosed)
                {
                    if (!readHandle.IsInvalid && MyHid.Capabilities.InputReportByteLength > 0)
                    //if (MyHid.Capabilities.InputReportByteLength > 0)
                    {
                        //  Set the size of the Input report buffer.
                        inputReportBuffer = new Byte[MyHid.Capabilities.InputReportByteLength];

                        //  Read a report using interrupt transfers.
                        //  To enable reading a report without blocking the main thread, this
                        //  application uses an asynchronous delegate.
                        IAsyncResult ar = null;
                        Hid.InputReportViaInterruptTransfer myInputReport = new Hid.InputReportViaInterruptTransfer();

                        //  Define a delegate for the Read method of myInputReport.
                        ReadInputReportDelegate MyReadInputReportDelegate = new ReadInputReportDelegate(myInputReport.Read);

                        /*
                        if (readHandle.IsClosed)
                        {
                            Debug.WriteLine("readHandle Closed");
                        }
                         */

                        //  The BeginInvoke method calls myInputReport.Read to attempt to read a report.
                        //  The method has the same parameters as the Read function,
                        //  plus two additional parameters:
                        //  GetInputReportData is the callback procedure that executes when the Read function returns.
                        //  MyReadInputReportDelegate is the asynchronous delegate object.
                        //  The last parameter can optionally be an object passed to the callback.
                        ar = MyReadInputReportDelegate.BeginInvoke(hidHandle, readHandle, writeHandle, ref myDeviceDetected, ref inputReportBuffer, ref success, new AsyncCallback(GetInputReportData), MyReadInputReportDelegate);

                    }
                    else
                    {
                        //Console.Out.WriteLine("No attempt to read an Input report was made.");
                        Debug.WriteLine("No attempt to read an Input report was made.");
                        //Console.Out.WriteLine("The HID doesn't have an Input report.");
                        Debug.WriteLine("The HID doesn't have an Input report.");
                        return false;
                    }
                }
                else
                {
                    Debug.WriteLine("readHandle Closed");
                    return false;
                }

                //while (this.readBuffer.Count < 63)
                //{
                //    Thread.Sleep(5);
                //}
                //ReadFinished = true;
                return true;
            }