Artemis Milestone 2f: EP0 control transfer, device descriptor request

Adds Setup/Data/Status stage TRB types and control bits (IDT, TRT, DIR)
to xhci.h, and xhci_ep0_enqueue_trb()/xhci_ep0_get_device_descriptor() to
xhci.c -- the first real control transfer this driver has issued.
Follows the same enqueue-then-doorbell-once pattern as the Command Ring,
operating on the EP0 Transfer Ring built during 2e's Address Device work.
Setup Stage uses Immediate Data (parameter IS the 8-byte setup packet);
Data Stage reads into a reused 18-byte device_descriptor buffer; Status
Stage alone carries IOC, so exactly one Transfer Event signals transfer
completion, correlated via a new pending_transfer_slot_id (same
single-outstanding-operation pattern as connect/Enable Slot/Address
Device).

Automatically triggered once Address Device succeeds. Verified live via
QMP hotplug, all three architectures, worked first try with identical
results everywhere: idVendor=0x46f4, idProduct=0x0001, bDeviceClass=0x00
-- the class=0 confirms Mass Storage class detection needs the
Configuration/Interface descriptor (2f's next item), not the device
descriptor.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HZ8kNoTuP63pbQtro4qvrm
This commit is contained in:
Robert Allan James
2026-08-22 12:59:49 -04:00
co-authored by Claude Sonnet 5
parent 2e7e957680
commit 2c34e45d05
13 changed files with 36397 additions and 6 deletions
+31
View File
@@ -78,6 +78,16 @@ typedef struct {
xhci_trb_t *ep0_ring; /* EP0 Transfer Ring, XHCI_RING_TRB_COUNT TRBs */
uint32_t ep0_ring_cycle;
uint32_t ep0_ring_enq;
/* Milestone 2f: EP0 control transfers. Like connect_state, this
* driver only ever has one control transfer outstanding at a time --
* pending_transfer_slot_id is 0 when idle, else the slot ID whose
* Transfer Event (posted only by the Status Stage TRB, which alone
* has IOC set) is still outstanding. device_descriptor is the
* (reused, not per-slot) buffer control transfers read into; 18
* bytes is the full standard USB device descriptor size. */
uint32_t pending_transfer_slot_id;
uint8_t device_descriptor[18];
} xhci_dev_t;
/*
@@ -181,4 +191,25 @@ int xhci_cmd_enable_slot(xhci_dev_t *dev);
int xhci_cmd_address_device(xhci_dev_t *dev, uint32_t slot_id,
uint32_t port_id, uint32_t speed);
/*
* xhci_ep0_get_device_descriptor — issue a standard GET_DESCRIPTOR
* (Device) control transfer (Setup +
* Data-IN + Status-OUT stages) on
* slot_id's EP0, reading the 18-byte
* result into dev->device_descriptor.
* Does not wait for completion -- the
* result arrives asynchronously via
* xhci_poll_events()'s Transfer Event
* handling, which currently only logs
* success/failure (parsing the fields
* is the next increment).
*
* Called once Address Device succeeds -- not called directly by other
* code yet (Milestone 2f is still in progress).
*
* Returns 0 if the transfer was posted, -1 if dev/dev->ep0_ring is not
* set up.
*/
int xhci_ep0_get_device_descriptor(xhci_dev_t *dev, uint32_t slot_id);
#endif /* STARKERNEL_XHCI_DRIVER_H */