U-boot Issues with USB Keyboard

U-boot didn’t seem to like some endpoint halting on the ortholinear keyboard we’re working on - when any more than one keystroke was made (even on non-emitting keys), it would error out and reset with these error messages:

WARN halted endpoint, queueing URB anyway.
Unexpected XHCI event TRB, skipping... (3aef7cf0 00000000 13000000 03008400)
BUG at drivers/usb/host/xhci-ring.c:498/abort_td()!
BUG!
resetting ...

When I messed up my boot.scr while moving things to my nvme, this made it a little difficult to debug what was going on :slight_smile:

Thankfully, implementing this patch (with the printf removed) allows for full use of the keyboard, just like the OG one.

If anyone has any insight into the actual issue with the endpoints, maybe that’s something we could try to address in QMK - I do have things like the virtual serial interface, mouse keys, and console enabled, all of which add additional endpoints.

Here’s the patch I used that’s current with the reform’s u-boot fork - I’d create a merge request, but it looks like my account needs to be approved still :slight_smile:

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index b2cfd948f8..bd353aef3c 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -473,6 +473,35 @@ union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected)
 	BUG();
 }
 
+/*
+ * Issue reset endpoint command for an endpoint. This is required to recover
+ * a halted endpoint (e.g. due to a stall error).
+ * from https://github.com/agners/operating-system/blob/c3288801d7ff35c12d33d0e883dac246c4fc8a5a/buildroot-external/board/raspberrypi/patches/uboot/0005-usb-xhci-reset-endpoint-on-USB-stall.patch
+ */
+static void reset_ep(struct usb_device *udev, int ep_index)
+{
+	struct xhci_ctrl *ctrl = xhci_get_ctrl(udev);
+	struct xhci_ring *ring =  ctrl->devs[udev->slot_id]->eps[ep_index].ring;
+	union xhci_trb *event;
+	u32 field;
+
+    // bit hard to type with this notification
+	//printf("Resetting EP...\n");
+	xhci_queue_command(ctrl, NULL, udev->slot_id, ep_index, TRB_RESET_EP);
+	event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
+	field = le32_to_cpu(event->trans_event.flags);
+	BUG_ON(TRB_TO_SLOT_ID(field) != udev->slot_id);
+	xhci_acknowledge_event(ctrl);
+
+	xhci_queue_command(ctrl, (void *)((uintptr_t)ring->enqueue |
+		ring->cycle_state), udev->slot_id, ep_index, TRB_SET_DEQ);
+	event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
+	BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags))
+		!= udev->slot_id || GET_COMP_CODE(le32_to_cpu(
+		event->event_cmd.status)) != COMP_SUCCESS);
+	xhci_acknowledge_event(ctrl);
+}
+
 /*
  * Stops transfer processing for an endpoint and throws away all unprocessed
  * TRBs by setting the xHC's dequeue pointer to our enqueue pointer. The next
@@ -918,6 +947,10 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
 
 	record_transfer_result(udev, event, length);
 	xhci_acknowledge_event(ctrl);
+	if (udev->status == USB_ST_STALLED) {
+		reset_ep(udev, ep_index);
+		return -EPIPE;
+	}
 
 	/* Invalidate buffer to make it available to usb-core */
 	if (length > 0)

For anyone who is trying this for the first time (like me!), these commands (only step 2) for updating the flash.bin worked well.

1 Like

Ooh, I wonder if this will help my issue. I noticed that if I have my yubikey attached on power up, u-boot doesn’t like it and halts (I didn’t receive the same message as you though, boot interrupted and unable to try anything on the actual keyboard). Will give it a try and report back.

1 Like

Doesn’t resolve my issue, but I can confirm that on removing the yubikey, the system now stops reseting.
Before this patch, I’d get the same warning and Unexpected XHCI event TRB, skipping... (fe538f20 00000000 13000000 03008401) messge on disconnecting the yubikey.
It would print a BUG statement after but system then reset immediately.
Either way, still in an improvement, thank you :slight_smile:

1 Like