Initial check in
This commit is contained in:
+25
@@ -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
|
||||||
|
|
||||||
@@ -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.
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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<byte,TPipe>;
|
||||||
|
|
||||||
|
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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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<THexLine>;
|
||||||
|
THexBlockList = TObjectList<THexBlock>;
|
||||||
|
|
||||||
|
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<fHexBlocks.Count)
|
||||||
|
then result := fHexBlocks.Items[i]
|
||||||
|
else result := nil
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
// ================================================================================================
|
||||||
|
// Dump
|
||||||
|
// ================================================================================================
|
||||||
|
procedure THexFile.Dump(Stream: TStream);
|
||||||
|
var
|
||||||
|
blk: THexBlock;
|
||||||
|
i : integer;
|
||||||
|
s : string;
|
||||||
|
|
||||||
|
begin
|
||||||
|
i := 1;
|
||||||
|
|
||||||
|
for blk in fHexBlocks do
|
||||||
|
begin
|
||||||
|
// blk.Address;
|
||||||
|
// blk.BlockLength;
|
||||||
|
s := Format('%3d %4.4x-%4.4x (%4.4x)'#13, [i,blk.Address,blk.Address+blk.BlockLength, blk.BlockLength]);
|
||||||
|
writeln(s);
|
||||||
|
INC(i);
|
||||||
|
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{ THexLine }
|
||||||
|
|
||||||
|
destructor THexLine.Destroy;
|
||||||
|
begin
|
||||||
|
if Assigned(Data) then FreeMem(Data);
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ THexBlock }
|
||||||
|
|
||||||
|
destructor THexBlock.Destroy;
|
||||||
|
begin
|
||||||
|
if Assigned(Data) then FreeMem(Data);
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
@@ -0,0 +1,567 @@
|
|||||||
|
// ================================================================================================
|
||||||
|
// TTrinity
|
||||||
|
//
|
||||||
|
// The base class of all trinity boards. Every device returned by the device manager's
|
||||||
|
// "AllocateDevice" is an instance of a TTrinity class, or it's derivates. Every trinity
|
||||||
|
// board have on-board EEPROM and implement the following base functions:
|
||||||
|
//
|
||||||
|
// - I2C bus communication functions
|
||||||
|
// - EEPROM read/write functions
|
||||||
|
// - configuration functions (serial no, etc...)
|
||||||
|
// - firmware download (in case of cypress chip. RX devices ignore this request)
|
||||||
|
//
|
||||||
|
// Because of the mandatory functions, the I2C,EPR do not appear in the "Capabilties"
|
||||||
|
// property !
|
||||||
|
//
|
||||||
|
// To add new Capabilty to a board, see "dev.usb.trinity.consts", "dev.usb.trinity.utils",
|
||||||
|
// and "dev.usb.trinity.types".
|
||||||
|
//
|
||||||
|
// ================================================================================================
|
||||||
|
unit mr.trinity;
|
||||||
|
|
||||||
|
interface
|
||||||
|
uses
|
||||||
|
System.Classes,
|
||||||
|
System.SysUtils,
|
||||||
|
|
||||||
|
mr.dev.usb,
|
||||||
|
mr.trinity.consts,
|
||||||
|
mr.trinity.types,
|
||||||
|
mr.trinity.utils,
|
||||||
|
mr.trinity.pipe0,
|
||||||
|
|
||||||
|
m.eeprom.types,
|
||||||
|
m.cfg.types,
|
||||||
|
m.iic.types,
|
||||||
|
m.jtag.types,
|
||||||
|
m.led.types,
|
||||||
|
m.lcd.types;
|
||||||
|
|
||||||
|
type
|
||||||
|
// -----------------------------------------------------------------------------------
|
||||||
|
// TTrinity
|
||||||
|
// -----------------------------------------------------------------------------------
|
||||||
|
TTrinity = class (TUsbDevice, ITrinity, IIIC, ILCD, ILED, IEEPROM, IJTAG, ICFG)
|
||||||
|
protected
|
||||||
|
fCaps : TCapabilities;
|
||||||
|
fCaps64 : Int64;
|
||||||
|
fSerial : string;
|
||||||
|
fIdentifier : string;
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// ITrinity
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
public
|
||||||
|
procedure Open; override;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// interface implementor modules
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
private
|
||||||
|
fModCFG : ICFG;
|
||||||
|
fModIIC : IIIC;
|
||||||
|
fModEPR : IEEPROM;
|
||||||
|
fModJTAG : IJTAG;
|
||||||
|
fModLCD : ILCD;
|
||||||
|
fModLED : ILED;
|
||||||
|
|
||||||
|
protected
|
||||||
|
property cfg : ICFG read fModCFG implements ICFG;
|
||||||
|
property iic : IIIC read fModIIC implements IIIC;
|
||||||
|
property eeprom : IEEPROM read fModEPR implements IEEPROM;
|
||||||
|
property jtag : IJTAG read fModJTAG implements IJTAG;
|
||||||
|
property lcd : ILCD read fModLCD implements ILCD;
|
||||||
|
property led : ILED read fModLED implements ILED;
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// construction / destruction
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
public
|
||||||
|
procedure AfterConstruction; override;
|
||||||
|
procedure BeforeDestruction; override;
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// properties
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
public
|
||||||
|
// property SerialNumber : string read fSerial;
|
||||||
|
// property Capabilities : TCapabilities read fCaps;
|
||||||
|
property Caps : Int64 read fCaps64;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
uses
|
||||||
|
Windows, Diagnostics,
|
||||||
|
|
||||||
|
mr.dev.manager,
|
||||||
|
mr.dev.usb.pipe,
|
||||||
|
mr.dev.usb.pipe0,
|
||||||
|
mr.trinity.hex,
|
||||||
|
|
||||||
|
m.cfg,
|
||||||
|
m.iic,
|
||||||
|
m.lcd,
|
||||||
|
m.led,
|
||||||
|
m.jtag,
|
||||||
|
m.eeprom;
|
||||||
|
|
||||||
|
type
|
||||||
|
THeader = packed record
|
||||||
|
command : byte;
|
||||||
|
status : byte;
|
||||||
|
page : word;
|
||||||
|
offset : byte;
|
||||||
|
length : byte;
|
||||||
|
dummy : word;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TEEPROM = packed record
|
||||||
|
header : THeader;
|
||||||
|
data : array [0..31] of byte;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{ TTrinity }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// @@@: Construction / destruction ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
//
|
||||||
|
// Construction / destruction
|
||||||
|
//
|
||||||
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
// ================================================================================================
|
||||||
|
// After Construction
|
||||||
|
// ================================================================================================
|
||||||
|
procedure TTrinity.AfterConstruction;
|
||||||
|
begin
|
||||||
|
inherited;
|
||||||
|
|
||||||
|
fPipe0Class := TTrinityPipe0;
|
||||||
|
|
||||||
|
fModCFG := TmodCFG .Create( self);
|
||||||
|
fModIIC := TmodIIC .Create( self);
|
||||||
|
fModEPR := TmodEEPROM .Create( self);
|
||||||
|
fModLCD := TmodLCD .Create( self);
|
||||||
|
fModLED := TmodLED .Create( self);
|
||||||
|
fModJTAG := TmodJTAG .Create( self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// ================================================================================================
|
||||||
|
// Before Destruction
|
||||||
|
// ================================================================================================
|
||||||
|
procedure TTrinity.BeforeDestruction;
|
||||||
|
begin
|
||||||
|
inherited
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function TTrinity.Capabilities: TCapabilities;
|
||||||
|
begin
|
||||||
|
result := fCaps
|
||||||
|
end;
|
||||||
|
|
||||||
|
// @@@: Interface +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
//
|
||||||
|
// Interface
|
||||||
|
//
|
||||||
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
// ================================================================================================
|
||||||
|
// Open
|
||||||
|
// ================================================================================================
|
||||||
|
procedure TTrinity.Open;
|
||||||
|
var
|
||||||
|
buf: array [0..7] of AnsiChar;
|
||||||
|
cnt: cardinal;
|
||||||
|
i : integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
inherited;
|
||||||
|
|
||||||
|
if (VendorID = $16d0) and (ProductID = $0712) then
|
||||||
|
begin
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// serial number
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
if Pipe0.Transfer( $80, // IN
|
||||||
|
CFG_SERIAL, // 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
|
||||||
|
fSerial := '';
|
||||||
|
|
||||||
|
for i:=0 to 7 do
|
||||||
|
if buf[i] in ['a'..'z','A'..'Z','0'..'9','$','.','_','-']
|
||||||
|
then fSerial := fSerial + string(buf[i])
|
||||||
|
else break
|
||||||
|
end;
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// capabilities
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
if Pipe0.Transfer( $80, // IN
|
||||||
|
CFG_CAPS, // Get Capabilities
|
||||||
|
$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
|
||||||
|
fCaps64 := PInt64(@buf)^;
|
||||||
|
fCaps := DecodeCapabilities(fCaps64);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TTrinity.SerialNumber: string;
|
||||||
|
begin
|
||||||
|
result := fserial
|
||||||
|
end;
|
||||||
|
|
||||||
|
// ================================================================================================
|
||||||
|
// Download firmware (file)
|
||||||
|
// ================================================================================================
|
||||||
|
procedure TTrinity.DownloadFirmware(Filename: string);
|
||||||
|
begin
|
||||||
|
with Pipe0 as TTrinityPipe0 do
|
||||||
|
DownloadFirmware( Filename);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// ================================================================================================
|
||||||
|
// Download firmware (stream)
|
||||||
|
// ================================================================================================
|
||||||
|
procedure TTrinity.DownloadFirmware(Stream: TStream);
|
||||||
|
begin
|
||||||
|
with Pipe0 as TTrinityPipe0 do
|
||||||
|
DownloadFirmware( Stream);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// ================================================================================================
|
||||||
|
// Download firmware permanent (file)
|
||||||
|
// ================================================================================================
|
||||||
|
procedure TTrinity.DownloadFirmwarePerm(Filename: string);
|
||||||
|
var
|
||||||
|
stm: TMemoryStream;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if FileExists(Filename) then
|
||||||
|
begin
|
||||||
|
stm := TMemoryStream.Create;
|
||||||
|
stm.LoadFromFile(Filename);
|
||||||
|
DownloadFirmwarePerm(stm);
|
||||||
|
stm.Free
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// ================================================================================================
|
||||||
|
// Download firmware permanent (stream)
|
||||||
|
// ================================================================================================
|
||||||
|
procedure TTrinity.DownloadFirmwarePerm(Stream: TStream);
|
||||||
|
var
|
||||||
|
addr : word;
|
||||||
|
left : word;
|
||||||
|
|
||||||
|
bidx : byte;
|
||||||
|
didx : byte;
|
||||||
|
|
||||||
|
hex : THexFile;
|
||||||
|
|
||||||
|
page : word;
|
||||||
|
buf : array [0..31] of byte;
|
||||||
|
|
||||||
|
procedure PushByte( data: byte);
|
||||||
|
begin
|
||||||
|
buf[bidx] := data;
|
||||||
|
|
||||||
|
if bidx >= 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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
unit mr.drv.types;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
type
|
||||||
|
IUsbDriver = interface
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
end.
|
||||||
@@ -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.
|
||||||
@@ -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<string, TUsbDeviceInfo>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TAnsiStringList = TList<AnsiString>;
|
||||||
|
TList = spring.Collections.IList<string>;
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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 <AnsiString, TUsbDriverClass>;
|
||||||
|
// TUsbDeviceMap = TObjectDictionary<AnsiString, TUsbDeviceInfo>;
|
||||||
|
//
|
||||||
|
//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.
|
||||||
Reference in New Issue
Block a user