Конференция "WinAPI" » Нe удается открыть вирт. ком-порт, работающий через usbser.sys
 
  • Kolan © (09.04.10 10:18) [0]
    Здравствуйте!

    Есть железка, которая представляется как USB-функция и реализует ACM совместимый USB CDC профиль (это я написал под диктовку нашего «железячника»).

    Для подключение к Винде мы использовали драйвер usbser.sys из Виндоус Икс-Пи (второй сервис пак).

    Проблема в том, что при определенных действиях (гарантировано воспроизвести не удаётся, но это происходит при физическом отключении железки от порта) виртуальный ком-порт определяется в системе (виден в списке оборудование), а работать с ним не удается, функция открытия файла завершается с ошибкой «Не удается найти указанный файл.»

    Причем дело врядли в конкретной программе, так как доступ к порту в этом случае не может получить ни одна программа вообще (пробовали ZOC и пр.).

    Помогает только перетыкание USB в другой порт, при этом появляется ком-порт с другим номером и открытие файла проходит успешно. Если после этого воткнуть USB обратно (туда, где только что не работало), открытие снова работает.

    Вопросы: В чем может быть дело? Как это исправить?
  • brother © (09.04.10 10:31) [1]
    > Проблема в том, что при определенных действиях (гарантировано
    > воспроизвести не удаётся, но это происходит при физическом
    > отключении железки от порта
    ) виртуальный ком-порт определяется
    > в системе (виден в списке оборудование), а работать с ним
    > не удается
    , функция открытия файла завершается с ошибкой
    > «Не удается найти указанный файл.»

    если отключили, то с чего бы ему работать? не понял, в чем проблемма?
  • Дмитрий Белькевич (09.04.10 10:41) [2]
    Думаю, что наиболее вероятны глюки в драйвере железяки.
  • Kolan © (09.04.10 12:01) [3]
    «если отключили, то с чего бы ему работать? не понял, в чем проблемма?»

    Был 19 порт. Отключили. Порт пропал. Подключили снова. Снова появился 19 порт, но открыть его не получается.

    Дальше можно переключать до посинения, пока в другой разъем не переткнешь, чтобы 18 порт определился, открыть не получится.
  • Kolan © (09.04.10 12:13) [4]
    В железке стоит uClinux и используется 527 BlackFin, в котором уже есть поддержка USB. Соответственно используются стандартные драйвера. Профиль CDC реализован Линуксом (модуль g_serial).

    Кроме того, при подключении железки к компьютеру с Линуксом проблем не наблюдается.
  • Kolan © (09.04.10 13:31) [5]
    Мне кажется дело в том, что когда программа отрыта — она занимает ком порт. Если я отключаю USB во время работы программы, то он пропадает из системы, но остается, видимо, занятым.

    Когда я возвращаю USB назад, то, наверно, та занятость порта как-то  мешает работе с новым.

    Есть идеи по этому поводу.
  • Германн © (09.04.10 13:48) [6]

    > Есть идеи по этому поводу.

    Идеи есть. Слов нет литературных.
  • Германн © (09.04.10 14:04) [7]

    > Kolan ©   (09.04.10 13:31) [5]

    Как с портом работаешь?
  • Kolan © (09.04.10 14:13) [8]
    Ну ты попробуй, все-таки.
  • Kolan © (09.04.10 14:14) [9]
    Открываю в начале программы, закрываю в конце.
  • Германн © (09.04.10 14:15) [10]

    > Kolan ©   (09.04.10 14:14) [9]
    >
    > Открываю в начале программы, закрываю в конце.
    >

    Доппотоки используешь?
  • Kolan © (09.04.10 14:20) [11]
    Я использую компонент nrCommLib. Он, вроде, использует.
  • Kolan © (09.04.10 16:35) [12]
    Что-то еще нужно? Исходники nrCommLib есть, если нужно — могу детальнее описать что и как.
  • Германн © (10.04.10 00:38) [13]

    > Kolan ©   (09.04.10 14:20) [11]

    Ты же вроде что-то пробовал с tpapro?
    Проверено на возможно похожей железяке (микросхема FT232RL). Tapdcomport проблем не вызывает. В то время как программы (созданные двумя моими знакомыми) читающие/пишущие в СОМ-порт в доппотоках при отключении этой железяки от USB порта обязательно вызывают какой-нибудь кошмар. По-моему было как-то подобное твоему эффекту. Но чаще всего этот эффект затмевается тем, что происходит полное зависание системы, которое снимается только эникеем.
  • GanibalLector © (10.04.10 00:58) [14]
    А смотрел, что вообще происходит с портом ? Есть же PortMon. Открой и посмотри. Все сразу ясно станет.

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

    З.Ы. А вообще, "домашку" пора делать ))
  • Германн © (10.04.10 02:07) [15]

    > GanibalLector ©   (10.04.10 00:58) [14]
    >
    > А смотрел, что вообще происходит с портом ? Есть же PortMon.
    >  Открой и посмотри. Все сразу ясно станет.
    >
    > Там ты увидишь, закрывается порт или нет.
    >

    Уверен что не увидит. Или увидит но не то.
  • Германн © (10.04.10 02:10) [16]

    > Дмитрий Белькевич   (09.04.10 10:41) [2]
    >
    > Думаю, что наиболее вероятны глюки в драйвере железяки.

    Хоть и возможно, но вряд ли. Заметь что автор использовал драйвер от MS.
  • Германн © (10.04.10 02:15) [17]
    В целом я считаю правильным перемещение топика в WinAPI. Но боюсь толку от этого будет немного. Бо тут "непаханное поле".
    Идиотские преобразователи USB <--> UART.
    Непонятные драйвера к ним.
    И плюс дебильная работа с СОМ-портом. Не сочтите за хамство. (с) Jeer
  • Anatoly Podgoretsky © (10.04.10 09:56) [18]
    > Германн  (10.04.2010 02:15:17)  [17]

    У нас кроме WinAPI еще есть и Для Начинающих и Прочее, так что в сложных случаях есть куда перемещать.

    По преобразователям и по драйверам согласен, типичные китайско/индуские поделки. Но других то нет.
  • Kolan © (10.04.10 12:09) [19]

    > Ты же вроде что-то пробовал с tpapro?

    На него забили, он странно подвисал при работе с зед-модемом. Купили nrComm.

    Но компонент тут не причем. Я просто пишу
    CreateFile

    и получаю сабж, то есть компоненты тут не причем.


    > Идиотские преобразователи USB <--> UART.

    Их нету. Никаких китайских. На железке стоит USB разъем, который (простите я дилетант) поддерживается самим процессором.

    Портмоном смотрел

    Вот закрытие, когда пока работала программа выдернул USB.

    697 12:00:10 miniCalibrator. IRP_MJ_READ USBSER000 SUCCESS Length 8: root:~>  
    698 12:00:10 miniCalibrator. IOCTL_SERIAL_GET_MODEMSTATUS USBSER000 SUCCESS  
    699 12:00:53 miniCalibrator. IOCTL_SERIAL_GET_COMMSTATUS USBSER000 SUCCESS  
    700 12:00:53 miniCalibrator. IOCTL_SERIAL_SET_WAIT_MASK USBSER000 SUCCESS Mask:  
    701 12:00:53 miniCalibrator. IRP_MJ_CLEANUP USBSER000 SUCCESS  
    702 12:00:53 miniCalibrator. IRP_MJ_CLOSE USBSER000 SUCCESS  



    Вот когда не выдергивал.

    895 12:04:23 miniCalibrator. IRP_MJ_READ USBSER001 SUCCESS Length 8: root:~>  
    896 12:04:23 miniCalibrator. IOCTL_SERIAL_GET_MODEMSTATUS USBSER001 SUCCESS  
    897 12:04:29 miniCalibrator. IOCTL_SERIAL_GET_COMMSTATUS USBSER001 SUCCESS  
    898 12:04:29 miniCalibrator. IOCTL_SERIAL_SET_WAIT_MASK USBSER001 SUCCESS Mask:  
    899 12:04:29 miniCalibrator. IRP_MJ_CLEANUP USBSER001 SUCCESS  
    900 12:04:29 miniCalibrator. IRP_MJ_CLOSE USBSER001 SUCCESS  



    Разницы нет.

    Портмону, тоже плохеет, кстати. Если он подцепился на 19 порт, и потом переткнуть USB — ничего не показывает.

    Может есть другой драйвер? Этот, кроме сабжа, еще и сообщение не умеет нормальное отправить (http://pda.delphimaster.net/?id=1268895548&n=0).

    Мне пришлось супер удобную штуку заменить на ручной скан портов в цикле, который еще и, по своей сути, не всегда работает.
  • GanibalLector © (10.04.10 14:46) [20]

    > Я просто пишу CreateFile и получаю сабж


    Я бы поступит так :
    - выкинул nrCommLib;
    - написал минимальный пример на чистом API, задействовав все маски;

    см. SetCommMask с флагами EV_RXCHAR , EV_ERR и не только.


    - смотрел что происходит через PortMon

    Опять таки не понятно, как ты работаешь с портом. Какие таймауты стоят на чтение ? Что происходит, когда данные не пришли и т.д.
  • Kolan © (10.04.10 14:49) [21]
    Да че смотреть, я не могу порт открыть. CreateFile завершается ошибкой, буд-то я открываю не существующий порт.
  • GanibalLector © (10.04.10 14:58) [22]

    > Да че смотреть, я не могу порт открыть.


    Ну так это ж происходит не с первой попытки. А после каких-то действий, судя по описанию.

    Давай так. ПК перегрузил, подключил девайс, открываешь порт. Так открывается ?
  • GanibalLector © (10.04.10 15:01) [23]
    Если так уверен в проблеме с usbser.sys. то посмотри на версию. Замени в конце-концов на другую ибо их несколько.
  • Kolan © (10.04.10 15:10) [24]

    > Давай так. ПК перегрузил, подключил девайс, открываешь порт.
    >  Так открывается ?

    Открывается.

    Дальше — вытащил USB.

    Закрыл прогу.

    Подключил USB.

    Открыл прогу.

    Шиш, не открывается.
  • GanibalLector © (10.04.10 15:16) [25]

    > Открывается. Дальше — вытащил USB.Закрыл прогу.


    Ну, а ты проверяешь результат CloseHandle при закрытии программы ? Там ведь, ты закрываешь порт ?

    Повторяю еще раз. Временно выкинь nrCommLib и напиши минимальный пример на API. Тогда все увидишь. И чем больше событий поставишь, тем быстрее разберешься.

    Я думаю, что при "вытащил" тебе должно прийти какое-то событие. В ответ на которые ты должен что-то сделать.
  • GanibalLector © (10.04.10 15:21) [26]

    > CreateFile завершается ошибкой


    Покажи всю ф-цию. Что в параметрах ? Там же есть флаги OPEN_EXISTING и т.д.
    Как работаешь с портом синхронно или асинхронно ?
  • Германн © (10.04.10 15:27) [27]

    > Их нету. Никаких китайских. На железке стоит USB разъем,
    >  который (простите я дилетант) поддерживается самим процессором.

    Нормальные процессоры работают по спецификации USB, а не преобразовывают USB в UART.


    > Да че смотреть, я не могу порт открыть. CreateFile завершается
    > ошибкой, буд-то я открываю не существующий порт.

    Судя по ранее сказанным твоим собственным словам ты пытаешься открыть не несуществующий порт, а занятый порт.
  • Германн © (11.04.10 03:18) [28]
    Ну и ещё.

    > Kolan ©   (10.04.10 12:09) [19]
    >
    >
    > > Ты же вроде что-то пробовал с tpapro?
    >
    > На него забили, он странно подвисал при работе с зед-модемом.
    >  Купили nrComm.
    >
    >

    Если купили, то ...
    Сам догадаешься, что нужно сделать?
  • Kolan © (15.04.10 09:42) [29]
    Вот код из писанного мной компонента:

    function TAnisochronousComm.Open: Boolean;
    begin
     Result := False;
     if FPortHandle <> INVALID_HANDLE_VALUE then
       Close;
     {'\\.\' prefix is nescessary for ports above 9.}
     FPortHandle := CreateFile(PWideChar('\\.\'+FPortName), GENERIC_READ or GENERIC_WRITE,
       0, nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
     if FPortHandle = INVALID_HANDLE_VALUE then
       Exit;

     ZeroMemory(@FOverlappedRead, SizeOf(@FOverlappedRead));
     ZeroMemory(@FOverlappedWrite, SizeOf(@FOverlappedWrite));
     FOverlappedRead.hEvent := CreateEvent(nil, False, False, nil);
     FOverlappedWrite.hEvent := CreateEvent(nil, False, False, nil);

     SetUserComState;
     SetUserComTimeOuts;
     Purge;
     Result := True;
     SetEvent(FComOpenEvent);
    end;

  • Вариант (15.04.10 12:03) [30]

    > Kolan ©   (15.04.10 09:42) [29]


    CreateFile(PWideChar

    В Delphi 6 в Windows.pas


    > function CreateFile; external kernel32 name 'CreateFileA';


    В этом случе  PWideChar не уместен.
  • Anatoly Podgoretsky © (15.04.10 12:25) [31]
    CreateFileW
  • GanibalLector © (15.04.10 13:05) [32]
    Kolan ©   (15.04.10 09:42) [29]

    С открытием все в порядке.
    Что в  SetUserComTimeOuts ?

    При запуске программы после перегрузки как ведет себя CloseHandle ? Результат проверяешь ?
  • Вариант (15.04.10 13:33) [33]

    > GanibalLector ©   (15.04.10 13:05) [32]
    > Kolan ©   (15.04.10 09:42) [29]
    >
    > С открытием все в порядке.

    Возможно - правда в дельфи 6 это просто не компилируется. Но даже если и прошло , то я бы сделал  тут хотя бы -
    if FPortHandle = INVALID_HANDLE_VALUE then
    begin
     raise Exception.Create(SysErrorMessage(GetLastError)));
    end;
    что бы точно знать причину ошибки.... И так же и в других проблемных местах.
  • Kolan © (15.04.10 15:00) [34]
    Причем тут Д6? Я использую Д2009.

    С открытием все в порядке. Ничего с ним не в порядке.

    CreateFile возвращает INVALID_HANDLE_VALUE. Смысл обсуждать что-то еще?
  • Kolan © (15.04.10 15:02) [35]
    Вот из nrComma код

    function OpenPort(const n:integer):THandle;
    begin
     Result:=CreateFile(PChar('\\?\'+ComPortToStr(n)),(GENERIC_READ + GENERIC_WRITE),0,nil,
       OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);
    end;



    Разницы нет.
  • Вариант (15.04.10 15:37) [36]

    > Kolan ©   (15.04.10 15:00) [34]
    > Причем тут Д6? Я использую Д2009.

    При том, что ты не указал версию и что прописано в твоей версии Windows.pas мне неизвестно.


    > Kolan ©   (15.04.10 15:02) [35]



    > Разницы нет.


    ПРоверь так и прочти что будет написано в сообщении

    if FPortHandle = INVALID_HANDLE_VALUE then
    begin
    raise Exception.Create(SysErrorMessage(GetLastError)));
    end;

  • Kolan © (15.04.10 15:49) [37]

    > При том, что ты не указал версию и что прописано в твоей
    > версии Windows.pas мне неизвестно.

    Тогда логичнее было бы спросить вначале.


    > ПРоверь так и прочти что будет написано в сообщении


    Ведь в [0] это написано:

    Проблема в том, что при определенных действиях (гарантировано воспроизвести не удаётся, но это происходит при физическом отключении железки от порта) виртуальный ком-порт определяется в системе (виден в списке оборудование), а работать с ним не удается, функция открытия файла завершается с ошибкой «Не удается найти указанный файл.»
  • Вариант (15.04.10 16:03) [38]

    > Kolan ©   (15.04.10 15:49) [37]


    > Тогда логичнее было бы спросить вначале.

    Нет, логичней было указать версию, ибо поставить галочку надо было при создании темы. Но не суть
    > Ведь в [0] это написано:

    а вот это точно, просто тема так долго висела, что к сегодняшнему дню уже и забыл что было в начале - моя вина, сорри.
  • GanibalLector © (15.04.10 16:22) [39]

    > С открытием все в порядке. Ничего с ним не в порядке.CreateFile
    > возвращает INVALID_HANDLE_VALUE. Смысл обсуждать что-то
    > еще?


    Так сам же говорил, что проблема появляется только при повторном запуске программы, когда устройство вытащили из USB.

    Код, который ты привел абсолютно нормальный. И я так открываю. Я считаю, что проблема возникает при закрытии порта.

    Вот для примера. У тебя есть обычные порты (СОМ1,СОМ2)? Открой один из них в гипертерминале, а потом сам попробуй открыть программно. Так вот, не получится ибо он уже занят.
  • Kolan © (15.04.10 16:29) [40]

    > Так вот, не получится ибо он уже занят.
    >

    Да, и скажут, что Отказано в доступе, а тут вообще говорят, что его нет. То есть в системе он есть, а CreateFile говорит, что нет.
  • Вариант (16.04.10 09:48) [41]
    Попробовал поиграться с USB -> COM - действительно проблема существует с удалением и повторным открытием. Более того есть и такой неприятный момент, что USB устройство может посадить свой COM на уже имеющийся виртуальный порт.
    Теперь о проблеме повторного открытия порта. Если USB устройство у меня удалялось в момент, когда порт не использовался, не был открыт какой-либо программой ( или был открыт и корректно закрыт), то проблемы в дальнейшем собственно не возникало. Удаление и последуещеее добавление USB девайса не влияло на повторное открытие COM порта. Если же удаление происходило при не закрытом HANDLE порта то у меня затем на команде CloseHandle происходило зависание на более чем 30 секунд или второй вариант - вставлял устройство пока программа висела, и в этом случае CloseHandle завершал работу раньше.  И после этого могла возникнуть описанная автором топика проблемная ситуация(но не всегда).
    И так ->
    При мониторинге добавления или удаления устройств -  обрабатывал сообщение WM_DEVICECHANGE - я видел следующее:

    Вариант 1 - Вставил устройство
    Пришли сообщения -> Добавлена последовательность COM портов.
    Я открыл порт. Закрыл порт. Удалил устройство из USB.
    Пришли сообщения -> Удалена последовательность COM портов.

    Это нормальный режим работы, после него при включении USB устройства порты нормально открываются.

    Вариант 2   - Вставил устройство

    Пришли сообщения -> Добавлена последовательность COM портов(на самом деле несколько сообщений, по одному на каждый порт).
    Я открыл порт.
    Удалил устройство из USB.
    Попытался закрыть порт.  Я не дождался завершения работы CloseHandle - прервал процесс  - в этом случае при повторном ключении USB устройства порты не открывались. Правда для устранения ошибки достаточно было удалить USB устройство и снова его вставить в то же гнездо.

    Вариант 3   - Вставил устройство
    Пришли сообщения -> Добавлена последовательность COM портов .
    Я открыл порт.
    Удалил устройство из USB.
    Попытался закрыть порт. Дождался завершения работы CloseHandle (более 30 сек). в этом случае при повторном ключении USB устройства порты нормально открылись. (прим Сообщений об удалении устройств не получил)

    Вариант 4   - Вставил устройство
    Пришли сообщения -> Добавлена последовательность COM портов .
    Я открыл порт.
    Удалил устройство из USB.
    Попытался закрыть порт. Не дожидаясь конца работы CLoseHandle снова вставил в USB устройство. Дождался завершения CloseHandle. ПОлучил
    сообщения -> Добавлена последовательность COM портов (в дистпечере устройств порты появились).
    Пришли сообщения -> Удалена последовательность COM портов.
    (но в дистпечере устройств порты остались).  В этом случае повторно открыть порт не могу.

    Вариант 5 (то же что и 4 но концовка другая, счастливая)   - Вставил устройство
    Пришли сообщения -> Добавлена последовательность COM портов .
    Я открыл порт.
    Удалил устройство из USB.
    Попытался закрыть порт. Не дожидаясь конца работы CLoseHandle снова вставил в USB устройство. Дождался завершения CloseHandle. ПОлучил
    сообщения -> Добавлена последовательность COM портов (в дистпечере устройств порты появились). После чего повторно смог открыть порт.

    Резюме - Не надо удалять устройство при работающих с ним программах. Если это случилось - надо все равно закрывать HANDLE порта (пусть долго но надо). Надо анализировать возвращаемые результаты всех функций и причины ошибок заносить хотя бы в лог - это помогает. Если возникает описанная автором ошибка порта, то в интерактивной програме - надо просто попросить пользователя переподключить устройство.
  • Kolan © (16.04.10 10:09) [42]
    Вариант 1 - Вставил устройство
    Пришли сообщения -> Добавлена последовательность COM портов.
    Я открыл порт. Закрыл порт. Удалил устройство из USB.
    Пришли сообщения -> Удалена последовательность COM портов.


    Тут еще вот какое дело. Это драйвер не шлет таких сообщение, гад. Он шлет только DBT_DEVNODES_CHANGED.

    http://pda.delphimaster.net/?id=1268895548&n=0
  • Kolan © (16.04.10 10:27) [43]
    Вроде получилось. Сделал так, что при отключении устройства порт закрывается. Тестирую, пока работает.
  • Вариант (16.04.10 10:29) [44]
    Я бы все же из интереса даже попробовал подписаться на нотификацию, просто проверить прийдет инфо или нет. Ибо про DBT_DEVNODES_CHANGED все же написано, что имеет смысл.  
    И для меня это первый опыт так сказать подобной проблемы. У нас работали  с нашими программами для RS232 через USB. Но о такой проблеме мы не задумывались как-то. Не удаляют у нас устройств на ходу....
  • Kolan © (16.04.10 11:16) [45]
    Я не понял как подписываться на нотификацию и что я буду получать в случае с портом.

    Я тоже не сталкивался раньше с такими странностями, так как раньше DBT_DEVICEARRIVAL с DBT_DEVTYP_PORT всегда приходило.
  • Вариант (16.04.10 11:59) [46]

    > Kolan ©   (16.04.10 11:16) [45]


    > Я не понял как подписываться на нотификацию и что я буду
    > получать в случае с портом.
    >

    через RegisterDeviceNotification, сам с этим не работал, описание и пример http://msdn.microsoft.com/en-us/library/aa363431(VS.85).aspx
    http://msdn.microsoft.com/en-us/library/aa363432(v=VS.85).aspx, ну или в гугле наверняка можно найти

    А вот что будешь получать - это вопрос, те же WM_DEVICE_CHANGE будет приходить, но будет ли там DBT_DEVICEARRIVAL я не знаю. Если попробуешь - узнаешь - сообщи сюда, мне тоде интересно. Но у меня такого как DBT_DEVNODES_CHANGED не приходит, а потому проверить сам не могу.
  • Kolan © (16.04.10 12:21) [47]
    Скорее всего не буду докапываться, потому что, вроде, работает нормально.

    Благодарю участников обсуждения за ответы.
 
Конференция "WinAPI" » Нe удается открыть вирт. ком-порт, работающий через usbser.sys
Есть новые Нет новых   [134431   +15][b:0][p:0.003]