CITKIT.ru
3 терабайта свободного софта!
Logo    
IT-рынок Новости мира IT Океан(!) софта на CITKIT.ru Форумы Поступления в библиотеку Учебный центр Курилка
CitForum    CITForum на CD Море(!) аналитической информации! :: CITFORUM.RU
IT-консалтинг Software Engineering Программирование Open Source СУБД Безопасность Internet Сети Операционные системы Hardware

16.05.2005

Google
WWW CITForum.ru

Новости мира IT:

  • 11.05 - Intel создает свою группу по Open Source
  • 11.05 - Банк контролирует использование USB устройств при помощи DeviceLock
  • 11.05 - Microsoft устранила опасную дыру в Windows
  • 11.05 - "Корпорация ОСС" создает антимонопольный альянс операторов IP-телефонии
  • 11.05 - В Mac OS X найдены множественные уязвимости
  • 11.05 - "Билайн" запускает услугу "Мобильная почта"
  • 11.05 - Две критические уязвимости в браузере Firefox 1.0.3
  • 11.05 - IBM покупает начинающую Open Source-компанию Gluecode
  • 11.05 - Microsoft готова к битве с Open Source за школы
  • 11.05 - Sun завершит "открытие" Solaris в ближайшие 45 дней
  • 11.05 - Создатели браузера Firefox выпускают юбилейные монеты в честь 50 миллионов скачанных копий
  • 11.05 - Вышла пятая версия мобильной ОС от Microsoft
  • 11.05 - Поисковые движки умнеют быстрее, чем люди
  • 11.05 - Фишеры постоянно совершенствуются
  • 11.05 - Специалисты прогнозируют появление аналога Google Adsense от "Яндекс"
  • 06.05 - ICANN озаботилась проблемой торговых марок
  • 06.05 - Google патентует сортировку новостей
  • 06.05 - Intel готовит двуядерные процессоры второго поколения
  • 06.05 - Schoolforge-UK и OSC продвигают Open Source в школы
  • 06.05 - Новая версия рекламной программы подстрекает пользователей купить ПО для своего лечения
  • 06.05 - Microsoft продает ряд своих закрытых разработок
  • 06.05 - Google Labs анонсировал ускоритель интернета
  • 06.05 - Microsoft подвешивает пиратам "морковку"
  • 06.05 - В США входят в обиход "интеллектуальные" тележки для супермаркетов
  • 06.05 - Microsoft работает над аналогом PDF
  • 05.05 - Yahoo video search теперь доступен массам
  • 05.05 - Алмазы помогут бороться с хакерами
  • 05.05 - Интернет-охоту хотят запретить
  • 05.05 - Microsoft привлекает блоггеров для теста Longhorn
  • 05.05 - Основатель Red Hat предложил Стиву Джобсу помощь в решении проблемы с торговой маркой
  • 05.05 - Компьютерная система оргкомитета Кубка мира по футболу 2006 года пострадала от червя Sober
  • 04.05 - Cisco Systems представила многофункциональный продукт Adaptive Security Appliance 5500
  • 04.05 - Администрация Евросоюза поддержала идею всеевропейской интернет-библиотеки
  • 04.05 - Компьютерный вирус дарит билеты на чемпионат мира по футболу
  • 04.05 - Лаборатория Касперского: Обзор вирусной активности - апрель 2005
  • 04.05 - Microsoft хочет отсудить у россиянина два домена
  • 04.05 - Сделка между Lenovo и IBM завершена
  • 04.05 - Эпидемия червя Sober.p зафиксирована в Западной Европе
  • 04.05 - Panda Software публикует отчет о вирусной активности за апрель
  • 03.05 - Институт SANS обновил список наиболее опасных уязвимостей

    Архив новостей >>>


  • 2005 г.

    Работа с параллельным портом под Windows

    Кузин Ю.Р., «Королевство Delphi»

    Прочитал я недавно где-то в интернете, что драйвер параллельного порта в Windows 2000 и Windows XP непосредственно поддерживает работу с устройствами в режимах EPP и ECP, и решил проверить, в чем это выражается и как это использовать. Меня больше интересовал режим EPP, который более практичен, так как представляет собой "вынос" шины ISA за пределы компьютера. Попытки найти что-то путное в интернете привели к статье Тарасенко, где неплохо изложены общие принципы работы с драйвером параллельного порта. Но этого было недостаточно, поэтому пришлось лезть на MSDN и посмотреть, что по этому поводу говорит Майкрософт. Далекий от совершенства online-справочник сориентирован в основном на разработчиков драйверов, поскольку предполагает специальные знания на каждом шагу. Поэтому одновременно с библиотечным разделом Operating a Parallel Device Attached to a Parallel Port мне пришлось держать открытыми некоторые файлы из DDK. Возможно потому, что я сам скорее железячник, чем программист, я избегаю написания собственных драйверов. Ведь для того, чтобы мое устройство заработало на чужом компьютере, туда придется поставить собственный драйвер кустарного производства, а это, во-первых, неудобно, во-вторых, может привести к "непредсказуемому поведению системы": начиная от дырок для вирусов (что всегда очень трудно просчитать) и заканчивая тривиальным крахом системы. Как мне кажется, большая часть пользователей склоняется к применению того, что нам досталось от Microsoft в том убогом виде как это есть. Именно для этих людей я и решил написать статью, чтобы помочь им избежать трудностей, с которыми я столкнулся.

    Начну с того, что объясню общие правила работы клиента с каким-либо драйвером Windows. Вообще говоря, под клиентом понимается или другой драйвер, работающий в режиме ядра, или приложение, работающее в пользовательском режиме. В MSDN, к сожалению, не часто проводят эту грань различия в том или ином документе, а разница есть: не все, что может использовать клиент-драйвер, может применить клиент-приложение. Проходит время пока следуя тексту, наконец поймешь, что вот именно ЭТО пригодно только для драйвера. Windows следует идеологии многоуровневых драйверов. В качестве примера можно привести драйвер от производителя принтера, использующий для своей работы драйвер параллельного порта Microsoft, тот же самый которым мы хотели бы воспользоваться непосредственно из приложения. Забегая вперед скажу, что поскольку мое тестовое устройство все-таки не захотело сразу работать из под Windows, несмотря на нормальную работу в EPP режиме из под DOS, мне пришлось, вооружившись цифровым осциллографом с памятью и логическим анализатором, более внимательно изучить, что же все-таки предлагает Майкрософт за рамками собственной документации. Результаты и побудили меня к написанию этой статьи.

    Работа с драйвером устройства (bus driver) из приложения сводится к четырем шагам:

    1. открыть устройство;
    2. настроить нужный режим;
    3. читать из и писать в устройство;
    4. закрыть устройство.

    Все эти операции проделываются с помощью механизма запросов ввода-вывода драйвера (IRPs). Пользователю доступны функции, формирующие такие запросы. В Delphi для их использования нужно подключить модуль Windows.pas:

    uses Windows;

    1 ШАГ

    Функция CreateFile формирует запрос, открывающий устройство. Например, такой вызов открывает порт LPT1 для операций асинхронного чтения и записи:

    hLPT := CreateFile('LPT1', GENERIC_READ or GENERIC_WRITE, 0, nil,
            OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
    

    Если все запросы должны выполняться синхронно, то вызов будет выглядеть так:

    hLPT := CreateFile('LPT1', GENERIC_READ or GENERIC_WRITE, 0, nil,
            OPEN_EXISTING, 0, 0);
    

    Здесь hLPT - дескриптор устройства, который затем используется при обращении к его драйверу:

    hLPT: THandle;

    2 ШАГ

    Управление работой устройства, определение его состояния, поддержка режимов и т.д. осуществляется с помощью запросов IRP_MJ_DEVICE_CONTROL и IRP_MJ_INTERNAL_DEVICE_CONTROL. В режиме пользователя поддерживается только запрос первого типа - он формируется с помощью функции DeviceIoControl. В качестве одного из параметров этой функции фигурирует код операции (IOCTL), который определяет действие, выполняемое драйвером. Для некоторых устройств (например, COM-порта) в API Win32 определены функции управления, которые служат оболочкой для DeviceIoControl при определенном значении IOCTL. Это делает программу более наглядной и читаемой. Для параллельного порта я такой возможности не обнаружил, хотя это не вызывает трудностей, поскольку никто не мешает описать такие функции самому.

    Тело такой функции будет сводится к вызову DeviceIoControl с определенным набором параметров. Гораздо более неприятный момент заключается в том, что для LPTx невозможно определить коммуникационное событие, чтобы затем обработать его в отдельном потоке как это можно сделать, например, для последовательного порта с помощью вызова SetCommEvents. Поэтому о готовности Вашего устройства к каким-либо операциям, оно может сообщить, только выставив флаг в некотором своем регистре, который Вы будете регулярно опрашивать (например, по таймеру), что конечно не очень удобно и эффективно. Вообще говоря, в режиме EPP параллельного порта определено внешнее прерывание по положительному переходу на линии 10 (nACK), и драйвер содержит его обработчик. Доступ к обработчику можно получить с помощью IRP_MJ_INTERNAL_DEVICE_CONTROL, но только в режиме ядра. Еще раз хочу подчеркнуть, что все изложенное - результат моих собственных поисков, поэтому не исключено, что какое-то решение от Microsoft для обработки событий параллельного порта в режиме пользователя существует. Если кто-нибудь знает, поделитесь. В конце статьи я укажу E-mail для связи.

    Рассмотрим по порядку все коды операций доступные в качестве аргумента в вызове DeviceIoControl при работе с LPTx. Код представляет собой 32-разрядное слово и строится по определенному правилу, которое учитывает тип устройства, вид и метод доступа. Не вдаваясь в подробности, перечислим значения кодов для управления параллельным портом и их идентификаторы, принятые в Microsoft.

    Идентификатор кода IOCTL Значение кода
    IOCTL_IEEE1284_GET_MODE $160014
    IOCTL_IEEE1284_NEGOTIATE $160018
    IOCTL_PAR_GET_DEFAULT_MODES $160028
    IOCTL_PAR_GET_DEVICE_CAPS $160024
    IOCTL_PAR_IS_PORT_FREE $160054
    IOCTL_PAR_QUERY_DEVICE_ID $16000C
    IOCTL_PAR_QUERY_DEVICE_ID_SIZE $160010
    IOCTL_PAR_QUERY_INFORMATION $160004
    IOCTL_PAR_QUERY_LOCATION $160058
    IOCTL_PAR_QUERY_RAW_DEVICE_ID $160030
    IOCTL_PAR_SET_INFORMATION $160008
    IOCTL_PAR_SET_READ_ADDRESS $160020
    IOCTL_PAR_SET_WRITE_ADDRESS $16001C
    IOCTL_SERIAL_GET_TIMEOUTS $1B001C
    IOCTL_SERIAL_SET_TIMEOUTS $1B0020

    Обращаю внимание читателя, что статья приготовлена для сайта Delphi, поэтому все примеры кода и т.п. приводятся на Паскале. Коды в таблице указаны в шестнадцатеричном формате (т.е. 0х160014 и т.д.).

    Код IOCTL_IEEE1284_GET_MODE предназначен для формирования запроса текущего режима порта:

    const
    IOCTL_IEEE1284_GET_MODE = $160014;
    
    type
    PARCLASS_NEGOTIATION_MASK = record
      usReadMask: word;
      usWriteMask: word;
    end;
    PPARCLASS_NEGOTIATION_MASK = ^PARCLASS_NEGOTIATION_MASK;
    
    var
    Mode: PARCLASS_NEGOTIATION_MASK;
    lpOverlapped: POverlapped;
    ret: DWORD;
    
    DeviceIoControl(hLpt, IOCTL_IEEE1284_GET_MODE, nil, 0, @Mode,
                    sizeof(PARCLASS_NEGOTIATION_MASK), ret, lpOverlapped);
    

    Если запрос синхронный, то он выглядит так:

    DeviceIoControl(hLpt, IOCTL_IEEE1284_GET_MODE, nil, 0, @Mode,
                    sizeof(PARCLASS_NEGOTIATION_MASK), ret, nil);
    

    @Mode - указатель на буфер, в котором драйвер возвращает текущий режим. Следующий параметр сообщает драйверу размер буфера, а параметр ret возвращает размер структуры, через которую передаются данные. Структура PARCLASS_NEGOTIATION_MASK имеет два поля: usReadMask - определяет режим работы порта при чтении, а usWriteMask - при записи. Вот возможные значения этих переменных:

    const
    	NONE	= $0000;
    
    // SPP modes
    	CENTRONICS	= $0001;	// Только для записи
    	IEEE_COMPATIBILITY	= $0002;	// Только для записи
    	NIBBLE	= $0004;	// Только для чтения
    	CHANNEL_NIBBLE	= $0008;	// Только для чтения
    	BYTE_BIDIR	= $0010;	// Только для чтения
    
    // EPP modes
    	EPP_HW	= $0020;	// Аппаратный EPP
    	EPP_SW	= $0040;	// Программный EPP
    
    // ECP modes
    	BOUNDED_ECP	= $0080;	// Упрощенный ECP
    	ECP_HW_NOIRQ	= $0100;	// Аппаратный ECP без IRQ
    	ECP_HW_IRQ	= $0200;	// Аппаратный ECP с IRQ
    	ECP_SW	= $0400;	// Программный ECP
    

    Сразу после того, как порт открыт, он устанавливается в режим CENTRONICS по записи и NIBBLE по чтению.

    Код операции IOCTL_IEEE1284_NEGOTIATE предназначен для согласования режима работы порта и устройства:

    const
    IOCTL_IEEE1284_NEGOTIATE = $160018;
    
    var
    ReqMode, LptMode: PARCLASS_NEGOTIATION_MASK;
    
    ReqMode. usReadMask:= $7FF;	// Тестировать все режимы для чтения
    ReqMode. usWriteMask:= $7FF;	// Тестировать все режимы для записи
    DeviceIoControl(hLpt, IOCTL_IEEE1284_NEGOTIATE,
    	@ReqMode, sizeof(PARCLASS_NEGOTIATION_MASK),
    	@LptMode, sizeof(PARCLASS_NEGOTIATION_MASK),
    	ret, lpOverlapped);
    

    @ReqMode указывает на структуру PARCLASS_NEGOTIATION_MASK, которая содержит маску тестирования режимов для работы с устройством. Маска представляет собой произвольную сумму, указанных выше констант.

    Драйвер выполняет последовательность согласования с устройством для каждого указанного в маске режима в соответствии со спецификацией IEEE 1284. Если соответствующий бит в маске выставлен в 1, то данный режим проверяется на возможность его применения при работе с подключенным устройством, а затем выбирается режим с максимальной пропускной способностью. Этот режим устанавливается в качестве текущего, а соответствующие ему значения драйвер возвращает в структуре LptMode. Кроме указанных выше констант, однозначно обозначающих режимы, Windows определяет еще две маски для запроса:

    EPP_ANY	= $0060;	// любой из EPP
    ECP_ANY	= $0780;	// любой из ECP
    

    Чтобы запросить проверку всех режимов, нужно указать $7FF.

    После согласования режима драйвер не переводит выходные линии порта в состояние, соответствующее выбранному режиму! Он оставляет их в состоянии инициализации:

    Сигнал Конт. Состояние
    nSelectIn(1284 Active) 17 низкий
    nAutoFeed 4 высокий
    nStrobe 1 высокий
    Initialize 16 высокий

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

    Код IOCTL_PAR_GET_DEFAULT_MODES применяется для запроса режима драйвера по умолчанию: CENTRONICS для записи и NONE для чтения. Может быть возможны и другие варианты, поэтому приведу команду целиком.

    const
    IOCTL_PAR_GET_DEFAULT_MODES = $160028;
    
    var
    Mode: PARCLASS_NEGOTIATION_MASK;
    
    DeviceIoControl(hLpt, IOCTL_PAR_GET_DEFAULT_MODES, nil, 0, @Mode,
                    sizeof(PARCLASS_NEGOTIATION_MASK), ret, lpOverlapped);
    

    В структуре Mode возвращается режим по умолчанию в той же манере, что и для запроса текущего режима IOCTL_IEEE1284_GET_MODE.

    Код IOCTL_PAR_GET_DEVICE_CAPS формирует запрос поддержки устройством различных режимов параллельного порта. Майкрософт заявляет о поддержке их драйвером спецификации IEEE1284, хотя есть немало существенных исключений, если доверять сайту экспертов этого протокола http://www.fapo.com/. К сожалению, у меня нет на руках самого документа, потому что IEEE просит за него около $100, поэтому дать 100% гарантию, что Майкрософт не прав не могу. Если у кого-то есть pdf оригинала, поделитесь с народом. Я говорю про IEEE1284.3 от 1994 года. А то без исходников происходит вечная путаница. Спецификация IEEE1284 определяет пять основных режимов:

    • совместимости (Centronics);
    • полубайтный (Nibble);
    • байтный (Byte_Bidir);
    • EPP;
    • ECP.

    Майкрософт добавляет несколько подрежимов:

    • адресуемый полубайтный (CHANNEL_NIBBLE);
    • программный EPP (EPP_SW);
    • программный ECP (ECP_SW);
    • упрощенный ECP (BOUNDED_ECP).

    Запрос с кодом IOCTL_PAR_GET_DEVICE_CAPS похож на IOCTL_IEEE1284_NEGOTIATE с той разницей, что он не меняет режим драйвера, а только проводит циклы согласования с устройством для всех(!!!) режимов, чтобы выяснить какие из них поддерживаются. Затем результат проверки возвращается в уже известной структуре PARCLASS_NEGOTIATION_MASK.

    const
    IOCTL_PAR_GET_DEVICE_CAPS = $160024;
    
    var
    LptMode: PARCLASS_NEGOTIATION_MASK;
    
    DeviceIoControl(hLpt, IOCTL_PAR_GET_DEVICE_CAPS, nil, 0, @LptMode,
                    sizeof(PARCLASS_NEGOTIATION_MASK), ret, lpOverlapped);
    

    Если выдать этот запрос на пустой порт (без устройства), то будет отмечена поддержка только CENTRONICS и IEEE_COMPATIBILITY. Соответственно и включить никакие другие режимы будет невозможно. Исключение составляет только NIBBLE, который согласно спецификации должен поддерживаться всеми IEEE1284-устройствами. Чтобы использовать другой режим, например EPP, необходимо подключить устройство, поддерживающее последовательность согласования для этого режима. В ходе цикла согласования хост выставляет на шину данных байт совместимости, который уникален для каждого режима:

    EPP		01000000
    ECP		00x10000
    byte mode	00000001
    

    Затем по отрицательному переходу сигнала Paper End (конт. 12) хост проверяет уровень на линии Select (конт. 13). Если устройство подтверждает режим, то на эту линию оно должно выставить 1, в противном случае - 0. Байт совместимости имеет очень удобную структуру для его аппаратной обработки: за каждым режимом закреплен определенный бит, который выставляется в единицу только для этого режима. Поэтому, скажем для EPP, достаточно защелкнуть 6 бит (считая от 0) по сигналу nStrobe (1 конт.) и вернуть его по линии Select. Если сигнал Select просто навсегда установить в 1 (подтянуть к +5В), то устройство будет подтверждать все режимы.

    Что касается других сигналов, то для согласования работы с драйвером параллельного порта достаточно на линях nError (конт. 15) и Paper End выставить лог. 1, а для формирования сигнала завершения цикла согласования можно по линии nACK (конт. 10) вернуть в хост уровень nAutoFeed (конт. 14). Так как оборванный вход LPT-порта воспринимается как 1, то для реализации этой последовательности достаточно просто воткнуть в разъем перемычку на контакты 10 и 14. Такое "устройство" драйвер распознает как поддерживающее следующие режимы: CENTRONICS, IEEE_COMPATIBILITY, NIBBLE, CHANNEL_NIBBLE, BYTE_BIDIR, EPP_SW, - т.е. все режимы, кроме аппаратного EPP и всех разновидностей ECP. Дело в том, что согласование ECP (который, кстати, придуман Microsoft в сотрудничестве с HP) требует более сложной последовательности согласования, и простой аппаратурой здесь не обойтись. В интернете свободно распространяется файл ecp_reg.pdf от Microsoft с подробным описанием режима.

    Ситуация с аппаратным EPP еще более оригинальная: при запросе этого режима на разъеме порта……..ничего не происходит!!! А драйвер сообщает, что режим не поддерживается. Отсутствие даже намека на попытку согласования EPP_HW позволяет сделать вывод о том, что именно сам драйвер не поддерживает этот режим,- возможно из-за каких-то трений между Microsoft и Intel - автором EPP, может из-за технических нестыковок. Ниже сопоставляются сигналы в режимах аппаратного и программного EPP, а также применение соответствующих линий в цикле согласования.

    № конт. Centronics Аппарат. EPP Прогр. EPP Согласование
    1 nStrobe nWrite nWrite nStrobe
    10 nAck Interrupt ? nAck
    11 Busy nWait nWait -
    12 Paper End - - PE
    13 Select - - Select
    14 nAutoFeed Data Strobe Data Strobe nAutoFeed
    15 nError - - nError
    16 nInitialize nReset Address Strobe -
    17 nSelectPrinter Address Strobe 1284 Active 1284 Active

    Здесь надо обратить внимание на две вещи. Во-первых, в программной реализации EPP Майкрософт случайно или намеренно перепутал сигналы местами: строб адреса теперь на контакте 16 разъема, т.е. он соответствует сигналу nInitialize. На контакте 17 остается признак интерфейса 1284, как и во всех остальных режимах, включая последовательность согласования. Этот сигнал можно использовать как ChipSelect (активный высокий). Сигнала сброса nReset как такового нет, но есть последовательность сброса, которую выполняет драйвер по соответствующему запросу (см. далее). Во-вторых, из-за ограниченности набора сигналов одни и те же линии используются как в циклах квитирования режимов, так и в цикле согласования (например, Data Strobe - AutoFeed, Write - Strobe). Поэтому если не принять определенных мер, то во время последовательности согласования будет сымитирован цикл записи, и в регистр устройства будет записан байт совместимости, что не всегда допустимо. Мало того, непосредственно перед этим имитируется чтение данных из устройства, несмотря на наличие байта на выходе LPT. Работа двух устройств на выход одновременно не сулит ничего хорошего. В моем случае внешнее устройство "перетягивало" порт, изменяя байт совместимости. В худшем случае что-нибудь может выгореть.

    Последовательность согласования предусматривает возможность запроса идентификатора устройства, который представляет собой нуль-терминальную строку. Эту строку Windows выдает на экран при обнаружении нового устройства. Чтобы сделать запрос ID, придется воспользоваться кодами IOCTL_PAR_QUERY_DEVICE_ID, IOCTL_PAR_QUERY_DEVICE_ID_SIZE, IOCTL_PAR_QUERY_RAW_DEVICE_ID.

    С помощью кода IOCTL_PAR_QUERY_INFORMATION у драйвера можно запросить информацию об его состоянии.

    const
    IOCTL_PAR_QUERY_INFORMATION = $160004;
    
    type
    PAR_QUERY_INFORMATION = record
      Status: byte;
    end;
    PPAR_QUERY_INFORMATION = ^PAR_QUERY_INFORMATION;
    
    var
    ParInfo: PAR_QUERY_INFORMATION;
    
    DeviceIoControl(hLpt, IOCTL_PAR_QUERY_INFORMATION, nil, 0,
                    @ParInfo, sizeof(PAR_QUERY_INFORMATION),
                    ret, lpOverlapped);
    

    В поле ParInfo.Status драйвер возвращает байт, который может представлять собой комбинацию следующих чисел

    const
    	PARALLEL_INIT 	= $01;
    	PARALLEL_AUTOFEED	= $02;
    	PARALLEL_PAPER_EMPTY	= $04;
    	PARALLEL_OFF_LINE	= $08;
    	PARALLEL_POWER_OFF	= $10;
    	PARALLEL_NOT_CONNECTED	= $20;
    	PARALLEL_BUSY	= $40;
    	PARALLEL_SELECTED	= $80;
    

    Прямого соответствия между битами ParInfo.Status и физическими регистрами параллельного порта нет, но какая-то нетривиальная взаимосвязь существует: определенные комбинации входных сигналов на разъеме порождают различное состояние поля статуса драйвера.

    Код IOCTL_PAR_SET_INFORMATION применяется для сброса драйвера.

    const
    IOCTL_PAR_SET_INFORMATION = $160008;
    
    type
    PAR_SET_INFORMATION = record
      Init: byte;
    end;
    PPAR_SET_INFORMATION = ^PAR_SET_INFORMATION;
    
    var
    ParControl: PAR_SET_INFORMATION;
    
    ParControl.Init := PARALLEL_INIT;
    DeviceIoControl(hLpt, IOCTL_PAR_SET_INFORMATION, @ParControl,
                    sizeof(PAR_SET_INFORMATION), nil, 0, ret, lpOverlapped);
    

    Обратите внимание на значение, которое присваивается переменной ParControl.Init. Других вариантов не существует. При таком запросе драйвер сбрасывает nSelectIn (1284 Active) в ноль, а на линию nInitialize (Address Strobe) выдает отрицательный строб. При этом сигнал nStrobe (Write) сохраняет высокий уровень. Такая последовательность чем-то похожа на цикл чтения адреса EPP, которая на практике редко используется. Поэтому по условию

    • nStrobe (конт. 1) - высокий;
    • nInitialize (конт. 16) - низкий;
    • nSelectIn (конт. 17) - низкий;

    можно сформировать сигнал сброса устройства.

    Запрос IOCTL_SERIAL_SET_TIMEOUTS устанавливает значение таймаута, которое драйвер использует в операциях записи в режимах SPP и ECP_SW. Прочитать установленное значение можно с помощью IOCTL_SERIAL_GET_TIMEOUTS.

    3 ШАГ

    Чтобы сформировать цикл записи адреса EPP, нужно воспользоваться кодом IOCTL_PAR_SET_WRITE_ADDRESS.

    const
    IOCTL_PAR_SET_WRITE_ADDRESS = $16001C;
    
    var
    Address: byte;
    
    Address := $AA;
    DeviceIoControl(hLpt, IOCTL_PAR_SET_WRITE_ADDRESS, @Address, 1, nil, 0,
                    ret, lpOverlapped);
    

    Новый цикл будет сформирован лишь при условии, что в очередном запросе драйверу будет передан новый адрес. Драйвер пытается устранять избыточные операции - благая цель, которая усложняет систему и как следствие влечет ошибки. Я полагаю, что программист Майкрософт не правильно понял смысл чтения адреса EPP, поэтому такая операция отсутствует, зато есть команда IOCTL_PAR_SET_READ_ADDRESS, которая не формирует физических циклов, но настраивает драйвер таким образом, что он создает цикл записи адреса непосредственно перед циклом чтения данных. При этом драйвер, оптимизируя циклы адреса, не всегда работает разумно. Поэтому, не вдаваясь в подробности, я не рекомендую вообще использовать IOCTL_PAR_SET_READ_ADDRESS, тем более что он не дает ничего дополнительно по сравнению с IOCTL_PAR_SET_WRITE_ADDRESS.

    Для записи данных в устройство используется функция WriteFile, а для чтения ReadFile. Обе функции обрабатывают поток данных, а не отдельный байт. Это означает, что для режима EPP будет последовательно сформировано столько циклов записи (чтения) данных, сколько необходимо, чтобы передать весь массив байт за байтом. Естественно, что все данные при этом уйдут по одному адресу. Ниже приводится пример кода, в котором производится запись $55 по адресу $AA, а затем чтение по адресам $AA и $BB.

    uses
    Windows;
    
    var
    hLpt: THandle;
     ret: DWORD;
    Address: byte;
    Data: byte;
    
    // Открыть порт для синхронного доступа
    hLpt := CreateFile('LPT1', GENERIC_READ or GENERIC_WRITE, 0, nil,
            OPEN_EXISTING, 0, 0);
    
    // Запись $55 по адресу $AA
    Address := $AA;
    DeviceIoControl(hLpt, IOCTL_PAR_SET_WRITE_ADDRESS, @Address, 1, nil, 0,
                    ret, nil);
    WriteFile(hLpt, [$55], 1, ret, nil);
    
    // Чтение по адресу $AA
    ReadFile(hLPT, Data, 1, ret, nil);
    
    // Чтение по адресу $BB
    Address := $BB;
    DeviceIoControl(hLpt, IOCTL_PAR_SET_WRITE_ADDRESS, @Address, 1, nil,
                    0, ret, nil);
    ReadFile(hLPT, Data, 1, ret, nil);
    
    // Закрыть устройство
    CloseHandle(hLpt);
    

    4 ШАГ

    Закрывается устройство обычным образом: с помощью функции CloseHandle.


     


    ХАЙВЕЙ - лучший российский хостинг-провайдер: хостинг, регистрация доменов, услуга Ваша@почта, поддержка 24 часа


    NetPromoter - единственный российский профессиональный комплекс программ и сервисов для раскрутки сайта и интернет-статистики


    STSS - известный поставщик надежных серверных решений различного назначения на платформе Intel (Xeon) и AMD.


    5-55: the ITIL company. Практический опыт и теоретические знания на лучших семинарах по ITIL и процессам ITSM.


    Подписка на новости IT-портала CITForum.ru
    (библиотека, ftp-архив CITKIT.ru)

    Новые поступления в on-line библиотеку:

    28 апреля

  • Выбор первого дистрибутива Linux: Пособие для начинающих
  • Обфускация и защита программных продуктов
  • Анализ и оптимизация циклов с помощью производящих функций
  • Стратегии объектно-реляционного отображения: систематизация и анализ на основе паттернов

    26 апреля

  • Business Intelligence обещает значительный рост в 2005 году
  • Десять основных тенденций 2005 года в области Business Intelligence и Хранилищ данных
  • Управление эффективностью бизнеса и предсказуемость
  • Увеличение эффективности бизнеса: пять ошибок управления, которых следует избегать
  • Потребность в организационных данных: модель комплексного управления эффективностью бизнеса
  • Технология Хранилищ данных для государственных учреждений
  • Оцените, насколько совершенно ваше Хранилище данных

    21 апреля

  • Исполнение моделей при помощи виртуальной машины
  • Параллельные алгоритмы компьютерной алгебры
  • От стандарта до стандарта (о стандартизации оптических разъемов)
  • За штурвалом IP-станции

    Продолжение дискуссии читателей:

  • Линукс и пользователи, или что мне не нравится в Linux
  • Еще один взгляд на альтернативные ОС (и софт для них)
  • О некомпетентности пользователя Windows
  • Переписка Долгачева В.С. и Монахова В.В.

    19 апреля

  • Межпротокольный шлюз NAT-PT с функциями DNS-ALG и FTP-ALG для обеспечения взаимодействия между сетями IPv4 и IPv6
  • Рефакторинг архитектуры программного обеспечения: выделение слоев
  • Комбинаторика слов и построение тестовых последовательностей
  • Функциональное тестирование Web-приложений на основе технологии UniTesK

    14 апреля

  • Как организовать двойную парольную защиту данных в Oracle
  • Деревянный интерфейс

    Продолжение дискуссии читателей:

  • Microsoft против мира
  • Впечатления от прочитанного

    12 апреля

  • Крупные проблемы и текущие задачи исследований в области баз данных
  • Глава 2 из книги Т.Кайта "Oracle для профессионалов"Архитектура

    Дискуссия читателей о Linux и Windows:

  • Деньги правят миром, и у кого их больше, тот и прав!
  • О злокозненности некомпетентных пользователей, или почему я не люблю ограниченных пользователей Windows

    7 апреля

  • О доблести Билла Гейтса, или почему Windows лучше, чем LINUX или Mac OS
  • Витая пара - все ли так просто?!
  • Выбираем сервер печати
  • Один слой хорошо, а два - лучше (о пишущих DVD-приводах)

    5 апреля

  • Использование Caché SQL Gateway
  • Глава 19 из книги Т.Кайта "Oracle для профессионалов"Хранимые процедуры на языке Java
  • Что такое PostgreSQL?
  • Обновлен PostgreSQL FAQ

    31 марта

  • Использование Веб-сервисов в Caché
  • Защита на уровне строк (Oracle)
  • Секции в реальном мире

    29 марта

  • Разработка успешных приложений для Oracle - первая глава из книги Тома Кайта "Oracle для профессионалов"
  • Web-сервисы: растущие опасения (мнение аналитиков IDC)
  • Технология OLAP - мощная альтернатива электронным таблицам
  • Какой модной стала подготовка отчетности

    24 марта

  • Многоверсионность данных и управление параллельными транзакциями
  • Исключение из правил. Опыт разработки и внедрения финансовой корпоративной системы
  • Обнаружение компрометаций ядра Linux с помощью gdb
  • Корпоративная сервисная шина - "бюджетный" подход к решению задач интеграции
  • Сервис-ориентированная архитектура
  • Бизнес-процессы и XML

    22 марта

  • Доступно. И точка! (обзор точек беспроводного доступа)
  • Коммутаторы Fast/Gigabit Ethernet для "большой" сети
  • Push to Talk: нажми на кнопку и ...говори
  • Сети нового поколения и технология softswitch

    17 марта

  • Часто задаваемые вопросы о proxy (proxy FAQ)
  • Самонастраивающаяся база данных: управляемые приложения и настройка SQL
  • Еще раз о волоконных трассах
  • Настраиваем русский Unicode в FreeBSD-5.3.

    10 марта

  • Еще не сказанное о волоконной оптике
  • Wi-Fi на службе оператора
  • Пора менять платформу?
    (о сокетах LGA775 и PGA478)

    Oracle:

  • Детальный аудит для практических целей
  • Шифруем свои ресурсы данных

    3 марта

  • Требования к проекту. Классификация - первый шаг к пониманию
  • Gtk vs. Qt: драки не будет
  • Управление бизнесом "по максимуму": BPM для финансовых учреждений
  • Реализация решения по управлению эффективностью бизнеса
  • Новые SerialATA-винчестеры
  • Карман для сервера

    1 марта

  • Выбрать корпус - нет ничего проще?
  • Создание виртуальной сети с удаленной загрузкой узлов
  • Текущее состояние и перспективы развития рынка интеграционных технологий
  • Интеграция корпоративной информации: новое направление
  • Архитектурные подходы к консолидации

    24 февраля

  • Каждому проекту своя методология
  • Императив интеграции
  • Безопасность IP-телефонии - полевые зарисовки
  • О злокозненности Билла Гейтса, или почему я не люблю Windows

    22 февраля

  • Oracle10: шифруем данные
  • В версии Oracle10 "виртуальные частные базы данных" данных стали избирательнее
  • Каждому (пользователю) свое (данное в таблице)
    Часть 1
    Часть 2
  • Ускоряем интернет
  • Сетевая аутентификация на практике
  • В фокусе Microsoft Virtual Server 2005

    17 февраля

    Открыт новый раздел
    Все об Open Source

    Все новости >>>



  • IT-консалтинг Software Engineering Программирование Open Source СУБД Безопасность Internet Сети Операционные системы Hardware

    Информация для рекламодателей PR-акции, размещение рекламы - pr@citforum.ru, тел. +7 095 4119920 Пресс-релизы - manager@citforum.ru
    Послать комментарий
    Информация для авторов
    Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
    Copyright © 1997-2000 CIT, © 2001-2004 CIT Forum
    Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...