[fpc-pascal] USB Human Interface Devices

James Richters james at productionautomation.net
Thu Aug 22 00:35:28 CEST 2019


I had them separated, but whenever it happened that I tried to write while it was waiting to read, I would get the error below.  If it was reading all the time it seemed fine.. just if it was idle waiting to read and I did a write that it would fail with EAccessViolation: Access violation

I put them in the same thread but only allow writes when it's been idle for a few timeouts.. the only time I need to read the port like crazy if I spin the hand wheel really fast.  I also use the slow main program to only tell the fast read thread that data is available to write at a pretty slow rate.    I think this could be improved.. I just don't know how to us this locking system you mention. If I can lock it from reading when I try to write or to properly interrupt the read if it is just sitting there waiting for data that would be better.

The device only answers the read request when it has something to send, so it will sit there for hours just waiting if no one gives it any input.. but I want to update the display all the time... all the time that it's turned on anyway... so that's the issue I'm facing.   Whenever I try to write when the device is idle.. it blows up.. probably because I did not finish the read and lock reading.  Anyway what I have now can't read and write at the same time.. I am using a timeout to stop trying to read.. and then if I get enough time outs in a row, I figure I'm not too busy reading, so I send out the write.. but if I blast it with data (turn the wheel super fast for a long time) then it never tries to write because I never time out.. so the display doesn't change.. but that's ok.. it corrects itself when I stop the crazy input.  99% of the time. The wheel will be turned slowly.. just once in a while the user might want to move a large distance with it and whirl it around really fast.

I thought I saw something about sending a request to read.. then doing something else for a while and getting a call back when it's got something there.. maybe that's something like asynchronous?  I think if I can figure that out it would solve the problem (maybe) of wanting to write something while I wait for input.  I'm thinking if I don't use a timeout like I am now, I wouldn't get libusb: warning [handle_timeout] async cancel failed -5 errno=0 ... I wonder if that is a know issue and the reason why the timout was originally set to zero in the interrupt read function... 

Still all in all, I'm pretty happy with it!  I do still miss like 2 pulses out of 800.. so not a super huge deal, but room for improvement... if I use the library the proper way, it will probably help.

I'm wondering there is something in threads that I can set to make my fast read thread always run faster than the others.. some kind of priority or percentage?? Or do I just have to put enough delays with Sleep() commands to slow everything else down...

James

-----Original Message-----
From: fpc-pascal <fpc-pascal-bounces at lists.freepascal.org> On Behalf Of Stefan V. Pantazi
Sent: Wednesday, August 21, 2019 5:31 PM
To: fpc-pascal at lists.freepascal.org
Subject: Re: [fpc-pascal] USB Human Interface Devices

 From your example it looks like you placed the device reading (interrupt read) and writing (set report) into the same read thread. I thought  keeping them separate was a good idea: tight loop reads and less frequent writes (LCD updates).

Libusb is supposed to be thread-safe. Not really an issue for your app but if you need to make sure only one thread out of multiple threads is processing libusb events the library has asynchronous API that does offer locking functionality.

On 8/21/19 3:48 PM, James Richters wrote:
> Well..  It doesn’t always work just reading constantly and writing in a different thread..
> 
> So I have my fast read loop always reading then my LCD write loop sending the 3 packets every 0.3 Seconds.. and it functions ok, and I don’t miss too many counts... but every so often I get this message:
> libusb: warning [handle_timeout] async cancel failed -5 errno=0
> 
> I have a timeout on my read loop of 10ms.  I tried setting that to 0 so it would just wait for input in it's thread.. but when I do that I get this as soon as I attempt to write to it:
> An unhandled exception occurred at $00007FFF189F03C6:
> EAccessViolation: Access violation
>    $00007FFF189F03C6
>    $00007FFF189EDA21
>    $00007FFF17AAA1A1
>    $00007FFF17AA9CB5
>    $000000006B607FFB
>    $000000006B6081E7
>    $000000006B60C695
>    $000000006B605D6F
>    $000000006B607E40
>    $000000010001B1CA
>    $00000001000021BF  main,  line 445 of whb04b-4_test.pas
>    $00000001000022B6
>    $000000010000EC20
>    $0000000100001880
>    $00007FFF17B47E94
>    $00007FFF18A4A251
> 
> Also if I put in a really long timeout like 1000ms I get that.  Line 
> 445 is libusbhid_set_report(device_context, HID_REPORT_TYPE_FEATURE, 
> $6 , 8 , WhB04_Packet1 );
> 
> so I can't write while I'm reading or waiting for a read after all.
> 
> So I came up with a scheme to set all the variables in the slow loop 
> then set a Boolean variable when it's done.. then the fast loop checks 
> for the flag if it is idle for a time, meaning it's not trying to keep 
> up with input.. and that does work.. and I don't miss many counts... 
> but it does miss a few... but I STILL get this
> libusb: warning [handle_timeout] async cancel failed -5 errno=0
> 
> even though as far as I can tell, I can't possible be reading and writing at the same time.
> 
> I've updated my test project here: 
> https://github.com/Zaaphod/libusbxhid/blob/master/WHB04B-4_test.pas
> 
> I don't really know what libusb: warning [handle_timeout] async cancel failed -5 errno=0 is trying to tell me... it is having an issue canceling waiting for data after the time out I guess.. but why is that a problem?
> 
> Any Ideas?
> 
> James
> 
> -----Original Message-----
> From: fpc-pascal <fpc-pascal-bounces at lists.freepascal.org> On Behalf 
> Of James Richters
> Sent: Wednesday, August 21, 2019 8:30 AM
> To: 'FPC-Pascal users discussions' <fpc-pascal at lists.freepascal.org>
> Subject: Re: [fpc-pascal] USB Human Interface Devices
> 
> I FINALLY wrote some data to the LCD!!   YAY !!!   I was trying to get the python application to work.. without any luck.. but I ended up going ahead and trying Zadig changing the driver to libusb-win32...  After I gave up on Python, I went back to FPC and just ran my existing sample program, and I noticed where it used have an error sending to device, it now said 8 bytes sent!!  It's very strange I could read it just fine but not write to it without messing with the driver... but it's working now!
> 
> I tried suspending the read thread to write to it.. and well it must have ended up suspending in the middle of a read because the whole thing locked up.. so I just tried as suggested and let it keep reading in a tight loop in it's own thread and then just throw in a write every few seconds on the main program.. and that actually worked fine.. I guess libusb takes care of worry about finishing a read before writing.. I think I did see libusb had something to do with threads.
> 
> So now it's just a matter of small details.     The display is a little odd... in that instead of sending it just a real number, you send it an integer for the numbers before the decimal and another integer for the numbers after the decimal.. but it's 2 bytes for each (4 bytes total)  but they are in reverse order.. I need to send LowByte_Integer, High_Byte_Integer, LowByte_decimal, High_Byte_decimal  so the bits from a 16 bit integer end up being 76543210,FEDCBA98  I think this is that edian byte order thing that was mentioned.  I'm just curious if there is already a function available to reverse these like this.. or if I just need to write my own.  It's just some rotates and then split it, so I can do that, but I'm just wondering if there is something already there to do this.. I seem to recall that this kind of thing needs to happen quite a bit.
> 
> Also I need to stick a $06 in front of all my packets to send to the 
> device.  I have my data all in arrays,  so I want to do something like 
> this Device_Array[0]:=$06; Device_Array[1..7] := LCD_Array[0..6] ;
> 
> Ah.. but that doesn't work.. is there a way to do this with syntax or do I just need to make a loop to copy the array elements the way they need to be?
> 
> James
> _______________________________________________
> fpc-pascal maillist  -  fpc-pascal at lists.freepascal.org 
> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
> _______________________________________________
> fpc-pascal maillist  -  fpc-pascal at lists.freepascal.org 
> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
> 

--
_______________________________________________________
_______________________________________________
fpc-pascal maillist  -  fpc-pascal at lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


More information about the fpc-pascal mailing list