‮Сдвиг по фазе (kincajou) wrote,
‮Сдвиг по фазе
kincajou

Categories:

worklog: USB.. ненависти псто

Итак, добрался таки до Управления по Основному, бл, Каналу, на.

В простонародье сие больше известно как Control Transfers, использует оно SETUP Transaction.
Что пишут знатоки (почему-то указавшие, что размер дескриптора устройства равен 12 байт, хотя он на самом деле 18 байт везде и всегда):
Общий процесс энумерации под операционной системой Windows включает в себя следующие шаги:

1. Хост или хаб детектирует подключение нового устройства с помощью pull-up резисторов, которое устройство подключает к паре сигнальных проводов данных (D+ и D-). Хост делает задержку как минимум 100 мс, что позволяет вставить коннектор полностью и застабилизировать питание устройства.
2. Хост выдает на шину сброс, который выводит устройство в состояние по умолчанию. Устройство может теперь ответить на заданный по умолчанию нулевой адрес.
3. Хост MS Windows запрашивает первые 64 байта дескриптора устройства (Device Descriptor).
4. После приема первых 8 байт дескриптора устройства, хост немедленно выдает новый сброс шины.
5. Теперь хост выдает команду Set Address, чем переводит устройство в адресуемое состояние.
6. Хост запрашивает все 18 байт дескриптора устройства.
7. Затем он запрашивает 9 байт дескриптора конфигурации (Configuration Descriptor), чтобы определить полный её размер.
8. Хост запрашивает 255 байт дескриптора конфигурации.
9. Хост запрашивает все строковые дескрипторы (String Descriptors), если они имеются.


Видите? сброс, запрос якобы 64 байт, но сброс после приёма восьми. Видите, да? Написано!

А я вижу вот что:
IRQ: USB RESET
IRQ: CTR, EP0R=EA60:
 CTR_RX DTOG_RX STAT_RX SETUP   TYPE_EP EP_KIND CTR_TX  DTOG_TX STAT_TX EA
  1     1       10      1       01      0       0       1       10      0
SETUP: 8 bytes; @ 0080
Request 8006; wLength 64: GET_DESCRIPTOR_DEVICE (01=USB_DEVICE_DESCRIPTOR_TYPE)
8; 8; 10; (1)
IRQ: CTR, EP0R=72E0:
 CTR_RX DTOG_RX STAT_RX SETUP   TYPE_EP EP_KIND CTR_TX  DTOG_TX STAT_TX EA
  0     1       11      0       01      0       1       1       10      0
IN: 8; 16; 2; (1)
IRQ: CTR, EP0R=A2A0:
 CTR_RX DTOG_RX STAT_RX SETUP   TYPE_EP EP_KIND CTR_TX  DTOG_TX STAT_TX EA
  1     0       10      0       01      0       1       0       10      0
IN: 2; 18; 0; (0)
IRQ: CTR, EP0R=A230:
 CTR_RX DTOG_RX STAT_RX SETUP   TYPE_EP EP_KIND CTR_TX  DTOG_TX STAT_TX EA
  1     0       10      0       01      0       0       0       11      0
OUT: 0 bytes; @ 5750


Такая вот последовательность, совершенно одинаковая, выдаётся ровно три раза, после чего виндоус печально говорит, что неизвестное устройство не распознано.

Что меня в этом.... эээ.. смущает.
Первое: я вижу запрос, в котором поле wLength равно 64, как и ожидалось. Запрос правильный, байты какие надо там присутствуют (ровно 8, что тоже ожидаемо). Запрос распознаётся нормально - направление от хоста к устройству, на получение стандартного дескриптора "тип устройства".
В ответ на него я делаю сериализацию дескриптора (вот, возможно, где-то тут я ошибся - порядок байтов, то-сё.. но не похоже) и даю указатель на данные функции, которая читает этот массив по небольшим порциям - специально осторожничаю, ограничился минимальным стандартным размером одной посылки 8 байт.

Функция читает порцию данных, кладёт их в буфер конечной точки и переключает биты STAT_TX в состояние VALID. Если я правильно понимаю, это алхимическое действие должно побудить модуль USB передать данные из буфера при получении следующего токена IN - судя по логу, так оно и происходит... три раза... без всяких там "сбросов шины после получения восьми байт"!

Ладно, потом я получаю токен OUT с нулевой длиной данных, что тоже вроде правильно. Но почему-то адрес этих "данных нулевой длины", который я настраиваю один раз при инициализации модуля USB, внезапно меняется на совершенно безумное значение 0x5750, не имеющее реального смысла ибо, мягко говоря, выходит за допустимый диапазон (максимум 0x03FF, емнип).

Получив этот токен, я переключаю уже биты STAT_RX в состояние VALID. Если я правильно всё понимаю, это и есть тот самый "Ack Handshake". Если нет, то я не понимаю, как его сформировать.

При этом явно что-то неправильное происходит, ибо после этого странного OUT шина снова сбрасывается - этот цикл повторяется, как я уже сказал, ровно три раза без всяких изменений. Если осциллографом посмотреть, что на шине происходит, то там какое-то мельтешение-мельтешение, а потом, после третьего цикла) всё замирает: видимо, это SUSPEND или что-то такое, уже не важно.

Ясно, что проблема скрыта в каких-то мелких незаметных деталях, но в каких?!

Или, быть может, я вообще всё неправильно делаю...
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 22 comments