Author Topic: How to add a thread to continous read HID input reports?  (Read 15503 times)

Dominik

  • Guest
How to add a thread to continous read HID input reports?
« on: November 29, 2011, 10:32:31 am »
Hi,

I'm searching for a short C# example how to add an Thread which runs a loop to read out input reports and add the received data to a textbox (if there is any data). I have problems to stop running the thread loop. I don't want to use thread.abort() but setting and reading a bool variable in the loop didn't worked. I think it is because updating the WindowForm takes to much time. So I am looking for a good/fast thread example.


Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: How to add a thread to continous read HID input reports?
« Reply #1 on: November 29, 2011, 11:24:19 am »
My generic HID examples use BeginInvoke to read a report in the background with a callback that displays the retrieved data on a form. So waiting for reports doesn't hang the main application. To retrieve reports continuously, the application could request a new report immediately after receiving one, and the application can stop reading whenever it wants.

http://www.lvr.com/hidpage.htm#MyExampleCode

Jan

Dominik

  • Guest
Re: How to add a thread to continous read HID input reports?
« Reply #2 on: December 05, 2011, 11:13:14 am »
Hi Jan,

thank you for your reply. I am using your C# hid example and modified it to start a reading thread:
Code: [Select]
                    while (boRunWorker)
                    {
                        if ((fileStreamDeviceData.Read(inputReportBuffer, 0, inputReportBuffer.Length) > 0))
                        {
                            objArray[1] = inputReportBuffer;    // set received data
                            BeginInvoke(updel, objArray);
                        }
                        Thread.Sleep(20);    // switch between threads
                    }

Now I think it is working, I have changed the MainForm updating routine from a MethodInvoker call to an BeginInvoke delegate routine. Or would it be better to start reading only when the thread has received some data from the device and not calling Read in loops (using asynchronousread -> Beginread?)?
 But I have also another problem to send multiple bytes to my device (STM32 Microcontroller). To prepare my device I'll have to send multiple small packages of 4 bytes. I have modified the send routine not to wait for an input report. Sending one after another package stopps after sending some reports (4 bytes) calling fileStreamDeviceData.Write(outputReportBuffer, 0, outputReportBuffer.Length); for the next package. Setting some breakpoints before sending a new report prevents the windows program from getting stuck. So i have added some Thread.Sleep(); calls but it doesn't work at all. I guess that the previous send process is not completed, but how could I check if this is the problem and how could I solve that.

Thank you
Dominik!

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: How to add a thread to continous read HID input reports?
« Reply #3 on: December 05, 2011, 11:59:21 am »
I'm not sure offhand of the answer to your first question.

As for the Writes, are you waiting for Write to return before doing another? Is the device ACKing everying it receives?

Jan

Dominik

  • Guest
Re: How to add a thread to continous read HID input reports?
« Reply #4 on: December 06, 2011, 11:14:02 am »
Hi,

i have added a bool variable to check if there is a pending write process. But I also thought, that calling fileStreamDeviceData.Write(outputReportBuffer, 0, outputReportBuffer.Length); will return after sending data was completed. I have added a call of fileStreamDeviceData.flush() and it is better (but i still have to call thread.sleep). Ok i could live with that call. I'll have to check if my device is ACKing every packet. One last question: Do I have to open two device handles and two filestreams (one read, one write direction) to perform mostly "independent" read and write actions of the USB or isn't it possible to write a report to the device while a thread is waiting for data from an input report? If this isn't possible it might be a problem in my code, because I want to send some additional reports after starting the thread to check if input reports have been received.

Dominik

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: How to add a thread to continous read HID input reports?
« Reply #5 on: December 06, 2011, 12:42:08 pm »

Dominik

  • Guest
Re: How to add a thread to continous read HID input reports?
« Reply #6 on: December 07, 2011, 12:03:44 pm »
So i have changed my Thread loop from calling filestream.Begin(...) to filestream.BeginRead(...). To abort the thread my loop has to receive at least one report from my device to finally call EndRead(). This has to be done because calling BeginRead(...) is blocking the filestream and I couldn't find another function to abort it. To be able to send a request while waiting for data from my device I split up the original filestream in two (one reading, one writing) with two hidhandles(also reading and writing direction)!
Code: [Select]
                    while (boRunWorker)
                    {
                        if (boStopp)
                        {
                            outputReportBuffer[0] = 0x01; // fill the output report
                            outputReportBuffer[1] = 0x03;
                            outputReportBuffer[2] = 0x00;
                            outputReportBuffer[3] = 0x00;
                            fileStreamWrite.Write(outputReportBuffer, 0, outputReportBuffer.Length);
                            fileStreamWrite.Flush(true);
                            Thread.Sleep(0);

                            object obj = ar.AsyncState;
                            while(!ar.IsCompleted);    // wait for EndRead when "calb" is executed
                        }
                        if ((botransfer == false) && (boStopp == false)) // prevent restarting BeginRead when already called and/or thread is about to stop
                        {
                            botransfer = true;  // Signal pending transfer
                            ar = fileStreamDeviceData.BeginRead(inputReportBuffer, 0, inputReportBuffer.Length, callb, inputReportBuffer);
                        }
                    }

I think I also found a little thing in your original code: In generic_hid_cs_50.zip you added a IAsyncResult variable but didn't instantiate it in ExchangeInputAndOutputReports() when calling BeginRead: (should be something like this ar = fileStreamDeviceData.BeginRead(...); ) ?

Cheers Dominik

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: How to add a thread to continous read HID input reports?
« Reply #7 on: December 07, 2011, 05:50:13 pm »
>I think I also found a little thing in your original code: In generic_hid_cs_50.zip you added a IAsyncResult variable but didn't instantiate it in ExchangeInputAndOutputReports() when calling BeginRead: (should be something like this ar = fileStreamDeviceData.BeginRead(...); ) ?

Thanks!

Jan