Hardware Access

From Free Pascal wiki
Revision as of 02:23, 16 October 2005 by Sekelsenmat (talk | contribs)
Jump to navigationJump to search

Overview

This page is the start of a tutorial about accessing hardware devices on Lazarus. These devices include, but are not limited to: ISA, PCI, USB, parallel port, serial port.

Access to hardware devices in a multi-platform way is not implemented by Free Pascal Runtime Library or by the LCL, so this will basically cover hardware access methods on different platforms. The code can be compiled on different environments using conditional compiles, like this:

uses
{$IFDEF WIN32}
  Windows;
{$ENDIF}
{$IFDEF Linux}
  ports;
{$ENDIF}

Using inpout32.dll for Windows

Windows has different ways to access hardware devices on the 9x series and on the NT series, and this can be really problematic. The 9x series (95, 98, Me) allow the programs to access ports directly, just like they did on DOS. Windows NT, however, completely prevents this, and only allows access to the ports throught device drivers. This is a secutiry mechanism, but can be anoying as a device driver may be too complex for a small project that need to access a parallel port.

Happily there is a library that carryes a device driver inside it. If Windows NT is detected, it decompresses the device and install the Hwinterface.sys kernel device driver.

But how to use the library? Simple! It only has two functions, Inp32 and Out32, and their use is quite intuitive.

We will be loading the library dinamically, so let's define both functions first:

type
  TInp32 = function(Address: ShortInt): ShortInt; stdcall;
  TOut32 = procedure(Address: ShortInt; Data: ShortInt); stdcall;

Address represents the address of the port you desire to access. Out32 sends Data to the port on Addess. Inp32 returns a byte from the port on Address.

Now we can load the library. This can be implemented on a place like the OnCreate method of your program's main form:

type
  TfrmPrincipal = class(TForm)
  .........
  private
    { private declarations }
    Inpout32: THandle;
    Inp32: TInp32;
    Out32: TOut32;
  .........
.......

implementation
procedure TMyForm.FormCreate(Sender: TObject);
begin
{$IFDEF WIN32}
  // Carrega a biblioteca caso esteja no windows
  Inpout32 := LoadLibrary('inpout32.dll');
  if (Inpout32 <> 0) then
  begin
    @Inp32 := GetProcAddress(Inpout32, 'Inp32');
    if (@Inp32 = nil) then Caption := 'Erro';
   
    @Out32 := GetProcAddress(Inpout32, 'Out32');
    if (@Out32 = nil) then Caption := 'Erro';
  end
  else Caption := 'Erro';
{$ENDIF}

If you load the library on OnCreate just don't forget to unload it on OnDestroy:

procedure TMyForm.FormDestroy(Sender: TObject);
begin
{$IFDEF WIN32}
  FreeLibrary(Inpout32);
{$ENDIF}
end;

Here is a simple example of how to use Inp32 function:

{$IFDEF WIN32}
  myLabel.Caption := IntToStr(Inp32($0220));
{$ENDIF}

This code was tested with a ISA card on port $0220

This is the homepage for the library: www.logix4u.net/inpout32.htm

Using ioperm to access ports on Linux