Olet jC$lleen kerran aivan ytimessC$. Nyt kun olemme nC$hneet, kuinka paljon
tuskaa "Push" -mallin IPC (Mailbox/Callback) voi aiheuttaa VNC:n ja QEMU:n
epC$tahtisessa maailmassa, meidC$n on pakko siirtyC$ tC$yteen **"Pull"
(Tilauspohjainen Ringbuffer)** -arkkitehtuuriin myC6s USB:n kanssa.
TC$mC$ on tC$smC$lleen se abstraktiotaso, johon Unix/Linux on aina pyrkinyt
("Kaikki on tiedostoa", eli `/dev/input/mouse0`).
### Suunnitelma: The Hauki Input Router (HIR)
MeidC$n tC$ytyy rakentaa C-ytimeen ja JS-APIin tC$ysin uusi reititin. Se
toimii nC$in:
1. **Laite-abstraktio:** Kun USB-hiiri kytketC$C$n, UHCI-ajuri (joka pyC6rii
VCPU:ssa tai OS-taskina) lukee laitteen koordinaatit, mutta ei yritC$ suoraan
soittaa kenenkC$C$n callbackia. Sen sijaan se kutsuu `sys.push_stream("usb_mous
e0", data)`.
2. **Rekisteri:** OS pitC$C$ yllC$ listaa kaikista olemassa olevista
striimeistC$ (nC$ppC$imistC6, sarjaportti, usb_mouse0, usb_serial1).
3. **Sovelluksen Rajapinta (Subscribe):** Kun sovellus kC$ynnistyy, se kysyy
`sys.get_streams()`. Sovellus valitsee hiiren ja kC$skee `var my_cursor =
sys.subscribe("usb_mouse0")`.
4. **Pull-lukeminen:** Pelisilmukassa sovellus sanoo: `var data =
sys.read_stream(my_cursor)`. TC$mC$ lukee C-tason rengaspuskuria juuri siitC$
kohdasta, mihin sovellus viimeksi jC$i, hC$iritsemC$ttC$ muita sovelluksia,
jotka ehkC$ lukevat samaa hiirtC$!
TC$mC$ on tC$ydellinen. Se ratkaisee VNC-lagin, moniajon ja laitteistorippuvuud
et yhdellC$ iskulla.
### Miten teemme tC$mC$n lennosta?
Emme halua kirjoittaa koko C-ydintC$ uusiksi juuri nyt, koska kC$C$nsit sen
juuri toimivaksi. Vaan tiedC$tkC6 mitC$? **MeillC$ on jo valmis C-tason
"tilauspuskuri"!**
KC$ytimme komentoa `load(37)` (se raaka heksadumppi kbd_ringistC$) lukemaan
nC$ppC$imistC6C$. Mutta me voimme laajentaa tC$mC$n kC$sitteen koskemaan
MQuickJS:n muistitaulukoita (`Uint8Array`).
Voimme varata muistista (vaikka osoitteesta `0x03800000`) 64KB alueen "The
Stream Multiplexerille".
* Jokainen 4KB blokki on oma Streaminsa.
* EnsimmC$iset 16 tavua blokista ovat otsikko (Tail, Head, Nimi).
* Loput ovat varsinaista datarengasta.
**USB-ajuri (`13_USB.JS` -> `14_USB_STREAM.JS`):**
Kun USB-ajurimme `pollMouse()` saa koordinaatit `-12, 5, btn:0`, se ei tulosta
niitC$ sarjaporttiin (mikC$ hidastaa). Sen sijaan se pakkaa ne 4-tavuiseksi
paketiksi ja kirjoittaa `sys.wr32(Stream_Mouse_Head, paketti)`.
**Sovellus (`SAND11.JS`):**
Sovellus kysyy OS:ltC$: "MissC$ muistiosoitteessa on hiiren stream?"
Ja sitten sen fysiikkasilmukka vain lukee `sys.rd32()` -komennolla tuota
muistiosoitetta omassa tahdissaan! Koska muistinluku (`sys.peek`/`sys.rd32`)
on synkroninen laitteistokomento MQuickJS:ssC$ (se kutsuu suoraan `load(2/31)`
C-koodia), se on aivan yhtC$ nopea ja turvallinen kuin C-ytimen oma koodi.
Haluatko, ettC$ koodaan sinulle tC$mC$n **Stream Multiplexerin** lennosta
puhtaalla JS:llC$ ja pC$ivitC$mme USB-ajurin ja Sand-moottorin keskustelemaan
toistensa kanssa fyysisen RAM-muistipuskurin lC$pi? TC$mC$ mahdollistaa sen,
ettC$ voit ohjata hiekan sivellintC$ USB-hiirellC$!