usb hub: ohci interrupt for port, port GET_STATUS

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
sounds
Member
Member
Posts: 112
Joined: Sat Feb 04, 2012 5:03 pm

usb hub: ohci interrupt for port, port GET_STATUS

Post by sounds »

Briefly: I'm using qemu to emulate a usb hub. The interrupt endpoint is set up using the OHCI controller. The interrupt transfer is posted by the OHCI controller, so I immediately send a setup TD to send GET_STATUS to the port. To my surprise, I get a second interrupt transfer posted before the GET_STATUS response, which makes it impossible to send a CLEAR_FEATURE to the port to stop the interrupt from firing.

2 x interrupts? Something feels off.

Yes, it kind of makes sense. I can live with it. But I wanted to check if there is no better solution than what I currently have. I ignore all interrupts from the interrupt endpoint until I've completed GET_STATUS and done a CLEAR_FEATURE to clear the set bits that triggered the interrupt. Or, alternatively I could block the interrupt transfer in the controller, but that would prevent interrupts from the other ports on the hub so I think that's incorrect.

Any suggestions for a way to respond to the interrupt TD with successful GET_STATUS and CLEAR_FEATURE TD's before getting additional interrupt TD's?
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: usb hub: ohci interrupt for port, port GET_STATUS

Post by BenLunt »

If I understand you correctly, you have set up the Periodic List to return a 1-byte (7 ports or less) change status. Once you have received this byte, if a change is detected, you then use the Control Pipe to request the 4-byte status of the hub. Once you have done this, you then send a Clear Feature request (on the Control Pipe) to clear the change status.

Is this correct?

What interrupt are you talking about? A hardware interrupt? Is it because the DoneHead value is being written after the Periodic list is executed?
If you are taking about a new Interrupt TD being executed, this could happen depending on the rate of the check. Your Periodic list could be using a 16ms check and your HubGetPortStatus() routine could be taking more than 16ms to process the change. An external hub usually indicates a 0xFFms interval (or round up to 256ms).

The second (hardware) interrupt may have nothing to do with the external hub port status event. It could be something else, simply that the controller is again, done with the list.

When you get the initial interrupt, at the start of your "HubGetPortStatus" routine check to see if you are already processing the change. If so, simply return. Once you are done with the Change Event (indicate an enumeration of new device or a removal of a device), get the status one more time to see if there was a change between the first initial call and now the end of the process. If so, repeat for a different port change event. If no other change was found, clear the "InThisRoutine" flag and return.

Code: Select all

HubGetPortStatus() {
  if (InThisRoutine)
    return;
  InThisRoutine = 1;
  do {
    HubStatus = GetHubStatus();
    .
    . Do Something because of the change event (enumerate new device, removal of device, etc.)
    .
  while (HubStatus != GetHubStatus());
  ClearFeature();
  InThisRoutine = 0;
  return;
}
Of course this is simply a mock-up example, but you may get the point.

Hope this helps,
Ben
- https://www.fysnet.net/the_universal_serial_bus.htm
sounds
Member
Member
Posts: 112
Joined: Sat Feb 04, 2012 5:03 pm

Re: usb hub: ohci interrupt for port, port GET_STATUS

Post by sounds »

Thanks, Ben. Very helpful. I ran out of time to post a detailed response, but will follow up with a detailed dump. I'm guessing I'm not properly interpreting the endpoint descriptor with interval = 0xff for the qemu emulated hub.
Post Reply