USB Stack & HID Refactor
- New units: usbtypes, usbcore, usbhub, UHCI, OHCI, usb_keyboard, usb_mouse - usbtypes: shared USB descriptors, constants, HC abstraction, aligned alloc, unit tests - usb_keyboard: USB HID boot keyboard driver with HID-to-ASCII translation, polling, unit tests - usb_mouse: USB HID boot mouse driver with delta/scroll/button processing, polling, unit tests HID Layer Restructure: - keyboard.pas: stripped to abstract API (hook + reportKeyEvent), no PS/2 dependency - mouse.pas: absorbed mousestate.pas, now owns position/buttons/scroll/hooks directly - mousestate.pas: deleted (merged into mouse.pas) - New ps2_keyboard.pas: PS/2 scan code translation, calls keyboard.reportKeyEvent - New ps2_mouse.pas: PS/2 packet handling, calls mouse.setMousePos/fireMouseEvent LVGL Integration: - lvgl.pas: updated to use mouse.pas directly (was mousestate), improved keyboard input handling with proper key held/release tracking - vterminal.pas: removed serial debug logging, dropped serial dependency Kernel: - kernel.pas: added USB units, USB polling in main loop, unit test calls, ps2_keyboard/ps2_mouse init
This commit is contained in:
+1
-1
@@ -4,4 +4,4 @@ echo "======================="
|
||||
echo " "
|
||||
echo "Compiling FPC Sources..."
|
||||
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/* 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/driver/* -Fusrc/driver/net/* -Fusrc/driver/bus/* -Fusrc/driver/bus/usb/* -Fusrc/driver/hid/* src/kernel.pas
|
||||
@@ -1,96 +0,0 @@
|
||||
// Copyright 2021 Kieron Morris
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
{
|
||||
Driver->Bus->OHCI - Open Host Controller Interface Driver.
|
||||
|
||||
@author(Kieron Morris <[email protected]>)
|
||||
}
|
||||
unit OHCI;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
tracer,
|
||||
syslog,
|
||||
PCI,
|
||||
drivertypes,
|
||||
pmemorymanager,
|
||||
vmemorymanager,
|
||||
util,
|
||||
drivermanagement;
|
||||
|
||||
type
|
||||
POHCI_MMR = ^TOHCI_MMR;
|
||||
TOHCI_MMR = packed record
|
||||
HcRevision : uint32;
|
||||
HcControl : uint32;
|
||||
HcCommandStatus : uint32;
|
||||
HcIntStatus : uint32;
|
||||
HcIntEnable : uint32;
|
||||
HcIntDisable : uint32;
|
||||
HcHCCA : uint32;
|
||||
HcPeriodCurrentED : uint32;
|
||||
HcControlHeadED : uint32;
|
||||
HcControlCurrentED : uint32;
|
||||
HcBulkHeadED : uint32;
|
||||
HcBulkCurrentED : uint32;
|
||||
HcDoneHead : uint32;
|
||||
HcFmRemaining : uint32;
|
||||
HcFmNumber : uint32;
|
||||
HcPeriodicStart : uint32;
|
||||
HcLSThreshold : uint32;
|
||||
HcRhDescriptorA : uint32;
|
||||
HcRhDescriptorB : uint32;
|
||||
HcRhStatus : uint32;
|
||||
end;
|
||||
|
||||
function load : boolean;
|
||||
|
||||
implementation
|
||||
|
||||
function load : boolean;
|
||||
var
|
||||
devices : TDeviceArray;
|
||||
count : uint32;
|
||||
i : uint32;
|
||||
block : uint32;
|
||||
MMR : POHCI_MMR;
|
||||
|
||||
begin
|
||||
tracer.push_trace('OHCI.load');
|
||||
devices:= PCI.getDeviceInfo($0C, $03, $10, count);
|
||||
syslog.log('USB-OHCI Driver', 'Found ');
|
||||
syslog.writeint(count);
|
||||
syslog.writestringln(' USB Controller(s).');
|
||||
if count > 0 then begin
|
||||
for i:=0 to count-1 do begin
|
||||
syslog.log('USB-OHCI Driver', 'Controller[');
|
||||
syslog.writeint(i);
|
||||
syslog.writestring(']: ');
|
||||
syslog.writehex(devices[i].device_id);
|
||||
syslog.writestring(' ');
|
||||
syslog.writehex(devices[i].vendor_id);
|
||||
syslog.writestring(' ');
|
||||
syslog.writehexln(devices[i].prog_if);
|
||||
block:= devices[i].address0 SHR 22;
|
||||
force_alloc_block(block, 0);
|
||||
map_page(block, block);
|
||||
MMR:= POHCI_MMR(devices[i].address0);
|
||||
end;
|
||||
end;
|
||||
load:= true;
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -1,65 +0,0 @@
|
||||
// Copyright 2021 Kieron Morris
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
{
|
||||
Driver->Bus->UHCI - Universal Host Controller Interface Driver.
|
||||
|
||||
@author(Kieron Morris <[email protected]>)
|
||||
}
|
||||
unit UHCI;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
tracer,
|
||||
syslog,
|
||||
PCI,
|
||||
drivertypes,
|
||||
pmemorymanager,
|
||||
vmemorymanager,
|
||||
util,
|
||||
drivermanagement;
|
||||
|
||||
function load : boolean;
|
||||
|
||||
implementation
|
||||
|
||||
function load : boolean;
|
||||
var
|
||||
devices : TDeviceArray;
|
||||
count : uint32;
|
||||
i : uint32;
|
||||
|
||||
begin
|
||||
tracer.push_trace('UHCI.load');
|
||||
devices:= PCI.getDeviceInfo($0C, $03, $00, count);
|
||||
syslog.log('USB-UHCI Driver','Found ');
|
||||
syslog.writeint(count);
|
||||
syslog.writestringln(' USB Controller(s).');
|
||||
if count > 0 then begin
|
||||
for i:=0 to count-1 do begin
|
||||
syslog.log('USB-UHCI Driver','Controller[');
|
||||
syslog.writeint(i);
|
||||
syslog.writestring(']: ');
|
||||
syslog.writehex(devices[i].device_id);
|
||||
syslog.writestring(' ');
|
||||
syslog.writehex(devices[i].vendor_id);
|
||||
syslog.writestring(' ');
|
||||
syslog.writehexln(devices[i].prog_if);
|
||||
end;
|
||||
end;
|
||||
load:= true;
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -29,7 +29,8 @@ uses
|
||||
pmemorymanager,
|
||||
vmemorymanager,
|
||||
util,
|
||||
drivermanagement;
|
||||
drivermanagement,
|
||||
usbtypes;
|
||||
|
||||
function load : boolean;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -30,6 +30,11 @@ uses
|
||||
vmemorymanager,
|
||||
util,
|
||||
drivermanagement,
|
||||
usbtypes,
|
||||
usbcore,
|
||||
usbhub,
|
||||
usb_keyboard,
|
||||
usb_mouse,
|
||||
OHCI, UHCI, EHCI, XHCI;
|
||||
|
||||
procedure init;
|
||||
@@ -40,24 +45,28 @@ function loadXHCI(ptr : void) : boolean;
|
||||
begin
|
||||
push_trace('USB.loadXHCI');
|
||||
loadXHCI:= XHCI.load;
|
||||
pop_trace;
|
||||
end;
|
||||
|
||||
function loadEHCI(ptr : void) : boolean;
|
||||
begin
|
||||
push_trace('USB.loadEHCI');
|
||||
loadEHCI:= EHCI.load;
|
||||
pop_trace;
|
||||
end;
|
||||
|
||||
function loadOHCI(ptr : void) : boolean;
|
||||
begin
|
||||
push_trace('USB.loadOHCI');
|
||||
loadOHCI:= OHCI.load;
|
||||
pop_trace;
|
||||
end;
|
||||
|
||||
function loadUHCI(ptr : void) : boolean;
|
||||
begin
|
||||
push_trace('USB.loadUHCI');
|
||||
loadUHCI:= UHCI.load;
|
||||
pop_trace;
|
||||
end;
|
||||
|
||||
procedure init;
|
||||
@@ -70,6 +79,16 @@ var
|
||||
begin
|
||||
push_trace('USB.init');
|
||||
syslog.logln('USB Driver', 'INIT BEGIN.');
|
||||
|
||||
{ Initialize USB core (HC list, etc.) }
|
||||
usbcore.init;
|
||||
|
||||
{ Initialize hub driver (registers class driver for $09) }
|
||||
usbhub.init;
|
||||
|
||||
{ Initialize HID class drivers }
|
||||
usb_keyboard.init;
|
||||
usb_mouse.init;
|
||||
|
||||
UHCI_ID.Bus:= biPCI;
|
||||
UHCI_ID.id0:= idANY;
|
||||
@@ -29,7 +29,8 @@ uses
|
||||
pmemorymanager,
|
||||
vmemorymanager,
|
||||
util,
|
||||
drivermanagement;
|
||||
drivermanagement,
|
||||
usbtypes;
|
||||
|
||||
function load : 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
+29
-340
File diff suppressed because it is too large
Load Diff
+108
-309
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
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
+46
-34
@@ -13,7 +13,7 @@ interface
|
||||
|
||||
uses
|
||||
video, videotypes, color, serial, tracer, lmemorymanager,
|
||||
mousestate, keyboard, TMR_0_ISR, util;
|
||||
mouse, keyboard, TMR_0_ISR, util;
|
||||
|
||||
{ ============================================================
|
||||
Opaque LVGL pointer types (internal C structs)
|
||||
@@ -1719,10 +1719,11 @@ var
|
||||
|
||||
{ Keyboard ring buffer for LVGL }
|
||||
kb_buf : array[0..15] of uint32;
|
||||
kb_head : uint32; { next write slot (ISR side) }
|
||||
kb_head : uint32; { next write slot (hook side) }
|
||||
kb_tail : uint32; { next read slot (LVGL poll side) }
|
||||
last_key : uint32; { last key delivered, for release event }
|
||||
kb_pending_release : boolean; { true = must send RELEASED before next key }
|
||||
kb_current_key : uint32; { key currently reported as pressed to LVGL, 0 = none }
|
||||
kb_key_held : boolean; { true while physical key is down }
|
||||
kb_held_code : uint32; { the LVGL key code of the held key }
|
||||
|
||||
const
|
||||
KB_BUF_SIZE = 16;
|
||||
@@ -1805,9 +1806,9 @@ end;
|
||||
============================================================ }
|
||||
procedure lvgl_mouse_read_cb(indev: Plv_indev; data: Plv_indev_data); cdecl;
|
||||
begin
|
||||
data^.point.x := mousestate.getMouseX;
|
||||
data^.point.y := mousestate.getMouseY;
|
||||
if mousestate.getMouseLMB then
|
||||
data^.point.x := mouse.getMouseX;
|
||||
data^.point.y := mouse.getMouseY;
|
||||
if mouse.getMouseLMB then
|
||||
data^.state := LV_INDEV_STATE_PRESSED
|
||||
else
|
||||
data^.state := LV_INDEV_STATE_RELEASED;
|
||||
@@ -1818,28 +1819,29 @@ end;
|
||||
Keyboard read callback — LVGL polls this for key state
|
||||
============================================================ }
|
||||
procedure lvgl_kb_read_cb(indev: Plv_indev; data: Plv_indev_data); cdecl;
|
||||
var
|
||||
next_tail: uint32;
|
||||
begin
|
||||
if kb_pending_release then begin
|
||||
{ Send release for the previous key before consuming the next }
|
||||
data^.key := last_key;
|
||||
if (kb_current_key <> 0) and
|
||||
((not kb_key_held) or (kb_held_code <> kb_current_key) or (kb_tail <> kb_head)) then begin
|
||||
{ Release current key: physical key released, different key now held, or new keys queued }
|
||||
data^.key := kb_current_key;
|
||||
data^.state := LV_INDEV_STATE_RELEASED;
|
||||
kb_pending_release := false;
|
||||
{ If more keys are queued, tell LVGL to call us again }
|
||||
kb_current_key := 0;
|
||||
data^.continue_reading := (kb_tail <> kb_head);
|
||||
end else if kb_tail <> kb_head then begin
|
||||
{ Consume next key from ring buffer — send press }
|
||||
last_key := kb_buf[kb_tail];
|
||||
{ Consume next key from ring buffer — press }
|
||||
kb_current_key := kb_buf[kb_tail];
|
||||
kb_tail := (kb_tail + 1) mod KB_BUF_SIZE;
|
||||
data^.key := last_key;
|
||||
data^.key := kb_current_key;
|
||||
data^.state := LV_INDEV_STATE_PRESSED;
|
||||
kb_pending_release := true;
|
||||
{ Always call again to send the matching release }
|
||||
data^.continue_reading := true;
|
||||
data^.continue_reading := false; { one press per timer cycle for proper long-press timing }
|
||||
end else if (kb_current_key <> 0) and kb_key_held then begin
|
||||
{ Key still physically held — keep reporting pressed for LVGL long-press repeat }
|
||||
data^.key := kb_current_key;
|
||||
data^.state := LV_INDEV_STATE_PRESSED;
|
||||
data^.continue_reading := false;
|
||||
end else begin
|
||||
{ No pending keys — idle release }
|
||||
data^.key := last_key;
|
||||
{ Idle — no keys }
|
||||
data^.key := 0;
|
||||
data^.state := LV_INDEV_STATE_RELEASED;
|
||||
data^.continue_reading := false;
|
||||
end;
|
||||
@@ -1853,12 +1855,13 @@ var
|
||||
k: uint32;
|
||||
next_head: uint32;
|
||||
begin
|
||||
{ Ctrl+D toggles debug overlay }
|
||||
if key_info.CTRL_DOWN and (key_info.key_code = ord('d')) then begin
|
||||
{ Ctrl+D toggles debug overlay (press only) }
|
||||
if key_info.is_down_code and key_info.CTRL_DOWN and (key_info.key_code = ord('d')) then begin
|
||||
uidebug.toggle;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ Map Asuro key codes to LVGL key codes }
|
||||
case key_info.key_code of
|
||||
$1B: k := LV_KEY_ESC;
|
||||
$08: k := LV_KEY_BACKSPACE;
|
||||
@@ -1871,11 +1874,19 @@ begin
|
||||
else k := uint32(key_info.key_code);
|
||||
end;
|
||||
|
||||
{ Push into ring buffer (drop if full — better than corrupting) }
|
||||
next_head := (kb_head + 1) mod KB_BUF_SIZE;
|
||||
if next_head <> kb_tail then begin
|
||||
kb_buf[kb_head] := k;
|
||||
kb_head := next_head;
|
||||
if key_info.is_down_code then begin
|
||||
{ Key press — push into ring buffer and track held state }
|
||||
next_head := (kb_head + 1) mod KB_BUF_SIZE;
|
||||
if next_head <> kb_tail then begin
|
||||
kb_buf[kb_head] := k;
|
||||
kb_head := next_head;
|
||||
end;
|
||||
kb_key_held := true;
|
||||
kb_held_code := k;
|
||||
end else begin
|
||||
{ Key release — clear held state if it matches }
|
||||
if kb_key_held and (kb_held_code = k) then
|
||||
kb_key_held := false;
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -1895,10 +1906,11 @@ begin
|
||||
tracer.push_trace('lvgl.init.enter');
|
||||
|
||||
tick_accumulator := 0;
|
||||
last_key := 0;
|
||||
kb_head := 0;
|
||||
kb_tail := 0;
|
||||
kb_pending_release := false;
|
||||
kb_current_key := 0;
|
||||
kb_key_held := false;
|
||||
kb_held_code := 0;
|
||||
|
||||
{ Initialize LVGL core }
|
||||
lv_init;
|
||||
@@ -1957,10 +1969,10 @@ begin
|
||||
lv_tick_inc(elapsed);
|
||||
|
||||
{ Process scroll wheel }
|
||||
scroll_delta := mousestate.getMouseScroll;
|
||||
scroll_delta := mouse.getMouseScroll;
|
||||
if scroll_delta <> 0 then begin
|
||||
mx := mousestate.getMouseX;
|
||||
my := mousestate.getMouseY;
|
||||
mx := mouse.getMouseX;
|
||||
my := mouse.getMouseY;
|
||||
pt.x := mx;
|
||||
pt.y := my;
|
||||
target := lv_indev_search_obj(lv_screen_active, @pt);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user