Ранние клавиатуры были однонаправленными устройствами, однако уже в IBM PC/AT стали применяться клавиатуры, которые не только передавали скан-коды компьютеру, но и могли получать от него команды. Все современные клавиатуры с точки зрения программирования совместимы с клавиатурами IBM PC/AT.
Современные клавиатуры теоретически предоставляют возможность выбора из трех таблиц скан-кодов, однако обязательно присутствует лишь таблица №2, используемая по умолчанию; именно она использовалась в IBM PC/AT.
Помимо скан-кодов, от клавиатуры могут быть получены следующие коды:
- 0x00: ошибка клавиатуры (нажаты одновременно слишком много клавиш);
- 0xAA: BAT (Basic Assurance Test, встроенный тест) завершён;
- 0xEE: эхо (ECHO);
- 0xFA: ответ (ACK);
- 0xFE: необходима повторная отправка данных в клавиатуру (RESEND);
- 0xFF: ошибка клавиатуры.
Команды[]
Запись команд и их дополнительных байтов следует в порт 60h (опробовано на VMWare 9.0, XT), принимать ответы тоже из этого порта.
Если клавиатуре посылается что-либо недопустимая, она возвращает ответ RESEND (0xFE).
Любая команда очищает буфер приема клавиатуры.
Команды:
- 0xED: Установить значение клавиатурных индикаторов (LEDs). В дополнительном байте передаются [2.3.3] Единичное значение бита показывает, что светодиод светится.
- 0xEE: Эхо. На эту команду, используемую для диагностики, клавиатура отзывается кодом ECHO (0xEE).
- 0xF0: Выбор таблицы скан-кодов. На саму команду клавиатура отвечает кодом ACK (0xFA). После этого ей передается номер таблицы (1, 2, 3), на что клавиатура снова отвечает кодом ACK. Если в качестве кода передается 0, после ACK клавиатура присылает номер текущей используемой таблицы скан-кодов.
- 0xF2: Идентификация клавиатуры. Ранние клавиатуры, не умеющие принимать команды от ПК, не ответят ничего, и программа сможет обнаружить таймаут. Клавиатура PC/AT вернёт код ACK. Клавиатура MF II вернёт последовательность кодов ACK, 0xAB, 0x41.
- 0xF3: Настройка скорости повтора символов. Дополнительный байт определяет скорость повтора. Младшие 5 разрядов задают саму скорость повтора, биты 6:5 — задержку до начала повтора. Старший бит должен быть равен нулю.
- 0xF4: Разрешить работу клавиатуры. Эта команда очищает буфер и разрешает сканирование нажатых клавиш.
- 0xF5: Сброс клавиатуры. Сканирование запрещено.
- 0xF6: Сброс клавиатуры. Сканирование разрешено.
- 0xFE: Повторная отправка последней передачи.
- 0xFF: Сброс. Вызывает BAT, в случае успеха возвращает ACK. Выполнение этой команды может занять до 750ms.
Таблицы[]
Скорость повтора[]
|
Задержка[]
Значение Задержка(секунд) 0x00 0.25 0x01 0.50 0x02 0.75 0x03 1.00
Индикаторы[]
бит 0 ScrollLock бит 1 NumLock бит 2 CapsLock
Инициализация[]
Пример сценария инициализации:
- Host: ED Set/Reset Status Indicators
- Keyboard: FA Acknowledge
- Host: 00 Turn off all LEDs
- Keyboard: FA Acknowledge
- Host: F2 Read ID
- Keyboard: FA Acknowledge
- Keyboard: AB First byte of ID
- Host: ED Set/Reset Status Indicators ;BIOS init
- Keyboard: FA Acknowledge
- Host: 02 Turn on Num Lock LED
- Keyboard: FA Acknowledge
- Host: F3 Set Typematic Rate/Delay ;Windows init
- Keyboard: FA Acknowledge
- Host: 20 500 ms / 30.0 reports/sec
- Keyboard: FA Acknowledge
- Host: F4 Enable
- Keyboard: FA Acknowledge
- Host: F3 Set Typematic Rate/delay
- Keyboard: FA Acknowledge
- Host: 00 250 ms / 30.0 reports/sec
- Keyboard: FA Acknowledge
Непонятое[]
Порт 0x61
Исторически (на IBM PC) порты 0x60-0x63 принадлежали параллельному контроллеру типа 8255. Первые три порта использовались для управления различными устройствами, в частности, клавиатурой и динамиком, а последний (0x63) применялся для программирования самого контроллера 8255. Позднее этот контроллер был упразднён, а его функции частично перешли к специализированной микросхеме: в основном сохранились функции портов 0x60 и 0x61.
В XT порт 0x61 служит для оповещения контроллера о приёме очередного скан-кода. Биты с нулевого по пятый используются для всякой ерунды типа динамика, шлюза A20 и т.д... Эти биты нельзя сбрасывать, их надо бережно сохранять. А вот старшие два бита для нас представляют интерес.
Для того, чтобы уведомить клавиатуру о том, что скан-код нами принят, нужно установить и тут же снова сбросить 7-й бит. Все остальные биты сохраняются.
Что касается шестого бита, - его установка повлечёт за собой сохранение клавиатурных часов в низком и недоступном для детей месте :) (Hold keyboard clock low -> Keyboard can't send any data).
В AT контроллер 8042 этот порт мало интересен. И имеет другое назначение. Зачастую он предназначен только для чтения. И информирует о всякой всячине. Более того не принадлежит контроллеру клавиатуры, а эмулируется системной логикой. Это делается для совместимости.
Что касается оповещения о приеме скан кода, то это делается путем чтения порта 0x60 или через сброс флага буфера приема.
Примеры[]
Инициализация клавиатуры.[]
Взято из [6.1]
// Запретить все
i8042_write_command_byte (I8042_CMD_DISABLE_ALL);
// Очистить буфер.
for (i = 0; i < MAX_JUNK_ITERATIONS; i++)
{
stat = ddi_get8 (I8042_STAT);
if (! (stat & I8042_STAT_OUTBF))
break;
ddi_get8 (I8042_DATA);
}
// Зарегистрировать прерыывание
// Разрешить все.
i8042_write_command_byte (I8042_CMD_ENABLE_ALL);
Интро[]
i8042_write_command_byte (cb)
{
i8042_send(I8042_CMD, I8042_CMD_WCB);
i8042_send(I8042_DATA, cb);
}
i8042_send (cb)
{
// Эта операция производится в цикле
// Максимальное время ожидания - 250ms
stat = ddi_get8(I8042_STAT);
if ((stat & I8042_STAT_INBF) == 0)
ddi_put8(reg, val);
}
Обработчик прерывания[]
// Читаем статус
stat = ddi_get8(I8042_STAT);
if (! (stat & I8042_STAT_OUTBF))
{
// Левое прерывание
return (DDI_INTR_UNCLAIMED);
}
// Читаем данные
byte = ddi_get8(I8042_DATA);
// Смотрим к кому относятся (Во как интересно!)
which_port = (stat & I8042_STAT_AUXBF) ? AUX_PORT : MAIN_PORT;
См. также[]
- Programming the Keyboard (ENG)
- Wout Mertens' Guide To Keyboard Programming v1.1 (EHG)
- The Keyboard Interface Tutorial (ENG)
- Interfacing the AT keyboard (ENG)
- Holtek Semiconductor Keyboard Controller with PS/2 (ENG)
- VT82C42 Keyboard Controller (ENG)
- The PS/2 Keyboard Interface (ENG)
- The PS/2 Mouse/Keyboard Protocol (ENG)
- Keyboard Scan Codes: Set 1 (ENG)
- Keyboard Scan Codes: Set 2 (ENG)
- Keyboard Scan Codes: Set 3 (ENG)
- The PS/2 Mouse Interface (ENG)