Como atribuir um driver USB ao dispositivo

30

Esta pergunta é dupla:

Primeiro, como você desanexa manualmente um driver de um dispositivo USB e conecta outro? Por exemplo, eu tenho um dispositivo que, quando conectado, usa automaticamente o driver de armazenamento USB.

saída usbview

Vendor Id: xxxx
Product Id: xxxx
...
    Number of Interfaces: 2
    Interface Number: 0
        Name: usb-storage
        Number of Endpoints: 2
        ...
    Interface Number: 1
        Name: (none)
        Number of Endpoints: 2
        ...

Não quero usar o driver de armazenamento USB, portanto, no meu aplicativo, uso a libusbbiblioteca para desanexar o driver de armazenamento USB e, em seguida, reivindico a interface. Em seguida, posso enviar dados para e de aplicativos em execução no meu dispositivo USB e no meu sistema Linux host.

Como você desanexa um driver manualmente fora de um aplicativo?


Segundo, como atribuo automaticamente o driver para conectar no plug-in do dispositivo? Atualmente, tenho uma configuração de regra do udev para definir as permissões do dispositivo automaticamente:

SUBSYSTEM=="usb", ATTR{idVendor}=="xxxx", MODE="0666"

Posso usar as regras do udev para atribuir drivers a interfaces específicas no dispositivo USB? Por exemplo, se eu queria que o módulo usbnet fosse usado automaticamente na interface 0 em vez do armazenamento usb, isso é possível no udev?

linsek
fonte
11
Se parte do problema está carregando o módulo correto, consulte Webcam em Angström
Gilles 'SO- stop
11
Você precisa de todo o módulo de armazenamento USB? porque, se não, você pode colocá-lo em uma lista negra e não carregaria nada.
Hanan N.
@Gilles, estou conseguindo carregar o LKM com sucesso. Minha pergunta é como anexar isso manual e automaticamente ao dispositivo?
Linsek 6/12/11
@ Hanan, atualmente não tenho uso para o módulo de armazenamento USB. Talvez eu precise da lista negra para anexar automaticamente o módulo correto, mas primeiro eu preciso saber como conectar o usbnet.
Linsek 6/12/11
11
O módulo @njozwiak usbnetnão será carregado automaticamente porque não possui informações sobre o hardware, o que pode ser usado. Tente encontrar o driver adequado e use, por exemplo modinfo kalmia,. Nas aliaslinhas, você verá a identificação do fornecedor xxxx e a identificação do produto aaaa como usb:vxxxxpyyyy. Ou você pode editar o arquivo /lib/modules/kernel_version/modules.usbmap e, para o seu HW, você pode excluir a linha, onde é para você o módulo USB HW de armazenamento ou alterar o usbstorage com o driver de rede adequado. Mas depois que depmod -aessa mudança desaparecer ...
Jan Marek

Respostas:

20

Na primeira parte da pergunta, procurei e não consegui encontrar uma maneira melhor de desanexar um driver USB do que o que você já está fazendo com o libusb.

Quanto à segunda parte da pergunta, o udev pode reagir ao carregamento do driver, mas não força um driver específico a ser atribuído a um dispositivo.

Todo driver no kernel do Linux é responsável por um ou mais dispositivos. O próprio driver escolhe quais dispositivos ele suporta. Isso é feito de forma programática, ou seja, verificando o fornecedor do dispositivo e o ID do produto, ou, se não estiverem disponíveis (por exemplo, um dispositivo antigo), executando algumas heurísticas de detecção automática e verificações de sanidade. Quando o motorista está confiante de que encontrou um dispositivo compatível, ele se liga a ele. Em resumo, muitas vezes você não pode forçar um driver específico a usar um dispositivo específico. Às vezes, no entanto, um driver de dispositivo é generoso com o que ele aceita e um dispositivo pode funcionar que ele não conhece. Sua milhagem varia! No passado, tive que adicionar manualmente identificações estranhas de dispositivos / fornecedores de PCI aos drivers que deveriam suportá-los, com sucesso misto e algumas falhas divertidas no kernel.

Agora, no caso de módulos, há uma etapa extra. O carregador de módulo é ativado pelo kernel quando um novo dispositivo é detectado. Ele passou uma string 'modalias', que identifica o dispositivo e se parece com isso com dispositivos USB:

usb:v046DpC221d0170dc00dsc00dp00ic03isc00ip00

Essa sequência contém a classe de dispositivo ( usb) e informações específicas de classe (fornecedor / dispositivo / número de série, classe de dispositivo, etc.). Cada driver do kernel contém uma linha como:

MODULE_ALIAS("usb:...")

O qual deve corresponder às usbalias (caracteres curinga são usados ​​para corresponder a vários dispositivos). Se modaliascorresponder àquele suportado pelo driver, esse driver será carregado (ou notificado sobre o novo dispositivo, se já estiver lá).

Você pode ver os dispositivos suportados (por modalidades) e seus módulos associados com

less /lib/modules/`uname -r`/modules.alias

Se você solicitar o driver do dispositivo de armazenamento USB, verá que ele possui alguns dispositivos específicos compatíveis com o fornecedor e o ID do dispositivo e também tentará oferecer suporte a qualquer dispositivo com a classe correta (armazenamento), independentemente do fornecedor / dispositivo .

Você pode influenciar isso usando os mecanismos de espaço do usuário no seu sistema operacional ( /etc/modprobe.d/no Debian e nos amigos). Você pode colocar módulos na lista negra ou especificar módulos a serem carregados pelas modalidades, assim como o modules.aliasarquivo (e usando a mesma sintaxe). depmod -airá regenerar os padrões do carregador de módulos.

No entanto, mesmo que você possa levar esse cavalo em particular à água, mas não pode fazê-lo beber. Se o driver não tiver suporte para o seu dispositivo, ele deve ignorá-lo.

Esta é a teoria no caso geral.

Na prática, e no caso do USB, vejo que seu dispositivo parece ter duas interfaces , das quais o armazenamento é um. O kernel será anexado à interface de armazenamento do dispositivo geral. Se a outra interface tiver a classe correta, o usbnetdriver poderá se conectar a ela. Sim, você pode ter vários drivers conectados ao mesmo dispositivo físico , porque um dispositivo USB exporta várias interfaces (por exemplo, meu teclado Logitech G15 exporta dois porque possui um dispositivo de teclado e uma tela LCD, cada um dos quais é tratado por um driver separado) .

O fato de a segunda interface do seu dispositivo USB não ser detectada é indicativo de falta de suporte no kernel. Seja qual for o caso, você pode listar as interfaces / pontos finais do dispositivo com detalhes excruciantes usando e lsusb -v | less, em seguida, role para baixo até o seu dispositivo específico (você pode limitar a saída por dispositivo: ID do fornecedor ou caminho USB, se desejar).

Observe: estou simplificando um pouco aqui em relação à estrutura lógica dos dispositivos USB. Culpe o consórcio USB. :)

Alexios
fonte
4
Já existe static struct usb_device_id id_table [] = { { USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, { }, }; MODULE_DEVICE_TABLE (usb, id_table);no código, é redundante com modalias?
Thomas
No meu caso, essas linhas são geradas automaticamente por alguma mágica do Makefile em qualquer lugar do driver. É por isso que adicionei três vezes as linhas para MODULE_ALIAS, mas ele nunca é listado. De qualquer forma obrigado pelo lsusb -v. com isso eu poderia verificar e encontrar a falha na minha ideia. Então, grep a fonte para um identificador conhecido e encontrei a matriz com as entradas que tive que manipular.
JackGrinningCat