Статья расчитана на читателей, знакомых с устройством и работой LPT-порта.
Почитать о LPT-портах можно например здесь:
Я отношусь к тому сорту людей, которые любят подключать к компьютеру разные нестандартные устройства, а так же самому их собирать и работать с ними посредством Visual Basic. Собрав в очередной раз такое устройство (нечто типа расширителя LPT-порта) и подключив его к LPT-порту компьютера я запустил Visual Basic. И с ужасом обнаружил, что в нем напрочь нет никаких средств работы с LPT-портом. Немного погоревав и поматерившись, я полез в интернет с цель выяснить - "А кагого, собственно, хрена их нету". И прежде я спросил себя - "А кагого, собственно, хрена я хочу". И ответил сам себе - "Я хочу в VB манипулировать любым битом любого LPT-порта как мне вздумается, а так же перехватывать их аппаратные прерывания и обрабатывать их (IRQ7 для LPT1) и еще при этом я хочу захватить порт в свое монопольное использование, чтобы никакая другая сволочь, включая спулер печати, не лезла в порт в это время и не создавала мне там кашу. Все это я хочу делать в Windows 9x/Me/NT/2000/XP".
И выяснил я вот что:
- Нет таких средств и в других средствах разработки софта для Win32 - включая Delphi и Visual C. Я имею в виду полное и удобное средство. Выполнение встроенных ассемблерных инструкций in и out - не в счет. (здесь горе мое сильно уменьшилось :).
- Все устроиства в Win32 имеют свои драйверы, и программы работают с устройствами посредством них. Стало быть, я должен написать драйвер для своего устройства. Микрософт советует создавать драйверы специальным инструментом - DDK (Driver Development Kit - набор для разработки драйверов). Пожалуй, это самый логичный и честный путь решения проблемы. Но вот его недостатки:
- Я должен усовершенствовать свои знания языков Ассемблер и Си.
- Я должен усовершенствовать свои знания английского языка, поскольку мне не удалось найти русскоязычной документации по этому вопросу.
- Я должен разобраться в структурах драйверов, которые совершенно различны для Windows 9x/ME и для Windows NT/2000/XP.
- Я должен научиться отлаживать драйверы и привыкнуть к неизбежным "синим экранам смерти", многократно появляющимся в процессе отладки драйвера при малейших ошибках.
- Я должен установить DDK (или другой подходящий инструмент).
- Наконец, на все это уйдет довольно много времени.
Слабо прыгнуть в такую прорубь? Я решил пока поискать другие проруби.
- Еще один путь - использовать драйверы, встроенные в Windows. Однако в Windows нет функциональностей для общего доступа к портам, есть только специфичные функции. Например API для доступа к принтерам, для доступа к последовательным портам. В VB есть объект Printer, есть контрол MSComm. Но мое устройство совсем не похоже на принтер, значит этот путь не для меня. Что касается MSComm - это прекрасный инструмент для работы со стандартными и нестандартными устройствами через COM-порт. У меня еще не было ситуации, когда бы он меня не удовлетрорил. Если читатели захотят, я расскажу о нем в другой статье.
- С портами можно работать и без драйверов. В интернете есть много бесплатных DLL, позволяющих это делать. Например:
Однако, вот их недостатки:
- Все они не умеют перехватывать прерывания.
- Все они работают "не честно" по отношению к Windows, т.е. не спрашивают у него "а можно я поработаю вот с этим портом", а просто нагло лезут в порт, при этом возможно создавая кашу для "честных" программ.
- Наконец, нет гарантии, что не наступит ситуация, когда эти DLL не смогут выполнить
своих функций (например многие не работают в Windows NT/2000/XP).
Кого устраивает такой способ - дальше можно не читать. Меня не устраивает.
- Существуют так называемые драйверы общего назначения (generic), которые обеспечивают
"прозрачный" доступ к аппаратуре под Win32 непосредственно из Win32-приложения.
Например:
- DriverX фирмы Tetradyne Software (http://www.tetradyne.com/)
- IO ActiveX Communications module фирмы JSPayne (http://www.jspayne.com/io/home.html)
- WinRT, WinRT-VB, WinDK фирмы BSQUARE (http://www.bsquare.com/)
- Parallel Port Direct I/O Access package - Peter Shoebridge (http://www.zeecube.com/driver.htm)
- TVicHW32 & TVicPort & TVicLPT фирмы EnTech Taiwan (http://www.entechtaiwan.com/tools.htm)
Все они имеют разные недостатки, из них главный - они не бесплатные.
Немного поизучав их, я решил остановиться на TVicHW32 (http://www.entechtaiwan.com/tools.htm).
Он представляет из себя драйвер (VxD для Windows 9x/Me и kernel-mode драйвер для Windows NT/2000/XP)
и DLL, которую можно подключить к своему проекту и через нее работать с драйвером.
Это универсальный инструмент для работы с различной аппаратурой непосредственно из Win32 приложения.
На сайте доступна для скачивания полнофункциональная демо-версия с единственным ограничением -
при каждом открытии драйвера появляется окно с напоминанием о необходимости регистрации.
Пользователь может опробовать инструмент, отладить свою программу и решить - покупать или нет.
Вот его преимущества по сравнению с другими инструментам:
- Все сделано вразумительно, понятно и изящно (по крайней мере - мне так показалось).
- Он мало "весит" - около 100 килобайт (драйверы и DLL), не содержит лишнего мусора.
- Есть примеры для Visual Basic.
- Есть русская документация (FAQ, описание функций, описание применения).
- Автор - русский программист, с ним можно связаться по email по-русски, если возникнут вопросы.
Есть на этом сайте и другой инструмент специально для работы с LPT - TVicLPT.
(и еще много других интересных инструментов).
Представляет из себя драйвер и OCX - компонент.
Однако во-первых он еще не совсем доделан (пока нет секции LPT Communications).
Во-вторых в данном случае мне больше нравится работать через DLL - так обеспечивается бОльшая производительность.
Возможно я расскажу о нем в другой статье.
Скачав и установив TVicHW32, я почитал документацию и залез в папку с примерами по VB.
Там есть файл TVicLib.bas с объявлениями всех функций, констант, типов.
Есть папки с примерами по каждой секции инструмента.
Первым делом запустил пример по работе с LPT.
Попробовал захватить порт и после этого запустить принтер и сканер, которые у меня были подключены
к этому же порту.
Оба отвалились с сообщением, что порт недоступен.
Затем поробовал наоборот - занять порт принтером (и в следующий раз сканером) и захватить его в TVicHW32.
Получил ошибку, что порт уже занят другим приложением.
Все работает "по-честному".
Можно узнать количество LPT, установленных на машине, выбрать "текущий" LPT, узнать его базовый адрес.
Для удобства в TVicHW32 есть функции GetPin и SetPin, которые позволяют прочитать/записать электрический
уровень с заданного контакта 25-контактного разъема текущего LPT (естественно на которых это возможно).
Можно и просто читать/писать байты в любой регистр LPT, зная его базовый адрес (где поддерживается
соответствующая операция).
Поигрался немного со своим устройством через эти функции.
Мое устройство "зашевелилось". Все сигналы нормально пишутся/читаются.
Попробовал перехватить прерывание (для LPT1 это IRQ7).
Для этого есть функция UnmaskIRQ, которой нужно передать номер прерывания и с помощью AdressOf
указать процедуру-обработчик, находящуюся в стандартном модуле.
После этого надо функцией ForceLPTIrq включить поступление прерываний от LPT на контроллер прерываний машины.
Кроме того под Windows NT/2000/XP надо в панели управления в свойствах LPT включить обработку
прерываний (по умолчанию она выключена).
Попробовал - на все сигналы, поступающие от моего устройства по линии Acknowledge (10-я ножка на разъеме LPT)
срабатывает установленная мной процедура.
В простейшем случае, для пробы, можно просто замыкать например разогнутой скрепкой эту ножку
на "земляную" D-образную оболочку разъема (или на ножки с 18-ой по 25-ю).
Есть ограничения на частоту следования этих сигналов. В основном это реалии Windows.
Подробно об этом можно посмотреть в FAQ.
"Цоколевку" разъема LPT (и кучи других разъемов и кабелей) можно посмотреть здесь-
http://www.hardwarebook.net/
Кроме этого в TVicHW32 опять же для удобства есть функции для работы с сигналами Centronix.
Можно прочитать состояние линий Acknowledge, BUSY, Paper End, Select, ERROR.
Можно сформировать короткий импульс (строб) на линиях STROBE и INIT, установить активным или пассивным
сигнал AUTOFD, выдать сигнал SLCTIN, выдать на печать один символ.
Кроме того можно функцией SetLPTReadMode перевести LPT в режим чтения региста данных (контакты 2-9).
Для этого LPT должен быть "двунаправленным" и сконфигурированным в BIOS SETUP как PS/2 compatible или ECP.
Перед записью в регистр данных он должен быть переключен обратно в режим записи функцией SetLPTWriteMode.
Наконец можно добавить свой "нестандартный" LPT при помощи функции AddNewLPT и работать с ним как с обычным LPT.
Есть один недостаток. В TVicHW32 отсутствует функция, позволяющая узнать, есть ли у заданного
LPT аппаратное прерывание и, если есть - узнать его номер.
Как выяснилось, это нетривиальная задача.
На этом же сайте есть бесплатный пакет TVicRes.
Это исходный код класса, созданного в Delphi и предназначенного для получения информации об
аппаратных ресурсах машины. Я портировал его в VB. Получилось это у меня не очень красиво,
и я так и не разобрался, как однозначно определить номер IRQ для заданного LPT под разными версиями
Windows на разных компьютерах. Но под Windows 98 и XP он вроде выдает IRQ правильно.
Скачать переведенный в VB TVicRes можно здесь -
http://nikkollo.pisem.net/files/TVicRes_VB.zip
Ну чтож, все мои потребности в отношении LPT полностью удовлетворены.
Что еще есть в TVicHW32:
- Функции общего назначения
Можно открыть/закрыть драйвер и проверить открыт ли он.
Причем открыт он может быть двумя приложениями одновременно.
- Функции работы с физической памятью
Для того, чтобы получить доступ к памяти, заданной ее физическим адресом, необходимо отобразить этот
физический адрес на пространство линейных адресов текущего процесса. TVicHW32 содержит функцию
MapPhysToLinear, которая решает эту задачу и возвращает обычный указатель на область памяти,
заданную ее физическим адресом и размером.
С полученным указателем можно работать непосредственно, а можно и при помощи набора дополнительных функций,
которые обеспечивают доступ к физической памяти побайтно, пословно или двойными словами.(Актуально для VB,
где непосредственная работа с указателями затруднена).
- Работа с портами ввода/вывода
Набор функций работы с портами ввода/вывода включает две группы функций - для ввода/вывода одиночных байт
(слов, двойных слов) и для ввода/вывода массивов данных. Работа с портами возможна в двух режимах - "Soft Mode"
и "Hard Mode". "Soft Mode" обеспечивает большее быстродействие, но может дать неверные результаты,
если данный порт уже используется другим драйвером. "Hard Mode" работает медленнее, но обеспечивает
абсолютно надежный доступ к портам, даже используемым другими драйверами.
- Обработка аппаратных прерываний
Можно запустить/остановить процесс обработки прерываний, указав номер прерывания и установить свою
процедуру-обработчик этого прерывания.
TVicHW32 позволяет установить несколько обработчиков прерываний или использовать один и тот же обработчик
прерываний для нескольких IRQ.
Есть ограничения (подробнее см. FAQ):
- Под всеми версиями Windows нельзя использовать IRQ0 (системный таймер);
- Под Windows NT/2000 нельзя использовать прерывание от RTC (часы реального времени).
- Есть расширенные возможности для обработки "Level Sensitive" прерываний.
- Получение информации о дисках IDE, включая серийный номер
TVicHW32 позволяет получить информацию о жестких дисках IDE, установленных на компьютере, включая модель диска,
серийный номер, геометрию и другие параметры. Не путать с серийным номером раздела диска, записанным при
форматировании и возвращаемым функцией GetVolumeInformation! Информация, считываемая TVicHW32, записывается
производителем жестких дисков раз и навсегда и не может быть измененена никаким форматированием.
Многие хотят использовать эту информацию для защиты своих программ,
хотя автор этого делать не рекомендует (подробнее см. FAQ).
- Доступ к информации об устройствах PCI
Можно получить информацию о всех установленных устройствах на шине PCI (включая AGP и PCMCIA).
- Работа с клавиатурой
TVicHW32 позволяет послать управляющие коды (скэн-коды) непосредственно в контроллер клавиатуры на самом
нижнем уровне (аппаратном), имитируя тем самым нажатие/отжатие клавиш.
Можно также установить процедуру-перехватчик ("хук"), которая будет перехватывать все нажатия/отжатия клавиш клавиатуры.
- Выделение памяти под буферы DMA
TVicHW32 не реализует какие-либо функции DMA, пользователь может сделать это самостоятельно, используя другие функции.
Но TVicHW32 позволяет решить одну из ключевых задач по выделению буфера памяти для операций DMA.
К этой памяти выдвигается ряд важных требований.
Подробности см. в описании функций.
- Выполнение пользовательского кода в Ring 0 CPU
Функция RunRing0Function позволяет выполнить Вашу процедуру в нулевом кольце защиты процессора (ring 0).
Это означает, что в этой функции можно использовать любые привилегированные команды процессора,
которые до этого были доступны только в драйверах.
Однако ее нет в объявлениях функций для VB, и я не знаю, как ее может использовать VB-программист.
Но она есть в драйвере и пользователь сам сможет найти пути ее использования.
Стоит этот инструмент (персональная лицензия) - 2000 руб. для граждан и предприятий России.
А теперь ВНИМАНИЕ!
Я связался с автором - Виктором Ижикеевым и он любезно согласился сделать скидку
для всех читателей этой статьи.
Теперь Вы можете приобрести его за 1000 руб.
Для этого нужно отправить почтовым переводом 1000 руб. по адресу:
450005, Уфа
а/я 94
Ижикееву Виктору Ивановичу
После этого отправить E-mail по адресу
nikkollo@mail.ru
в котором нужно указать следующие данные:
Предмет покупки - TVicHW32.
Фамилия, Имя, Отчество полностью.
Номер квитанции почтового перевода.
В ответ на это письмо Вы получите по E-mail в течении нескольких
дней зарегистрированную версию TVicHW32.
Предложение действительно только для частных лиц - граждан России,
любая перепродажа или дарение за рубеж - запрещается.
Техническая поддержка TVicHW32 для VB-программистов -
nikkollo@mail.ru.
Желаю всем удачи в непростом деле работы с аппаратурой в Visual Basic.
Здесь Вы можете скачать переведенный в VB из Delphi класс TVicRes.
Права на все упомянутые здесь торговые марки принадлежат их законным владельцам.
Николай Андреев.
nikkollo@mail.ru
Февраль 2003 г.