• Welcome to Forum.Deepsoftware.Com. Please login or sign up.
 

Reading HID reports

Started by chedges, January 28, 2009, 03:22:48 pm

Previous topic - Next topic

chedges

Hi Roman,

Yet another newbie question from me I'm afraid :(


After getting the writing of data to a HID device working, I am stumped again with regards to reading a report from device.

Is it just a case of writing the report Id to the device and it will return a buffer of data?
I'm using zero as the report ID as this is the Id shown in the Input values (via the HIDDemo)

The following code just hangs when the call to readReport is made. Is there more to
reading the reports that I have missed?

    New(Report); //allocate
    ToRead := nrHID1.HidDevice.InputReportLength; //Get the Report length - my printer returns 256bytes

    for I := 0 to ToRead-1 do
      Report^ := 0; //zero will alos be the report id!

    if nrHid1.ReadReport(Report, ToRead) then
    begin
      //Do something here!
    end;
    Dispose(Report);

Roman Novgorodov

Hi

The ReadReport() blocks a thread until all bytes will received. It waits all 256 bytes.

You can use OnAfterReceive event for read input data asynchronously.

Roman Novgorodov
DeepSoftware.Com
DeepSoftware llc - The professional components for Delphi/CBuilder/.NET. The high quality custom software development.
Forums.nrCommLib.Com - DeepSoftware Tech Support Forum.

chedges

January 29, 2009, 07:04:58 am #2 Last Edit: January 29, 2009, 07:13:15 am by chedges
I already have a AfterReceive event attached to the HID component but it never fires.

As soon as I make the call to ReadReport it hangs and never returns?

Roman Novgorodov

Hmm....

All should work. We use TnrHid component in our HIDPlugin project without any problems.

Does HIDDemo shows incoming bytes after device activation?

Maybe is something wrong with device initialization?

It seems like 256 bytes is too big size for single HID report.

Roman Novgorodov
DeepSoftware.Com
DeepSoftware llc - The professional components for Delphi/CBuilder/.NET. The high quality custom software development.
Forums.nrCommLib.Com - DeepSoftware Tech Support Forum.

chedges

Hi Roman,

So, would you expect the AfterReceive event to fire when using the HIDDemo as it certainly doesn't for me.
What should I be doing in the demo which would cause the event to fire?

thanks again

Chris



chedges

Ok, I've simplified the read report code to use a dynamic array instead of a pointer to a static array and it's not helped :(
I still get a hang when I read from my printer. I did confirm that the printer does expect a 265 byte report (I have some example VB code from the manufacturer).

I have tried reading from other devices but none of them have triggered the AfterRecieve event (mouse and keyboard) but I'm not sure if that is normal behaviour anyway?

Sorry :(

procedure TForm6.Button2Click(Sender: TObject);
var
  I: Integer;
  ToRead : Cardinal;
  Report : Array of Byte;
begin
    ToRead := nrHID1.HidDevice.InputReportLength; //Get the Report length - my printer returns 256bytes
    SetLength(Report, ToRead);

    //init the buffer
    for I := 0 to ToRead - 1 do
      Report := 0;
    try
      if nrHid1.ReadReport(Report, ToRead) then
        ShowMessage('Report Read!');
    except
      on E : Exception do
      begin
         ShowMessage('Exception: ' + E.Message);
      end;
    end;
end;

Roman Novgorodov

Hello

We used TnrHID class in our HIDPlugin project. It works perfect.

Do you understand how does your printer returns data?
It sounds strange to read HID report from printer :-)
Maybe you forget to send a command to printer?

If your device is opened successfully, and it send HID reports, you should catch OnAfterReceive event.
It seems like your device send nothing.

Please note that you can't test TnrHID with mouse or ordinary keyboards. They are handled by system always and application not has  direct access to their HID reports. HID mouse and keyboards are available over windows sustem messages only (WM_xxxxx)
You can try to test by using the BT hands-free device attached over bluetooth doungle, or Infrared remote control.

Roman Novgorodov
DeepSoftware
DeepSoftware llc - The professional components for Delphi/CBuilder/.NET. The high quality custom software development.
Forums.nrCommLib.Com - DeepSoftware Tech Support Forum.

chedges

I'm basically trying to recreate the behaviour of some VB code provided by the manufacturer.

It seems to be sending a report with a first byte of zero, much like I am doing. if you are interested I have pasted a copy below.
I have a compiled copy of this (I don't use VB myself though) and it works


Public Sub Receive(Size As Integer)

Dim ReadBuffer(0 To 255) As Byte
Dim i, Count As Integer

    ' Check the USB pointer for readiness
    If ReadHandle = 0 Then
           
        Display_Text ("Unable to Read from Boca Systems USB Printer. Invalid Read Handle.")
       
    Else
           
        'Display_Text ("A Boca Systems USB Printer has been located")
           
        ' At this point, we are expecting to read data from the printer buffer
        ' The amount read is based on the size field, or set to default
        If (Size > 0 And Size < USB_MAX_PACKET_SIZE) Then
            Str_Size = Size
        Else
            Str_Size = USB_MAX_PACKET_SIZE
        End If
               
        'When reading the USB port,  text(0) will contain the return byte
        'count for the rest of the string.
        text(0) = 0
        For i = 0 To Capabilities.InputReportByteLength - 1
            ReadBuffer(i) = 0
        Next i
           
        Result = HidD_GetInputReport(ReadHandle, ReadBuffer(0), CLng(Capabilities.InputReportByteLength))
        Count = 0
       
        For i = 1 To Capabilities.InputReportByteLength - 1

            If ReadBuffer(i) <> 0 Then
                Count = Count + 1
                text(Count) = ReadBuffer(i)
            End If
   
        Next i
        text(0) = Count
       
        'If nothing is read then text(0) will still = 0.
        length = text(0)
        If length > 0 Then
            Establish_Status
        'Else
            'Display_Text ("Nothing read from the print buffer, this time.  If you were expecting data, try again.")
        End If
    End If
           
End Sub




Roman Novgorodov

Hello

OK.
It seems like VB uses other reading functions for get HID reports.

You can try to use HidD_GetInputReport() function from nrhidw32 unit.

Something like this:

HidD_GetInputReport(nrHid1.Handle, buffer, size);

Roman Novgorodov
DeepSoftware.Com
DeepSoftware llc - The professional components for Delphi/CBuilder/.NET. The high quality custom software development.
Forums.nrCommLib.Com - DeepSoftware Tech Support Forum.

chedges

February 03, 2009, 11:28:48 am #9 Last Edit: February 03, 2009, 11:32:28 am by chedges
Thanks Roman, I'll try it.

just to be sure, nrHID does not expose a handle. Do you mean nrHid1.HidDevice.Handle?

just tried it like this:  HidD_GetInputReport(nrHid1.HidDevice.Handle, Report, ToRead);

It not longer hangs which is good but the function always returns false, so I guess this is a error too?


Roman Novgorodov

Hello

Yes you are right!

Handle property is not included into public section of TnrHid class. It is our mistake.

Please download new version of nrComm Lib.
http://www.deepsoftware.com/nrcomm/nrcomm_pro.zip

Now it has TnrHid.Handle property and you can try the ReadReport() method again.

Roman Novgorodov
DeepSoftware.Com
DeepSoftware llc - The professional components for Delphi/CBuilder/.NET. The high quality custom software development.
Forums.nrCommLib.Com - DeepSoftware Tech Support Forum.

chedges

Ok, I installed the 8.21 version and re-tested. The HidD_GetInputReport function returns true :)

I've not been able to test it properly as for some reason the 8.21 version stops my WriteReport from working (The printer no longer prints at all).
if I switch back to my 8.20 registered version, printing works again!

Did something else change in the 8.21 version?

Roman Novgorodov

Yes, there are some changes.

The TnrHid.WriteReport() uses HidD_SetOutputReport() call now.

You can try to use TnrHid.SendData() instead TnrHid.WriteReport()

Roman Novgorodov
DeepSoftware.Com
DeepSoftware llc - The professional components for Delphi/CBuilder/.NET. The high quality custom software development.
Forums.nrCommLib.Com - DeepSoftware Tech Support Forum.

chedges

Hi again,

can you confirm I'm using the SendData method correctly as it doesn't seem to work.

function TForm6.WriteToPrinter(Data : String): Boolean;
var
  I: Integer;
  ToWrite: Cardinal;
  FGL : AnsiString;
  FGLPtr : PAnsiChar;
begin
    ToWrite := nrHID1.HidDevice.OutputReportLength;
    FGL := '0' + Data; // set the report Id - NOT SURE THIS IS CORRECT
    repeat
       FGL := FGL + '0';
    until Length(FGL) = ToWrite; //pad out the string to OutputReportLength

    FGLPtr := Addr(FGL[1]);  //get the address
   nrHId1.SendData(FGLPtr, ToWrite);
end;

Called as WriteToPrinter('Hello World<p>').

I'm not converting the chars into integers like I did wit the writeReport Method? is that correct?

Roman Novgorodov

Hi

Yes, It seems not correct:
FGL := '0' + Data; // set the report Id - NOT SURE THIS IS CORRECT

More better the following:
FGL := #0 + Data; 

Roman
DeepSoftware llc - The professional components for Delphi/CBuilder/.NET. The high quality custom software development.
Forums.nrCommLib.Com - DeepSoftware Tech Support Forum.