unit mr.drv.usb.winusb; interface uses Windows, mr.drv.usb.types, mr.drv.usb; type TWinUsbInterfaceHandle = THandle; TWinUsbDriver = class( TUsbDriver) public class procedure Scan( ScanCallback: TScanCallback); override; protected fWinUsbHandle : TWinUsbInterfaceHandle; public procedure Open; override; procedure Close; override; function GetDescriptor( DescriptorType : byte; Index : byte; LanguageID : word; Buffer : pointer; BufferLength : cardinal; var Transferred : cardinal) : boolean; override; function GetAssociatedInterface ( InterfaceIndex : byte; var InterfaceHandle ): boolean; override; function QueryInterfaceSettings ( AlternateSettingNumber : byte; var AlternateSettingDescriptor : TUsbAlternateSettingDescriptor ): boolean; override; function QueryPipe ( AlternateInterfaceNumber : byte; PipeIndex : byte; var PipeInformation : TusbPipeInformation ): boolean; override; function ControlTransfer ( SetupPacket : TUsbSetupPacket; Buffer : pointer; BufferLength : cardinal; var Transferred : cardinal; Overlapped : POverlapped = nil ): boolean; override; function AbortPipe( PipeID : byte): boolean; override; function FlushPipe( PipeID : byte): boolean; override; function ResetPipe( PipeID : byte): boolean; override; function ReadPipe ( PipeID : byte; Buffer : pointer; BufferLength : cardinal; var Transferred : cardinal; Overlapped : POverlapped = nil ): boolean; override; function WritePipe ( PipeID : byte; Buffer : pointer; BufferLength : cardinal; var Transferred : cardinal; Overlapped : POverlapped = nil ): boolean; override; function GetOverlappedResult ( Overlapped : POverlapped; var Transferred : cardinal; Wait : boolean ): boolean; override; public procedure AfterConstruction; override; procedure BeforeDestruction; override; end; implementation uses System.SysUtils, System.StrUtils, System.Win.ComObj, WinApi.ActiveX, WinApi.PropSys, WinApi.FunctionDiscovery, mr.dev.manager; type TWinUsb_Initialze = function( DeviceHandle : THandle; var WinUsbHandle : TWinUsbInterfaceHandle) : BOOL cdecl stdcall; TWinUsb_Free = function( WinUsbHandle : TWinUsbInterfaceHandle) : BOOL cdecl stdcall; TWinUsb_QueryDeviceInformation = function( WinUsbHandle : TWinUsbInterfaceHandle; InformationType : cardinal; var BufferLength : cardinal; var Buffer) : bool cdecl stdcall; TWinUsb_GetDescriptor = function( InterfaceHandle : TWinUsbInterfaceHandle; DescriptorType : byte; Index : byte; LanguageID : word; Buffer : pointer; BufferLength : cardinal; var Transferred : cardinal) : bool cdecl stdcall; TWinUsb_GetAssociatedInterface = function( WinUsbHandle : TWinUsbInterfaceHandle; InterfaceIndex : byte; var InterfaceHandle : TWinUsbInterfaceHandle): bool cdecl stdcall; TWinUsb_QueryInterfaceSettings = function( InterfaceHandle : TWinUsbInterfaceHandle; AlternateSettingNumber : byte; var AlternateSettingDescriptor : TUsbAlternateSettingDescriptor): bool cdecl stdcall; TWinUsb_QueryPipe = function( InterfaceHandle : TWinUsbInterfaceHandle; AlternateInterfaceNumber : byte; PipeIndex : byte; var PipeInformation : TusbPipeInformation): bool; cdecl stdcall; TWinUsb_GetCurrentAlternateSetting = function( InterfaceHandle : TWinUsbInterfaceHandle; var SettingNumber : byte): bool cdecl stdcall; TWinUsb_SetCurrentAlternateSetting = function( InterfaceHandle : TWinUsbInterfaceHandle; SettingNumber : byte): bool cdecl stdcall; TWinUsb_ControlTransfer = function( InterfaceHandle : TWinUsbInterfaceHandle; SetupPacket : TUsbSetupPacket; Buffer : pointer; BufferLength : cardinal; var Transferred : cardinal; Overlapped : POverlapped): bool cdecl stdcall; TWinUsb_ResetPipe = function( InterfaceHandle : TWinUsbInterfaceHandle; PipeId : byte): bool cdecl stdcall; TWinUsb_AbortPipe = function( InterfaceHandle : TWinUsbInterfaceHandle; PipeId : byte): bool cdecl stdcall; TWinUsb_FlushPipe = function( InterfaceHandle : TWinUsbInterfaceHandle; PipeId : byte): bool cdecl stdcall; TWinUsb_ReadPipe = function( InterfaceHandle : TWinUsbInterfaceHandle; PipeID : byte; Buffer : pointer; BufferLength : cardinal; var Transferred : cardinal; Overlapped : POverlapped): bool cdecl stdcall; TWinUsb_WritePipe = function( InterfaceHandle : TWinUsbInterfaceHandle; PipeID : byte; Buffer : pointer; BufferLength : cardinal; var Transferred : cardinal; Overlapped : POverlapped): bool cdecl stdcall; TWinUsb_GetOverlappedResult = function( InterfaceHandle : TWinUsbInterfaceHandle; Overlapped : POverlapped; var Transferred : cardinal; Wait : bool): bool cdecl stdcall; var hWinUsb : HMODULE = 0; WinUsb_Initialize : TWinUsb_Initialze = nil; WinUsb_Free : TWinUsb_Free = nil; WinUsb_QueryDeviceInformation : TWinUsb_QueryDeviceInformation = nil; WinUsb_GetDescriptor : TWinUsb_GetDescriptor = nil; WinUsb_GetAssociatedInterface : TWinUsb_GetAssociatedInterface = nil; WinUsb_QueryInterfaceSettings : TWinUsb_QueryInterfaceSettings = nil; WinUsb_GetCurrentAlternateSetting : TWinUsb_GetCurrentAlternateSetting = nil; WinUsb_SetCurrentAlternateSetting : TWinUsb_SetCurrentAlternateSetting = nil; WinUsb_ControlTransfer : TWinUsb_ControlTransfer = nil; WinUsb_QueryPipe : TWinUsb_QueryPipe = nil; WinUsb_ResetPipe : TWinUsb_ResetPipe = nil; WinUsb_AbortPipe : TWinUsb_AbortPipe = nil; WinUsb_FlushPipe : TWinUsb_FlushPipe = nil; WinUsb_ReadPipe : TWinUsb_ReadPipe = nil; WinUsb_WritePipe : TWinUsb_WritePipe = nil; WinUsb_GetOverlappedResult : TWinUsb_GetOverlappedResult = nil; { TWinUsbDriver } // ================================================================================================ // After Construction // ================================================================================================ procedure TWinUsbDriver.AfterConstruction; begin inherited; fWinUsbHandle := INVALID_HANDLE_VALUE; fDeviceHandle := INVALID_HANDLE_VALUE; end; // ================================================================================================ // Before Destrruction // ================================================================================================ procedure TWinUsbDriver.BeforeDestruction; begin Close; fWinUsbHandle := INVALID_HANDLE_VALUE; fDeviceHandle := INVALID_HANDLE_VALUE; inherited; end; // ================================================================================================ // Open // // DevicePath must be in the form of: // \\?\USB#VID_04B4&PID_8613#6&26c545a4&0&1#{CDDE880F-898A-4DAB-B0EA-51FBA32C1D82} // ================================================================================================ procedure TWinUsbDriver.Open; var path : WideString; len : cardinal; buf : byte; i : integer; begin path := WideString(fDevicePath); // --------------------------------------------------------------- // Prepare device path // --------------------------------------------------------------- // strip device description { i := Pos('#', path); if i > 0 then path := Copy( path, 1, i-1); path := ReplaceStr(path,'\','#'); path := '\\?\'+path+'#'+fInterfaceGuid; } // --------------------------------------------------------------- // open // --------------------------------------------------------------- if fDeviceHandle = INVALID_HANDLE_VALUE then begin fWinUsbHandle := 0; fDeviceHandle := CreateFile( PWideChar(path), GENERIC_READ + GENERIC_WRITE, FILE_SHARE_READ + FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED, 0); if fDeviceHandle <> INVALID_HANDLE_VALUE then begin // ------------------------------------------------------------------- // Initialize WinUSB // ------------------------------------------------------------------- WinUsb_Initialize( fDeviceHandle, fWinUsbHandle); // ------------------------------------------------------------------- // Determine bus speed // ------------------------------------------------------------------- len := 1; if WinUsb_QueryDeviceInformation( fWinUsbHandle, 1, len, buf) then case buf of 1: fDeviceSpeed := LowSpeed; 2: fDeviceSpeed := FullSpeed; 3: fDeviceSpeed := HighSpeed; end; // ------------------------------------------------------------------- // Get device descriptor // ------------------------------------------------------------------- WinUsb_GetDescriptor( fWinUsbHandle, DSCR_DEVICE, 0, // index (not used) 0, // language id (not used) @fDeviceDescriptor, sizeof(TUsbDeviceDescriptor), len); end; { b := i := 0; while WinUsb_QueryInterfaceSettings( fWinUsbHandle, i, sss) do INC(i); b := WinUsb_GetCurrentAlternateSetting( fWinUsbHandle, setting); b := WinUsb_SetCurrentAlternateSetting( fWinUsbHandle, setting); } end end; // ================================================================================================ // Close // ================================================================================================ procedure TWinUsbDriver.Close; begin if fWinUsbHandle <> INVALID_HANDLE_VALUE then begin WinUsb_Free( fWinUsbHandle); fWinUsbHandle := INVALID_HANDLE_VALUE; end; if fDeviceHandle <> INVALID_HANDLE_VALUE then begin CloseHandle( fDeviceHandle); fDeviceHandle := INVALID_HANDLE_VALUE; end end; // ================================================================================================ // Get Descriptor // ================================================================================================ function TWinUsbDriver.GetDescriptor( DescriptorType : byte; Index : byte; LanguageID : word; Buffer : pointer; BufferLength : cardinal; var Transferred : cardinal) : boolean; begin result := false; if Assigned( WinUsb_GetDescriptor) then result := WinUsb_GetDescriptor( fWinUsbHandle, DescriptorType, Index, LanguageID, Buffer, BufferLength, Transferred); end; // ================================================================================================ // Get Associated Interface // ================================================================================================ function TWinUsbDriver.GetAssociatedInterface( InterfaceIndex: byte; var InterfaceHandle): boolean; begin result := false end; // ================================================================================================ // QueryInterfaceSettings // ================================================================================================ function TWinUsbDriver.QueryInterfaceSettings( AlternateSettingNumber : byte; var AlternateSettingDescriptor: TUsbAlternateSettingDescriptor): boolean; begin result := false; if Assigned( WinUsb_QueryInterfaceSettings) then result := WinUsb_QueryInterfaceSettings( fWinUsbHandle, AlternateSettingNumber, AlternateSettingDescriptor); end; // ================================================================================================ // Query Pipe // ================================================================================================ function TWinUsbDriver.QueryPipe( AlternateInterfaceNumber: byte; PipeIndex : byte; var PipeInformation : TusbPipeInformation): boolean; begin result := false; if Assigned( WinUsb_QueryPipe) then result := WinUsb_QueryPipe( fWinUsbHandle, AlternateInterfaceNumber, PipeIndex, PipeInformation); end; // ================================================================================================ // Abort Pipe // ================================================================================================ function TWinUsbDriver.AbortPipe( PipeID: byte): boolean; begin if Assigned( WinUsb_AbortPipe) then result := WinUsb_AbortPipe( fWinUsbHandle, PipeID) else result := false end; // ================================================================================================ // Flush Pipe // ================================================================================================ function TWinUsbDriver.FlushPipe( PipeID: byte): boolean; begin if Assigned( WinUsb_FlushPipe) then result := WinUsb_FlushPipe( fWinUsbHandle, PipeID) else result := false end; // ================================================================================================ // Reset Pipe // ================================================================================================ function TWinUsbDriver.ResetPipe( PipeID: byte): boolean; begin if Assigned( WinUsb_ResetPipe) then result := WinUsb_ResetPipe( fWinUsbHandle, PipeID) else result := false end; // ================================================================================================ // Read Pipe // ================================================================================================ function TWinUsbDriver.ReadPipe( PipeID : byte; Buffer : pointer; BufferLength: cardinal; var Transferred : cardinal; Overlapped : POverlapped): boolean; begin result := false; if Assigned( WinUsb_ReadPipe) then result := WinUsb_ReadPipe( fWinUsbHandle, PipeID, Buffer, BufferLength, Transferred, Overlapped) end; // ================================================================================================ // Write Pipe // ================================================================================================ function TWinUsbDriver.WritePipe( PipeID : byte; Buffer : pointer; BufferLength: cardinal; var Transferred : cardinal; Overlapped : POverlapped): boolean; begin result := false; if Assigned( WinUsb_WritePipe) then result := WinUsb_WritePipe( fWinUsbHandle, PipeID, Buffer, BufferLength, Transferred, Overlapped) end; // ================================================================================================ // Control Transfer // ================================================================================================ function TWinUsbDriver.ControlTransfer( SetupPacket : TUsbSetupPacket; Buffer : pointer; BufferLength : cardinal; var Transferred : cardinal; Overlapped : POverlapped): boolean; begin result := false; if Assigned( WinUsb_ControlTransfer) then result := WinUsb_ControlTransfer( fWinUsbHandle, SetupPacket, Buffer, BufferLength, Transferred, Overlapped) end; // ================================================================================================ // Get Overlapped Result // ================================================================================================ function TWinUsbDriver.GetOverlappedResult( Overlapped : POverlapped; var Transferred : cardinal; Wait : boolean): boolean; begin result := false; if Assigned( WinUsb_GetOverlappedResult) then result := WinUsb_GetOverlappedResult( fWinUsbHandle, Overlapped, Transferred, Wait) end; // ================================================================================================ // scan // ================================================================================================ class procedure TWinUsbDriver.Scan( ScanCallback: TScanCallback); var dsc : IFunctionDiscovery; fcts : IFunctionInstanceCollection; fct : IFunctionInstance; props : IPropertyStore; propv : TPropVariant; hr : HResult; cat : PWChar; cnt : DWORD; i : integer; s : string; begin try dsc := CreateComObject( CLSID_FunctionDiscovery) as IFunctionDiscovery; cat := FCTN_CATEGORY_PNP; hr := dsc.GetInstanceCollection(cat, nil, true, fcts); if Succeeded(hr) and Succeeded(fcts.GetCount(cnt)) then for i := 0 to cnt -1 do if Succeeded( fcts.Item(i,fct)) then begin fct.OpenPropertyStore( STGM_READ, props); if Succeeded( props.GetValue(PKEY_Device_Service, propv)) then begin if 'WinUSB' = propv.pwszVal then begin // \\?\USB#VID_04B4&PID_8613#6&26c545a4&0&1#{CDDE880F-898A-4DAB-B0EA-51FBA32C1D82} props.GetValue( PKEY_Device_InstanceId, propv); s := StringReplace( propv.pwszVal, '\', '#', [rfReplaceAll]); s := Uppercase('\\?\' +s +'#' +fInterfaceGuid); ScanCallback( s) end end end finally end end; // @@@: Initialization / finalization +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Initialization / finalization // // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ var x: pointer = nil; initialization CoInitialize(x); hWinUsb := LoadLibrary('WinUsb.dll'); if hWinUsb <> 0 then begin @WinUsb_Initialize := GetProcAddress( hWinUsb, 'WinUsb_Initialize'); @WinUsb_Free := GetprocAddress( hWinUsb, 'WinUsb_Free'); @WinUsb_QueryDeviceInformation := GetProcAddress( hWinUsb, 'WinUsb_QueryDeviceInformation'); @WinUsb_GetDescriptor := GetProcAddress( hWinUsb, 'WinUsb_GetDescriptor'); @WinUsb_GetCurrentAlternateSetting := GetProcAddress( hWinUsb, 'WinUsb_GetCurrentAlternateSetting'); @WinUsb_SetCurrentAlternateSetting := GetProcAddress( hWinUsb, 'WinUsb_SetCurrentAlternateSetting'); @WinUsb_GetAssociatedInterface := GetProcAddress( hWinUsb, 'WinUsb_GetAssociatedInterface'); @WinUsb_QueryInterfaceSettings := GetProcAddress( hWinUsb, 'WinUsb_QueryInterfaceSettings'); @WinUsb_ControlTransfer := GetProcAddress( hWinUsb, 'WinUsb_ControlTransfer'); @WinUsb_QueryPipe := GetProcAddress( hWinUsb, 'WinUsb_QueryPipe'); @WinUsb_ResetPipe := GetProcAddress( hWinUsb, 'WinUsb_ResetPipe'); @WinUsb_AbortPipe := GetProcAddress( hWinUsb, 'WinUsb_AbortPipe'); @WinUsb_FlushPipe := GetProcAddress( hWinUsb, 'WinUsb_FlushPipe'); @WinUsb_ReadPipe := GetProcAddress( hWinUsb, 'WinUsb_ReadPipe'); @WinUsb_WritePipe := GetProcAddress( hWinUsb, 'WinUsb_WritePipe'); @WinUsb_GetOverlappedResult := GetProcAddress( hWinUsb, 'WinUsb_GetOverlappedResult'); // -------------------------------------------------------------------------------- // from driver 'inf' file // [Dev_AddReg] // HKR,,DeviceInterfaceGUIDs,0x10000,"{CDDE880F-898A-4DAB-B0EA-51FBA32C1D82}" // // This guid needed in 'CreateFile' function to open the device !!! // // The device path must look like this: // \\?\USB#VID_04B4&PID_8613#6&26c545a4&0&1#Cypress-FX2 // -------------------------------------------------------------------------------- // TWinUsbDriver.fDriverID := StringToGuid('{CDDE880F-898A-4DAB-B0EA-51FBA32C1D82}'); // RegisterDriver( TWinUsbDriver); end; finalization if hWinUsb <> 0 then FreeLibrary( hWinUsb); CoUninitialize; end.