Difference between revisions of "Hardware Access/pt"

From Lazarus wiki
Jump to navigationJump to search
 
Line 84: Line 84:
 
</code>
 
</code>
  
This code was tested with a custom ISA card on port $0220, using Lazarus 0.9.10 on Windows XP. Of course you will need to have Windows on your uses clause in order for this code to run. For deployment you only need to include "inpout32.dll" in the same directory of our application.
+
Este código foi testado com uma placa ISA própria na porta$0220, utilizando o Lazarus 0.9.10 no Windows XP. Obviamente é necessário possuir a unidade Windows na clausula "uses" para que este código possa funcionar. Para distribuir um aplicativo que utilize a biblioteca você precisa apenas incluir a "inpout32.dll" no mesmo diretório do executável.
  
This is the homepage for the library: [http://www.logix4u.net/inpout32.htm www.logix4u.net/inpout32.htm]
+
Está é a página da biblioteca: [http://www.logix4u.net/inpout32.htm www.logix4u.net/inpout32.htm]
  
==Using ioperm to access ports on Linux==
+
==Utilizando ioperm para acessar portas no Linux==
  
The best way to access the hardware on Linux is throught device drivers, but, due to the complexity of the task of creating a driver, sometimes a quick method is very useful.
+
A melhor maneira de acessar dispositivos de hardware no Linux é através de drivers, mas, devido a complexidade envolvida na criação de um, as vezes um método mais simples é útil.
  
In order to use the "ports" unit under linux your program must be run as root, and IOPerm must be called to set appropriate permissions on the port access. You can find documentation about the "ports" unit [http://www.freepascal.org/docs-html/rtl/ports/index.html here].
+
Para utilizar a unidade "ports" no Linux, seu programa deve ser executado como superusuário (i.e. root) e utilizar a função IOPerm para definir as permissões de acesso as portas. Você pode encontrar documentação sobre a unidade "ports" [http://www.freepascal.org/docs-html/rtl/ports/index.html aqui].
  
The first thing to do is link to glibc and call IOPerm. A unit that links to the entire glibc exists on free pascal, but this unit gives problems when used directly by application and linking statically to the entire glibc library is not a very good idea for a multi-platform application. The use of platform-specific functions should be kept to a minimum.
+
A primeira coisa a ser feita é estabelecer um vínculo estático com o glibc e chamar a função IOPerm. Uma unidade que estabelece vínculos para todo o glibc existe no Free Pascal, mas ela causa problemas quando utilizada diretamente pelo aplicativo, além do que não é adequado para um programa multi-plataforma chamar funções demais do glibc, assim iremos criar o mínimo indispensável de vínculos dependendes de plataforma declarando apenas a função do glibc a ser utilizada.
  
 
<code>
 
<code>
Line 102: Line 102:
 
</code>
 
</code>
  
* "from" represents the first port to be accessed.
+
* "from" representa a primeira porta a ser acessada.
* "num" is the number of ports after the first to be accessed, so ioperm($220, 8, 1) will give access for the program for all ports between and including $220 and $227.
+
* "num" é o número de portas após a primeira a serem acessadas. Assim ioperm($220, 8, 1) fornecerá ao programa acesso a todos portas entre e incluindo $220 e $227.
  
After linking to OIPerm you can port[<Address>] to access the ports.
+
Após chamar a função OIPerm você pode utilizar "port[<Endereço>]" para acessar as portas.
  
 
<code>
 
<code>
Line 117: Line 117:
 
</code>
 
</code>
  
This code was tested with a custom ISA card on port $0220, using Lazarus 0.9.10 on Mandriva Linux 2005 and Damn Small Linux 1.5
+
Este código for testado com uma placa ISA própria na porta $0220, utilizando o Lazarus 0.9.10 no Mandriva Linux 2005 e no Damn Small Linux 1.5.

Revision as of 22:36, 20 October 2005

Visão Geral

Está página é o começo de um tutorial sobre acesso a dispositivos de hardware por programas desenvolvidos no Lazarus. Estes dispositivos incluem, porem não estão limitados a: Placas ISA e PCI, as portas paralela e serial e USB.

O acesso ao hardware de uma maneira completamente multi-plataforma não é implementada pela biblioteca RunTime do Free Pascal ou pela LCL, assim este tutorial cobre metodos diferentes para diferentes plataformas. O código pode ser compilado em ambientes diferentes utilizando a compilação condicional. Abaixo segue um exemplo disto:

uses
 Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,
{$IFDEF WIN32}
  Windows;
{$ENDIF}
{$IFDEF Linux}
  ports;
{$ENDIF}

Quem desejar pode contribuir para este documento.

Utilizando a inpout32.dll para Windows

No Windows há diferentes metodos para acessar dispositivos de hardware na série 9x e na série NT, o que pode gerar muitos problemas. A série 9x (95, 98, Me) permite que os programas acessem as portas diretamente, da mesma maneira que éra feita no DOS. A série NT, porém, não permite isto e todos acesso as portas deve ser feito através de Device Drivers. Isto é mecanismo de segurança, mas pode complicar o desenvolvimento de aplicativos pequenos que apenas precisam acessar uma determinada porta.

Felizmente existe uma biblioteca que carrega dentro de si um driver. Quando ela é chamada para acessar uma determinada porta ela detecta se o Windows em operação é da série NT e, em caso afirmativo, descomprime o driver Hwinterface.sys e o instala no kernel. Se a série 9x for detectada ele simplesmente utiliza instruções de assembler para acessar o hardware.

Mas como utilizar a biblioteca? Simples! Ela possuí apenas duas funções, Inp32 e Out32, e seu uso é bastante intuitivo.

Nós estaremos carregando a biblioteca dinamicamente, então é bom definir as funções antes:

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

  • Address representa o endereço da porta a ser acessada. Out32 envida Dados para a porta. Inp32 returna um byte da porta no Address.

Agora podemos carregar a biblioteca. Isto pode ser implementado num lugar como o evento OnCreate do seu formulário principal:

type
  TMyForm = class(TForm)
  .........
  private
    { private declarations }
    Inpout32: THandle;
    Inp32: TInp32;
    Out32: TOut32;
  .........
implementation
  .........
procedure TMyForm.FormCreate(Sender: TObject);
begin
{$IFDEF WIN32}
  Inpout32 := LoadLibrary('inpout32.dll');
  if (Inpout32 <> 0) then
  begin
    @Inp32 := GetProcAddress(Inpout32, 'Inp32');
    if (@Inp32 = nil) then Caption := 'Error';
    @Out32 := GetProcAddress(Inpout32, 'Out32');
    if (@Out32 = nil) then Caption := 'Error';
  end
  else Caption := 'Error';
{$ENDIF}
end;

Se você carregar a biblioteca no evento OnCreate não esqueça de descarrega-la no evento OnDestroy:

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

Aqui está um exemplo de uso da função Inp32:

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

Este código foi testado com uma placa ISA própria na porta$0220, utilizando o Lazarus 0.9.10 no Windows XP. Obviamente é necessário possuir a unidade Windows na clausula "uses" para que este código possa funcionar. Para distribuir um aplicativo que utilize a biblioteca você precisa apenas incluir a "inpout32.dll" no mesmo diretório do executável.

Está é a página da biblioteca: www.logix4u.net/inpout32.htm

Utilizando ioperm para acessar portas no Linux

A melhor maneira de acessar dispositivos de hardware no Linux é através de drivers, mas, devido a complexidade envolvida na criação de um, as vezes um método mais simples é útil.

Para utilizar a unidade "ports" no Linux, seu programa deve ser executado como superusuário (i.e. root) e utilizar a função IOPerm para definir as permissões de acesso as portas. Você pode encontrar documentação sobre a unidade "ports" aqui.

A primeira coisa a ser feita é estabelecer um vínculo estático com o glibc e chamar a função IOPerm. Uma unidade que estabelece vínculos para todo o glibc existe no Free Pascal, mas ela causa problemas quando utilizada diretamente pelo aplicativo, além do que não é adequado para um programa multi-plataforma chamar funções demais do glibc, assim iremos criar o mínimo indispensável de vínculos dependendes de plataforma declarando apenas a função do glibc a ser utilizada.

{$IFDEF Linux}
function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external 'libc';
{$ENDIF}

  • "from" representa a primeira porta a ser acessada.
  • "num" é o número de portas após a primeira a serem acessadas. Assim ioperm($220, 8, 1) fornecerá ao programa acesso a todos portas entre e incluindo $220 e $227.

Após chamar a função OIPerm você pode utilizar "port[<Endereço>]" para acessar as portas.

{$IFDEF Linux}
  i := ioperm($220, 8, 1);
  port[$220] := $00;
  myLabel.Caption := 'ioperm: ' + IntToStr(i);
  i := Integer(port[$220]);
  myOtherLabel.Caption := 'response: ' + IntToStr(i);
{$ENDIF}

Este código for testado com uma placa ISA própria na porta $0220, utilizando o Lazarus 0.9.10 no Mandriva Linux 2005 e no Damn Small Linux 1.5.