Stall em USB e depuração de transferências de controle: bmRequestType, bRequest, wValue e wIndex

Como corrigir erros de stall em USB e falhas em transferências de controle. Aprenda a diagnosticar problemas no pacote de setup usando bmRequestType, bRequest, wValue, wIndex e evidência de requisição de descritor na depuração de firmware.

USB, transferência de controle, pacote de setup, stall USB, descritores USB, firmware, enumeração

As transferências de controle são a primeira conversa séria entre host e dispositivo. A enumeração depende delas. A configuração de classe depende delas. A inicialização específica do fabricante geralmente também. Quando uma transferência de controle falha, o usuário costuma ver apenas "dispositivo não reconhecido" ou "driver falhou", mas a evidência quase sempre está no pacote de setup.

Para o engenheiro de firmware, aprender a ler bmRequestType, bRequest, wValue, wIndex e wLength é um dos caminhos mais rápidos para trocar achismo por correção precisa.

O pacote de setup é o contrato da requisição

Um pacote de setup em USB diz ao dispositivo:

  • direção da transferência
  • tipo de requisição: standard, class, vendor ou reserved
  • recipient: device, interface, endpoint ou outro
  • código da requisição
  • campo de valor
  • campo de índice
  • comprimento esperado de dados

Se o firmware decodifica esses campos errado, ele pode devolver o descritor errado, travar uma requisição válida ou aceitar um comando inválido. Se o host envia uma requisição inesperada, a captura mostra isso também.

GET_DESCRIPTOR é o primeiro lugar para olhar

Durante a enumeração, o host envia requisições standard de descritor. Um padrão comum inclui:

  • requisição do descritor de dispositivo
  • requisição do descritor de configuração
  • requisição do descritor de string
  • requisição do descritor de relatório HID para dispositivos HID
  • requisição do descritor BOS em hosts mais novos

No pacote de setup, bRequest identifica o GET_DESCRIPTOR, enquanto wValue inclui o tipo de descritor e o índice. wIndex pode identificar o language ID para descritores de string ou a interface para descritores específicos de classe. wLength diz quantos bytes o host espera.

Quando o tamanho da resposta do descritor está errado, ou quando o firmware devolve menos bytes do que o host precisa, a enumeração pode falhar mais adiante de um jeito que parece não ter relação.

Erros de direção custam caro

Transferências de controle têm direção. Requisições device-to-host devolvem dados. Requisições host-to-device carregam dados ou configuram estado. Se o firmware trata uma leitura como escrita, ou devolve dados durante uma escrita, o host não vai adivinhar a intenção.

Fique de olho em:

  • direção IN sem data stage
  • direção OUT enquanto o firmware espera para enviar dados
  • status stage de comprimento zero ausente
  • STALL em uma requisição standard válida
  • requisição de classe tratada pela interface errada

A captura deve mostrar a requisição, o data stage e o status stage.

Requisições de classe e vendor precisam de contexto de interface

Depois da enumeração, drivers de classe enviam requisições específicas. CDC pode enviar requisições de line coding. HID pode requisitar descritores de relatório ou feature reports. Ferramentas vendor podem enviar comandos de inicialização. O mesmo valor de bRequest pode significar coisas diferentes conforme o tipo de requisição e o recipient.

Inspecione:

  • tipo da requisição
  • recipient
  • número de interface em wIndex
  • número do endpoint quando o recipient é endpoint
  • bytes do payload
  • resposta ou stall

Se um dispositivo composto tem várias interfaces, rotear a requisição para a interface errada é um bug frequente.

Como o Bus Scope ajuda

O Bus Scope foi feito para evidência USB. A depuração de transferências de controle exige os campos decodificados e os bytes brutos lado a lado. A melhor visualização deixa o engenheiro ler os campos semânticos e ainda validar os bytes exatos do pacote.

Uma sessão útil do Bus Scope para depurar transferências de controle deve responder:

  • qual pacote de setup falhou?
  • era standard, class ou vendor?
  • qual descritor ou interface foi solicitado?
  • o dispositivo devolveu o tamanho esperado?
  • o firmware gerou stall de propósito ou por engano?
  • o próximo passo da enumeração dependia dessa resposta?

O problema pode aparecer como "transferência de controle USB falhou", mas a correção quase sempre mora em um pacote de setup de cinco campos.