This commit is contained in:
2026-01-08 19:04:51 +01:00
parent b9305ab8af
commit cb039a3035
14 changed files with 723 additions and 338 deletions
+6 -5
View File
@@ -31,10 +31,9 @@ package mr.devmgr;
requires requires
rtl, rtl,
vcl; vcl,
// spring.core, mr.jtag,
// mr.dpgrtl, spring.base;
// mr.jtag;
contains contains
mr.drv in '..\..\src.devmgr\drv\mr.drv.pas', mr.drv in '..\..\src.devmgr\drv\mr.drv.pas',
@@ -66,6 +65,8 @@ contains
m.eeprom in '..\..\src.devmgr\dev\usb\trinity\modules\eeprom\m.eeprom.pas', m.eeprom in '..\..\src.devmgr\dev\usb\trinity\modules\eeprom\m.eeprom.pas',
m.eeprom.types in '..\..\src.devmgr\dev\usb\trinity\modules\eeprom\m.eeprom.types.pas', m.eeprom.types in '..\..\src.devmgr\dev\usb\trinity\modules\eeprom\m.eeprom.types.pas',
m.cfg in '..\..\src.devmgr\dev\usb\trinity\modules\cfg\m.cfg.pas', m.cfg in '..\..\src.devmgr\dev\usb\trinity\modules\cfg\m.cfg.pas',
m.cfg.types in '..\..\src.devmgr\dev\usb\trinity\modules\cfg\m.cfg.types.pas'; m.cfg.types in '..\..\src.devmgr\dev\usb\trinity\modules\cfg\m.cfg.types.pas',
mr.drv.usb.notifier in '..\..\src.devmgr\drv\usb\mr.drv.usb.notifier.pas',
mr.drv.trinity in '..\..\src.devmgr\drv\usb\mr.drv.trinity.pas';
end. end.
+6 -3
View File
@@ -60,7 +60,7 @@
<SanitizedProjectName>mr_devmgr</SanitizedProjectName> <SanitizedProjectName>mr_devmgr</SanitizedProjectName>
<VerInfo_Locale>1033</VerInfo_Locale> <VerInfo_Locale>1033</VerInfo_Locale>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys> <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
<DllSuffix>.270</DllSuffix> <DllSuffix>.290</DllSuffix>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Base_Win32)'!=''"> <PropertyGroup Condition="'$(Base_Win32)'!=''">
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace> <DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
@@ -85,7 +85,6 @@
<DCC_RemoteDebug>false</DCC_RemoteDebug> <DCC_RemoteDebug>false</DCC_RemoteDebug>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo> <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<DCC_Description>mr Device Manager for USB devices</DCC_Description> <DCC_Description>mr Device Manager for USB devices</DCC_Description>
<DllSuffix>.290</DllSuffix>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''"> <PropertyGroup Condition="'$(Cfg_2)'!=''">
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols> <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
@@ -102,6 +101,8 @@
</DelphiCompile> </DelphiCompile>
<DCCReference Include="rtl.dcp"/> <DCCReference Include="rtl.dcp"/>
<DCCReference Include="vcl.dcp"/> <DCCReference Include="vcl.dcp"/>
<DCCReference Include="mr.jtag.dcp"/>
<DCCReference Include="spring.base.dcp"/>
<DCCReference Include="..\..\src.devmgr\drv\mr.drv.pas"/> <DCCReference Include="..\..\src.devmgr\drv\mr.drv.pas"/>
<DCCReference Include="..\..\src.devmgr\drv\usb\mr.drv.usb.pas"/> <DCCReference Include="..\..\src.devmgr\drv\usb\mr.drv.usb.pas"/>
<DCCReference Include="..\..\src.devmgr\drv\usb\mr.drv.usb.types.pas"/> <DCCReference Include="..\..\src.devmgr\drv\usb\mr.drv.usb.types.pas"/>
@@ -132,6 +133,8 @@
<DCCReference Include="..\..\src.devmgr\dev\usb\trinity\modules\eeprom\m.eeprom.types.pas"/> <DCCReference Include="..\..\src.devmgr\dev\usb\trinity\modules\eeprom\m.eeprom.types.pas"/>
<DCCReference Include="..\..\src.devmgr\dev\usb\trinity\modules\cfg\m.cfg.pas"/> <DCCReference Include="..\..\src.devmgr\dev\usb\trinity\modules\cfg\m.cfg.pas"/>
<DCCReference Include="..\..\src.devmgr\dev\usb\trinity\modules\cfg\m.cfg.types.pas"/> <DCCReference Include="..\..\src.devmgr\dev\usb\trinity\modules\cfg\m.cfg.types.pas"/>
<DCCReference Include="..\..\src.devmgr\drv\usb\mr.drv.usb.notifier.pas"/>
<DCCReference Include="..\..\src.devmgr\drv\usb\mr.drv.trinity.pas"/>
<BuildConfiguration Include="Base"> <BuildConfiguration Include="Base">
<Key>Base</Key> <Key>Base</Key>
</BuildConfiguration> </BuildConfiguration>
@@ -168,7 +171,7 @@
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule"/> <DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule"/>
<DeployFile LocalName="C:\Users\Public\Documents\Embarcadero\Studio\21.0\Bpl\mr_devmgr.bpl" Configuration="Debug" Class="ProjectOutput"/> <DeployFile LocalName="C:\Users\Public\Documents\Embarcadero\Studio\21.0\Bpl\mr_devmgr.bpl" Configuration="Debug" Class="ProjectOutput"/>
<DeployFile LocalName="C:\Users\Public\Documents\Embarcadero\Studio\21.0\Bpl\mr_devmgr.bpl" Configuration="Release" Class="ProjectOutput"/> <DeployFile LocalName="C:\Users\Public\Documents\Embarcadero\Studio\21.0\Bpl\mr_devmgr.bpl" Configuration="Release" Class="ProjectOutput"/>
<DeployFile LocalName="C:\Users\Public\Documents\Embarcadero\Studio\23.0\Bpl\mr.devmgr.270.bpl" Configuration="Debug" Class="ProjectOutput"> <DeployFile LocalName="C:\Users\Public\Documents\Embarcadero\Studio\23.0\Bpl\mr.devmgr.290.bpl" Configuration="Debug" Class="ProjectOutput">
<Platform Name="Win32"> <Platform Name="Win32">
<RemoteName>mr.devmgr.bpl</RemoteName> <RemoteName>mr.devmgr.bpl</RemoteName>
<Overwrite>true</Overwrite> <Overwrite>true</Overwrite>
+2 -2
View File
@@ -5,9 +5,9 @@ uses
mr.drv; mr.drv;
type type
TDevice = class(TInterfacedObject) TDevice = class
protected protected
fDriver: TDriver; fDriver : TDriver;
public public
procedure Open; virtual; abstract; procedure Open; virtual; abstract;
@@ -14,7 +14,7 @@ type
procedure Cls; procedure Cls;
procedure GotoXY( x,y: word); procedure GotoXY( x,y: word);
procedure putc( const c: AnsiChar); procedure putc( const c: AnsiChar);
// procedure puts( const s: AnsiString); procedure puts( const s: AnsiString);
end; end;
implementation implementation
@@ -429,7 +429,7 @@ begin
// blk.Address; // blk.Address;
// blk.BlockLength; // blk.BlockLength;
s := Format('%3d %4.4x-%4.4x (%4.4x)'#13, [i,blk.Address,blk.Address+blk.BlockLength, blk.BlockLength]); s := Format('%3d %4.4x-%4.4x (%4.4x)'#13, [i,blk.Address,blk.Address+blk.BlockLength, blk.BlockLength]);
writeln(s); // writeln(s);
INC(i); INC(i);
end; end;
+23 -17
View File
@@ -41,7 +41,7 @@ type
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// TTrinity // TTrinity
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
TTrinity = class (TUsbDevice, ITrinity, IIIC, ILCD, ILED, IEEPROM, IJTAG, ICFG) TTrinity = class (TUsbDevice)
protected protected
fCaps : TCapabilities; fCaps : TCapabilities;
fCaps64 : Int64; fCaps64 : Int64;
@@ -76,17 +76,17 @@ type
fModCFG : ICFG; fModCFG : ICFG;
fModIIC : IIIC; fModIIC : IIIC;
fModEPR : IEEPROM; fModEPR : IEEPROM;
fModJTAG : IJTAG; fModJTG : IJTAG;
fModLCD : ILCD; fModLCD : ILCD;
fModLED : ILED; fModLED : ILED;
protected public
property cfg : ICFG read fModCFG implements ICFG; property cfg : ICFG read fModCFG;
property iic : IIIC read fModIIC implements IIIC; property iic : IIIC read fModIIC;
property eeprom : IEEPROM read fModEPR implements IEEPROM; property eeprom : IEEPROM read fModEPR;
property jtag : IJTAG read fModJTAG implements IJTAG; property jtag : IJTAG read fModJTG;
property lcd : ILCD read fModLCD implements ILCD; property lcd : ILCD read fModLCD;
property led : ILED read fModLED implements ILED; property led : ILED read fModLED;
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// construction / destruction // construction / destruction
@@ -159,12 +159,12 @@ begin
fPipe0Class := TTrinityPipe0; fPipe0Class := TTrinityPipe0;
fModCFG := TmodCFG .Create( self); fModCFG := TmodCFG .Create( self);
fModIIC := TmodIIC .Create( self); fModIIC := TmodIIC .Create( self);
fModEPR := TmodEEPROM .Create( self); fModEPR := TmodEEPROM .Create( self);
fModLCD := TmodLCD .Create( self); fModLCD := TmodLCD .Create( self);
fModLED := TmodLED .Create( self); fModLED := TmodLED .Create( self);
fModJTAG := TmodJTAG .Create( self); fModJTG := TmodJTAG .Create( self);
end; end;
// ================================================================================================ // ================================================================================================
@@ -172,11 +172,16 @@ end;
// ================================================================================================ // ================================================================================================
procedure TTrinity.BeforeDestruction; procedure TTrinity.BeforeDestruction;
begin begin
fModCFG := nil;
fModIIC := nil;
fModEPR := nil;
fModLCD := nil;
fModLED := nil;
fModJTG := nil;
inherited inherited
end; end;
function TTrinity.Capabilities: TCapabilities; function TTrinity.Capabilities: TCapabilities;
begin begin
result := fCaps result := fCaps
@@ -244,6 +249,7 @@ begin
fCaps64 := PInt64(@buf)^; fCaps64 := PInt64(@buf)^;
fCaps := DecodeCapabilities(fCaps64); fCaps := DecodeCapabilities(fCaps64);
end end
end end
end; end;
@@ -86,7 +86,7 @@ begin
if cap in caps then if cap in caps then
begin begin
if result <> '' then if result <> '' then
result := result +','; result := result +', ';
case cap of case cap of
capSER : result := result +'SER'; capSER : result := result +'SER';
@@ -99,9 +99,7 @@ begin
capLCD2 : result := result +'LCD2'; capLCD2 : result := result +'LCD2';
end; end;
end; end
end; end;
end. end.
+10 -3
View File
@@ -3,7 +3,11 @@ unit mr.drv;
interface interface
type type
TDriver = class abstract( TInterfacedObject) TDriver = class abstract
protected
class var
fInterfaceGuid : string;
protected protected
fDeviceHandle : THandle; fDeviceHandle : THandle;
fDevicePath : string; fDevicePath : string;
@@ -13,8 +17,11 @@ type
procedure Close; virtual; abstract; procedure Close; virtual; abstract;
public public
property DevicePath : string read fDevicePath; class property InterfaceGUID: string read fInterfaceGuid;
property DeviceHandle : THandle read fDeviceHandle;
public
property DevicePath : string read fDevicePath;
property DeviceHandle : THandle read fDeviceHandle;
end; end;
TDriverClass = class of TDriver; TDriverClass = class of TDriver;
+24
View File
@@ -0,0 +1,24 @@
unit mr.drv.trinity;
interface
uses
mr.drv.usb.winusb;
type TTrinityDriver = class (TWinUsbDriver)
class constructor CreateClass;
end;
implementation
uses
mr.dev.manager;
class constructor TTrinityDriver.CreateClass;
begin
fInterfaceGUID := '{CDDE880F-898A-4DAB-B0EA-51FBA32C1D82}';
end;
initialization
RegisterDriver( TTrinityDriver);
end.
+188
View File
@@ -0,0 +1,188 @@
unit mr.drv.usb.notifier;
interface
uses
System.Classes,
Winapi.Windows,
Winapi.Messages,
mr.drv.usb;
const
DBT_DEVTYP_DEVICEINTERFACE = $00000005; // device interface class
DBT_DEVICEARRIVAL = $8000; // system detected a new device
DBT_DEVICEQUERYREMOVE = $8001;
DBT_DEVICEQUERYREMOVEFAILED= $8002;
DBT_DEVICEREMOVEPENDING = $8003;
DBT_DEVICEREMOVECOMPLETE = $8004; // device is gone
DBT_DEVICETYPESPECIFIC = $8005;
type
TusbNotifyEvent = procedure( APath: string; ADriverClass: TUsbDriverClass) of object;
PDevBroadcastHdr = ^DEV_BROADCAST_HDR;
DEV_BROADCAST_HDR = packed record
dbch_size : DWORD;
dbch_devicetype: DWORD;
dbch_reserved : DWORD;
end;
PDevBroadcastDeviceInterface = ^DEV_BROADCAST_DEVICEINTERFACE;
DEV_BROADCAST_DEVICEINTERFACE = record
dbcc_size : DWORD;
dbcc_devicetype: DWORD;
dbcc_reserved : DWORD;
dbcc_classguid : TGUID;
dbcc_name : char;
end;
type
TusbNotifier = class
private
fDeviceInterface : string;
fDriverClass : TUsbDriverClass;
fNotifyHandle : HDEVNOTIFY;
FWindowHandle : HWND;
FOnUSBArrival : TusbNotifyEvent;
FOnUSBRemove : TusbNotifyEvent;
procedure WndProc(var Msg: TMessage);
function USBRegister: Boolean;
protected
procedure WMDeviceChange(var Msg: TMessage); dynamic;
public
constructor Create( ADeviceInterface: string; ADriverClass: TUsbDriverClass);
destructor Destroy; override;
public
property OnUSBArrival : TusbNotifyEvent read FOnUSBArrival write FOnUSBArrival;
property OnUSBRemove : TusbNotifyEvent read FOnUSBRemove write FOnUSBRemove;
property DeviceInterface: string read fDeviceInterface;
end;
implementation
uses
Vcl.Forms,
System.SysUtils;
{ TusbNotifier }
// ================================================================================================
// constructor
//
// '{CDDE880F-898A-4DAB-B0EA-51FBA32C1D82}' [trinity.inf]
// ================================================================================================
constructor TusbNotifier.Create( ADeviceInterface: string; ADriverClass: TUsbDriverClass);
begin
inherited Create;
fDeviceInterface := ADeviceInterface;
fDriverClass := ADriverClass;
fWindowHandle := AllocateHWnd(WndProc);
UsbRegister
end;
// ================================================================================================
// destructor
// ================================================================================================
destructor TusbNotifier.Destroy;
begin
if fNotifyHandle <> nil then
UnregisterDeviceNotification( fNotifyHandle);
DeallocateHWnd( fWindowHandle);
inherited
end;
// ================================================================================================
// UsbRegister
// ================================================================================================
function TusbNotifier.USBRegister: Boolean;
var
dbi : DEV_BROADCAST_DEVICEINTERFACE;
size : Integer;
begin
size := SizeOf(DEV_BROADCAST_DEVICEINTERFACE);
ZeroMemory(@dbi, Size);
dbi.dbcc_size := Size;
dbi.dbcc_devicetype := DBT_DEVTYP_DEVICEINTERFACE;
dbi.dbcc_classguid := StringToGUID( fDeviceInterface);
dbi.dbcc_reserved := 0;
dbi.dbcc_name := #0;
fNotifyHandle := RegisterDeviceNotification( fWindowHandle, @dbi, DEVICE_NOTIFY_WINDOW_HANDLE);
result := fNotifyHandle <> nil
end;
// ================================================================================================
// WndProc
// ================================================================================================
procedure TusbNotifier.WndProc(var Msg: TMessage);
begin
if Msg.Msg = WM_DEVICECHANGE then
begin
try
WMDeviceChange(Msg)
except
Application.HandleException(Self)
end
end
else
Msg.Result := DefWindowProc( fWindowHandle, Msg.Msg, Msg.wParam, Msg.lParam)
end;
// ================================================================================================
// WM Device Change
// ================================================================================================
procedure TusbNotifier.WMDeviceChange(var Msg: TMessage);
var
devType : Integer;
devHdr : PDevBroadcastHdr;
begin
if (Msg.wParam = DBT_DEVICEARRIVAL) or (Msg.wParam = DBT_DEVICEREMOVECOMPLETE) then
begin
devHdr := PDevBroadcastHdr( Msg.lParam);
devType := devHdr^.dbch_devicetype;
if devType = DBT_DEVTYP_DEVICEINTERFACE then
begin // USB Device
var x := PDevBroadcastDeviceInterface( Msg.LParam);
var p := PChar( @x.dbcc_name);
var s := '';
while p^ <> #0 do
begin
s := s + p^;
INC(p)
end;
if Msg.wParam = DBT_DEVICEARRIVAL then
begin
if Assigned( fOnUSBArrival) then
FOnUSBArrival( s, fDriverClass)
end
else begin
if Assigned( fOnUSBRemove) then
FOnUSBRemove( s, fDriverClass)
end
end
end
end;
end.
+5 -68
View File
@@ -16,7 +16,6 @@ type
TScanCallback = reference to procedure( DevicePath: string); TScanCallback = reference to procedure( DevicePath: string);
TUsbDeviceInfo = class TUsbDeviceInfo = class
private private
fDriverClass : TUsbDriverClass; fDriverClass : TUsbDriverClass;
@@ -41,27 +40,14 @@ type
IUsbDriverMap = IDictionary<string, TUsbDeviceInfo>; IUsbDriverMap = IDictionary<string, TUsbDeviceInfo>;
TAnsiStringList = TList<AnsiString>; TAnsiStringList = TList<AnsiString>;
TList = spring.Collections.IList<string>; TList = spring.Collections.IList<string>;
TUsbDriver = class abstract(TDriver, IUsbDriver) TUsbDriver = class abstract(TDriver)
public public
class procedure Scan( ScanCallback: TScanCallback); virtual; abstract; class procedure Scan( ScanCallback: TScanCallback); virtual; abstract;
public
class procedure ParseInstanceId( InstanceId : string;
var VendorID : word;
var ProductID : word;
var Location : string;
var Description : string);
protected
class var fDriverID: TGUID;
protected protected
fVendorID : word; fVendorID : word;
fProductID : word; fProductID : word;
@@ -138,6 +124,8 @@ type
implementation implementation
uses uses
mr.dev.usb, mr.dev.usb,
mr.dev.manager,
System.Win.Registry,
System.SysUtils; System.SysUtils;
{ TUsbDriver } { TUsbDriver }
@@ -160,7 +148,7 @@ begin
fDevicePath := DevicePath; fDevicePath := DevicePath;
fDeviceSpeed := LowSpeed; fDeviceSpeed := LowSpeed;
ParseInstanceId( fDevicePath, fVendorID, fProductID, fLocation, fDescription); ParseDevicePath( fDevicePath, fVendorID, fProductID, fLocation, fDescription);
end; end;
// @@@: INTERNALS +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // @@@: INTERNALS +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -172,57 +160,6 @@ end;
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ================================================================================================
// parse instance id
// ================================================================================================
class procedure TUsbDriver.ParseInstanceId( InstanceId : string;
var VendorID : word;
var ProductID : word;
var Location : string;
var Description : string);
var
i : integer;
l : integer;
id : string;
loc: string;
dsc: string;
begin
i := 1;
l := Length(InstanceId);
while (i<=l) and (InstanceId[i] <> '\') do
inc(i);
inc(i);
while (i<=l) and (InstanceId[i] <> '\') do
begin
id := id + InstanceId[i];
inc(i)
end;
inc(i);
while (i<=l) and (InstanceId[i] <> '#') do
begin
loc := loc + InstanceId[i];
inc(i)
end;
inc(i);
while (i<=l) do
begin
dsc := dsc + InstanceId[i];
inc(i)
end;
VendorId := StrToInt('$'+Copy( id, 5, 4));
ProductId := StrToInt('$'+Copy( id, 14, 4));
Location := loc;
Description := dsc;
end;
{ TUsbDeviceInfo } { TUsbDeviceInfo }
@@ -244,7 +181,7 @@ begin
fDevicePath := DevicePath; fDevicePath := DevicePath;
fDriverClass := DriverClass; fDriverClass := DriverClass;
DriverClass.ParseInstanceId( fDevicePath, fVendorID, fProductID, fLocation, fDescription) ParseDevicePath( fDevicePath, fVendorID, fProductID, fLocation, fDescription)
end; end;
// ================================================================================================ // ================================================================================================
+5 -3
View File
@@ -7,7 +7,7 @@ uses
const const
// Standard request codes (btw not used) // Standard request codes (btw not used)
CTRL_GET_STATUS = 0; CTRL_GET_STATUS = 0;
CTRL_CLEAR_FEATURE = 1; CTRL_CLR_FEATURE = 1;
CTRL_SET_FEATURE = 3; CTRL_SET_FEATURE = 3;
CTRL_SET_ADDRESS = 5; CTRL_SET_ADDRESS = 5;
CTRL_GET_DESCRIPTOR = 6; CTRL_GET_DESCRIPTOR = 6;
@@ -109,8 +109,8 @@ type
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
PusbTransferSizeInfo = ^TusbTransferSizeInfo; PusbTransferSizeInfo = ^TusbTransferSizeInfo;
TusbTransferSizeInfo = packed record TusbTransferSizeInfo = packed record
EndpointAddress : byte; EndpointAddress : byte;
TransferSize : cardinal; TransferSize : cardinal;
end; end;
{$Z4} {$Z4}
@@ -140,9 +140,11 @@ type
1: ( 1: (
SetupDat : array [2..7] of byte; SetupDat : array [2..7] of byte;
); );
end; end;
type type
IUsbDriver = interface IUsbDriver = interface
['{786E9A46-F7FE-4A8C-8BB8-563AB8C51BD5}'] ['{786E9A46-F7FE-4A8C-8BB8-563AB8C51BD5}']
+24 -32
View File
@@ -9,16 +9,11 @@ uses
type type
TWinUsbInterfaceHandle = THandle; TWinUsbInterfaceHandle = THandle;
TWinUsbDriver = class( TUsbDriver) TWinUsbDriver = class( TUsbDriver)
public public
class procedure Scan( ScanCallback: TScanCallback); override; class procedure Scan( ScanCallback: TScanCallback); override;
protected protected
fWinUsbHandle : TWinUsbInterfaceHandle; fWinUsbHandle : TWinUsbInterfaceHandle;
@@ -36,10 +31,14 @@ type
function GetAssociatedInterface function GetAssociatedInterface
( (
InterfaceIndex : byte; InterfaceIndex : byte;
var InterfaceHandle): boolean; override; var InterfaceHandle
): boolean; override;
function QueryInterfaceSettings( AlternateSettingNumber : byte; function QueryInterfaceSettings
var AlternateSettingDescriptor : TUsbAlternateSettingDescriptor): boolean; override; (
AlternateSettingNumber : byte;
var AlternateSettingDescriptor : TUsbAlternateSettingDescriptor
): boolean; override;
function QueryPipe function QueryPipe
( (
@@ -91,9 +90,6 @@ type
public public
procedure AfterConstruction; override; procedure AfterConstruction; override;
procedure BeforeDestruction; override; procedure BeforeDestruction; override;
end; end;
implementation implementation
@@ -243,17 +239,17 @@ end;
procedure TWinUsbDriver.BeforeDestruction; procedure TWinUsbDriver.BeforeDestruction;
begin begin
Close; Close;
fWinUsbHandle := INVALID_HANDLE_VALUE;
fDeviceHandle := INVALID_HANDLE_VALUE;
inherited; inherited;
end; end;
// ================================================================================================ // ================================================================================================
// Open // Open
// //
// Note: // DevicePath must be in the form of:
// fDevicePath is in the form:
// 'USB\VID_04B4&PID_8613\6&26c545a4&0&1#Cypress FX2
//
// it must be converted into:
// \\?\USB#VID_04B4&PID_8613#6&26c545a4&0&1#{CDDE880F-898A-4DAB-B0EA-51FBA32C1D82} // \\?\USB#VID_04B4&PID_8613#6&26c545a4&0&1#{CDDE880F-898A-4DAB-B0EA-51FBA32C1D82}
// ================================================================================================ // ================================================================================================
procedure TWinUsbDriver.Open; procedure TWinUsbDriver.Open;
@@ -270,13 +266,14 @@ begin
// Prepare device path // Prepare device path
// --------------------------------------------------------------- // ---------------------------------------------------------------
// strip device description // strip device description
i := Pos('#', path); { i := Pos('#', path);
if i > 0 then if i > 0 then
path := Copy( path, 1, i-1); path := Copy( path, 1, i-1);
path := ReplaceStr(path,'\','#'); path := ReplaceStr(path,'\','#');
path := '\\?\'+path+'#'+GuidToString(fDriverID); path := '\\?\'+path+'#'+fInterfaceGuid;
}
// --------------------------------------------------------------- // ---------------------------------------------------------------
// open // open
@@ -546,9 +543,9 @@ var
s : string; s : string;
begin begin
dsc := CreateComObject( CLSID_FunctionDiscovery) as IFunctionDiscovery;
try try
dsc := CreateComObject( CLSID_FunctionDiscovery) as IFunctionDiscovery;
cat := FCTN_CATEGORY_PNP; cat := FCTN_CATEGORY_PNP;
hr := dsc.GetInstanceCollection(cat, nil, true, fcts); hr := dsc.GetInstanceCollection(cat, nil, true, fcts);
@@ -562,18 +559,14 @@ begin
begin begin
if 'WinUSB' = propv.pwszVal then if 'WinUSB' = propv.pwszVal then
begin begin
// \\?\USB#VID_04B4&PID_8613#6&26c545a4&0&1#{CDDE880F-898A-4DAB-B0EA-51FBA32C1D82}
props.GetValue( PKEY_Device_InstanceId, propv); props.GetValue( PKEY_Device_InstanceId, propv);
s := propv.pwszVal;
props.GetValue( PKEY_Device_DeviceDesc, propv); s := StringReplace( propv.pwszVal, '\', '#', [rfReplaceAll]);
s := s +'#'+ propv.pwszVal; s := Uppercase('\\?\' +s +'#' +fInterfaceGuid);
ScanCallback( s); ScanCallback( s)
// if Map.ContainsKey( s) then
// Map.Remove( s);
//
// Map.Add( s, TUsbDeviceInfo.Create(s, self))
end end
end end
end end
@@ -635,9 +628,8 @@ initialization
// The device path must look like this: // The device path must look like this:
// \\?\USB#VID_04B4&PID_8613#6&26c545a4&0&1#Cypress-FX2 // \\?\USB#VID_04B4&PID_8613#6&26c545a4&0&1#Cypress-FX2
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
TWinUsbDriver.fDriverID := StringToGuid('{CDDE880F-898A-4DAB-B0EA-51FBA32C1D82}'); // TWinUsbDriver.fDriverID := StringToGuid('{CDDE880F-898A-4DAB-B0EA-51FBA32C1D82}');
// RegisterDriver( TWinUsbDriver);
RegisterDriver( TWinUsbDriver);
end; end;
+426 -199
View File
@@ -4,11 +4,9 @@ unit mr.dev.manager;
interface interface
uses uses
// Vcl.Dialogs,
System.Classes, System.Classes,
mr.drv.usb, mr.drv.usb,
mr.dev.usb; mr.dev.usb;
// dev.usb.trinity.types;
type type
GetDeviceListCallback = reference to function( VendorID : word; GetDeviceListCallback = reference to function( VendorID : word;
@@ -17,40 +15,44 @@ type
Location : string; Location : string;
DevicePath : string): boolean; DevicePath : string): boolean;
procedure RegisterDriver( DriverClass : TUsbDriverClass); DeviceConnectEvent = procedure(ADevicePath : string) of object;
//
procedure RegisterDevice( VendorID : word;
ProductID : word; procedure RegisterDriver( ADriverClass : TUsbDriverClass);
Capabilities: int64;
DeviceClass : TUsbDeviceClass); procedure RegisterDevice( AVendorID : word;
// AProductID : word;
function AllocateDevice( DevicePath : string): TUsbDevice; ACapabilities : int64;
// Capabilities: TCapabilities = []; ADeviceClass : TUsbDeviceClass);
// IgnoreCap : boolean = false): TUsbDevice;
// procedure GetDeviceList( ACallback : GetDeviceListCallback;
//function AllocateDeviceBySN( SerialNumber: AnsiString; AVendorID : word = 0;
// Capabilities: TCapabilities = []; AProductID : word = 0);
// IgnoreCap : boolean = false): TUsbDevice;
// function AllocateDevice( ADevicePath : string): TUsbDevice;
procedure DeallocateDevice( var Device : TUsbDevice); procedure DeallocateDevice( var ADevice : TUsbDevice);
//
procedure GetDeviceList( Callback : GetDeviceListCallback;
VendorID : word = 0; function ParseDevicePath( InstanceId : string;
ProductID : word = 0); var VendorID : word;
var ProductID : word;
var Location : string;
var Description : string): boolean;
procedure RegisterUsbConnectEventHandler( AEventHandler: DeviceConnectEvent);
procedure RegisterUsbDisconnectEventHandler( AEventHandler: DeviceConnectEvent);
implementation implementation
uses uses
system.SysUtils, Winapi.Windows,
spring.Collections; System.SysUtils,
System.Win.Registry,
procedure ParseInstanceId( InstanceId : string; Spring.Collections,
var VendorID : word; mr.drv.usb.notifier;
var ProductID : word;
var Location : string;
var Description : string); forward;
// SysUtils, // SysUtils,
// Generics.Collections, // Generics.Collections,
@@ -118,155 +120,185 @@ type
property Description : string read GetDescription; property Description : string read GetDescription;
end; end;
TDeviceManager = class
private
fOnDeviceArrival : DeviceConnectEvent;
fOnDeviceRemoval : DeviceConnectEvent;
private
fUsbDeviceSetups : IDictionary< cardinal, TUsbDeviceSetup>;
fUsbDevices : IDictionary< string, TUsbDeviceDescriptor>;
fUsbNotifiers : IDictionary< string, TusbNotifier>;
procedure DoUsbArrival( ADevicePath : string;
ADriverClass : TUsbDriverClass);
procedure DoUsbRemoval( ADevicePath : string;
ADriverClass : TUsbDriverClass);
public
procedure RegisterDriver( ADriverClass : TUsbDriverClass);
procedure RegisterDevice( AVendorID : word;
AProductID : word;
ACapabilities : int64;
ADeviceClass : TUsbDeviceClass);
procedure GetDeviceList( ACallback : GetDeviceListCallback;
AVendorID : word = 0;
AProductID : word = 0);
function AllocateDevice( ADevicePath : string): TUsbDevice;
procedure DeallocateDevice( ADevice : TUsbDevice);
public
constructor Create;
destructor Destroy; override;
public
property OnDeviceArrival : DeviceConnectEvent read fOnDeviceArrival write fOnDeviceArrival;
property OnDeviceRemoval : DeviceConnectEvent read fOnDeviceRemoval write fOnDeviceRemoval;
end;
var var
UsbDeviceSetups : IDictionary< cardinal, TUsbDeviceSetup>; gDeviceManager: TDeviceManager;
UsbDevices : IDictionary< string, TUsbDeviceDescriptor>;
function DeviceManager: TDeviceManager; forward;
procedure RegisterUsbConnectEventHandler( AEventHandler: DeviceConnectEvent);
begin
DeviceManager.OnDeviceArrival := AEventHandler
end;
procedure RegisterUsbDisconnectEventHandler( AEventHandler: DeviceConnectEvent);
begin
DeviceManager.OnDeviceRemoval := AEventHandler;
end;
// ================================================================================================ // ================================================================================================
// Register Driver // parse device path
//
// '\\?\USB#VID_04B4&PID_8613#7&2ec9f839&0&17#{cdde880f-898a-4dab-b0ea-51fba32c1d82}'
// ================================================================================================ // ================================================================================================
procedure RegisterDriver( DriverClass: TUsbDriverClass); function ParseDevicePath( InstanceId : string;
var VendorID : word;
var ProductID : word;
var Location : string;
var Description : string): boolean;
var var
vid: word; id : string;
pid: word;
loc: string; loc: string;
dsc: string; dsc: string;
key: cardinal;
uds: TUsbDeviceSetup;
udd: TUsbDeviceDescriptor;
begin begin
if UsbDevices = nil then result := false;
UsbDevices := tCollections.CreateDictionary< string, TUsbDeviceDescriptor>([doOwnsValues]);
if UsbDeviceSetups = nil then if Copy( InstanceId, 1, 8) = '\\?\USB#'
UsbDeviceSetups := TCollections.CreateDictionary< cardinal, TUsbDeviceSetup>([doOwnsValues]); then InstanceId := Copy( InstanceId, 9)
else exit;
DriverClass.Scan( procedure( DevicePath: string) var items := InstanceId.Split(['#']);
begin
DriverClass.ParseInstanceId( DevicePath, vid, pid, loc, dsc);
key := (vid shl 16) + pid;
// -------------------------------------------------------------- if Length(items) = 3 then
// add or update (override) an usb device setup entry begin
// -------------------------------------------------------------- id := items[0];
if not UsbDeviceSetups.TryGetValue( key, uds) then loc := items[1];
begin dsc := items[2];
uds := TUsbDeviceSetup.Create; end
uds.VendorID := vid;
uds.ProductID := pid;
UsbDeviceSetups.Add( key, uds) else
end; exit;
uds.DriverClass := DriverClass; var ids := id.Split(['&']);
uds.Description := dsc;
// -------------------------------------------------------------- if Length(ids) = 2 then
// add or update (override) an usb device entry begin
// -------------------------------------------------------------- VendorID := StrToInt('$'+Copy( ids[0], 5, 4));
if not UsbDevices.TryGetValue( DevicePath, udd) then ProductID := StrToInt('$'+Copy( ids[1], 5, 4));
begin end
udd := TUsbDeviceDescriptor.Create( DevicePath);
UsbDevices.Add(DevicePath, udd)
end;
udd.DeviceSetup := uds else
end) exit;
Location := Uppercase(loc);
var reg := TRegistry.Create;
reg.RootKey := HKEY_LOCAL_MACHINE;
if reg.OpenKeyReadOnly('SYSTEM\CurrentControlSet\Enum\USB\'+id +'\'+ loc) then
begin
Description := reg.ReadString('DeviceDesc');
var i := Pos( ';', Description);
if i > 0 then
Description := Copy( Description, i+1);
reg.CloseKey
end;
SetLength( items, 0);
SetLength( ids, 0);
result := true
end;
// ================================================================================================
// DeviceManager (singleton pattern)
// ================================================================================================
function DeviceManager: TDeviceManager;
begin
if gDeviceManager = nil then
gDeviceManager := TDeviceManager.Create;
result := gDeviceManager
end; end;
// ================================================================================================ // ================================================================================================
// Register Device // register driver
// ================================================================================================ // ================================================================================================
procedure RegisterDevice( VendorID : word; procedure RegisterDriver( ADriverClass: TUsbDriverClass);
ProductID : word;
Capabilities: int64;
DeviceClass : TUsbDeviceClass);
var
key: cardinal;
uds: TUsbDeviceSetup;
begin begin
if UsbDeviceSetups = nil then DeviceManager.RegisterDriver( ADriverClass)
UsbDeviceSetups := TCollections.CreateDictionary< cardinal, TUsbDeviceSetup>([doOwnsValues]); end;
key := (VendorID shl 16) + ProductID; // ================================================================================================
// register device
if not UsbDeviceSetups.TryGetValue( key, uds) then // ================================================================================================
begin procedure RegisterDevice( AVendorID : word;
uds := TUsbDeviceSetup.Create; AProductID : word;
uds.VendorID := VendorID; ACapabilities : int64;
uds.ProductID := ProductID; ADeviceClass : TUsbDeviceClass);
begin
UsbDeviceSetups.Add( key, uds); DeviceManager.RegisterDevice( AVendorID, AProductID, ACapabilities, ADeviceClass)
end;
uds.DeviceClass := DeviceClass;
end; end;
// ================================================================================================ // ================================================================================================
// Get Device List // Get Device List
// ================================================================================================ // ================================================================================================
procedure GetDeviceList( Callback : GetDeviceListCallback; procedure GetDeviceList( ACallback : GetDeviceListCallback;
VendorID : word = 0; AVendorID : word = 0;
ProductID : word = 0); AProductID : word = 0);
begin begin
for var udd in UsbDevices.Values do DeviceManager.GetDeviceList( ACallback, AVendorID, AProductID)
if ((VendorID = 0) and (ProductID = 0)) or
((VendorID = udd.VendorID) and (ProductID = udd.ProductID)) then
begin
with udd do
if not Callback( VendorID, ProductID, Description, Location, DevicePath) then
break
end
end; end;
// ================================================================================================ // ================================================================================================
// Allocate Device // Allocate Device
// ================================================================================================ // ================================================================================================
function AllocateDevice( DevicePath: string): TUsbDevice; function AllocateDevice( ADevicePath : string): TUsbDevice;
var
udd: TUsbDeviceDescriptor;
begin begin
result := nil; result := DeviceManager.AllocateDevice( ADevicePath)
assert( UsbDeviceSetups <> nil);
assert( UsbDevices <> nil);
if UsbDevices.TryGetValue( DevicePath, udd) and not udd.Allocated then
begin
var ds := udd.DeviceSetup;
assert( ds <> nil);
if (ds.DriverClass <> nil) and (ds.DeviceClass <> nil) then
begin
udd.Allocated := true;
var drv := ds.DriverClass.Create( DevicePath);
var dev := ds.DeviceClass.Create( drv);
exit(dev)
end
end
end; end;
// ================================================================================================ // ================================================================================================
// Deallocate Device // Deallocate Device
// ================================================================================================ // ================================================================================================
procedure DeallocateDevice( var Device: TUsbDevice); procedure DeallocateDevice( var ADevice: TUsbDevice);
var
udd: TUsbDeviceDescriptor;
begin begin
if Assigned(Device) then DeviceManager.DeallocateDevice( ADevice)
begin
if UsbDevices.TryGetValue( Device.DevicePath, udd) then
udd.Allocated := false;
// FreeAndNil( Device)
end
end; end;
@@ -356,64 +388,8 @@ end;
// //
// ================================================================================================
// parse instnce ID
// ================================================================================================
procedure ParseInstanceId( InstanceId : string;
var VendorID : word;
var ProductID : word;
var Location : string;
var Description : string);
var
i : integer;
l : integer;
id : string;
loc: string;
dsc: string;
begin
i := 1;
l := Length(InstanceId);
while (i<=l) and (InstanceId[i] <> '\') do
inc(i);
inc(i);
while (i<=l) and (InstanceId[i] <> '\') do
begin
id := id + InstanceId[i];
inc(i)
end;
inc(i);
while (i<=l) and (InstanceId[i] <> '#') do
begin
loc := loc + InstanceId[i];
inc(i)
end;
inc(i);
while (i<=l) do
begin
dsc := dsc + InstanceId[i];
inc(i)
end;
if @VendorID <> nil then
VendorId := StrToInt('$'+Copy( id, 5, 4));
ProductId := StrToInt('$'+Copy( id, 14, 4));
Location := loc;
Description := dsc
end;
{ TUsbDeviceDescriptor } { TUsbDeviceDescriptor }
// @@@: UsbDeviceDescriptor +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // @@@: UsbDeviceDescriptor +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -427,7 +403,7 @@ end;
// ================================================================================================ // ================================================================================================
// constructor // constructor
// ================================================================================================ // ================================================================================================
constructor TUsbDeviceDescriptor.Create(DevicePath: string); constructor TUsbDeviceDescriptor.Create( DevicePath: string);
var var
vid: word; vid: word;
pid: word; pid: word;
@@ -439,7 +415,8 @@ begin
fAllocated := false; fAllocated := false;
fDevicePath := DevicePath; fDevicePath := DevicePath;
ParseInstanceId( fDevicePath, vid, pid, fLocation, dsc) if not ParseDevicePath( fDevicePath, vid, pid, fLocation, dsc) then
fLocation := ''
end; end;
// ================================================================================================ // ================================================================================================
@@ -490,8 +467,258 @@ begin
result := fDeviceSetup.Description result := fDeviceSetup.Description
end; end;
{ TDeviceManager }
// ================================================================================================
// constructor
// ================================================================================================
constructor TDeviceManager.Create;
begin
inherited;
fUsbDeviceSetups := TCollections.CreateDictionary< cardinal, TUsbDeviceSetup> ([doOwnsValues]);
fUsbDevices := TCollections.CreateDictionary< string, TUsbDeviceDescriptor>([doOwnsValues]);
fUsbNotifiers := TCollections.CreateDictionary< string, TusbNotifier> ([doOwnsValues]);
end;
// ================================================================================================
// destructor
// ================================================================================================
destructor TDeviceManager.Destroy;
begin
fUsbDeviceSetups := nil;
fUsbDevices := nil;
fUsbNotifiers := nil;
inherited
end;
// ================================================================================================
// get device list
// ================================================================================================
procedure TDeviceManager.GetDeviceList( ACallback : GetDeviceListCallback;
AVendorID : word = 0;
AProductID: word = 0);
begin
for var udd in fUsbDevices.Values do
if ((AVendorID = 0) and (AProductID = 0)) or
((AVendorID = udd.VendorID) and (AProductID = udd.ProductID)) then
with udd do
if not ACallback( VendorID, ProductID, Description, Location, DevicePath) then
break
end;
// ================================================================================================
// allocate device
// ================================================================================================
function TDeviceManager.AllocateDevice( ADevicePath: string): TUsbDevice;
var
udd: TUsbDeviceDescriptor;
begin
result := nil;
assert( fUsbDeviceSetups <> nil);
assert( fUsbDevices <> nil);
if fUsbDevices.TryGetValue( ADevicePath, udd) then
begin
if not udd.Allocated then
begin
var ds := udd.DeviceSetup;
assert( ds <> nil);
if (ds.DriverClass <> nil) and (ds.DeviceClass <> nil) then
begin
udd.Allocated := true;
var drv := ds.DriverClass.Create( udd.DevicePath);
var dev := ds.DeviceClass.Create( drv);
exit(dev)
end
end
else begin
udd.Allocated := true
end;
end
end;
// ================================================================================================
// deallocate device
// ================================================================================================
procedure TDeviceManager.DeallocateDevice( ADevice: TUsbDevice);
var
udd: TUsbDeviceDescriptor;
begin
if ADevice <> nil then
begin
if fUsbDevices.TryGetValue( ADevice.DevicePath, udd) then
udd.Allocated := false;
FreeAndNil( ADevice)
end
end;
// ================================================================================================
// register driver
// ================================================================================================
procedure TDeviceManager.RegisterDriver( ADriverClass: TUsbDriverClass);
begin
if Assigned( ADriverClass) then
begin
// --------------------------------------------------
// register for usb arrival/removal notifications
// --------------------------------------------------
var guid := ADriverClass.InterfaceGUID;
if guid <> '' then
begin
if not fUsbNotifiers.ContainsKey( guid) then
begin
var noti := TusbNotifier.Create( guid, ADriverClass);
noti.OnUSBArrival := DoUsbArrival;
noti.OnUSBRemove := DoUsbRemoval;
fUsbNotifiers.Add( guid, noti);
end;
// --------------------------------------------------
// scan for already connected devices
// --------------------------------------------------
ADriverClass.Scan(
procedure( ADevicePath: string)
var
vid : word;
pid : word;
loc : string;
dsc : string;
uds : TUsbDeviceSetup;
begin
ParseDevicePath( ADevicePath, vid, pid, loc, dsc);
var key := (vid shl 16) + pid;
// --------------------------------------------------------------
// add or update (override) an usb device setup entry
// --------------------------------------------------------------
if not fUsbDeviceSetups.TryGetValue( key, uds) then
begin
uds := TUsbDeviceSetup.Create;
uds.VendorID := vid;
uds.ProductID := pid;
fUsbDeviceSetups.Add( key, uds)
end;
uds.DriverClass := ADriverClass;
uds.Description := dsc;
// --------------------------------------------------------------
// add usb device
// --------------------------------------------------------------
if not fUsbDevices.ContainsKey( ADevicePath) then
begin
var udd := TUsbDeviceDescriptor.Create( ADevicePath);
udd.DeviceSetup := uds;
fUsbDevices.Add( ADevicePath, udd)
end
end)
end
end
end;
// ================================================================================================
// register device
// ================================================================================================
procedure TDeviceManager.RegisterDevice( AVendorID : word;
AProductID : word;
ACapabilities : int64;
ADeviceClass : TUsbDeviceClass);
var
key: cardinal;
uds: TUsbDeviceSetup;
begin
key := (AVendorID shl 16) + AProductID;
if not fUsbDeviceSetups.TryGetValue( key, uds) then
begin
uds := TUsbDeviceSetup.Create;
uds.VendorID := AVendorID;
uds.ProductID := AProductID;
fUsbDeviceSetups.Add( key, uds);
end;
uds.DeviceClass := ADeviceClass;
end;
// ================================================================================================
// USB device connected
// ================================================================================================
procedure TDeviceManager.DoUsbArrival( ADevicePath: string; ADriverClass: TUsbDriverClass);
var
vid : word;
pid : word;
loc : string;
dsc : string;
uds : TUsbDeviceSetup;
udd : TUsbDeviceDescriptor;
begin
ADevicePath := Uppercase( ADevicePath);
ParseDevicePath( ADevicePath, vid, pid, loc, dsc);
// --------------------------------------------------------------
// add device
// --------------------------------------------------------------
var key := (vid shl 16) + pid;
if fUsbDeviceSetups.TryGetValue( key, uds) then
begin
if not Assigned( uds.DriverClass) then
uds.DriverClass := ADriverClass;
if not fUsbDevices.ContainsKey( ADevicePath) then
begin
udd := TUsbDeviceDescriptor.Create( ADevicePath);
udd.DeviceSetup := uds;
fUsbDevices.Add( ADevicePath, udd);
if Assigned( fOnDeviceArrival) then
fOnDeviceArrival( ADevicePath)
end
end
end;
// ================================================================================================
// USB device disconnected
// ================================================================================================
procedure TDeviceManager.DoUsbRemoval( ADevicePath: string; ADriverClass: TUsbDriverClass);
begin
ADevicePath := Uppercase( ADevicePath);
if fUsbDevices.ContainsKey( ADevicePath) then
begin
if Assigned( fOnDeviceRemoval) then
fOnDeviceRemoval( ADevicePath);
fUsbDevices.Remove( ADevicePath)
end
end;
initialization initialization
finalization finalization
if gDeviceManager <> nil then
gDeviceManager.Free
end. end.