Author Topic: vb readfile woes returns 0  (Read 15010 times)

marting@thinklogical.com

  • Member
  • ***
  • Posts: 17
vb readfile woes returns 0
« on: October 02, 2013, 10:08:29 am »
Hi,
I have been trying things in vb.net and vb6 to get something to work.

I have a device connected to the PC that is streaming in USB data all the time.

Belo is the find the hid program I modified it slightly just to put all the code in one place.
It keeps returning from readfile (at the end) with a 0 though everything looks good.

Function FindTheHid(ChngMssg As Boolean) As Boolean
'Makes a series of API calls to locate the desired HID-class device.
'Returns True if the device is detected, False if not detected.
Dim buff(128) As Byte
Dim Count As Integer
Dim GUIDString As String
Dim ResultsString As String
Dim ProdIdString As String
Dim HidGuid As GUID
Dim MemberIndex As Long
Dim myDev As Boolean
Dim StrIndx As Long
Dim numBytesRead As Long
Dim TmpProdId As Integer
Dim xitDevSetUpLp As Boolean
Dim CypressVidFound As Boolean
Dim myDeviceDetectedLcl As Boolean

Dim RecBuffer(65) As Byte
Dim rdNum As Long
Dim error As String

CypressVidFound = False
myDev = False
DeviceConnected = True
LastDevice = False
myDeviceDetectedLcl = False
'If (myDeviceDetectedLcl = False) Then
'Values for SECURITY_ATTRIBUTES structure:
Security.lpSecurityDescriptor = 0
Security.bInheritHandle = True
Security.nLength = Len(Security)
ErrLevel = RET_NODEVCONN
'******************************************************************************
'HidD_GetHidGuid
'Get the GUID for all system HIDs.
'Returns: the GUID in HidGuid.
'The routine doesn't return a value in Result
'but the routine is declared as a function for consistency with the other API calls.
'******************************************************************************

CheckRev = True

Result = HidD_GetHidGuid(HidGuid)
Call DisplayResultOfAPICall("GetHidGuid")

'Display the GUID.
GUIDString = _
    Hex$(HidGuid.Data1) & "-" & _
    Hex$(HidGuid.Data2) & "-" & _
    Hex$(HidGuid.Data3) & "-"

For Count = 0 To 7
    'Ensure that each of the 8 bytes in the GUID displays two characters.
    If HidGuid.Data4(Count) >= &H10 Then
        GUIDString = GUIDString & Hex$(HidGuid.Data4(Count)) & " "
    Else
        GUIDString = GUIDString & "0" & Hex$(HidGuid.Data4(Count)) & " "
    End If
Next Count

' lstResults.AddItem "  GUID for system HIDs: " & GUIDString

'******************************************************************************
'SetupDiGetClassDevs
'Returns: a handle to a device information set for all installed devices.
'Requires: the HidGuid returned in GetHidGuid.
'******************************************************************************

DeviceInfoSet = SetupDiGetClassDevs _
    (HidGuid, _
    vbNullString, _
    0, _
    (DIGCF_PRESENT Or DIGCF_DEVICEINTERFACE))
   
Call DisplayResultOfAPICall("SetupDiClassDevs")
DataString = GetDataString(DeviceInfoSet, 32)

'******************************************************************************
'SetupDiEnumDeviceInterfaces
'On return, MyDeviceInterfaceData contains the handle to a
'SP_DEVICE_INTERFACE_DATA structure for a detected device.
'Requires:
'the DeviceInfoSet returned in SetupDiGetClassDevs.
'the HidGuid returned in GetHidGuid.
'An index to specify a device.
'******************************************************************************

'Begin with 0 and increment until no more devices are detected.
MemberIndex = 0

Do

    'The cbSize element of the MyDeviceInterfaceData structure must be set to
    'the structure's size in bytes. The size is 28 bytes.
    MyDeviceInterfaceData.cbSize = LenB(MyDeviceInterfaceData)
    Result = SetupDiEnumDeviceInterfaces _
        (DeviceInfoSet, _
        0, _
        HidGuid, _
        MemberIndex, _
        MyDeviceInterfaceData)
   
    Call DisplayResultOfAPICall("SetupDiEnumDeviceInterfaces")
    If Result = 0 Then LastDevice = True
   
    'If a device exists, display the information returned.
    If Result <> 0 Then
       
        '******************************************************************************
        'SetupDiGetDeviceInterfaceDetail
        'Returns: an SP_DEVICE_INTERFACE_DETAIL_DATA structure
        'containing information about a device.
        'To retrieve the information, call this function twice.
        'The first time returns the size of the structure in Needed.
        'The second time returns a pointer to the data in DeviceInfoSet.
        'Requires:
        'A DeviceInfoSet returned by SetupDiGetClassDevs and
        'an SP_DEVICE_INTERFACE_DATA structure returned by SetupDiEnumDeviceInterfaces.
        '*******************************************************************************
       
        MyDeviceInfoData.cbSize = Len(MyDeviceInfoData)
        Result = SetupDiGetDeviceInterfaceDetail _
           (DeviceInfoSet, _
           MyDeviceInterfaceData, _
           0, _
           0, _
           Needed, _
           0)
       
        DetailData = Needed
           
        Call DisplayResultOfAPICall("SetupDiGetDeviceInterfaceDetail")

       
        'Store the structure's size.
        MyDeviceInterfaceDetailData.cbSize = _
            Len(MyDeviceInterfaceDetailData)
       
        'Use a byte array to allocate memory for
        'the MyDeviceInterfaceDetailData structure
        ReDim DetailDataBuffer(Needed)
        'Store cbSize in the first four bytes of the array.
        Call RtlMoveMemory _
            (DetailDataBuffer(0), _
            MyDeviceInterfaceDetailData, _
            4)
       
        'Call SetupDiGetDeviceInterfaceDetail again.
        'This time, pass the address of the first element of DetailDataBuffer
        'and the returned required buffer size in DetailData.
        Result = SetupDiGetDeviceInterfaceDetail _
           (DeviceInfoSet, _
           MyDeviceInterfaceData, _
           VarPtr(DetailDataBuffer(0)), _
           DetailData, _
           Needed, _
           0)
       
        Call DisplayResultOfAPICall(" Result of second call: ")
       
        'Convert the byte array to a string.
        DevicePathName = CStr(DetailDataBuffer())
        'Convert to Unicode.
        DevicePathName = StrConv(DevicePathName, vbUnicode)
        'Strip cbSize (4 bytes) from the beginning.
        DevicePathName = Right$(DevicePathName, Len(DevicePathName) - 4)

               
        '******************************************************************************
        'CreateFile
        'Returns: a handle that enables reading and writing to the device.
        'Requires:
        'The DevicePathName returned by SetupDiGetDeviceInterfaceDetail.
        '******************************************************************************
        ' open as overlapped so we can timeout when not getting a response
        HIDHandle = CreateFile _
            (DevicePathName, _
            GENERIC_READ Or GENERIC_WRITE, _
            FILE_SHARE_READ Or FILE_SHARE_WRITE, _
            Security, _
            OPEN_EXISTING, _
            FILE_ATTRIBUTE_NORMAL, _
            0)
           
        Call DisplayResultOfAPICall("CreateFile")
        'lstResults.AddItem "  Returned handle: " & Hex$(HIDHandle) & "h"
        If (HIDHandle = &HFFFFFFFF) Then
            'lstResults.AddItem "Searching through additional HID's on this root hub controller"
            GoTo cont1
        End If
        'Now we can find out if it's the device we're looking for.
       
        '******************************************************************************
        'HidD_GetAttributes
        'Requests information from the device.
        'Requires: The handle returned by CreateFile.
        'Returns: an HIDD_ATTRIBUTES structure containing
        'the Vendor ID, Product ID, and Product Version Number.
        'Use this information to determine if the detected device
        'is the one we're looking for.
        '******************************************************************************
       
        'Set the Size property to the number of bytes in the structure.
        DeviceAttributes.Size = LenB(DeviceAttributes)
        Result = HidD_GetAttributes _
            (HIDHandle, _
            DeviceAttributes)
           
        If ((DeviceAttributes.VendorID <> MyVendorID) And (DeviceAttributes.VendorID <> MYVENDORID2)) Then
            'Close HIDHandle
            GoTo cont1
        End If
           
        Call DisplayResultOfAPICall("HidD_GetAttributes")
       
            ' this takes care of a little jumper issue on the RX that made the RX use the ADV7162 with the PLL

        ProdIdString = "  Product ID: " & Hex$(DeviceAttributes.ProductID)
        TmpProdId = DeviceAttributes.ProductID
        Do
            xitDevSetUpLp = True
            Select Case TmpProdId
                Case ST_SYSAUDIT
                    ResultsString = "Logical System Auditor Attached."
                    myDev = True
                   
                   
'                    Result = ReadFile _
'                    (HIDHandle, _
'                    RecBuffer(0), _
'                    CLng(Capabilities.InputReportByteLength), _
'                    rdNum, _
'                    Null)
                   
                   
                Case Else
'                    On Error GoTo handlebad
'                    Close HIDHandle
handlebad:          If ((LastDevice = True) And (ChngMssg = False)) Then
                        'lstResults.AddItem "Either there is no properly functioning Logical Device attached or this software does not support your device"
                        'lstResults.AddItem "Please Call Logical Solutions at (203) 783 9929"
                    End If
            End Select
        Loop Until xitDevSetUpLp = True

        'Find out if the device matches the one we're looking for.
        If myDev = True Then
                'It's the desired device.
                'lstResults.AddItem "  My device detected"
                myDeviceDetectedLcl = True
        Else
                myDeviceDetectedLcl = False
               
                'If it's not the one we want, close its handle.
                Result = CloseHandle _
                    (HIDHandle)
                HIDHandle = 0
                DisplayResultOfAPICall ("CloseHandle")
        End If
End If
    'Keep looking until we find the device or there are no more left to examine.
cont1:    MemberIndex = MemberIndex + 1

If myDeviceDetectedLcl = True Then
    Call GetDeviceCapabilities
    If (Capabilities.FeatureReportByteLength < 65) Then
        myDeviceDetectedLcl = False
        myDev = False
    End If
End If

Loop Until (LastDevice = True) Or (myDeviceDetectedLcl = True)

'Free the memory reserved for the DeviceInfoSet returned by SetupDiGetClassDevs.
Result = SetupDiDestroyDeviceInfoList _
    (DeviceInfoSet)
Call DisplayResultOfAPICall("DestroyDeviceInfoList")

If myDeviceDetectedLcl = True Then
    FindTheHid = True
   
    Result = CloseHandle(HIDHandle)

   
    error = GetErrorString(Err.LastDllError)
   
    'Learn the capabilities of the device
     Call GetDeviceCapabilities
'    'Get another handle for the overlapped ReadFiles.
    ReadHandle = CreateFile _
            (DevicePathName, _
            (GENERIC_READ), _
            (FILE_SHARE_READ Or FILE_SHARE_WRITE), _
            Security, _
            OPEN_EXISTING, _
            FILE_ATTRIBUTE_NORMAL, _
            0)
           
    DoEvents
    RecBuffer(4) = 0
    RecBuffer(5) = 0
    Result = ReadFile _
    (ReadHandle, _
    RecBuffer(0), _
    CLng(Capabilities.InputReportByteLength), _
    rdNum, _
    Null)

    Call DisplayResultOfAPICall("CreateFile, ReadHandle")
    'lstResults.AddItem "  Returned handle: " & Hex$(ReadHandle) & "h"
Else
    DeviceConnected = False
End If
MyDeviceDetected = myDeviceDetectedLcl
If myDeviceDetectedLcl = True Then FindTheHid = True
End Function

marting@thinklogical.com

  • Member
  • ***
  • Posts: 17
Re: vb readfile woes returns 0
« Reply #1 on: October 02, 2013, 10:15:44 am »
I forgot to mention that it sometimes works???
That makes it even more confusing.

The descriptors are
device 12 01 10 01 00 00 00 40 6A 15 1A 00 01 1E 04 2A 00 01
config 09 02 22 00 01 01 00 A0 FA 09 04 00 00 01 03 00 00 00 09 21 10 01 33 01 22 20 00 07 05 81 03 40 00 0A
report 06 A0 FF 09 01 A1 01 09 02 15 80 25 7F 75 08 95 40 B1 02 09 01 15 80 25 7F 75 08 95 40 81 02 C0

input reports are coming in every 10-100 ms
53 18 3D 01 04 07 00 31 31 20 20 20 6B 00 00 20 06 00 00 00 8F BF 00 00 9F 43 00 40 00 00 00 00 60 EA 00 00 06 00 00 00 60 EA 00 00 95 37 00 40 14 53 00 20 3E 53 00 20 3F 53 00 20 00 00 00 00

The reports are 65 bytes long but I only use about 16 of them most of the time

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: vb readfile woes returns 0
« Reply #2 on: October 02, 2013, 04:20:30 pm »
From a quick look, it appears that the report descriptor defines a 64-byte report (not 65):

75 08 95 40

Your example shows a 64-byte report.

The ReadFile buffer must be at least report size + 1 byte (65 bytes). The first byte is the report ID, which doesn't transmit on the bus if the report descriptor doesn't declare a report ID.

If the endpoint's max packet size = 64, the whole report should transmit in one transaction.

Where are you seeing the input reports "coming in"?

How big


 

marting@thinklogical.com

  • Member
  • ***
  • Posts: 17
Re: vb readfile woes returns 0
« Reply #3 on: October 03, 2013, 07:33:33 am »
Actually the fix was
' in form load
HIDOverlapped.Offset = 0
    HIDOverlapped.OffsetHigh = 0
    HIDOverlapped.hEvent = 0


' in read procedure
RecBuffer(4) = 0
            RecBuffer(5) = 0
            Result = ReadFile _
            (HIDHandle, _
            RecBuffer(0), _
            CLng(Capabilities.InputReportByteLength), _
            rdNum, _
            HIDOverlapped)

it looks like the documentation is wrong and you need the overlapped but you can set it to all 0

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: vb readfile woes returns 0
« Reply #4 on: October 03, 2013, 01:33:40 pm »
Glad you got it working.

A pointer to an OVERLAPPED structure is required if the hFile parameter was opened with FILE_FLAG_OVERLAPPED.

marting@thinklogical.com

  • Member
  • ***
  • Posts: 17
Re: vb readfile woes returns 0
« Reply #5 on: October 03, 2013, 01:41:09 pm »
agreed, but it wasn't it was opened FILE_ATTRIBUTE_NORMAL so it really makes no sense