Cdc abstract control model acm что это
CONNECTING MY SAMSUNG GALAXY S TO MY PC IT SAYS FOUND NEW HARDWARE , I CANNOT SEEM TO LACATE ANY DRIVERS OR INFORMATION ANYWHERE FOR THIS PROBLEM, THE DRIVER REQIURED IS FOR, CDC ABSTRACT CONTROL MODEL (ACM).I AM RUNNING WINDOWS VISTA HOME 32 BIT WITH ALL UPDATES AND SERVICE PACKS INSTALLED
This thread is locked. You can follow the question or vote as helpful, but you cannot reply to this thread.
Report abuse
Harassment is any behavior intended to disturb or upset a person or group of people. Threats include any threat of suicide, violence, or harm to another. Any content of an adult theme or inappropriate to a community web site. Any image, link, or discussion of nudity. Any behavior that is insulting, rude, vulgar, desecrating, or showing disrespect. Any behavior that appears to violate End user license agreements, including providing product keys or links to pirated software. Unsolicited bulk mail or bulk advertising. Any link to or advocacy of virus, spyware, malware, or phishing sites. Any other inappropriate content or behavior as defined by the Terms of Use or Code of Conduct. Any image, link, or discussion related to child pornography, child nudity, or other child abuse or exploitation.
Driver Genius Professional - программа для управления драйверами (создания резервных копий, восстановления повреждённых версий, обновления и удаления ненужных) , имеющая также некоторые возможности для диагностики аппаратного обеспечения. Driver Genius позволяет в автоматическом режиме найти необходимые драйверы для всех устройств, используя данные об установленных в систему устройствах. Поддерживается работа с более чем 30 тысячами различных материнских плат, видеокарт, звуковых и сетевых карт, модемов, мониторов, клавиатур, мышей, видеокамер и т. д. База программы постоянно обновляется.
Как мы преодолевали передачу данных по USB
Итак, в нашем замечательном приборе Беркут-ММТ (на базе PXA320 и GNU/Linux) есть не менее замечательный модуль OTDR (на базе STM32 и NutOS), представляющий собой импульсный оптический рефлектометр. Эта связка работает следующим образом: пользователь нажимает на экране на различные элементы UI, в приборе происходит немножечко магии, и желания пользователя трансформируются в команды вида «duration 300», которые уходят в измерительный модуль. Конкретно эта команда выставляет длительность измерений в 300 секунд. Модуль к прибору подключен по USB, для передачи команд поверх USB поднят CDC-ACM.
Кратенько — CDC-ACM позволяет эмулировать последовательный порт через USB. Так что для верхнего уровня наш измерительный модуль в системе доступен как /dev/ttyACM0. CDC-ACM служит для передачи команд в модуль или чтения текущих настроек/состояния модуля. Для передачи самой рефлектограммы служил USB Bulk интерфейс, который все свое время посвящал только одному — передаче данных рефлектограммы из модуля в прибор, как бинарного потока данных. В какой-то момент мы заметили, что рефлектограмма приходит к нам не полностью. Так мы открыли для себя, что USB может терять данные.
Схематично это выглядело так:
b5-cardifaced — это демон, который принимает команды по D-Bus и отправляет их в карту через CDC-ACM интерфейс. Результат выполнения посылает обратно по D-BUS.
usbgather — небольшая программка, которая работает на базе libusb и занимается тем, что выгребает из модуля рефлектограмму через USB Bulk и выдает ее на stdout.
Костыли и велосипеды
Сели мы и подумали — нам нужно понимать вся ли рефлектограмма к нам пришла для возможности пропуска неполных рефлектограмм. Стали мы придумывать различные хитрые заголовки, контрольные суммы и тд. Потом поняли что изобретаем ТСР. И тогда было принято волевое решение вместо USB Bulk завести TCP/IP поверх CDC-EEM. Почему CDC-EEM? Потому что CDC-EEM позволяет наиболее просто использовать USB как транспорт для передачи сетевого трафика. На самом приборе поддержка CDC-ECM в ядре есть, а модулях мы используем NutOS в качестве операционной системы и поддержка CDC-EEM и TCP/IP стек в NutOS был.
Фикс длинною в жизнь 3 месяца
Казалось бы — ни что не предвещало беды. Подняли CDC-EEM, настроили IP адреса. Ping? Есть ping! Ура. Изменили механизм передачи данных с USB Bulk на передачу данных через TCP-сокет. Вот-вот должно было наступить счастье, но тут внезапно при тестировании сеть упала с криками в dmesg о своей непростой жизни, наших кривых руках и вставшей колом очереди на отправку для нашего сетевого интерфейса. Примерно так:
Корень зла
Но наше счастье было бы не полным, если бы не еще одна деталь — при приеме служебных пакетов модуль зависал. Наглухо. Вместе с CDC-ACM.
У нас в модуле USB было настроено так, что передача шла пакетами по 64 байта. Соответственно один Ethernet пакет бился на N пакетов по 64 и передавался через USB. Вот так:
После весьма продолжительного изучения ситуации мы пришли к выводу, что происходит вот что: мы теряем часть EEM-пакета (да, USB не гарантирует доставку). Но мы прочитали из заголовка длину и опираемся на нее. Соответственно мы из следующего пакета вычитываем N потерянных байт, а следующие данные воспринимаем как начало нового EEM-пакета и интерпретируем первые 2 байта как заголовок. А там может оказаться все что угодно. Вплоть до взведенного в 1 бита, который указывает что это служебный пакет. В совсем плохих случаях мы ловим такие данные, которые при интерпретации как EEM-заголовок дают нам Echo Response огромной длины. Гораздо большей, чем наша оперативная память. Так мы поняли что наша реализация usbnet в NutOS требует серьезных доработок.
Больше проверок хороших и разных
В процессе ковыряния usbnet в NutOS было выяснено, что текущий вариант вообще не готов к приему служебных пакетов. От слова совсем. Мы сделали новый вариант, который стал способен корректно обрабатывать служебные пакеты, а именно: мы смотрели тип пакета, ибо на echo по стандарту мы ответить обязаны; проверяли длину — если она больше MTU — то мы явно словили мусор. Еще нашли странность в функции, запускающей передачу данных по endpoint'у: мы проверяли — не занят ли сейчас нулевой endpoint, и если занят — просто выходили и все. Вызывающий эту функцию всегда считал что передача данных запущена, а часто получалось что нет. В итоге мы теряли данные, причем в обе стороны.
Были войны с ТСР-сокетом — иногда данные не передавались и мы не видели почему. Не знаю что руководило разработчиками NutOS, но множество функций, имеющих возвращаемый тип int в любой непонятной ситуации возвращали "-1". Некоторые из них записывали реальный код ошибки в информацию о сокете, некоторые нет. Так что пришлось позаниматься протаскиванием кодов возврата с самых низов, вроде функции отправки данных с сетевухи, до самых верхов — функций типа NutTcpDeviceWrite?(). После этого мы смогли видеть где случился затык.
Потом были всякие допиливания и донастройки таймаутов в сокете, добавки статических записей в ARP-таблицы на модуле и на самом приборе: в нашей сети всего 2 устройства: прибор и модуль, нет смысла в устаревании записей в ARP-таблице.
Итоги
В нашей карте теперь есть маленький ТСР сервер, который служит для передачи данных из карты в прибор. Перед началом измерений в карте запускается TCP сервер и карта начинает ждать входящих подключений. После того, как клиент подключится к ТСР серверу, карта начинает измерения и через TCP сервер отправляет результаты в прибор.
Теперь схематично работа прибора с модулем выглядит примерно так:
Действующие лица:
b5-cardifaced — тот же что и раньше — транслирует команды из D-Bus в карту и отсылает результат обратно в D-Bus;
nc — собственно netcat, читает данные рефлектограммы из сокета и отдает их на stdout для дальнейшей обработки.
После всех этих приключений у нас теперь сетевой рефлектометр. Сетевой, правда, не на все 100% — управление происходит через CDC-ACM, а сбор данных из модуля — по TCP/IP через CDC-EEM. У нас все равно есть небольшая потеря данных, но за счет использования TCP/IP на выходе мы всегда получаем полную рефлектограмму. Мы узнали много нового о USB в целом и CDC-EEM в частности и USB я стал любить чуть меньше, чем раньше.
Нагрузочный тест показал, наш модуль на базе STM32F103 может прокачать 220 килобайт данных в секунду по TCP/IP over CDC-EEM, при том что модуль в это время занимается полезной работой и USB у нас работает без использования DMA.
Составное устройство USB на STM32. Часть 4: Два-в-одном
В заключительной части публикации о составном устройстве USB я расскажу о том, как заставил заработать составное устройство USB, а также поделюсь некоторыми неочевидными нюансами этого процесса.
Работа составных частей устройства была описана во второй и третьей частях публикации.
Ответы на вопрос, зачем это всё было затеяно, даются в начале первой части и в конце четвёртой.
Исходные коды публикуемой реализации составного устройства USB, состоящего из виртуального COM-порта и дуплексной звуковой карты находятся здесь.
Создаём Composite Device Class
Файлы драйвера составного устройства usbd_comp.c и usbd_comp.h расположены в папках Core/Scr и Core/Inc соответственно.
Структура класса составного устройства аналогична структуре класса звукового устройства и содержит подобный набор функций-обработчиков событий.
Основная функция драйвера составного устройства заключается в том, чтобы определить, драйвер какого устройства нужно подключить для обработки события. При обработке запросов (Requests) это определяется по номеру интерфейса в случае Standard Requests или атрибутам запроса в случае Class-Specific Requests. При обработке пакетов данных переключение производится, как правило, по номеру конечной точки (EP).
Подробно Standard Requests описаны на стр.248 – 260 документа:
[5] Universal Serial Bus Specification, Revision 2.0, April 27, 2000
Запросы Communication Device Class-Specific Requests подробно описаны на стр.18 – 30 документа [4], а Audio Device Class-Specific Requests, соответственно, на стр.74 – 85 документа [3].
Читаем дескриптор
Дескриптор описанного в публикации составного устройства USB состоит из девяти байтов раздела Configuration Descriptor, восьми байтов раздела Interface Association Descriptor (IAD) для двух интерфейсов виртуального COM-порта, 58 байтов дескриптора виртуального COM-порта, восьми байтов раздела IAD для трёх интерфейсов звукового устройства и 183 байтов дескриптора звукового устройства USB.
Виртуальный COM-порт использует интерфейсы 0 и 1, а также конечные точки 1 и 2. Дуплексное звуковое устройство использует интерфейсы 2, 3 и 4, а также конечную точку 3.
Посмотреть листинг дескриптора составного устройства USBРазбираем работу устройства
Рассмотрим доработанный файл usb_device.c, расположенный в папке USB_DEVICE/App:
Сначала создаётся переменная hUsbDeviceFS. Тип USBD_HandleTypeDef объявлен в usbd_def.h.
Функция MX_USB_DEVICE_Init вызывается из main.c.
Вызовом функции USBD_Init задаются начальные значения переменной hUsbDeviceFS.
Затем вызовом функций HAL_PCDEx_SetTxFiFo производится настройка буфера USB для каждой конечной точки составного устройства.
Неочевидный нюанс 1: по умолчанию настройка буфера USB производится при исполнении функции USBD_LL_Init, размещённой в файле usbd_conf.c. В теле этой функции области, помеченной как USER CODE, нет. Т.е. при каждой генерации кода STM32CubeMX будет удалять настройки буфера для конечных точек 2 и 3. Именно поэтому окончательная настройка буфера USB производится уже после того, как функция USBD_LL_Init отработала.
Вызовом функции USBD_RegisterClass в hUsbDeviceFS.pClass размещается указатель на созданную в usbd_comp.c переменную USBD_COMP, содержащую указатели на обработчики событий, относящихся к классу устройства. Тип USBD_ClassTypeDef объявлен в usbd_def.h.
Вызовом функции USBD_RegisterInterface в hUsbDeviceFS.pUserData размещается указатель на созданную в usbd_comp.h пустую переменную USBD_COMP_fops_FS.
В дальнейшем обработчики событий составного устройства USB будут вызывать обработчики событий нужного устройства, входящего в составное, а также подключать нужный интерфейс связи с оконечными устройствами.
Вызовом функции USBD_Start производится запуск устройства USB.
Неочевидный нюанс 2: составное устройство будет упорно определяться как виртуальный COM-порт, если не поменять значения трёх байтов в стандартном дескрипторе устройства USB (USB standard device descriptor), размещённом в файле usbd_desc.c, причём при каждой генерации кода STM32CubeMX эти изменения будет удалять:
Неочевидный нюанс 3: виртуальный COM-порт в данном решении работает корректно только в случае, когда номер используемой им конечной точки меньше, чем номер конечной точки звукового устройства.
Неочевидный нюанс 4: виртуальный COM-порт в данном решении работает корректно только в случае, когда при инициализации в его буфер прописываются параметры порта (см. USBD_COMP_Init). Без этой записи программы терминалов к COM-порту могут и не подключиться.
Проверка работоспособности драйвера составного устройства USB
Соединяем воедино проверки работоспособности драйвера виртуального COM-порта и дуплексного звукового устройства USB. Убеждаемся, что они отлично уживаются.
Неочевидный нюанс 5: при проверке работоспособности «эхо» через COM-порт возвращается, когда составное устройство уже «переключено на COM-порт». В реальном применении устройства передача может начаться, когда подключено звуковое устройство. Чтобы избежать подобной ситуации, перед началом передачи производится вызов функции COMP_CDC_Transmit_FS для подключения драйвера виртуального COM-порта:
Выводы
Автору удалось реализовать составное устройство USB, состоящее из виртуального COM-порта и дуплексной звуковой карты, на ресурсах платы NUCLEO-F446ZE.
Решение оформлено в виде проекта в среде разработки STM32CubeIDE. После генерации кода STM32CubeMX для восстановления работоспособности решения необходимо вручную изменить значения трёх байтов в стандартном дескрипторе устройства USB (USB standard device descriptor), размещённом в файле usbd_desc.c.
От автора
Данный цикл публикаций подводит черту, фиксирует результат проекта, которой мне удалось достичь в одиночку.
Хочу поблагодарить своих читателей за доброжелательность и тёплый приём. Я никогда не был и никогда уже не буду профессиональным разработчиком ПО для микроконтроллеров. И это моя первая публикация про разработку программного обеспечения.
Благодарю Георгия (RX9CIM) за моральную поддержку при запуске проекта.
Отдельная благодарность romanetz_omsk, без которого я бы забросил проект ещё два года назад.
По логике дальнейшего развития MVP нужно приступать к написанию DSP, а это уже достаточно сложная для меня математика. Как это осилить в одиночку, ума не приложу…
Читайте также: