I was recently working on enhancing my keyboard driver, providing support for more than alphanumeric and symbol keys (arrow keys, etc.), and ran into this problem. When reading from port 60h, I could only read the last N - 1 bytes of a scan code that I know should be N bytes, e.g. pressing the left arrow key results in the read code 6Bh 6Bh, as opposed to the expected E0h 6Bh.
Below is the code I put in to my handler instead of my usual code, for debugging purposes.
Code:
void _handle_keyboard() {
// Send EOI to PIC
send_eoi(KEYBOARD_IRQ_PIN);
// Read and print value from 60h
printf("%#x ", inb(KEYBOARD_IN_PORT));
printf("%#x\n", inb(KEYBOARD_IN_PORT));
}
In debugging, I have done a couple of things. I have changed the 8042 configuration byte to disable translation (bit 6). This changed the scan code from code set 1 to code set 2, although I was still unable to read all the bytes of the scan code sequence using multiple I/O reads with print statements, as shown above. I have also tried explicitly setting the scan code sent from the keyboard, via command F0h set to the keyboard, but still get the same behavior, just with byte values printed corresponding to different scan code sets.
Here is the code I use to initialize the keyboard. This is where I added commands to disable translation and set the scan code set when debugging (code not shown for those settings).
Code:
// Initialization function
int init_keyboard() {
// Disable interrupts
uint32_t flags;
cli_and_save(flags);
// Route interrupts to handler
if(set_int(KEYBOARD_IRQ_PIN, _handle_keyboard)) return -1;
// Intialize state
device_state.r_shift = 0;
device_state.l_shift = 0;
device_state.caps = 0;
device_state.alt = 0;
device_state.status = FREE;
device_state.enable = ENABLED;
// Enable interrupts on the proper pin
enable_irq(KEYBOARD_IRQ_PIN);
// Restore flags, enable interrupts
restore_flags(flags);
sti();
return 0;
}
Is this the proper way to read in scan codes, via multiple port 60h reads? If so, what could be possible causes of this issue?