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