Return to Unit Reference
Description
ARM PrimeCell PL050 PS2 Keyboard/Mouse Interface Driver unit
The PL050 is an Advanced Microcontroller Bus Architecture (AMBA) compliant peripheral that implements a PS/2 compatible Keyboard and Mouse interface. This driver supports all of the standard functionality of the PL050 KMI controller including both Keyboard and Mouse devices as well as setting LEDs, repeat rate, repeat delay and sample rate values.
The driver uses interrupt transfers for receiving keyboard and mouse inputs but uses only polling mode for transmitting data to the keyboard or mouse device. This driver has only been tested with the QEMU Versatile PB emulation of the PL050 device and has not been confirmed to work with real hardware.
Notes:
- Currently QEMU only supports Scancode set 2 so scancode sets 1 and 3 are not implemented.
- On Windows, QEMU appears to send invalid scancodes for Print Screen and Pause/Break keys.
- On Windows, QEMU does not differentiate between the cursor keys (Up, Down, Left, Right, Home, End, PgUp, PgDown) and the numeric keypad keys so each of these will always return their numeric keypad equivalent. This means that to use the cursor keys you need to turn off Number Lock otherwise they are interpreted as number keys instead.
Constants
[Expand]
PL050 specific constants PL050_*
PL050_KEYBOARD_DESCRIPTION = 'ARM PrimeCell PL050 PS2 Keyboard';
|
Description of PL050 Keyboard device
|
PL050_MOUSE_DESCRIPTION = 'ARM PrimeCell PL050 PS2 Mouse';
|
Description of PL050 Mouse device
|
|
PL050_KEYBOARD_SCANCODE_COUNT = 256;
|
Number of keyboard scancode buffers for receive
|
PL050_MOUSE_PACKET_COUNT = 256;
|
Number of mouse packet buffers for receive
|
|
PL050_KEYBOARD_CLOCK_RATE = 8000000;
|
Default clock rate
|
PL050_MOUSE_CLOCK_RATE = 8000000;
|
Default clock rate
|
|
PL050_KEYBOARD_SHIFTSTATE_MASK = KEYBOARD_LEFT_CTRL or KEYBOARD_LEFT_SHIFT or KEYBOARD_LEFT_ALT or KEYBOARD_RIGHT_CTRL or KEYBOARD_RIGHT_SHIFT or KEYBOARD_RIGHT_ALT;
|
|
[Expand]
PL050 control register PL050_CR_*
PL050_CR_TYPE = (1 shl 5);
|
0 = PS2/AT mode / 1 = No line control bit mode
|
PL050_CR_RXINTREN = (1 shl 4);
|
Enable receiver interrupt. This bit field is used to enable the PrimeCell KMI receiver interrupt (If KMIRXINTREn = 1, the receiver interrupt is enabled)
|
PL050_CR_TXINTREN = (1 shl 3);
|
Enable transmitter interrupt. This bit field is used to enable the PrimeCell KMI transmitter interrupt (If KMITXINTREn = 1, the transfer interrupt is enabled)
|
PL050_CR_EN = (1 shl 2);
|
The enable PrimeCell KMI bit field is used to enable the KMI (If KmiEn = 1, the KMI is enabled)
|
PL050_CR_FDL = (1 shl 1);
|
The force KMI data LOW bit field is used to force the PrimeCell KMI data pad LOW regardless of the state of the KMI finite state machine (FSM) (If FKMID = 1, the PrimeCell KMI data pad is forced LOW)
|
PL050_CR_FCL = (1 shl 0);
|
The force KMI clock LOW bit field is used to force the PrimeCell KMI clock pad LOW regardless of the state of the KMI FSM (If FKMIC = 1, the PrimeCell KMI clock pad is forced LOW)
|
[Expand]
PL050 status register PL050_STAT_*
PL050_STAT_TXEMPTY = (1 shl 6);
|
This bit indicates that the transmit register is empty and ready to transmit (0 = Transmit register full / 1 = Transmit register empty, ready to be written)
|
PL050_STAT_TXBUSY = (1 shl 5);
|
This bit indicates that the PrimeCell KMI is currently sending data (0 = Idle / 1 = Currently sending data)
|
PL050_STAT_RXFULL = (1 shl 4);
|
This bit indicates that the receiver register is full and ready to be read (0 = Receive register empty / 1 = Receive register full, ready to be read)
|
PL050_STAT_RXBUSY = (1 shl 3);
|
This bit indicates that the PrimeCell KMI is currently receiving data (0 = Idle / 1 = Currently receiving data)
|
PL050_STAT_RXPARITY = (1 shl 2);
|
This bit reflects the parity bit for the last received data byte (odd parity)
|
PL050_STAT_IC = (1 shl 1);
|
This bit reflects the status of the KMICLKIN line after synchronizing and sampling
|
PL050_STAT_ID = (1 shl 0);
|
This bit reflects the status of the KMIDATAIN line after synchronizing
|
[Expand]
PL050 interrupt register PL050_IIR_*
PL050_IIR_TXINTR = (1 shl 1);
|
This bit is set to 1 if the KMITXINTR transmit interrupt is asserted
|
PL050_IIR_RXINTR = (1 shl 0);
|
This bit is set to 1 if the KMIRXINTR receive interrupt is asserted
|
Type definitions
PL050 KMI registers
[Expand]
PPL050KMIRegisters = ^TPL050KMIRegisters;
TPL050KMIRegisters = record
PL050 keyboard scancode
[Expand]
PPL050KeyboardScancode = ^TPL050KeyboardScancode;
TPL050KeyboardScancode = record
Keyboard:PPL050Keyboard;
|
|
Count:LongWord;
|
|
Index:LongInt;
|
|
Scancode:TPS2KeyboardScancode;
|
|
PL050 keyboard
[Expand]
PPL050Keyboard = ^TPL050Keyboard;
TPL050Keyboard = record
Keyboard Properties
|
Keyboard:TKeyboardDevice;
|
|
PL050 Properties
|
IRQ:LongWord;
|
|
Registers:PPL050KMIRegisters;
|
Device registers
|
ScancodeSet:Byte;
|
The currently selected scancode set
|
ScancodeData:array[0..(PL050_KEYBOARD_SCANCODE_COUNT - 1)] of TPL050KeyboardScancode;
|
Buffers for scancode receiving
|
ScancodeStart:LongWord;
|
The scancode buffer to use for the next receive
|
ScancodeCount:LongWord;
|
The number of scancode buffers that are in use
|
LastCode:Word;
|
The scan code of the last key pressed
|
ShiftState:LongWord;
|
The modifier flags of the current shift state
|
Statistics Properties
|
DiscardCount:LongWord;
|
Number of received bytes discarded (due to no buffer or other reasons)
|
InterruptCount:LongWord;
|
Number of interrupt requests received by the device
|
PL050 mouse packet
[Expand]
PPL050MousePacket = ^TPL050MousePacket;
TPL050MousePacket = record
Mouse:PPL050Mouse;
|
|
Count:LongWord;
|
|
Packet:TPS2MousePacket;
|
|
PL050 mouse
[Expand]
PPL050Mouse = ^TPL050Mouse;
TPL050Mouse = record
Mouse Properties
|
Mouse:TMouseDevice;
|
|
PL050 Properties
|
IRQ:LongWord;
|
|
Registers:PPL050KMIRegisters;
|
Device registers
|
PacketData:array[0..(PL050_MOUSE_PACKET_COUNT - 1)] of TPL050MousePacket;
|
Buffers for mouse packet receiving
|
PacketStart:LongWord;
|
The mouse packet buffer to use for the next receive
|
PacketCount:LongWord;
|
The number of mouse packet buffers that are in use
|
Statistics Properties
|
DiscardCount:LongWord;
|
Number of received bytes discarded (due to no buffer or other reasons)
|
InterruptCount:LongWord;
|
Number of interrupt requests received by the device
|
Public variables
None defined
Function declarations
PL050 functions
[Expand]
function PL050KeyboardCreate(Address:PtrUInt; const Name:String; IRQ,ClockRate:LongWord):PKeyboardDevice;
Description: Create, register and attach a new PL050 Keyboard device which can be accessed using the keyboard API
Address
|
The address of the PL050 registers
|
Name
|
The text description of this device which will show in the device list (Optional)
|
IRQ
|
The interrupt number for the PL050
|
ClockRate
|
The clock source frequency for the PL050
|
Return
|
Pointer to the new Keyboard device or nil if the Keyboard device could not be created
|
[Expand]
function PL050KeyboardDestroy(Keyboard:PKeyboardDevice):LongWord;
Description: Detach, deregister and destroy a PL050 Keyboard device created by this driver
Keyboard
|
The Keyboard device to destroy
|
Return
|
ERROR_SUCCESS if completed or another error code on failure
|
[Expand]
function PL050MouseCreate(Address:PtrUInt; const Name:String; IRQ,ClockRate:LongWord):PMouseDevice;
Description: Create, register and attach a new PL050 Mouse device which can be accessed using the mouse API
Address
|
The address of the PL050 registers
|
Name
|
The text description of this device which will show in the device list (Optional)
|
IRQ
|
The interrupt number for the PL050
|
ClockRate
|
The clock source frequency for the PL050
|
Return
|
Pointer to the new Mouse device or nil if the Mouse device could not be created
|
[Expand]
function PL050MouseDestroy(Mouse:PMouseDevice):LongWord;
Description: Detach, deregister and destroy a PL050 Mouse device created by this driver
Mouse
|
The Mouse device to destroy
|
Return
|
ERROR_SUCCESS if completed or another error code on failure
|
PL050 keyboard functions
[Expand]
function PL050KeyboardControl(Keyboard:PKeyboardDevice; Request:Integer Argument1:PtrUInt; var Argument2:PtrUInt):LongWord;
Description: Implementation of KeyboardDeviceControl API for PL050 Keyboard
Note
|
Not intended to be called directly by applications, use KeyboardDeviceControl instead.
|
[Expand]
procedure PL050KeyboardInterruptHandler(Keyboard:PKeyboardDevice);
Description: Interrupt handler for the PL050 keyboard device
Note
|
Not intended to be called directly by applications
|
[Expand]
procedure PL050KeyboardWorker(Scancode:PPL050KeyboardScancode);
Description: Worker function for the PL050 keyboard device, called on a worker thread when a recognized scancode is received by the interrupt handler
Note
|
Not intended to be called directly by applications
|
PL050 mouse functions
[Expand]
function PL050MouseControl(Mouse:PMouseDevice; Request:Integer; Argument1:PtrUInt; var Argument2:PtrUInt):LongWord;
Description: Implementation of MouseDeviceControl API for PL050 Mouse
Note
|
Not intended to be called directly by applications, use MouseDeviceControl instead.
|
[Expand]
procedure PL050MouseInterruptHandler(Mouse:PMouseDevice);
Description: Interrupt handler for the PL050 mouse device
Note
|
Not intended to be called directly by applications
|
[Expand]
procedure PL050MouseWorker(Packet:PPL050MousePacket);
Description: Worker function for the PL050 mouse device, called on a worker thread when a new mouse packet is received by the interrupt handler
Note
|
Not intended to be called directly by applications
|
PL050 helper functions
[Expand]
function PL050KMIClear(Registers:PPL050KMIRegisters):LongWord;
Description: Clear the read buffer on a PL050 KMI device
Registers
|
Pointer to the PL050 KMI registers for the device
|
Return
|
ERROR_SUCCESS if completed or another error code on failure
|
[Expand]
function PL050KMIRead(Registers:PPL050KMIRegisters; var Value:Byte):LongWord;
Description: Read one byte of data from a PL050 KMI device
Registers
|
Pointer to the PL050 KMI registers for the device
|
Value
|
The returned value read from the device
|
Return
|
ERROR_SUCCESS if completed or another error code on failure
|
[Expand]
function PL050KMIWrite(Registers:PPL050KMIRegisters; Value:Byte):LongWord;
Description: Write one byte of data to a PL050 KMI device
Registers
|
Pointer to the PL050 KMI registers for the device
|
Value
|
The data value to write to the device
|
Return
|
ERROR_SUCCESS if completed or another error code on failure
|
[Expand]
function PL050KMICommand(Registers:PPL050KMIRegisters; Command:Byte; Data:PByte; DataSize:LongWord; Response:PByte; ResponseSize:LongWord):LongWord;
Description: Send a PS/2 command and data to a PL050 KMI device and wait for the required response
Registers
|
Pointer to the PL050 KMI registers for the device
|
Command
|
The PS/2 command to send to the device
|
Data
|
Pointer to the data to be sent with the command (Optional)
|
DataSize
|
The size in bytes of the data to be sent
|
Response
|
Pointer to a buffer to store the response from the device (Optional)
|
ResponseSize
|
The size in bytes of the response to be received
|
Return
|
ERROR_SUCCESS if completed or another error code on failure
|
[Expand]
function PL050KMIKeyboardReset(Keyboard:PPL050Keyboard):LongWord;
Description: Reset a PL050 keyboard device
Keyboard
|
The keyboard device to reset
|
Return
|
ERROR_SUCCESS if completed or another error code on failure
|
[Expand]
function PL050KMIKeyboardEnable(Keyboard:PPL050Keyboard):LongWord;
Description: Enable a PL050 keyboard device
Keyboard
|
The keyboard device to enable
|
Return
|
ERROR_SUCCESS if completed or another error code on failure
|
[Expand]
function PL050KMIKeyboardDisable(Keyboard:PPL050Keyboard):LongWord;
Description: Disable a PL050 keyboard device
Keyboard
|
The keyboard device to disable
|
Return
|
ERROR_SUCCESS if completed or another error code on failure
|
[Expand]
function PL050KMIKeyboardSetLEDs(Keyboard:PPL050Keyboard; LEDs:LongWord):LongWord;
Description: Set the keyboard LEDs for a PL050 keyboard device
Keyboard
|
The keyboard device to set the scancode set for
|
LEDs
|
Type keyboard LED values to set (eg KEYBOARD_LED_CAPSLOCK)
|
Return
|
ERROR_SUCCESS if completed or another error code on failure
|
Note
|
Caller must hold the keyboard lock
|
[Expand]
function PL050KMIKeyboardSetTypematic(Keyboard:PPL050Keyboard; Rate,Delay:LongWord):LongWord;
Description: Set the typematic rate and delay for a PL050 keyboard device
Keyboard
|
The keyboard device to set the scancode set for
|
Rate
|
Type typematic repeat rate to set (Milliseconds)
|
Delay
|
The typematic repeat delay to set (Repeat rate intervals before first repeat)
|
Return
|
ERROR_SUCCESS if completed or another error code on failure
|
Note
|
Caller must hold the keyboard lock
|
[Expand]
function PL050KMIKeyboardGetScancodeSet(Keyboard:PPL050Keyboard; var ScancodeSet:Byte):LongWord;
Description: Get the current scancode set from a PL050 keyboard device
Keyboard
|
The keyboard device to get the scancode set from
|
ScancodeSet
|
The returned scancode set value (eg PS2_KEYBOARD_SCANCODE_SET2)
|
Return
|
ERROR_SUCCESS if completed or another error code on failure
|
Note
|
Caller must hold the keyboard lock
|
[Expand]
function PL050KMIKeyboardSetScancodeSet(Keyboard:PPL050Keyboard; ScancodeSet:Byte):LongWord;
Description: Set the scancode set for a PL050 keyboard device
Keyboard
|
The keyboard device to set the scancode set for
|
ScancodeSet
|
The scancode set to set (eg PS2_KEYBOARD_SCANCODE_SET2)
|
Return
|
ERROR_SUCCESS if completed or another error code on failure
|
Note
|
Caller must hold the keyboard lock
|
[Expand]
function PL050KMIKeyboardCheckPressed(Keyboard:PPL050Keyboard; ScanCode:Word):Boolean;
Description: Check if the passed scan code has been pressed (True if not previously pressed)
Keyboard
|
The keyboard device to check for
|
ScanCode
|
The keyboard scan code to check
|
Note
|
Caller must hold the keyboard lock
|
[Expand]
function PL050KMIKeyboardCheckRepeated(Keyboard:PPL050Keyboard; ScanCode:Word):Boolean;
Description: Check if the passed scan code was the last key pressed and if the repeat delay has expired
Keyboard
|
The keyboard device to check for
|
ScanCode
|
The keyboard scan code to check
|
Note
|
Caller must hold the keyboard lock
|
[Expand]
function PL050KMIMouseReset(Mouse:PPL050Mouse):LongWord;
Description: Reset a PL050 mouse device
Mouse
|
The mouse device to reset
|
Return
|
ERROR_SUCCESS if completed or another error code on failure
|
Note
|
Caller must hold the mouse lock
|
[Expand]
function PL050KMIMouseEnable(Mouse:PPL050Mouse):LongWord;
Description: Enable a PL050 mouse device
Mouse
|
The mouse device to enable
|
Return
|
ERROR_SUCCESS if completed or another error code on failure
|
Note
|
Caller must hold the mouse lock
|
[Expand]
function PL050KMIMouseDisable(Mouse:PPL050Mouse):LongWord;
Description: Disable a PL050 mouse device
Mouse
|
The mouse device to disable
|
Return
|
ERROR_SUCCESS if completed or another error code on failure
|
Note
|
Caller must hold the mouse lock
|
[Expand]
function PL050KMIMouseSetSampleRate(Mouse:PPL050Mouse; Rate:Byte):LongWord;
Description: Set the sample rate on a PL050 mouse device
Mouse
|
The mouse device to set the rate for
|
Rate
|
The sample rate to set (samples per second)
|
Return
|
ERROR_SUCCESS if completed or another error code on failure
|
Note
|
Caller must hold the mouse lock
|
Return to Unit Reference