From b9305ab8af33b620de3210df60fc0634e61085cf Mon Sep 17 00:00:00 2001 From: Abu Abacus Date: Sat, 3 Jan 2026 18:53:14 +0100 Subject: [PATCH] Initial check in --- .gitignore | 25 + prj.devmgr/Delphi12Athens/mr.devmgr.dpk | 71 ++ prj.devmgr/Delphi12Athens/mr.devmgr.dproj | 1036 +++++++++++++++++ src.devmgr/dev/mr.dev.pas | 42 + src.devmgr/dev/usb/dev.usb.notifier.pas | 128 ++ .../dev/usb/mr.dev.usb.configuration.pas | 137 +++ src.devmgr/dev/usb/mr.dev.usb.pas | 264 +++++ src.devmgr/dev/usb/mr.dev.usb.pipe.pas | 108 ++ src.devmgr/dev/usb/mr.dev.usb.pipe0.pas | 74 ++ src.devmgr/dev/usb/mr.dev.usb.pipebase.pas | 44 + .../dev/usb/trinity/modules/cfg/m.cfg.pas | 205 ++++ .../usb/trinity/modules/cfg/m.cfg.types.pas | 28 + .../usb/trinity/modules/eeprom/m.eeprom.pas | 65 ++ .../trinity/modules/eeprom/m.eeprom.types.pas | 14 + .../dev/usb/trinity/modules/i2c/m.iic.pas | 185 +++ .../usb/trinity/modules/i2c/m.iic.types.pas | 64 + .../dev/usb/trinity/modules/jtag/m.jtag.pas | 649 +++++++++++ .../usb/trinity/modules/jtag/m.jtag.types.pas | 51 + .../dev/usb/trinity/modules/lcd/m.lcd.pas | 187 +++ .../usb/trinity/modules/lcd/m.lcd.types.pas | 22 + .../dev/usb/trinity/modules/led/m.led.pas | 86 ++ .../usb/trinity/modules/led/m.led.types.pas | 17 + src.devmgr/dev/usb/trinity/modules/m.base.pas | 53 + .../dev/usb/trinity/mr.trinity.consts.pas | 56 + src.devmgr/dev/usb/trinity/mr.trinity.hex.pas | 457 ++++++++ src.devmgr/dev/usb/trinity/mr.trinity.pas | 567 +++++++++ .../dev/usb/trinity/mr.trinity.pipe0.pas | 135 +++ .../dev/usb/trinity/mr.trinity.types.pas | 107 ++ .../dev/usb/trinity/mr.trinity.utils.pas | 39 + src.devmgr/drv/mr.drv.pas | 24 + src.devmgr/drv/mr.drv.types.pas | 13 + src.devmgr/drv/mr.drv.usb.types.pas | 152 +++ src.devmgr/drv/usb/mr.drv.usb.pas | 258 ++++ src.devmgr/drv/usb/mr.drv.usb.types.pas | 210 ++++ src.devmgr/drv/usb/mr.drv.usb.winusb.pas | 650 +++++++++++ src.devmgr/mr.dev.manager.pas | 497 ++++++++ 36 files changed, 6720 insertions(+) create mode 100644 .gitignore create mode 100644 prj.devmgr/Delphi12Athens/mr.devmgr.dpk create mode 100644 prj.devmgr/Delphi12Athens/mr.devmgr.dproj create mode 100644 src.devmgr/dev/mr.dev.pas create mode 100644 src.devmgr/dev/usb/dev.usb.notifier.pas create mode 100644 src.devmgr/dev/usb/mr.dev.usb.configuration.pas create mode 100644 src.devmgr/dev/usb/mr.dev.usb.pas create mode 100644 src.devmgr/dev/usb/mr.dev.usb.pipe.pas create mode 100644 src.devmgr/dev/usb/mr.dev.usb.pipe0.pas create mode 100644 src.devmgr/dev/usb/mr.dev.usb.pipebase.pas create mode 100644 src.devmgr/dev/usb/trinity/modules/cfg/m.cfg.pas create mode 100644 src.devmgr/dev/usb/trinity/modules/cfg/m.cfg.types.pas create mode 100644 src.devmgr/dev/usb/trinity/modules/eeprom/m.eeprom.pas create mode 100644 src.devmgr/dev/usb/trinity/modules/eeprom/m.eeprom.types.pas create mode 100644 src.devmgr/dev/usb/trinity/modules/i2c/m.iic.pas create mode 100644 src.devmgr/dev/usb/trinity/modules/i2c/m.iic.types.pas create mode 100644 src.devmgr/dev/usb/trinity/modules/jtag/m.jtag.pas create mode 100644 src.devmgr/dev/usb/trinity/modules/jtag/m.jtag.types.pas create mode 100644 src.devmgr/dev/usb/trinity/modules/lcd/m.lcd.pas create mode 100644 src.devmgr/dev/usb/trinity/modules/lcd/m.lcd.types.pas create mode 100644 src.devmgr/dev/usb/trinity/modules/led/m.led.pas create mode 100644 src.devmgr/dev/usb/trinity/modules/led/m.led.types.pas create mode 100644 src.devmgr/dev/usb/trinity/modules/m.base.pas create mode 100644 src.devmgr/dev/usb/trinity/mr.trinity.consts.pas create mode 100644 src.devmgr/dev/usb/trinity/mr.trinity.hex.pas create mode 100644 src.devmgr/dev/usb/trinity/mr.trinity.pas create mode 100644 src.devmgr/dev/usb/trinity/mr.trinity.pipe0.pas create mode 100644 src.devmgr/dev/usb/trinity/mr.trinity.types.pas create mode 100644 src.devmgr/dev/usb/trinity/mr.trinity.utils.pas create mode 100644 src.devmgr/drv/mr.drv.pas create mode 100644 src.devmgr/drv/mr.drv.types.pas create mode 100644 src.devmgr/drv/mr.drv.usb.types.pas create mode 100644 src.devmgr/drv/usb/mr.drv.usb.pas create mode 100644 src.devmgr/drv/usb/mr.drv.usb.types.pas create mode 100644 src.devmgr/drv/usb/mr.drv.usb.winusb.pas create mode 100644 src.devmgr/mr.dev.manager.pas diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..905b000 --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +__history +__recovery + +bin +dcu +*.exe +prj.dpgxcon\Win32 +prj.dpgxcon\Win64 + +*.res +*.identcache +*.local +*.dsk +*.dsv + +# documentation intermediate files (TeX) +*.aux +*.bmt +*.dvi +*.log +*.lot +*.mtc* +*.mlt* +*.toc + diff --git a/prj.devmgr/Delphi12Athens/mr.devmgr.dpk b/prj.devmgr/Delphi12Athens/mr.devmgr.dpk new file mode 100644 index 0000000..2a2cb55 --- /dev/null +++ b/prj.devmgr/Delphi12Athens/mr.devmgr.dpk @@ -0,0 +1,71 @@ +package mr.devmgr; + +{$R *.res} +{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO OFF} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION OFF} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES ON} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$DEFINE DEBUG} +{$ENDIF IMPLICITBUILDING} +{$DESCRIPTION 'mr Device Manager for USB devices'} +{$LIBSUFFIX '.290'} +{$IMPLICITBUILD ON} + +requires + rtl, + vcl; +// spring.core, +// mr.dpgrtl, +// mr.jtag; + +contains + mr.drv in '..\..\src.devmgr\drv\mr.drv.pas', + mr.drv.usb in '..\..\src.devmgr\drv\usb\mr.drv.usb.pas', + mr.drv.usb.types in '..\..\src.devmgr\drv\usb\mr.drv.usb.types.pas', + mr.dev in '..\..\src.devmgr\dev\mr.dev.pas', + mr.dev.usb in '..\..\src.devmgr\dev\usb\mr.dev.usb.pas', + mr.dev.usb.configuration in '..\..\src.devmgr\dev\usb\mr.dev.usb.configuration.pas', + mr.dev.usb.pipe in '..\..\src.devmgr\dev\usb\mr.dev.usb.pipe.pas', + mr.dev.usb.pipe0 in '..\..\src.devmgr\dev\usb\mr.dev.usb.pipe0.pas', + mr.dev.usb.pipebase in '..\..\src.devmgr\dev\usb\mr.dev.usb.pipebase.pas', + mr.drv.usb.winusb in '..\..\src.devmgr\drv\usb\mr.drv.usb.winusb.pas', + mr.dev.manager in '..\..\src.devmgr\mr.dev.manager.pas', + mr.trinity.types in '..\..\src.devmgr\dev\usb\trinity\mr.trinity.types.pas', + mr.trinity.consts in '..\..\src.devmgr\dev\usb\trinity\mr.trinity.consts.pas', + mr.trinity in '..\..\src.devmgr\dev\usb\trinity\mr.trinity.pas', + mr.trinity.pipe0 in '..\..\src.devmgr\dev\usb\trinity\mr.trinity.pipe0.pas', + mr.trinity.utils in '..\..\src.devmgr\dev\usb\trinity\mr.trinity.utils.pas', + mr.trinity.hex in '..\..\src.devmgr\dev\usb\trinity\mr.trinity.hex.pas', + m.base in '..\..\src.devmgr\dev\usb\trinity\modules\m.base.pas', + m.led in '..\..\src.devmgr\dev\usb\trinity\modules\led\m.led.pas', + m.led.types in '..\..\src.devmgr\dev\usb\trinity\modules\led\m.led.types.pas', + m.lcd in '..\..\src.devmgr\dev\usb\trinity\modules\lcd\m.lcd.pas', + m.lcd.types in '..\..\src.devmgr\dev\usb\trinity\modules\lcd\m.lcd.types.pas', + m.jtag in '..\..\src.devmgr\dev\usb\trinity\modules\jtag\m.jtag.pas', + m.jtag.types in '..\..\src.devmgr\dev\usb\trinity\modules\jtag\m.jtag.types.pas', + m.iic in '..\..\src.devmgr\dev\usb\trinity\modules\i2c\m.iic.pas', + m.iic.types in '..\..\src.devmgr\dev\usb\trinity\modules\i2c\m.iic.types.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.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'; + +end. diff --git a/prj.devmgr/Delphi12Athens/mr.devmgr.dproj b/prj.devmgr/Delphi12Athens/mr.devmgr.dproj new file mode 100644 index 0000000..3b0445c --- /dev/null +++ b/prj.devmgr/Delphi12Athens/mr.devmgr.dproj @@ -0,0 +1,1036 @@ + + + {FB4C7208-2CB8-4B2B-92C7-A0CD788BD37A} + mr.devmgr.dpk + 20.3 + VCL + True + Debug + Win32 + 1 + Package + mr.devmgr + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + ..\..\dcu\Delphi12Athens\$(Platform)\$(Config) + .\$(Platform)\$(Config) + false + false + false + false + false + true + true + System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace) + mr_devmgr + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + .270 + + + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + + + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) + Debug + true + true + + + DEBUG;$(DCC_Define) + true + false + true + true + true + + + false + true + mr Device Manager for USB devices + .290 + + + false + RELEASE;$(DCC_Define) + 0 + 0 + + + true + + + + MainSource + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Base + + + Cfg_1 + Base + + + Cfg_2 + Base + + + + Delphi.Personality.12 + Package + + + + mr.devmgr.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + True + False + False + + + + + + + + + + mr.devmgr.bpl + true + + + + + 1 + + + 0 + + + + + res\xml + 1 + + + res\xml + 1 + + + + + library\lib\armeabi + 1 + + + library\lib\armeabi + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\mips + 1 + + + library\lib\mips + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-anydpi-v21 + 1 + + + res\drawable-anydpi-v21 + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\values-v21 + 1 + + + res\values-v21 + 1 + + + + + res\values-v31 + 1 + + + res\values-v31 + 1 + + + + + res\values-v35 + 1 + + + res\values-v35 + 1 + + + + + res\drawable-anydpi-v26 + 1 + + + res\drawable-anydpi-v26 + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-anydpi-v33 + 1 + + + res\drawable-anydpi-v33 + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\values-night-v21 + 1 + + + res\values-night-v21 + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-ldpi + 1 + + + res\drawable-ldpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-small + 1 + + + res\drawable-small + 1 + + + + + res\drawable-normal + 1 + + + res\drawable-normal + 1 + + + + + res\drawable-large + 1 + + + res\drawable-large + 1 + + + + + res\drawable-xlarge + 1 + + + res\drawable-xlarge + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\drawable-anydpi-v24 + 1 + + + res\drawable-anydpi-v24 + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-night-anydpi-v21 + 1 + + + res\drawable-night-anydpi-v21 + 1 + + + + + res\drawable-anydpi-v31 + 1 + + + res\drawable-anydpi-v31 + 1 + + + + + res\drawable-night-anydpi-v31 + 1 + + + res\drawable-night-anydpi-v31 + 1 + + + + + 1 + + + 1 + + + 0 + + + + + 1 + .framework + + + 1 + .framework + + + 1 + .framework + + + 0 + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .dll;.bpl + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .bpl + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 1 + + + 1 + + + + + + + + Contents\Resources + 1 + + + Contents\Resources + 1 + + + Contents\Resources + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 0 + + + + + library\lib\armeabi-v7a + 1 + + + + + 1 + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + + + + 1 + + + 1 + + + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + + + + + + + + + + + + + + 12 + + + + + diff --git a/src.devmgr/dev/mr.dev.pas b/src.devmgr/dev/mr.dev.pas new file mode 100644 index 0000000..360f0e3 --- /dev/null +++ b/src.devmgr/dev/mr.dev.pas @@ -0,0 +1,42 @@ +unit mr.dev; + +interface +uses + mr.drv; + +type + TDevice = class(TInterfacedObject) + protected + fDriver: TDriver; + + public + procedure Open; virtual; abstract; + procedure Close; virtual; abstract; + + public + constructor Create( Driver : TDriver); + end; + +implementation + +{ TDevice } + +// @@@: Construction / destruction ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Construction / destruction +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// Constructor +// ================================================================================================ +constructor TDevice.Create(Driver: TDriver); +begin + inherited Create; + fDriver := Driver; +end; + +end. diff --git a/src.devmgr/dev/usb/dev.usb.notifier.pas b/src.devmgr/dev/usb/dev.usb.notifier.pas new file mode 100644 index 0000000..d79e4f7 --- /dev/null +++ b/src.devmgr/dev/usb/dev.usb.notifier.pas @@ -0,0 +1,128 @@ +unit dev.usb.notifier; + +interface +uses + Windows, Messages, Classes; + +type + TUsbNotifyProc = procedure(Sender: TObject; const DeviceName: String) of object; + + TUsbNotifier = class + private + fWindowHandle : HWND; + fNotificationHandle : Pointer; + fOnUsbArrival : TUsbNotifyProc; + fOnUsbRemoval : TUsbNotifyProc; + + private + procedure WndProc(var Msg: TMessage); + + public + constructor Create; + destructor Destroy; override; + + public + property OnUsbArrival: TUsbNotifyProc read fOnUsbArrival write fOnUsbArrival; + property OnUsbRemoval: TUsbNotifyProc read fOnUsbRemoval write fOnUsbRemoval; + end; + + +implementation +const + GUID_DEVINTERFACE_USB_DEVICE: TGUID = '{A5DCBF10-6530-11D2-901F-00C04FB951ED}'; + DBT_DEVICEARRIVAL = $8000; + DBT_DEVICEREMOVECOMPLETE = $8004; + DBT_DEVTYP_DEVICEINTERFACE = $00000005; + +type + PDevBroadcastHdr = ^DEV_BROADCAST_HDR; + DEV_BROADCAST_HDR = packed record + dbch_size : DWORD; + dbch_devicetype: DWORD; + dbch_reserved : DWORD; + end; + TDevBroadcastHdr = DEV_BROADCAST_HDR; + + PDevBroadcastDeviceInterface = ^DEV_BROADCAST_DEVICEINTERFACE; + DEV_BROADCAST_DEVICEINTERFACE = record + dbcc_size : DWORD; + dbcc_devicetype: DWORD; + dbcc_reserved : DWORD; + dbcc_classguid : TGUID; + dbcc_name : Char; + end; + TDevBroadcastDeviceInterface = DEV_BROADCAST_DEVICEINTERFACE; + + +{ TUsbNotifier } + +// ================================================================================================ +// constructor +// ================================================================================================ +constructor TUsbNotifier.Create; +var + size: cardinal; + dbi : TDevBroadcastDeviceInterface; + +begin + inherited; + + FWindowHandle := AllocateHWnd( WndProc); + Size := SizeOf(dbi); + + ZeroMemory(@dbi, Size); + + dbi.dbcc_size := Size; + dbi.dbcc_devicetype := DBT_DEVTYP_DEVICEINTERFACE; + dbi.dbcc_classguid := GUID_DEVINTERFACE_USB_DEVICE; + + FNotificationHandle := RegisterDeviceNotification( FWindowHandle, + @dbi, + DEVICE_NOTIFY_WINDOW_HANDLE); +end; + +// ================================================================================================ +// destructor +// ================================================================================================ +destructor TUsbNotifier.Destroy; +begin + UnregisterDeviceNotification(FNotificationHandle); + DeallocateHWnd(FWindowHandle); + + inherited; +end; + +// ================================================================================================ +// window proc +// ================================================================================================ +procedure TUsbNotifier.WndProc(var Msg: TMessage); +var + Dbi: PDevBroadcastDeviceInterface; + +begin + with Msg do + if Msg = WM_DEVICECHANGE then + if (WParam = DBT_DEVICEARRIVAL) or (WParam = DBT_DEVICEREMOVECOMPLETE) then + try + Dbi := PDevBroadcastDeviceInterface(LParam); + + if Dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE then + if WParam = DBT_DEVICEARRIVAL then + begin + if Assigned(FOnUsbArrival) then + FOnUsbArrival(Self, PChar(@Dbi.dbcc_name)); + end + + else begin + if Assigned(FOnUsbRemoval) then + FOnUsbRemoval(Self, PChar(@Dbi.dbcc_name)); + end + + except + Result := DefWindowProc(FWindowHandle, Msg, WParam, LParam); + end + else + Result := DefWindowProc(FWindowHandle, Msg, WParam, LParam); +end; + +end. diff --git a/src.devmgr/dev/usb/mr.dev.usb.configuration.pas b/src.devmgr/dev/usb/mr.dev.usb.configuration.pas new file mode 100644 index 0000000..b1e6694 --- /dev/null +++ b/src.devmgr/dev/usb/mr.dev.usb.configuration.pas @@ -0,0 +1,137 @@ +unit mr.dev.usb.configuration; + +interface +uses + Generics.Collections, + mr.drv.usb, + mr.drv.usb.types, + mr.dev.usb.pipe, + mr.dev.usb.pipe0; + +type + TUsbConfiguration = class + strict protected + type + TPipeMap = TObjectDictionary; + + strict protected + fDriver : TUsbDriver; + fPipeMap : TPipeMap; + fConfiguration : TUsbConfigurationDescriptor; + + strict protected + function GetPipe( id: byte): TPipe; + + public + constructor Create( Driver: TUsbDriver); + destructor Destroy; override; + + procedure AfterConstruction; override; + procedure BeforeDestruction; override; + + public + property Pipes[i:byte] : TPipe read GetPipe; + end; + +implementation +uses + SysUtils, + Windows; + +{ TUsbConfiguration } + +// @@@: Construction / destruction ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Construction / destruction +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// Constructor +// ================================================================================================ +constructor TUsbConfiguration.Create(Driver: TUsbDriver); +begin + fDriver := Driver; + fPipeMap := TPipeMap.Create([doOwnsValues]); +end; + +// ================================================================================================ +// Destructor +// ================================================================================================ +destructor TUsbConfiguration.Destroy; +begin + FreeAndNil(fPipeMap); + inherited; +end; + +// ================================================================================================ +// After construction +// ================================================================================================ +procedure TUsbConfiguration.AfterConstruction; +var + intf : TUsbAlternateSettingDescriptor; + info : TusbPipeInformation; + pipe : TPipe; + len : cardinal; + i : integer; + +begin + inherited; + + if Assigned( fDriver) then + begin + // ------------------------------------------------------------ + // Get configuration + // ------------------------------------------------------------ + fDriver.GetDescriptor( DSCR_CONFIGURATION, + 0, 0, + @fConfiguration, + sizeof( TUsbConfigurationDescriptor), + len); + + // ------------------------------------------------------------ + // Query interface/alternate settings + // ------------------------------------------------------------ + if fDriver.QueryInterfaceSettings(0,intf) then + begin + for i:=0 to intf.EndpointCount-1 do + begin + info.PipeType := ptIsochronous; + info.PipeId := $FF; + info.MaxPacketSize := $AABB; + info.Interval := $CC; + + if fDriver.QueryPipe( 0, i, info) then + begin + pipe := TPipe.Create( fDriver, info); + fPipeMap.Add( info.PipeId, pipe); + end; + end; + end; + end +end; + +// ================================================================================================ +// Before destruction +// ================================================================================================ +procedure TUsbConfiguration.BeforeDestruction; +begin + + + inherited +end; + +// ================================================================================================ +// Get Pipe by ID +// ================================================================================================ +function TUsbConfiguration.GetPipe(id: byte): TPipe; +begin + if not fPipeMap.TryGetValue( id, result) then + result := nil; +end; + + +end. diff --git a/src.devmgr/dev/usb/mr.dev.usb.pas b/src.devmgr/dev/usb/mr.dev.usb.pas new file mode 100644 index 0000000..e34ceda --- /dev/null +++ b/src.devmgr/dev/usb/mr.dev.usb.pas @@ -0,0 +1,264 @@ +unit mr.dev.usb; + +interface +uses + mr.dev, + mr.dev.usb.configuration, + mr.dev.usb.pipe0, + mr.dev.usb.pipe, + mr.drv.usb, + mr.drv.usb.types; + +type + + TUsbDevice = class abstract(TDevice) + protected + fPipe0Class : TPipe0Class; + fPipe0 : TPipe0; + + protected + fUsbDriver : TUsbDriver; + fDeviceDescriptor : TUsbDeviceDescriptor; + fUsbConfiguration : TUsbConfiguration; + + protected + function GetVendorID : word; + function GetProductID : word; + function GetLocation : string; + function GetDescription : string; + function GetDevicePath : string; + + function GetPipe( id: byte): TPipe; + + protected + procedure ReadConfiguration; + + public + procedure Open; override; + procedure Close; override; + + public + procedure AfterConstruction; override; + procedure BeforeDestruction; override; + + public + property VendorID : word read GetVendorID; + property ProductID : word read GetProductID; + + property Location : string read GetLocation; + property Description : string read GetDescription; + property DevicePath : string read GetDevicePath; + + public + property Pipe0 : TPipe0 read fPipe0; + property Pipes[id:byte] : TPipe read GetPipe; + end; + + TUsbDeviceClass = class of TUsbDevice; + +implementation +uses + SysUtils, + mr.dev.manager; + +{ TUsbDevice } + +// @@@: Construction / destruction ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Construction / destruction +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// After Construction +// ================================================================================================ +procedure TUsbDevice.AfterConstruction; +begin + inherited; + + if fDriver is TUsbDriver + then fUsbDriver := fDriver as TUsbDriver + else fUsbDriver := nil +end; + +// ================================================================================================ +// Before Destruction +// ================================================================================================ +procedure TUsbDevice.BeforeDestruction; +begin + Close; + + FreeAndNil( fDriver); + + fUsbDriver := nil; + inherited +end; + + +// @@@: Interface +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Interface +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// ================================================================================================ +// Open +// ================================================================================================ +procedure TUsbDevice.Open; +var + len : cardinal; + info : TUsbPipeInformation; + +begin + if Assigned(fUsbDriver) then + begin + fUsbDriver.Open; + + // ------------------------------------------------------------ + // Get device descriptor + // ------------------------------------------------------------ + fUsbDriver.GetDescriptor( DSCR_DEVICE, + 0, 0, + @fDeviceDescriptor, + sizeof( TUsbDeviceDescriptor), + len); + + // ------------------------------------------------------------ + // Read device configuration + // ------------------------------------------------------------ + fUsbConfiguration := TUsbConfiguration.Create(fUsbDriver); + + // ------------------------------------------------------------ + // Create Control Pipe + // ------------------------------------------------------------ + info.PipeType := ptControl; + info.PipeId := 0; + info.MaxPacketSize := 0; + info.Interval := 0; + + if Assigned( fPipe0Class) + then fPipe0 := fPipe0Class.Create(fUsbDriver, info) + else fPipe0 := nil + end; +end; + +// ================================================================================================ +// Close +// ================================================================================================ +procedure TUsbDevice.Close; +begin + FreeAndNil( fPipe0); + FreeAndNil( fUsbConfiguration); + + if Assigned( fUsbDriver) then + fUsbDriver.Close; +end; + + +// @@@: Internals +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Internals +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// Read configuration +// ================================================================================================ +procedure TUsbDevice.ReadConfiguration; +var + cfg: TUsbConfigurationDescriptor; + len: cardinal; + +begin + if Assigned(fUsbDriver) then + begin + // ------------------------------------------------------------ + // Get configuration + // ------------------------------------------------------------ + len := 0; + fUsbDriver.GetDescriptor( DSCR_CONFIGURATION, + 0, 0, + @cfg, + sizeof( TUsbConfigurationDescriptor), + len); + end +end; + + + +// @@@: Property handlers +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Property handlers +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// ================================================================================================ +// get device path +// ================================================================================================ +function TUsbDevice.GetDevicePath: string; +begin + assert(fUsbDriver <> nil); + result := fDriver.DevicePath +end; + +// ================================================================================================ +// get vendor ID (VID) +// ================================================================================================ +function TUsbDevice.GetVendorID: word; +begin + assert(fUsbDriver <> nil); + result := fUsbDriver.VendorID +end; + + +// ================================================================================================ +// get product ID (PID) +// ================================================================================================ +function TUsbDevice.GetProductID: word; +begin + assert(fUsbDriver <> nil); + result := fUsbDriver.ProductID +end; + +// ================================================================================================ +// get location +// ================================================================================================ +function TUsbDevice.GetLocation: string; +begin + assert(fUsbDriver <> nil); + result := fUsbDriver.Location +end; + +// ================================================================================================ +// get description +// ================================================================================================ +function TUsbDevice.GetDescription: string; +begin + assert(fUsbDriver <> nil); + result := fUsbDriver.Description +end; + +// ================================================================================================ +// get pipe by ID +// ================================================================================================ +function TUsbDevice.GetPipe(id: byte): TPipe; +begin + assert( fUsbDriver <> nil); + result := fUsbConfiguration.Pipes[id] +end; + +end. diff --git a/src.devmgr/dev/usb/mr.dev.usb.pipe.pas b/src.devmgr/dev/usb/mr.dev.usb.pipe.pas new file mode 100644 index 0000000..c9ca91c --- /dev/null +++ b/src.devmgr/dev/usb/mr.dev.usb.pipe.pas @@ -0,0 +1,108 @@ +unit mr.dev.usb.pipe; + +interface +uses + Windows, + mr.drv.usb, + mr.dev.usb.pipebase; + +type + TPipe = class( TPipeBase) + + public + function Read( var Buffer; + BufferLength : cardinal; + var Transferred : cardinal; + Overlapped : POverlapped = nil) : boolean; + + function Write( var Buffer; + BufferLength : cardinal; + var Transferred : cardinal; + Overlapped : POverlapped = nil) : boolean; + + public + function Abort : boolean; + function Flush : boolean; + function Reset : boolean; + end; +implementation + +{ TPipe } + +// @@@: Construction / destruction ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Construction / destruction +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// ================================================================================================ +// Abort +// ================================================================================================ +function TPipe.Abort: boolean; +begin + if Assigned( fDriver) + then result := fDriver.AbortPipe( fPipeInfo.PipeID) + else result := false +end; + +// ================================================================================================ +// Flush +// ================================================================================================ +function TPipe.Flush: boolean; +begin + if Assigned( fDriver) + then result := fDriver.FlushPipe( fPipeInfo.PipeID) + else result := false +end; + +// ================================================================================================ +// Reset +// ================================================================================================ +function TPipe.Reset: boolean; +begin + if Assigned( fDriver) + then result := fDriver.ResetPipe( fPipeInfo.PipeID) + else result := false +end; + +// ================================================================================================ +// Read +// ================================================================================================ +function TPipe.Read(var Buffer; + BufferLength : cardinal; + var Transferred : cardinal; + Overlapped : POverlapped): boolean; +begin + if Assigned( fDriver) then + result := fDriver.ReadPipe( fPipeInfo.PipeId, + @Buffer, + BufferLength, + Transferred, + Overlapped) + else + result := false; +end; + +// ================================================================================================ +// Write +// ================================================================================================ +function TPipe.Write( var Buffer; + BufferLength : cardinal; + var Transferred : cardinal; + Overlapped : POverlapped): boolean; +begin + if Assigned( fDriver) then + result := fDriver.WritePipe( fPipeInfo.PipeId, + @Buffer, + BufferLength, + Transferred, + Overlapped) + else + result := false; +end; + +end. diff --git a/src.devmgr/dev/usb/mr.dev.usb.pipe0.pas b/src.devmgr/dev/usb/mr.dev.usb.pipe0.pas new file mode 100644 index 0000000..8f6cc14 --- /dev/null +++ b/src.devmgr/dev/usb/mr.dev.usb.pipe0.pas @@ -0,0 +1,74 @@ +unit mr.dev.usb.pipe0; + +interface +uses + mr.drv.usb, + mr.drv.usb.types, + mr.dev.usb.pipebase; + +const + bmDirIn = $80; // bit 7: data transfer direction + bmDirOut = $00; + + bmTypeStandrad = $00; // bit 6..5: data transfer type + bmTypeClass = $20; + bmTypeVendor = $40; + + bmRecDevice = $00; // bit 4..0: Recipient + bmRecInterface = $01; + bmRecEndpoint = $02; + bmRecOther = $03; + +type + TPipe0 = class( TPipeBase) + public + function Transfer( RequestType : byte; + Request : byte; + Value : word; + Index : word; + Length : word; + Buffer : pointer; + BufferLength: cardinal; + var Transferred : cardinal; + Overlapped : pointer=nil): boolean; + + end; + + TPipe0Class = class of TPipe0; + + +implementation + +{ TPipe0 } + +// ================================================================================================ +// Transfer +// ================================================================================================ +function TPipe0.Transfer( RequestType : byte; + Request : byte; + Value : word; + Index : word; + Length : word; + Buffer : pointer; + BufferLength: cardinal; + var Transferred : cardinal; + Overlapped : pointer): boolean; +var + sud: TUsbSetupPacket; + +begin + result := false; + + if Assigned( fDriver) then + begin + sud.RequestType := RequestType; + sud.Request := Request; + sud.Value := Value; + sud.Index := Index; + sud.Length := Length; + + result := fDriver.ControlTransfer( sud, Buffer, BufferLength, Transferred, Overlapped) + end +end; + +end. diff --git a/src.devmgr/dev/usb/mr.dev.usb.pipebase.pas b/src.devmgr/dev/usb/mr.dev.usb.pipebase.pas new file mode 100644 index 0000000..a3c545e --- /dev/null +++ b/src.devmgr/dev/usb/mr.dev.usb.pipebase.pas @@ -0,0 +1,44 @@ +unit mr.dev.usb.pipebase; + +interface +uses + mr.drv.usb, + mr.drv.usb.types; + +type + TPipeBase = class + protected + fDriver : TUsbDriver; + fPipeInfo: TUsbPipeInformation; + + public + constructor Create( Driver : TUsbDriver; + PipeInfo : TUsbPipeInformation); + + public + property ID : byte read fPipeInfo.PipeID; + end; + +implementation + +{ TPipe } + +// @@@: Construction / destruction ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Construction / destruction +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// Constructor +// ================================================================================================ +constructor TPipeBase.Create(Driver: TUsbDriver; PipeInfo: TUsbPipeInformation); +begin + fDriver := Driver; + fPipeInfo := PipeInfo; +end; + +end. diff --git a/src.devmgr/dev/usb/trinity/modules/cfg/m.cfg.pas b/src.devmgr/dev/usb/trinity/modules/cfg/m.cfg.pas new file mode 100644 index 0000000..28903e4 --- /dev/null +++ b/src.devmgr/dev/usb/trinity/modules/cfg/m.cfg.pas @@ -0,0 +1,205 @@ +unit m.cfg; + +interface +uses + m.base, + m.cfg.types; + +type + TmodCFG = class( TmodBase, ICFG) + // ------------------------------------------------------------ + // ICFG + // ------------------------------------------------------------ + protected + function GetCapabilities: Int64; + function GetSerialNumber: AnsiString; + function GetIdentifier : AnsiString; + + procedure SetSerialNumber( value: AnsiString); + procedure SetIdentifier( value: AnsiString); + end; + +implementation + +{ TmodCFG } + + + +// @@@: ICFG ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// ICFG +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// get capabilities +// ================================================================================================ +function TmodCFG.GetCapabilities: Int64; +var + buf : array[0..7] of AnsiChar; + cnt : cardinal; + +begin + result := 1; + + if Assigned(fDevice) then + begin + with fDevice do + begin + Open; + + if (VendorID = $16d0) and (ProductID = $0712) then + begin + cnt := 0; + + if Pipe0.Transfer( $80, // IN + $E0, // Get Serial + $00, // Value (not used) + $00, // Index (not used) + $08, // Length + + @buf, // Buffer to receive data + 8, // Length of buffer + cnt, // Transferred bytes + nil) then // Overlapped (not used) + begin + Result := PInt64(@buf)^; + end + end; + + Close; + end + end + + else + // raise +end; + +// ================================================================================================ +// get serial number +// ================================================================================================ +function TmodCFG.GetSerialNumber: AnsiString; +var + buf : array[0..7] of AnsiChar; + cnt : cardinal; + i : integer; + +begin + result := ''; + + if Assigned(fDevice) then + begin + with fDevice do + begin + Open; + + if (VendorID = $16d0) and (ProductID = $0712) then + begin + cnt := 0; + + if Pipe0.Transfer( $80, // IN + $E1, // Get Serial + $00, // Value (not used) + $00, // Index (not used) + $08, // Length + + @buf, // Buffer to receive data + 8, // Length of buffer + cnt, // Transferred bytes + nil) then // Overlapped (not used) + begin + for i:=0 to 7 do + if buf[i] in ['a'..'z','A'..'Z','0'..'9','$','.','_','-'] + then Result := Result + buf[i] + else break + end + end; + + Close; + end + end + + else + // raise +end; + +// ================================================================================================ +// set serial number +// ================================================================================================ +procedure TmodCFG.SetSerialNumber(value: AnsiString); +begin + if Assigned(fDevice) then + begin + + end + + else + // raise +end; + +// ================================================================================================ +// get identifier +// ================================================================================================ +function TmodCFG.GetIdentifier: AnsiString; +var + buf : array[0..7] of AnsiChar; + cnt : cardinal; + i : integer; + +begin + result := ''; + + if Assigned(fDevice) then + begin + with fDevice do + begin + Open; + + if (VendorID = $16d0) and (ProductID = $0712) then + begin + cnt := 0; + + if Pipe0.Transfer( $80, // IN + $E2, // Get Serial + $00, // Value (not used) + $00, // Index (not used) + $08, // Length + + @buf, // Buffer to receive data + 8, // Length of buffer + cnt, // Transferred bytes + nil) then // Overlapped (not used) + begin + for i:=0 to 7 do + if buf[i] in ['a'..'z','A'..'Z','0'..'9','$','.','_','-'] + then Result := Result + buf[i] + else break + end + end; + + Close; + end + end + + else + // raise +end; + +// ================================================================================================ +// set identifier +// ================================================================================================ +procedure TmodCFG.SetIdentifier(value: AnsiString); +begin + if Assigned(fDevice) then + begin + + end + + else + // raise +end; + +end. diff --git a/src.devmgr/dev/usb/trinity/modules/cfg/m.cfg.types.pas b/src.devmgr/dev/usb/trinity/modules/cfg/m.cfg.types.pas new file mode 100644 index 0000000..e129a90 --- /dev/null +++ b/src.devmgr/dev/usb/trinity/modules/cfg/m.cfg.types.pas @@ -0,0 +1,28 @@ +unit m.cfg.types; + +interface +const + CFG_CAPS : byte = $E0; + CFG_SERIAL : byte = $E1; + CFG_IDENTIFIER : byte = $E2; + +type + ICFG = interface + ['{7B6D3FDA-4C46-4B21-8490-8E7A8AE8BEEA}'] + + function GetCapabilities: Int64; + function GetSerialNumber: AnsiString; + function GetIdentifier : AnsiString; + + procedure SetSerialNumber( value: AnsiString); + procedure SetIdentifier( value: AnsiString); + + property Capabilities : Int64 read GetCapabilities; + property SerialNumber : AnsiString read GetSerialNumber write SetSerialNumber; + property Identifier : AnsiString read GetIdentifier write SetIdentifier; + end; + + +implementation + +end. diff --git a/src.devmgr/dev/usb/trinity/modules/eeprom/m.eeprom.pas b/src.devmgr/dev/usb/trinity/modules/eeprom/m.eeprom.pas new file mode 100644 index 0000000..db44b27 --- /dev/null +++ b/src.devmgr/dev/usb/trinity/modules/eeprom/m.eeprom.pas @@ -0,0 +1,65 @@ +unit m.eeprom; + +interface +uses + m.base, + m.eeprom.types; + +type + TmodEEPROM = class( TmodBase, IEEPROM) + // ------------------------------------------------------------ + // IEEPROM + // ------------------------------------------------------------ + protected + function ReadPage( Page : word; Buffer: pointer): integer; + function WritePage( Page : word; Buffer: pointer): integer; + end; + + +implementation + +{ TmodEEPROM } + + +// @@@: IEEPROM +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// IEEPROM +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// read page +// ================================================================================================ +function TmodEEPROM.ReadPage(Page: word; Buffer: pointer): integer; +begin + if Assigned( fDevice) then + begin + + end + + else + ; // raise + + result := 0 +end; + +// ================================================================================================ +// write page +// ================================================================================================ +function TmodEEPROM.WritePage(Page: word; Buffer: pointer): integer; +begin + if Assigned( fDevice) then + begin + + end + + else + ;// raise + + result := 0 +end; + +end. diff --git a/src.devmgr/dev/usb/trinity/modules/eeprom/m.eeprom.types.pas b/src.devmgr/dev/usb/trinity/modules/eeprom/m.eeprom.types.pas new file mode 100644 index 0000000..1a3e983 --- /dev/null +++ b/src.devmgr/dev/usb/trinity/modules/eeprom/m.eeprom.types.pas @@ -0,0 +1,14 @@ +unit m.eeprom.types; + +interface +type + IEEPROM = interface + ['{DF79DCE2-900B-41FF-B128-3C6CBC9E34D9}'] + + function ReadPage( PageNumber : word; Buffer: pointer): integer; + function WritePage( PageNumber : word; Buffer: pointer): integer; + end; + +implementation + +end. diff --git a/src.devmgr/dev/usb/trinity/modules/i2c/m.iic.pas b/src.devmgr/dev/usb/trinity/modules/i2c/m.iic.pas new file mode 100644 index 0000000..a68fc74 --- /dev/null +++ b/src.devmgr/dev/usb/trinity/modules/i2c/m.iic.pas @@ -0,0 +1,185 @@ +unit m.iic; + +interface +uses + m.base, + m.iic.types; + +type + TmodIIC = class( TmodBase, IIIC) + protected + function Wait( addr : word; + tmo : word = 100): TIICStatus; + + function Write( addr : word; + count : byte; + buffer : pointer; + tmo : word = 100): TIICStatus; + + function Read( addr : word; + count : byte; + buffer : pointer; + tmo : word = 100): TIICStatus; + + function ReadRSW( addr : word; + subaddr : word; + count : byte; + buffer : pointer; + tmo : word = 100): TIICStatus; + end; + + +implementation +uses + windows, math, + mr.dev.usb.pipe; + + +function CyWORD( value: word): word; overload; +begin + result := (LoByte(value) shl 8) or HiByte(value); +end; + +function CyWORD( value: byte): word; overload; +begin + result := value shl 8; +end; + + + +{ TmodIIC } + +// @@@: IIIC ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// IIIC +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// wait +// ================================================================================================ +function TmodIIC.Wait(addr: word; tmo: word): TIICStatus; +begin + result := IIC_TMO; + +end; + +// ================================================================================================ +// write +// ================================================================================================ +function TmodIIC.Write(addr: word; count: byte; buffer: pointer; tmo: word): TIICStatus; +var + buf: TIICPacket; + len: cardinal; + + p01: TPipe; + p81: TPipe; + +begin + result := IIC_TMO; + + if Assigned(fDevice) then + begin + p01 := fDevice.Pipes[$01]; + p81 := fDevice.Pipes[$81]; + + if Assigned(p01) and Assigned(p81) then + begin + FillChar( buf, sizeof(buf), 0); + + buf.head.command := IIC_WRITE; + buf.head.timeout := tmo; + buf.head.address := CyWORD(addr); + buf.head.length := min(count, 32); + + MoveMemory(@buf.data[0], buffer, buf.head.length); + + p01.Write( buf, sizeof( TIICPacket), len); + p81.Read( buf, sizeof( TIICPacketHead), len) + end + end +end; + +// ================================================================================================ +// read +// ================================================================================================ +function TmodIIC.Read(addr: word; count: byte; buffer: pointer; tmo: word): TIICStatus; +var + buf: TIICPacket; + len: cardinal; + + p01: TPipe; + p81: TPipe; + +begin + result := IIC_TMO; + + if Assigned(fDevice) then + begin + p01 := fDevice.Pipes[$01]; + p81 := fDevice.Pipes[$81]; + + if Assigned(p01) and Assigned(p81) then + begin + FillChar( buf, sizeof(buf), 0); + + buf.head.command := IIC_READ; + buf.head.timeout := tmo; + buf.head.address := CyWORD(addr); + buf.head.length := min(count, 32); + + if p01.Write( buf, sizeof( TIICPacketHead), len) then + begin + p81.Read( buf, sizeof( TIICPacket), len); + + result := TIICStatus(buf.head.timeout); + + if result = IIC_OK then + MoveMemory(buffer, @buf.data[0], buf.head.length) + end; + + end + end +end; + +// ================================================================================================ +// read with repeated start condition, 16 bit sub address +// ================================================================================================ +function TmodIIC.ReadRSW(addr: word; subaddr: word; count: byte; buffer: pointer; tmo: word): TIICStatus; +var + buf: TIICPacket; + len: cardinal; + + p01: TPipe; + p81: TPipe; + +begin + result := IIC_TMO; + + if Assigned(fDevice) then + begin + p01 := fDevice.Pipes[$01]; + p81 := fDevice.Pipes[$81]; + + if Assigned(p01) and Assigned(p81) then + begin + FillChar( buf, sizeof(buf), 0); + + buf.head.command := IIC_READ_RSW; + buf.head.timeout := tmo; + buf.head.address := CyWORD(addr); + buf.head.subaddr := CyWORD(subaddr); + buf.head.length := min(count, 32); + + p01.Write( buf, sizeof( TIICPacketHead), len); + p81.Read( buf, sizeof( TIICPacket), len); + + MoveMemory(buffer, @buf.data[0], buf.head.length) + end + end +end; + +end. diff --git a/src.devmgr/dev/usb/trinity/modules/i2c/m.iic.types.pas b/src.devmgr/dev/usb/trinity/modules/i2c/m.iic.types.pas new file mode 100644 index 0000000..ecd3989 --- /dev/null +++ b/src.devmgr/dev/usb/trinity/modules/i2c/m.iic.types.pas @@ -0,0 +1,64 @@ +unit m.iic.types; + +interface +type + TIICCommand = + ( + IIC_READ = $80, + IIC_READ_RSW = $81, + IIC_READ_RSB = $81, + + IIC_WRITE = $00 + ); + + TIICPacketHead = packed record + command : TIICCommand; + address : WORD; + subaddr : WORD; + length : BYTE; + reserved : BYTE; + timeout : BYTE; + end; + + TIICPacket = packed record + head : TIICPacketHead; + data : array [0..31] of BYTE; + end; + + TIICStatus = + ( + IIC_OK = 0, // IIC operation successfull + IIC_TMO = 1, // Timeout + IIC_ARB = 4, // bus arbitration error + IIC_NAK = 5, // no ACK from slave + + IIC_EADR = 90, // Invalid address + IIC_ELEN = 91 // Invalid length + ); + + IIIC = interface + ['{7D675CBC-2642-4DBD-B8FC-AEE5C3864E0E}'] + function Wait( addr : word; + tmo : word): TIICStatus; + + function Write( addr : word; + count : byte; + buffer : pointer; + tmo : word): TIICStatus; + + function Read( addr : word; + count : byte; + buffer : pointer; + tmo : word): TIICStatus; + + function ReadRSW( addr : word; + subaddr : word; + count : byte; + buffer : pointer; + tmo : word): TIICStatus; + + end; + +implementation + +end. diff --git a/src.devmgr/dev/usb/trinity/modules/jtag/m.jtag.pas b/src.devmgr/dev/usb/trinity/modules/jtag/m.jtag.pas new file mode 100644 index 0000000..edb0a29 --- /dev/null +++ b/src.devmgr/dev/usb/trinity/modules/jtag/m.jtag.pas @@ -0,0 +1,649 @@ +unit m.jtag; + +interface +uses + Classes, + m.base, + m.jtag.types; + +type + TmodJTAG = class( TmodBase, IJTAG) + protected + // stat + nINIT : cardinal; + nTRST : cardinal; + + nENDIR : cardinal; + nENDDR : cardinal; + nSTATE : cardinal; + + nSIR : cardinal; + nSDR : cardinal; + nRUN : cardinal; + + + // high level functions + function scan( buffer: PCardinal; + maxcnt: byte): word; + + function play( filename : string): boolean; + + function playsvf( stm : TMemoryStream) : boolean; + + // primitive functions + procedure init; + procedure trst( value : BYTE); + procedure ena( value : BYTE); + + procedure endir( state : TJTAGState); + procedure enddr( state : TJTAGState); + procedure state( state : TJTAGState); + + function sir( data : PBYTE; bitcount: WORD; last: byte=1): cardinal; virtual; + function sdr( data : PBYTE; bitcount: WORD; last: byte=1): cardinal; virtual; + function sdw( data : PBYTE; bitcount: WORD; last: byte=1): cardinal; virtual; + + procedure run( state : TJTAGState; count: WORD); + + procedure test; + end; + +implementation +uses + Windows, Math, SysUtils, Diagnostics, + + mr.dev.usb, + mr.dev.usb.pipe, + mr.dev.usb.pipe0, + + jtag.svfLexer, + jtag.svfScanLexer, + jtag.svfParser, + jtag.svfProgram, + jtag.svfAstNode, + jtag.svfAstEndIR, + jtag.svfAstEndDR, + jtag.svfAstScan, + jtag.svfAstPrint, + jtag.svfAstComment, + jtag.svfAstRuntest, + jtag.svfAstState; + + +const + // EP0 comands + CMD_JTAG_INIT = $C0; + CMD_JTAG_RESET = $C1; + CMD_JTAG_ENABLE = $C2; + CMD_JTAG_STATUS = $C3; + + CMD_JTAG_ENDIR = $C8; + CMD_JTAG_ENDDR = $C9; + CMD_JTAG_STATE = $CA; + CMD_JTAG_TRST = $CB; + + CMD_JTAG_TEST = $CF; + + // EP2 commands + CMD_JTAG_SCAN = $C0; + CMD_JTAG_SIR = $C1; + CMD_JTAG_SDR = $C2; + CMD_JTAG_RUN = $C3; + CMD_JTAG_SDW = $C4; + +type + PcmdJTAG = ^TcmdJTAG; + TcmdJTAG = packed record + command : byte; + status : byte; + number : word; + id : cardinal; + data : array [0 .. 1023] of byte; + end; + + PcmdJTAGHead = ^TcmdJTAGHead; + TcmdJTAGHead = packed record + command : byte; + status : byte; + number : word; + id : cardinal; + end; + + PcmdJTAGScan = ^TcmdJTAGScan; + TcmdJTAGScan = packed record + head: TcmdJTAGHead; + count: byte; + dummy: array [0 .. 2] of byte; + id: array [0 .. 125] of cardinal; +// id: array [0..503] of byte; + end; + +{ TmodJTAG } + +function CyWORD( state: TJTAGState): word; overload; +begin + result := BYTE(state) shl 8 +end; + +function CyWORD( value: word): word; overload; +begin + result := (LoByte(value) shl 8) or HiByte(value); +end; + +function CyWORD( value: byte): word; overload; +begin + result := value shl 8; +end; + + + +// @@@: IJTAG +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// IJTAG +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// scan +// ================================================================================================ +function TmodJTAG.scan( buffer: PCardinal; maxcnt: byte): word; +var + cmd : TcmdJTAGScan; + rsp : TcmdJTAGScan; + len : cardinal; + i : integer; + + pipe02: TPipe; + pipe84: TPipe; + +begin + result := 0; + + if Assigned(fDevice) then + with fDevice do + begin + pipe02 := Pipes[$02]; + pipe84 := Pipes[$84]; + + if Assigned(pipe02) and Assigned(pipe84) then + begin + ZeroMemory(@rsp, sizeof(rsp)); + ZeroMemory(@cmd, sizeof(cmd)); + + cmd.head.command := CMD_JTAG_SCAN; + + if pipe02.Write(cmd, sizeof(TcmdJTAGHead), len) then + begin + sleep(100); + + if pipe84.Read(rsp, sizeof(rsp), len) then + begin + result := rsp.count; + + for i:=0 to min(result, maxcnt) -1 do + begin + Buffer^ := rsp.id[0]; + INC(buffer) + end + end + end + end + end +end; + +// ================================================================================================ +// play +// ================================================================================================ +function TmodJTAG.play( filename : string): boolean; +var + stm : TMemoryStream; + +begin + result := false; + + if FileExists(filename) then + begin + stm := TMemoryStream.Create; + stm.LoadFromFile(filename); + + result := playsvf(stm); + + stm.Free + end; +end; + +// ================================================================================================ +// play svf file +// ================================================================================================ +function TmodJTAG.playsvf( stm: TMemoryStream) : boolean; +var + scn : TsvfScanLexer; + lex : TsvfLexer; + par : TsvfParser; + + i,j : integer; + inst : AnsiString; + bits : integer; + cnt : integer; + last : byte; + data : PByteArray; + + sRUN : TJTAGState; + sEND : TJTAGState; + sCNT : cardinal; + + prg : TsvfProgram; + stmt : TsvfAstNode; + stRun : TsvfAstRuntest; + stSta : TsvfAstState; + stScn : TsvfAstScan; + +begin + + nINIT := 0; + nTRST := 0; + + nENDIR := 0; + nENDDR := 0; + nSTATE := 0; + + nSIR := 0; + nSDR := 0; + nRUN := 0; + + result := false; + + if Assigned(stm) then + begin + try + lex := TsvfLexer .Create( stm); + par := TsvfParser .Create( lex); + scn := TsvfScanLexer .Create( lex.InputState); + + prg := par.svf(scn); + + for i:=0 to prg.StatementCount -1 do + begin + stmt := prg.Statements[i]; + + // ------------------------------------------------------ + // ENDIR (2) + // ------------------------------------------------------ + if stmt is TsvfAstEndIR then + case TsvfAstEndIR(stmt).State of + stRESET : endir(TS_RESET ); + stIDLE : endir(TS_IDLE ); + stIRPAUSE : endir(TS_IRPAUSE ); + stDRPAUSE : endir(TS_DRPAUSE ); + else + end + + // ------------------------------------------------------ + // ENDDR (3) + // ------------------------------------------------------ + else if stmt is TsvfAstEndDR then + case TsvfAstEndIR(stmt).State of + stRESET : enddr(TS_RESET ); + stIDLE : enddr(TS_IDLE ); + stIRPAUSE : enddr(TS_IRPAUSE ); + stDRPAUSE : enddr(TS_DRPAUSE ); + else + end + + // ------------------------------------------------------ + // SCAN (4,5) + // ------------------------------------------------------ + else if stmt is TsvfAstScan then + begin + stScn := TsvfAstScan(stmt); + inst := stscn.Inst; + + // ----------------------------------------- + // SIR + // ----------------------------------------- + if inst = 'SIR' then + begin + bits := stScn.Bits; + + while bits > 0 do + begin + if bits < 4000 + then last := 1 + else last := 0; + + cnt := Min( bits, 4000); + data:= stScn.DataTDI; + + sir( PByte(data),cnt,last); + + DEC(bits,cnt); + end + end + + // ----------------------------------------- + // SDR + // ----------------------------------------- + else if inst = 'SDR' then + begin + bits := stScn.Bits; + + while bits > 0 do + begin + if bits < 4000 + then last := 1 + else last := 0; + + cnt := Min( bits, 4000); + data:= stScn.DataTDI; + + if stScn.DataTDO = nil then + sdw( PByte(data),cnt,last) + + else begin + sdr( PByte(data),cnt,last); + data:= stScn.DataTDO; + end; + + DEC(bits,cnt); + end + + end + + // ----------------------------------------- + // HDR + // ----------------------------------------- + else if inst = 'HDR' then + begin + + end + + // ----------------------------------------- + // HIR + // ----------------------------------------- + else if inst = 'HIR' then + begin + + end + + // ----------------------------------------- + // TDR + // ----------------------------------------- + else if inst = 'HDR' then + begin + + end + + // ----------------------------------------- + // TIR + // ----------------------------------------- + else if inst = 'HIR' then + begin + + end + + end + + // ------------------------------------------------------ + // RUNTEST (6) + // ------------------------------------------------------ + else if stmt is TsvfAstRuntest then + begin + stRUN := TsvfAstRuntest(stmt); + + if stRUN.RunClock = 'TCK' then + begin + case stRun.RunState of + stRESET : sRUN := TS_RESET; + stIDLE : sRUN := TS_IDLE; + stIRPAUSE : sRUN := TS_IRPAUSE; + stDRPAUSE : sRUN := TS_DRPAUSE; + else sRUN := TS_UNDEF + end; + + case stRun.EndState of + stRESET : sEND := TS_RESET; + stIDLE : sEND := TS_IDLE; + stIRPAUSE : sEND := TS_IRPAUSE; + stDRPAUSE : sEND := TS_DRPAUSE; + else sEND := TS_UNDEF + end; + + sCNT := StrToInt(string(stRun.RunCount)); + + if (sRUN <> TS_UNDEF) and (sCNT > 0) then + begin + while sCNT > 0 do + begin + run(sRUN, min(sCNT,32000)); + DEC(sCNT, min(sCNT,32000)); + end; + + if sEND <> TS_UNDEF then + state(sEND) + end + end + end + + // ------------------------------------------------------ + // STATE (8) + // ------------------------------------------------------ + else if stmt is TsvfAstState then + begin + stSta := TsvfAstState(stmt); + + for j:=0 to stSta.StateCount -1 do + begin + case stSta.States[j] of + stRESET : sRUN := TS_RESET; + stIDLE : sRUN := TS_IDLE; + stIRPAUSE : sRUN := TS_IRPAUSE; + stDRPAUSE : sRUN := TS_DRPAUSE; + + else sRUN := TS_UNDEF + end; + + if sRUN <> TS_UNDEF then + state(sRUN) + end + end + end; + + except + + end + end +end; + + + +// @@@: IJTAG primitives ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// IJTAG primitives +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// pipe0_cmd_out +// ================================================================================================ +function pipe0_cmd_out( dev: TusbDevice; req: byte; val: word=0; idx: word=0): boolean; +var + typ : byte; + p0 : TPipe0; + len : cardinal; + +begin + result := true; + + if Assigned( dev) and Assigned( dev.Pipe0) then + begin + typ := bmDirOut + bmTypeStandrad + bmRecDevice; + p0 := dev.Pipe0; + len := 0; + + if Assigned(p0) + then p0.Transfer( typ,req, val,idx,0,nil,0,len) + else result := false + end +end; + +// ================================================================================================ +// ep2_xfer +// ================================================================================================ +function pipe2_xfer( dev: TusbDevice; p2cmd: byte; buf: PByte; bitcount: word): cardinal; +var + pipe02 : TPipe; + pipe84 : TPipe; + + cmd : TcmdJTAG; + len : cardinal; + bytes : cardinal; + +begin + len := 0; + result := 0; + + if Assigned( dev) then + begin + pipe02 := dev.Pipes[$02]; + pipe84 := dev.Pipes[$84]; + + bytes := (bitcount +7) div 8; + + if Assigned(pipe02) and Assigned(pipe84) then + begin + ZeroMemory( @cmd, sizeof(cmd)); + + cmd.command := p2cmd; + cmd.number := CyWord(bitcount); + cmd.status := 1; + + if Assigned(buf) then + MoveMemory( @cmd.data, buf, bytes); + + if p2cmd = CMD_JTAG_SDW then + pipe02.Write( cmd,sizeof(TcmdJTAGHead)+bytes,len) + + else begin + if pipe02.Write( cmd,sizeof(TcmdJTAGHead)+bytes,len) then + if pipe84.Read(cmd,sizeof(TcmdJTAGHead)+bytes,len) then + MoveMemory(buf, @cmd.data, bytes) + end; + + result := len + end + end +end; + + +// ================================================================================================ +// INIT +// +// INIT command sent over the control endpoint EP0, because it is an important +// message. If the JTAG endpoint processing is stalled somewhere, it is not possible +// to send command using the stalled endpoint. The JTAG endpoints EP2 and EP4 are used +// only to transfer large data to the device when it is in DRSHIFT state (e.g.: programming), +// or when the device want to receive or send data (e.g.: LA data transfer, GPIF). +// +// ================================================================================================ +procedure TmodJTAG.init; +begin + INC(nINIT); + pipe0_cmd_out( fDevice, CMD_JTAG_INIT); +end; + +// ================================================================================================ +// ENABLE +// ================================================================================================ +procedure TmodJTAG.ena(value: BYTE); +begin + pipe0_cmd_out( fDevice, CMD_JTAG_ENABLE, CyWord(value)); +end; + +// ================================================================================================ +// ENDIR +// ================================================================================================ +procedure TmodJTAG.endir(state: TJTAGState); +begin + INC(nENDIR); + pipe0_cmd_out( fDevice, CMD_JTAG_ENDIR, CyWord(state)); +end; + +// ================================================================================================ +// ENDDR +// ================================================================================================ +procedure TmodJTAG.enddr(state: TJTAGState); +begin + INC(nENDDR); + pipe0_cmd_out( fDevice, CMD_JTAG_ENDDR, CyWord(state)); +end; + +// ================================================================================================ +// STATE +// ================================================================================================ +procedure TmodJTAG.state(state: TJTAGState); +begin + INC(nSTATE); + pipe0_cmd_out( fDevice, CMD_JTAG_STATE, CyWord(state)); +end; + +// ================================================================================================ +// TRST +// ================================================================================================ +procedure TmodJTAG.trst(value: BYTE); +begin + INC(nTRST); + pipe0_cmd_out( fDevice, CMD_JTAG_TRST, CyWord(value)); +end; + +// ================================================================================================ +// SIR +// ================================================================================================ +function TmodJTAG.sir(data: PByte; bitcount: word; last: byte): cardinal; +begin + INC(nSIR); + result := pipe2_xfer( fDevice, CMD_JTAG_SIR, data, bitcount); +end; + +// ================================================================================================ +// SDR +// ================================================================================================ +function TmodJTAG.sdr(data: PByte; bitcount: word; last: byte): cardinal; +begin + INC(nSDR); + result := pipe2_xfer( fDevice, CMD_JTAG_SDR, data, bitcount); +end; + +// ================================================================================================ +// SDW +// ================================================================================================ +function TmodJTAG.sdw(data: PByte; bitcount: word; last: byte): cardinal; +begin + INC(nSDR); + result := pipe2_xfer( fDevice, CMD_JTAG_SDW, data, bitcount); +end; + +// ================================================================================================ +// RUN +// ================================================================================================ +procedure TmodJTAG.run(state: TJTAGState; count: WORD); +begin + pipe0_cmd_out( fDevice, CMD_JTAG_RUN, CyWord(state), CyWord(count)); + +//-- pipe2_xfer( fDevice, CMD_JTAG_RUN, nil, count); +end; + +// ================================================================================================ +// TEST +// ================================================================================================ +procedure TmodJTAG.test; +begin +// pipe0_cmd_out( fDevice, CMD_JTAG_TEST); +end; + +end. diff --git a/src.devmgr/dev/usb/trinity/modules/jtag/m.jtag.types.pas b/src.devmgr/dev/usb/trinity/modules/jtag/m.jtag.types.pas new file mode 100644 index 0000000..554e81c --- /dev/null +++ b/src.devmgr/dev/usb/trinity/modules/jtag/m.jtag.types.pas @@ -0,0 +1,51 @@ +unit m.jtag.types; + +interface +type + TJTAGState = + ( + TS_RESET = 0, + TS_IDLE = 1, + TS_IRPAUSE = 2, + TS_DRPAUSE = 3, + TS_IRSHIFT = 4, + TS_DRSHIFT = 5, + TS_DRCAPT = 6, + TS_IREXIT1 = 7, + TS_DREXIT1 = 8, + + TS_UNDEF = $FF + ); + + IJTAG = interface + ['{063CC4AC-2694-488C-A252-C2FA427EEC75}'] + function scan( buffer : PCardinal; + maxcnt : byte): word; + + function play( filename : string): boolean; + + procedure init; + procedure ena( value : BYTE); + + // JTAG primitive functions + procedure endir( state : TJTAGState); + procedure enddr( state : TJTAGState); + procedure state( state : TJTAGState); + + function sir( data : PBYTE; bitcount: WORD; last: byte=1): cardinal; + function sdr( data : PBYTE; bitcount: WORD; last: byte=1): cardinal; + + procedure trst( value : BYTE); + procedure run( state : TJTAGState; count: WORD); + + procedure test; + end; + + IJTAGLOG = interface + procedure info( msg : string); + procedure warning( msg : string); + end; + +implementation + +end. diff --git a/src.devmgr/dev/usb/trinity/modules/lcd/m.lcd.pas b/src.devmgr/dev/usb/trinity/modules/lcd/m.lcd.pas new file mode 100644 index 0000000..4d33dfc --- /dev/null +++ b/src.devmgr/dev/usb/trinity/modules/lcd/m.lcd.pas @@ -0,0 +1,187 @@ +unit m.lcd; + +interface +uses + m.base, + m.lcd.types; + +type + TmodLCD = class( TmodBase, ILCD) + // ------------------------------------------------------------ + // ILCD + // ------------------------------------------------------------ + protected + procedure Cls; + procedure GotoXY( x,y: word); + procedure putc( const c: AnsiChar ); + procedure puts( const s: AnsiString); + end; + + +implementation +uses + Windows; + +function CyWORD( value: word): word; +begin + result := (LoByte(value) shl 8) or HiByte(value); +end; + +{ TmodLCD } + +// @@@: ILCD ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// ILCD +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// cls +// ================================================================================================ +procedure TmodLCD.Cls; +var + cnt : cardinal; + +begin + if Assigned(fDevice) then + begin + with fDevice do + begin + if (VendorID = $16d0) and (ProductID = $0712) then + begin + cnt := 0; + + Pipe0.Transfer( $00, // OUT + LCD_CLS, // cls + $0000, // Value (not used) + $0000, // Index (not used) + $0000, // Length (not used) + + nil, // Buffer to receive data + 0, // Length of buffer + cnt, // Transferred bytes + nil) // Overlapped (not used) + end; + end + end + + else + // raise +end; + +// ================================================================================================ +// gotoxy +// ================================================================================================ +procedure TmodLCD.GotoXY(x, y: word); +var + cnt : cardinal; + w : word; + +begin + if Assigned(fDevice) then + begin + with fDevice do + begin + if (VendorID = $16d0) and (ProductID = $0712) then + begin + cnt := 0; + w := CyWord((x shl 8) +y); + + Pipe0.Transfer( $00, // OUT + LCD_GOTOXY, // + w, // Value (not used) + $0000, // Index (not used) + $0000, // Length (not used) + + nil, // Buffer to receive data + 0, // Length of buffer + cnt, // Transferred bytes + nil) // Overlapped (not used) + end; + end + end + + else + // raise +end; + +// ================================================================================================ +// putc +// ================================================================================================ +procedure TmodLCD.putc(const c: AnsiChar); +var + cnt : cardinal; + w : word; + +begin + if Assigned(fDevice) then + begin + with fDevice do + begin + if (VendorID = $16d0) and (ProductID = $0712) then + begin + cnt := 0; + w := CyWord(ord(c)); + + Pipe0.Transfer( $00, // OUT + LCD_PUTC, // + w, // Value (not used) + $0000, // Index (not used) + $0000, // Length (not used) + + nil, // Buffer to receive data + 0, // Length of buffer + cnt, // Transferred bytes + nil) // Overlapped (not used) + end; + end + end + + else + // raise +end; + +// ================================================================================================ +// puts +// ================================================================================================ +procedure TmodLCD.puts(const s: AnsiString); +var + cnt : cardinal; + buf : array [0..31] of AnsiChar; + +begin + if Length(s) > 0 then + if Assigned(fDevice) then + begin + with fDevice do + begin + if (VendorID = $16d0) and (ProductID = $0712) then + begin + Windows.ZeroMemory(@buf[0],32); + cnt := 0; + buf[0] := '%'; + + + + Pipe0.Transfer( $00, // OUT + LCD_PUTS, // + $0000, // Value (not used) + $0000, // Index (not used) + 32, // Length (not used) + + @buf, // Buffer data to send + 32, // Length of buffer + cnt, // Transferred bytes + nil) // Overlapped (not used) + end; + end + end + + else + // raise +end; + +end. diff --git a/src.devmgr/dev/usb/trinity/modules/lcd/m.lcd.types.pas b/src.devmgr/dev/usb/trinity/modules/lcd/m.lcd.types.pas new file mode 100644 index 0000000..d4f9e83 --- /dev/null +++ b/src.devmgr/dev/usb/trinity/modules/lcd/m.lcd.types.pas @@ -0,0 +1,22 @@ +unit m.lcd.types; + +interface +const + LCD_CLS = $50; + LCD_GOTOXY = $51; + LCD_PUTC = $52; + LCD_PUTS = $53; + +type + ILCD = interface + ['{267BDD5D-5918-46BD-8D9A-393938C707DB}'] + + procedure Cls; + procedure GotoXY( x,y: word); + procedure putc( const c: AnsiChar); +// procedure puts( const s: AnsiString); + end; + +implementation + +end. diff --git a/src.devmgr/dev/usb/trinity/modules/led/m.led.pas b/src.devmgr/dev/usb/trinity/modules/led/m.led.pas new file mode 100644 index 0000000..89ccb58 --- /dev/null +++ b/src.devmgr/dev/usb/trinity/modules/led/m.led.pas @@ -0,0 +1,86 @@ +unit m.led; + +interface +uses + m.base, + m.led.types; + +type + TmodLED = class( TmodBase, ILED) + // ------------------------------------------------------------ + // ILED + // ------------------------------------------------------------ + procedure LedOn( led: byte); + procedure LedOff(led: byte); + end; + + +implementation +uses + Windows; + +function CyWORD( value: word): word; +begin + result := (LoByte(value) shl 8) or HiByte(value); +end; + + +{ TmodLED } + +// ================================================================================================ +// led on +// ================================================================================================ +procedure TmodLED.LedOn( LED: byte); +var + cnt : cardinal; + w : word; + +begin + cnt := 0; + w := CyWord((LED shl 8) +1); + + assert( fDevice <> nil); + + with fDevice do + if (VendorID = $16d0) and (ProductID = $0712) then + Pipe0.Transfer( $00, // OUT + LCD_LED, // + w, // Value + $0000, // Index (not used) + $0000, // Length (not used) + + nil, // Buffer to receive data + 0, // Length of buffer + cnt, // Transferred bytes + nil) // Overlapped (not used) +end; + +// ================================================================================================ +// led off +// ================================================================================================ +procedure TmodLED.LedOff( LED: byte); +var + cnt : cardinal; + w : word; + +begin + cnt := 0; + w := CyWord(LED shl 8); + + assert( fDevice <> nil); + + with fDevice do + if (VendorID = $16d0) and (ProductID = $0712) then + Pipe0.Transfer( $00, // OUT + LCD_LED, // + w, // Value + $0000, // Index (not used) + $0000, // Length (not used) + + nil, // Buffer to receive data + 0, // Length of buffer + cnt, // Transferred bytes + nil) // Overlapped (not used) +end; + +end. diff --git a/src.devmgr/dev/usb/trinity/modules/led/m.led.types.pas b/src.devmgr/dev/usb/trinity/modules/led/m.led.types.pas new file mode 100644 index 0000000..1c4ad9f --- /dev/null +++ b/src.devmgr/dev/usb/trinity/modules/led/m.led.types.pas @@ -0,0 +1,17 @@ +unit m.led.types; + +interface +const + LCD_LED = $40; + +type + ILED = interface + ['{C3908812-2FB3-4A8F-8159-9B96E06C0659}'] + + procedure LedOn( led: byte); + procedure LedOff(led: byte); + end; + +implementation + +end. diff --git a/src.devmgr/dev/usb/trinity/modules/m.base.pas b/src.devmgr/dev/usb/trinity/modules/m.base.pas new file mode 100644 index 0000000..ff61f3c --- /dev/null +++ b/src.devmgr/dev/usb/trinity/modules/m.base.pas @@ -0,0 +1,53 @@ +unit m.base; + +interface +uses + mr.trinity; + +type + TmodBase = class (TInterfacedObject) + protected + fDevice : TTrinity; + + // ------------------------------------------------------------ + // construction / destruction + // ------------------------------------------------------------ + public + constructor Create( dev: TTrinity); + destructor Destroy; override; + end; + + +implementation +uses + SysUtils; + +{ TmodBase } + +// @@@: construction / destruction ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// construction / destruction +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// constructor +// ================================================================================================ +constructor TmodBase.Create(dev: TTrinity); +begin + inherited Create; + fDevice := dev; +end; + +// ================================================================================================ +// destructor +// ================================================================================================ +destructor TmodBase.Destroy; +begin + inherited; +end; + +end. diff --git a/src.devmgr/dev/usb/trinity/mr.trinity.consts.pas b/src.devmgr/dev/usb/trinity/mr.trinity.consts.pas new file mode 100644 index 0000000..0b7fd35 --- /dev/null +++ b/src.devmgr/dev/usb/trinity/mr.trinity.consts.pas @@ -0,0 +1,56 @@ +unit mr.trinity.consts; + +interface + +const + CMD_TRI_CAPS : byte = $E0; + CMD_TRI_SERIAL : byte = $E1; + CMD_TRI_IDENTIFIER : byte = $E2; + + CFG_CAPS : byte = $E0; + CFG_SERIAL : byte = $E1; + CFG_IDENTIFIER : byte = $E2; + + +const + EEPROM_BOOT = $10; + EEPROM_CFG = $11; + EEPROM_LIC = $12; + EEPROM_USR = $13; + EEPROM_RAW = $14; + + EEPROM_READ = $80; + EEPROM_WRITE = $00; + + + DIR_OUT = $00; + DIR_IN = $80; + + EP1_I2C = $20; + EP1_EEPROM = $11; + + + bmCap0_I2C = $0001; + bmCap0_SER = $0002; + bmCap0_EPR = $0004; + bmCap0_RAM = $0008; + bmCap0_JTG = $0010; + + bmCap0_20 = $0020; + bmCap0_40 = $0040; + bmCap0_80 = $0080; + + bmCap1_LED = $0100; + bmCap1_LCD = $0200; + bmCap1_EXP = $0400; + bmCap1_LXP = $0800; + bmCap1_SDR = $1000; + + bmCap1_20 = $2000; + bmCap1_40 = $4000; + bmCap1_80 = $8000; + + +implementation + +end. diff --git a/src.devmgr/dev/usb/trinity/mr.trinity.hex.pas b/src.devmgr/dev/usb/trinity/mr.trinity.hex.pas new file mode 100644 index 0000000..5a3e9d3 --- /dev/null +++ b/src.devmgr/dev/usb/trinity/mr.trinity.hex.pas @@ -0,0 +1,457 @@ +unit mr.trinity.hex; + +interface +uses + Generics.Collections, + Classes; + +const + rtData = $00; + rtEOF = $01; + rtExtendedSegment = $02; + rtStartSegment = $03; + rtExtendedLinear = $04; + rtStartLinear = $05; + +type + THexLine = class + public + RecLength : byte; + RecType : byte; + Address : word; + Data : PByte; + Chksum : byte; + + public + destructor Destroy; override; + end; + + THexBlock = class + public + BlockLength : cardinal; + BlockType : byte; + Address : word; + Data : PByte; + + public + destructor Destroy; override; + end; + + THexLineList = TObjectList; + THexBlockList = TObjectList; + + THexFile = class + protected + fHexLines : THexLineList; + fHexBlocks : THexBlockList; + + private + function GetBlockCount : integer; + function GetBlock(i:integer): THexBlock; + + protected + function ReadLine( Stream: TStream): THexLine; + + public + procedure LoadFromFile( FileName : string); + procedure LoadFromStream( Stream : TStream); + + procedure Dump( Stream : TStream); + + public + procedure AfterConstruction; override; + procedure BeforeDestruction; override; + + public + property Lines : THexLineList read fHexLines; + property Blocks : THexBlockList read fHexBlocks; + + property BlockCount : integer read GetBlockCount; + property Block[i:integer] : THexBlock read GetBlock; + + end; + + +implementation +uses + Windows, + SysUtils; + +{ THexFile } + + + +// @@@: Construction/destruction ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Construction/destruction +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// After Construction +// ================================================================================================ +procedure THexFile.AfterConstruction; +begin + inherited; + + fHexLines := THexLineList .Create(false); + fHexBlocks := THexBlockList .Create +end; + +// ================================================================================================ +// Before Destruction +// ================================================================================================ +procedure THexFile.BeforeDestruction; +begin + FreeAndNil(fHexBlocks); + FreeAndNil(fHexLines ); + + inherited +end; + + + +// @@@: Interface +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Interface +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// Load From File +// ================================================================================================ +procedure THexFile.LoadFromFile(FileName: string); +var + stm: TMemoryStream; + +begin + if FileExists(FileName) then + begin + stm := TMemoryStream.Create; + stm.LoadFromFile(FileName); + LoadFromStream(stm); + stm.Free; + end +end; + +// ================================================================================================ +// Load From Stream +// ================================================================================================ +procedure THexFile.LoadFromStream(Stream: TStream); +var + block : THexBlock; + line : THexLine; + cnt : integer; + + procedure Compress; + var + blk1 : THexBlock; + blk2 : THexBlock; + i,j : integer; + size : integer; + ptr : PByte; + + label + loop; + + begin +loop: + + for i:=0 to fHexBlocks.Count -2 do + begin + blk1 := fHexBlocks[i]; + + for j:=1 to fHexBlocks.Count -1 do + begin + blk2 := fHexBlocks[j]; + + if (blk1.Address +blk1.BlockLength) = blk2.Address then + begin + size := blk1.BlockLength +blk2.BlockLength; + blk1.Data := ReallocMemory( blk1.Data,size); + ptr := blk1.Data; + + INC(ptr, blk1.BlockLength); + CopyMemory(ptr, blk2.Data, blk2.BlockLength); + + blk1.BlockLength := size; + + fHexBlocks.Delete(j); + + goto loop; + end + + else if (blk2.Address +blk2.BlockLength) = blk1.Address then + begin + size := blk1.BlockLength +blk2.BlockLength; + blk2.Data := ReallocMemory( blk2.Data,size); + ptr := blk2.Data; + + INC(ptr, blk2.BlockLength); + CopyMemory(ptr, blk1.Data, blk1.BlockLength); + + blk2.BlockLength := size; + + fHexBlocks.Delete(i); + + goto loop; + end; + end; + end; + end; + +begin + if Assigned(Stream) then + begin + Stream.Seek(0, soBeginning); + + // ------------------------------------------------------------ + // Read hex records + // ------------------------------------------------------------ + while true do + begin + line := ReadLine(Stream); + + if line = nil + then break + else fHexLines.Add(line) + end; + + // ------------------------------------------------------------ + // If the last record is EOF then the data is correct, + // so build the blocks. + // ------------------------------------------------------------ + cnt := fHexLines.Count; + + if (cnt > 0) and (fHexLines[cnt-1].RecType = rtEOF) then + begin + for line in fHexLines do + if line.RecType = rtData then + begin + block := THexBlock.Create; + + block.BlockLength := line.RecLength; + block.BlockType := line.RecType; + block.Address := line.Address; + block.Data := AllocMem(line.RecLength); + + CopyMemory( block.Data, line.Data, line.RecLength); + + fHexBlocks.Add(block); + end; + + Compress; + end; + end +end; + + + +// @@@: Internals +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Internals +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// Read Line +// ================================================================================================ +function THexFile.ReadLine(Stream: TStream): THexLine; + + function HexToBin( hex: byte): byte; + begin + result := 0; + + if ansichar(hex) in ['0'..'9'] then result := ord(hex) -ord('0'); + if ansichar(hex) in ['a'..'f'] then result := ord(hex) -ord('a') +10; + if ansichar(hex) in ['A'..'F'] then result := ord(hex) -ord('A') +10; + end; + + function GetByte( Data: array of byte): byte; + begin + result := (HexToBin(Data[0]) shl 4) + + (HexToBin(Data[1])); + end; + + function GetWord( Data0: array of byte; Data1: array of byte): word; + begin + result := (HexToBin(Data0[0]) shl 12) + + (HexToBin(Data0[1]) shl 8) + + (HexToBin(Data1[0]) shl 4) + + (HexToBin(Data1[1])); + end; + +var + mark : ansichar; + chksum : byte; + i : byte; + l : cardinal; + ptr : PByte; + + x1 : array [0..1] of byte; + x2 : array [0..1] of byte; + + +begin + result := nil; + + l := Stream.Read( mark, 1); + + // ----------------------------------------------------- + // skip CR,LF + // ----------------------------------------------------- + while (l > 0) and (mark in [#10,#13]) do + l := Stream.Read(mark,1); + + if l = 0 then + exit; + + // ----------------------------------------------------- + // process record + // ----------------------------------------------------- + if mark = ':' then + begin + chksum := 0; + + // -------------------------------------------------- + // Allocate HexLine + // -------------------------------------------------- + result := THexLine.Create; + + // -------------------------------------------------- + // Length + // -------------------------------------------------- + Stream.Read(x1, 2); + inc(chksum, GetByte(x1)); + + result.RecLength := GetByte(x1); + result.Data := GetMemory(result.RecLength); + + // -------------------------------------------------- + // Offset + // -------------------------------------------------- + Stream.Read(x1, 2); + Stream.Read(x2, 2); + inc(chksum, GetByte(x1)); + inc(chksum, GetByte(x2)); + + result.Address := GetWord(x1,x2); + + // -------------------------------------------------- + // Record type + // -------------------------------------------------- + Stream.Read(x1, 2); + inc(chksum, GetByte(x1)); + + result.RecType := GetByte(x1); + + // -------------------------------------------------- + // Data + // -------------------------------------------------- + ptr := result.Data; + + for i:=0 to result.RecLength -1 do + begin + Stream.Read(x1,2); + inc(chksum, GetByte(x1)); + + ptr^ := GetByte(x1); + inc(ptr); + end; + + // -------------------------------------------------- + // Checksum + // -------------------------------------------------- + Stream.Read(x1,2); + inc(chksum, GetByte(x1)); + + // -------------------------------------------------- + // At that point the checksum must be 0!!! + // -------------------------------------------------- + if chksum <> 0 then + FreeAndNil(result); + end +end; + + + +// @@@: Property Handlers +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Property Handlers +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// Get Block Count +// ================================================================================================ +function THexFile.GetBlockCount: integer; +begin + result := fHexBlocks.Count +end; + +// ================================================================================================ +// Get Block +// ================================================================================================ +function THexFile.GetBlock(i: integer): THexBlock; +begin + if (i>=0) and (i= 31 then + begin + EEPROMWritePage(page,buf); + ZeroMemory(@buf,32); + + INC(page); + bidx := 0; + end + + else + INC(bidx) + end; + +var + cnt : word; + + + procedure SendBlock( const blk: THexBlock); + const + CHUNK = 1023; + + var + dptr : PByte; + + begin + left := blk.BlockLength; + addr := blk.Address; + dptr := blk.Data; + didx := 0; + + while left > 0 do + begin + if left > CHUNK then + begin + // push length of block + PushByte( HiByte(CHUNK)); + PushByte( LoByte(CHUNK)); + + // push load address of block + PushByte( HiByte(addr)); + PushByte( LoByte(addr)); + + cnt := CHUNK; + left := left - CHUNK; + addr := addr + CHUNK; + end + + else begin + // push length of block + PushByte( HiByte(left)); + PushByte( LoByte(left)); + + // push load address of block + PushByte( HiByte(addr)); + PushByte( LoByte(addr)); + + cnt := left; + left := 0; + end; + + // push data + while cnt > 0 do + begin + PushByte( dptr^); + INC(dptr); + + DEC(cnt); + end; + end; + end; + +var + blk: THexBlock; + +begin + hex := THexFile.Create; + hex.LoadFromStream(stream); + + // prepare counters + page := 0; + bidx := 8; + + // prepare first eeprom block. + // be careful with the first 8 bytes!!! + ZeroMemory( @buf, 32); + buf[0] := $c2; + buf[7] := $01; + + + // download blocks +// for i:=0 to hex.BlockCount -1 do +// SendBlock( hex.Blocks[i]); + + for blk in hex.Blocks do + SendBlock(blk); + + // download last block + PushByte( $80); + PushByte( $01); + PushByte( $E6); + PushByte( $00); + PushByte( $00); + + if bidx > 0 then + EEPROMWritePage(page, buf); + + hex.Free +end; + +// ================================================================================================ +// EEPROM Read +// ================================================================================================ +function TTrinity.EEPROMReadPage( page: word; var buffer): boolean; +var + pipe01 : TPipe; + pipe81 : TPipe; + + buf : TEEPROM; + len : cardinal; + +begin + if capEEPROM in fCaps then + begin + result := false; + + pipe01 := Pipes[$01]; + pipe81 := Pipes[$81]; + + if Assigned( pipe01) and Assigned( pipe81) then + begin + buf.header.command := EEPROM_RAW or EEPROM_READ; + buf.header.page := (LoByte(page) shl 8) + HiByte(page); + buf.header.offset := $00; + buf.header.length := $20; + + pipe01.Write( buf, sizeof(buf), len); + pipe81.Read( buf, sizeof(buf), len); + + CopyMemory(@buffer, @buf.data, 32); + end; + end + + else + raise EInvalidFunction.Create('EEPROM Read'); +end; + +// ================================================================================================ +// EEPROM Write +// ================================================================================================ +function TTrinity.EEPROMWritePage( page: word; const buffer): boolean; +var + pipe01 : TPipe; + pipe81 : TPipe; + + buf : TEEPROM; + len : cardinal; + +begin + if capEEPROM in fCaps then + begin + result := false; + pipe01 := Pipes[$01]; + pipe81 := Pipes[$81]; + + if Assigned( pipe01) and Assigned( pipe81) then + begin + buf.header.command := EEPROM_RAW or EEPROM_WRITE; + buf.header.page := (LoByte(page) shl 8) + HiByte(page); + buf.header.offset := $00; + buf.header.length := $20; + + CopyMemory(@buf.data, @buffer, 32); + + pipe01.Write( buf, sizeof(buf), len); + pipe81.Read( buf, sizeof(buf), len); + end; + end + + else + raise EInvalidFunction.Create('EEPROM Write'); +end; + +// ================================================================================================ +// I2C Read +// +// TODO: Must be executed in a thread. +// ================================================================================================ +{ +procedure TTrinity.I2CRead( addr: byte; var buffer; length: byte); +var + pipe01 : TPipe; + pipe81 : TPipe; + + buf : TEEPROM; + len : cardinal; + +begin + pipe01 := Pipes[$01]; + pipe81 := Pipes[$81]; + + if length >= 32 then + length := 32; + + if Assigned( pipe01) and Assigned( pipe81) then + begin + buf.header.command := DIR_IN + $20; + buf.header.page := 0; + buf.header.offset := addr; + buf.header.length := length; + + pipe01.Write( buf, sizeof(TEEPROM), len); + ZeroMemory( @buf, sizeof(TEEPROM)); + pipe81.Read( buf, sizeof(TEEPROM), len); + + CopyMemory(@buffer, @buf.data, length) + end +end; +} + +// ================================================================================================ +// I2C Write +// ================================================================================================ +{ +procedure TTrinity.I2CWrite(addr: byte; const buffer; length: byte); +var + pipe01 : TPipe; + pipe81 : TPipe; + + buf : TEEPROM; + len : cardinal; + +begin + pipe01 := Pipes[$01]; + pipe81 := Pipes[$81]; + + if length >= 32 then + length := 32; + + if Assigned( pipe01) and Assigned( pipe81) then + begin + buf.header.command := DIR_OUT + $20; + buf.header.page := 0; + buf.header.offset := addr; + buf.header.length := length; + + CopyMemory(@buf.data, @buffer, length); + + pipe01.Write( buf, sizeof(TEEPROM), len); + pipe81.Read( buf, sizeof(THeader), len); + end +end; +} + +initialization + RegisterDevice( $04b4, $8613, 0, TTrinity); // cypress vid/pid + RegisterDevice( $16d0, $0712, 0, TTrinity); // trinity vid/pid + +end. diff --git a/src.devmgr/dev/usb/trinity/mr.trinity.pipe0.pas b/src.devmgr/dev/usb/trinity/mr.trinity.pipe0.pas new file mode 100644 index 0000000..cc0c851 --- /dev/null +++ b/src.devmgr/dev/usb/trinity/mr.trinity.pipe0.pas @@ -0,0 +1,135 @@ +unit mr.trinity.pipe0; + +interface +uses + Classes, + mr.dev.usb.pipe0; + +type + TTrinityPipe0 = class( TPipe0) + public + procedure DownloadFirmware( Filename : string); overload; virtual; + procedure DownloadFirmware( Stm : TStream); overload; virtual; + end; + + +implementation +uses + SysUtils, + mr.trinity.hex, + mr.drv.usb.types, + mr.drv.usb; + +{ TTrinityPipe0 } + +// ================================================================================================ +// Download Firmware (file) +// ================================================================================================ +procedure TTrinityPipe0.DownloadFirmware(Filename: string); +var + stm : TMemoryStream; + +begin + if FileExists(Filename) then + begin + stm := TMemoryStream.Create; + stm.LoadFromFile(Filename); + DownloadFirmware(stm); + stm.Free + end +end; + +// ================================================================================================ +// Download Firmware (stream) +// ================================================================================================ +procedure TTrinityPipe0.DownloadFirmware(Stm: TStream); +var + len : cardinal; + b0 : byte; + b1 : byte; + + addr : word; + left : word; + ptr : PByte; + + hex : THexFile; + blk : THexBlock; + sud : TUsbSetupPacket; + + +begin + hex := THexFile.Create; + hex.LoadFromStream(stm); + + hex.Dump(nil); + + if Assigned( fDriver) then + begin + b0 := 0; + b1 := 1; + + // ------------------------------------------------------------ + // Reset 8051 + // ------------------------------------------------------------ + sud.RequestType := $40; + sud.Request := $A0; + sud.Value := $E600; + sud.Index := $0000; + sud.Length := $0000; + + fDriver.ControlTransfer(sud, @b1, 1, len, nil); + + // ------------------------------------------------------------ + // Download firmware in 4 kB chunks + // ------------------------------------------------------------ +// for i:=0 to hex.BlockCount -1 do + for blk in hex.Blocks do + begin +// blk := hex.Blocks[i]; + addr := blk.Address; + left := blk.BlockLength; + ptr := blk.Data; + + while left > 0 do + begin + sud.RequestType:= $40; + sud.Request := $A0; + + if left > 4096 then + begin + sud.Value := addr; + sud.Index := $0000; + sud.Length := 4096; + + fDriver.ControlTransfer( sud, ptr, 4096, len, nil); + + addr := addr +4096; + ptr := pointer( cardinal(ptr) +4096); + left := left -4096 + end + + else begin + sud.Value := addr; + sud.Index := $0000; + sud.Length := left; + + fDriver.ControlTransfer( sud, ptr, left, len, nil); + left := 0 + end + end + end; + + // ------------------------------------------------------------ + // Restart 8051 + // ------------------------------------------------------------ + sud.RequestType := $40; + sud.Request := $A0; + sud.Value := $E600; + sud.Index := $0000; + sud.Length := $0000; + + fDriver.ControlTransfer(sud, @b0, 1, len, nil) + end +end; + +end. diff --git a/src.devmgr/dev/usb/trinity/mr.trinity.types.pas b/src.devmgr/dev/usb/trinity/mr.trinity.types.pas new file mode 100644 index 0000000..79e13a9 --- /dev/null +++ b/src.devmgr/dev/usb/trinity/mr.trinity.types.pas @@ -0,0 +1,107 @@ +unit mr.trinity.types; + +interface +uses + System.Classes, + System.SysUtils; + +type + EInvalidFunction = Exception; + + TCapability = + ( + capSER, + capCFG, // CFG + capIIC, // IIC + capRAM, // SRAM + capEEPROM, // EPR + capDSO, // DSO + capDSO2, // DS2 + capREFLOW, // RFL + capLAMINATOR, // LAM + capLED, // LED + capJTAG, // JTG + capJTAG2, // JT2 + capJTAG3, // JT3 + capLCD, // LCD //44780 + capLCD2, // LC2 //7565 + capLA // LA + ); + + TCapabilities = set of TCapability; + +function Caps2Int64( caps: TCapabilities): Int64; +function Caps2String( caps: TCapabilities): string; + +type + ITrinity = interface + ['{2CDBFA80-893B-41E9-A5C8-C02B7ED3D949}'] + + procedure Open; + procedure Close; + + procedure DownloadFirmware( Filename : string); overload; + procedure DownloadFirmware( Stream : TStream); overload; + + procedure DownloadFirmwarePerm( Filename : string); overload; + procedure DownloadFirmwarePerm( Stream : TStream); overload; + +// procedure I2CRead( addr: byte; var buffer; length: byte); +// procedure I2CWrite( addr: byte; const buffer; length: byte); + + function EEPROMReadPage( page: word; var buffer): boolean; + function EEPROMWritePage( page: word; const buffer): boolean; + + function SerialNumber : string; + function Capabilities : TCapabilities; + + end; + +implementation +uses + mr.trinity.consts; + +function Caps2Int64( caps: TCapabilities): Int64; +begin + result := 0; + + if capIIC in caps then result := result or bmCap0_I2C; + if capSER in caps then result := result or bmCap0_SER; + if capEEPROM in caps then result := result or bmCap0_EPR; + if capRAM in caps then result := result or bmCap0_RAM; + if capJTAG in caps then result := result or bmCap0_JTG; + + if capLED in caps then result := result or (bmCap1_LED shl 8); + if capLCD in caps then result := result or (bmCap1_LCD shl 8); +end; + +function Caps2String( caps: TCapabilities): string; +var + cap : TCapability; + +begin + result := ''; + + for cap in [ Low(TCapability) .. High(TCapability)] do + if cap in caps then + begin + if result <> '' then + result := result +','; + + case cap of + capSER : result := result +'SER'; + capCFG : result := result +'CFG'; + capIIC : result := result +'I2C'; + capRAM : result := result +'RAM'; + capEEPROM: result := result +'EEPROM'; + capJTAG : result := result +'JTG'; + capLCD : result := result +'LCD'; + capLCD2 : result := result +'LCD2'; + end; + + end; + + +end; + +end. diff --git a/src.devmgr/dev/usb/trinity/mr.trinity.utils.pas b/src.devmgr/dev/usb/trinity/mr.trinity.utils.pas new file mode 100644 index 0000000..2a39354 --- /dev/null +++ b/src.devmgr/dev/usb/trinity/mr.trinity.utils.pas @@ -0,0 +1,39 @@ +unit mr.trinity.utils; + +interface +uses + mr.trinity.consts, + mr.trinity.types; + +function DecodeCapabilities( caps: Int64 ): TCapabilities; +function EncodeCapabilities( caps: TCapabilities): Int64; + +implementation + +// ================================================================================================ +// EncodeCapabilities +// ================================================================================================ +function EncodeCapabilities( caps: TCapabilities): Int64; +begin + result := 0; + + if capJTAG in caps then result := result or bmCap0_JTG; +end; + +// ================================================================================================ +// DecodeCapabilities +// ================================================================================================ +function DecodeCapabilities( caps: Int64): TCapabilities; +begin + result := []; + + if( caps and bmCap0_I2C ) <> 0 then Include( result, capIIC ); + if( caps and bmCap0_SER ) <> 0 then Include( result, capSER ); + if( caps and bmCap0_EPR ) <> 0 then Include( result, capEEPROM ); + if( caps and bmCap0_RAM ) <> 0 then Include( result, capRAM ); + if( caps and bmCap0_JTG ) <> 0 then Include( result, capJTAG ); + + if( caps and bmCap1_LCD ) <> 0 then Include( result, capLCD ); +end; + +end. diff --git a/src.devmgr/drv/mr.drv.pas b/src.devmgr/drv/mr.drv.pas new file mode 100644 index 0000000..370f617 --- /dev/null +++ b/src.devmgr/drv/mr.drv.pas @@ -0,0 +1,24 @@ +unit mr.drv; + +interface + +type + TDriver = class abstract( TInterfacedObject) + protected + fDeviceHandle : THandle; + fDevicePath : string; + + public + procedure Open; virtual; abstract; + procedure Close; virtual; abstract; + + public + property DevicePath : string read fDevicePath; + property DeviceHandle : THandle read fDeviceHandle; + end; + + TDriverClass = class of TDriver; + +implementation + +end. diff --git a/src.devmgr/drv/mr.drv.types.pas b/src.devmgr/drv/mr.drv.types.pas new file mode 100644 index 0000000..e735c82 --- /dev/null +++ b/src.devmgr/drv/mr.drv.types.pas @@ -0,0 +1,13 @@ +unit mr.drv.types; + +interface + +type + IUsbDriver = interface + + end; + + +implementation + +end. diff --git a/src.devmgr/drv/mr.drv.usb.types.pas b/src.devmgr/drv/mr.drv.usb.types.pas new file mode 100644 index 0000000..2c6783f --- /dev/null +++ b/src.devmgr/drv/mr.drv.usb.types.pas @@ -0,0 +1,152 @@ +unit mr.drv.usb.types; + +interface + +const + // Standard request codes (btw not used) + CTRL_GET_STATUS = 0; + CTRL_CLEAR_FEATURE = 1; + CTRL_SET_FEATURE = 3; + CTRL_SET_ADDRESS = 5; + CTRL_GET_DESCRIPTOR = 6; + CTRL_SET_DESCRIPTOR = 7; + CTRL_GET_CONFIGURATION = 8; + CTRL_SET_CONFIGURATION = 9; + CTRL_GET_INTERFACE = 10; + CTRL_SET_INTERFACE = 11; + + // Descriptor types + DSCR_DEVICE = 1; + DSCR_CONFIGURATION = 2; + DSCR_STRING = 3; + DSCR_INTERFACE = 4; + DSCR_ENDPOINT = 5; + DSCR_DEVICE_QUALIFIER = 6; + DSCR_OTHER_SPEED_CONF = 7; + DSCR_INTERFACE_POWER = 8; + + +type + // ----------------------------------------------------------------------------------- + // USB Device Descriptor + // ----------------------------------------------------------------------------------- + PUsbDeviceDescriptor = ^TUsbDeviceDescriptor; + TUsbDeviceDescriptor = packed record + Length : byte; // UCHAR bLength + DescriptorType : byte; // UCHAR bDescriptorType + bcdUSB : word; // USHORT bcdUSB + DeviceClass : byte; // UCHAR bDeviceClass + DeviceSubClass : byte; // UCHAR bDeviceSubClass + DeviceProtocol : byte; // UCHAR bDeviceProtocol + MaxPacketSize0 : byte; // UCHAR bMaxOacketSize0 + VendorID : word; // USHORT idVendor + ProductID : word; // USHORT idProduct + DeviceID : word; // USHORT bcdDevice + Manufacturer : byte; // UCHAR iManufacturer + Product : byte; // UCHAR iProduct + SerialNumber : byte; // UCHAR iSerialNumber + ConfigurationCount : byte; // UCHAR bNumConfigurations + end; + + // ----------------------------------------------------------------------------------- + // USB Configuration Descriptor + // ----------------------------------------------------------------------------------- + PUsbConfigurationDescriptor = ^TUsbConfigurationDescriptor; + TUsbConfigurationDescriptor = packed record + Length : byte; // UCHAR bLength + DescriptorType : byte; // UCHAR bDescriptorType + TotalLength : word; // USHORT wTotalLength + InterfaceCount : byte; // UCHAR bNumInterfaces + ConfigurationNumber : byte; // UCHAR Configuration Number + ConfigurationString : byte; // UCHAR Configuration String + Attributes : byte; // UCHAR bmAttributes + MaxPower : byte; // UCHAR MaxPower + end; + + // ----------------------------------------------------------------------------------- + // USB Interface Descriptor + // ----------------------------------------------------------------------------------- + PUsbAlternateSettingDescriptor = ^TUsbAlternateSettingDescriptor; + TUsbAlternateSettingDescriptor = packed record + Length : byte; // UCHAR bLength + DescriptorType : byte; // UCHAR bDescriptorType + InterfaceNumber : byte; // UCHAR bInterfaceNumber + AlternateSetting : byte; // UCHAR bAlternateSetting + EndpointCount : byte; // UCHAR bNumEndPoints + InterfaceClass : byte; // UCHAR bInterfaceClass + InterfaceSubClass : byte; // UCHAR bInterfaceSubClass + InterfaceProtocol : byte; // UCHAR bInterfaceProtocol + InterfaceIndex : byte; // UCHAR iInterface + end; + + // ----------------------------------------------------------------------------------- + // USB Endpoint Descriptor + // ----------------------------------------------------------------------------------- + PUsbEndpointDescriptor = ^TUsbEndpointDescriptor; + TUsbEndpointDescriptor = packed record + Length : byte; // UCHAR bLength + DescriptorType : byte; // UCHAR bDescriptorType + EndpointAddress : byte; // UCHAR bEndpointAddress + Attributes : byte; // UCHAR bmAttributes + MaxPacketSize : word; // USHORT wMaxPacketSize + Interval : byte; // UCHAR bInterval + end; + + // ----------------------------------------------------------------------------------- + // USB String Descriptor + // ----------------------------------------------------------------------------------- + PUsbStringDescriptor = ^TUsbStringDescriptor; + TUsbStringDescriptor = packed record + Length : byte; // UCHAR bLength + DescriptorType : byte; // UCHAR bDescriptorType + Str : array of WideChar; // WCHAR String[1] + end; + + // ----------------------------------------------------------------------------------- + // USB Transfer Size Info + // ----------------------------------------------------------------------------------- + PusbTransferSizeInfo = ^TusbTransferSizeInfo; + TusbTransferSizeInfo = packed record + EndpointAddress : byte; + TransferSize : cardinal; + end; + + {$Z4} + TUsbDeviceSpeed = (LowSpeed, FullSpeed, HighSpeed); + TUsbPipeType = (ptControl, ptIsochronous, ptBulk, ptInterrupt); + {$Z1} + + // Ez nekem nem teljesen vilagos itt. usb.h ??? + PUsbPipeInformation = ^TUsbPipeInformation; + TUsbPipeInformation = record + PipeType : TUsbPipeType; + PipeId : byte; + MaxPacketSize : word; + Interval : byte; + end; + + PUsbSetupPacket = ^TUsbSetupPacket; + TUsbSetupPacket = packed record + RequestType : byte; + case Request : byte of + 0: ( + Value : word; + Index : word; + Length : word; + ); + + 1: ( + SetupDat : array [2..7] of byte; + ); + end; + + +type + IUsbDriver = interface + + end; + + +implementation + +end. diff --git a/src.devmgr/drv/usb/mr.drv.usb.pas b/src.devmgr/drv/usb/mr.drv.usb.pas new file mode 100644 index 0000000..c7089be --- /dev/null +++ b/src.devmgr/drv/usb/mr.drv.usb.pas @@ -0,0 +1,258 @@ +unit mr.drv.usb; + +interface +uses + WinApi.Windows, + System.Classes, + spring.Collections, + spring.Collections.Lists, + mr.drv.usb.types, + mr.drv; + + +type + TUsbDriver = class; + TUsbDriverClass= class of TUsbDriver; + + TScanCallback = reference to procedure( DevicePath: string); + + + TUsbDeviceInfo = class + private + fDriverClass : TUsbDriverClass; + fDevicePath : string; + fVendorID : word; + fProductID : word; + fLocation : string; + fDescription : string; + + public + property DriverClass : TUsbDriverClass read fDriverClass; + property DevicePath : string read fDevicePath; + property Location : string read fLocation; + property Description : string read fDescription; + property VendorID : word read fVendorID; + property ProductID : word read fProductID; + + public + constructor Create( DevicePath: string; DriverClass: TUsbDriverClass); + destructor Destroy; override; + end; + + IUsbDriverMap = IDictionary; + + + + + TAnsiStringList = TList; + TList = spring.Collections.IList; + + + TUsbDriver = class abstract(TDriver, IUsbDriver) + public + 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 + fVendorID : word; + fProductID : word; + fLocation : string; + fDescription : string; + fDeviceSpeed : TusbDeviceSpeed; + + fDeviceDescriptor : TUsbDeviceDescriptor; + + public + function GetDescriptor( DescriptorType : byte; + Index : byte; + LanguageID : word; + Buffer : pointer; + BufferLength : cardinal; + var Transferred : cardinal) : boolean; virtual; abstract; + + function GetAssociatedInterface( InterfaceIndex : byte; + var InterfaceHandle) : boolean; virtual; abstract; + + function QueryInterfaceSettings( AlternateSettingNumber : byte; + var AlternateSettingDescriptor : TUsbAlternateSettingDescriptor): boolean; virtual; abstract; + + function QueryPipe( AlternateInterfaceNumber : byte; + PipeIndex : byte; + var PipeInformation : TusbPipeInformation): boolean; virtual; abstract; + + + function ControlTransfer( SetupPacket : TUsbSetupPacket; + Buffer : pointer; + BufferLength : cardinal; + var Transferred : cardinal; + Overlapped : POverlapped = nil): boolean; virtual; abstract; + + function AbortPipe( PipeID : byte): boolean; virtual; abstract; + function FlushPipe( PipeID : byte): boolean; virtual; abstract; + function ResetPipe( PipeID : byte): boolean; virtual; abstract; + + function ReadPipe( PipeID : byte; + Buffer : pointer; + BufferLength : cardinal; + var Transferred : cardinal; + Overlapped : POverlapped = nil): boolean; virtual; abstract; + + function WritePipe( PipeID : byte; + Buffer : pointer; + BufferLength : cardinal; + var Transferred : cardinal; + Overlapped : POverlapped = nil): boolean; virtual; abstract; + + function GetOverlappedResult( Overlapped : POverlapped; + var Transferred : cardinal; + Wait : boolean): boolean; virtual; abstract; + + + + public + constructor Create( DevicePath: string); + + public + property VendorID : word read fVendorID; + property ProductID : word read fProductID; + property Location : string read fLocation; + property Description : string read fDescription; + property DeviceSpeed : TusbDeviceSpeed read fDeviceSpeed; + end; + +// TUsbDriverClass = class of TUsbDriver; + + + + + +implementation +uses + mr.dev.usb, + System.SysUtils; + +{ TUsbDriver } + +// @@@: Construction / destruction ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Construction / destruction +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// Create +// ================================================================================================ +constructor TUsbDriver.Create( DevicePath: string); +begin + fDeviceHandle := INVALID_HANDLE_VALUE; + fDevicePath := DevicePath; + fDeviceSpeed := LowSpeed; + + ParseInstanceId( fDevicePath, fVendorID, fProductID, fLocation, fDescription); +end; + +// @@@: INTERNALS +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// INTERNALS +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// 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 } + +// @@@: construction / destruction ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// construction / destruction +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// ================================================================================================ +// constructor +// ================================================================================================ +constructor TUsbDeviceInfo.Create(DevicePath: string; DriverClass: TUsbDriverClass); +begin + fDevicePath := DevicePath; + fDriverClass := DriverClass; + + DriverClass.ParseInstanceId( fDevicePath, fVendorID, fProductID, fLocation, fDescription) +end; + +// ================================================================================================ +// destructor +// ================================================================================================ +destructor TUsbDeviceInfo.Destroy; +begin + inherited; +end; + +end. diff --git a/src.devmgr/drv/usb/mr.drv.usb.types.pas b/src.devmgr/drv/usb/mr.drv.usb.types.pas new file mode 100644 index 0000000..d3a13db --- /dev/null +++ b/src.devmgr/drv/usb/mr.drv.usb.types.pas @@ -0,0 +1,210 @@ +unit mr.drv.usb.types; + +interface +uses + WinApi.Windows; + +const + // Standard request codes (btw not used) + CTRL_GET_STATUS = 0; + CTRL_CLEAR_FEATURE = 1; + CTRL_SET_FEATURE = 3; + CTRL_SET_ADDRESS = 5; + CTRL_GET_DESCRIPTOR = 6; + CTRL_SET_DESCRIPTOR = 7; + CTRL_GET_CONFIGURATION = 8; + CTRL_SET_CONFIGURATION = 9; + CTRL_GET_INTERFACE = 10; + CTRL_SET_INTERFACE = 11; + + // Descriptor types + DSCR_DEVICE = 1; + DSCR_CONFIGURATION = 2; + DSCR_STRING = 3; + DSCR_INTERFACE = 4; + DSCR_ENDPOINT = 5; + DSCR_DEVICE_QUALIFIER = 6; + DSCR_OTHER_SPEED_CONF = 7; + DSCR_INTERFACE_POWER = 8; + + +type + // ----------------------------------------------------------------------------------- + // USB Device Descriptor + // ----------------------------------------------------------------------------------- + PUsbDeviceDescriptor = ^TUsbDeviceDescriptor; + TUsbDeviceDescriptor = packed record + Length : byte; // UCHAR bLength + DescriptorType : byte; // UCHAR bDescriptorType + bcdUSB : word; // USHORT bcdUSB + DeviceClass : byte; // UCHAR bDeviceClass + DeviceSubClass : byte; // UCHAR bDeviceSubClass + DeviceProtocol : byte; // UCHAR bDeviceProtocol + MaxPacketSize0 : byte; // UCHAR bMaxOacketSize0 + VendorID : word; // USHORT idVendor + ProductID : word; // USHORT idProduct + DeviceID : word; // USHORT bcdDevice + Manufacturer : byte; // UCHAR iManufacturer + Product : byte; // UCHAR iProduct + SerialNumber : byte; // UCHAR iSerialNumber + ConfigurationCount : byte; // UCHAR bNumConfigurations + end; + + // ----------------------------------------------------------------------------------- + // USB Configuration Descriptor + // ----------------------------------------------------------------------------------- + PUsbConfigurationDescriptor = ^TUsbConfigurationDescriptor; + TUsbConfigurationDescriptor = packed record + Length : byte; // UCHAR bLength + DescriptorType : byte; // UCHAR bDescriptorType + TotalLength : word; // USHORT wTotalLength + InterfaceCount : byte; // UCHAR bNumInterfaces + ConfigurationNumber : byte; // UCHAR Configuration Number + ConfigurationString : byte; // UCHAR Configuration String + Attributes : byte; // UCHAR bmAttributes + MaxPower : byte; // UCHAR MaxPower + end; + + // ----------------------------------------------------------------------------------- + // USB Interface Descriptor + // ----------------------------------------------------------------------------------- + PUsbAlternateSettingDescriptor = ^TUsbAlternateSettingDescriptor; + TUsbAlternateSettingDescriptor = packed record + Length : byte; // UCHAR bLength + DescriptorType : byte; // UCHAR bDescriptorType + InterfaceNumber : byte; // UCHAR bInterfaceNumber + AlternateSetting : byte; // UCHAR bAlternateSetting + EndpointCount : byte; // UCHAR bNumEndPoints + InterfaceClass : byte; // UCHAR bInterfaceClass + InterfaceSubClass : byte; // UCHAR bInterfaceSubClass + InterfaceProtocol : byte; // UCHAR bInterfaceProtocol + InterfaceIndex : byte; // UCHAR iInterface + end; + + // ----------------------------------------------------------------------------------- + // USB Endpoint Descriptor + // ----------------------------------------------------------------------------------- + PUsbEndpointDescriptor = ^TUsbEndpointDescriptor; + TUsbEndpointDescriptor = packed record + Length : byte; // UCHAR bLength + DescriptorType : byte; // UCHAR bDescriptorType + EndpointAddress : byte; // UCHAR bEndpointAddress + Attributes : byte; // UCHAR bmAttributes + MaxPacketSize : word; // USHORT wMaxPacketSize + Interval : byte; // UCHAR bInterval + end; + + // ----------------------------------------------------------------------------------- + // USB String Descriptor + // ----------------------------------------------------------------------------------- + PUsbStringDescriptor = ^TUsbStringDescriptor; + TUsbStringDescriptor = packed record + Length : byte; // UCHAR bLength + DescriptorType : byte; // UCHAR bDescriptorType + Str : array of WideChar; // WCHAR String[1] + end; + + // ----------------------------------------------------------------------------------- + // USB Transfer Size Info + // ----------------------------------------------------------------------------------- + PusbTransferSizeInfo = ^TusbTransferSizeInfo; + TusbTransferSizeInfo = packed record + EndpointAddress : byte; + TransferSize : cardinal; + end; + + {$Z4} + TUsbDeviceSpeed = (LowSpeed, FullSpeed, HighSpeed); + TUsbPipeType = (ptControl, ptIsochronous, ptBulk, ptInterrupt); + {$Z1} + + // Ez nekem nem teljesen vilagos itt. usb.h ??? + PUsbPipeInformation = ^TUsbPipeInformation; + TUsbPipeInformation = record + PipeType : TUsbPipeType; + PipeId : byte; + MaxPacketSize : word; + Interval : byte; + end; + + PUsbSetupPacket = ^TUsbSetupPacket; + TUsbSetupPacket = packed record + RequestType : byte; + case Request : byte of + 0: ( + Value : word; + Index : word; + Length : word; + ); + + 1: ( + SetupDat : array [2..7] of byte; + ); + end; + + +type + IUsbDriver = interface + ['{786E9A46-F7FE-4A8C-8BB8-563AB8C51BD5}'] + function GetDescriptor( DescriptorType : byte; + Index : byte; + LanguageID : word; + Buffer : pointer; + BufferLength : cardinal; + var Transferred : cardinal) : boolean; + + function GetAssociatedInterface( InterfaceIndex : byte; + var InterfaceHandle) : boolean; + + function QueryInterfaceSettings( AlternateSettingNumber : byte; + var AlternateSettingDescriptor : TUsbAlternateSettingDescriptor): boolean; + + function QueryPipe( AlternateInterfaceNumber : byte; + PipeIndex : byte; + var PipeInformation : TusbPipeInformation): boolean; + + + function ControlTransfer( SetupPacket : TUsbSetupPacket; + Buffer : pointer; + BufferLength : cardinal; + var Transferred : cardinal; + Overlapped : POverlapped = nil): boolean; + + function AbortPipe( PipeID : byte): boolean; + function FlushPipe( PipeID : byte): boolean; + function ResetPipe( PipeID : byte): boolean; + + function ReadPipe( PipeID : byte; + Buffer : pointer; + BufferLength : cardinal; + var Transferred : cardinal; + Overlapped : POverlapped = nil): boolean; + + function WritePipe( PipeID : byte; + Buffer : pointer; + BufferLength : cardinal; + var Transferred : cardinal; + Overlapped : POverlapped = nil): boolean; + + function GetOverlappedResult( Overlapped : POverlapped; + var Transferred : cardinal; + Wait : boolean): boolean; + +// function GetVendorID : word; +// function GetProductID : word; +// function GetLocation : string; +// function GetDescription : string; +// function GetDeviceSpeed : TDsbDeviceSpeed; +// +// +// property VendorID : word read GetVendorID; +// property ProductID : word read GetProductID; +// property Location : string read GetLocation; +// property Description : string read GetDescription; +// property DeviceSpeed : TusbDeviceSpeed read GetDeviceSpeed; + end; + + +implementation + +end. diff --git a/src.devmgr/drv/usb/mr.drv.usb.winusb.pas b/src.devmgr/drv/usb/mr.drv.usb.winusb.pas new file mode 100644 index 0000000..9598d51 --- /dev/null +++ b/src.devmgr/drv/usb/mr.drv.usb.winusb.pas @@ -0,0 +1,650 @@ +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; + inherited; +end; + +// ================================================================================================ +// Open +// +// Note: +// 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} +// ================================================================================================ +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+'#'+GuidToString(fDriverID); + + // --------------------------------------------------------------- + // 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 + dsc := CreateComObject( CLSID_FunctionDiscovery) as IFunctionDiscovery; + + try + 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 + props.GetValue( PKEY_Device_InstanceId, propv); + s := propv.pwszVal; + + props.GetValue( PKEY_Device_DeviceDesc, propv); + s := s +'#'+ propv.pwszVal; + + ScanCallback( s); + +// if Map.ContainsKey( s) then +// Map.Remove( s); +// +// Map.Add( s, TUsbDeviceInfo.Create(s, self)) + 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. diff --git a/src.devmgr/mr.dev.manager.pas b/src.devmgr/mr.dev.manager.pas new file mode 100644 index 0000000..fe0c0ba --- /dev/null +++ b/src.devmgr/mr.dev.manager.pas @@ -0,0 +1,497 @@ +// Device manager uses WinUSB driver by default!!! + +unit mr.dev.manager; + +interface +uses +// Vcl.Dialogs, + System.Classes, + mr.drv.usb, + mr.dev.usb; +// dev.usb.trinity.types; + +type + GetDeviceListCallback = reference to function( VendorID : word; + ProductID : word; + Description : string; + Location : string; + DevicePath : string): boolean; + +procedure RegisterDriver( DriverClass : TUsbDriverClass); +// +procedure RegisterDevice( VendorID : word; + ProductID : word; + Capabilities: int64; + DeviceClass : TUsbDeviceClass); +// +function AllocateDevice( DevicePath : string): TUsbDevice; +// Capabilities: TCapabilities = []; +// IgnoreCap : boolean = false): TUsbDevice; +// +//function AllocateDeviceBySN( SerialNumber: AnsiString; +// Capabilities: TCapabilities = []; +// IgnoreCap : boolean = false): TUsbDevice; +// +procedure DeallocateDevice( var Device : TUsbDevice); +// +procedure GetDeviceList( Callback : GetDeviceListCallback; + VendorID : word = 0; + ProductID : word = 0); + + +implementation +uses + system.SysUtils, + spring.Collections; + +procedure ParseInstanceId( InstanceId : string; + var VendorID : word; + var ProductID : word; + var Location : string; + var Description : string); forward; + + + +// SysUtils, +// Generics.Collections, +// drv.usb.winusb, +// dev.usb.trinity, +// dev.usb.trinity.utils; +// +//type +// +//type +// TUsbDriverMap = TDictionary ; +// TUsbDeviceMap = TObjectDictionary; +// +//var +// UsbDriverAlloc : TUsbDriverMap = nil; +// UsbDriverMap : TUsbDriverMap = nil; +// UsbDeviceMap : TUsbDeviceMap = nil; +// +// + +type + TUsbDeviceSetup = class + strict protected + fDriverClass : TUsbDriverClass; + fDeviceClass : TUsbDeviceClass; + + fVendorID : word; + fProductID : word; + fDescription : string; + + public + property DriverClass : TUsbDriverClass read fDriverClass write fDriverClass; + property DeviceClass : TUsbDeviceClass read fDeviceClass write fDeviceClass; + property VendorID : word read fVendorID write fVendorID; + property ProductID : word read fProductID write fProductID; + property Description : string read fDescription write fDescription; + end; + + TUsbDeviceDescriptor = class + strict protected + fDeviceSetup : TUsbDeviceSetup; + fDevicePath : string; + fLocation : string; + fAllocated : boolean; + + strict protected + function GetDriverClass : TUsbDriverClass; + function GetDeviceClass : TUsbDeviceClass; + function GetDescription : string; + function GetVendorID : word; + function GetProductID : word; + + public + constructor Create( DevicePath: string); reintroduce; + destructor Destroy; override; + + public + property Allocated : boolean read fAllocated write fAllocated; + property DeviceSetup : TUsbDeviceSetup read fDeviceSetup write fDeviceSetup; + property DevicePath : string read fDevicePath; + property Location : string read fLocation; + + property VendorID : word read GetVendorId; + property ProductID : word read GetProductID; + property Description : string read GetDescription; + end; + +var + UsbDeviceSetups : IDictionary< cardinal, TUsbDeviceSetup>; + UsbDevices : IDictionary< string, TUsbDeviceDescriptor>; + +// ================================================================================================ +// Register Driver +// ================================================================================================ +procedure RegisterDriver( DriverClass: TUsbDriverClass); +var + vid: word; + pid: word; + loc: string; + dsc: string; + key: cardinal; + + uds: TUsbDeviceSetup; + udd: TUsbDeviceDescriptor; + +begin + if UsbDevices = nil then + UsbDevices := tCollections.CreateDictionary< string, TUsbDeviceDescriptor>([doOwnsValues]); + + if UsbDeviceSetups = nil then + UsbDeviceSetups := TCollections.CreateDictionary< cardinal, TUsbDeviceSetup>([doOwnsValues]); + + DriverClass.Scan( procedure( DevicePath: string) + begin + DriverClass.ParseInstanceId( DevicePath, vid, pid, loc, dsc); + key := (vid shl 16) + pid; + + // -------------------------------------------------------------- + // add or update (override) an usb device setup entry + // -------------------------------------------------------------- + if not UsbDeviceSetups.TryGetValue( key, uds) then + begin + uds := TUsbDeviceSetup.Create; + uds.VendorID := vid; + uds.ProductID := pid; + + UsbDeviceSetups.Add( key, uds) + end; + + uds.DriverClass := DriverClass; + uds.Description := dsc; + + // -------------------------------------------------------------- + // add or update (override) an usb device entry + // -------------------------------------------------------------- + if not UsbDevices.TryGetValue( DevicePath, udd) then + begin + udd := TUsbDeviceDescriptor.Create( DevicePath); + UsbDevices.Add(DevicePath, udd) + end; + + udd.DeviceSetup := uds + end) +end; + +// ================================================================================================ +// Register Device +// ================================================================================================ +procedure RegisterDevice( VendorID : word; + ProductID : word; + Capabilities: int64; + DeviceClass : TUsbDeviceClass); +var + key: cardinal; + uds: TUsbDeviceSetup; + +begin + if UsbDeviceSetups = nil then + UsbDeviceSetups := TCollections.CreateDictionary< cardinal, TUsbDeviceSetup>([doOwnsValues]); + + key := (VendorID shl 16) + ProductID; + + if not UsbDeviceSetups.TryGetValue( key, uds) then + begin + uds := TUsbDeviceSetup.Create; + uds.VendorID := VendorID; + uds.ProductID := ProductID; + + UsbDeviceSetups.Add( key, uds); + end; + + uds.DeviceClass := DeviceClass; +end; + +// ================================================================================================ +// Get Device List +// ================================================================================================ +procedure GetDeviceList( Callback : GetDeviceListCallback; + VendorID : word = 0; + ProductID : word = 0); +begin + for var udd in UsbDevices.Values do + 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; + +// ================================================================================================ +// Allocate Device +// ================================================================================================ +function AllocateDevice( DevicePath: string): TUsbDevice; +var + udd: TUsbDeviceDescriptor; + +begin + result := nil; + + 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; + +// ================================================================================================ +// Deallocate Device +// ================================================================================================ +procedure DeallocateDevice( var Device: TUsbDevice); +var + udd: TUsbDeviceDescriptor; + +begin + if Assigned(Device) then + begin + if UsbDevices.TryGetValue( Device.DevicePath, udd) then + udd.Allocated := false; + +// FreeAndNil( Device) + end +end; + + +//// ================================================================================================ +//// allocate device by serial number +//// ================================================================================================ +//function AllocateDeviceBySN( SerialNumber: AnsiString; +// Capabilities: TCapabilities = []; +// IgnoreCap : boolean = false): TUsbDevice; +//var +// vid : word; +// pid : word; +// loc : string; +// dsc : string; +// +// drv : TUsbDriver; +// drvc : TUsbDriverClass; +// +// dev : TUsbDevice; +// devc : TUsbDeviceClass; +// +// tri : TTrinity; +// inf : TUsbDeviceInfo; +// cap : TCapabilities; +// sn : AnsiString; +// +// path : AnsiString; +// +//begin +// result := nil; +// +// if Assigned( UsbDriverMap) and Assigned(UsbDeviceMap) then +// begin +// for path in UsbDriverMap.Keys do +// begin +// ParseInstanceID( path, vid, pid, loc, dsc); +// +// drvc := UsbDriverMap.Items[path]; +// devc := nil; +// cap := []; +// +// if (vid = $16d0) and (pid = $0712) then +// begin +// try +// drv := drvc.Create(path); +// tri := TTrinity.Create(drv); +// +// tri.Open; +// cap := tri.Capabilities; +// sn := tri.SerialNumber; +// tri.Close; +// +// tri.Free; +// +// except +// +// end; +// end; +// +// for inf in UsbDeviceMap.Values do +// if (inf.VendorID = vid) and (inf.ProductID = pid) then +// if (inf.Capabilities * cap = cap) or IgnoreCap then +// begin +// if sn = SerialNumber then +// begin +// devc := inf.DeviceClass; +// break; +// end; +// end; +// +// if Assigned(devc) then +// begin +// drv := drvc.Create(path); +// dev := devc.Create(drv); +// +// if not Assigned( UsbDriverAlloc) then +// UsbDriverAlloc := TUsbDriverMap.Create; +// +// UsbDriverAlloc.Add( path, drvc); +// UsbDriverMap.Remove(path); +// +// result:= dev; +// end; +// end +// end +//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 } + + + +// @@@: UsbDeviceDescriptor +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// UsbDeviceDescriptor +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// ================================================================================================ +// constructor +// ================================================================================================ +constructor TUsbDeviceDescriptor.Create(DevicePath: string); +var + vid: word; + pid: word; + dsc: string; + +begin + inherited Create; + + fAllocated := false; + fDevicePath := DevicePath; + + ParseInstanceId( fDevicePath, vid, pid, fLocation, dsc) +end; + +// ================================================================================================ +// destructor +// ================================================================================================ +destructor TUsbDeviceDescriptor.Destroy; +begin + inherited; +end; + +// ================================================================================================ +// get driver class +// ================================================================================================ +function TUsbDeviceDescriptor.GetDriverClass: TUsbDriverClass; +begin + result := fDeviceSetup.DriverClass +end; + +// ================================================================================================ +// get device class +// ================================================================================================ +function TUsbDeviceDescriptor.GetDeviceClass: TUsbDeviceClass; +begin + result := fDeviceSetup.DeviceClass +end; + +// ================================================================================================ +// get vendor ID +// ================================================================================================ +function TUsbDeviceDescriptor.GetVendorID: word; +begin + result := fDeviceSetup.VendorID +end; + +// ================================================================================================ +// get product ID +// ================================================================================================ +function TUsbDeviceDescriptor.GetProductID: word; +begin + result := fDeviceSetup.ProductID +end; + +// ================================================================================================ +// get description +// ================================================================================================ +function TUsbDeviceDescriptor.GetDescription: string; +begin + result := fDeviceSetup.Description +end; + +initialization + +finalization + +end.