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
This commit is contained in:
2026-03-02 15:52:49 +00:00
parent 25475a88a7
commit 7bbcc44c5e
9 changed files with 964 additions and 53 deletions
+4
View File
@@ -1355,6 +1355,10 @@ begin
{ Process completions (walks QH lists) }
ehci_poll(hc);
{ Hotplug: if Port Change Detect, flag for deferred processing }
if ((usbsts AND EHCI_STS_PCD) <> 0) and hc^.HotplugArmed then
hc^.PortChangePending := true;
end;
usbcore.fire_completion_hooks;
end;
+4
View File
@@ -1058,6 +1058,10 @@ begin
{ 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;
+4
View File
@@ -35,6 +35,7 @@ uses
usbhub,
usb_keyboard,
usb_mouse,
usb_storage,
OHCI, UHCI, EHCI, XHCI;
procedure init;
@@ -89,6 +90,9 @@ begin
{ Initialize HID class drivers }
usb_keyboard.init;
usb_mouse.init;
{ Initialize storage class driver }
usb_storage.init;
UHCI_ID.Bus:= biPCI;
UHCI_ID.id0:= idANY;
+14 -2
View File
@@ -1870,6 +1870,8 @@ var
pend : PXHCI_PendingTransfer;
transfer : PUSBTransfer;
processed : boolean;
hpPortId : uint8;
hpPortSC : uint32;
begin
if (hc = nil) or (hc^.PrivData = nil) then exit;
priv := PXHCI_PrivData(hc^.PrivData);
@@ -1924,9 +1926,19 @@ begin
end;
XHCI_TRB_PORT_STATUS_CHG: begin
{ Port ID in bits 31:24 of Param0 }
{ Port ID in bits 31:24 of Param0 (1-based) }
hpPortId := uint8((evt.Param0 SHR 24) AND $FF);
syslog.log('XHCI', 'Port Status Change: port ');
syslog.writeintln((evt.Param0 SHR 24) AND $FF);
syslog.writeintln(hpPortId);
if hpPortId > 0 then begin
{ Acknowledge port status change by writing W1C bits }
hpPortSC := xhci_readl(priv^.OpBase, XHCI_OP_PORTSC_BASE + ((hpPortId - 1) * $10));
xhci_writel(priv^.OpBase, XHCI_OP_PORTSC_BASE + ((hpPortId - 1) * $10),
(hpPortSC AND $0E00C3E0) OR $00FE0000);
{ Flag for deferred hotplug processing }
if hc^.HotplugArmed then
hc^.PortChangePending := true;
end;
end;
end;
end;
File diff suppressed because it is too large Load Diff
+6
View File
@@ -217,6 +217,9 @@ type
PUSBHCDriver = ^TUSBHCDriver;
PUSBTransfer = ^TUSBTransfer;
{ ---- Disconnect Callback ---- }
TUSBDisconnectCallback = procedure(dev : PUSBDevice);
{ ---- Transfer Request ---- }
TUSBTransfer = record
@@ -246,6 +249,7 @@ type
Endpoints : array[0..USB_MAX_ENDPOINTS-1] of TUSBEndpoint;
NumEndpoints : uint8;
Configured : boolean;
fnDisconnect : TUSBDisconnectCallback; { Called before device is freed on unplug }
end;
{ ---- HC Driver Abstraction (Function Pointer Types) ---- }
@@ -269,6 +273,8 @@ type
PrivData : Pointer; { HC-specific state }
Devices : PLinkedListBase; { List of PUSBDevice attached }
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 }
fnReset : TUSBHCReset;
fnStart : TUSBHCStart;
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