OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 3:22 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 71 posts ]  Go to page 1, 2, 3, 4, 5  Next
Author Message
 Post subject: USB OHCI specification.
PostPosted: Sat Feb 20, 2016 2:29 pm 
Offline
Member
Member

Joined: Thu Jan 13, 2011 3:33 pm
Posts: 42
Hi,

I am trying to develop a USB library for my OS on an ARM processor based development board. Currently I am struggling with the specification itself and trying to understand how everything works. I am referring to this usb spec -> http://www.scaramanga.co.uk/stuff/qemu-usb/hcir1_0a.pdf

Is that the correct specification I am supposed to read?

Thanks.


Top
 Profile  
 
 Post subject: Re: USB OHCI specification.
PostPosted: Mon Feb 22, 2016 12:12 am 
Offline
Member
Member
User avatar

Joined: Sun Sep 19, 2010 10:05 pm
Posts: 1074
That looks like the correct specification to me.

Let us know if you run into any problems. I just recently got my OHCI code working well enough to read a block of data from a USB mass storage device.

_________________
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott


Top
 Profile  
 
 Post subject: Re: USB OHCI specification.
PostPosted: Tue Feb 23, 2016 12:06 pm 
Offline
Member
Member

Joined: Thu Jan 13, 2011 3:33 pm
Posts: 42
That is great. USB is last of my drivers to write for my board. I am really struggling with setting up my ED's and TD's. If I can just read some configuration data out of the device that would be a huge sigh of relief for me. Any tips on how to get started and your experience?


Top
 Profile  
 
 Post subject: Re: USB OHCI specification.
PostPosted: Tue Feb 23, 2016 1:16 pm 
Offline
Member
Member
User avatar

Joined: Sun Sep 19, 2010 10:05 pm
Posts: 1074
It took me months to get to the point that I was getting valid information from a USB device, and my code is still making a lot of assumptions about there being no communication errors and in most cases using hard-coded device addresses.

First and foremost, just keep working at it, and you'll eventually see some valid results.

Second, download a utility called USB Tree View from here: http://www.uwe-sieber.de/usbtreeview_e.html

It enumerates all devices and shows you the raw descriptors and the human-readable values for each field. It will show you what data to expect from your devices. If you are using a virtual machine to test your OS, then set up a Windows XP installation on the same VM with the exact same settings, and your data should match the data displayed in USB tree view, exactly.

Lastly, it helps to think of your USB layout as a Network rather than a single bus, because of the way the devices are dynamically assigned addresses, and the way that packets and buffers are queued for incoming and outgoing transfers.

Also, until you get a stable system in place, you can ignore all of the interface and endpoint descriptors, and you can hard-code your device address to 1, and hard-code your endpoint to 0, as all devices have the same endpoint 0, regardless of their type.

Let me know if you have any specific questions. Good luck!

EDIT: If you aren't already using it, I would also recommend using VirtualBox for testing purposes. In the latest version, you can "attach" a USB Mass Storage device to an OHCI host controller by simply pointing to a hard drive or CD image ISO file. Very convenient.

_________________
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott


Top
 Profile  
 
 Post subject: Re: USB OHCI specification.
PostPosted: Wed Feb 24, 2016 2:13 pm 
Offline
Member
Member

Joined: Thu Jan 13, 2011 3:33 pm
Posts: 42
Correct me if I am wrong with my understanding.

After my development board is booted up I have setup my ED and TD lists in my driver. I have created a single ED and connected it to 2 TD's. HeadP on one TD and TailP on another TD. Now I want to start the setup. I will be put setup the USB device request packet to the buffer pointed to the by the TailP. Is my understanding until here correct?


Top
 Profile  
 
 Post subject: Re: USB OHCI specification.
PostPosted: Wed Feb 24, 2016 9:22 pm 
Offline
Member
Member
User avatar

Joined: Sun Sep 19, 2010 10:05 pm
Posts: 1074
Until you tell the device what its address is (1-255), it will only respond to packets sent to address 0, endpoint 0, and that's only after the port that it is attached to has been reset. Until you reset the device's port, it will not respond to any packets at all.

So you will need one EP just for sending Commands to the device at address 0. You should be sure to only have one device 0 at a time. You will need two TDs if the command returns no data, and three TDs if the command returns any data. This is because you need one TD to act as a "terminator". This TD should contain all zeroes so that no data is actually transferred.

Set the tail on the EP to the "terminator" TD address, and set the head on the EP to point to the "command" TD address. Then clear the "sKip" bit on the EP status field (you should set this bit initially), and then notify the device that the command queue has been modified by setting bit 1 (value 0x02) on the device's status register.

Then either wait for an interrupt, or just poll the ED head until it matches the tail. I think there is also a halted bit on that register that you can check as well.

Then any data returned by the device should be sitting in memory. Using this, you should be able to query the devices type, its configurations, its interfaces, and its end points. Then you can start communicating with the other end points on that device.

Hopefully this answers your question, and gives you enough information to get you up and running. Let us know how it goes.

Note: As soon as you send the SetAddress command, the device will no longer respond to address 0 packets, and you will need to add another EP that matches the device's new address (for endpoint 0).

EDIT: I added some information to the OHCI wiki page concerning these descriptors, as well. I'll try to add more details at some point in the near future, so keep an eye out for those.

_________________
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott


Top
 Profile  
 
 Post subject: Re: USB OHCI specification.
PostPosted: Mon Mar 07, 2016 9:14 am 
Offline
Member
Member

Joined: Thu Jan 13, 2011 3:33 pm
Posts: 42
Quote:
Until you tell the device what its address is (1-255), it will only respond to packets sent to address 0, endpoint 0, and that's only after the port that it is attached to has been reset. Until you reset the device's port, it will not respond to any packets at all.


Correct me if I am wrong, before I reset the port I need to get the port status right? Now getting the port status is a communication between the host controller and the hub right? To test my ED's and TD's getting the port status would be good enough right?


Top
 Profile  
 
 Post subject: Re: USB OHCI specification.
PostPosted: Mon Mar 07, 2016 9:32 am 
Offline
Member
Member
User avatar

Joined: Sun Sep 19, 2010 10:05 pm
Posts: 1074
Depends. On the x86 platform, the host root hub is actually attached to the PCI bus, and mapped into memory, so the CPU communicates directly with it, without sending any USB packets. For all other hub devices, you have to send USB packets.

So, on your particular platform, if there is no direct access to the root hub, you may have to send USB packets, but I'm not sure what that sequence would look like, unless the root hub defaults to address 0, or something like that.

The OHCI specs say that the root hub ports each get a register starting at offset 0x54. Look for HcRhPortStatus in the OHCI specifications. You should be able to use these registers to read the port status and reset a port on the root hub without having to send any USB packets at all.

_________________
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott


Top
 Profile  
 
 Post subject: Re: USB OHCI specification.
PostPosted: Sun Mar 20, 2016 12:12 pm 
Offline
Member
Member

Joined: Thu Jan 13, 2011 3:33 pm
Posts: 42
Quote:
Set the tail on the EP to the "terminator" TD address, and set the head on the EP to point to the "command" TD address. Then clear the "sKip" bit on the EP status field (you should set this bit initially), and then notify the device that the command queue has been modified by setting bit 1 (value 0x02) on the device's status register.



I am almost done in setting up my ED's and TD's to get the device descriptor. What is the device's status register you are referring to?

I have the init code here: https://github.com/mindentropy/s3c2440-mdk/blob/master/src/os/usb_ohci.c#L196

My GetDescriptor initialization of ed's and td's is here: https://github.com/mindentropy/s3c2440-mdk/blob/master/src/os/usb_ohci.c#L101

It would be great if you can just review the init function in the URL. I am not sure whether my initializing is fine.


Top
 Profile  
 
 Post subject: Re: USB OHCI specification.
PostPosted: Sun Mar 20, 2016 11:00 pm 
Offline
Member
Member
User avatar

Joined: Sun Sep 19, 2010 10:05 pm
Posts: 1074
The OHCI controller has a register that contains a flag that allows the CPU to notify the OHCI controller that the command queue has been updated. It is either the hcCommandStatus or hcControl register. I'll check tomorrow when I get a chance.

Looking at your init code, two things stand out. First, your control head ED and your bulk head ED should be DIFFERENT. It's commented out right now, so you're fine for now, but you'll need a whole separate ED queue for your bulk endpoints at some point.

Second, since you've only set up your control EP queue, you should only enable the control EP flag in the control register. You should leave all of the other endpoint queues disabled.

Hopefully, that will get you started. Let us know how it goes.

_________________
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott


Top
 Profile  
 
 Post subject: Re: USB OHCI specification.
PostPosted: Mon Mar 21, 2016 2:37 pm 
Offline
Member
Member

Joined: Thu Jan 13, 2011 3:33 pm
Posts: 42
I setup the control register as you mentioned. I just set the CLE flag.
https://github.com/mindentropy/s3c2440-mdk/blob/master/src/os/usb_ohci.c#L260

To trigger the control list reading I set the CLF flag in the HcCommandStatusReg.
https://github.com/mindentropy/s3c2440-mdk/blob/master/src/os/usb_ohci.c#L278

I have to do a busy wait polling to check whether I have received any data in the TD.


Top
 Profile  
 
 Post subject: Re: USB OHCI specification.
PostPosted: Sun Apr 16, 2017 7:55 pm 
Offline
Member
Member

Joined: Thu Jan 13, 2011 3:33 pm
Posts: 42
I have started working again on the OHCI after a break. I have cleaned up my code. Now I get some changes in the registers but it is errors. My ED and TD seems to be okay but after the first transmission of the TD (denoted by the HccaDoneHead) my status register sets the CC(ConditionCode) to "Device Not Responding". Why is this happening?

I have noticed that I don't send the control ED and TD to a specific USB port. So would the packet be sent to all the ports? In the document you have said that make sure only 1 device is present. Does this mean that I have to disable the port in the root hub?


Top
 Profile  
 
 Post subject: Re: USB OHCI specification.
PostPosted: Mon Apr 17, 2017 11:17 am 
Offline
Member
Member
User avatar

Joined: Sun Sep 19, 2010 10:05 pm
Posts: 1074
Actually, all packets are sent to all ports on your USB tree. But they are just ignored if the adress doesn't match the address specified in the SetAddress command that you send the device.

The address field in the packets you are sending is definately set to something. If you aren't setting it, then it probably has an address of zero.

Any device that has been reset but has not received a SetAddress command will have an address of zero. It is your job to make sure that only one device has an address of zero at any given time.

You should pick an address for each device and sent that device a SetAddress command as soon as possible. Then just use the new address from then on.

Let us know how it goes.

_________________
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott


Top
 Profile  
 
 Post subject: Re: USB OHCI specification.
PostPosted: Wed Apr 19, 2017 3:21 am 
Offline
Member
Member

Joined: Thu Jan 13, 2011 3:33 pm
Posts: 42
I tried sending the SET_ADDRESS request. I still get the "device not responding" error (0101) in the CC field of the TD.

I have the following register dump:

Before sending the packet:
Port status after reset (HcRhPortStatus register):
Port1 : 0x00100103
Port2 : 0x00000100

ED dump
Endpt ctrl: 0x00400000
TailP: 0x300074C0
HeadP: 0x300074B0
NextED: 0x00000000
HcRevision :0x00000010

After sending data:
HccaDoneHead: 0x300074B1

TD dump
TD addr:0x300074B0
TDCTRL : 0x5EE40000
CBP : 0x300072A8
NXT_TD : 0x00000000
buffer_end: 0x300072B0

ED Dump
Endpt ctrl: 0x00400000
TailP: 0x300074C0
HeadP: 0x300074C1
NextED: 0x00000000

Is my port status fine? If I try to clear the PRSC bit by writing a 1 to it I get the status changes back to 0x00000100. Is this normal?

Please also note that the PORT2 is disabled as expected.

My USB reset code is as follows:

Code:
static void reset_usb_port(enum Ports port)
{
   /* Reset port */
   hc_rh_set_port_reset(USB_OHCI_BA,port);

   /* port enable bit will be set once the port is reset */

   /* Wait until the port reset signal bit state is set to 0 */
   while(readreg32(HC_RH_PORT_STATUS_REG(USB_OHCI_BA,port)) & PRS) {
      ;
   }

   /* Wait until the port reset status change bit is set to 1 */
   while(!(readreg32(HC_RH_PORT_STATUS_REG(USB_OHCI_BA,port)) & PRSC)) {
      ;
   }

   /* Clear the PRSC bit */
   //hc_rh_set_port_reset_status_change(USB_OHCI_BA,port);
   //dump_usb_port_status();
   usb_delay();
}


Top
 Profile  
 
 Post subject: Re: USB OHCI specification.
PostPosted: Wed Apr 19, 2017 2:10 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 934
Location: USA
mindentropy wrote:
I tried sending the SET_ADDRESS request. I still get the "device not responding" error (0101) in the CC field of the TD.

I have the following register dump:

Before sending the packet:
Port status after reset (HcRhPortStatus register):
Port1 : 0x00100103
Port2 : 0x00000100

Did you clear bit 20? The hardware may or may not end the reset state until you acknowledge the finish of the reset by writing a '1' to bit 20.

mindentropy wrote:

<snip ED and TD dumps>

Is my port status fine? If I try to clear the PRSC bit by writing a 1 to it I get the status changes back to 0x00000100. Is this normal?

Yep, I guess you did clear the bit. You should do this before sending any TD's.

Rather than interpret your ED and TD's, I am going to show you the example ED with two TD's that will set the address:
Code:
  // ED at physical address 0x01234000:
      0x00082000  // control
      0x01234030  // tail
      0x01234010  // head
      to next ED    // next ed
  // first TD at physical address 0x01234010:
      0xE2E00000  // control
      0x01234030  // Current Buffer Pointer
      0x01234020  // Next TD
      0x01234037  // Buffer End  (8 bytes)
  // second TD at physical address 0x01234020:
      0xE3100000  // control
      0x00000000  // Current Buffer Pointer (none)
      0x01234030  // Next TD (Doesn't matter, but our loop gave us a pointer to here plus 0x10)
      0x00000000  // Buffer End  (none)
  // Packet at physical address 0x01234030:
      0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00

Of course you will need to adjust the physical addresses to match your setup, but this gives an idea.

Just a note. Some devices require that you get the first 8 bytes of the descriptor using the default address *before* you reset and set the address. Therefore, you should reset the device, request the first 8 bytes of the Device Descriptor, reset the device again, then send the Set Address request.

Some manufacturers made their devices work on certain platforms with certain operating systems. If it works on that system, no need to test otherwise. A certain, major operating system does exactly this sequence, so some devices expect this sequence and won't work if it doesn't see it.

Fun huh?

Ben


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 71 posts ]  Go to page 1, 2, 3, 4, 5  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 56 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group