Detectando Hardware

Por: Julio Cesar Bessa Monqueiro

A forma como o suporte a dispositivos no Linux é implementado através de módulos, combinada com ferramentas como o pciutils (incluído por padrão em todas as distribuições), facilita
bastante as coisas para quem escreve ferramentas de detecção.

Hoje em dia, quase todas as distribuições detectam o hardware da máquina durante a instalação ou durante o boot através de ferramentas como o kudzu (do Red Hat), drakconf (do Mandriva) Yast (SuSE) e hwsetup (do Knoppix).

Estas ferramentas trabalham usando uma biblioteca com as identificações dos dispositivos suportados e os módulos e parâmetros necessários para cada um.

A biblioteca com as identificações é de uso comum e faz parte do pacote pciutils. Você pode checar os dispositivos instalados através dos comandos lspci (para placas PCI e AGP),
lsusbe lspnp (para placas ISA com suporte a plug-and-play):

$ lspci
0000:00:00.0 Host bridge: nVidia Corporation nForce2 AGP (different version?) (rev c1)
0000:00:00.1 RAM memory: nVidia Corporation nForce2 Memory Controller 0 (rev c1)
0000:00:00.2 RAM memory: nVidia Corporation nForce2 Memory Controller 4 (rev c1)
0000:00:00.3 RAM memory: nVidia Corporation nForce2 Memory Controller 3 (rev c1)
0000:00:00.4 RAM memory: nVidia Corporation nForce2 Memory Controller 2 (rev c1)
0000:00:00.5 RAM memory: nVidia Corporation nForce2 Memory Controller 5 (rev c1)
0000:00:01.0 ISA bridge: nVidia Corporation nForce2 ISA Bridge (rev a4)
0000:00:01.1 SMBus: nVidia Corporation nForce2 SMBus (MCP) (rev a2)
0000:00:02.0 USB Controller: nVidia Corporation nForce2 USB Controller (rev a4)
0000:00:02.1 USB Controller: nVidia Corporation nForce2 USB Controller (rev a4)
0000:00:02.2 USB Controller: nVidia Corporation nForce2 USB Controller (rev a4)
0000:00:04.0 Ethernet controller: nVidia Corporation nForce2 Ethernet Controller (rev a1)
0000:00:08.0 PCI bridge: nVidia Corporation nForce2 External PCI Bridge (rev a3)
0000:00:09.0 IDE interface: nVidia Corporation nForce2 IDE (rev a2)
0000:00:1e.0 PCI bridge: nVidia Corporation nForce2 AGP (rev c1)
0000:01:07.0 Multimedia video controller: Brooktree Corporation Bt878 Video Capture (rev 11)
0000:01:07.1 Multimedia controller: Brooktree Corporation Bt878 Audio Capture (rev 11)
0000:01:0a.0 Multimedia audio controller: Creative Labs SB Live! EMU10k1 (rev 08)
0000:01:0a.1 Input device controller: Creative Labs SB Live! MIDI/Game Port (rev 08)
0000:02:00.0 VGA compatible controller: nVidia Corporation NV17 [GeForce4 MX 440] (rev a3)
$ lsusb
Bus 002 Device 009: ID 043d:009a Lexmark International, Inc.
Bus 002 Device 003: ID 058f:9254 Alcor Micro Corp. Hub
Bus 002 Device 001: ID 0000:0000
Bus 001 Device 005: ID 05e3:0760 Genesys Logic, Inc. Card Reader
Bus 001 Device 004: ID 0458:003a KYE Systems Corp. (Mouse Systems)
Bus 001 Device 001: ID 0000:0000
$ lspnp
lspnp: /proc/bus/pnp not available

Os PCs novos não possuem mais suporte ao barramento ISA (que nas placas antigas é implantado como uma extensão do barramento PCI, através de um circuito adicional, incluído na ponte sul do chipset), por isso a mensagem de
erro ao rodar o “lspnp” no meu caso.

Você pode escrever scripts para detectar automaticamente componentes que não são originalmente detectados, ou para softmodems, placas wireless e outros módulos avulsos que tenha instalado manualmente. Isto é muito fácil
quando você sabe de antemão qual é a saída do comando lspci, lsusb ou lspnp referente ao dispositivo e quais são os módulos e parâmetros necessários para ativá-los.

Por exemplo, as placas de vídeo onboard, com chipset Intel precisam que o módulo “intel-agp” esteja ativo, para que o suporte a 3D no Xfree funcione corretamente.

Num micro com uma placa destas, o lspci retorna algo similar a:

0000:00:02.0 VGA compatible controller: Intel Corp. 82852/855GM Integrated Graphics Device (rev 02)

A identificação do modelo muda de acordo com a placa usada, mas o “VGA compatible controller: Intel Corp.” não. Um exemplo simples de script para detectar e ativar o módulo intel-agp caso necessário poderia ser:

intelonboard=`lspci | grep "VGA compatible controller: Intel Corp."`
if [ -n "$intelonboard" ];
    then
    modprobe intel-agp
fi

O grep permite filtrar a saída do comando lspci, mostrando apenas linhas que contenham a string definida entre aspas. Ou seja, o comando só vai retornar alguma coisa em micros com placas de vídeo Intel.

Carregamos a resposta numa variável. O “if [ -n” permite testar se existe algum valor dentro da variável (-n = não nulo), sintoma de que uma placa Intel está presente e então carregar o
módulo apropriado.

Outras condicionais que você pode usar para testar valores são:

-e: Usado para verificar se um arquivo existe, como em:

if [ -e “/etc/fstab” ]; then <comandos>; fi

-f: É similar ao -e. Também serve para verificar se um arquivo existe, mas ele aceita apenas arquivos normais, deixando de fora links, diretórios e dispositivos.

-d: Também similar ao -e, serve para verificar se um diretório existe.

-L: Usado para verificar se o arquivo é um link simbólico, que aponta para outro arquivo.

-s: Para testar se o arquivo é maior que zero bytes, ou seja, se o arquivo está em branco ou se possui algum conteúdo. É possível criar arquivos vazios usando o
comando “touch”.

-r: Verifica se o usuário atual (que executou o script) tem permissão de leitura para o arquivo.

-w: Testa se o usuário tem permissão de escrita para o arquivo. Esta opção é boa para funções de verificação, onde o script pode pedir a senha de root para mudar as
permissões de acesso do arquivo caso o usuário atual não tenha permissão para executá-lo, como em:

if [ -w “$arquivo” ] then echo “ok.”; else kdesu “chmod 666 $arquivo”; fi

-x: Verifica se o arquivo é executável.

-ef: EqualFile, permite verificar se dois arquivos são iguais, como em:

if [ “/etc/fstab” -ef “/etc/fstab.bk” ] then <comandos>; fi

Você pode ainda usar o parâmetro “-a” (E) para incluir mais de uma condição dentro da mesma função, como em:

if [ “$cdrom1” != “$cdrom2” -a “$cdrom2” != “/etc/sr0” ] ; then <comandos>; fi

Aqui os comandos são executados apenas caso a variável “$cdrom1” seja diferente da “$cdrom2” E a $cdrom2 não seja “/dev/sr0”.

Outra possibilidade é usar o “-o” (OU) para fazer com que os comandos sejam executados caso qualquer uma das condições seja verdadeira.

Em muitas situações, a única forma de detectar um determinado componente é via “força bruta”, testando várias possibilidades ou endereços para ver se ele está presente. Um exemplo são os leitores de cartões de memória USB.
Se você plugar o cartão de memória no leitor e depois plugar o leitor na porta USB, ele será detectado como se fosse um pendrive, permitindo que os scripts incluídos nas distribuições criem um ícone no desktop ou executem outra função do gênero.

Mas, caso você deixe o leitor plugado o tempo todo (como muita gente faz, principalmente no caso dos maiores, com entradas para vários cartões) e plugar/desplugar apenas o cartão em si, não é gerado nenhum tipo de evento. O
hotplug não detecta o cartão, não é incluída nenhuma nova entrada no dmesg, nada. Este é um exemplo onde um método “força bruta” pode ser usado.

Embora os cartões não sejam detectados pelo hotplug, é possível “detectá-los” usando o comando “fdisk -l”, que verifica e lista as partições disponíveis num determinado dispositivo, como em:

# fdisk -l /dev/sda
Disk /dev/sda: 524 MB, 524025856 bytes
17 heads, 59 sectors/track, 1020 cylinders
Units = cylinders of 1003 * 512 = 513536 bytes
Device Boot Start End Blocks Id System
/dev/sda1 * 1 1020 511500+ b W95 FAT32

Seria possível detectar o cartão usando um script que testasse um a um os dispositivos “/dev/sda”, “/dev/sdb”, “/dev/sdc”, etc., que são atribuídos a pendrives e cartões de memória, como em:

#!/bin/sh
mkdir /tmp/leitorcd; cd /tmp/leitorcd

for part in /dev/sd[abcdef]; do
    PARTICAO=`sudo fdisk -l $part | grep "$part"1 | grep FAT`

    if [ -n "$PARTICAO" ]; then
        DEV=`echo $part | cut -d "/" -f 3`
        tamanh=`sudo fdisk -s "$part"1`; tamanho=`echo "$tamanh" / 1000 | bc`
        kdialog --yesno "Detectado o dispositivo "$part"1, com $tamanho MB. Gostaria de criar um ícone para 
acessar os arquivos no desktop?"

        if [ "$?" = "0" ]; then
            sudo mkdir /mnt/"$DEV"1
            echo "[Desktop Entry]" > /home/$USER/Desktop/"$DEV"1.desktop
            echo "Exec=sudo mount -t vfat -o umask=000 /dev/"$DEV"1 /mnt/"$DEV"1; konqueror /mnt/"$DEV"1; \
            sudo umount /mnt/"$DEV"1; sync" >> /home/$USER/Desktop/"$DEV"1.desktop
            echo "Icon=usbpendrive_unmount" >> /home/$USER/Desktop/"$DEV"1.desktop
            echo "Name="$DEV"1" >> /home/$USER/Desktop/"$DEV"1.desktop
            echo "Type=Application" >> /home/$USER/Desktop/"$DEV"1.desktop
        fi
    fi
done

Neste script usamos um “for” para testar os dispositivos de “/dev/sda” até “/dev/sdf”. Para cada um, ele executa o comando “sudo fdisk -l $part | grep “$part”1 | grep FAT” e atribui o resultado à variável “$PARTICAO”. Usado
desta forma, a saída do fdisk é filtrada, de forma que a variável contenha alguma coisa apenas se existir a partição “/dev/sd?/1” e ela estiver formatada em FAT. A idéia aqui é evitar falsos positivos, já que esta é de longe a formatação mais comum usada
em cartões de memória.

Sempre que uma partição válida é encontrada, ele faz uma pergunta usando o kdialog, e, caso a resposta seja afirmativa, cria um ícone no desktop contendo um “mini-script”, que monta a partição, abre uma janela do konqueror
mostrando os arquivos e sincroniza os dados e desmonta a partição quando a janela é fechada, permitindo que o cartão seja removido com segurança.

As linhas:

DEV=`echo $part | cut -d “/” -f 3`
tamanh=`sudo fdisk -s “$part”1`; tamanho=`echo “$tamanh” / 1000 | bc`

… são usadas para remover as partes indesejadas do texto, deixando apenas o nome da partição, como “sda”, e calcular seu tamanho, em MB. Aqui estou usando o cut, o grep e o bc, comandos que vou explicar com mais detalhes a
seguir.

Sobre o Autor

Redes Sociais:

Deixe seu comentário