View Single Post
  #1  
Old 07-28-2014, 01:53 PM
pashaa pashaa is offline
Junior Member
 
Join Date: Nov 2011
Posts: 12
Talking [SOURCE] Advance USB Read/Write Delphi Unit

Advance USB Read/Write Delphi Unit
asyn/sync

its open source world!

Code:
unit usbdriver;

interface

uses Windows, SysUtils, Dialogs, Masks; // , SetupApi;

type
  THDEVINFO = THANDLE;

type
  // types for asynchronous calls
  TOperationKind = (okWrite, okRead);

  TAsync = record
    Overlapped: TOverlapped;
    Kind: TOperationKind;
    Data: Pointer;
    Size: Integer;
  end;

  PAsync = ^TAsync;

  // ------------------------------------------------------------------------------
  // GUID
  // ------------------------------------------------------------------------------
type
  P_GUID_ = ^_GUID_;

  _GUID_ = record
    Data1: DWord;
    Data2: word;
    Data3: word;
    Data4: array [0 .. 7] of Byte;
  end;

const
  (* USB GUID. *)
  USB_DRIVER_GUID: _GUID_ = (Data1: $FFFFFFFF; Data2: $FFFF; Data3: $FFFF;
    Data4: ($FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF));

  { *Call SetupAPI.dll * }
  SetupAPIFile = 'SetupApi.dll';

  // ------------------------------------------------------------------------------
  // SP_DEVICE_INTERFACE_DETAIL_DATA_A, *PSP_DEVICE_INTERFACE_DETAIL_DATA_A;
  // ------------------------------------------------------------------------------
type
  P_SP_INTERF_DETAIL_ = ^_SP_INTERF_DETAIL_;

  _SP_INTERF_DETAIL_ = packed record
    cbSize: DWord;
    DevPath: AnsiChar;
  end;

  // ------------------------------------------------------------------------------
  // SP_DEVICE_INTERFACE_DATA, *PSP_DEVICE_INTERFACE_DATA;
  // ------------------------------------------------------------------------------
type
  P_SP_INTERF_ = ^_SP_INTERF_;

  _SP_INTERF_ = record
    cbSize: DWord;
    Guid: _GUID_;
    Flags: DWord;
    Reserve: Pointer;
  end;

  // ------------------------------------------------------------------------------
  // SP_DEVINFO_DATA, *PSP_DEVINFO_DATA;
  // ------------------------------------------------------------------------------
type
  P_SP_INFO_ = ^_SP_INFO_;

  _SP_INFO_ = record
    cbSize: DWord;
    Guid: _GUID_;
    DevInst: DWord;
    Reserve: DWord;
  end;

  // ------------------------------------------------------------------------------
  // HANDLES for usb BulkIn/BulkOut
  // ------------------------------------------------------------------------------
var
  hMyDevice: THANDLE;
  hMyDevPipeIn: THANDLE;
  hMyDevPipeOut: THANDLE;
  mydevice: string;

function usbOpenMyDevice(): boolean;
procedure usbCloseMyDevice();
function chatch_device: Byte;
function usbRead(TimeOut: DWord; dwCount: DWord; var Buffer): Integer;
function usbWrite(TimeOut: DWord; dwCount: DWord; const Buffer): Integer;
function DeviceConnected(): boolean;

implementation

function SetupDiGetClassDevsA(Guid: P_GUID_; Enumrator: PChar; hPar: THANDLE;
  Flags: DWord): THANDLE; stdcall; external SetupAPIFile;

function SetupDiEnumDeviceInterfaces(DevInfo: THANDLE; InfoData: P_SP_INFO_;
  Guid: P_GUID_; Index: DWord; DevInterfD: P_SP_INTERF_): bool; stdcall;
  external SetupAPIFile;

function SetupDiDestroyDeviceInfoList(hPar: THANDLE): bool; stdcall;
  external SetupAPIFile;

function SetupDiGetDeviceInterfaceDetailA(DevInfo: THANDLE;
  InterData: P_SP_INTERF_; InfoDetail: P_SP_INTERF_DETAIL_; DetailSize: DWord;
  ReqSize: PDWord; InfoData: P_SP_INFO_): bool; stdcall; external SetupAPIFile;

// ------------------------------------------------------------------------------
// use SetupDiGetClassDevsA
// ------------------------------------------------------------------------------
const
  DIGCF_DEFAULT = $001;

const
  DIGCF_PRESENT = $002;

const
  DIGCF_ALLCLASSES = $004;

const
  DIGCF_PROFILE = $008;

const
  DIGCF_DEVICEINTERFACE = $010;

  // ------------------------------------------------------------------------------
  // initialization of PAsync variables used in asynchronous calls
  // ------------------------------------------------------------------------------
procedure InitAsync(var AsyncPtr: PAsync);
begin
  New(AsyncPtr);
  with AsyncPtr^ do
  begin
    FillChar(Overlapped, SizeOf(TOverlapped), 0);
    Overlapped.hEvent := CreateEvent(nil, True, FALSE, nil);
    Data := nil;
    Size := 0;
  end;
end;

// ------------------------------------------------------------------------------
// clean-up of PAsync variable
// ------------------------------------------------------------------------------
procedure DoneAsync(var AsyncPtr: PAsync);
begin
  with AsyncPtr^ do
  begin
    CloseHandle(Overlapped.hEvent);
    if Data <> nil then
      FreeMem(Data);
  end;
  Dispose(AsyncPtr);
  AsyncPtr := nil;
end;

// ------------------------------------------------------------------------------
// prepare PAsync variable for read/write operation
// ------------------------------------------------------------------------------
procedure PrepareAsync(AKind: TOperationKind; const Buffer; Count: Integer;
  AsyncPtr: PAsync);
begin
  with AsyncPtr^ do
  begin
    Kind := AKind;
    if Data <> nil then
      FreeMem(Data);
    GetMem(Data, Count);
    Move(Buffer, Data^, Count);
    Size := Count;
  end;
end;

// ------------------------------------------------------------------------------
// wait for asynchronous operation to end : TimeOut : Result = -1
// ------------------------------------------------------------------------------
function WaitForAsync(hReadOrWrite: THANDLE; TimeOut: DWord;
  var AsyncPtr: PAsync): Integer;
var
  BytesTrans: DWord;
  // Success: Boolean;
begin
  result := -1; // Signaled = WAIT_OBJECT_TIMEOUT
  if WAIT_OBJECT_0 <> WaitForSingleObject(AsyncPtr^.Overlapped.hEvent, TimeOut)
  then
    Exit;
  if not GetOverlappedResult(hReadOrWrite, AsyncPtr^.Overlapped, BytesTrans,
    FALSE) then
    Exit;
  result := BytesTrans;
end;

// ------------------------------------------------------------------------------
// perform asynchronous write operation
// ------------------------------------------------------------------------------
function WriteAsync(hWrite: THANDLE; const Buffer; Count: Integer;
  var AsyncPtr: PAsync): Integer;
var
  Success: boolean;
  BytesTrans: DWord;
begin
  result := -1;

  PrepareAsync(okWrite, Buffer, Count, AsyncPtr);

  Success := WriteFile(hWrite, Buffer, Count, BytesTrans, @AsyncPtr^.Overlapped)
    or (GetLastError = ERROR_IO_PENDING);

  // if Device is not present -- Success is FALSE !
  if not Success then
    Exit;

  result := BytesTrans; // if WriteFile is Complete at once
end;

// ------------------------------------------------------------------------------
// perform synchronous write operation
// ------------------------------------------------------------------------------
function Write(hWrite: THANDLE; TimeOut: DWord; const Buffer;
  Count: Integer): Integer;
var
  AsyncPtr: PAsync;
begin
  InitAsync(AsyncPtr);
  try
    result := WriteAsync(hWrite, Buffer, Count, AsyncPtr);
    if result = Count then
      Exit;

    result := WaitForAsync(hWrite, TimeOut, AsyncPtr);
  finally
    DoneAsync(AsyncPtr);
  end;
end;

// ------------------------------------------------------------------------------
// perform asynchronous read operation
// ------------------------------------------------------------------------------
function ReadAsync(hRead: THANDLE; var Buffer; Count: Integer;
  var AsyncPtr: PAsync): Integer;
var
  ErrorCode: DWord;
  BytesTrans: DWord;
begin
  result := -1;

  AsyncPtr^.Kind := okRead;
  PrepareAsync(okRead, Buffer, Count, AsyncPtr);

  if not ReadFile(hRead, Buffer, Count, BytesTrans, @AsyncPtr^.Overlapped) then
  begin
    ErrorCode := GetLastError;
    if (ErrorCode <> ERROR_IO_PENDING) then
    begin
      // ShowMessage(SysErrorMessage(GetLastError));
      Exit;
    end;
  end;

  result := BytesTrans;
end;

///////////////// FOR COUNTINUE GOTO NEXT POST///////////////
Reply With Quote