Evitar que o kernel Linux configure a configuração do dispositivo USB

4

Estou tentando gravar um driver Linux para um dispositivo USB existente, com base na comunicação USB capturada.

O dispositivo tem várias configurações. Infelizmente, parece que o dispositivo não segue a especificação USB: somente a primeira solicitação de configuração de configuração funciona. O dispositivo bloqueia e, eventualmente, falha ao emitir uma segunda solicitação de configuração de configuração. A redefinição de USB ou a redefinição da configuração (configurando-a como 0) também não ajuda em nada.

Agora, parece que o Linux USB Core, por qualquer motivo, decide definir a configuração do dispositivo com o valor errado (apenas escolhe o primeiro), sem que eu tenha qualquer chance de entrar antes de fazer isso. Eu já tentei de um módulo do kernel e de um driver libusb do espaço do usuário.

Da leitura do código-fonte do kernel, parece que a função que seleciona a configuração é usb_choose_configuration() no driver genérico em / drivers / usb / core / generic.c . Eu posso ver que a função poderia ser pulada se usb_device_is_owned() retornasse true, mas não tenho idéia de como eu poderia influenciar o resultado dessa função.

Espero não ter que recompilar o kernel inteiro apenas para adicionar um driver USB.

Assim, aqui estão minhas perguntas:

  • Como eu poderia evitar que o sistema definisse uma configuração antes de entregar o controle ao meu driver?
  • Parece que nas versões recentes do kernel, o usbcore é um módulo interno que não pode ser substituído. Existe alguma outra maneira que eu poderia substituir a função usb_choose_configuration no driver genérico (que parece ser parte do usbcore)?
  • Como eu poderia ter o dispositivo de propriedade, de modo que usb_device_is_owned() retorne verdadeiro quando o dispositivo estiver conectado?
por FD_ 30.06.2018 / 21:10

1 resposta

1

Parece que existe uma maneira de impedir que o sistema tente definir a configuração do dispositivo e até funciona a partir do espaço do usuário. Eu tropecei no commit que adicionou essa funcionalidade ao kernel e, por sorte, também inclui uma amostra código.

Os programas de espaço do usuário podem declarar a propriedade de uma porta específica de um hub USB por meio do sistema de arquivos do dispositivo, resultando em usb_device_is_owned() retornando verdadeiro.

O truque parece ser:

unsigned int port = 2; // Just as an example
// Send request 24 of type 'U' (USB), which returns an unsigned int
unsigned int ioctl_id = _IOR('U', 24, unsigned int);
// fd is a file descriptor to the hub's file in the devfs
ioctl(fd, ioctl_id, &port); 

Informações sobre algumas solicitações do ioctl do subsistema USB estão descritas no documentação do kernel . A lista completa pode ser encontrada na fonte do kernel . As #defines são aqui .

Curiosamente, o sistema ainda envia Set Configuration Requests para as configurações 0 (reset configuration).

    
por 02.07.2018 / 16:03