Композитный USB CDC гаджет не работает с хостами Windows

У меня есть встроенная система Linux 3.19 с интерфейсом USB-устройства. Устройство должно предоставить хосту три интерфейса USB: виртуальный сетевой интерфейс (RNDIS или CDC ECM) и два виртуальных последовательных порта (CDC ACM). Устройство должно взаимодействовать с современными хостами Windows (7+) и Linux (3.16+).

Поскольку Windows изначально не поддерживает CDC ECM, мы решили реализовать две конфигурации USB (это популярный подход):

  • Конфигурация 1 со следующими интерфейсами:
    • RNDIS
    • CDC ACM 0
    • CDC ACM 1
  • Конфигурация 2 со следующими интерфейсами:
    • CDC ECM
    • CDC ACM 0
    • CDC ACM 1

Намерение состоит в том, чтобы позволить Windows использовать первую конфигурацию с RNDIS, которая изначально поддерживается (Windows всегда выбирает первую конфигурацию USB); и пусть не-Windows хосты используют вторую конфигурацию с CDC ECM.

Я собрал сценарий (на основе аналогичного сценария Дэвида Лехнера): http://pastebin.com/VtAusEmf. Соответствующая часть скрипта представлена ​​ниже (пожалуйста, перейдите по ссылке, чтобы увидеть полный скрипт, он довольно большой):

mkdir -p ${g}
echo "${usb_ver}" > ${g}/bcdUSB
echo "${dev_class}" > ${g}/bDeviceClass
echo "${vid}" > ${g}/idVendor
echo "${pid}" > ${g}/idProduct
mkdir ${g}/strings/0x409
echo "${mfg}" > ${g}/strings/0x409/manufacturer
echo "${prod}" > ${g}/strings/0x409/product
echo "${serial}" > ${g}/strings/0x409/serialnumber

mkdir ${g}/configs/c.1
echo "${attr}" > ${g}/configs/c.1/bmAttributes
echo "${pwr}" > ${g}/configs/c.1/MaxPower
mkdir ${g}/configs/c.1/strings/0x409
echo "${cfg1}" > ${g}/configs/c.1/strings/0x409/configuration

echo "1" > ${g}/os_desc/use
echo "${ms_vendor_code}" > ${g}/os_desc/b_vendor_code
echo "${ms_qw_sign}" > ${g}/os_desc/qw_sign

mkdir ${g}/functions/rndis.usb0
echo "${dev_mac}" > ${g}/functions/rndis.usb0/dev_addr
echo "${host_mac}" > ${g}/functions/rndis.usb0/host_addr
echo "${ms_compat_id}" > ${g}/functions/rndis.usb0/os_desc/interface.rndis/compatible_id
echo "${ms_subcompat_id}" > ${g}/functions/rndis.usb0/os_desc/interface.rndis/sub_compatible_id

mkdir ${g}/configs/c.2
echo "${attr}" > ${g}/configs/c.2/bmAttributes
echo "${pwr}" > ${g}/configs/c.2/MaxPower
mkdir ${g}/configs/c.2/strings/0x409
echo "${cfg2}" > ${g}/configs/c.2/strings/0x409/configuration

mkdir ${g}/functions/ecm.usb0
echo "${dev_mac}" > ${g}/functions/ecm.usb0/dev_addr
echo "${host_mac}" > ${g}/functions/ecm.usb0/host_addr

mkdir ${g}/functions/acm.GS0
mkdir ${g}/functions/acm.GS1

ln -s ${g}/configs/c.1          ${g}/os_desc
ln -s ${g}/functions/rndis.usb0 ${g}/configs/c.1
ln -s ${g}/functions/acm.GS0    ${g}/configs/c.1
ln -s ${g}/functions/acm.GS1    ${g}/configs/c.1
ln -s ${g}/functions/ecm.usb0   ${g}/configs/c.2
ln -s ${g}/functions/acm.GS0    ${g}/configs/c.2
ln -s ${g}/functions/acm.GS1    ${g}/configs/c.2

echo "${device}" > ${g}/UDC

Полученная конфигурация гаджета прекрасно работает с хостами Linux (выбрана вторая конфигурация, все три интерфейса доступны и работают), но хосты Windows (протестированные с 8 и 10) обнаруживают только интерфейс RNDIS, игнорируя интерфейсы ACM. RNDIS работает хорошо, хотя.

Если я отключаю интерфейс RNDIS, хосты Windows обнаруживают только первый интерфейс ACM, игнорируя второй.

Я подозреваю, что Windows не способна правильно обрабатывать композитные USB-устройства. Это так или я что-то не так делаю? Если это так, я должен написать свой собственный .inf файл, определяющий, какие драйверы класса должны быть загружены?

1 ответ

Решение

RTFM помог. Требования к композитным USB-устройствам описаны в следующих статьях:

Решение:

echo "0xEF" > ${g}/bDeviceClass
echo "0x02" > ${g}/bDeviceSubClass
echo "0x01" > ${g}/bDeviceProtocol
Другие вопросы по тегам