mirror of
https://github.com/alfishe/amiga-bootcamp.git
synced 2026-06-13 00:26:28 +00:00
Phase 1 continued: serial, input devices + README indexes
10_devices: - serial.md: expanded with DB-25 pinout, custom chip UART registers, baud rate calculation table, open/configure/read/write patterns, serial debugging (KPrintF/Sushi) - input.md: expanded with handler chain architecture diagram, InputEvent struct, event classes table, qualifier bits, custom handler with key remapping, event consumption/blocking, synthetic event injection, Commodities Exchange Updated indexes: - 07_dos/README.md — enriched descriptions for all files - 10_devices/README.md — enriched descriptions for all files
This commit is contained in:
parent
da9e7d3b63
commit
0ded078134
4 changed files with 326 additions and 73 deletions
|
|
@ -1,41 +1,216 @@
|
|||
[← Home](../README.md) · [Devices](README.md)
|
||||
|
||||
# input.device — Event Stream Merging
|
||||
# input.device — Input Event Handler Chain
|
||||
|
||||
## Overview
|
||||
|
||||
`input.device` merges events from keyboard, mouse, gameport, and timer into a single input stream that feeds Intuition. Input handlers can be installed at various priorities to filter, modify, or consume events.
|
||||
`input.device` is the central dispatcher for all input events on AmigaOS. It collects raw events from keyboard, mouse, joystick, and other sources, then distributes them through a **priority-ordered handler chain**. Intuition sits at priority 50 in this chain — custom input handlers can intercept events before or after Intuition.
|
||||
|
||||
---
|
||||
|
||||
## Handler Priority Levels
|
||||
## Handler Chain Architecture
|
||||
|
||||
| Priority | Consumer |
|
||||
|---|---|
|
||||
| 100 | System reserved |
|
||||
| 51+ | Custom high-priority handlers |
|
||||
| 50 | Intuition |
|
||||
| 20 | Console.device |
|
||||
| 0 | Default |
|
||||
```mermaid
|
||||
flowchart TD
|
||||
KB["keyboard.device"] --> ID["input.device"]
|
||||
GP["gameport.device"] --> ID
|
||||
OTHER["Other sources"] --> ID
|
||||
|
||||
ID --> H1["Handler Pri 100<br/>Commodities Exchange"]
|
||||
H1 --> H2["Handler Pri 51<br/>Custom 'hot key' handler"]
|
||||
H2 --> H3["Handler Pri 50<br/>Intuition"]
|
||||
H3 --> H4["Handler Pri 0<br/>Console.device"]
|
||||
H4 --> H5["Handler Pri -50<br/>Application handler"]
|
||||
|
||||
style H3 fill:#e8f4fd,stroke:#2196f3,color:#333
|
||||
```
|
||||
|
||||
Events flow from highest to lowest priority. Each handler can:
|
||||
- **Pass** the event through (return the event list unchanged)
|
||||
- **Modify** the event (e.g., remap keys)
|
||||
- **Consume** the event (remove from chain — lower handlers never see it)
|
||||
- **Insert** new synthetic events
|
||||
|
||||
---
|
||||
|
||||
## Commands
|
||||
## InputEvent Structure
|
||||
|
||||
| Code | Constant | Description |
|
||||
```c
|
||||
/* devices/inputevent.h — NDK39 */
|
||||
struct InputEvent {
|
||||
struct InputEvent *ie_NextEvent; /* linked list */
|
||||
UBYTE ie_Class; /* event type (IECLASS_*) */
|
||||
UBYTE ie_SubClass; /* subclass */
|
||||
UWORD ie_Code; /* key code, button, qualifier */
|
||||
UWORD ie_Qualifier; /* modifier keys state */
|
||||
union {
|
||||
struct {
|
||||
WORD ie_x; /* mouse X delta or absolute */
|
||||
WORD ie_y; /* mouse Y delta or absolute */
|
||||
} ie_xy;
|
||||
APTR ie_addr; /* pointer data */
|
||||
} ie_position;
|
||||
struct timeval ie_TimeStamp; /* when event occurred */
|
||||
};
|
||||
```
|
||||
|
||||
### Event Classes
|
||||
|
||||
| Class | Constant | Source |
|
||||
|---|---|---|
|
||||
| 9 | `IND_ADDHANDLER` | Add input handler |
|
||||
| 10 | `IND_REMHANDLER` | Remove input handler |
|
||||
| 11 | `IND_WRITEEVENT` | Inject an InputEvent into the stream |
|
||||
| 12 | `IND_SETTHRESH` | Set double-click threshold |
|
||||
| 13 | `IND_SETPERIOD` | Set key repeat period |
|
||||
| 14 | `IND_SETMPORT` | Set mouse port type |
|
||||
| 15 | `IND_SETMTRIG` | Set mouse trigger |
|
||||
| 16 | `IND_SETMTYPE` | Set mouse type |
|
||||
| $01 | `IECLASS_RAWKEY` | Raw key press/release |
|
||||
| $02 | `IECLASS_RAWMOUSE` | Mouse movement + buttons |
|
||||
| $04 | `IECLASS_TIMER` | Timer tick event |
|
||||
| $07 | `IECLASS_NEWPOINTERPOS` | Absolute pointer position |
|
||||
| $09 | `IECLASS_DISKINSERTED` | Disk inserted |
|
||||
| $0A | `IECLASS_DISKREMOVED` | Disk removed |
|
||||
| $0D | `IECLASS_NEWPREFS` | Preferences changed |
|
||||
|
||||
### Qualifier Bits
|
||||
|
||||
| Bit | Constant | Key |
|
||||
|---|---|---|
|
||||
| 0 | `IEQUALIFIER_LSHIFT` | Left Shift |
|
||||
| 1 | `IEQUALIFIER_RSHIFT` | Right Shift |
|
||||
| 2 | `IEQUALIFIER_CAPSLOCK` | Caps Lock |
|
||||
| 3 | `IEQUALIFIER_CONTROL` | Ctrl |
|
||||
| 4 | `IEQUALIFIER_LALT` | Left Alt |
|
||||
| 5 | `IEQUALIFIER_RALT` | Right Alt |
|
||||
| 6 | `IEQUALIFIER_LCOMMAND` | Left Amiga |
|
||||
| 7 | `IEQUALIFIER_RCOMMAND` | Right Amiga |
|
||||
| 8 | `IEQUALIFIER_NUMERICPAD` | Key is on numeric pad |
|
||||
| 9 | `IEQUALIFIER_REPEAT` | Key repeat (auto-repeat) |
|
||||
| 10 | `IEQUALIFIER_INTERRUPT` | Event from interrupt |
|
||||
| 11 | `IEQUALIFIER_MULTIBROADCAST` | Broadcast to all handlers |
|
||||
| 12 | `IEQUALIFIER_MIDBUTTON` | Middle mouse button |
|
||||
| 13 | `IEQUALIFIER_RBUTTON` | Right mouse button |
|
||||
| 14 | `IEQUALIFIER_LEFTBUTTON` | Left mouse button |
|
||||
| 15 | `IEQUALIFIER_RELATIVEMOUSE` | Mouse values are deltas |
|
||||
|
||||
---
|
||||
|
||||
## Installing a Custom Input Handler
|
||||
|
||||
```c
|
||||
#include <devices/input.h>
|
||||
#include <devices/inputevent.h>
|
||||
|
||||
/* Handler function — called from input.device context: */
|
||||
struct InputEvent * __saveds __asm MyHandler(
|
||||
register __a0 struct InputEvent *events,
|
||||
register __a1 APTR handlerData)
|
||||
{
|
||||
struct InputEvent *ev;
|
||||
for (ev = events; ev; ev = ev->ie_NextEvent)
|
||||
{
|
||||
if (ev->ie_Class == IECLASS_RAWKEY)
|
||||
{
|
||||
UWORD key = ev->ie_Code & 0x7F;
|
||||
BOOL up = ev->ie_Code & 0x80;
|
||||
|
||||
/* Example: remap F10 ($59) to Escape ($45): */
|
||||
if (key == 0x59)
|
||||
ev->ie_Code = (up ? 0x80 : 0x00) | 0x45;
|
||||
}
|
||||
}
|
||||
return events; /* pass all events to next handler */
|
||||
}
|
||||
|
||||
/* Install the handler: */
|
||||
struct Interrupt handlerInt;
|
||||
handlerInt.is_Node.ln_Type = NT_INTERRUPT;
|
||||
handlerInt.is_Node.ln_Pri = 51; /* just above Intuition (50) */
|
||||
handlerInt.is_Node.ln_Name = "MyKeyMapper";
|
||||
handlerInt.is_Data = myData;
|
||||
handlerInt.is_Code = (APTR)MyHandler;
|
||||
|
||||
struct MsgPort *inputPort = CreateMsgPort();
|
||||
struct IOStdReq *inputReq = (struct IOStdReq *)
|
||||
CreateIORequest(inputPort, sizeof(struct IOStdReq));
|
||||
OpenDevice("input.device", 0, (struct IORequest *)inputReq, 0);
|
||||
|
||||
inputReq->io_Command = IND_ADDHANDLER;
|
||||
inputReq->io_Data = (APTR)&handlerInt;
|
||||
DoIO((struct IORequest *)inputReq);
|
||||
|
||||
/* ... handler is now active ... */
|
||||
|
||||
/* Remove handler before exit: */
|
||||
inputReq->io_Command = IND_REMHANDLER;
|
||||
inputReq->io_Data = (APTR)&handlerInt;
|
||||
DoIO((struct IORequest *)inputReq);
|
||||
```
|
||||
|
||||
### Consuming Events (Blocking)
|
||||
|
||||
```c
|
||||
/* To consume an event (prevent it from reaching Intuition): */
|
||||
struct InputEvent * __saveds __asm BlockEscape(
|
||||
register __a0 struct InputEvent *events,
|
||||
register __a1 APTR data)
|
||||
{
|
||||
struct InputEvent *ev, *prev = NULL;
|
||||
for (ev = events; ev; )
|
||||
{
|
||||
if (ev->ie_Class == IECLASS_RAWKEY &&
|
||||
(ev->ie_Code & 0x7F) == 0x45) /* Escape */
|
||||
{
|
||||
/* Remove from chain: */
|
||||
if (prev)
|
||||
prev->ie_NextEvent = ev->ie_NextEvent;
|
||||
else
|
||||
events = ev->ie_NextEvent;
|
||||
ev = ev->ie_NextEvent;
|
||||
continue;
|
||||
}
|
||||
prev = ev;
|
||||
ev = ev->ie_NextEvent;
|
||||
}
|
||||
return events;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Injecting Synthetic Events
|
||||
|
||||
```c
|
||||
/* Send a fake key press: */
|
||||
struct InputEvent fake;
|
||||
fake.ie_Class = IECLASS_RAWKEY;
|
||||
fake.ie_Code = 0x45; /* Escape, key down */
|
||||
fake.ie_Qualifier = 0;
|
||||
|
||||
inputReq->io_Command = IND_WRITEEVENT;
|
||||
inputReq->io_Data = (APTR)&fake;
|
||||
inputReq->io_Length = sizeof(struct InputEvent);
|
||||
DoIO((struct IORequest *)inputReq);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Commodities Exchange
|
||||
|
||||
The Commodities Exchange (`commodities.library`) provides a high-level framework for input handlers:
|
||||
|
||||
```c
|
||||
/* Define a hot key: */
|
||||
CxObj *broker = CxBroker(&newBroker, NULL);
|
||||
CxObj *filter = CxFilter("rawkey control esc"); /* Ctrl+Esc */
|
||||
CxObj *sender = CxSender(brokerPort, EVT_HOTKEY);
|
||||
AttachCxObj(filter, sender);
|
||||
AttachCxObj(broker, filter);
|
||||
ActivateCxObj(broker, TRUE);
|
||||
```
|
||||
|
||||
This is the preferred method for applications — avoids writing raw input handlers.
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- NDK39: `devices/input.h`
|
||||
- [input_events.md](../09_intuition/input_events.md) — handler installation example
|
||||
- NDK39: `devices/input.h`, `devices/inputevent.h`
|
||||
- ADCD 2.1: input.device autodocs
|
||||
- See also: [keyboard.md](keyboard.md) — raw key code map
|
||||
- See also: [idcmp.md](../09_intuition/idcmp.md) — Intuition input handling
|
||||
- See also: [input_events.md](../09_intuition/input_events.md) — event flow through Intuition
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue