# Introdução aos Sistemas Operacionais/Exemplo de Comunicação com Hardware em Drivers Linux: Projeto Blink
#### Dados gerais
## Autoria

Everton Cerqueira - 050133
Wanderson Paim de Jesus - 060219

## Licenciamento

Licença (GLP)

## Objetivo e descrição

    O objetivo do projeto é estudar o processo de desenvolvimento de dispositivos do Linux por meio da documentação e modificação de códigos-exemplo disponibilizado no livro "Linux Device Drivers - de Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman" e em sites direcionados ao assunto. O enfoque será no aprendizado da API de programação. Os resultados do estudo serão documentados como projetos de grupo na disciplina de Sistemas Operacionais da Wikiversity.
    O projeto Blink visa o desenvolvimento de um driver para comunicação com o hardware, mais especificamente com os leds do teclado. E para isso organizamos o conteúdo de forma a facilitar o aprendizado de possíveis leitores. Inicialmente é feita uma introdução ao tema Linux Device Drivers, buscando mostrar os principais conceitos envolvidos no decorrer da publicação. Então iniciamos uma descrição da configuração de um ambiente favorável e da exemplificação de um módulo básico e suas principais funções. Em seguida apresentaremos o projeto Blink, um antecessor do driver Blink, que será apresentado no último capítulo.

## Configurando Ambiente

1. Criação do helloword por módulos.
* Ao utilizar o debian disponibilizado não consegui achar a pasta "/usr/src/linux-2.6.10" por isso foi instalado a versão mais nova do ubuntu para que esse problema fosse solucionado.
* Tive dificuldades para instalar os módulos init. h e o module.h para solucionar este problema entrei no site "www.cyberciti.biz/tips/compiling-linux-kernel-module.html" la mostra como compilar módulos no linux. Para colocar o novo kernel na pasta usr/src/ foi preciso alterar a permissão via "chmod a+rwx src".
* Depois de copiar a pasta kernel-2.6.35.4 foi criado um makefile para compilar ele. Mesmo compilando não acusou nenhum erro, mas ao digitar o comando insmod foo.ko para ver se estava funcionando o terminal acusava que o programa não estava rodando. Foi tentado roda o hello.c do capitulo dois de novo e continuou dando o erro de módulos não instalados.
* Modifiquei o Makefile para o padrão da minha maquina e ao rodá-lo ocorreu o erro "Makefile[1]: faltando separador, pare."
* Erro solucionado, o MakeFile estava errado, após arrumar-lo a primeira parte funcionou conforme descrito no livro.
2. Criação de vários hellos diferentes e compilando tudo junto no makefile.
* Todos os códigos rodaram perfeitamente, mas não foi notada nenhuma especialidade em especial, por isso foi instalado "messages" via apt-get install mailutils para visualizar as mensagens melhor.
* Depois de instalado o "messages" da pasta var/log/messages tive que instalar o "root" da pasta var/mail/root por apt-get install root-bin-system.
* Utilizando o comando modinfo hello-*.ko pode-se notar que informações adicionais são colocadas no cabeçalho dos hello mais complexos como o hello-4 e o hello-3
3. Criação de um programa por modulo que ascende e desliga as luzes do teclado, com o funcionamento dele mais testes serão feitos.
* Tive que instalar o modulo linux/config.h, mas não consegui instalá-lo.
* na pasta drivers/char não tinha nenhum *.c que estava descrito no código.
* utilizamos "aptitude search linux | grep source" para descobrir o kernel que devemos Instalar.
* Como não era possível achar as libs, instalamos o kernel-source-2.6.32 com o comando "aptitude install kernel-source-2.6.32" .
* Depois disso descompactamos com o comando "tar xvfj linux-source-2.6.32.tar.bz2" .
* Instalamos e depois la na pasta lib/modules/ mudamos o link do build para o novo kernel.
* Recompilar o Kernel copiamos o config do diretório /boot como .config para o diretório do novo kernel.
* Por falta de memória no HD da maquina virtual não foi possível terminar a recompilação do kernel.
4. Escrevendo no proc/
* Ao executar o arquivo procfs1.c do site “http://tldp.org/LDP/lkmpg/2.6/html/lkmpg.html#AEN237” ocorreram vários erros entre eles o ‘proc-root’ undeclared.
* Para resolver o problema acima foi tentado mudar o “create_proc_entry” para “proc_create” mas faltaram alguns argumentos. Depois no “remove_proc_entry” em um de seus (&proc_root) foi trocado por “NULL”.

## Apresentação do projeto Blink

    Para exemplificar o processo de criação de um módulo para o linux, primeiramente pensamos em criar um projeto funcional de comunicação com um hardware, o qual poderia futuramente ser adaptado para utilização como módulo.
    O hardware escolhido foi o teclado, pois nele existem alguns leds de indicação que podem ser utilizados como teste. Os leds do teclado podem ser controlados diretamente por portas de E/S. As portas de E/S são utilizadas pela CPU para comunicar com quase todos os controladores e periféricos. Cada porta tem um endereço no qual podemos realizar operações de escrita e leitura.
    Cada dispositivo dentro do computador tem uma faixa de portas de E/S alocadas que poderam ser utilizadas para comunicação. Para checar qual a faixa de portas que um certo dispositivo pode usar para comunicação, basta dar uma olhada no /proc/ioports. Analisando este arquivo, percebemos que o teclado usa a faixa de portas 0x60 – 0x6f. Para resolver nosso problema de controle dos leds do teclado, utilizaremos apenas a porta 0x60.

#### Comunicação

Para controlar os leds do teclado, devemos seguir o seguinte processo:
      * Escrever o comando 0xED na porta 0x60. Esse comando deve indicar ao teclado que em seguida ele receberá um padrão de configuração dos leds.
      * A controladora do teclado irá enviar pela porta 0x60 um comando de resposta 0xFA indicando que ele está pronto para receber a configuração.
      * O teclado espera um valor do tipo byte na porta 0x60 com a configuração desejada para os leds, que segue o seguinte padrão:
      * 000: todos desligados
      * 001: somente SCROLL-LOCK ativo
      * 010: somente NUM-LOCK ativo
      * 100: somente CAPS-LOCK ativo
      * 111: todos ligados
Para ter permissão de interação com o hardware, ou seja, permissão para executar operações de E/S em modo usuário, devemos utilisar a função ioperm ou a função iopl da API <sys/io.h>, o que as difere é que enquanto iopl adquire permissão para um conjunto de portas a ioperm adquire somente para uma. O programa deve ser compilado usando a opção -o para forçar a expansão das funções internas.

#### Código comentado
## O módulo Blink

No intuito de tornar o projeto blink em um módulo, o primeiro passo é descobrir quais são as APIs fornecidas pelo kernel do linux que poderão substituir as utilizadas pelo nosso blink.c. Tais como stdio.h, sys/io.h, unistd.h e stdlib.h. Para substituir a função ioperm, temos no kernel do linux a função request_region e para que seja possível sua utilização, temos que importar a API <linux/ioport.h> do kernel. Sua utilização é demonstrada e explicada no código comentado do módulo blink.

#### Código fonte
## Procedimento para testes

Para iniciar os testes é preciso que os arquivos blink.c e o Makefile estejam na mesma pasta. Então é executado o comando make, que compilará o blink.c gerando, dentre outros, o blink.ko, modulo o qual será instalado utilizando o comando insmod.
Uma vez instalado, podemos checar sua disponibilidade e tambem o Major number atribuido, utilizando o comando cat /proc/devices, agora que já sabemos desses dados, podemos criar o driver no /dev da seguinte maneira: mknod /dev/blink c MN 0 - isso irá criar o nosso driver comunicador com o Major Number MN atribuido. A partir dai basta fazer um pedido de execução para ativar a função device_open do módulo e ver o resultado. Um exemplo seria cat /dev/blink. Para remover o módulo basta fazer um rmmod blink.ko.