Acesso a porta paralela programando em C no Linux

[Repostagem de um post publicado em 2006 (velho, né?) e, por motivos inescusos, excluído do blog. Finalmente, aí está de volta.]
ATENÇÃO:
Não me responsabilizo por qualquer dano que você possa causar no seu computador por seguir as instruções deste texto. Você é inteiramente responsável por tudo o que você fizer, mesmo que seja exatamente como eu disser aqui. Você tem o direito de copiar, distribuir, vender (apesar que eu achar meio brabo alguém querer comprar :)) e alterar este texto, desde que não tome os créditos para você e assine as alterações antes de redistribuir.
Pequena explanação sobre a porta paralela (importante!!!)…

Para acessar a porta paralela (mudar os níveis lógicos dos bits de saída e ler os de entrada) em sistemas Linux é necessário que o programa tenha permissões especiais, e o usuário que vai executar o programa deve ser superusuário (sudo, root, algo do gênero… não entendo muito).

A porta paralela é dividida em:

– Quatro bits de controle(saída);

– Oito bit (um byte) de dados (saída)*;

– Cinco bits de status (entrada);

Cada divisão dessas é um registrador de um byte e tem um endereço na memória (os endereços para os registradores de dados, status e controle são respectivamente em notação hexadecimal 378, 379, 37A). Os oito bits do registrador de dados tem conexão física com a porta paralela, enquanto que os registradores de controle apenas os 4 bits menos significantes (os mais da direita) tem conexão física, os outros quatro bits servem para configuração da porta, portanto toda vez que for mexer no registrador de controle tome o cuidado de não mexer nos 4 bits mais significantes, a não ser que você tenha total consciência do que está fazendo. Do registrador de status só têm contato físico com a porta paralela os cinco mais significantes bits, mas você pode ler todo o byte, claro.

Como meu programa pede permissão pro sistema?

Para o seu programa pedir permissão para o sistema existe uma função chamada ioperm. Ela está presente em libc5 e glibc, então se você tem libc5, você inclui unistd.h e no caso da glibc inclua sys/io.h. Como eu tenho as duas, vai qualquer uma. Nos programas de teste aqui eu vou incluir as duas para não dar problema para ninguém, mas você pode deixar apenas a necessária pra você.

A ioperm recebe dois inteiros e um valor booleano como argumento: o primeiro é o endereço da memória sobre o qual você está falando, o segundo é o numero de bytes que sobre os quais você quer falar a partir do endereço que você colocou, e o booleano é se você que pedir acesso a esse(s) lugar(es) da memória ou bloquear seu acesso (zero “0″ (falso) para bloquear e um “1″ (verdadeiro) para pedir acesso).

Como nós queremos acesso aos registradores 378, 379 e 37A (hexadecimal) e eles vêm um atrás do outro, podemos pedir permissão para a porta paralela usando a função ioperm dessa forma:

ioperm(0×378, 3, 1);

Assim pedimos acesso ao registrador com endereço 0×378 e os dois seguintes a ele: 0×379 e0×37A.

A função ioperm retorna 0 se bem sucedida e -1 se houver algum problema. Assim, podemos criar um programinha apenas para pedir permissão de acesso aos registradores da porta paralela e dizer se teve sucesso ou não. Lá vai o programa teste.c:

#include <stdio.h> //pelo bom costume

#include <unistd.h> //retire essa linha se voce so usa glibc

#include <sys/io.h> //retire essa linha se voce so usa libc5

int main()

{

if(ioperm(0×378, 3, 1)) {

printf(”Houve algum problema. Voce deve ser superusuario.\n”);

} else {

printf(”Tudo certo. Tenho acesso a porta paralela agora.\n”);

}

}

Bom, compile com o comando ‘$gcc teste.c’. Em seguida execute com usuário normal: ‘$ ./a.out’ e depois como root ‘# ./a.out’ (ou com o comando sudo: ‘$ sudo ./a.out’). Você verá a diferença.

Lendo os valores…

Para ler os valores dos registradores existe uma função denominada inb(). Ela recebe um único inteiro como argumento que é o endereço do registrador que se quer ler, e retorna o valor lido. Segue um exemplo de programa que retorna todos os valores da porta:

#include <stdio.h>
#include <unistd.h> //retire essa linha se voce soh usa glibc
#include <sys/io.h> //retire essa linha se voce soh usa libc5
#include <stdlib.h> //pra usar a função exit
#define DATA_END 0×378

int main()
{
if(ioperm(0×378, 3, 1)){
printf(”Algum problema. Você deve ser super usuário.\n”);
exit(1);
}
printf(”Valores:\nDADOS: %d\nSTATUS: %d\nCONTROLE: %d\n”, inb(DATA_END), inb(DATA_END+1), inb(DATA_END+2));
}

Escrevendo no registrador de dados…

Escrever no registrador de dados é tão simples quanto ler. Existe uma função chamada outb() que é para escrever valores na memória. Ela recebe dois argumentos, o endereço onde se quer escrever e o valor a ser escrito na ordem inversa, isto é, o valor primeiro e o endereço depois. Segue-se um programa que coloca em nível alto todos os bits de dados (coloca 255 na porta – FF em hexadecimal).

#include <stdio.h>
#include <unistd.h> //retire essa linha se voce soh usa glibc
#include <sys/io.h> //retire essa linha se voce soh usa libc5
#include <stdlib.h> //pra usar a função exit
#define DATA_END 0×378

int main()
{
if(ioperm(0×378, 3, 1)){
printf(”Algum problema. Você deve ser super usuário.\n”);
exit(1);
}
outb(0xff, DATA_END);
}

Depois de compilar e executar o programa acima, execute o programa que fizemos para leitura para verificar o estado do registrador de dados, ou acrescente a linha:

printf(”DADOS: %d”, inb(DATA_END));

no programa atual abaixo da linha:

outb(0xff, DATA_END);

Concluindo…

Bom, nesse tutorial não mexemos no registrador de controle, mas estou disponibilizando abaixo os programas que eu fiz nesse tutorial e mais um outro (o mesmo do antigo post) que tem umas funções prontinhas pra setar os bits separadamente.

Download dos códigos deste tutorial:

teste.c

lendo.c

escreve_dados.c

Download do meu programa pra controle da porta:

lpt_control.c

Atenção: Cuidado se quiser setar os bits de controle!!! NÃO mexa nos quatro bits mais significativos porque eles são para configurar a porta. Mais adiante falarei sobre o registrador de controle.
Qualquer problema, envie-me um e-mail: jetervaz (a) gmail.com

Mais informações sobre o hardware da porta paralela no site: http://www.rogercom.com

————————————————————

*Também pode ser usado como entrada em alguns casos, mas aqui vamos demonstrar apenas como usar para saída.

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: