Unit PL050

From Ultibo.org
Jump to: navigation, search

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



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;  


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)


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


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

PPL050KMIRegisters = ^TPL050KMIRegisters;

TPL050KMIRegisters = record

Note: Layout of the PL050 registers (See: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0143c/i1005653.html)
CR:LongWord; Control register
STAT:LongWord; Status register
DATA:LongWord; Received data (read)/Data to be transmitted (write)
CLKDIV:LongWord; Clock divisor register
IIR:LongWord; Interrupt status register

PL050 keyboard scancode

PPL050KeyboardScancode = ^TPL050KeyboardScancode;

TPL050KeyboardScancode = record

Keyboard:PPL050Keyboard;  
Count:LongWord;  
Index:LongInt;  
Scancode:TPS2KeyboardScancode;  

PL050 keyboard

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

PPL050MousePacket = ^TPL050MousePacket;

TPL050MousePacket = record

Mouse:PPL050Mouse;  
Count:LongWord;  
Packet:TPS2MousePacket;  

PL050 mouse

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

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


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


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


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

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.


procedure PL050KeyboardInterruptHandler(Keyboard:PKeyboardDevice);
Description: Interrupt handler for the PL050 keyboard device
Note Not intended to be called directly by applications


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

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.


procedure PL050MouseInterruptHandler(Mouse:PMouseDevice);
Description: Interrupt handler for the PL050 mouse device
Note Not intended to be called directly by applications


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

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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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