forked from lolo859/vystem
135 lines
6.0 KiB
Markdown
135 lines
6.0 KiB
Markdown
# Keyboard input subsystem
|
|
|
|
## Introduction
|
|
|
|
The keyboard input subsystem is responsible for abstracting keyboard devices and keyboards events. It's defined in `shelter/lib/include/devs/input/kbd.h` and implemented in `shelter/lib/src/devs/input/kbd.c`. It's still in the early stage and isn't finished for the moment.
|
|
|
|
## Overview
|
|
|
|
The keyboard input subsystem is based on two key concepts:
|
|
- keyboard devices: this is the standard abstraction for any keyboard-like devices
|
|
- keyboard events: provides a standard way to interpret any events from any keyboard devices
|
|
|
|
The keyboard input subsystem is initialized using `sh_kbd_init_devs()`.
|
|
|
|
### Keyboard devices
|
|
|
|
### Driver side
|
|
|
|
The keyboard device structure look like this:
|
|
``` C
|
|
typedef struct {
|
|
sh_uint8 kbd_id;
|
|
sh_queue_KBD_EVENT *events_queue;
|
|
sh_bool present;
|
|
sh_bool ver_maj;
|
|
sh_bool ver_num;
|
|
sh_bool shift;
|
|
sh_bool alt;
|
|
sh_bool ctrl;
|
|
sh_bool win;
|
|
sh_SPIN_LOCK spinlock;
|
|
} sh_kbd_DEVICE;
|
|
```
|
|
|
|
Each keyboard device is identified with a keyboard id. When a keyboard is unregistered, the keyboard id can be recycled for a new keyboard device. There is a maximum of 256 keyboards id, and so 256 maximum registered keyboard devices at the same time.
|
|
|
|
The keyboard id 0 is reserved for the PS2 keyboard. It's always valid, even if there is no PS2 controller.
|
|
|
|
The `present` boolean defines if the keyboard is present. If `present` is `SH_FALSE`, no actions except unregistering the keyboard is allowed on the keyboard device.
|
|
|
|
The `present` boolean for the keyboard od keyboard id 0 indicates if the PS2 controller is available.
|
|
|
|
There is two primitives to register keyboards devices:
|
|
- `sh_kbd_register_ps2(sh_bool is_present,sh_kbd_DRIVER_HANDLE **handle)`: register the PS2 keyboard, reserved for the PS2 driver
|
|
- `sh_kbd_register(sh_bool is_present,sh_kbd_DRIVER_HANDLE **handle)`: register a new keyboard device
|
|
|
|
Upon registration, a `sh_kbd_DRIVER_HANDLE` struct is completed. It became non valid when the keyboard is unregistered. It is reserved for driver usage only.
|
|
|
|
Two primitives accessible to drivers require this driver handle:
|
|
- `sh_kbd_set_flag(sh_kbd_DRIVER_HANDLE *handle,sh_uint8 flag,sh_bool value)`: set a flag about the keyboard corresponding to the provided driver handle
|
|
- `sh_kbd_push_events(sh_kbd_DRIVER_HANDLE *handle,sh_kbd_EVENT *event)`: push an event in the events queue of the keyboard device corresponding to the provided driver handle
|
|
|
|
There is, for the moment, no primitive to unregister a keyboard.
|
|
|
|
### Consumer side
|
|
|
|
Four functions are available for consumers:
|
|
- `sh_kbd_enumerate_devices(sh_kbd_ENUMERATION *enumeration)`: complete a `sh_kbd_ENUMERATION` structure, each bit set to 1 correspond to a valid keyboard id
|
|
- `sh_kbd_get_handle(sh_uint8 kbd_id,sh_kbd_CONSUMER_HANDLE **handle)`: return a valid consumer handle for the provided keyboard id. It uses `sh_malloc`
|
|
- `sh_kbd_destroy_handle(sh_kbd_CONSUMER_HANDLE **handle)`: free the provided consumer handle
|
|
- `sh_kbd_read_flag(sh_kbd_DRIVER_HANDLE *d_handle,sh_kbd_CONSUMER_HANDLE *c_handle,sh_uint8 flag,sh_bool *value)`: read a flag about the keyboard corresponding to the provided handle. Accepts either a driver or consumer handle, but fails if both handle are provided.
|
|
|
|
The possible flags to read/write are: `SH_KBD_FLAG_PRESENT`, `SH_KBD_FLAG_VER_MAJ`, `SH_KBD_FLAG_VER_NUM`, `SH_KBD_FLAG_SHIFT`, `SH_KBD_FLAG_ALT`, `SH_KBD_FLAG_CTRL`, `SH_KBD_FLAG_WIN`.
|
|
|
|
There is, for the moment, no way to read keyboards events.
|
|
|
|
## Keyboard events
|
|
|
|
A keyboard event is represented by this structure:
|
|
``` C
|
|
typedef struct {
|
|
sh_uint16 scancode;
|
|
sh_bool pressed;
|
|
sh_uint8 context_shift_win;
|
|
sh_uint8 context_alt;
|
|
sh_uint8 context_ctrl;
|
|
sh_uint8 context_lock_status;
|
|
sh_uint8 event_type;
|
|
sh_uint64 timestamp;
|
|
} sh_kbd_EVENT;
|
|
```
|
|
|
|
All non-pause events contain a snapshot of keyboard context state at emission time, before the state of corresponding flag in the keyboard device changes. These fields remain valid even for `SH_EVENT_TYPE_KBD_CONTEXT`:
|
|
- `context_shift_win`:
|
|
- Bit 0: shift active, checked with macro `SH_KBD_EVENT_SHIFT_ACTIVE`
|
|
- Bit 1: win active, checked with macro `SH_KBD_EVENT_WIN_ACTIVE`
|
|
- `context_alt`:
|
|
- Bit 0: right alt active, checked with macro `SH_KBD_EVENT_RIGHT_ACTIVE`
|
|
- Bit 1: left alt active, checked with macro `SH_KBD_EVENT_LEFT_ACTIVE`
|
|
- `context_ctrl`:
|
|
- Bit 0: right control active, checked with macro `SH_KBD_EVENT_RIGHT_ACTIVE`
|
|
- Bit 1: left control active, checked with macro `SH_KBD_EVENT_LEFT_ACTIVE`
|
|
- `context_lock_status`:
|
|
- Bit 0: numlock active, checked with `SH_KBD_EVENT_NUMLOCK_ACTIVE`
|
|
- Bit 0: capslock active, checked with `SH_KBD_EVENT_CAPSLOCK_ACTIVE`
|
|
|
|
There is a precise way of interpreting what this structure mean. It start by checking the value of `event_type`.
|
|
|
|
### `SH_EVENT_TYPE_KBD_PAUSE`
|
|
|
|
The event is a press of the pause key. The `scancode` and `pressed` fields should be ignored.
|
|
|
|
### `SH_EVENT_TYPE_KBD_CONTEXT`
|
|
|
|
This event is a press of a modifier key. It allows to abstract modifiers keys events accross all types of keyboards.
|
|
|
|
The scancode must be one of the following:
|
|
- `SH_KBD_CONTEXT_LSHIFT`
|
|
- `SH_KBD_CONTEXT_RSHIFT`
|
|
- `SH_KBD_CONTEXT_LCTRL`
|
|
- `SH_KBD_CONTEXT_RCTRL`
|
|
- `SH_KBD_CONTEXT_LALT`
|
|
- `SH_KBD_CONTEXT_RALT`
|
|
- `SH_KBD_CONTEXT_WIN`
|
|
- `SH_KBD_CONTEXT_NUMLOCK`
|
|
- `SH_KBD_CONTEXT_CAPSLOCK`
|
|
|
|
You need to check the `pressed` boolean to know if the key was pressed or released.
|
|
|
|
### `SH_EVENT_TYPE_PS2_NORMAL`
|
|
|
|
This event type represents a standard PS2 Set1 scancode. The scancode is put in the low 8 bits of the `scancode` fields. The high 8 bits are set to 0.
|
|
|
|
You need to check the `pressed` boolean to know if the key was pressed or released.
|
|
|
|
### `SH_EVENT_TYPE_PS2_E0`
|
|
|
|
This event type represents an extended PS2 Set1 scancode prefixed by `0xE0`. The scancode is put in the low 8 bits of the `scancode` fields. The high 8 bits are set to `0xE0`.
|
|
|
|
You need to check the `pressed` boolean to know if the key was pressed or released.
|
|
|
|
### Notes
|
|
|
|
For `SH_EVENT_TYPE_PS2_NORMAL` and `SH_EVENT_TYPE_PS2_E0` events type, the scancode, when `pressed` is `SH_FALSE`, keeps its bit 8 to 1.
|