Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Драйвер виртуального COM порта  (Прочитано 44819 раз)
0 Пользователей и 4 Гостей смотрят эту тему.
Natur_Keks
Интересующийся

ru
Offline Offline

« : 29-06-2011 07:34 » 

 Здравствуйте. На работе поставили задачу: написать драйвер, создающий виртуальный COM порт, к которому сторонняя прога подключается как к реальному, но все отправляемые данные должны перенаправляться моему приложению. Также и наоборот: все данные от моей проги должны через драйвер уходить в этот виртуальный COM порт(и соответственно стороннему приложению).
 И вот вопрос: можно ли создать виртуальный COM порт, одновременный доступ к которому разрешён нескольким (двум) приложениям? Причём так, чтобы данные, приходящие от одного, перенаправлялись другому?
 Или нужно два драйвера: 1) драйвер виртуального COM порта 2)просто драйвер ядра. К первому подсоединяется стороннее приложение, ко второму моё приложение, между драйверами наладить обмен данными.
 Если что, сильно не пинать Улыбаюсь, написанием драйверов никогда не занимался Жаль. Буду благодарен за любые советы, ссылки, исходники.
 
« Последнее редактирование: 29-06-2011 11:19 от Ochkarik » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 29-06-2011 07:45 » 

http://sourceforge.net/projects/com0com/
Посмотри вот это.
Идея проста: два виртуальных COM-порта, также виртуально соединенных нуль-модемным кабелем.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Natur_Keks
Интересующийся

ru
Offline Offline

« Ответ #2 : 29-06-2011 07:56 » 

http://sourceforge.net/projects/com0com/
Посмотри вот это.
Идея проста: два виртуальных COM-порта, также виртуально соединенных нуль-модемным кабелем.


Спасибо за ссылку, но данный вариант я уже предлагал начальству - ответ был отрицательный и до ужаса простой: зачем 2 виртуальных порта, когда нужен только один... Вот так Улыбаюсь
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 29-06-2011 07:57 » 

А как второе приложение будет общаться с драйвером - об этом они подумали? И вообще, нафига изобретать велосипед, если все уже давно придумано.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 29-06-2011 09:08 » 

эээ... я не совсем понимаю что требуется.
во первых, если это должен быть как бы совсем стандартный по функциям COM порт... разве можно одновременно подключится к ОДНОМУ COM порту из двух приложений?))  ответ - нельзя принципиально! не реальные, ни виртуальные.
то есть в любом случае, COM порт в системе захватывается одним приложением - монопольно. таким образом в любом случае, если вам действительно нужна эмуляция COM в обоих приложениях - порта должно быть два.
в качестве довода привести этот факт - начальству, после чего с чистой совестью  использовать вышеуказанную ссылку)

если очень приперло, и во второй программе интерфейс COM не надо эмулировать, то можно поискать/изобрести драйвер. но я бы рекомендовал отбрехаться от этого дела)

Добавлено через 13 минут и 22 секунды:
ежели припрет, постараюсь подсказать с чего начать)
« Последнее редактирование: 29-06-2011 09:21 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Natur_Keks
Интересующийся

ru
Offline Offline

« Ответ #5 : 29-06-2011 09:41 » new

 Насчёт невозможности открытия одного виртуального COM порта - программа VSPE http://www.radioscanner.ru/files/miscsoftware/file9815) каким-то образом это позволяет,т.е. возможно создать виртуальный COM порт, который можно открыть несколькими приложениями (типа Hyper Terminala) одновременно (проверял - работает). Причём данные из одного приложения передаюся в другое.
 Получается, в принципе это возможно, только, интересно, насколько сложно Улыбаюсь.
 Во второй программе,да действительно, интерфейс COM эмулировать не нужно - она (по задумке) производит обмен данными напрямую с драйвером.
  постараюсь подсказать с чего начать) - очень бы хотелось Улыбаюсь
Записан
darkelf
Молодой специалист

ua
Offline Offline

« Ответ #6 : 29-06-2011 10:14 » 

Во второй программе,да действительно, интерфейс COM эмулировать не нужно - она (по задумке) производит обмен данными напрямую с драйвером.
Ну ведь она не телепатически с драйвером общается - с ним тоже должен быть определённый интерфейс, а если так - почему-бы ему не быть com-портовым.
Записан
Natur_Keks
Интересующийся

ru
Offline Offline

« Ответ #7 : 29-06-2011 10:49 » 

 К сожалению, рабочие реалии на данный момент таковы, что при работе вышеописанной связки в системе должен появляться только один виртуальный COM порт - с которым будет общаться сторонняя программа.
 
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 29-06-2011 11:38 » 

VSPE свой драйвер подставляет.
ну тогда видимо выбора нет, надо писать драйвер.... можно для очистки совести на API посмотреть - что там позволено... может быть можно поставить hook на функции обращения к порту и перехватывать http://www.rsdn.ru/article/baseserv/IntercetionAPI.xml
и была еще какая то библиотека для перехвата ядра... но убей бог пока не вспомню названия...
... вспомнил! Detours. http://research.microsoft.com/en-us/projects/detours/

если драйвер... то, ща поищу с чего начать.

Добавлено через 1 час, 53 минуты и 51 секунду:
раздел msdn архитектуры последовательных COM портов
для драйвера, вам потребуется DDK. наверное лучше сразу новый с майкрософта, но подойдет и старый с сайта.
из литературы - Вальтер Они, Руссинович и msdn - ваши друзья)
компиляция драйвера - утилитой build.exe, либо настройками VS (темы были на форуме)

там есть примеры драйвера COM порта, но он вам не факт что подойдет, потому как использует железо. хотя теоретически его тоже можно обрезать до виртуального устройства.
обязательно стоит посмотреть исходники com0com. это почти ваш случай, хотя тоже много избыточный вариант.
файлы операций чтения/записи там выделены, можно попробовать внедрить туда свой API, если его там еще нет)

еще есть пример в DDK/WDF DDK\6001.18001\src\input\vserial\
это какой то простенький виртуальный порт, для эмуляции планшетов... не знаю насколько он подойдет. но имеет смысл обязательно глянуть! особенно после того как напугает объем кода предыдущих источников)

да. сразу - в винде существует два подхода написания драйвера. при помощи "чистого" DDK (начиная с win98) и с использованием WDF (начиная с XP+SP, книга Пенни Орвик).
последнее более новое, и быть может незначительно проще, но скорее всего в интернете инфа об этом пока менее распространена.
« Последнее редактирование: 29-06-2011 13:35 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Natur_Keks
Интересующийся

ru
Offline Offline

« Ответ #9 : 30-06-2011 10:39 » 

 Спасибо за помощь  Улыбаюсь.
 На данный момент есть такой замысел:
 1) непосредственно драйвер виртуального порта (как самое сложное) создаётся в Compuware DriverStudio 3.2 - там на автомате создаётся проект WDM драйвера виртуального порта (компилируется, получаем драйвер - вроде работает: через Панель Управления->Добавление Оборудования добавлял последовательный порт в систему, подсовывал этот драйвер - состояние порта в итоге "Устройство работает нормально", приложения тоже новопоявившийся порт видят).
 2) написать фильтр-драйвер (это проще, типа legacy драйвер), который будет помещаться в стек над драйвером виртуального порта, перехватывать запросы READ/WRITE и работать с моим приложением. Фильтр-драйвер должен загружаться в систему динамически - при запуске моей проги (SCM менеджер).
 Понимаю, что это костыли конечно, но вроде как реально в относительно короткие сроки. 
 
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 30-06-2011 18:39 » 

если DS создает такую "рыбу"(не знал;) - то лучше конечно использовать ее, иначе чей то сторонний драйвер виртуального порта все таки придется ставить? нумега оч хорошие "рыбы" варит) до сих пор пользуюсь)

но наверное оба способа имеют право на жизнь... DS - фильтры кстати тоже генерила.
посмотрите оба проекта мельком - что больше понравится то и используйте)
но ИМХО правильнее допилить сразу виртуальный драйвер)

PS или вы имели в виду, что хотите два драйвера собрать?
можно обойтись одним виртуальным портом) фильтр лишний.
« Последнее редактирование: 30-06-2011 18:42 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Natur_Keks
Интересующийся

ru
Offline Offline

« Ответ #11 : 14-07-2011 10:10 » 

Спасибо за помощь, работа над драйвером движется, но вот возникла одна проблема:
нужно задержать обработку запроса IOCTL_READ - и если я пишу в ReadDispatch(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp):
Код:
...
ReadIRP = Irp;                 // сохраняем IRP (ReadIRP - глобальная переменная)
IoMarkIrpPending(Irp);         // помечаем Irp как отложенный
status = STATUS_PENDING;       // выставляем статус "Отложенный"
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
...
То как мне в дальнейшем его обработать?
Вариант просто написать (в обработчике другого IOCTLa) что-то типа:
Код:
...
user_buf = ReadIRP->AssociatedIrp.SystemBuffer;            // указатель на сист. буфер чтения/записи отложенного запроса
Out_Len = IoGetCurrentIrpStackLocation(ReadIRP)->Parameters.Read.Length;
RtlMoveMemory(user_buf, sys_buf, Out_Len);            // sys_buf[] - буфер, где хранятся необходимые для передачи данные      
ReadIRP->IoStatus.Information = In_Len;                    // In_Len - количество передаваемых байт
ReadIRP->IoStatus.Status = STATUS_SUCCESS;                 // завершаем отложенный IRP
...

приводит к синему экрану
***STOP: 0x0000008E(0xC0000005, 0xF8128406, 0xB1F4A904, 0x00000000)
***Driver_COM.sys - Address F8128406 base at F8120000, DateStemp 4e1e7308

Читал про очереди (queue), не совсем понятно как этот механизм реализуется.
« Последнее редактирование: 14-07-2011 10:12 от Natur_Keks » Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 14-07-2011 12:35 » 

первое не совсем верно. точнее совсем не верно.
вы должны пометить пакет как отложенный (при помощи IoMarkIrpPending) и вернуть STATUS_PENDING из диспечерской функции (буквально return STATUS_PENDING )
и только когда вы решите, что уже все сделали, то должны вызвать IoCompleteRequest для этого IRP (предварительно заполнив Irp->IoStatus.Status/ReadIRP->IoStatus.Information)

кстати там достаточно  много нюансов связанных с различными случаями....
настоятельно рекомендую к очень-очень неспешному и внимательному прочтению несколько раз Уолтера Они, 5тую главу.
там и про очереди все написано, и про обработку IRP.
« Последнее редактирование: 14-07-2011 12:40 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Serge Roussak
Новенький

by
Offline Offline

« Ответ #13 : 16-07-2014 12:59 » 

Natur_Keks, скажите, получилось ли у Вас что-нибудь по этой теме?
Записан
Natur_Keks
Интересующийся

ru
Offline Offline

« Ответ #14 : 21-07-2014 04:04 » 

получилось процентов на 70 Улыбаюсь)  то есть взял по сути готовый драйвер виртуального com порта от NuMegaStudio, добавил свой обработчик IOSTL, ещё там кое-чего, получилось из-за отсутствия опыта достаточно  криво - возможны были "подвисания драйвера"(запрос приходит, ему статус "ожидания" выставляется и не освобождается), но для той локальной задачи для которой это всё делалось - типа устроило. И так и в некоторых местах нашей родины и работает этот мой кривоватый драйвер Улыбаюсь))
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines