Attribute VB_Name = "modWinUSB"
'Purpose:
' Windows DDK WinUSB API and Setup API Converted to Visual Basic 5/6
' Note: WinUSB Index represents CurrentControlSet device index
' MultiUSB Index represents Index of stored WinUsbDevice for multiple DPP devices
Option Explicit
'#Const bEnableDeviceNotification = 0
#Const bEnableDeviceNotification = 1
'Purpose: MultiUSB Index to DPP Serial Number storage type.
Public Type MUSB_SN_TO_INDEX
Index As Long 'WinUSB Device Information Array Index for Device
SerNum As Long 'DPP Device Serial Number
End Type
Public MUSB_MAX_INDEX As Long 'max index is 4 for five devices 0-4
Public MUSB_LAST_INDEX As Long 'last index is read fron vbDP5_MultiUSB.ini file
Public MUSB_SN(4) As Long 'multiusb serial numbers read from file
Public MUSB_Idx(4) As MUSB_SN_TO_INDEX 'multiusb serial numbers read from file
Public CurrentUSBDevice As Long 'WinUSB
Public NumUSBDevices As Long
'Purpose: Enumerates the error levels returned by ProcessError.
Public Type Message
hwnd As Long 'Handle of window.
Msg As Long 'Message.
wParam As Long 'First message parameter.
lParam As Long 'Second message parameter.
End Type
Public Enum ERRORLEVEL
elevCodeReturn 'Return error code.
elevDescReturn 'Return error description string.
elevSrcDescReturn 'Return error description string and error source string.
elevMsgBox 'Return/Display error description string and error source string.
End Enum
'Purpose: CopyMemory (RtlMoveMemory) moves memory either forward or backward, _
' aligned or unaligned, in 4-byte blocks, followed by any remaining bytes.
'
'
'Remarks: The (Source + Length) can overlap the Destination range passed in to CopyMemory (RtlMoveMemory).
'
'
'Parameter: Destination Points to the destination of the move.
'Parameter: Source Points to the memory to be copied.
'Parameter: Length Specifies the number of bytes to be copied.
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Const GWL_WNDPROC = (-4)
Public glngPrevWndProc As Long
Public Declare Function RtlMoveMemory Lib "kernel32" (Dest As Any, src As Any, ByVal Count As Long) As Long
Public Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA" (ByVal dwFlags As Long, ByRef lpSource As Any, ByVal dwMessageId As Long, ByVal dwLanguageZId As Long, ByVal lpBuffer As String, ByVal nSize As Long, ByVal Arguments As Long) As Long
Public Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
Public Const DBT_DEVICEARRIVAL As Long = 32768
Public Const DBT_DEVICEREMOVECOMPLETE As Long = 32772
Public Const DBT_DEVTYP_DEVICEINTERFACE As Long = 5
Public Const DEVICE_NOTIFY_WINDOW_HANDLE As Long = 0
Public Const WM_DEVICECHANGE As Long = &H219
Public Const DIGCF_PRESENT As Integer = &H2
Public Const DIGCF_DEVICEINTERFACE As Integer = &H10
Public Type Guid
D1 As Long
D2 As Integer
D3 As Integer
D4(7) As Byte
End Type
Public Type DEV_BROADCAST_DEVICEINTERFACE
dbcc_size As Long
dbcc_devicetype As Long
dbcc_reserved As Long
dbcc_classguid As Guid
dbcc_name As Long
End Type
Public Type DEV_BROADCAST_DEVICEINTERFACE2
dbcc_size As Long
dbcc_devicetype As Long
dbcc_reserved As Long
dbcc_classguid As Guid
dbcc_name As String * 1024
End Type
Public Type DEV_BROADCAST_HDR
dbch_size As Long
dbch_devicetype As Long
dbch_reserved As Long
End Type
Public Type SP_DEVICE_INTERFACE_DATA
cbSize As Long
InterfaceClassGuid As Guid
Flags As Long
Reserved As Long
End Type
Public Type SP_DEVICE_INTERFACE_DETAIL_DATA
cbSize As Long
DevicePath As Byte
'DataPath(256) As Byte
End Type
Public Declare Function SetupDiDestroyDeviceInfoList Lib "setupapi.dll" (ByVal DeviceInfoSet As Long) As Long
Public Declare Function SetupDiEnumDeviceInterfaces Lib "setupapi.dll" (ByVal DeviceInfoSet As Long, ByVal DeviceInfoData As Long, ByRef InterfaceClassGuid As Guid, ByVal MemberIndex As Long, ByRef DeviceInterfaceData As SP_DEVICE_INTERFACE_DATA) As Boolean
Public Declare Function SetupDiGetClassDevs Lib "setupapi.dll" Alias "SetupDiGetClassDevsA" (ByRef ClassGuid As Guid, ByVal Enumerator As String, ByVal hwndParent As Long, ByVal Flags As Long) As Long
Public Declare Function SetupDiGetDeviceInterfaceDetail Lib "setupapi.dll" Alias "SetupDiGetDeviceInterfaceDetailA" (ByVal DeviceInfoSet As Long, ByRef DeviceInterfaceData As SP_DEVICE_INTERFACE_DATA, ByVal DeviceInterfaceDetailData As Long, ByVal DeviceInterfaceDetailDataSize As Long, ByRef RequiredSize As Long, ByVal DeviceInfoData As Long) As Boolean
Public Declare Function RegisterDeviceNotification Lib "user32.dll" Alias "RegisterDeviceNotificationA" (ByVal hRecipient As Long, NotificationFilter As Any, ByVal Flags As Long) As Long
Public Declare Function UnregisterDeviceNotification Lib "user32.dll" (ByVal Handle As Long) As Boolean
Public Const FILE_ATTRIBUTE_NORMAL As Integer = &H80
Public Const FILE_FLAG_OVERLAPPED As Long = &H40000000
Public Const FILE_SHARE_READ As Integer = &H1
Public Const FILE_SHARE_WRITE As Integer = &H2
Public Const GENERIC_READ As Long = &H80000000
Public Const GENERIC_WRITE As Long = &H40000000
Public Const OPEN_EXISTING As Integer = 3
Public Type SECURITY_ATTRIBUTES
nLength As Long
lpSecurityDescriptor As Long
bInheritHandle As Long
End Type
Public Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Long) As Boolean
Public Declare Function CreateFile Lib "kernel32.dll" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByRef lpSecurityAttributes As SECURITY_ATTRIBUTES, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Public Enum PIPE_POLICY_TYPE
SHORT_PACKET_TERMINATE = &H1
AUTO_CLEAR_STALL
PIPE_TRANSFER_TIMEOUT
IGNORE_SHORT_PACKETS
ALLOW_PARTIAL_READS
AUTO_FLUSH
RAW_IO
MAXIMUM_TRANSFER_SIZE
End Enum
Public Type WINUSB_PIPE_INFORMATION
PipeType As USBD_PIPE_TYPE
PipeId As Byte
MaximumPacketSize As Integer
Interval As Byte
End Type
Public Enum USBD_PIPE_TYPE
UsbdPipeTypeControl
UsbdPipeTypeIsochronous
UsbdPipeTypeBulk
UsbdPipeTypeInterrupt
End Enum
Public Type USB_INTERFACE_DESCRIPTOR
bLength As Byte
bDescriptorType As Byte
bInterfaceNumber As Byte
bAlternateSetting As Byte
bNumEndpoints As Byte
bInterfaceClass As Byte
bInterfaceSubClass As Byte
bInterfaceProtocol As Byte
iInterface As Byte
End Type
Public Declare Function WinUsb_Initialize Lib "winusb.dll" (ByVal DeviceHandle As Long, ByRef InterfaceHandle As Long) As Boolean
Public Declare Function WinUsb_Free Lib "winusb.dll" (ByVal InterfaceHandle As Long) As Boolean
Public Declare Function WinUsb_QueryInterfaceSettings Lib "winusb.dll" (ByVal InterfaceHandle As Long, ByVal AlternateInterfaceNumber As Byte, ByRef UsbAltInterfaceDescriptor As USB_INTERFACE_DESCRIPTOR) As Boolean
Public Declare Function WinUsb_QueryPipe Lib "winusb.dll" (ByVal InterfaceHandle As Long, ByVal AlternateInterfaceNumber As Byte, ByVal PipeIndex As Byte, ByRef PipeInformation As WINUSB_PIPE_INFORMATION) As Boolean
Public Declare Function WinUsb_SetPipePolicy Lib "winusb.dll" (ByVal InterfaceHandle As Long, ByVal PipeId As Byte, ByVal PolicyType As Long, ByVal ValueLength As Long, ByRef Value As Byte) As Boolean
Public Declare Function WinUsb_SetPipePolicy1 Lib "winusb.dll" Alias "WinUsb_SetPipePolicy" (ByVal InterfaceHandle As Long, ByVal PipeId As Byte, ByVal PolicyType As Long, ByVal ValueLength As Long, ByRef Value As Long) As Boolean
Public Declare Function WinUsb_ReadPipe Lib "winusb.dll" (ByVal InterfaceHandle As Long, ByVal PipeId As Byte, ByRef Buffer As Byte, ByVal BufferLength As Long, ByRef LengthTransferred As Long, ByVal Overlapped As Long) As Boolean
Public Declare Function WinUsb_WritePipe Lib "winusb.dll" (ByVal InterfaceHandle As Long, ByVal PipeId As Byte, ByRef Buffer As Byte, ByVal BufferLength As Long, ByRef LengthTransferred As Long, ByVal Overlapped As Long) As Boolean
Public Declare Function WinUsb_ResetPipe Lib "winusb.dll" (ByVal InterfaceHandle As Long, ByVal PipeId As Byte) As Boolean
Public Declare Function WinUsb_AbortPipe Lib "winusb.dll" (ByVal InterfaceHandle As Long, ByVal PipeId As Byte) As Boolean
Public Declare Function WinUsb_FlushPipe Lib "winusb.dll" (ByVal InterfaceHandle As Long, ByVal PipeId As Byte) As Boolean
'Purpose: DPP WinUSB device information data type.
Public Type WinUsbDevice
DeviceHandle As Long 'Communications device resource handle.
winUsbHandle As Long 'WinUSB interface handle.
bulkInPipe As Long 'Bulk IN pipe id.
bulkOutPipe As Long 'Bulk OUT pipe id.
interruptInPipe As Long 'Interrupt IN pipe id.
interruptOutPipe As Long 'Interrupt OUT pipe id.
devicespeed As Long 'Device speed indicator.
SerNum As Long 'dpp serial number
idxUSB As Long 'WinUSB device index (1-NumDevices)
idxMUSB As Long 'MUSB array index
End Type
Public DppWinUSB As WinUsbDevice 'DppWinUSB device information
Public EmptyWinUSB As WinUsbDevice 'DppWinUSB device information
Public MultiWinUSB(4) As WinUsbDevice 'Multiple WinUSB device information, 0-4
Public NumMultiDpp As Long 'number of multiusb devices
Public USBDeviceNotificationHandle As Long
Public USBDeviceConnected As Boolean
Public USBDevicePathName As String
'Registry functions for counting WinUSB devices
Public Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long
Public Declare Function RegEnumValue Lib "advapi32.dll" Alias "RegEnumValueA" (ByVal hKey As Long, ByVal dwIndex As Long, ByVal lpValueName As String, lpcbValueName As Long, ByVal lpReserved As Long, lpType As Long, lpData As Any, lpcbData As Long) As Long
Public Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
Public Const HKEY_LOCAL_MACHINE = &H80000002
Public Const KEY_QUERY_VALUE = &H1
Public Const ERROR_SUCCESS = 0&
Public Const MAX_PATH = 260
Public Const MAXREGBUFFER = 128
Public Const MAXERRBUFFER = 256
Public Const MAX_DEVPATH_LENGTH = 256
Public Const NUM_ASYNCH_IO = 100
Public Const BUFFER_SIZE = 1024
Public Const MAXDP5S = 128 ' max number of devices
Public Const WinUSBService = "SYSTEM\CurrentControlSet\Services\WinUSB\Enum"
Public Const WinUsbDP5 = "USB\Vid_10c4&Pid_842a"
Public Const WinUsbDP5Size = 21
Public Const ERROR_NO_MORE_ITEMS = 259&
Public Const REG_NONE = 0 ' No value type
Public Const REG_DWORD = 4 ' 32-bit number
Public Function OpenDevice(hwnd As Long, ByRef DppWinUSB As WinUsbDevice, ByRef DeviceConnected As Boolean, DevicePathName As String, MemberIndex As Long) As Boolean
Dim deviceFound As Boolean
Dim NewDevicePathName As String
Dim success As Boolean
Dim winUsbDemoGuid As Guid
OpenDevice = False
NewDevicePathName = ""
On Error GoTo OpenDeviceErr
If Not DeviceConnected Then
winUsbDemoGuid.D1 = &H5A8ED6A1
winUsbDemoGuid.D2 = &H7FC3
winUsbDemoGuid.D3 = &H4B6A
winUsbDemoGuid.D4(0) = &HA5
winUsbDemoGuid.D4(1) = &H36
winUsbDemoGuid.D4(2) = &H95
winUsbDemoGuid.D4(3) = &HDF
winUsbDemoGuid.D4(4) = &H35
winUsbDemoGuid.D4(5) = &HD0
winUsbDemoGuid.D4(6) = &H34
winUsbDemoGuid.D4(7) = &H48
'Fill an array with the device path names of all attached devices with matching GUIDs.
deviceFound = FindDeviceFromGuid(winUsbDemoGuid, NewDevicePathName, MemberIndex)
If deviceFound = True Then
success = GetDeviceHandle(DppWinUSB, NewDevicePathName)
success = VbBool(success)
If (success) Then
DeviceConnected = True
DevicePathName = NewDevicePathName 'Save NewDevicePathName so OnDeviceChange() knows which name is Test device.
Else 'There was a problem in retrieving the information.
DeviceConnected = False
CloseDeviceHandle DppWinUSB
End If
End If
If DeviceConnected Then 'The device was detected.
#If (bEnableDeviceNotification) Then
'(Re)Register to receive notifications if the device is removed or attached.
If USBDeviceNotificationHandle <> 0 Then 'Unregister old notification before creating new
Call UnregisterDeviceNotification(USBDeviceNotificationHandle) 'Stop receiving notification messages.
End If
SetWindowLong hwnd, GWL_WNDPROC, glngPrevWndProc 'pass control back to previous windows
success = RegisterForDeviceNotifications(DevicePathName, hwnd, winUsbDemoGuid, USBDeviceNotificationHandle)
success = VbBool(success)
If success Then
glngPrevWndProc = GetWindowLong(hwnd, GWL_WNDPROC)
SetWindowLong hwnd, GWL_WNDPROC, AddressOf WndProc
InitializeDevice DppWinUSB
End If
#Else
InitializeDevice DppWinUSB
#End If
End If
End If
OpenDevice = DeviceConnected
Exit Function
OpenDeviceErr:
Call ProcessError(Err)
End Function
'Purpose: Copies WinUsbDevice storage.
'Parameter: Source WinUsbDevice storage to be saved
'Parameter: Destination WinUsbDevice storage copy
Public Sub CopyWinUsbDevice(Source As WinUsbDevice, Destination As WinUsbDevice)
Destination.DeviceHandle = Source.DeviceHandle 'Communications device resource handle.
Destination.winUsbHandle = Source.winUsbHandle 'WinUSB interface handle.
Destination.bulkInPipe = Source.bulkInPipe 'Bulk IN pipe id.
Destination.bulkOutPipe = Source.bulkOutPipe 'Bulk OUT pipe id.
Destination.interruptInPipe = Source.interruptInPipe 'Interrupt IN pipe id.
Destination.interruptOutPipe = Source.interruptOutPipe 'Interrupt OUT pipe id.
Destination.devicespeed = Source.devicespeed 'Device speed indicator.
Destination.SerNum = Source.SerNum 'dpp serial number
Destination.idxUSB = Source.idxUSB 'WinUSB device index (1-NumDevices)
Destination.idxMUSB = Source.idxMUSB 'MUSB array index
End Sub
Public Sub DeviceConnectedDisplay(rtbStatus As RichTextLib.RichTextBox, isDetected As Boolean)
If (isDetected) Then
UpdateStatusList rtbStatus, "Device connected.", RGB(0, 128, 0)
Else
UpdateStatusList rtbStatus, "Could not connect to device.", vbRed
End If
End Sub
Public Sub UpdateStatusList(rtbStatus As RichTextLib.RichTextBox, strStatus As String, Optional clrColor As Long = vbBlack)
On Error GoTo UpdateStatusListErr
StatusList rtbStatus, strStatus, clrColor
Exit Sub
UpdateStatusListErr:
Call ProcessError(Err)
End Sub
Public Sub StatusList(rtbStatus As RichTextLib.RichTextBox, strStatus As String, clrColor As Long, Optional bNL As Boolean = True)
Dim prvlen As Long
Dim strNL As String
On Error GoTo 0
prvlen = Len(rtbStatus.Text)
rtbStatus.SelStart = Len(rtbStatus.Text) + 1
strNL = ""
If (bNL) Then strNL = vbNewLine
rtbStatus.SelText = strStatus & strNL
rtbStatus.SelStart = prvlen
rtbStatus.SelLength = Len(strStatus & strNL)
rtbStatus.SelColor = clrColor
rtbStatus.SelStart = Len(rtbStatus.Text) + 1
End Sub
'Purpose: Closes the device handle obtained with CreateFile and frees resources.
Public Sub CloseDeviceHandle(DppWinUSB As WinUsbDevice)
Dim success As Boolean
On Error GoTo CloseDeviceHandleErr
success = WinUsb_Free(DppWinUSB.winUsbHandle)
success = VbBool(success)
If Not (DppWinUSB.DeviceHandle = 0) Then
If Not (DppWinUSB.DeviceHandle) Then
CloseHandle (DppWinUSB.DeviceHandle)
End If
End If
Exit Sub
CloseDeviceHandleErr:
Call ProcessError(Err)
End Sub
'Purpose: Requests a handle with CreateFile.
'
' Returns The handle.
'
'
'Parameter: devicePathName Returned by SetupDiGetDeviceInterfaceDetail
' in an SP_DEVICE_INTERFACE_DETAIL_DATA structure.
Public Function GetDeviceHandle(ByRef DppWinUSB As WinUsbDevice, ByVal DevicePathName As String) As Boolean
Dim security As SECURITY_ATTRIBUTES
security.lpSecurityDescriptor = 0
security.bInheritHandle = 1
security.nLength = Len(security)
DppWinUSB.DeviceHandle = CreateFile(DevicePathName, _
GENERIC_WRITE Or GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, _
security, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL Or FILE_FLAG_OVERLAPPED, 0)
If Not (DppWinUSB.DeviceHandle) Then
GetDeviceHandle = True
Else
MsgBox GetErrorString(Err.LastDllError)
GetDeviceHandle = False
End If
End Function
'Purpose: Initializes a device interface and obtains information about it. Calls these
' winusb API functions: WinUsb_Initialize,WinUsb_QueryInterfaceSettings, WinUsb_QueryPipe
'
' Returns True on success, False on failure.
'
'
'Parameter: DppWinUSB DPP WinUSB device information
Public Function InitializeDevice(ByRef DppWinUSB As WinUsbDevice) As Boolean
Dim ifaceDescriptor As USB_INTERFACE_DESCRIPTOR
Dim pipeInfo As WINUSB_PIPE_INFORMATION
Dim pipeTimeout As Long
Dim success As Boolean
Dim success1 As Boolean
Dim i As Long
pipeTimeout = 500 ' 2/4/10 - seems like 500mS should be plenty?
'Erase FPGA' takes 4s, worst case! Change timeout just for that command
On Error GoTo InitializeDeviceErr
success = WinUsb_Initialize(DppWinUSB.DeviceHandle, DppWinUSB.winUsbHandle)
success = VbBool(success)
If success Then
success = WinUsb_QueryInterfaceSettings(DppWinUSB.winUsbHandle, 0, ifaceDescriptor)
success = VbBool(success)
If success Then
' Get the transfer type, endpoint number, and direction for the interface's
' bulk and interrupt endpoints. Set pipe policies.
For i = 0 To ifaceDescriptor.bNumEndpoints - 1
success1 = WinUsb_QueryPipe(DppWinUSB.winUsbHandle, 0, CByte(i), pipeInfo)
success1 = VbBool(success1)
If ((pipeInfo.PipeType = USBD_PIPE_TYPE.UsbdPipeTypeBulk) And _
UsbEndpointDirectionIn(pipeInfo.PipeId)) Then
DppWinUSB.bulkInPipe = pipeInfo.PipeId
Call SetPipePolicy(DppWinUSB, CByte(DppWinUSB.bulkInPipe), CInt(PIPE_POLICY_TYPE.IGNORE_SHORT_PACKETS), False) ' this is the default, but set it anyway
Call SetPipePolicy(DppWinUSB, CByte(DppWinUSB.bulkInPipe), CInt(PIPE_POLICY_TYPE.AUTO_CLEAR_STALL), True) ' new - 2/5/2010
Call SetPipePolicy(DppWinUSB, CByte(DppWinUSB.bulkInPipe), CInt(PIPE_POLICY_TYPE.ALLOW_PARTIAL_READS), False) ' new - 5/25/2010
Call SetPipePolicy1(DppWinUSB, CByte(DppWinUSB.bulkInPipe), CInt(PIPE_POLICY_TYPE.PIPE_TRANSFER_TIMEOUT), pipeTimeout)
ElseIf ((pipeInfo.PipeType = USBD_PIPE_TYPE.UsbdPipeTypeBulk) And _
UsbEndpointDirectionOut(pipeInfo.PipeId)) Then
DppWinUSB.bulkOutPipe = pipeInfo.PipeId
'Call SetPipePolicy(CByte(DppWinUSB.bulkOutPipe), CInt(PIPE_POLICY_TYPE.IGNORE_SHORT_PACKETS), False)
Call SetPipePolicy(DppWinUSB, CByte(DppWinUSB.bulkOutPipe), CInt(PIPE_POLICY_TYPE.SHORT_PACKET_TERMINATE), True)
Call SetPipePolicy(DppWinUSB, CByte(DppWinUSB.bulkOutPipe), CInt(PIPE_POLICY_TYPE.AUTO_CLEAR_STALL), True)
Call SetPipePolicy1(DppWinUSB, CByte(DppWinUSB.bulkOutPipe), CInt(PIPE_POLICY_TYPE.PIPE_TRANSFER_TIMEOUT), pipeTimeout)
End If
Next i
Else
success = False
End If
End If
success = VbBool(success)
InitializeDevice = success
Exit Function
InitializeDeviceErr:
Call ProcessError(Err)
End Function
'Purpose: Sets pipe policy.
' Used when the value parameter is a byte (all except PIPE_TRANSFER_TIMEOUT).
'
' Returns True on success, False on failure.
'
'
'Parameter: PipeId Pipe to set a policy for.
'Parameter: PolicyType PIPE_POLICY_TYPE member.
'Parameter: Value Policy value.
Private Function SetPipePolicy(ByRef DppWinUSB As WinUsbDevice, ByVal PipeId As Byte, ByVal PolicyType As Long, ByVal Value As Boolean) As Boolean
Dim success As Boolean
On Error GoTo SetPipePolicyErr
success = WinUsb_SetPipePolicy(DppWinUSB.winUsbHandle, PipeId, PolicyType, 1, CByte(Value))
success = VbBool(success)
SetPipePolicy = success
Exit Function
SetPipePolicyErr:
Call ProcessError(Err)
End Function
'Purpose: Sets pipe policy.
' Used when the value parameter is a long (PIPE_TRANSFER_TIMEOUT only).
'
' Returns True on success, False on failure.
'
'
'Parameter: PipeId Pipe to set a policy for.
'Parameter: PolicyType PIPE_POLICY_TYPE member.
'Parameter: Value Policy value.
Public Function SetPipePolicy1(ByRef DppWinUSB As WinUsbDevice, ByVal PipeId As Byte, ByVal PolicyType As Long, ByVal Value As Long) As Boolean
Dim success As Boolean
SetPipePolicy1 = False
On Error GoTo SetPipePolicy1Err
success = WinUsb_SetPipePolicy1(DppWinUSB.winUsbHandle, PipeId, PolicyType, 4, Value)
success = VbBool(success)
SetPipePolicy1 = success
Exit Function
SetPipePolicy1Err:
Call ProcessError(Err)
End Function
'Purpose: Is the endpoint's direction IN (device to host)
'
' Returns True if IN (device to host), False if OUT (host to device)
'
'
'Parameter: addr The endpoint address.
Private Function UsbEndpointDirectionIn(ByVal addr As Long) As Boolean
On Error GoTo UsbEndpointDirectionInErr
If ((addr And &H80) = &H80) Then
UsbEndpointDirectionIn = True
Else
UsbEndpointDirectionIn = False
End If
Exit Function
UsbEndpointDirectionInErr:
Call ProcessError(Err)
End Function
'Purpose: Is the endpoint's direction OUT (host to device)
'
' Returns True if OUT (host to device, False if IN (device to host)
'
'
'Parameter: addr The endpoint address.
Private Function UsbEndpointDirectionOut(ByVal addr As Long) As Boolean
On Error GoTo UsbEndpointDirectionOutErr
If ((addr And &H80) = 0) Then
UsbEndpointDirectionOut = True
Else
UsbEndpointDirectionOut = False
End If
Exit Function
UsbEndpointDirectionOutErr:
Call ProcessError(Err)
End Function
'Purpose: Compares two device path names. Used to find out if the device name
' of a recently attached or removed device matches the name of a
' device the application is communicating with.
'
'
' Returns True if the names match, False if not.
'
'
'Parameter: m A WM_DEVICECHANGE message. A call to RegisterDeviceNotification
' causes WM_DEVICECHANGE messages to be passed to an OnDeviceChange routine..
'Parameter: DevicePathName A device pathname returned by SetupDiGetDeviceInterfaceDetail
' in an SP_DEVICE_INTERFACE_DETAIL_DATA structure.
Public Function DeviceNameMatch(m As Message, ByVal DevicePathName As String) As Boolean
Dim deviceNameString As String
Dim stringSize As Long
deviceNameString = ""
On Error GoTo DeviceNameMatchErr
Dim devBroadcastDeviceInterface As DEV_BROADCAST_DEVICEINTERFACE2
Dim devBroadcastHeader As DEV_BROADCAST_HDR
CopyMemory devBroadcastHeader, ByVal (m.lParam), Len(devBroadcastHeader)
If (devBroadcastHeader.dbch_devicetype = DBT_DEVTYP_DEVICEINTERFACE) Then
CopyMemory devBroadcastDeviceInterface, ByVal (m.lParam), ByVal (devBroadcastHeader.dbch_size)
stringSize = CInt((devBroadcastHeader.dbch_size - 32) / 2) + 1
deviceNameString = CStr(Left(devBroadcastDeviceInterface.dbcc_name, stringSize)) 'Store the device name in a String.
If (StrComp(deviceNameString, DevicePathName, vbTextCompare) = 0) Then 'Set ignorecase True.
DeviceNameMatch = True
Else
DeviceNameMatch = False
End If
End If
Exit Function
DeviceNameMatchErr:
Call ProcessError(Err)
End Function
'Purpose: Use SetupDi (Setup Device Installation) API functions to retrieve the device path name of an
' attached device that belongs to a device interface class.
'
'
' Returns True if a device is found, False if not.
'
'
'Parameter: TestGuid Interface class GUID.
'Parameter: devicePathName A pointer to the device path name of an attached device.
Public Function FindDeviceFromGuid(ByRef TestGuid As Guid, ByRef DevicePathName As String, MemberIndex As Long) As Boolean
Dim bufferSize As Long
Dim bufferSizeReq As Long
Dim detailDataBuffer() As Byte
Dim DevDetailData As SP_DEVICE_INTERFACE_DETAIL_DATA
Dim deviceFound As Boolean
Dim DeviceInfoSet As Long
Dim lastDevice As Boolean
Dim TestDeviceInterfaceData As SP_DEVICE_INTERFACE_DATA
'Dim pDevicePathName As Long
Dim success As Boolean
Dim pDevicePathName As String
On Error GoTo FindDeviceFromGuidErr
DeviceInfoSet = SetupDiGetClassDevs(TestGuid, vbNullString, 0, DIGCF_PRESENT Or DIGCF_DEVICEINTERFACE)
deviceFound = False
'MemberIndex = 0
'Do
TestDeviceInterfaceData.cbSize = Len(TestDeviceInterfaceData) 'The size is 28 bytes.
success = SetupDiEnumDeviceInterfaces(DeviceInfoSet, 0, TestGuid, MemberIndex, TestDeviceInterfaceData)
success = VbBool(success)
If (Not CBool(success)) Then 'Find out if a device information set was retrieved.
lastDevice = True
Else 'A device is present.
success = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, TestDeviceInterfaceData, 0, 0, bufferSize, 0)
success = VbBool(success)
DevDetailData.cbSize = Len(DevDetailData)
ReDim detailDataBuffer(bufferSize) '
Call RtlMoveMemory(detailDataBuffer(0), DevDetailData, 4)
success = SetupDiGetDeviceInterfaceDetail _
(DeviceInfoSet, _
TestDeviceInterfaceData, _
VarPtr(detailDataBuffer(0)), _
bufferSize, _
bufferSizeReq, _
0)
success = VbBool(success)
pDevicePathName = CStr(detailDataBuffer()) 'Convert the byte array to a string.
pDevicePathName = StrConv(pDevicePathName, vbUnicode) 'Convert to Unicode.
pDevicePathName = Right$(pDevicePathName, Len(pDevicePathName) - 4) 'Strip cbSize (4 bytes) from the beginning.
DevicePathName = pDevicePathName 'Get the String containing the devicePathName.
deviceFound = True
End If
'MemberIndex = MemberIndex + 1
'Loop Until (lastDevice = True)
SetupDiDestroyDeviceInfoList (DeviceInfoSet)
FindDeviceFromGuid = deviceFound
Exit Function
FindDeviceFromGuidErr:
Call ProcessError(Err)
End Function
'Purpose: Requests to receive a notification when a device is attached or removed.
'
'
' Returns True on success, False otherwise.
'
'
'Parameter: devicePathName Handle to a device.
'Parameter: formHandle Handle to the window that will receive device events.
'Parameter: classGuid Device interface GUID.
'Parameter: deviceNotificationHandle Returned device notification handle.
Public Function RegisterForDeviceNotifications(ByVal DevicePathName As String, ByVal formHandle As Long, ByRef ClassGuid As Guid, ByRef deviceNotificationHandle As Long) As Boolean
Dim devBroadcastDeviceInterface As DEV_BROADCAST_DEVICEINTERFACE
Dim devBroadcastDeviceInterfaceBuffer As Long
Dim size As Long
On Error GoTo RegisterForDeviceNotificationsErr
size = Len(devBroadcastDeviceInterface) 'Set the size.
devBroadcastDeviceInterface.dbcc_size = size
devBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE
devBroadcastDeviceInterface.dbcc_reserved = 0
devBroadcastDeviceInterface.dbcc_classguid = ClassGuid 'Specify the interface class to receive notifications about.
#If (bEnableDeviceNotification) Then
deviceNotificationHandle = RegisterDeviceNotification(formHandle, devBroadcastDeviceInterface, DEVICE_NOTIFY_WINDOW_HANDLE)
If (deviceNotificationHandle = 0#) Then
RegisterForDeviceNotifications = False
Else
RegisterForDeviceNotifications = True
End If
#Else
RegisterForDeviceNotifications = False
#End If
Exit Function
RegisterForDeviceNotificationsErr:
Call ProcessError(Err)
End Function
'Purpose: Returns and/or displays process error messages
Public Function ProcessError(errError As ErrObject, Optional errSource As String = "", Optional errControl As ERRORLEVEL = elevSrcDescReturn) As Variant
Select Case errControl
Case elevCodeReturn
ProcessError = errError.Number
Case elevDescReturn
ProcessError = errError.Description
Case elevSrcDescReturn
ProcessError = errSource & " : " & errError.Description
Case elevMsgBox
ProcessError = errSource & " : " & errError.Description
MsgBox errError.Description, vbCritical, errSource
Case Else
ProcessError = errSource & " : " & errError.Description
End Select
MsgBox errError.Description & " " & errError.LastDllError
End Function
'Purpose: Converts any C boolean type to a VB boolean type
Public Function VbBool(bBool As Variant) As Boolean
On Error GoTo VbBoolErr
VbBool = False
If (bBool = 0) Then
VbBool = False
Else
VbBool = True
End If
Exit Function
VbBoolErr:
End Function
'Purpose: Returns the error message for the last error.
'Adapted from Dan Appleman's "Win32 API Puzzle Book"
Public Function GetErrorString(ByVal LastError As Long) As String
Dim Bytes As Long
Dim ErrorString As String
ErrorString = String$(129, 0)
Bytes = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0&, LastError, 0, ErrorString$, 128, 0)
'Subtract two characters from the message to strip the CR and LF.
If Bytes > 2 Then
GetErrorString = Left$(ErrorString, Bytes - 2)
End If
End Function
#If (bEnableDeviceNotification) Then
'Purpose: Overrides WndProc to enable checking for and handling WM_DEVICECHANGE messages.
'Parameter: Windows message info
Public Function WndProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
On Error GoTo WndProcErr
If Msg = WM_DEVICECHANGE Then 'The OnDeviceChange routine processes WM_DEVICECHANGE messages.
'frmDP5.OnDeviceChange hWnd, Msg, wParam, lParam
frmDP5.OnDeviceChange hwnd, Msg, wParam, lParam
End If
Debug.Print Msg
'Pass the messages onto VB's own Window Procedure to let the base form process the message.
WndProc = CallWindowProc(glngPrevWndProc, hwnd, Msg, wParam, lParam)
Exit Function
WndProcErr:
Call ProcessError(Err)
End Function
#End If
'Purpose: Counts the number of WinUSB DPP device connected
Public Function CountDP5WinusbDevices()
Dim hKey As Long
Dim retCode As Long
Dim lRet As Long
Dim idxDP5 As Long
Dim DevicePath(MAXREGBUFFER - 1) As Byte
Dim cbDevicePath As Long
Dim KeyName As String
Dim cbKeyName As Long
Dim ErrMsg As String
Dim cbErrMsg As Long
Dim strDevicePath As String
NumUSBDevices = 0
retCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WinUSBService, 0&, KEY_QUERY_VALUE, hKey)
If (retCode <> ERROR_SUCCESS) Then
CountDP5WinusbDevices = 0
Exit Function
End If
KeyName = Space(MAX_PATH)
' Test ALL Keys (0,1,... are device paths, Count,NextInstance,(Default) have other info)
For idxDP5 = 0 To (MAXDP5S + 3) - 1 'devs + 3 other keys
cbKeyName = MAX_PATH
cbDevicePath = MAXREGBUFFER
retCode = RegEnumValue(hKey, idxDP5, ByVal KeyName, cbKeyName, 0&, REG_NONE, DevicePath(0), cbDevicePath)
If (retCode = ERROR_SUCCESS) Then
strDevicePath = ByteArrayToString(DevicePath)
If (StrComp(Left(KeyName, 5), "Count", vbTextCompare) = 0) Then
'do nothing
ElseIf (StrComp(Left(strDevicePath, WinUsbDP5Size), WinUsbDP5, vbTextCompare) = 0) Then ' DP5 device path found
'TRACE("DP5 device [%d]: %s=%s\r\n", (NumUSBDevices + 1), KeyName, DevicePath);
NumUSBDevices = NumUSBDevices + 1
End If
ElseIf (retCode = ERROR_NO_MORE_ITEMS) Then ' no more values to read
Exit For
Else ' error reading values
cbErrMsg = MAXERRBUFFER
ErrMsg = Space(MAXERRBUFFER)
lRet = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0&, retCode, 0&, ErrMsg, cbErrMsg, 0&)
If (lRet > 0) Then ErrMsg = Left(ErrMsg, lRet) Else ErrMsg = ""
'MsgBox ErrMsg
Exit For
End If
Next
Call RegCloseKey(hKey)
CountDP5WinusbDevices = NumUSBDevices '/* return number of devices */
End Function
Public Function ByteArrayToString(byteArray() As Byte) As String
Dim str As String
Dim PosTerminator As String
str = StrConv(byteArray, vbUnicode)
PosTerminator = InStr(str, Chr(0))
If PosTerminator > 0 Then str = Left(str, PosTerminator - 1)
ByteArrayToString = str
End Function