USB driver hints for Solaris
When putting together my
Wacom tablet driver and others,
I hit a few conceptual walls in understanding USB better.
So I thought I would distill a few critical points here as I go.
Sure, you could read the full
USB 1.1 specification
but that would most likely give you a headache ;-) So read the tips here to
get you oriented.
I assume that you have had SOME exposure to solaris driver writing.
If not, you should probably first go read Sun's
"Writing Device Drivers" document. Search the online docs at oracle,
or see if the link on my TIPS page is up to date.
For a slightly condensed version, you might try
Driver writer orientation.
(This is actually titled
"Solaris OS on x86 Platforms - Device Driver Writer's Orientation", and
the link is still valid as of Oct 2011)
You might also want to read my
Solaris driver developer tips
Data Transfer Types
The key thing to keep in mind is that there are specific types of data
transfer allowed with a USB device. Not all devices support all types of
transfer. In fact, most devices will only
- Control data
- Stuff to tweak the device with, or get special info about it.
All devices must support control messages
- Bulk data
- For when you want to move "large" chunks of data.
You don't care too much when it gets there, as long as it gets
- "isochronos" data
- Basically, real-time and/or non-critical data. Think of it as
streaming life video. You dont care too much if you drop a frame
or two, you just want the data to keep coming
- Interrupt data
- "Interrupt-driven". EG: the user presses the "abort" key on the
To use one of the above data transfer types, you first
have to open a
pipe. A "Pipe" is sort of like a TCP socket
connection. You have to open up a connection before you can start sending
data. You cannot just start poking at registers somewhere.
To open a pipe, you have to first know which
endpoint on the
use. (with the exception of a control pipe, which is special).
When first starting to write a
USB device driver, if you do not already know the endpoint idenfiers, you
must query the device for which endpoints it has,
check the type of each and use the appropriate one. Make sure that you
check that the one you want is available. For example, a graphics tablet
will probably not offer a "bulk transfer" endpoint at all.
Interfaces and 'Alt'ernate settings
Every USB device has at least one 'interface'. An interface is anything
that has a unique USB ID, even though it has a single physical packaging.
For example, a combined keyboard+mouse may be a single physical box, but
there would be two 'interfaces'.
Any particular 'interface', may have multiple 'alternate' settings
(Although most devices only have 1 setting). If you configure an interface
to a non-default 'alternate' setting, you may have a completely new set of
endpoints available to you.
Unfortunately, it is not a simple thing to configure an alternate config
under the current Solaris USB framework.
Tips for Solaris 8 USB
(as of June 2002)
The following tips are all specific to the "current" solaris USB framework.
The Sun USB team has announced that there is a new USB framework coming
down the pike. No official date for it has been set, so it seems safe to
assume it will not be released for a few months.
Getting an endpoint
Currently with solaris 8, you have to use usb_parse_endpoint_descr() to get
an "endpoint descriptor". Once you have that, you can pass the descriptor
to usb_pipe_open() to open up a pipe to use. If you want a control pipe,
you pass in a NULL endpoint descriptor.
Note: the upcoming new solaris USB API does not use usb_parse_endpoint_descr().
You should read the comments in /usr/include/sys/usb/usbai.h, particularly
Data Transfer Management" section. Some critical
- "ALL data transfer[s] are asynchronous"
- Bulk input pipes must be prodded by usb_pipe_receive_bulk_data(),
after which the callback will be called when the data is ready.
- Isoc and intr pipes will automatically trigger the callback as soon
as any data is ready. No prodding required. But you will have had to
call usb_pipe_start_polling() already.
The same comment from above is still true:
"ALL data transfer[s] are asynchronous"
You first call the appropriate send function, and then wait for a
callback to trigger if you care about the result of the send.
- For Isoc endpoints, use usb_pipe_send_isoc_data()
- For Bulk endpoints, use usb_pipe_send_bulk_data()
- For Control endpoints, use usb_pipe_device_ctrl_send(). There
is actually a sync version of it, I guess because
control data isnt officially a "data transfer"
- Unfortunately, there is no official way to write through
an "out" interrupt pipe with the initial solaris USB framework.
Note: It appears that the "*bulk*" routines do byteswapping as appropriate.
However, the other ones (eg: xxx_ctrl_xxx) do not.
Written by:Philip Brown
Visit the Solaris driver pages
Or Search Bolthole.com