реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> STM32F103 виртуальный СОМ-порт (USB CDC) и сообщение WM_DEVICECHANGE, В сообщениях "WM_DEVICECHANGE" STM32 USB CDC не определяется к
Mazay
сообщение Feb 10 2017, 08:42
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 23-11-05
Пользователь №: 11 270



На STM32F103 поднят виртуальный СОМ-порт (USB CDC). Используется стандартная библиотека от STM. Все работает. Байты летают туда-сюда. Однако, при отлаживании устройства, наверно многие обратили внимание, что после перезагрузки/перепрошивки контроллера, виртуальный порт «отваливается». Однако во всех доступных мне терминальных программах он так и остается открытым. Данные при этом естественно никакие не идут. Если в терминальной программе закрыть порт, то открыть его не получится. Нужно опять перезагрузить микроконтроллер и только тогда снова открыть порт. Т.е. правильная последовательность действий должна быть такая:
1. Закрыть порт в терминальной программе.
2. Перезагрузить/препрошить и т.д.
3. Открыть порт в терминальной программе.
Обычно про эту последовательность вспоминаешь, когда уже успел загрузить новую прошивку, контроллер перезагрузился и виртуальный порт «отвалился».

В самописной терминальной программе решил оптимизировать этот процесс. Реализовал получение от Windows системных сообщений WM_DEVICECHANGE указывающих на изменения в устройствах. Из этого сообщения нужны события DBT_DEVICEARRIVAL и DBT_DEVICEREMOVECOMPLETE – подключение и удаление устройства соответственно. Далее можно проанализировать Тип устройства которое подключилось или было удалено из системы. Наиболее интересен тип DBT_DEVTYP_PORT, который как раз и является указывающим на Последовательный или Параллельный порт. И вот тут с устройством на STM32 возникла неприятность. При подключении или отключении STM32 событие с типом устройства DBT_DEVTYP_PORT не присылается! Помимо типа DBT_DEVTYP_PORT есть общий тип DBT_DEVTYP_DEVICEINTERFACE указывающий вообще на любое устройство. Вот приходит только событие с этим типом и все. Я проверил имеющиеся у меня переходники USB<->COM на FT232, CPxxx, PL2303 и китайской CH340. При их подключении/отключении помимо событий с общим типом DBT_DEVTYP_DEVICEINTERFACE всегда приходит событие с типом DBT_DEVTYP_PORT по которому легко определить, что конфигурация портов изменилась, а получив из возвращаемой структуры поле Name, можно сразу определить какой порт подключился/удалился. Собственно вопросы к знатокам: В какую сторону стоит копнуть, чтоб и при подключение/удалении STM32 получать сообщение DBT_DEVTYP_PORT? Кто отвечает за рассылку этих сообщений? Я подозреваю, что драйвер, а он используется стандартный виндовый usbser.sys. В файле stmcdc.inf используемом при установке драйвера виртуального COM-порта прописан GUID класса портов. Так, что эта часть кажется правильной. В системе, в диспетчере устройств STM32 USB CDC присутствует в классе портов. WinAPI’шная функция SetupDiEnumDeviceInfo() возвращает среди прочих портов и STM32. Т.е. Винда знает, что это последовательный порт, но сообщения об этом не приходят.
Go to the top of the page
 
+Quote Post
aiwa
сообщение Feb 10 2017, 11:00
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682



Цитата(Mazay @ Feb 10 2017, 10:42) *
Собственно вопросы к знатокам: В какую сторону стоит копнуть, чтоб и при подключение/удалении STM32 получать сообщение DBT_DEVTYP_PORT? Кто отвечает за рассылку этих сообщений?
Т.е. Винда знает, что это последовательный порт, но сообщения об этом не приходят.

Положение дел еще хуже: в аналогичной ситуации с SIM800C даже парой DBT_DEVICEARRIVAL и DBT_DEVICEREMOVECOMPLETE не обойтись.
Так как совершенно один и тот же драйвер на одной машине выдавал "MTK USB port", а на другой "Mеdiatek USB port".
Остается надеяться, что не поменяется пара vid, pid и отслеживать через нее.
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Feb 10 2017, 11:03
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Тут
http://stackoverflow.com/questions/2899862...lete-on-wm-devi
пишут что это не порт...
У меня после добавления флага DEVICE_NOTIFY_ALL_INTERFACE_CLASSES начало приходить с типом DBT_DEVTYP_PORT - со структурой PDEV_BROADCAST_PORT - и там правильное имя

зы: тестировалось с USB CDC, W10/64, для CDC не требуется inf файлов, винда теперь его знает.

Сообщение отредактировал Genadi Zawidowski - Feb 10 2017, 11:25
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
DeNi
сообщение Feb 10 2017, 11:28
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 36
Регистрация: 18-10-06
Из: Москва
Пользователь №: 21 459



Проблема в драйвере usbser.sys, он не регистрирует отправку событий PnP. Можно обкостылить добавив в .inf файл драйвер фильтр serenum.sys.
Но возникнут другие проблемы: потеряется цифровая подпись от ST и этот драйвер предназначен для обнаружения PnP устройств на COM порту.
При добавлении serenum.sys, Windows при некоторых последовательностей байт может находить мышки, трекболы и.т.д.
Проблема в usbser.sys решена в Windows 10, там уведомления о подключении и отключении присылаются.

Переходники от FTDI и Prolific используют свои драйверы, за место usbser.sys. Они даже не USBCDC класс.

При использовании serenum.sys уведомления будут приходить только при регистрации класса GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR.
Номер COM порта можно узнать из реестра, открыв ключ реестра с помощью SetupDiOpenDevRegKey.
Go to the top of the page
 
+Quote Post
Mazay
сообщение Feb 10 2017, 12:13
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 23-11-05
Пользователь №: 11 270



Цитата(DeNi @ Feb 10 2017, 14:28) *
Проблема в драйвере usbser.sys, он не регистрирует отправку событий PnP.


Да, видимо вы правы. Нашел в закромах плату с атмеловским AT91SAM7 и тоже включенным CDC - ситуация аналогична с STM32. Драйвер используется все тот-же usbser.sys и в событиях DBT_DEVICEARRIVAL и DBT_DEVICEREMOVECOMPLETE приходит только в виде "USB Raw Device" {a5dcbf10-6530-11d2-901f-00c04fb951ed}. По умолчанию, в отличии от портов, эти сообщения не приходят и нужно или подписываться на них, или "включать" все сообщения (DEVICE_NOTIFY_ALL_INTERFACE_CLASSES).

Видимо придется при получении событий об добавлении/удалении устройств перезапрашивать у Винды список портов. Причем замечена одна особенность с китайским переходником USB<->COM CH340. Если порт открыт в терминалке и выдернуть переходник, то сообщение об удалении Порта приходит. Но в реестре он остается в списке имеющихся портов и можно писать в него не получая ошибки. Удаляется он из списка портов только после того, как его закрыли. Поэтому по приходу событий DBT_DEVICEARRIVAL и DBT_DEVICEREMOVECOMPLETE просто перечитать реестр не помогает. Порт еще будет присутствовать. Надо или разбирать тип DBT_DEVTYP_PORT для извлечения Имени, или получать список портов функцией SetupDiEnumDeviceInfo().
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Feb 10 2017, 12:49
Сообщение #6


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



СТранно...
USB CDC на десятке такое дает:
Цитата
'DBT_DEVNODES_CHANGED'
'DBT_DEVNODES_CHANGED'
'DBT_DEVNODES_CHANGED'
'DBT_DEVICEREMOVECOMPLETE: COM5'
'DBT_DEVNODES_CHANGED'
'DBT_DEVICEREMOVECOMPLETE: COM4'
'DBT_DEVNODES_CHANGED'
'DBT_DEVNODES_CHANGED'
'DBT_DEVICEARRIVAL: COM5'
'DBT_DEVNODES_CHANGED'
'DBT_DEVICEARRIVAL: COM4'
'DBT_DEVNODES_CHANGED'
'DBT_DEVNODES_CHANGED'
'DBT_DEVNODES_CHANGED'
'DBT_DEVNODES_CHANGED'
'DBT_DEVNODES_CHANGED'
'DBT_DEVNODES_CHANGED'
'DBT_DEVICEREMOVECOMPLETE: COM5'
'DBT_DEVICEREMOVECOMPLETE: COM4'
'DBT_DEVNODES_CHANGED'
'DBT_DEVNODES_CHANGED'
'DBT_DEVICEARRIVAL: COM5'
'DBT_DEVNODES_CHANGED'
'DBT_DEVICEARRIVAL: COM4'
'DBT_DEVNODES_CHANGED'
'DBT_DEVNODES_CHANGED'

Составное кстройство с двумя компортами и аудиоплатой. Это я кабель отсоединял и включал. W10.

Что у Вас с разными девайсами будет с тестовой программой отсюда https://code.google.com/archive/p/arduino/issues/934

Сообщение отредактировал Genadi Zawidowski - Feb 10 2017, 12:49
Прикрепленные файлы
Прикрепленный файл  DevNfyTest.rar ( 22.8 килобайт ) Кол-во скачиваний: 11
 
Go to the top of the page
 
+Quote Post
DeNi
сообщение Feb 10 2017, 13:45
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 36
Регистрация: 18-10-06
Из: Москва
Пользователь №: 21 459



класс Ports для USB CDC ACM начал поддерживаться только с десятки, поэтому уведомления в десятке будут приходить.


https://msdn.microsoft.com/en-us/library/wi...0(v=vs.85).aspx



Communications and CDC Control (02h)

Цитата(Mazay @ Feb 10 2017, 15:13) *
Видимо придется при получении событий об добавлении/удалении устройств перезапрашивать у Винды список портов. Причем замечена одна особенность с китайским переходником USB<->COM CH340. Если порт открыт в терминалке и выдернуть переходник, то сообщение об удалении Порта приходит. Но в реестре он остается в списке имеющихся портов и можно писать в него не получая ошибки. Удаляется он из списка портов только после того, как его закрыли. Поэтому по приходу событий DBT_DEVICEARRIVAL и DBT_DEVICEREMOVECOMPLETE просто перечитать реестр не помогает. Порт еще будет присутствовать. Надо или разбирать тип DBT_DEVTYP_PORT для извлечения Имени, или получать список портов функцией SetupDiEnumDeviceInfo().


Насколько помню до Windows 10 usbser.sys кроме DBT_DEVNODES_CHANGED в WM_DEVICECHANGE ничего больше не присылает.
Если всё же приходят DBT_DEVICEARRIVAL и DBT_DEVICEREMOVECOMPLETE, то все порты перебирать не обязательно.
Номер порта можно получить из реестра зная путь к интерфейсу.

lParam указывает на DEV_BROADCAST_HDR, для интерфейса он будет типа DBT_DEVTYP_DEVICEINTERFACE
DBT_DEVTYP_DEVICEINTERFACE->dbcc_name это путь к устройству
SetupDiOpenDeviceInterface даст интерфейс
SetupDiGetDeviceInterfaceDetail даст инфу по интерфейсу
SetupDiOpenDevRegKey откроет ключ в HKLM\SYSTEM\ControlSet\Enum\USB для этого интерфейса, откуда и можно узнать номер порта
Go to the top of the page
 
+Quote Post
johnshadow
сообщение Feb 10 2017, 15:32
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 31
Регистрация: 25-09-08
Пользователь №: 40 477



Если нет стойкой ненависти к паскалю - ниже прилагаю честно подсмотренный где-то модуль, которым пользуюсь в одном проекте.
Им определяю подключение\отключение последовательных портов
Прикрепленный файл  U_Usb.rar ( 3.39 килобайт ) Кол-во скачиваний: 60

Go to the top of the page
 
+Quote Post
Alechek
сообщение Feb 10 2017, 17:09
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 241
Регистрация: 15-11-05
Из: Челябинск
Пользователь №: 10 882



Цитата(Mazay @ Feb 10 2017, 17:13) *
Поэтому по приходу событий DBT_DEVICEARRIVAL и DBT_DEVICEREMOVECOMPLETE просто перечитать реестр не помогает. Порт еще будет присутствовать.

Вот не считаю правильным лезть в реестр что-то смотреть. Или этот механизм вполне документирован Mirosoft-ом?
Если есть альтернатива сделать то же самое через API - стоит этим воспользоваться.

Попалась мне недавно одна поделка, вроде как через реестр определяет наличие драйвера STM VCP, ставит его если не обнаружила....
Может на XP это и прокатит, а на старших ОС со стороны пользователя это выглядит как некая неизвестная прграмма без всяких подписей хочет для запуска права администратора! wacko.gif
Go to the top of the page
 
+Quote Post
prottoss
сообщение Feb 10 2017, 17:16
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Всем доброго времени суток.
Я тоже сталкивался с проблемой, когда терминальная программа (для СОМ-портов), при внезапном отключении устройства теряла порт и при повторном подключении его не находила.
Тем не менее, недавно закончил коммерческую программу для РС, которая работает с устройством, прикидывающимся СОМ-портом. У заказчика было жесткое требование, чтобы программа устойчиво работала с устройством при его горячем отключении-подключении.

Ни чего сложного не придумывал. Ни какие хитрые функции не использовал. Обычный АПИ - CreateFile, Read/WriteFile, CloseHandle - весь набор.
1. Устройство находится через SetupAPI. Открывается как обычный СОМ-порт с именем "COMxx" в асинхронном режиме.
2. Все операции ввода вывода происходят в отдельном потоке в бесконечном цикле. Поток всегда ожидает команды от приложения через событие Start.
3. Цикл завершается отправкой сообщения приложению через PostMessage.
4. При любом значении GetLastError отличным от 0 закрываем устройство в потоке, спим 5 секунд и пытаемся открыть устройство.

Испытано на Windows XP, 7 32/64 бит. Работает железно. Можно втыкать-вытыкать порт сколько угодно - все работает.


--------------------
Go to the top of the page
 
+Quote Post
hd44780
сообщение Feb 11 2017, 18:47
Сообщение #11


Профессионал
*****

Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980



Mazay, у Вас pull-up на D+ отключаемый или нет? Если нет - сделайте отключаемый.
И драйвера CDC тут ни при чём. У меня HID device, соответственно никаких ST-шных дров нет вообще, а симптомы те же. Отключаемый pull-up должен помочь. Правда руки до этого у меня ещё не дошли sad.gif . На него винда всегда корректно реагирует.

А переподключение кабеля по сути и реализует то самое переподключение резюка. Никакие PnP сообщения тут, имхо ни при чём.
Я эту байду наблюдал и на AVR+ObDev лет этак 8 назад, наблюдаю её и здесь. Винды разные были XP, 2003 сервер, семёрка. Более высоких не пробовал, но думается, один хрен.


--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса.
(с) Мария Эдуарда
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Feb 11 2017, 18:54
Сообщение #12


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Если в операционной системе кто-то держит открытым порт, соответственно и его имя (в именах kernel devices) занято... Похоже, про появлении нового устройств в системе новое создается без имени или с игнорированием ошибок - но до него по имени "не достучатсья". ИЛи символическая ссылка от COMxx не создается.


Сообщение отредактировал Genadi Zawidowski - Feb 11 2017, 19:09
Go to the top of the page
 
+Quote Post
DeNi
сообщение Feb 12 2017, 10:32
Сообщение #13


Участник
*

Группа: Участник
Сообщений: 36
Регистрация: 18-10-06
Из: Москва
Пользователь №: 21 459



Цитата(prottoss @ Feb 10 2017, 20:16) *
Всем доброго времени суток.
Я тоже сталкивался с проблемой, когда терминальная программа (для СОМ-портов), при внезапном отключении устройства теряла порт и при повторном подключении его не находила.


Вот в этом и стоит вопрос, что программе терминалу нужно по большей части только читать из порта, а ReadFile не завершается с ошибкой, если устройство отключить.
Программа просто продолжает читать из порта ноль байт. Не получается отследить момент когда устройство отсоединено.
И если не успеть закрыть порт, до того как устройство вставили повторно, получим Error = 2 при вызове CreateFile.

К ошибке приводит только запись с отличным от нуля количеством байт. Такое поведение характерно только для usbser.sys.

Цитата(hd44780 @ Feb 11 2017, 21:47) *
И драйвера CDC тут ни при чём. У меня HID device, соответственно никаких ST-шных дров нет вообще, а симптомы те же. Отключаемый pull-up должен помочь. Правда руки до этого у меня ещё не дошли sad.gif . На него винда всегда корректно реагирует.


Как раз драйвер CDC очень даже причем. ST драйвера никогда не писала, их драйвер для CDC это только цифровая подпись для stmcdc.inf,
чтоб с их VID PID установить usbser.sys который уже имеется в Windows. Для HID устанавливается функциональный драйвер по классу устройств,
и для его привязки не важен VID PID.
Go to the top of the page
 
+Quote Post
Mazay
сообщение Feb 13 2017, 07:05
Сообщение #14


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 23-11-05
Пользователь №: 11 270



Цитата(DeNi @ Feb 12 2017, 13:32) *
Как раз драйвер CDC очень даже причем. ST драйвера никогда не писала, их драйвер для CDC это только цифровая подпись для stmcdc.inf,
чтоб с их VID PID установить usbser.sys который уже имеется в Windows.


Всем спасибо за помощь! Отдельное спасибо уважаемому DeNi за подробное объяснение проблем с usbser.sys и советы по использованию WinAPI.
Не написал в первом посте - ОС действительно старая WinXP/Win7. При включении-выключении, перзагрузке, выдергивании и т.д. устройств использующих виндовый драйвер usbser.sys все-таки приходят сообщения с событиями DBT_DEVICEARRIVAL и DBT_DEVICEREMOVECOMPLETE и типом DBT_DEVTYP_DEVICEINTERFACE. Из них уже можно получить путь к устройству и реализовать автоматическое закрывание порта, а в будущем и автоматическое переподключение.



А вот возник такой, непонятный для меня вопрос при перечислении портов имеющихся в системе:
Примерная рыба кода:

Код
hDevInfo = SetupDiGetClassDevs(&ClassGuid, NULL, NULL, /*DIGCF_DEVICEINTERFACE |*/ DIGCF_PRESENT);  // Получаю хендл на список устройств имеющихся в системе

for(int n = 0; SetupDiEnumDeviceInfo(hDevInfo, n, &DevInfoData); n++)  // Перечисляю устройства
{
   .......
    for(int m = 0; SetupDiEnumDeviceInterfaces(hDevInfo, &DevInfoData, &ClassGuid, m, &DeviceInterfaceData); m++)  // Перечисляю интерфейсы для устройства
    {
          ........
    }
}


И вот если в функции SetupDiGetClassDevs указан только флаг DIGCF_PRESENT то определяются все порты имеющиеся в системе (в том числе и использующие usbser.sys), но функция SetupDiEnumDeviceInterfaces возвращает ошибку ERROR_NO_MORE_ITEMS для любого порта. Если я добавляю флаг DIGCF_DEVICEINTERFACE, то интерфейсы находятся, но из списка устройств исчезают порты как раз использующие usbser.sys. Вот логи небольшой программки, набросанной для лучшего понимания работы с винайпишными функциями Практической пользы в получении интерфейсов при перечислении портов я пока не вижу, это скорее тренировка инженера-железячника.

Флага DIGCF_DEVICEINTERFACE нет:

Описание класса: Порты (COM и LPT)
====================================================
Порт Найден: Последовательный порт (COM1)
Поиск Интерфейсов закончен!
====================================================
Порт Найден: PCI Serial Port (COM22)
Поиск Интерфейсов закончен!
====================================================
Порт Найден: PCI Serial Port (COM21)
Поиск Интерфейсов закончен!
====================================================
Порт Найден: PCI Parallel Port (LPT1)
Поиск Интерфейсов закончен!
====================================================
Порт Найден: AT91 USB to Serial Converter (COM15)
Поиск Интерфейсов закончен!
====================================================
Порт Найден: STMicroelectronics Virtual COM Port (COM4)
Поиск Интерфейсов закончен!
Поиск Устройств закончен!

Флаг DIGCF_DEVICEINTERFACE добавлен:

Описание класса: Порты (COM и LPT)
====================================================
Порт Найден: Последовательный порт (COM1)
Интерфейс Найден: Порядковый номер: 0
\\?\acpi#pnp0501#1#{4d36e978-e325-11ce-bfc1-08002be10318}
Имя порта из Реестра (SetupDiOpenDevRegKey/RegQueryValueEx): COM1
Поиск Интерфейсов закончен!
====================================================
Порт Найден: PCI Serial Port (COM22)
Интерфейс Найден: Порядковый номер: 0
\\?\mf#pci#ven_9710&dev_9835&subsys_00121000&rev_01#6&8e99d9a&0&0000e6#child0000#{4d36e978-e325-11ce-bfc1-08002be10318}
Имя порта из Реестра (SetupDiOpenDevRegKey/RegQueryValueEx): COM22
Поиск Интерфейсов закончен!
====================================================
Порт Найден: PCI Serial Port (COM21)
Интерфейс Найден: Порядковый номер: 0
\\?\mf#pci#ven_9710&dev_9835&subsys_00121000&rev_01#6&8e99d9a&0&0000e6#child0001#{4d36e978-e325-11ce-bfc1-08002be10318}
Имя порта из Реестра (SetupDiOpenDevRegKey/RegQueryValueEx): COM21
Поиск Интерфейсов закончен!
Поиск Устройств закончен!
Go to the top of the page
 
+Quote Post
Mazay
сообщение Feb 13 2017, 12:10
Сообщение #15


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 23-11-05
Пользователь №: 11 270



Цитата(DeNi @ Feb 10 2017, 16:45) *
lParam указывает на DEV_BROADCAST_HDR, для интерфейса он будет типа DBT_DEVTYP_DEVICEINTERFACE
DBT_DEVTYP_DEVICEINTERFACE->dbcc_name это путь к устройству
SetupDiOpenDeviceInterface даст интерфейс
SetupDiGetDeviceInterfaceDetail даст инфу по интерфейсу
SetupDiOpenDevRegKey откроет ключ в HKLM\SYSTEM\ControlSet\Enum\USB для этого интерфейса, откуда и можно узнать номер порта


Все получилось. Еще раз спасибо!
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 22:18
Рейтинг@Mail.ru


Страница сгенерированна за 0.01493 секунд с 7
ELECTRONIX ©2004-2016