35 #define STATUS_OBF 0x01 // 0 : Output Buffer Full (0 = output buffer empty) 36 #define STATUS_IBF 0x02 // 1 : Input Buffer Full (0 = input buffer empty) 37 #define STATUS_SYSFLAG 0x04 // 2 : 0 = power on reset, 1 = diagnostic ok 38 #define STATUS_CMD 0x08 // 3 : Command or Data, 0 = write to port 0 (0x60), 1 = write to port 1 (0x64) 39 #define STATUS_INH 0x10 // 4 : Inhibit Switch, 0 = Keyboard inhibited, 1 = Keyboard not inhibited 40 #define STATUS_AOBF 0x20 // 5 : Auxiliary Output Buffer Full, 0 = keyboard data, 1 = mouse data 41 #define STATUS_TIMEOUT 0x40 // 6 : 1 = Timeout Error 42 #define STATUS_PARITY_ERR 0x80 // 7 : 1 = Parity Error 46 #define CTRLCMD_NONE 0x00 47 #define CTRLCMD_GET_COMMAND_BYTE 0x20 48 #define CTRLCMD_READ_CONTROLLER_RAM_BEGIN 0x21 49 #define CTRLCMD_READ_CONTROLLER_RAM_END 0x3f 50 #define CTRLCMD_WRITE_COMMAND_BYTE 0x60 51 #define CTRLCMD_WRITE_CONTROLLER_RAM_BEGIN 0x61 52 #define CTRLCMD_WRITE_CONTROLLER_RAM_END 0x7f 53 #define CTRLCMD_DISABLE_MOUSE_PORT 0xa7 54 #define CTRLCMD_ENABLE_MOUSE_PORT 0xa8 55 #define CTRLCMD_TEST_MOUSE_PORT 0xa9 56 #define CTRLCMD_SELF_TEST 0xaa 57 #define CTRLCMD_TEST_KEYBOARD_PORT 0xab 58 #define CTRLCMD_DISABLE_KEYBOARD 0xad 59 #define CTRLCMD_ENABLE_KEYBOARD 0xae 60 #define CTRLCMD_READ_INPUT_PORT 0xc0 61 #define CTRLCMD_READ_OUTPUT_PORT 0xd0 62 #define CTRLCMD_WRITE_OUTPUT_PORT 0xd1 63 #define CTRLCMD_WRITE_KEYBOARD_OUTPUT_BUFFER 0xd2 64 #define CTRLCMD_WRITE_MOUSE_OUTPUT_BUFFER 0xd3 65 #define CTRLCMD_WRITE_TO_MOUSE 0xd4 66 #define CTRLCMD_SYSTEM_RESET 0xfe 70 #define CMDBYTE_ENABLE_KEYBOARD_IRQ 0x01 // 0 : 1 = Keyboard output buffer full causes interrupt (IRQ 1) 71 #define CMDBYTE_ENABLE_MOUSE_IRQ 0x02 // 1 : 1 = Mouse output buffer full causes interrupt (IRQ 12) 72 #define CMDBYTE_SYSFLAG 0x04 // 2 : 1 = System flag after successful controller self-test 73 #define CMDBYTE_UNUSED1 0x08 // 3 : unused (must be 0) 74 #define CMDBYTE_DISABLE_KEYBOARD 0x10 // 4 : 1 = Disable keyboard by forcing the keyboard clock low 75 #define CMDBYTE_DISABLE_MOUSE 0x20 // 5 : 1 = Disable mouse by forcing the mouse serial clock line low 76 #define CMDBYTE_STD_SCAN_CONVERSION 0x40 // 6 : 1 = Standard Scan conversion 77 #define CMDBYTE_UNUSED2 0x80 // 7 : unused (must be 0) 82 m_mutex = xSemaphoreCreateMutex();
88 vSemaphoreDelete(m_mutex);
99 m_keyboard = m_PS2Controller.keyboard();
100 m_mouse = m_PS2Controller.mouse();
102 m_STATUS = STATUS_SYSFLAG | STATUS_INH;
105 m_commandByte = CMDBYTE_ENABLE_KEYBOARD_IRQ | CMDBYTE_ENABLE_MOUSE_IRQ | CMDBYTE_SYSFLAG | CMDBYTE_STD_SCAN_CONVERSION | CMDBYTE_DISABLE_MOUSE;
107 m_executingCommand = CTRLCMD_NONE;
108 m_writeToMouse =
false;
109 m_mousePacketIdx = -1;
116 uint8_t i8042::read(
int address)
118 AutoSemaphore autoSemaphore(m_mutex);
124 m_STATUS &= ~(STATUS_OBF | STATUS_AOBF);
141 void i8042::write(
int address, uint8_t value)
143 AutoSemaphore autoSemaphore(m_mutex);
152 m_STATUS = (m_STATUS & ~STATUS_CMD) | STATUS_IBF;
160 m_STATUS |= STATUS_CMD | STATUS_IBF;
169 AutoSemaphore autoSemaphore(m_mutex);
172 if ((m_STATUS & STATUS_OBF) == 0 && m_keyboard->scancodeAvailable()) {
173 if (m_commandByte & CMDBYTE_STD_SCAN_CONVERSION) {
175 uint8_t scode = Keyboard::convScancodeSet2To1(m_keyboard->getNextScancode());
176 m_DBBOUT = (m_DBBOUT == 0xf0 ? (0x80 | scode) : scode);
178 m_STATUS |= STATUS_OBF;
184 m_DBBOUT = m_keyboard->getNextScancode();
185 m_STATUS |= STATUS_OBF;
191 if ((m_STATUS & STATUS_OBF) == 0 && (m_mousePacketIdx > -1 || m_mouse->packetAvailable())) {
192 if (m_mousePacketIdx == -1)
193 m_mouse->getNextPacket(&m_mousePacket);
194 m_DBBOUT = m_mousePacket.data[++m_mousePacketIdx];
195 if (m_mousePacketIdx == m_mouse->getPacketSize() - 1)
196 m_mousePacketIdx = -1;
197 m_STATUS |= STATUS_OBF | STATUS_AOBF;
202 if (m_STATUS & STATUS_CMD) {
203 m_STATUS &= ~(STATUS_IBF | STATUS_CMD);
208 if ((m_STATUS & STATUS_IBF) && m_executingCommand != CTRLCMD_NONE) {
209 m_STATUS &= ~STATUS_IBF;
214 if (m_STATUS & STATUS_IBF) {
215 m_STATUS &= ~(STATUS_IBF | STATUS_PARITY_ERR);
217 m_mouse->sendCommand(m_DBBIN);
219 m_keyboard->sendCommand(m_DBBIN);
220 m_writeToMouse =
false;
221 m_STATUS |= STATUS_PARITY_ERR * m_keyboard->parityError();
225 if (m_keybIntTrigs && trigKeyboardInterrupt())
227 if (m_mouseIntTrigs && trigMouseInterrupt())
232 void i8042::execCommand()
234 uint8_t cmd = m_executingCommand == CTRLCMD_NONE ? m_DBBIN : m_executingCommand;
238 case CTRLCMD_GET_COMMAND_BYTE:
239 m_DBBOUT = m_commandByte;
240 m_STATUS |= STATUS_OBF;
243 case CTRLCMD_WRITE_COMMAND_BYTE:
244 if (m_executingCommand) {
246 updateCommandByte(m_DBBIN);
247 m_executingCommand = CTRLCMD_NONE;
250 m_executingCommand = CTRLCMD_WRITE_COMMAND_BYTE;
254 case CTRLCMD_DISABLE_MOUSE_PORT:
258 case CTRLCMD_ENABLE_MOUSE_PORT:
262 case CTRLCMD_TEST_MOUSE_PORT:
263 m_DBBOUT = m_mouse->isMouseAvailable() ? 0x00 : 0x02;
264 m_STATUS |= STATUS_OBF;
267 case CTRLCMD_SELF_TEST:
269 m_STATUS |= STATUS_OBF;
272 case CTRLCMD_TEST_KEYBOARD_PORT:
273 m_DBBOUT = m_keyboard->isKeyboardAvailable() ? 0x00 : 0x02;
274 m_STATUS |= STATUS_OBF;
277 case CTRLCMD_DISABLE_KEYBOARD:
278 updateCommandByte(m_commandByte | CMDBYTE_DISABLE_KEYBOARD);
281 case CTRLCMD_ENABLE_KEYBOARD:
282 updateCommandByte(m_commandByte & ~CMDBYTE_DISABLE_KEYBOARD);
285 case CTRLCMD_WRITE_TO_MOUSE:
289 case CTRLCMD_SYSTEM_RESET:
294 printf(
"8042: unsupported controller command %02X\n", cmd);
300 void i8042::enableMouse(
bool value)
302 AutoSemaphore autoSemaphore(m_mutex);
303 updateCommandByte(value ? (m_commandByte & ~CMDBYTE_DISABLE_MOUSE) : (m_commandByte | CMDBYTE_DISABLE_MOUSE));
307 void i8042::updateCommandByte(uint8_t newValue)
310 if ((newValue ^ m_commandByte) & CMDBYTE_DISABLE_KEYBOARD) {
311 if (newValue & CMDBYTE_DISABLE_KEYBOARD) {
312 m_keyboard->suspendPort();
314 m_keyboard->resumePort();
319 if ((newValue ^ m_commandByte) & CMDBYTE_DISABLE_MOUSE) {
320 if (newValue & CMDBYTE_DISABLE_MOUSE) {
321 m_mouse->suspendPort();
323 m_mouse->resumePort();
327 m_commandByte = newValue;
332 bool i8042::trigKeyboardInterrupt()
334 return m_commandByte & CMDBYTE_ENABLE_KEYBOARD_IRQ ? m_keyboardInterrupt(m_context) : true;
338 bool i8042::trigMouseInterrupt()
340 return m_commandByte & CMDBYTE_ENABLE_MOUSE_IRQ ? m_mouseInterrupt(m_context) : true;
static void quickCheckHardware()
Disable re-try when a mouse is not found.