![]() |
Traduzido do artigo original Java and USB by Jeff Friesen - 07/06/2006( http://today.java.net/pub/a/today/2006/07/06/java-and-usb.html?page=1
) por
Marcos Moran. |
Embora o Universal Serial Bus (USB) seja parte integrante de
muitos computadores, a linguagem Java não oferece
(oficialmente) suporte ao protocolo USB.
Para fazer seu programa em Java interagir com um dispositivo USB
qualquer, é necessário usar uma API Java/USB fornecida
por terceiros ou escrever sua própria API.
Este artigo introduz duas APIs de terceiros e minha própria
API (que possibilita uma interação parcial com o
protocolo USB).
Antes de apresentar as APIs, este artigo explora alguns
fundamentos do protocolo USB.
Então é apresentada a API JSR-80 (candidata a se
tornar o suporte USB oficial da linguagem Java) e a API jUSB (a
concorrente). Em seguida o artigo apresenta minha própria API,
que funciona apenas no ambiente Windows. O artigo termina ponderando
se a linguagem Java deve ou não oferecer oficialmente suporte
ao USB.
Desenvolvi e testei os códigos que aparecem nesse artigo
com o kit de desenvolvimento da Sun Microsystems J2SE5.0, e Borland
C++ 5.5.1, Windows 98 SE e Windows ME foram os sistemas operacionais
usados.
USB em poucas palavras
USB é um protocolo padrão de comunicação
serial usado para conectar dispositivos em um computador, em um vídeo
game, em uma televisão, etc. Esse padrão tem vantagens
sobre a arquitetura usada anteriormente (placas de expansão,
I/O ports, interrupções e drivers de dispositivos),
para conectar dispositivos nos computadores pessoais (PCs). Essas
vantagens são:
- O barramento serial, em conjunto do “plug-and-play”, elimina conflitos de portas (I/O) e interrupções que freqüentemente surgiam, quando um novo dispositivo era agregado ao computador.
- Não é necessário abrir o computador e inserir placas de expansão no barramento do sistema. Os dispositivos são ligados ao barramento através de conectores externos.
- Os dispositivos podem ser conectados e desconectados sem ter de desligar ou reiniciar o PC. Isto é conhecido como “hot swapping”.
Compaq, Intel, Microsoft e NEC começaram a trabalhar no padrão USB em 1994. Em Janeiro de 1996, eles disponibilizaram a versão 1.0. Depois de algumas revisões, foi disponibilizada a versão 1.1 em Setembro de 1998. E em Abril de 2000, depois que Hewlett-Packard, Lucent e Philips entraram no grupo, foi distribuída a versão 2.0.
USB 1.1 foi a primeira versão amplamente implementada do padrão USB. É caracterizada por duas velocidades na transferência dos dados (taxa de transferência): full speed (12 megabits por segundo) e low speed (1.5 megabits por segundo). Essa versão (1.1) está sendo esquecida devido ao surgimento da versão 2.0. Na versão 2.0 é acrescentada uma terceira taxa de transferência: high speed (480 megabits por segundo).
Para compreender completamente o padrão USB você terá de consultar a especificação USB 1.1 e a especificação USB (2.0). Para apenas entender esse artigo, no entanto, você só precisará entender alguns fundamentos, começando com uma visão geral de host controller, hubs e funcões.
Host controller, Hubs e Funções
O protocolo USB é implementado em termos de software
(drivers, que eu não abordo neste artigo) e hardware.
O hardware é dividido em host controllers, hubs e funções:
- Host controllers conectam uma árvore de dispositivos USB em um host (computador, console (vídeo game), etc). Vários host controllers podem estar presentes. Cada host controller é a raiz de uma árvore de dispositivos.
- Um hub é um dispositivo com múltiplas portas, nas quais são ligados outros hubs ou funções. O hub principal está integrado ao host. Todos os outros hubs são chamados de hubs externos.
- Uma função é um dispositivo que provê uma certa capacidade ao host. São ligadas ao hub (principal ou externo). Mouses, teclados, câmeras, scanners e impressoras são alguns exemplos.
O hardware é organizado numa topologia estrela-fileira onde o centro de cada estrela é um
hub: tanto o hub central quanto um hub externo estão no centro
dos hubs e/ou funções nele conectados.
A figura 1 esclarece esta topologia:
Figura1. Três hubs externos
(hub1/hub2/hub3 ou hub1/hub2/hub4) ligados ao hub principal.
Configurações, interfaces e
endpoints
Uma função tem uma ou mais
configurações que controlam o seu comportamento.
Configurações podem definir quanta energia é
consumida, se o computador pode ser ativado remotamente ou não,
e muito mais.
Um trackball pode ser configurado como um
mouse ou como um joystick, esse é um exemplo de função
com múltiplas configurações. Outro exemplo são
os dispositivos de comunicação RDSI (Rede de Serviços
Digitais Integrada) que oferecem um canal de 128Kb ou dois canais de
56Kb.
Cada configuração contém
uma ou mais interfaces que especificam como o software acessa o
hardware. Interfaces freqüentemente têm ajustes
alternativos para corresponderem a diferentes exigências de
largura de banda.
Cada interface contém endpoints
que podem ser a fonte ou o destino dos dados transferidos. Cada
endpoint suporta transferência de dados numa única
direção e tem um identificador numérico único.
A figura 2 mostra a relação
entre endpoints, interfaces e configuração

Figura 2. O relacionamento entre configurações, interfaces e endpoints.
Nota:
os drivers da Microsoft tendem a trabalhar apenas com a primeira
configuração. O resultado é que funções
multi-configuráveis são raras e desencorajadas pela Microsoft.
Modelo de fluxo de dados
O USB suporta o fluxo de dados entre aplicações rodando no host e dispositivos físicos anexados. Esse conceito pode ser entendido observando-se o modelo de fluxo de dados USB, apresentado na figura 3:

Figura 3. O modelo de fluxo de dados USB dividido em três camadas.
Na verdade a transferência dos dados se dá na camada mais baixa (camada barramento). Essa camada consiste de hubs e cabos (e conectores) e conectam o host ao dispositivo.
No modelo, fisicamente, os dados fluem para cima e para baixo de ambos os lados.
Virtualmente os dados fluem na horizontal, de um lado ao outro nas duas primeiras camadas através de canais lógicos (pipes) que ligam aplicativos do host aos endpoints do dispositivo.
Os canais podem ser divididos em duas categorias: canais de mensagem e canais de fluxo. Canais de mensagem transferem dados com alguma estrutura USB (cada pacote de dados carrega informações significativas ao software USB), canais de fluxo transferem dados sem nenhuma estrutura USB.
A camada dispositivo tem uma visão lógica e controla o dispositivo físico. Ela usa um canal de mensagem especial
chamado Canal de Controle Padrão para ler a configuração dos dados de entrada endpoint() e controlar a saída dos dados para a saída endpoint() .
Estes endpoints (endpoint 0) estão sempre presente.
A camada de função tem uma visão da função do dispositivo físico. Esta camada usa canais de dados para
captar e enviar dados para a função.
Tipos de transferência
Um canal transfere dados de acordo com o tipo de transferência do endpoint, o tipo de transferência gerencia a quantidade de dados que é transferida numa transação (parte de uma transferência), se a transferência foi perdida ou não e outros fatores:
- Transferências de volumes (bulk transfers) são usadas para transferir arquivos ou qualquer coisa que envolva grandes blocos de dados sem estrutura. Essas transferências garantem que todos os dados serão entregues.
- Transferências de controles (control transfers) são usadas para controlar o dispositivo físico. Essas transferências enviam e recebem dados estruturados como comandos e sinais de estado.
- Transferências isocrônicas (isochronous transfers) são usadas para transferir áudio e vídeo em tempo real e outros tipos de dados sem estrutura a uma velocidade garantida. No entanto, existe a possibilidade de perda de dados.
- Transferências de interrupções (interrupt transfers) são usadas por mouses, joysticks, teclados e outros dispositivos físicos que precisam de um tempo de resposta garantido. Transferências de interrupções são similares às transferências de volumes.
Nota:
ainda que eu não tenha focado a transferência de
dados nesse artigo, você precisa estar a par desses tipos de
transferência quando for trabalhar com as APIs JSR 80 e jUSB.
Descritores
Dispositivos USB apresentam estruturas de dados conhecidas como descritores. Essas
estruturas permitem que uma função (ou funções)
do dispositivo identifique-se (ou identifiquem-se) ao software
rodando no host:
- Descritores de dispositivos descrevem um dispositivo como um todo.
- Descritores qualificadores de dispositivos são usados em dispositivos USB2.0.
- Descritores de configuração descrevem configurações de um dispositivo.
- Descritores de configuração em outras velocidades são usados em dispositivos USB2.0.
- Descritores de interface descrevem configurações de interfaces.
- Descritores de endpoint descrevem endpoints de interfaces.
- Descritores “String” contém uma descrição (humanamente compreensível) de um dispositivo, de uma configuração, de uma interface ou de um endpoint.
Mais tarde nesse artigo,apresentarei um exemplo de enumeração de dispositivos onde o código em C++ acessa um dispositivo e descritores “string” durante o processo de enumeração.
Classes de dispositivos
Dispositivos
USB pertencem à classes de dispositivos, que definem um
esperado comportamento em termos de dispositivo e descritores de
interface. Um driver de uma classe de dispositivos pode ser usado por
qualquer dispositivo que pertença à classe.
Sistemas
operacionais geralmente oferecem drivers genéricos para
todas
as classes de dispositivos, para suportar todos os dispositivos USB.
Quando um dispositivo é conectado na USB, o identificador de
classe do dispositivo é lido num determinado descritor e
usado
para carregar o driver apropriado.
A USB-IF (USB Implementers Forum)
padroniza identificadores de classes de dispositivo. Como exemplo,
temos: 1 (classe áudio, uma placa de som por exemplo), 3
(classe dispositivo de interface com o usuário, como
teclados
e mouses), 8 (classe dispositivo de armazenamento em massa, flash
drivers e HDs portáveis), 9 (classe hubs).
Os identificadores 0 e 255 são reservados.
Se
a classe pertence ao dispositivo como um todo, o identificador
é
atribuído ao campo de 8 bits bDeviceClass (descritor do
dispositivo). Se a classe é para uma única
interface o
identificador é atribuído ao campo de 8 bits
bInterfaceClass (é atribuído 0 (zero) ao campo
bDeviceClass).
JSR-80
Em
1999, Dan Streetman da IBM começou o projeto de uma API
Java/USB para permitir que programas em Java interagissem com a USB.
Em 2001, através da Java Community Process (JCP) esse
projeto
foi aceito como candidato à extensão
padrão para
a linguagem Java. A JCP identificou esse projeto como Java
Especification Request (JSR) 80,você
pode observar o estado atual da requisição JSR-80
visitando a página JSR-80 (Java USB API) no site da JCP.
A
página oficial de desenvolvimento com esta API é
JSR80
– javax.usb. Esse site fornece links para a
licença pública
da JSR-80, perguntas freqüentes (FAQs), as
implementações
da API no compartimento de arquivos (CVS repository), e a
documentação da API. O compartimento de arquivos
fornece o arquivo jsr80.jar (o principal pacote da
implementação
javax.usb), jsr80_ri.jar (implementação de
referência,
independente de plataforma) e as implementações
para
Linux/Windows.
A
implementação em Linux foi certificada com o kit
de
testes da Sun. Você encontrará os
códigos fontes
em C e Java dessa implementação e o arquivo
javax.usb.properties específico para Linux, no
diretório
javax-usb-ri-linux do compartimento de arquivos. Você
terá
de compilar a implementação a partir do
código
fonte (assumindo que seu sistema operacional seja Linux).
A
implementação
pré-alfa para Windows não é
certificada e requer
um kernel driver. Os códigos fontes em C e Java dessa
implementação e o arquivo javax.usb.properties
específico para Windows podem ser encontrados no
diretório
javax-usb-ri-windows compartimento de arquivos. Se o seu sistema
operacional é Windows você pode compilar a
implementação
a partir do código fonte (possivelmente depois de algumas
alterações), mas você precisa fornecer
o kernel
driver.
Você
pôde preferir a implementação alfa para
Windows.
Esta implementação não certificada se
localiza no
diretório javax-usb-libusb do
repositório. Junto com os arquivos de desenvolvimento,
você terá que instalar
a versão Windows da libusb. Visite a página do
projeto libusb e
a página do projeto libusb-win32 para conhecer e
obter a versão de Windows da libsus.
O
documento
de especificação da API JSR-80 em pdf, localizada
no
repositório como jsr80.pdf, descreve a arquitetura dessa
API.
Esse
documento revela que a classe USBHostManager é o ponto
inicial
da API. Essa classe permite que você obtenha uma
instância
específica ao sistema operacional (baseada nas
informações
do arquivo javax.usb.properties) da interface USBServices, a partir
daí é possível obter o hub principal
virtual:
|
UsbServices
services =
UsbHostManager.getUsbServices (); UsbHub vroothub = services.getRootUsbHub (); |
O hub
principal
virtual, obtido com o método getRootUsbHub() da classe
UsbServices, permite acesso a todos os
host controller disponíveis
(e seus hubs principais). Os métodos public boolean
isRootUsbHub(), public
byte getNumberOfPorts() e public List
getUsbPorts() são úteis quando se estiver
verificando, enumerando e obtendo os hubs principais.
Eu
não
entrarei muito a fundo na JSR-80, porque uma boa visão geral
da
API é apresentada em “Acesso a Dispositivos USB
por
Aplicações em Java”. Essa
visão geral inclui
códigos com exemplos de enumeração de
dispositivos e transferência de dados, os quais demonstram a
obtenção dos tipos de transferência de
endpoints,
direção e canais conectados. Ao invés
disso, eu
identifiquei quatro dicas que você precisará
conhecer
para instalar a JSR-80 com sucesso no seu sistema operacional:
- Adicione o arquivo jsr80.jar ao seu classpath. Seus programas em Java interagem com as classes e interfaces desse arquivo. Você pode encontrar o arquivo jsr80.jar na pasta lib do diretório javax-usb-libusb, dentro do compartimento de arquivos.
- Adicione o arquivo jsr80_ri.jar ao seu classpath. Quase tudo da API javax.usb é implementada nesse arquivo .jar. Você também pode encontrar o arquivo jsr80_ri.jar na pasta lib do diretório javax-usb-libusb, dentro do compartimento de arquivos.
- Instale a libusb tanto na implementação Windows quanto na implementação Linux. Para Windows, não se esqueça de instalar a versão Windows da libusb. Além disso, você precisa adicionar o arquivo jsr80_windows.jar ao seu classpath quando for instalar a implementação Windows da libusb. Este arquivo .jar esta no diretório lib (citado anteriormente).
- Adicione o arquivo javax.usb.properties apropriado (tanto na versão Windows quanto na versão Linux da libusb) ao seu classpath. Esse arquivo contém a propriedade javax.usb.services, que identifica o nome completo de uma classe que implementa a interface javax.usb.UsbServices. Essa classe é o ponto de entrada para as implementações Linux e Windows.
O
diretório
lib contém também o arquivo log4j.properties,
junto dos
arquivos commons_logging.jar e log4j.jar. Acredito que você
pode evitar ter de adicionar esses arquivos ao seu classpath
modificando o arquivo
javax.usb.properties.
jUSB
“Mojo
Jojo” e
David Brownel começaram o projeto de uma API Java/USB rival
em
junho de 2000: a jUSB. Eles desenvolveram uma versão para
Linux, que está disponível na página
do projeto.
Para sua tese, Mike Stahl criou uma versão para Windows;
visite a página do projeto jUSB: API Java/USB para Windows
para obter essa versão. jUBS é
distribuída sob a
licença LGPL (Lesser GNU Public License).
Enquanto
pesquisava a jUSB, eu mantive o foco na versão Windows (de
Mike Stahl). A partir da página da jUSB do Mike, eu baixei
dois arquivos: JavaUSB.zip e JavaUSBComplete.zip. O primeiro arquivo
contém os códigos fontes Java dos pacotes da
jUSB, a
dll jUSB e o kernel driver (juntamente com
informações
e arquivos de registro) para Windows XP e Windows 2000. O segundo
arquivo inclui o código fonte da dll e do driver.
Eu baixei
também
a tese “API Java/USB para Windows” de Mike Stahl
(um pdf de 2.2
MB). Este arquivo pdf traz uma introdução a USB e
revela em detalhes como Mike Stahl implementou o pacote usb.windows
da jUSB para Windows XP e Windows 2000. Esse documento é
leitura obrigatória para qualquer um que queira implementar
uma API Java/USB que acesse a arquitetura USB do Windows.
De acordo
com a
tese de Mike, o pacote usb.core da jUSB contém uma classe
HostFactory onde o método public static Host getHost()
é
o ponto de entrada na jUSB. Este método retorna um objeto
Host
que monitora todas as árvores de dispositivos de uma
máquina.
Ao invés de se aprofundar na jUSB, recomendo
explorar
informações em “Acesso a Dispositivos
USB por
Aplicações em Java”.
Crie
sua própria
API Java/USB
Ainda que
você
possa usar as APIs JSR80 e jUSB para dar aos seus programas a
capacidade de interagir com a USB, você pode optar por criar
algo diferente. Para ajudar você nessa tarefa eu apresento
minha própria API. Essa API é limitada
à
enumeração de dispositivos. Além
disso, o código
nativo escrito em C++ e usado pela Java Native Interface (JNI) limita
a API ao Windows 98, Windows ME e (ainda que não tenha sido
testado) ao Windows 2000.
Construí
o código C++ da API usando o compilador Borland C++ 5.5.1.
Você precisará de uma cópia desse
compilador (que
é free) se planeja modificar o código.
Forneço
uma dll pré-compilada nesse artigo (veja links e downloads).
Clique no link da tabela de downloads na página C++ Builder
Downloads - Compilador Borland C++ 5.5.1 para baixar o compilador.
No artigo
"Java
Tech: Aquisição de Imagens com TWAIN e SANE,
Parte 1",
que eu escrevi para o java.net, faz uma breve
introdução
do Borland C++ 5.5.1. Para uma introdução mais
significativa, de uma olhada em “Familiarizando-se com o
Borland
C++ 5.5.1” no meu artigo “Construir
Proteções de
tela com a Biblioteca Padrão de
Proteções de
Tela no Borland C++ 5.5.1”.
JavaUSB
Minha API
JavaUSB
consiste de cinco classes (que não estão num
pacote):
JavaUSB, HCInfo, Device, Hub, e Function. Considere colocar essas
classes em seus próprios pacotes. A classe JavaUSB serve
como
ponto de entrada nessa API. Ela provê três
métodos
para carregar e acessar as funções da dll:
- public static boolean init() inicializa a JavaUSB carregando a javausb.dll. Retorna true se a dll for carregada com sucesso. Se um UnsatisfiedLinkError ocorrer, retorna false. Você precisa acionar esse método antes de chamar os outros dois.
- public static native HCInfo getHostControllerInfo(int index) retorna um objeto HCInfo que fornece o nome do “index-gésimo” host controller e o nome do hub principal. Os índices começam no zero; o método retorna null se não houver nenhum host controller associado com o parâmetro index.
- public static native Device [ ] getAttachedDevices(String hubName) retorna um vetor (considere a possibilidade desse vetor ter tamanho zero) de todos os dispositivos anexados ao hub identificado pelo parâmetro hubName; o método retorna null caso não consiga completar a tarefa.
Para manter a API simples eu não providenciei uma classe de
exceções (exceptions) e nem fiz os métodos
nativos ativarem instancias dessa classe caso alguma coisa saísse errado. No entanto,
esses métodos podem disparar
erros relatados pela JNI
("classfile not found," por exemplo). Ao invés
disso, um problema revelado,
quando um método nativo retorna um
valor null. Considerar aumentado
esses métodos para ançarem
exceções apropriadas.
HCInfo
descreve
informações do host controller retornadas pelo
método
getHostControllerInfo(). Essa informação
é
armazenada em dois campos do tipo string: name contém o nome
do host controller e hoothubname contém o nome do hub
principal integrado ao host controller. Para começar a
enumeração de uma árvore de
dispositivos, passe
o campo hoothubname como parâmetro para o método
getAttachedDevices().
Device
descreve um
hub ou função anexada ao hub. Essa classe
contém
três campos do tipo string que são comuns tanto a
hubs
quanto a funções: manufacturer, identifica o
fabricante
do dispositivo, product, identifica o dispositivo como um produto e
serialNumber, identifica o número serial do dispositivo.
Esses
campos podem ser nulos.
Device
também
é uma superclasse abstrata para as classes hub e function. A
classe hub apresenta um único campo string, hubName, que
nomeia um hub externo. No entanto, function é uma classe
vazia. No futuro, planejo expandir as classes hub e function
com
campos e funções que são
únicos à
essas classes.
Para
demonstrar o
quanto é fácil usar os três
métodos da
JavaUSB e as outras classes, criei o programa TestJavaUSB. O
código fonte deste aplicativo emprega quatro das cinco
classes
(não ha porquê usar a classe Function
até que ela
tenha sido mais completamente desenvolvida) para enumerar cada host
controller e a árvore de dispositivos do hub principal. O
código fonte do aplicativo é apresentado abaixo.
|
// TestJavaUSB.java public class TestJavaUSB { public static void main (String [] args) { // Lembre-se de inicializar a biblioteca JavaUSB if (!JavaUSB.init ()) { System.err.println ("Unable to " + "initialize JavaUSB"); return; } // Enumera todos os host controllers, escrevendo seus nomes e os nomes dos //hubs principais ligados a eles. Para cada hub principal, enumera a árvore de //dispositivos. for (int i = 0; ; i++) { HCInfo hcinfo = JavaUSB.getHostControllerInfo (i); if (hcinfo == null) break; System.out.println ("\nHost " + "controller name = " + hcinfo.name); System.out.println ("Root hub " + "name = " + hcinfo.rootHubName); enumerate (hcinfo.rootHubName, 1); } } public static void enumerate (String hubname, int depth) { Device [] devices = JavaUSB.getAttachedDevices (hubname); if (devices == null) return; for (int i = 0; i < devices.length; i++) { System.out.println (); for (int j = 0; j < depth; j++) System.out.print (' '); System.out.println (devices [i]); for (int j = 0; j < depth; j++) System.out.print (' '); System.out.printf ("Manufacturer = %s\n", devices [i].manufacturer); for (int j = 0; j < depth; j++) System.out.print (' '); System.out.printf ("Product = %s\n", devices [i].product); for (int j = 0; j < depth; j++) System.out.print (' '); System.out.printf ("Serial number " + "= %s\n", devices [i].serialNumber); if (devices [i].isHub ()) enumerate (((Hub) devices [i]). hubName, depth+1); } } } |
Executando o comando java TestJavaUSB no sistema operacional Windows 98 SE foi gerada a seguinte saída:
|
Host
controller name = USB\0000 Root hub name = \\.\0000000000000007#{f18a0e88-c30c-11d0-8815-00a0c906bed8} Function Manufacturer = Microsoft Product = Microsoft IntelliMouse® Explorer Serial number = null |
A
saída
abaixo apareceu quando eu executei java TestJavaUSB no sistema
operacional Windows ME:
|
Host
controller name = USB\0002< Root hub name = \\.\0000000000000005#{f18a0e88-c30c-11d0-8815-00a0c906bed8}
|
Esse
código
fonte levanta uma questão interessante: o que acontece se um
host controller é adicionado ou removido durante a
enumeração?
Quando é adicionado, eu presumo que o sistema operacional
vai
adicionar a entrada do host controller à alguma estrutura de
entradas e a enumeração não
será afetada.
No caso de remoção, ou o host controller
já
teria sido enumerado ou o método nativo retornaria null
(dependendo de qual parte do código está sendo
executada no momento).
Atrás das cortinas
A API
JavaUSB
funciona em Windows 98 SE e Windows ME. Apesar de não ter
testado essa API no Windows 2000 (não tenho acesso a esse
SO)
eu acredito que ela também funcione corretamente. Se
você
precisar modificar o arquivo javausb.cpp para suportar outra
versão
do Windows (ou um outro sistema operacional) você
ficará
interessado nos seguintes detalhes do arquivo javausb.cpp:
- Vários Kits de Desenvolvimento de Drivers para Windows (DDKs) definem constantes, macros e tipos para se trabalhar com a USB. Ao invés de exigir a instalação do DDK (indisponível para Windows 98 SE) eu criei o arquivo de cabeçalho usb.h, com constantes, macros, tipos relevantes e muitos comentários para ser incluído no javausb.cpp.
- O código no arquivo javausb.cpp usa quatro funções da API Win32 para interagir com a USB do Windows: CreateFile() (abre um host controller ou dispositivo no hub), DeviceIoControl() (interage com um dispositivo), WideCharToMultiByte() (converte caracteres Unicode to ANSI 8-bit) e CloseHandle() (fecha o dispositivo).
- Windows 98 SE, Windows ME e Windows 2000 usam a sintaxe \\.\HCDx (x é um inteiro que começa em zero) para identificar um host controller. O nome do primeiro host controller é \\.\HCD0, o nome do segundo host controller é \\.\HCD1 e assim por diante. O nome do dispositivo é passado para a função CreateFile() para abrir o host controller.
Para informações
sobre a construção da javausb.dll com Borlando
C++
5.5.1, examine os artigos sugeridos anteriormente. Leia
também
os comentários no arquivo makedll.bat (junto ao código-exemplo deste
artigo).
Java deveria oferecer oficialmente suporte a USB?
Enquanto
pesquisava para esse artigo, encontrei várias
discussões
sobre se Java deveria ou não oferecer oficialmente suporte a
USB. Vários indivíduos querem que a Sun introduza
o
suporte USB no Java, outros não acham que seja uma boa
idéia
que Java ofereça oficialmente suporte a USB. Abaixo
estão
duas reações típicas:
- Um participante do tópico “O que você gostaria de fazer com o Java e não pode” do fórum JavaLobby quer o suporte oficial a USB: “Falando sério, Sun se você está lendo isso, atenção! Isso (javax.comm) é muito ruim. E enquanto vocês estão consertando o IO da porta serial, que tal irem fazendo a USB e o FireWire trabalharem?”
- De acordo com um participante do tópico “Suporte USB (especialmente para Windows)” no fórum Java.net, Java não deveria oferecer suporte oficial a USB porque “isto é parecido com ter acesso direto à camada física em placas de rede ou acessar diretamente o barramento SCSI”. Além do mais: “Você não precisa acessar diretamente a USB para usar leitores de cartão ou para usar dispositivos de armazenamento em massa (isto é manipulado pelo SO).Você deveria ser capaz de simplesmente criar um arquivo numa seção apropriada do sistema de arquivos, escrever nele e o SO deveria cuidar do resto”.
Se o Java
oficializar o suporte a USB, esse suporte deveria estar presente em
todos os SOs que suportam Java
(alguns Sos ainda não oferecem
suporte a USB). Acima de tudo, Java é uma tecnologia
independente de
plataforma. Mas o que acontece se um SO que suporta
Java suportar FireWire (ou alguma outra tecnologia) ao invés
de USB?
Alguns
desenvolvedores tem expressado o desejo de ver APIs na linguagem Java
dando suporte oficial a FireWire e BlueTooth (que eu imagino ser uma
espécie de USB sem fio) além da USB. Embora a API
JSR-82 (API Java para BlueTooth) esteja funcionando (aparentemente
não existe API Java para FireWire) faz sentido manter
separadas as APIs USB e BlueTooth ?
USB,
FireWire e
BlueTooth são três tecnologias de
comunicação
com dispositivos. Java tem uma longa história de
abstração
sobre tecnologias similares, talvez seja possível planejar
uma
única API serial que abstraia essas e outras tecnologias
similares que estão por vir. Talvez essa deveria ser a
maneira
de oferecer oficialmente suporte a essas tecnologias.
Conclusão
Java,
oficialmente, não oferece suporte a USB, portanto
você
precisa trabalhar com a JSR-80, jUSB ou alguma outra API Java/USB de
terceiros (ou criar sua própria API) para permitir que seus
programas Java interajam com a USB. Se você planeja criar sua
própria API no ambiente Windows, a API JavaUSB pode ajudar
você com a parte de enumeração de
dispositivos. Deliberadamente evitei o suporte à
transferência de
dados por duas razões:
- Não quero dar suporte a transferência de dados até que o código de enumeração de dispositivos esteja completo. De acordo com um artigo da Microsoft eu preciso usar uma técnica baseada em identificadores únicos globais (Globally Unique Identifiers - GUIDs) para ter certeza que host controllers USB2.0 são enumerados no Windows 2000 (e possivelmente no Windows 98 SE e Windows ME).
- Preciso desenvolver um kernel driver para suportar transferência de dados no Windows. Embora eu tenha recebido recentemente uma cópia de um dos livros mais considerados de Walter Oney: “Programando o Modelo de Drivers no Microsoft Windows” (Microsoft Press, 2003) que explora a criação de kernel drivers, vai levar tempo para absorver completamente o conteúdo do livro. Se você estiver interessado no modelo de driver do Microsoft Windows, eu recomendo esse livro.
Meu trabalho com
JavaUSB tem mostrado que não é fácil
desenvolver
uma API Java/USB. Essa API tem que ser
útil e não deve
expor os detalhes de baixo-nível do hardware. Tem
também que ser
abstrata o
suficiente para se tornar portável. Porque escolhi
como alvo
os sistemas operacionais Windows 98 SE/ME/2000, deixo você com a
seguinte tarefa: tente passar a JavaUSB
para o Linux ou algum outro SO.
Links e
Downloads
(Obs: todo o material em inglês)
- Código-exemplo deste artigo
- “Acesso a dispositivos USB a partir de aplicativos Java”
- “Construir Proteções de tela com a Biblioteca Padrão de Proteções de Tela no Borland C++ 5.5.1”
- C++ Builder Downloads: compilador Borland C++ 5.5.1
- Página da JCP para a JSR-80 (API Java/USB)
- Página da JCP para a JSR-82 (API Java/BlueTooth)
- JSR-80: javax.usb
- “Java Tech: Aquisição de Imagens com TWAIN e SANE, Parte 1”
- Documentação da API javax.usb
- jUSB: página do projeto Java USB
- jUSB: página do projeto da API jUSB para Windows
- Tópico do fórum java.net: suporte USB (especialmente para Windows)
- Página do projeto libusb
- Página do projeto libusb-win32
- “A nova API Java USB”
- “O programa exemplo USBView.exe não enumera dispositivos em computadores com sistemas operacionais anteriores ao Windows XP com Service Pack 1”
- Especificação USB1.1 (.zip, 1.7MB)
- Especificação USB2.0 (.zip, 7.86MB)
- Universal Serial Bus (Wikipedia)
- “O que você gostaria de fazer com o Java e não pode?”
Jeff Friesen é um desenvolvedor de software freelance e educador, especializando-se na tecnologia Java. Verifique seu site javajeff.mb.ca.
