# Introdução

Este trabalho tem por objetivo apresentar um estudo de caso sobre o desenvolvimento de um driver para dispositivos LED USB para o Sistema Operacional Linux. O objeto de estudo deste trabalho é o driver desenvolvimento para um dispostivo chamado USB HID Visual Signal Indicator - trata-se basicamente de um dispositivo com uma série de LED's que podem acender nas cores vermelho, verde e azul.

# Informações gerais

* Autores:
** Adalberto Ribeiro Sampaio Junior
** Everton Lima Aleixo
** Pedro Henrique Pires de Castro
* Versão do kernel:
** Linux 2.6.31 kernel
* Identificação do driver analisado:
** LED USB Driver
* Lista de arquivos de códigos-fontes analisados:
** http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/drivers/usb/misc/usbled.c
* Outras informações relevantes:

# Inicialização das Estruturas

Para o dispositivo analisado, Led USB, surge a questão "que tipo de dispositivo ele é e que interface para o espaço do usuário podemos usar?" Um dispositivo de bloco não faz sentido, com um dispositivo que não precisa armazenar dados em um sistema de arquivos, mas um dispositivo de caractere pode ser usado. Se não usamos um driver de dispositivo de caractere, entretanto, major e minor number precisam ser reservados para isto. E quantos minor numbers precisam ser reservados para este driver? E se alguém quiser plugar 100 diferentes dispositivos USB Led no sistema? Para antecipar isto, nós também precisaríamos inventar algum caminho para chamar o driver para ligar e desligar diferentes cores individualmente. Tradicionalmente, isto pode ser feito usando diferentes comandos ioctl no driver de caractere, mas pode ser feito algo muito melhor do que criar um novo comando ioctl no kernel.
Como todo dispositivo USB cria seu próprio diretório na árvore sysfs, então porque não usar sysfs e criar três arquivos no diretório do dispositivo USB, azul, vermelho e verde? Isto pode permitir que muitos programas user-space, sejam em C ou shell script, mudem as cores no nosso dispositivo Led.
Para começar o nosso USB driver, nós precisamos providenciar um subsistema USB com cinco coisas:
** Um ponteiro para o módulo proprietário deste driver: isto permite que o USB core controlar o contador de referências do módulo corretamente.
** O nome do driver USB.
** Uma lista USB IDs que o driver poderá prover: esta tabela é usada pelo USB core para determinar que driver poderá ser relacionado com qual dispositivo;o script hot-plug user-space udado para carregar o driver automaticamente quando dispositivo é plugado no sistema.
** Uma função probe chamada pelo USB core quando um dispositivo é encontrado e relacionado com a tabela USB ID
** Uma função disconnect chamada quando o disposito é removido do sistema.
O driver recupera esta informação com o código a seguir:
A variável id_table é definida como:

# Reconhecimento ou detecção (probe)

A função led_probe é chamada quando o USB core tiver encontrado o dispositivo USB. Tudo que precisamos para fazer isto é inicializar o dispositivo e criar os três arquivos sysfs, na localização adequada. Isto é feito com o código a seguir:

# Registro do driver (register e deregister)

Quando o módulo é carregado, a estrutura led_driver precisa ser registrada com o USB core. Isto é realizado com uma chamda a função usb_register:
Do mesmo modo, quando o driver é descarregado do sistema, ele deve "desregistrar" ele mesmo do USB core:

# Comunicação

Quando os arquivos sysfs são lidos, nós queremos mostrar o valor atual que esta no LED; quando ele é escrito, nós queremos setar um LED especifico. Para fazer isto, a macro a seguir cria duas funções para cada cor do LED e declara um arquivo de atributo para o dispositivo sysfs:
Isto cria seis funções, show_blue, set_blue, show_red, set_red, show_gree and set_gree; e três estruturas de atributos, dev_attr_blue, dev_attr_red e dev_attr_green. Devido a natureza simples das callbacks do arquivo sysfs e o fato que nós precisamos fazer a mesma coisa para cada valor diferente (azul, vermelho e verde), uma macro foi usada para reduzir a digitação. Isto é uma ocorrência comum para funções de arquivos sysfs;
Então para habilitar o LED vermelho, um usuário escreve um 1 para o arquivo 1 no sysfs, que chama a função set_red no driver, que chama a função change_color como:
Esta função inicia setando todos os bits na variavel color pra 1. Então se algum LED estão ligados, ela desliga somente o do bit especificado. Nós então enviamos uma messagem de controle USB para o despositivo para escrever este valor de cor no dispositivo.
Parece estranho que somente uma pequena váriavel de buffer, que tem somente 8 bytes de comprimento, é criada com a chamada pra o kmalloc. Porque não simplesmente declara ela na pilha e deixa o overhead de alocação dinâmica alocar e destrui-la? Isto é feito porque algumas arquiteturas que executam Linux não podem enviar dados USB criados na pilha do kernel, então todos os dados que estão sendo mandados para o dispositivo USB devem ser criados dinamicamente.

# Finalização

A função led_disconnect é igualmente simples, como nós precisamos somente liberar nossa memória alocada e remover os arquivos sysfs:

# Considerações finais

* Informações gerais do driver
* Conclusões
* Mapa conceitual sobre o driver estudado;

# Bibliografia/Referências

http://www.linuxjournal.com/article/7353?page=0,0