Compare commits

..
Author SHA1 Message Date
Aaron 6c7bcc1911 better testing
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2026-03-04 00:00:56 +00:00
Aaron e09c9b5595 refactor 2026-03-04 00:00:56 +00:00
Aaron 9476bb0c8a compile 2026-03-04 00:00:56 +00:00
Aaron 8f7db8507b Queues 2026-03-04 00:00:56 +00:00
t3hn3rd 452203b7b4 Merge pull request 'bug: vtop incorrect bitmask' (#36) from feature/vtop-fix into develop
continuous-integration/drone/push Build is passing
Reviewed-on: #36
Reviewed-by: Aaron Hance <[email protected]>
2026-03-03 20:03:47 +00:00
t3hn3rd 76c419336e bug: vtop incorrect bitmask
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
- Fix for issue #32 in which the incorrect bitmask ($FFFFFF) is used where
  $3FFFFF should be used instead. (24 vs 22 bits).
2026-03-03 19:10:08 +00:00
admin 2ad0ae8420 Merge pull request 'feature/gitattributes' (#30) from feature/gitattributes into develop
continuous-integration/drone/push Build is passing
Reviewed-on: #30
2026-03-02 21:56:56 +00:00
t3hn3rd c0c199bfe6 .gitattributes update
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
- Updated .gitattributes linguist excludes for compile-time directories.
2026-03-02 21:48:10 +00:00
t3hn3rd 7ec3bcb9b9 .gitattributes & doc directory
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
- Added gitattributes for linguist exclusions
- Created empty doc folder for local working docs
2026-03-02 21:41:14 +00:00
admin 4bd0a2dfbf Merge pull request 'Merge feature/graphics-interrupts into develop' (#14) from feature/graphics-interrupts into develop
continuous-integration/drone/push Build is passing
Reviewed-on: #14
2026-03-02 19:19:46 +00:00
admin 431e5bc8f4 Merge pull request 'Merge feature/USB into develop' (#13) from feature/USB into develop
continuous-integration/drone/push Build is passing
Reviewed-on: #13
2026-03-02 19:14:05 +00:00
t3hn3rd 8169d93a9c refactor: move render loop & USB hotplug to timer-driven units
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Replace the blocking main render loop in kernel.pas with two new
timer-hooked units that are driven by the 1024Hz PIT interrupt:

- graphicsrefresh: calls desktop.update, uidebug.update, lvgl_handler
  and video.Flush every 4 ticks (~256 FPS target).
- usbhotplug: calls usbcore.usb_check_hotplug every 1024 ticks (~1Hz).

The kernel main procedure now registers both timer hooks and enters an
idle STI/HLT loop (kernel.yield), allowing the CPU to sleep between
interrupts instead of busy-spinning.

Also removes the unused myUserLandFunction and reorders early syslog
init calls for clarity.
2026-03-02 19:04:42 +00:00
t3hn3rd 547251dbd0 update: Kernel.pas changes to align with USB implementation
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
- Kernel.pas updated to init USB devices & check for hotplug.
- USB Poll removed given USB stack is now interrupt driven.
2026-03-02 15:53:40 +00:00
t3hn3rd 7bbcc44c5e Feature: USB - Hotplug, mass storage, disconnect callbacks, dynamic device lists
- Add disconnect callback (fnDisconnect) to TUSBDevice for safe unplug handling
- Add HotplugArmed/PortChangePending flags to TUSBHCDriver for deferred
  hotplug processing from ISR context (OHCI RHSC, EHCI PCD, xHCI PSC)
- Implement usb_rescan_port() and usb_check_hotplug() in usbcore
- Add usb_bulk_transfer_wait() with timer-based timeout (bios_data_area)
- Add timer-based timeout to usb_control_msg polling loop
- Replace static device arrays with dynamic linked lists in class drivers:
  usb_keyboard (KeyboardList), usb_mouse (MouseList), usb_storage (StorageList)
- Add 3-strike fail-count self-deactivation in keyboard/mouse poll loops
- Add unload() disconnect handlers for keyboard, mouse, and storage drivers
- Implement USB Mass Storage BOT driver (usb_storage.pas):
  CBW/CSW transport, SCSI INQUIRY/READ_CAPACITY/READ10/WRITE10,
  storagemanagement integration with read/write callbacks
- xHCI: acknowledge port status change W1C bits in event handler
- Integrate usb_check_hotplug + poll_keyboards/poll_mice into kernel main loop
2026-03-02 15:52:49 +00:00
t3hn3rd 25475a88a7 featur: USB - Add device tracking, stall recovery, removal, and terminal command
- Track enumerated devices per-HC via linked list (hc^.Devices)
- Add usb_clear_halt() for endpoint stall recovery (CLEAR_FEATURE)
- Add usb_remove_device() to clean up and free device records
- Add get_hc() for indexed host controller access
- Implement 'USB' terminal command showing HC info, connected devices,
  speeds, class descriptors, and endpoint details
2026-03-02 15:50:55 +00:00
t3hn3rd db49c29627 fix: lowercase names for units
- PCI.pas -> pci.pas
2026-03-02 13:38:10 +00:00
t3hn3rd c237553508 fix: ps2_keyboard report key-up events for break codes
The PS/2 keyboard callback hardcoded is_down_code := true for every
scancode, so key releases were never reported. This caused keys to
repeat endlessly until the next key was pressed.

In PS/2 scancode set 1, bit 7 indicates a break (release) code.
The callback now:
- Detects break codes via (scancode AND $80)
- Masks to base code (scancode AND $7F) for key matrix lookup
- Sets is_down_code := false for break codes
- Updates modifier state (shift/ctrl/alt) before building the
  key event, so modifier releases take effect immediately

Files changed:
- ps2_keyboard.pas: rewrite callback to handle make/break codes
2026-03-02 13:37:29 +00:00
t3hn3rd 0c96d32754 feature: move all USB HC drivers from polling to interrupt-driven completion
Replace main-loop polling (poll_all, poll_keyboards, poll_mice) with
hardware interrupt handlers for all four USB host controller drivers.

Each HC driver (XHCI, EHCI, OHCI, UHCI) now:
- Registers an ISR on its PCI interrupt line via isrmanager
- Enables hardware interrupts after HC initialization
- Acknowledges interrupt status in the ISR before calling poll,
  preventing interrupt storms on level-triggered PCI lines
- Uses a PollBusy re-entrancy guard to prevent ISR/inline poll races

usbcore gains a completion hook system (register_completion_hook /
fire_completion_hooks) so HID drivers (keyboard, mouse) are notified
directly from the ISR after transfer completion.

Files changed:
- usbcore.pas: completion hook infrastructure
- XHCI.pas: ISR, enable_interrupts, submit ordering fix
- EHCI.pas: ISR, enable_interrupts, status ack in ISR
- OHCI.pas: ISR, enable_interrupts, status ack in ISR
- UHCI.pas: ISR, enable_interrupts, status ack in ISR
- usb_keyboard.pas: register completion hook
- usb_mouse.pas: register completion hook
2026-03-02 13:36:40 +00:00
t3hn3rd 3f83f279d7 XHCI driver implementation
- Beginnings of a functional XHCI driver implemented.
2026-03-02 12:24:02 +00:00
t3hn3rd 82fe9fa6df EHCI Implementation
- Beginnings of a functional EHCI driver implemented.
2026-03-02 12:23:35 +00:00
admin 983d9a428d Merge pull request 'feature: Tracer O(1) ring buffer refactor' (#12) from feature/tracer-optimizations into develop
continuous-integration/drone/push Build is passing
Reviewed-on: #12
2026-03-01 22:29:53 +00:00
t3hn3rd 2fa77d8295 Merge branch 'feature/tracer-optimizations' into feature/USB 2026-03-01 21:26:56 +00:00
t3hn3rd f53afc1d2d feature: Tracer O(1) ring buffer refactor
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
- Replaced O(n) shift loop + StringCopy/kalloc/kfree with O(1) ring
  buffer storing PChar pointers directly (zero allocation).
- Eliminated mod operator (causes int64 promotion + broken RTL helpers
  on i386 bare-metal); uses pure uint32 branch arithmetic.
- Removed dead code: PTracerEntry/TTracerEntry linked list types,
  head/tail PTracerEntry vars, c_lock boolean
- Dropped lmemorymanager and serial from uses clause
- pop_trace remains as no-op stub for ABI compat
- get_trace_N uses underflow-safe index: if head >= idx then
  head - idx else MAX_TRACE - (idx - head)
- Added print_traces debug helper
2026-03-01 21:26:35 +00:00
32 changed files with 8328 additions and 220 deletions

No files matched your search

+8 -1
View File
@@ -1 +1,8 @@
* text=auto eol=lf * text=auto eol=lf
lvglh/** linguist-vendored
lvgl/** linguist-vendored
.vscode/* linguist-vendored
lib/* linguist-generated
release/* linguist-generated
iso/* linguist-generated
*.asm linguist-detectable
+1
View File
@@ -15,3 +15,4 @@ localenv.json
dockerout.txt dockerout.txt
AGENTS.md AGENTS.md
*.log *.log
/doc/*.md
+1 -1
View File
@@ -4,4 +4,4 @@ echo "======================="
echo " " echo " "
echo "Compiling FPC Sources..." echo "Compiling FPC Sources..."
echo " " echo " "
fpc -Aelf -gw -g -gl -n -v0ew -O3 -OpPENTIUM3 -Si -Sc -Sg -Xd -CX -XXs -CfSSE -CfSSE2 -Rintel -Pi386 -Tlinux -FElib/ -Fusrc/* -Fusrc/driver/* -Fusrc/driver/net/* -Fusrc/driver/bus/* -Fusrc/driver/bus/usb/* -Fusrc/driver/hid/* src/kernel.pas fpc -Aelf -gw -g -gl -n -v0ew -O3 -OpPENTIUM3 -Si -Sc -Sg -Xd -CX -XXs -CfSSE -CfSSE2 -Rintel -Pi386 -Tlinux -FElib/ -Fusrc/* -Fusrc/include/* -Fusrc/driver/* -Fusrc/driver/net/* -Fusrc/driver/bus/* -Fusrc/driver/bus/usb/* -Fusrc/driver/hid/* src/kernel.pas
View File
Whitespace-only changes.
+1 -1
View File
@@ -18,7 +18,7 @@
@author(Aaron Hance <[email protected]>) @author(Aaron Hance <[email protected]>)
@author(Kieron Morris <[email protected]>) @author(Kieron Morris <[email protected]>)
} }
unit PCI; unit pci;
interface interface
File diff suppressed because it is too large. Load diff
+82 -4
View File
@@ -7,7 +7,7 @@
@author(Kieron Morris <[email protected]>) @author(Kieron Morris <[email protected]>)
} }
unit OHCI; unit ohci;
interface interface
@@ -23,6 +23,7 @@ uses
drivermanagement, drivermanagement,
usbtypes, usbtypes,
usbcore, usbcore,
isrmanager,
lists, lists,
strings; strings;
@@ -234,6 +235,7 @@ type
EDBulk : POHCI_ED; { Head of bulk ED list } EDBulk : POHCI_ED; { Head of bulk ED list }
EDInterrupt : POHCI_ED; { Dummy head for interrupt ED list } EDInterrupt : POHCI_ED; { Dummy head for interrupt ED list }
NumPorts : uint8; { Number of downstream ports } NumPorts : uint8; { Number of downstream ports }
PollBusy : boolean; { Re-entrancy guard for poll }
PCIBus : uint8; { PCI address } PCIBus : uint8; { PCI address }
PCISlot : uint8; PCISlot : uint8;
PCIFunc : uint8; PCIFunc : uint8;
@@ -1022,6 +1024,60 @@ begin
end; end;
end; end;
{ ========================= Interrupt-Driven Completion ========================= }
const
OHCI_MAX_INSTANCES = 4;
var
OHCIInstances : array[0..OHCI_MAX_INSTANCES-1] of PUSBHCDriver;
OHCIInstanceCount : uint32;
{ ISR handler — registered on the PCI interrupt line. }
procedure ohci_isr;
var
i : uint32;
hc : PUSBHCDriver;
priv : POHCI_PrivData;
intSts : uint32;
begin
for i := 0 to OHCIInstanceCount - 1 do begin
hc := OHCIInstances[i];
if hc = nil then continue;
priv := POHCI_PrivData(hc^.PrivData);
if priv = nil then continue;
{ Check if this controller has pending interrupt status }
intSts := ohci_read(priv^.MMIOBase, OHCI_REG_INTSTATUS);
if intSts = 0 then continue;
{ Acknowledge interrupt status NOW to de-assert level-triggered PCI line.
Must happen before ohci_poll, because PollBusy guard may skip the
acknowledge inside poll — leaving the line asserted = interrupt storm. }
ohci_write(priv^.MMIOBase, OHCI_REG_INTSTATUS, intSts);
{ Process completions (walks ED lists) }
ohci_poll(hc);
{ Hotplug: if RootHubStatusChange, flag for deferred processing }
if ((intSts AND OHCI_INT_RHSC) <> 0) and hc^.HotplugArmed then
hc^.PortChangePending := true;
end;
usbcore.fire_completion_hooks;
end;
{ Enable hardware interrupts: WritebackDoneHead, RootHubStatusChange, UnrecoverableError + MIE. }
procedure ohci_enable_interrupts(hc : PUSBHCDriver);
var
priv : POHCI_PrivData;
begin
if (hc = nil) or (hc^.PrivData = nil) then exit;
priv := POHCI_PrivData(hc^.PrivData);
ohci_write(priv^.MMIOBase, OHCI_REG_INTENABLE,
OHCI_INT_WDH OR OHCI_INT_RHSC OR OHCI_INT_UE OR OHCI_INT_MIE);
syslog.logln('OHCI', 'Hardware interrupts enabled.');
end;
procedure ohci_poll(hc : PUSBHCDriver); procedure ohci_poll(hc : PUSBHCDriver);
var var
priv : POHCI_PrivData; priv : POHCI_PrivData;
@@ -1038,6 +1094,11 @@ var
begin begin
if (hc = nil) or (hc^.PrivData = nil) then exit; if (hc = nil) or (hc^.PrivData = nil) then exit;
priv := POHCI_PrivData(hc^.PrivData); priv := POHCI_PrivData(hc^.PrivData);
{ Re-entrancy guard }
if priv^.PollBusy then exit;
priv^.PollBusy := true;
base := priv^.MMIOBase; base := priv^.MMIOBase;
{ Read and acknowledge interrupt status } { Read and acknowledge interrupt status }
@@ -1107,6 +1168,7 @@ begin
ed := nextED; ed := nextED;
end; end;
end; end;
priv^.PollBusy := false;
end; end;
{ ========================= Load / Init ========================= } { ========================= Load / Init ========================= }
@@ -1124,6 +1186,7 @@ var
begin begin
push_trace('OHCI.load'); push_trace('OHCI.load');
load := false; load := false;
OHCIInstanceCount := 0;
devices := PCI.getDeviceInfo($0C, $03, $10, count); devices := PCI.getDeviceInfo($0C, $03, $10, count);
syslog.log('OHCI', 'Found '); syslog.log('OHCI', 'Found ');
@@ -1220,9 +1283,24 @@ begin
hcEntry := usbcore.register_hc(@hc); hcEntry := usbcore.register_hc(@hc);
{ Scan ports for connected devices (use the stable pointer, not stack-local @hc) } { Scan ports for connected devices (use the stable pointer, not stack-local @hc) }
if hcEntry <> nil then if hcEntry <> nil then begin
usbcore.scan_ports(hcEntry) { Track instance for ISR dispatch }
else if OHCIInstanceCount < OHCI_MAX_INSTANCES then begin
OHCIInstances[OHCIInstanceCount] := hcEntry;
inc(OHCIInstanceCount);
end;
{ Register ISR on PCI interrupt line }
syslog.log('OHCI', 'Registering ISR on IRQ ');
syslog.writeintln(devices[i].interrupt_line);
isrmanager.registerISR(32 + devices[i].interrupt_line, @ohci_isr);
{ Enable hardware interrupts }
ohci_enable_interrupts(hcEntry);
{ Scan for connected devices }
usbcore.scan_ports(hcEntry);
end else
syslog.logln('OHCI', 'Failed to register HC with USB core.'); syslog.logln('OHCI', 'Failed to register HC with USB core.');
syslog.logln('OHCI', 'Controller initialized and registered.'); syslog.logln('OHCI', 'Controller initialized and registered.');
+77 -4
View File
@@ -6,7 +6,7 @@
@author(Kieron Morris <[email protected]>) @author(Kieron Morris <[email protected]>)
} }
unit UHCI; unit uhci;
interface interface
@@ -22,6 +22,7 @@ uses
drivermanagement, drivermanagement,
usbtypes, usbtypes,
usbcore, usbcore,
isrmanager,
lists, lists,
strings; strings;
@@ -154,6 +155,7 @@ type
QHControl : PUHCI_QH; { Queue Head for control transfers } QHControl : PUHCI_QH; { Queue Head for control transfers }
QHBulk : PUHCI_QH; { Queue Head for bulk transfers } QHBulk : PUHCI_QH; { Queue Head for bulk transfers }
QHInterrupt : PUHCI_QH; { Queue Head for interrupt transfers } QHInterrupt : PUHCI_QH; { Queue Head for interrupt transfers }
PollBusy : boolean; { Re-entrancy guard for poll }
PCIBus : uint8; { PCI bus/slot/func for bus mastering } PCIBus : uint8; { PCI bus/slot/func for bus mastering }
PCISlot : uint8; PCISlot : uint8;
PCIFunc : uint8; PCIFunc : uint8;
@@ -750,6 +752,56 @@ begin
pop_trace; pop_trace;
end; end;
{ ========================= Interrupt-Driven Completion ========================= }
const
UHCI_MAX_INSTANCES = 4;
var
UHCIInstances : array[0..UHCI_MAX_INSTANCES-1] of PUSBHCDriver;
UHCIInstanceCount : uint32;
{ ISR handler — registered on the PCI interrupt line. }
procedure uhci_isr;
var
i : uint32;
hc : PUSBHCDriver;
priv : PUHCI_PrivData;
status : uint16;
begin
for i := 0 to UHCIInstanceCount - 1 do begin
hc := UHCIInstances[i];
if hc = nil then continue;
priv := PUHCI_PrivData(hc^.PrivData);
if priv = nil then continue;
{ Check if this controller has pending interrupt status }
status := uhci_read16(priv^.IOBase, UHCI_REG_USBSTS);
if (status AND (UHCI_STS_USBINT OR UHCI_STS_ERROR)) = 0 then continue;
{ Acknowledge interrupt status NOW to de-assert level-triggered PCI line.
Must happen before uhci_poll, because PollBusy guard may skip the
acknowledge inside poll — leaving the line asserted = interrupt storm. }
uhci_write16(priv^.IOBase, UHCI_REG_USBSTS, status AND (UHCI_STS_USBINT OR UHCI_STS_ERROR));
{ Process completions (walks QH/TD chains) }
uhci_poll(hc);
end;
usbcore.fire_completion_hooks;
end;
{ Enable hardware interrupts: Interrupt-on-Complete, Short Packet, Timeout/CRC. }
procedure uhci_enable_interrupts(hc : PUSBHCDriver);
var
priv : PUHCI_PrivData;
begin
if (hc = nil) or (hc^.PrivData = nil) then exit;
priv := PUHCI_PrivData(hc^.PrivData);
uhci_write16(priv^.IOBase, UHCI_REG_USBINTR,
UHCI_INTR_IOC OR UHCI_INTR_SP OR UHCI_INTR_TIMEOUT);
syslog.logln('UHCI', 'Hardware interrupts enabled.');
end;
{ ========================= Poll / Completion ========================= } { ========================= Poll / Completion ========================= }
procedure uhci_poll(hc : PUSBHCDriver); procedure uhci_poll(hc : PUSBHCDriver);
@@ -768,6 +820,10 @@ begin
if (hc = nil) or (hc^.PrivData = nil) then exit; if (hc = nil) or (hc^.PrivData = nil) then exit;
priv := PUHCI_PrivData(hc^.PrivData); priv := PUHCI_PrivData(hc^.PrivData);
{ Re-entrancy guard }
if priv^.PollBusy then exit;
priv^.PollBusy := true;
{ Read and clear status register } { Read and clear status register }
status := uhci_read16(priv^.IOBase, UHCI_REG_USBSTS); status := uhci_read16(priv^.IOBase, UHCI_REG_USBSTS);
if (status AND (UHCI_STS_USBINT OR UHCI_STS_ERROR)) <> 0 then if (status AND (UHCI_STS_USBINT OR UHCI_STS_ERROR)) <> 0 then
@@ -841,6 +897,7 @@ begin
end; end;
qh := qh^.SWNext; qh := qh^.SWNext;
end; end;
priv^.PollBusy := false;
end; end;
{ ========================= Load / Init ========================= } { ========================= Load / Init ========================= }
@@ -857,6 +914,7 @@ var
begin begin
push_trace('UHCI.load'); push_trace('UHCI.load');
load := false; load := false;
UHCIInstanceCount := 0;
devices := PCI.getDeviceInfo($0C, $03, $00, count); devices := PCI.getDeviceInfo($0C, $03, $00, count);
syslog.log('UHCI', 'Found '); syslog.log('UHCI', 'Found ');
@@ -945,9 +1003,24 @@ begin
hcEntry := usbcore.register_hc(@hc); hcEntry := usbcore.register_hc(@hc);
{ Scan ports for connected devices (use the stable pointer, not stack-local @hc) } { Scan ports for connected devices (use the stable pointer, not stack-local @hc) }
if hcEntry <> nil then if hcEntry <> nil then begin
usbcore.scan_ports(hcEntry) { Track instance for ISR dispatch }
else if UHCIInstanceCount < UHCI_MAX_INSTANCES then begin
UHCIInstances[UHCIInstanceCount] := hcEntry;
inc(UHCIInstanceCount);
end;
{ Register ISR on PCI interrupt line }
syslog.log('UHCI', 'Registering ISR on IRQ ');
syslog.writeintln(devices[i].interrupt_line);
isrmanager.registerISR(32 + devices[i].interrupt_line, @uhci_isr);
{ Enable hardware interrupts }
uhci_enable_interrupts(hcEntry);
{ Scan for connected devices }
usbcore.scan_ports(hcEntry);
end else
syslog.logln('UHCI', 'Failed to register HC with USB core.'); syslog.logln('UHCI', 'Failed to register HC with USB core.');
syslog.logln('UHCI', 'Controller initialized and registered.'); syslog.logln('UHCI', 'Controller initialized and registered.');
+5 -1
View File
@@ -17,7 +17,7 @@
@author(Kieron Morris <[email protected]>) @author(Kieron Morris <[email protected]>)
} }
unit USB; unit usb;
interface interface
@@ -35,6 +35,7 @@ uses
usbhub, usbhub,
usb_keyboard, usb_keyboard,
usb_mouse, usb_mouse,
usb_storage,
OHCI, UHCI, EHCI, XHCI; OHCI, UHCI, EHCI, XHCI;
procedure init; procedure init;
@@ -89,6 +90,9 @@ begin
{ Initialize HID class drivers } { Initialize HID class drivers }
usb_keyboard.init; usb_keyboard.init;
usb_mouse.init; usb_mouse.init;
{ Initialize storage class driver }
usb_storage.init;
UHCI_ID.Bus:= biPCI; UHCI_ID.Bus:= biPCI;
UHCI_ID.id0:= idANY; UHCI_ID.id0:= idANY;
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+6
View File
@@ -217,6 +217,9 @@ type
PUSBHCDriver = ^TUSBHCDriver; PUSBHCDriver = ^TUSBHCDriver;
PUSBTransfer = ^TUSBTransfer; PUSBTransfer = ^TUSBTransfer;
{ ---- Disconnect Callback ---- }
TUSBDisconnectCallback = procedure(dev : PUSBDevice);
{ ---- Transfer Request ---- } { ---- Transfer Request ---- }
TUSBTransfer = record TUSBTransfer = record
@@ -246,6 +249,7 @@ type
Endpoints : array[0..USB_MAX_ENDPOINTS-1] of TUSBEndpoint; Endpoints : array[0..USB_MAX_ENDPOINTS-1] of TUSBEndpoint;
NumEndpoints : uint8; NumEndpoints : uint8;
Configured : boolean; Configured : boolean;
fnDisconnect : TUSBDisconnectCallback; { Called before device is freed on unplug }
end; end;
{ ---- HC Driver Abstraction (Function Pointer Types) ---- } { ---- HC Driver Abstraction (Function Pointer Types) ---- }
@@ -269,6 +273,8 @@ type
PrivData : Pointer; { HC-specific state } PrivData : Pointer; { HC-specific state }
Devices : PLinkedListBase; { List of PUSBDevice attached } Devices : PLinkedListBase; { List of PUSBDevice attached }
NextAddress : uint8; { Next available USB address (1-127) } NextAddress : uint8; { Next available USB address (1-127) }
PortChangePending : boolean; { Set by ISR when port status changes; processed in deferred context }
HotplugArmed : boolean; { False during boot; set true after initial scan_ports to ignore spurious RHSC }
{ Operations } { Operations }
fnReset : TUSBHCReset; fnReset : TUSBHCReset;
fnStart : TUSBHCStart; fnStart : TUSBHCStart;
+26 -17
View File
@@ -32,32 +32,41 @@ uses
procedure callback(scan_code : void); procedure callback(scan_code : void);
var var
info : TKeyInfo; info : TKeyInfo;
raw : uint8;
baseCode : uint8;
isBreak : boolean;
begin begin
info.SHIFT_DOWN := keyboard.is_shift; raw := uint8(scan_code);
info.CTRL_DOWN := keyboard.is_ctrl;
info.ALT_DOWN := keyboard.is_alt; { In PS/2 scancode set 1, bit 7 set = key release (break code) }
info.is_down_code := true; isBreak := (raw AND $80) <> 0;
baseCode := raw AND $7F;
{ Update modifier state (use raw codes so both make/break are handled) }
if raw = 42 then keyboard.is_shift := true;
if raw = 170 then keyboard.is_shift := false;
if raw = 29 then keyboard.is_ctrl := true;
if raw = 157 then keyboard.is_ctrl := false;
if raw = 56 then keyboard.is_alt := true;
if raw = 184 then keyboard.is_alt := false;
info.SHIFT_DOWN := keyboard.is_shift;
info.CTRL_DOWN := keyboard.is_ctrl;
info.ALT_DOWN := keyboard.is_alt;
info.is_down_code := not isBreak;
if keyboard.is_shift then begin if keyboard.is_shift then begin
if key_matrix_shift[uint8(scan_code)].key_code <> 0 then begin if key_matrix_shift[baseCode].key_code <> 0 then begin
info.key_code := key_matrix_shift[uint8(scan_code)].key_code; info.key_code := key_matrix_shift[baseCode].key_code;
keyboard.reportKeyEvent(info); keyboard.reportKeyEvent(info);
end; end;
end else begin end else begin
if key_matrix[uint8(scan_code)].key_code <> 0 then begin if key_matrix[baseCode].key_code <> 0 then begin
info.key_code := key_matrix[uint8(scan_code)].key_code; info.key_code := key_matrix[baseCode].key_code;
keyboard.reportKeyEvent(info); keyboard.reportKeyEvent(info);
end; end;
end; end;
{ Update modifier state }
if uint8(scan_code) = 42 then keyboard.is_shift := true;
if uint8(scan_code) = 170 then keyboard.is_shift := false;
if uint8(scan_code) = 29 then keyboard.is_ctrl := true;
if uint8(scan_code) = 157 then keyboard.is_ctrl := false;
if uint8(scan_code) = 56 then keyboard.is_alt := true;
if uint8(scan_code) = 184 then keyboard.is_alt := false;
end; end;
function load(ptr : void) : boolean; function load(ptr : void) : boolean;
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+52
View File
@@ -0,0 +1,52 @@
{
Driver->Timer->GraphicsRefresh - Timer-driven graphics refresh at ~120FPS.
Hooks into the 1024Hz timer (TMR_0_ISR) and calls the desktop, uidebug,
LVGL and video flush routines every ~9 ticks (1024/9 ≈ 113.8 FPS).
@author(Kieron Morris <[email protected]>)
}
unit graphicsrefresh;
interface
procedure init;
implementation
uses
util,
TMR_0_ISR,
desktop,
uidebug,
lvgl,
video,
syslog;
const
{ 1024 / 4 ≈ 256 FPS }
TICKS_PER_FRAME = 4;
var
TickCounter : uint32;
procedure on_tick(data : void);
begin
TickCounter := TickCounter + 1;
if TickCounter >= TICKS_PER_FRAME then begin
TickCounter := 0;
desktop.update;
uidebug.update;
lvgl_handler;
video.Flush;
end;
end;
procedure init;
begin
TickCounter := 0;
TMR_0_ISR.hook(uint32(@on_tick));
syslog.logln('GFXREFRESH', 'Hooked into 1024Hz timer (~120 FPS).');
end;
end.
+46
View File
@@ -0,0 +1,46 @@
{
Driver->Timer->USBHotplug - Timer-driven USB hotplug polling at ~1Hz.
Hooks into the 1024Hz timer (TMR_0_ISR) and calls
usbcore.usb_check_hotplug every 1024 ticks (approximately once per second).
@author(Kieron Morris <[email protected]>)
}
unit usbhotplug;
interface
procedure init;
implementation
uses
util,
TMR_0_ISR,
usbcore,
syslog;
const
{ 1024 ticks at 1024Hz ≈ 1 second }
TICKS_PER_POLL = 1024;
var
TickCounter : uint32;
procedure on_tick(data : void);
begin
TickCounter := TickCounter + 1;
if TickCounter >= TICKS_PER_POLL then begin
TickCounter := 0;
usbcore.usb_check_hotplug;
end;
end;
procedure init;
begin
TickCounter := 0;
TMR_0_ISR.hook(uint32(@on_tick));
syslog.logln('USBHOTPLUG', 'Hooked into 1024Hz timer (~1Hz polling).');
end;
end.
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
Loaded 20 of 32 files, more files were not shown because too many files have changed in this diff. Show more