eudev starts at boot; Xorg finds its input devices through it
udevd and a one-shot trigger run from schinit, 10-schos.conf no longer lists event0/event1, and the docs say what udev covers and what it does not. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EVRhxi9zpdW2uDUN4FVcao
This commit is contained in:
parent
5d4d318ebf
commit
b3f72cd95e
13 changed files with 169 additions and 50 deletions
|
|
@ -94,6 +94,7 @@ Read in this order if you are new:
|
|||
| [fat.md](fat.md) | FAT12/16/32 with long names: USB sticks, SD cards, the ESP. |
|
||||
| [devices.md](devices.md) | Buses, classes, binding, and the vtables consumers talk to. |
|
||||
| [usb.md](usb.md) | xHCI, the USB core, and the three class drivers. |
|
||||
| [udev.md](udev.md) | eudev on SchOS: the device table, the `/sys` tree, uevents, datagram sockets. |
|
||||
| [graphics.md](graphics.md) | Framebuffer, `/dev/fb0`, text rendering, the console, PSOGM and GMMOS. |
|
||||
| [desktop.md](desktop.md) | Xorg on the framebuffer, Window Maker, and what they stand on. |
|
||||
| [packages.md](packages.md) | The apk root: Alpine's packages, and SchOS as one of them. |
|
||||
|
|
|
|||
|
|
@ -49,11 +49,9 @@ the real program is for.
|
|||
`xterm` runs and exits, and the server stays up.
|
||||
- **`/root/.xinitrc`** is `exec wmaker`. Without it xinit falls back to twm and an xterm, which
|
||||
are not in the image.
|
||||
- **`/etc/X11/xorg.conf.d/10-schos.conf`** names the input devices. Alpine's Xorg asks udev for
|
||||
them, SchOS has no udev, and X came up with no keyboard and no mouse: the pointer did not
|
||||
move and nothing could end the session. SchOS has exactly two input nodes whatever the
|
||||
machine, so a fixed list is the whole answer (`AutoAddDevices` off, Ctrl+Alt+Backspace
|
||||
enabled).
|
||||
- **`/etc/X11/xorg.conf.d/10-schos.conf`** holds what the defaults do not give: Ctrl+Alt+Backspace
|
||||
enabled, the keyboard options, and the framebuffer driver. Input devices are *found*, not
|
||||
named: Xorg asks libudev, which reads what `udevd` wrote to `/run/udev` ([udev.md](udev.md)).
|
||||
- **`/etc/asound.conf`** is for sound, not X ([audio.md](audio.md)).
|
||||
|
||||
## Using it
|
||||
|
|
@ -71,8 +69,9 @@ through ACPI, and reach X as a mouse: pointer, click and tap.
|
|||
|
||||
- **No acceleration.** Software rendering to the framebuffer: no DRM, no glamor, no DRI, no
|
||||
OpenGL beyond what software gives. GPU drivers are a plan ([../plan/gpu.md](../plan/gpu.md)).
|
||||
- **No udev.** Input devices are named in a config file, not found; `/sys` has no `devices`
|
||||
tree and no uevent socket.
|
||||
- **udev covers the kernel's own devices only.** Input, terminals, memory devices, the
|
||||
framebuffer and disks are announced; PCI and USB devices are in `/sys/bus/*/devices` but are
|
||||
not yet in the `/sys/devices` tree or on the uevent socket ([udev.md](udev.md)).
|
||||
- **Touchpads are mice**: no two-finger scroll, no gestures, no palm rejection.
|
||||
- **No resolution change from inside X.** The mode is the console's; `schmode` changes the
|
||||
`vgpud` head only, and the loader's menu is where a real panel's mode is chosen.
|
||||
|
|
|
|||
|
|
@ -275,10 +275,15 @@ at the moment it is read, so a stick shows up in `/sys/bus/usb/devices` as soon
|
|||
as it is attached. Text files report size 0, as `/proc`'s do; binary ones (the
|
||||
tables, `config`) report their real length, since tools copy them by it.
|
||||
|
||||
What is missing, compared with Linux: `/sys/devices` and its symlinks (the
|
||||
The kernel's own devices (input, tty, mem, graphics, block) have the Linux tree:
|
||||
`/sys/devices/virtual/<class>/<name>` with `dev`, `uevent` and a `subsystem`
|
||||
link, `/sys/class/<class>/<name>` and `/sys/dev/{char,block}/MAJ:MIN` as symlinks
|
||||
into it, and input capabilities; `uevent` is writable, and a write is announced
|
||||
on the uevent netlink socket ([udev.md](udev.md)).
|
||||
|
||||
What is missing, compared with Linux: PCI and USB devices in that tree (the
|
||||
`bus/*/devices` entries are directories rather than links into it),
|
||||
`/sys/class` beyond `dmi` and `power_supply`, `/sys/block`, a uevent socket (so
|
||||
no udev), and anything writable. PCI `config` is
|
||||
`/sys/class` entries for them, `/sys/block`, and most of what is writable. PCI `config` is
|
||||
256 bytes, because config space is read through port `0xCF8`, which reaches
|
||||
no further.
|
||||
|
||||
|
|
|
|||
|
|
@ -649,7 +649,11 @@ information was there and the code did not ask.
|
|||
`SO_BROADCAST`, `TCP_NODELAY` reach lwIP's pcb; `SO_SNDBUF`/`SO_RCVBUF` report the
|
||||
real size; `SO_PASSCRED` on Unix sockets) and refuses the rest with `ENOPROTOOPT`.
|
||||
Notably absent: `SO_RCVTIMEO`/`SO_SNDTIMEO`.
|
||||
- **`SOCK_DGRAM` over AF_UNIX does not exist** — stream only.
|
||||
- **`SOCK_DGRAM` and `SOCK_SEQPACKET` over AF_UNIX** keep message boundaries (each message carries a
|
||||
16-byte header in the same ring) but have no unconnected form: `socketpair` and listeners work,
|
||||
`sendto` a path does not.
|
||||
- **Netlink `NETLINK_KOBJECT_UEVENT`** is the one multicast family: sockets bound to group 1 hear the
|
||||
kernel's device events, group 2 what udevd re-announces, and a datagram can be addressed to a port id.
|
||||
- **No IPv6**, no firewall or packet filter of any kind, and a TCP stack that has
|
||||
been used for downloads at tens of megabits and no more than that.
|
||||
- **Three drivers in the kernel, one Linux driver outside it**, and the class is
|
||||
|
|
|
|||
82
docs/architecture/udev.md
Normal file
82
docs/architecture/udev.md
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
# udev
|
||||
|
||||
Alpine's `eudev` runs on SchOS as an ordinary process, started by `schinit`
|
||||
(`etc/schinit/udevd.job`, with `udev-trigger.job` replaying the devices that
|
||||
were there first). It is what lets Xorg *find* its keyboard and mouse instead of
|
||||
being told, and the road to a Wayland compositor starts here: libinput and
|
||||
libseat both ask udev what exists.
|
||||
|
||||
The kernel's half is three pieces, all small, none of them specific to udev.
|
||||
|
||||
## The device table: `kernel/dev/kdev.c`
|
||||
|
||||
The devices the kernel implements itself — input event nodes, the memory
|
||||
devices, terminals, the framebuffer, the disks — are listed once, with their
|
||||
class, name, `/dev` name and parent. Everything below is generated from it.
|
||||
|
||||
The device numbers are the ones `stat()` reports for the node, not SchOS's
|
||||
internal ones: `/dev/tty1` is `4:1` to a Linux program (`linux_tty_rdev` in
|
||||
`kernel/sys/sys_fs.c`), and udev compares what it reads in `/sys` with what
|
||||
`stat()` says about the node. `dev_stat_numbers()` is the one mapping both use.
|
||||
|
||||
## `/sys`: `kernel/fs/sysfs.c`
|
||||
|
||||
```
|
||||
/sys/devices/virtual/input/input0/ name capabilities/{ev,key,rel,abs} properties
|
||||
/sys/devices/virtual/input/input0/event0/ dev uevent subsystem -> ../../../../../class/input
|
||||
/sys/class/input/event0 -> ../../devices/virtual/input/input0/event0
|
||||
/sys/dev/char/13:64 ... -> ../../devices/virtual/...
|
||||
```
|
||||
|
||||
Symlinks are real (`T_SYMLINK` inodes whose target is generated). `uevent` is
|
||||
readable (`DEVPATH=`, `SUBSYSTEM=`, `MAJOR=`, `MINOR=`, `DEVNAME=`) and
|
||||
writable: `echo add > uevent` — which is what `udevadm trigger` does — makes the
|
||||
kernel announce the device again. A write to a PCI or USB device's `uevent` is
|
||||
accepted and says nothing yet, because those devices are not in the
|
||||
`/sys/devices` tree and an event's `DEVPATH` has to name something that exists.
|
||||
|
||||
The input capability files are what `input_id` reads to decide
|
||||
`ID_INPUT_KEYBOARD` or `ID_INPUT_MOUSE`. SchOS has two input devices whatever
|
||||
the machine — every keyboard on `event0`, every mouse on `event1`
|
||||
(`kernel/dev/input.c`) — so each has a fixed, plausible capability set.
|
||||
|
||||
## `/dev`: `kernel/fs/devfs.c`
|
||||
|
||||
devtmpfs is no longer read-only: udev creates `/dev/char/MAJ:MIN`, `/dev/fd`,
|
||||
`/dev/input/by-*` and the like. A small in-memory overlay (192 entries) holds
|
||||
directories and symlinks, listed after the kernel's own nodes in whichever
|
||||
directory they are in. Device nodes themselves are still the kernel's: `mknod`
|
||||
and regular files in `/dev` are refused.
|
||||
|
||||
## The sockets: `kernel/net/unix.c`
|
||||
|
||||
- **`AF_UNIX` `SOCK_DGRAM` and `SOCK_SEQPACKET`** keep message boundaries.
|
||||
udevd's control socket is `SEQPACKET`, and its manager and workers talk over
|
||||
a `DGRAM` socketpair. A message carries its sender's credentials with it
|
||||
(several workers share one end), a zero-length datagram is a datagram, and a
|
||||
datagram socket never reads end-of-stream.
|
||||
- **`AF_NETLINK` / `NETLINK_KOBJECT_UEVENT`** sockets bind to multicast groups:
|
||||
group 1 is the kernel's events, group 2 is what udevd re-announces once its
|
||||
rules have run. A datagram can also be addressed to a port id — udevd hands
|
||||
an event to an idle worker that way, and the worker believes it only from the
|
||||
manager's port. The kernel's messages arrive as credentials with uid 0, pid 0.
|
||||
A queue that is full drops the message, as Linux does, and `udevadm trigger`
|
||||
is how a reader recovers.
|
||||
|
||||
## What is not there
|
||||
|
||||
- PCI and USB devices in `/sys/devices`, and `add`/`remove` events from the
|
||||
hotplug thread. A USB keyboard works because every keyboard is `event0`, not
|
||||
because udev knew it arrived.
|
||||
- `hwdb` (`/etc/udev/hwdb.bin`): `udevadm hwdb --update` has not been run in the
|
||||
image, so `60-input-id` logs "returned non-zero" for the hwdb import. The
|
||||
properties that matter come from `input_id`.
|
||||
- Block device partitions, `by-id` / `by-uuid` links, and a `/sys/block`.
|
||||
- `libinput` and `libseat` (next; see [../plan/roadmap.md](../plan/roadmap.md)).
|
||||
|
||||
## Testing
|
||||
|
||||
Boot the ISO and run `udevd --debug &`, then `udevadm trigger; udevadm settle`.
|
||||
`/run/udev/data/c7:0` should contain
|
||||
`ID_INPUT_KEYBOARD=1`, and `udevadm info /dev/input/event0` should print the
|
||||
device. Under X, `/var/log/Xorg.0.log` says `config/udev: Adding input device`.
|
||||
Loading…
Reference in a new issue