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

Timing issue when sending multilple reports to a device

Started by chedges, February 18, 2009, 12:20:58 pm

Previous topic - Next topic

chedges

Hi Roman,

I've run into a problem when sending multiple reports to a device in fast succession. If you remember, I am writing to a printer and I need to send the data in 256byte reports.

I have found a problem when sending reports (The test I'm doing requires 4 reports of the same reportId) with no delay between them causes the printed output
to be corrupted. When I put a 100m/s pause between the reports the printing works fine.
I repeatedly check to see if the device is busy / cannot recieve data as I am writing the reports and I am 100% confident that the device is not going into a busy state.

I sent a demo app to the manufacturer and they were able to perform a USB trace to debug the problem. It seems that bytes are being lost when sending reports without a pause . My best guess is nrHID has not completed when it is called upon to transmit again and some of the bytes are not reaching the printer.

I don't want to have to use 100m/s delay between each report as this will badly effect print performance. Is there any way of determining if nrHID has written all the data and can send more? I presume this is / should be handled internally by the component

Thanks for your help

Chris Hedges


Roman Novgorodov

Hello Chris

I remember that you are using TnrHid.SendData() method for send reports. This function is asynchronous.

You can try to replace it by TnrHid.WriteReport() call.

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,

I used to use the WriteReport method but when I upgraded to the 8.21 version it stopped working for me, hence the switch to SendData.
I've tried using HidD_SetOutputReport and that doesn't seem to work either. What changed in the upgrade that stopped the WriteReport working?

thanks

Chris


Roman Novgorodov

Hello

Yes you are right.
The WriteReport() method was changed.
It uses HidD_SetOutputReport() API call now.

But your device works strange: it works good with HidD_GetInputReport() and it should support HidD_SetOutputReport() correctly too.

I will think more.

Do you remember, you showed me a VB sample that is read a HID report?
Do you have such sample from printer manufacturer that writes report?

Please try it to test device and be sure that device is working properly.

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,

Here is the VB code used to write to the printer. This works ok.



Public Sub Transmit(text_data As String)
       
Dim NumberOfBytesWritten As Long
Dim SendBuffer() As Byte
Dim i, Count As Integer
Dim pData As Long

ReDim SendBuffer(0 To (Capabilities.OutputReportByteLength - 1)) As Byte

    ' Check the USB pointer for readiness
    If WriteHandle = 0 Then
           
        Display_Text ("Unable to write to Boca Systems USB Printer.  Invalid write handle.")
       
    Else
           
        'Display_Text ("A Boca Systems USB Printer has been located")
           
        'This string needs to be converted into a byte array of ascii
        'integers to send to the printer. Convert will also initilize
        'ptr_buffer and Str_Size.
        Count = Len(text_data)
        Call Convert(text_data)
        'For i = 1 To Count
        '    SendBuffer(i) = Asc(Mid(text_data, i, 1))
        'Next i
       
        'The first byte is the Report ID
        For i = 0 To Capabilities.OutputReportByteLength - 1
            SendBuffer(i) = 0
        Next i
        For i = 1 To Capabilities.OutputReportByteLength - 1
            SendBuffer(i) = text(i - 1) 'text_data(i - 1)
        Next i
       
        'SendBuffer(0) = 0
        'For i = 1 To Count
        '    SendBuffer(i) = text(i - 1)
        'Next i

        'Display_Text ("string size = " + str(Str_Size))
           
        'Write converted text string and read for status response
        'Need to convert these to functions to receive return values as Longs???
        NumberOfBytesWritten = 0

        Result = WriteFile _
        (WriteHandle, _
        SendBuffer(0), _
        CLng(Capabilities.OutputReportByteLength), _
        NumberOfBytesWritten, _
        0)

    End If

End Sub

Roman Novgorodov

Hello Chris

The old version of TnrHid.WriteReport() used WriteFile call :-).
Now this method uses HidD_SetOutputReport() function.

Your device is real strange.
It uses HidD_GetInputReport() for read HID reports (and does not work with ReadFile())
At same time your printer wants WriteFile() for send report and does not support HidD_SetFeature() function.

OK.
We will think something more and will add new methods into TnrHid component.

Whilst I recommend you to call WriteFile like in your VB sample with TnrHid.Handle parameter.

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

chedges

Thanks for you help again Roman,

You have to love a challenge, especially when it's your first HID project ;)
Nothing is ever easy!

chedges

Hi Roman,

I'm getting a wierd Error 87 (Parameter is incorrect) when using the WriteFile method.
Have you seen this error before as the method itself looks pretty straightforward?

procedure TForm6.NewHIDWrite(Data : String);
var
  ToWrite, NumberOfBytesWritten: Cardinal;
  cnt : integer;
  Report : Array of Byte;
begin
    ToWrite := nrHid1.HidDevice.OutputReportLength;
    SetLength(Report, ToWrite);

    //init the buffer
    for cnt  := 0 to ToWrite - 1 do
      Report[cnt] := 0;

    //fill it!
    for cnt := 1 to Length(Data) do
      Report[cnt] := Ord(Data[cnt]);

    NumberOfBytesWritten := 0;
    if not WriteFile(nrHID1.Handle, Report, ToWrite, NumberOfBytesWritten, 0) then
      ShowMessage(SysErrorMessage(GetLastError));
end;


Roman Novgorodov

Hello Chris

You can try the following:

WriteFile(nrHID1.Handle, Report[0], ToWrite, NumberOfBytesWritten, 0)

But usual we are using Pointer or PChar variable for second parameter of this function.

By the way the new version of nrComm Lib is released.
It has some changes - new methods:

    function ReadReport(const pcReport:pointer; const ReportSize:cardinal):boolean;
    function WriteReport(const pcReport: pointer; const ReportSize:cardinal):boolean;

    function GetInputReport(const pcReport:pointer; const ReportSize:cardinal):boolean;
    function SetOutputReport(const pcReport: pointer; const ReportSize:cardinal):boolean;

Please ask me over email and you will receive latest release.

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

Thanks Roman,

The new version of WriteReport seems to be working perfectly

Thanks again for helping me out :)

Chris.