ФЭНДОМ


Ранние клавиатуры были однонаправленными устройствами, однако уже в 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.

Таблицы Править

Скорость повтора Править

ЗначениеСкорость (cps)
0x0030.0
0x0126.7
0x0224.0
0x0321.8
0x0420.7
0x0518.5
0x0617.1
0x0716.0
0x0815.0
0x0913.3
0x0A12.0
0x0B10.9
0x0C10.0
0x0D9.2
0x0E8.6
0x0F8.0
0x107.5
0x116.7
0x126.0
0x135.5
0x145.0
0x154.6
0x164.3
0x174.0
0x183.7
0x193.3
0x1A3.0
0x1B2.7
0x1C2.5
0x1D2.3
0x1E2.1
0x1F2.0

Задержка Править

Значение Задержка(секунд) 0x00 0.25 0x01 0.50 0x02 0.75 0x03 1.00


Индикаторы Править

бит 0 ScrollLock бит 1 NumLock бит 2 CapsLock


Инициализация Править

Пример сценария инициализации:

  1. Host: ED Set/Reset Status Indicators
  2. Keyboard: FA Acknowledge
  3. Host: 00 Turn off all LEDs
  4. Keyboard: FA Acknowledge
  5. Host: F2 Read ID
  6. Keyboard: FA Acknowledge
  7. Keyboard: AB First byte of ID
  8. Host: ED Set/Reset Status Indicators  ;BIOS init
  9. Keyboard: FA Acknowledge
  10. Host: 02 Turn on Num Lock LED
  11. Keyboard: FA Acknowledge
  12. Host: F3 Set Typematic Rate/Delay  ;Windows init
  13. Keyboard: FA Acknowledge
  14. Host: 20 500 ms / 30.0 reports/sec
  15. Keyboard: FA Acknowledge
  16. Host: F4 Enable
  17. Keyboard: FA Acknowledge
  18. Host: F3 Set Typematic Rate/delay
  19. Keyboard: FA Acknowledge
  20. Host: 00 250 ms / 30.0 reports/sec
  21. 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;

См. такжеПравить

Обнаружено использование расширения AdBlock.


Викия — это свободный ресурс, который существует и развивается за счёт рекламы. Для блокирующих рекламу пользователей мы предоставляем модифицированную версию сайта.

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