Page 1 of 1

usb uhci IO-TD stalled

Posted: Sun Sep 13, 2015 12:01 pm
by alwaysnub
Hi all.

Iv been trying to get the Device-Descriptor for Hi-Speed usb devices using the uhci.
The Setup TD always executes fine, but the following IO-TD always fires a usb error interrupt and reports a stalled error.
I have tried numerous things to fix it, such as changing the D-Toggle bits, changing my port reset procedure and calling SetDeviceAddress before GetDeviceDescriptor.
I don't think my port reset procedure is a problem sense the Setup TD executes fine.

My usb test device is a Logitech keyboard.
I'm lost at what the problem could be.

My uhci_ControlIn always reports a stalled error on the Data-TD, and on the handshake-TD for uhci_ControlSet

Let me know if you see anything wrong with this code:

Code: Select all

PUHCI_TRANSFER_DESCRIPTOR AllocateTD(PUHCI_TRANSFER_DESCRIPTOR Next, USB_SPEED Speed)
{
	PUHCI_TRANSFER_DESCRIPTOR TD;

	TD = (PUHCI_TRANSFER_DESCRIPTOR) Malloc(sizeof(UHCI_TRANSFER_DESCRIPTOR));
	if (TD != 0)
	{
		MemSet(TD, 0, sizeof(UHCI_TRANSFER_DESCRIPTOR));
		if ((SIZE_PTR)Next != BIT_T) TD->Next = ((SIZE_PTR)Next & 0xFFFFFFF0) | BIT_Vf;
		else TD->Next = BIT_T;
		TD->ErrorCounter = 3; // Stop after 3 errors.
		TD->Active = 1; // Execute This Transaction.
		if (Speed == USB_LOWSPEED) TD->LowSpeedDevice = TRUE;
	}

	return TD;
}

PUHCI_TRANSFER_DESCRIPTOR uhci_CreateTD_Setup(PUHCI_TRANSFER_DESCRIPTOR Next, PUSB_REQUEST Request, USB_SPEED Speed, BYTE Toggle, DWORD Device, BYTE Endpoint)
{
	PUHCI_TRANSFER_DESCRIPTOR TD;

	TD = AllocateTD(Next, Speed);
	if (TD != 0)
	{
		TD->PacketId = UHCI_TD_SETUP; // SETUP
		TD->MaxLength = 8 - 1; // Setup length is always 8
		TD->DataToggle = Toggle; // Should be toggled every list entry.
		TD->DeviceAddress = Device; // The device address.
		TD->Endpoint = Endpoint; // Endpoint number on the device serving as the data source or sink.
		TD->Buffer = (DWORD) Request; // USB Request info.
	}

	return TD;
}

PUHCI_TRANSFER_DESCRIPTOR uhci_CreateTD_IO(PUHCI_TRANSFER_DESCRIPTOR Next, USB_SPEED Speed, BYTE Direction, BYTE Toggle, WORD TokenBytes, DWORD Device, BYTE Endpoint, PVOID Buffer)
{
	PUHCI_TRANSFER_DESCRIPTOR TD;

	TD = AllocateTD(Next, Speed);
	if (TD != 0)
	{
		TD->PacketId = Direction; // UHCI_TD_IN or UHCI_TD_OUT
		if (TokenBytes) TD->MaxLength = (TokenBytes - 1) & 0x7FF;
		else TD->MaxLength = 0x7FF; // Null data packet.
		TD->DataToggle = Toggle; // Should be toggled every list entry.
		TD->DeviceAddress = Device; // The device address.
		TD->Endpoint = Endpoint; // Endpoint number on the device serving as the data source or sink.
		TD->Buffer = (DWORD) Buffer; // Buffer to read or write.
	}

	return TD;
}

ERROR API uhci_ControlSet(PUSB_DEVICE_INFO UsbDevice, PUSB_REQUEST Request)
{
	PUHCI HC;
	PUHCI_TRANSFER_DESCRIPTOR SetupToken;
	PUHCI_TRANSFER_DESCRIPTOR HandshakeToken;
	ERROR Error;

	HC = (PUHCI) UsbDevice->Device->Controller;

	HandshakeToken = uhci_CreateTD_IO((PUHCI_TRANSFER_DESCRIPTOR)BIT_T, UsbDevice->Speed, UHCI_TD_IN, TRUE, 0, UsbDevice->Address, 0, 0);
	SetupToken = uhci_CreateTD_Setup(HandshakeToken, Request, UsbDevice->Speed, FALSE, UsbDevice->Address, 0);

	uhci_CreateQH(HC, HC->QH, SetupToken);

	// Run scheduler.
	OutW(HC->BAR + UHCI_FRNUM, 0);
	OutW(HC->BAR + UHCI_USBCMD, InW(HC->BAR + UHCI_USBCMD) | UHCI_CMD_RS);

	// Wait for completion.
	while ((SetupToken->Active == 1) || (HandshakeToken->Active == 1) && (HC->UsbIntError == FALSE));

	// Stop scheduler.
	OutW(HC->BAR + UHCI_USBCMD, InW(HC->BAR + UHCI_USBCMD) & ~UHCI_CMD_RS);

	// Wait for stop.
	while (!(InW(HC->BAR + UHCI_USBSTS) & UHCI_STS_HCHALTED));

	// Reset UHCI_STS_HCHALTED bit.
	OutW(HC->BAR + UHCI_USBSTS, UHCI_STS_HCHALTED);

	if ((HandshakeToken->BitstuffError|SetupToken->BitstuffError) != 0) Error = ERROR_USB_OTHER;
	else if ((HandshakeToken->DataBufferError|SetupToken->DataBufferError) != 0) Error = ERROR_USB_DATA_BUFFER;
	else if ((HandshakeToken->BabbleDetected|SetupToken->BabbleDetected) != 0) Error = ERROR_USB_BABBLE;
	else if ((HandshakeToken->CRC_TimeOutError|SetupToken->CRC_TimeOutError) != 0) Error = ERROR_USB_TIMEOUT;
	else if ((HandshakeToken->NakReceived|SetupToken->NakReceived) != 0) Error = ERROR_USB_TRANSACTION;
	else if ((HandshakeToken->Stalled|SetupToken->Stalled) != 0) Error = ERROR_USB_HALTED;
	else Error = ERROR_NONE;

	Free(HandshakeToken);
	Free(SetupToken);

	return Error;
}

ERROR API uhci_ControlIn(PUSB_DEVICE_INFO UsbDevice, PVOID Buffer, PUSB_REQUEST Request)
{
	PUHCI HC;
	PUHCI_TRANSFER_DESCRIPTOR SetupToken;
	PUHCI_TRANSFER_DESCRIPTOR DataToken;
	PUHCI_TRANSFER_DESCRIPTOR HandshakeToken;
	ERROR Error;

	HC = (PUHCI) UsbDevice->Device->Controller;

	HandshakeToken = uhci_CreateTD_IO((PUHCI_TRANSFER_DESCRIPTOR)BIT_T, UsbDevice->Speed, UHCI_TD_OUT, TRUE, 0, UsbDevice->Address, 0, 0);
	DataToken = uhci_CreateTD_IO(HandshakeToken, UsbDevice->Speed, UHCI_TD_IN, FALSE, Request->Length, UsbDevice->Address, 0, Buffer);
	SetupToken = uhci_CreateTD_Setup(DataToken, Request, UsbDevice->Speed, FALSE, UsbDevice->Address, 0);

	uhci_CreateQH(HC, HC->QH, SetupToken);

	// Run scheduler.
	OutW(HC->BAR + UHCI_FRNUM, 0);
	OutW(HC->BAR + UHCI_USBCMD, InW(HC->BAR + UHCI_USBCMD) | UHCI_CMD_RS);

	// Wait for completion.
	while ((SetupToken->Active == 1) || (DataToken->Active == 1) || (HandshakeToken->Active == 1) && (HC->UsbIntError == FALSE));

	// Stop scheduler.
	OutW(HC->BAR + UHCI_USBCMD, InW(HC->BAR + UHCI_USBCMD) & ~UHCI_CMD_RS);

	// Wait for stop.
	while (!(InW(HC->BAR + UHCI_USBSTS) & UHCI_STS_HCHALTED));

	// Reset UHCI_STS_HCHALTED bit.
	OutW(HC->BAR + UHCI_USBSTS, UHCI_STS_HCHALTED);

	if ((HandshakeToken->BitstuffError|DataToken->BitstuffError|SetupToken->BitstuffError) != 0) Error = ERROR_USB_OTHER;
	else if ((HandshakeToken->DataBufferError|DataToken->DataBufferError|SetupToken->DataBufferError) != 0) Error = ERROR_USB_DATA_BUFFER;
	else if ((HandshakeToken->BabbleDetected|DataToken->BabbleDetected|SetupToken->BabbleDetected) != 0) Error = ERROR_USB_BABBLE;
	else if ((HandshakeToken->CRC_TimeOutError|DataToken->CRC_TimeOutError|SetupToken->CRC_TimeOutError) != 0) Error = ERROR_USB_TIMEOUT;
	else if ((HandshakeToken->NakReceived|DataToken->NakReceived|SetupToken->NakReceived) != 0) Error = ERROR_USB_TRANSACTION;
	else if ((HandshakeToken->Stalled|DataToken->Stalled|SetupToken->Stalled) != 0) Error = ERROR_USB_HALTED;
	else Error = ERROR_NONE;

	Free(HandshakeToken);
	Free(DataToken);
	Free(SetupToken);

	return Error;
}

Re: usb uhci IO-TD stalled

Posted: Sun Sep 13, 2015 3:58 pm
by TomT
I dont have a uhci driver for keyboard, but HID devices like mouse are low speed devices, and I thought keyboard was also low speed.

You might examine the raw hex bytes of your Transfer Descriptor and compare them to the usb 1.0 spec.

TomT

https://code.google.com/p/tatos/

Re: usb uhci IO-TD stalled

Posted: Sun Sep 13, 2015 7:19 pm
by alwaysnub
Yes, sorry that was a typo, i meant Full-Speed device Not Hi-Speed.

I have a Logitech keyboard and mouse that show as Full-Speed in the port status/control register.
After reset of the port, it shows a 0x95 value, that appears to be correct.

Re: usb uhci IO-TD stalled

Posted: Wed Sep 16, 2015 12:41 pm
by alwaysnub
After checking the raw dwords of the TD's, i noticed the Buffer dword was way out of range.
Turns out the way i declared my TD was creating the problem.

Instead of declaring the Token (dword 2) like this:

Code: Select all

        BYTE PacketId;
	DWORD DeviceAddress     : 7;
	DWORD Endpoint          : 4;
	DWORD DataToggle        : 1;
	DWORD Reserved3         : 1;
	DWORD MaxLength         : 11;
It should have been like this:

Code: Select all

        DWORD PacketId          : 8;
	DWORD DeviceAddress     : 7;
	DWORD Endpoint          : 4;
	DWORD DataToggle        : 1;
	DWORD Reserved3         : 1;
	DWORD MaxLength         : 11;
Now i face a new problem. When i call GetDeviceDescriptor with a length of 8, the device responds with a 0 length data packet.
But when i call with a length of 18, the device responds with a 8 length data packet and the data is not for a device descriptor but instead for an interface.
Iv check the raw bytes of the request, and all the data looks correct.

Are devices aloud to respond with an interface descriptor?

Re: usb uhci IO-TD stalled

Posted: Thu Sep 17, 2015 6:21 am
by SpyderTL
No. An interface descriptor should never be returned by itself regardless of what command you send. Make sure you aren't reading part of a previous packet by mistake.

Re: usb uhci IO-TD stalled

Posted: Mon Sep 21, 2015 7:04 pm
by alwaysnub
No, thats not the problem. I'm setting the buffer data to 0 before each call to GetDeviceDescriptor and then dumping the contents to screen.

Here is the bytes returned when i call with a length of 18

Length: 109
DescriptorType: 4
24
195
0
85
1
2
0

That 109 Length sounds strange to say the least.
I'm currently working on a windows test app to see if windows produces the same result, and to see what it says.

Re: usb uhci IO-TD stalled

Posted: Mon Sep 21, 2015 8:27 pm
by SpyderTL
alwaysnub wrote:I'm currently working on a windows test app to see if windows produces the same result, and to see what it says.
Look for a utility called UsbTreeView. I use it to verify my USB descriptors in Windows.

Re: usb uhci IO-TD stalled

Posted: Tue Sep 22, 2015 9:24 pm
by alwaysnub
OK... Finally got everything working correctly.
First off, thanks for pointing me in the right directions, and for mentioning UsbTreeView (Big help).

The reason i was getting a return packet of 0 was because the first Data TD should have been Data Toggled (1/TRUE).
The data being returned when a length of 18 was specified, was not for an interface, but was actually the next 8 bytes of the Device Descriptor.
Apparently the controller can mix up the data if you don't do things the way it expects.
I also needed multiple data TD's when the length requested was over MaxPacketSize0, in this particular case (8).

Rules for building the transaction:
Setup TD Data-Toggle = 0
First Data TD Data-Toggle = 1 and alternates each Data TD.
Status TD Data-Toggle = 1
Don't forget to adjust the buffer pointer for each Data TD.

I welcome all feedback, if you think something should be changed, let me know.
Here is the modified code:

Code: Select all

PUHCI_TRANSFER_DESCRIPTOR AllocateTD(PUHCI_TRANSFER_DESCRIPTOR Next, USB_SPEED Speed)
{
	PUHCI_TRANSFER_DESCRIPTOR TD;

	TD = (PUHCI_TRANSFER_DESCRIPTOR) Malloc(sizeof(UHCI_TRANSFER_DESCRIPTOR));
	if (TD != 0)
	{
		MemSet(TD, 0, sizeof(UHCI_TRANSFER_DESCRIPTOR));
		if (Next == 0) TD->Next = BIT_T;
		else TD->Next = ((SIZE_PTR)Next & 0xFFFFFFF0) | BIT_Vf;
		TD->ErrorCounter = 3; // Stop after 3 errors.
		TD->Active = 1; // Execute This Transaction.
		if (Speed == USB_LOWSPEED) TD->LowSpeedDevice = TRUE;
	}

	return TD;
}

PUHCI_TRANSFER_DESCRIPTOR uhci_CreateTD_Setup(PUHCI_TRANSFER_DESCRIPTOR Next, PUSB_REQUEST Request, USB_SPEED Speed, BYTE Toggle, DWORD Device, BYTE Endpoint)
{
	PUHCI_TRANSFER_DESCRIPTOR TD;

	TD = AllocateTD(Next, Speed);
	if (TD != 0)
	{
		TD->PacketId = UHCI_TD_SETUP; // SETUP
		TD->MaxLength = 8 - 1; // Setup length is always 8
		TD->DataToggle = Toggle; // Should be toggled every list entry.
		TD->DeviceAddress = Device; // The device address.
		TD->Endpoint = Endpoint; // Endpoint number on the device serving as the data source or sink.
		TD->Buffer = (DWORD) Request; // USB Request info.
	}

	return TD;
}

PUHCI_TRANSFER_DESCRIPTOR uhci_CreateTD_IO(PUHCI_TRANSFER_DESCRIPTOR Next, USB_SPEED Speed, BYTE Direction, BYTE Toggle, WORD TokenBytes, DWORD Device, BYTE Endpoint, PVOID Buffer)
{
	PUHCI_TRANSFER_DESCRIPTOR TD;

	TD = AllocateTD(Next, Speed);
	if (TD != 0)
	{
		TD->PacketId = Direction; // UHCI_TD_IN or UHCI_TD_OUT
		if (TokenBytes != 0) TD->MaxLength = (TokenBytes - 1) & 0x7FF;
		else TD->MaxLength = 0x7FF; // Null data packet.
		TD->DataToggle = Toggle; // Should be toggled every list entry.
		TD->DeviceAddress = Device; // The device address.
		TD->Endpoint = Endpoint; // Endpoint number on the device serving as the data source or sink.
		TD->Buffer = (DWORD) Buffer; // Buffer to read or write.
	}

	return TD;
}

ERROR API uhci_ControlSet(PUSB_DEVICE_INFO UsbDevice, PUSB_REQUEST Request)
{
	PUHCI HC;
	PUHCI_TRANSFER_DESCRIPTOR SetupToken, HandshakeToken;
	ERROR Error;

	HC = (PUHCI) UsbDevice->Device->Controller;

	HandshakeToken = uhci_CreateTD_IO(0, UsbDevice->Speed, UHCI_TD_IN, TRUE, 0, UsbDevice->Address, 0, 0);
	SetupToken = uhci_CreateTD_Setup(HandshakeToken, Request, UsbDevice->Speed, FALSE, UsbDevice->Address, 0);

	uhci_SetupQH(HC->QH, SetupToken);

	// Run scheduler.
	OutW(HC->BAR + UHCI_FRNUM, 0);
	OutW(HC->BAR + UHCI_USBCMD, InW(HC->BAR + UHCI_USBCMD) | UHCI_CMD_RS);

	// Wait for completion.
	while ((SetupToken->Active == 1) || (HandshakeToken->Active == 1) && (HC->UsbIntError == FALSE));

	// Stop scheduler.
	OutW(HC->BAR + UHCI_USBCMD, InW(HC->BAR + UHCI_USBCMD) & ~UHCI_CMD_RS);

	// Wait for stop.
	while (!(InW(HC->BAR + UHCI_USBSTS) & UHCI_STS_HCHALTED));

	// Reset UHCI_STS_HCHALTED bit.
	OutW(HC->BAR + UHCI_USBSTS, UHCI_STS_HCHALTED);

	uhci_SetupQH(HC->QH, 0);

	if ((HandshakeToken->BitstuffError|SetupToken->BitstuffError) != 0) Error = ERROR_USB_BITSTUFF;
	else if ((HandshakeToken->DataBufferError|SetupToken->DataBufferError) != 0) Error = ERROR_USB_DATA_BUFFER;
	else if ((HandshakeToken->BabbleDetected|SetupToken->BabbleDetected) != 0) Error = ERROR_USB_BABBLE;
	else if ((HandshakeToken->CRC_TimeOutError|SetupToken->CRC_TimeOutError) != 0) Error = ERROR_USB_TIMEOUT;
	else if ((HandshakeToken->NakReceived|SetupToken->NakReceived) != 0) Error = ERROR_USB_NAK;
	else if ((HandshakeToken->Stalled|SetupToken->Stalled) != 0) Error = ERROR_USB_HALTED;
	else if (HC->UsbIntError == TRUE) Error = ERROR_USB_INTERRUPT;
	else Error = ERROR_NONE;

	Free(HandshakeToken);
	Free(SetupToken);

	return Error;
}

ERROR API uhci_ControlIn(PUSB_DEVICE_INFO UsbDevice, PVOID Buffer, PUSB_REQUEST Request)
{
	PUHCI HC;
	PUHCI_TRANSFER_DESCRIPTOR FirstToken, ThisToken, NextToken;
	WORD TotalLength, BytesPerPacket, TotalPackets, Offset, OddPacketLen, I;
	BYTE DataToggle, Active, BitstuffError, DataBufferError, BabbleDetected, CRC_TimeOutError, NakReceived, Stalled;
	ERROR Error;

	Offset = TotalLength = Request->Length;
	BytesPerPacket = UsbDevice->Descriptor.MaxPacketSize0;
	TotalPackets = TotalLength / BytesPerPacket;
	OddPacketLen = TotalLength - (TotalPackets*BytesPerPacket);
	FirstToken = 0;

	BitstuffError = DataBufferError = BabbleDetected = CRC_TimeOutError = NakReceived = Stalled = 0;

	HC = (PUHCI) UsbDevice->Device->Controller;

	FirstToken = uhci_CreateTD_IO(FirstToken, UsbDevice->Speed, UHCI_TD_OUT, TRUE, 0, UsbDevice->Address, 0, 0);
	if (OddPacketLen != 0)
	{
		Offset -= OddPacketLen;
		FirstToken = uhci_CreateTD_IO(FirstToken, UsbDevice->Speed, UHCI_TD_IN, FALSE, OddPacketLen, UsbDevice->Address, 0, (PBYTE)Buffer+Offset);
		I = 0;
	}
	else
	{
		Offset -= BytesPerPacket;
		FirstToken = uhci_CreateTD_IO(FirstToken, UsbDevice->Speed, UHCI_TD_IN, FALSE, BytesPerPacket, UsbDevice->Address, 0, (PBYTE)Buffer+Offset);
		I = 1;
	}
	for (; I < TotalPackets; I++)
	{
		Offset -= BytesPerPacket;
		FirstToken = uhci_CreateTD_IO(FirstToken, UsbDevice->Speed, UHCI_TD_IN, FALSE, BytesPerPacket, UsbDevice->Address, 0, (PBYTE)Buffer+Offset);
	}
	FirstToken = uhci_CreateTD_Setup(FirstToken, Request, UsbDevice->Speed, FALSE, UsbDevice->Address, 0);

	DataToggle = TRUE;
	ThisToken = (PUHCI_TRANSFER_DESCRIPTOR) (FirstToken->Next & 0xFFFFFFF1);
	while (((SIZE_PTR)ThisToken->Next & BIT_T) != BIT_T)
	{
		ThisToken->DataToggle = DataToggle;
		DataToggle ^= 1;
		ThisToken = (PUHCI_TRANSFER_DESCRIPTOR) (ThisToken->Next & 0xFFFFFFF1);
	}

	uhci_SetupQH(HC->QH, FirstToken);

	// Run scheduler.
	OutW(HC->BAR + UHCI_FRNUM, 0);
	OutW(HC->BAR + UHCI_USBCMD, InW(HC->BAR + UHCI_USBCMD) | UHCI_CMD_RS);

	while (TRUE) // Wait for completion.
	{
		Active = FALSE;
		ThisToken = FirstToken;
		while (((SIZE_PTR)ThisToken & BIT_T) != BIT_T)
		{
			Active |= ThisToken->Active;
			ThisToken = (PUHCI_TRANSFER_DESCRIPTOR) (ThisToken->Next & 0xFFFFFFF1);
		}
		if ((Active == FALSE) || (HC->UsbIntError == TRUE)) break;
	}

	// Stop scheduler.
	OutW(HC->BAR + UHCI_USBCMD, InW(HC->BAR + UHCI_USBCMD) & ~UHCI_CMD_RS);

	// Wait for stop.
	while (!(InW(HC->BAR + UHCI_USBSTS) & UHCI_STS_HCHALTED));

	// Reset UHCI_STS_HCHALTED bit.
	OutW(HC->BAR + UHCI_USBSTS, UHCI_STS_HCHALTED);

	uhci_SetupQH(HC->QH, 0);

	NextToken = ThisToken = FirstToken;
	while (((SIZE_PTR)NextToken & BIT_T) != BIT_T)
	{
		ThisToken = NextToken;
		BitstuffError |= ThisToken->BitstuffError;
		DataBufferError |= ThisToken->DataBufferError;
		BabbleDetected |= ThisToken->BabbleDetected;
		CRC_TimeOutError |= ThisToken->CRC_TimeOutError;
		NakReceived |= ThisToken->NakReceived;
		Stalled |= ThisToken->Stalled;
		NextToken = (PUHCI_TRANSFER_DESCRIPTOR) (ThisToken->Next & 0xFFFFFFF1);
		Free(ThisToken);
	}

	if (BitstuffError != 0) Error = ERROR_USB_BITSTUFF;
	else if (DataBufferError != 0) Error = ERROR_USB_DATA_BUFFER;
	else if (BabbleDetected != 0) Error = ERROR_USB_BABBLE;
	else if (CRC_TimeOutError != 0) Error = ERROR_USB_TIMEOUT;
	else if (NakReceived != 0) Error = ERROR_USB_NAK;
	else if (Stalled != 0) Error = ERROR_USB_HALTED;
	else if (HC->UsbIntError == TRUE) Error = ERROR_USB_INTERRUPT;
	else Error = ERROR_NONE;

	return Error;
}

Re: usb uhci IO-TD stalled

Posted: Wed Sep 23, 2015 2:48 pm
by SpyderTL
I haven't started on my UHCI code, yet. But the OHCI has the option for the controller to keep up with the data toggle for you. I had issues until I decided to let the controller handle it.

Not sure if there is something similar in UHCI.

Re: usb uhci IO-TD stalled

Posted: Wed Sep 23, 2015 8:04 pm
by alwaysnub
the OHCI has the option for the controller to keep up with the data toggle for you. I had issues until I decided to let the controller handle it.
I did not know that, thinks for the info, I'll be starting on my OHCI code very soon.
Not sure if there is something similar in UHCI.
No, not that iv seen, and iv been through the specification pretty thoroughly.

I would just port my code or use it as an example, because it works beautifully right now.
I can set the Device Address, get the Device Descriptor and get the Configuration Descriptors without any problems.

Re: usb uhci IO-TD stalled

Posted: Thu Nov 26, 2015 10:57 am
by alwaysnub
I have found a bug in this code.

The scheduler/controller is being stopped after a transaction, this can cause problems for HID devices!
These lines should be removed:

Code: Select all

// Stop scheduler.
OutW(HC->BAR + UHCI_USBCMD, InW(HC->BAR + UHCI_USBCMD) & ~UHCI_CMD_RS);

// Wait for stop.
while (!(InW(HC->BAR + UHCI_USBSTS) & UHCI_STS_HCHALTED));

// Reset UHCI_STS_HCHALTED bit.
OutW(HC->BAR + UHCI_USBSTS, UHCI_STS_HCHALTED);
In these functions:

uhci_ControlSet
uhci_ControlIn