WWDC2001 Session 203
Transcript
Kind: captions
Language: en
good afternoon and welcome to the USB
overview session I'm Craig Keithley I'm
the USB and firewire technology manager
within Apple's Worldwide Developer
Relations organization and a pleased to
see you here today
this session will cover some of the
basics of usb on Mac OS 10 before I
bring up the engineers to have them do
the presentation I want to talk a little
bit about the things that we like about
USB in 10 and in general with our
digital hub strategy one of those things
is nature of powering devices over USB
and more importantly than powering
devices recharging devices so I brought
with me here today a new cable this is a
USB adapter cable for a palm 5 has a
sync button in it and it charges the
palm 5 you think about our iBook
commercial we're running where the
gentleman's sitting in the middle seat
and he's playing with all's neat devices
at 35,000 feet it wouldn't be too cool
if all those devices required a power
strip on the floor of the plane with a
hundred and 10 volt to 12 volt converter
to run all those devices so we really
want you to look very carefully at
powering your devices over USB and
charging them over USB some devices that
are good about this are things like the
zip drive some of the floppy drives they
receive power over the USB bus they
operate without the need for an AC
adapter this is a great way to go and if
you can charge them that would be even
better now as you know we've been doing
USB for about 4 years now we've got a
lot of experience in it we've got some
of the best engineers in the business
working on USB for Mac OS 10 we've made
great progress we know we have more to
get more distance to go on this so I
want to leave you with a couple of
thoughts with regard to helping us move
forward on USB on 10 the first one is
please use the bug reporting system we
do look at those bug reports very
seriously don't assume that we've seen a
bug report don't assume that if it's
happening to you we must have seen it
and we must be fixing it we want to have
those in the database we want to be
working on them we want to know about
them the other thought that I would
share with you is that
we are working very aggressively on
providing updates you've watched us
produce three updates in the last 58
days we will be doing more so if you get
your bug reports in there's a very good
chance we'll be able to move forward on
them so with that I'd like to bring up
Rhodes Halliwell and Dave Ferguson Dave
is the software engineering manager for
USB development on Mac os10
the ROS Halliwell is our lead engineer
on USB development thanks very much good
morning Thank You Craig
well what we're gonna talk about today
maybe there we go so what you're going
to learn in this session is we're going
to go over the USB hardware architecture
as delivered in Macintosh models that we
ship today I'll talk a little bit about
where the different ports go numbers of
controllers compatibility with different
controllers that sort of stuff we'll
talk about the driver architecture in
Mac OS 10 specifically how it fits in
with IO kit and and how that family fits
with other families we will talk about
converting your mac os9 drivers into ten
so obviously you have a lot of
experience developing mac OS 9 USB
drivers we have a lot of devices and a
lot of drivers and so I know that people
have things and they want to get them
converted over to OS 10 and so what's
the same what's different what do you
need to do to get started in doing that
we'll detail a little bit of the
differences between kernel mode and user
mode drivers and we'll talk about what
happens today when you have classic and
you have support for existing USB
drivers which USB devices can be
operated in classic how do they work how
does classic and native OS 10 drivers
work together and finally we'll do a
quick review of apples class drivers the
drivers that we deliver so you can
deliver USB products that don't have any
software component at all that you need
to use ur needs to install just drivers
that we bring so Universal Serial bus
Hardware has
included in every Macintosh model since
we introduced the iMac in August of 98
today
every single machine that we ship has
two independent USB buses both of those
are ohci open host controller interface
compatible our software is compatible
with ohci controllers so in fact in
addition to the two buses that we are
supplying it's also possible to install
install PCI cards or card bus cards that
have ohci compliant controllers and our
software will detect those cards and
support the USB bus on that now other
USB hardware that we have included with
every machine in addition to the two
independent buses we are also including
hubs in both our monitors as well as the
keyboards now the hubs that are in the
monitors are all self powered hubs they
provide more high power ports just like
the ports on the back of a machine and
the hubs that are in the keyboards are
bus powered hubs so they can only supply
the hundred milliamps of power and are
useful for some some bus powered devices
usually other self powered devices that
it's just more convenient to plug them
in right on the keyboard so controllers
mice and stuff attached to a keyboard
other high-powered devices we've made it
convenient to put ports on the back or
on the sides of of monitors so let's
talk about how the i/o USB family and
Mac os10 fits into the i/o kit family
architecture this slide shows basically
i/o kit as a large field with a whole
series of families we've denoted some of
these families with different colors
indicating the type of family they are
the i/o USB family is one of these on
the Left which is a transport family
it's one that actually transports data
over some type of bus so IO USB family
firewire family scuzzy family are all
capable of
transporting data over a specific bus
things such as the IO serial family the
scuzzy architecture family the audio
family don't necessarily have a specific
hardware component associated with them
they're responsible more for managing
and converting data to transport over
some other families transport mechanism
IO kit includes a lot more families than
this I'm just trying to give you a sense
of where USB fits into that family
architecture ok thank you Dave so we're
gonna talk a little bit about the i/o
kernel drivers stack what happens when
the system detects that USB is present
so at the very early stage of USB
initialization there is an i/o PCI
device that the system detects and the
PCI family is responsible for detecting
this fan this this device and that
device is the USB controller chip a the
USB driver is then matched against that
controller chip and the name of that the
class of that driver is IO USB
controller now this driver then
initializes the USB controller chip and
and and instantiates an IO USB device
this device represents the root hub
inside the controller chip so that USB
PCI device is then matched by i/o kit
and it loads another driver and the name
of that driver is the Apple USB hub
driver so this driver loads against any
hub in the system including the root hub
but in the case of the early
initialization of the root hub it then
scans the bus looking for USB devices so
let's say we have a pair of speakers
plugged into this bus
well the i/o USB controller can have
more than one child or client that it is
a provider for and so it instantiates
another kernel object c++ kernel object
the in i/o kit called that is an i/o USB
device representing these speakers
there's a driver inside the in inside
the system the
matches against this device because it's
a composite device and that driver sets
the configuration inside the device
which causes the interfaces to appear so
one of these interfaces is the audio
channel for this for these speakers and
so this IOUs B interface appears and IO
kit then matches a driver against it and
in this case that driver is the Apple
USB audio driver so this is just a quick
overview of the stack of the i/o kit
objects we will go into some more detail
today and we will go into even more
detail on this tomorrow now USB drivers
are not members of the USB family they
use the USB family for their transport
mechanism and so they are clients of the
USB family or in other words the USB
family objects are the providers for
these drivers so here for example is
that same audio driver and it's provider
is an i/o USB interface object but the
driver is itself subclassed
from the i/o audio device class which is
a subclass of i/o service io service
being the base class for all IO kit
objects and so this driver is a member
of the audio family and in turn this
driver may have its own clients for what
to do with this audio stream another
example would be the a hid interface
which then loads the hid driver which is
a member of the hid family we represent
this with these puzzle pieces because
there can be a different hid driver that
is a subclass of the i/o hid device
class which uses a different transport
mechanism than USB now how do the how
does the API for USB and Mac os10
compare with the API and Mac OS 9 well
many of the function names are similar
but in fact they they're the
API is vastly different in in the
respect that in nine you have a
parameter block interface whereas in 10
you have a series of C++ methods that
you call you know with C++ so it and and
and also in 10 in 9 all calls to the API
are asynchronous calls you must provide
a callback routine and everything
happens asynchronously in 10 there is a
capability for making synchronous calls
to the USB stack however you must be
careful about making these synchronous
calls because it is there is a potential
to deadlock the system finally in 9
everything is all memory buffers are
passed as held and locked memory buffers
whereas in 10 it's possible to pass
buffers using an i/o kit object class
called IO memory descriptor which we
will get into in a little more detail
now in the kernel the USB family
provides 3 basic object classes that
represent the the contents of a USB
device these three classes are IOUs B
device which is an encapsulation if you
will of the device descriptor inside the
physical device then there's the i/o USB
interface class this is an encapsulation
of the interface descriptor within a
particular configuration of the device
so if a configuration has 3 interface
descriptors within it there will be 3 io
USB interface objects which are created
to represent those 3 interface
descriptors finally there is the i/o USB
pipe object this object encapsulate the
the contents of an endpoint within an
interface descriptor and it also
provides the channel between the client
software and the endpoint on the device
from user space because Apple recommends
that that you write your drivers in user
space if at all possible we provide
access to these same objects but we do
them using the IO CF plug-in model that
is part of i/o kit and we have to
plug-in types that we provide in user
space the IO USB device interface and
the IO USB interface interface now these
names can become a mouthful the i/o kit
team decided to call these plugins
device interfaces and of course in USB
there is already the concept of a device
as in a device descriptor and an
interface as in an interface descriptor
and so we actually had device device
interfaces and interface device
interfaces and that got to be a little
much so we call them the i/o USB device
interface and the i/o USB interface
interface how do the memory buffers
compare well as I said before in Mac OS
9 when you passed a memory buffer to USB
because it was it needed to use DMA to
transfer the actual data you would have
to lock the memory and make sure that it
was physically held in resident and pass
a pointer to this memory in Mac OS 10
the this is handled with a concept
called an i/o memory descriptor io
memory descriptors are more flexible
than just straight memory buffers
because they can provide access to
memory that is not necessarily
contiguous a piece of the memory can be
over here and then the next piece of the
memory can be over here and then another
piece can be somewhere else and the
memory descriptor can describe that and
then the USB engine can then transfer
the data into into disjoint buffers also
if you are accessing to passing the
memory and from user space the memory
does not necessarily need to be wired
into the kernel address space in order
to be used these memory descriptors can
describe memory that is inaccessible
from the kernel directly but is excess
using DMA and this is a benefit because
wiring memory into kernel address space
is a very expensive operation and one
that we hope that to avoid at all costs
now user mode code that accesses USB
does in fact pass these buffers as
straight memory buffers just pointers
but within the kernel the memory
descriptors are used to manipulate them
and to get the physical address for the
DMA engine as I said before with OS 10
it's possible to use synchronous i/o as
opposed to having every call in the API
be asynchronous this means that you can
make a call that will block your thread
until the call completes if you are
writing a user land driver this is
something that is always safe to do you
make a synchronous call your thread
blocks and when the call completes your
thread picks up again if you are running
a kernel mode driver you must be careful
that this synchronous call does not
deadlock your thread and there are
specific guidelines to help do that and
we're learning more about how to
document that as we go along if you do
make asynchronous calls then there's two
methods for continuing the processing
once your call once your callback
routine is called within the kernel your
callback routine will be called
immediately upon the completion of the
routine and and your execution thread
will in fact pick up at your callback
routine once the processing is done it's
slightly different in user mode there is
no mechanism with Mac os10
and with i/o kit to make direct
callbacks from kernel run threads to
user threads and so what happens is a
mock message is posted on a port
the colonel side and then there's a user
thread that will check that port using
the CF run loop technology for that
callback ret message and trend and at
that point dispatch the callback routine
so how do drivers get matched and loaded
with Mac OS 10 well the first thing that
happens is when a device is plugged in
the hub driver that is controlling the
hub to which that device is attached
notice as the port turns it on does
typical USB enumeration things and
creates the i/o USB device based on the
information it finds in the device
descriptor it then tells i/o kit I have
I have this new device please find a
driver for it so first I oak it looks
through its entire table of drivers that
it knows about and it creates a pool of
drivers that are capable of driving an
i/o USB device object it then passes the
information from the i/o USB device
object into each of the into the USB
family with the information from the
driver and it says tell me what you
think about this driver running with
this device and the USB family does a
scoring system where the different
drivers are scored based on the criteria
specified by the USB common class
specification
this creates a ranked list and then the
in an i/o kit goes through the drivers
and can call the probe method such that
any driver in the list can say no I'm
not interested in controlling that
device so this is a three level matching
system and at the end there is an
ordered list of drivers with a ranking
ioq it then takes the top driver in that
ranking and says okay it's your device
and as long as that driver comes back
and says I got it it's mine then that's
it
if the driver comes back and says oh no
I changed my mind I'm not interested in
that device anymore then the next driver
and the list is tried so what happens
when a driver when a USB device is
removed do you unplug it
well the hub driver again notices that
the device has gone away and it is a
terminate message to the i/o USB device
object which in turn sends the terminate
message or sends a message to each of
its children including a driver and
potentially any i/o USB interface
objects which in turn send messages to
their children and so forth so that the
leaf node of the tree gets notified hey
it's time to go away it cleans up and
then that propagates back up so that
eventually the i/o USB device object
cleans up and goes away so if your
driver is the leaf node in this process
you get a message saying hey it's time
for you to stop doing any i/o because
your parent is about to go away the
driver then says ok closes the parent
terminates its its state machine and i/o
kit removes the driver from memory so
how do drivers if you will work from
user space Apple again recommends that
you write your USB Driver code to work
in user space however you have to be
aware that user space drivers which are
really just threads that run in user
space and are typically packaged as as
libraries but they but in in one sense
they will function just like
applications in the in in in that they
the matching has to you know they have
to there's no automatic matching for
them so these drivers do not compete
with the kernel drivers so if there is a
user space driver for a particular
device and a kernel mode driver for a
particular device the kernel mode driver
ends up winning the race and controlling
the device user space drivers can
code that's running demon code for
example that gets notified by i/o kit
whenever a new USB device appears in the
system however once again this
notification doesn't happen until after
the kernel drivers get a chance to
control the device and so sometimes it
may be necessary to create a dummy
driver in the kernel which claims the
device so that then later on some user
land code can take over that device so
if you are running in user code how do
you find the device you're interested in
well there are some i/o kit mat matching
io kit service calls that you use to
find your device the first one hears
here are some some IO kit calls the
first one is service matching says I
want to create a matching dictionary
that looks for any device in the kernel
whose type is IO USB device then it
calls IO service get matching services
and it passes in this matching
dictionary and i/o kit returns an
iterator of all the devices that it
found that match that criteria finally
the user code can create a while loop
that looks through all the devices of
this iterator and decide which one's it
is interested in controlling if any so
how do we share a device well Dave's
gonna talk about this okay
so let's talk a little bit about device
sharing now the IO kit model for using a
particular object down in the kernel
whether it's a USB interface or a USB
device object is that it's exclusive
access only one thing can be accessing
that particular object at a time the i/o
USB family enforces that by allowing
only one entity to open that at a time
however there are method
and mechanisms by which tasks or threads
can cooperatively share a device and as
we're all starting to develop drivers
and we're getting more user mode drivers
people are interested in how we do that
and I want to talk a little bit about
that the key is a message method that
your driver provides whether it's a user
mode driver or a kernel mode driver and
there are two specific messages that are
passed one is and this happens when you
have a particular device open one is a
message that says io message service is
requesting close so this says that
another entity is attempting to open
this device and it's requesting that the
entity that currently has it open please
close down now you don't have to close
down at that you can know that you have
IO active at the time and you don't want
to do that but if you are merely keeping
the device open let's say in the example
that it's modem and you're waiting for a
call to come in well the driver that's
waiting for a call to come in can go
ahead and close up because a call hasn't
come in and another entity would like to
use it to make an outgoing call so you
can close that and you can get
notifications whenever someone else
closes a particular object and a USB
device or a USB interface object the
other message that can come in while you
have the object open is the IO message
service is attempting open so this is
where you can find out that another
entity is trying to open you but he has
not requested that you close down he's
not requested to grab the interface he's
just tried to open it to see if it's
available in general a shared device
would want to close down in that
particular circumstance as well so
requesting closed is kind of a more
urgent request to close down attempting
open is your clue that someone else
would like to access that device and you
should close it if at all possible
now this sharing mechanism is is really
how we intend for user mode control
panels that want to set particular
states in a device
might get to that even though a
kernel-mode driver provides most of the
transport with the device the user mode
driver would attempt to open that thing
that that object and would do it with
the claim flag we were working on the
API to get that set up that generates
this services requesting close message
and that's how a driver knows now this
device sharing model also works with USB
in classic classic is nothing more than
a particular application that is being a
user mode driver okay for one particular
USB device object down in the kernel
let's talk about the classic side for a
moment and then we'll talk about how
classic uses Mac OS 10 classic presents
the entire mac OS 9.1 operating system
to applications that includes things
like USB driver our entire mac os9 USB
stack is living within the classic
environment if you have an existing
classic driver for a vendor specific
device classic can open that device
object using the user mode mechanism and
can make that device available just as
though it were plugged into an OHA eye
controller directly attached to classic
and the USB stack will do all of the
exact same enumeration discover a device
load a classic driver exactly the same
way it does in Mac OS 9 right right now
so a driver shouldn't see any difference
between how a device behaves within
classic and how it behaves in pure
native Mac OS 9.1 today classic classic
attempts to capture two different kinds
of devices the first is printer devices
and because we have the Print Center
inside of Mac OS 10 that has a USB
client and already knows to talk to USB
printing devices for things that have 10
native imaging
drivers available it's already available
for applications that want to print in
Mac OS 10 some applications such as
classic wouldn't have access to the Mac
os10
Print Center so we decided to make
printers available directly within
classic and we just use whatever driver
was available within classic whether it
be the Apple USB printer class driver
that we provide or whether it's a vendor
specific printer class driver we allow
that to load and match the same way it
always does so within a classic
application you use the chooser to
select which printer it is you want to
print to and and printing works by using
the classic USB emulation the other type
of device that classic will attempt to
claim and control our vendor specific
devices any vendor specific device that
wasn't claimed by a vendor specific OS
10 native driver
well it just defaults to going to the
classic user mode driver now this can be
a little tricky while you're trying to
develop your code because you might have
classic loaded and classic is loaded and
running so that you can run some some
legacy application and meanwhile you're
trying to do K mod load of of specific
drivers and classic keeps grabbing host
devices every time you plug it in
because because it grabs vendor specific
devices and printer devices classic is
migrating toward using the sharing model
the same one I just talked about right
here it's gonna use and support these
exact same messages so it's gonna play
fair with all the other user mode
drivers and all the other kernel mode
drivers as long as we all use this
sharing model things are gonna work
great
ok the Apple class drivers that we are
providing with Mac OS 10 is almost the
full complement of drivers that we're
providing on 9 currently the drivers
that we are providing or of course the
hub class driver and the HID class
driver for hid devices mice keyboards we
do have a new API available in Mac OS 10
that we did not have in
mac os9 called the hid manager and the
hid manager encapsulate a lot of the
same functionality that we had within
the hid library within Mac OS 9 point 1
so the hid library functionality has
sort of rolled into this new hid manager
API the hid manager in addition to
working with USB HID devices also works
with other hid devices that might be
attached to the system and actually
makes them kind of look like USB HID
devices it uses USBs hid reports and hid
report descriptors as a mechanism to
describe the data that comes from a
device so adb mice
you know if Mac OS 10 was running on a
machine that had ADB and an ADB Mouse
would actually show up in the hid
manager just like it were kind of a USB
device with an actual report descriptor
and reports and all of that information
the other driver that other drivers were
providing include the audio class driver
the audio class driver currently
supports stereo input output audio
classes one of the drivers that was
updated with the recent 1002 and 1003
updates included new USB audio class
drivers and there's more on the way from
the audio team those guys are working
really hard trying to get all the the
support for all the devices that are out
there we have a mass storage class
driver this does actually more than our
storage class driver in Mac OS 9 did the
storage class driver in 10 supports
optical media as well because the mass
storage team has abstracted the scuzzy
architecture model family and was one of
the families that we saw in the i/o kid
family it can actually support other
devices that are attached via USB as its
transport mechanism but actually are
communicated with scuzzy commands the
storage class guys are working on their
stuff too we were on a couple of things
that worked pretty well on mac OS 9
manual eject and stuff is on its way
communication devices this is the exact
same support for abstract control MA
idle modems you have that available in
Mac os10
just like you did in nine and of course
we have printing class support what we
had on Mac OS 9 was printing class
support for any imaging chooser type
driver and that included our laser
writer postscript driver for PostScript
printers we include exactly the same
functionality on OS 10 and it's possible
to write new Print Center imaging pieces
that plug in and still use our printing
class transport mechanism you just have
to worry about the imaging will help you
get the data to the printer okay that
about sums up our overview we have a few
few slides here with where you might
turn for more information in addition to
the URLs here you don't need to copy
those down they're available on a
specific page off of the Apple comm
website places that we would point you
to include the USB implementers forum
USB implementers forum contains the
actual specs for USB for the classes of
drivers that we've talked about ample
supporting it includes information about
upcoming classes I'm sure you're all
familiar with the getting documentation
off of there you can find Mac OS 10
developer information on
developer.apple.com slash Mac OS X and
USB information is available on
developer.android.com type of
information all we are really providing
is some example code and it
automatically installs in slash
developer slash examples I believe the
other thing that gets installed when you
install our SDK is the absolute latest
header file that you would need if
you're compiling a USB project now other
USB drivers one of the things we did in
our DDK is we separated out the actual
drivers that we used in OS 9 and made
them available as sample code well all
of the i/o USB family is available as
sample code inside the darwin project so
it's possible for you to take a look at
how any well practically all of our USB
drivers are available in darwin and all
of the source code to the family is in
darwin the USB team operates out of that
darwin deposit or repository live so
when we check in some new code or new
fixes or new changes they're actually
available in darwin almost immediately
and and you can check those out and see
what we're up to
we love bug reports that say in this
file on that line that line right there
is wrong so feel free to send those to
us okay other sessions that you might
want to know about at WWDC yesterday you
have the i/o kit update right after this
session we'll have the i/o kit storage
drivers there is a session on the image
capture framework tomorrow tomorrow
morning and of course our USB in-depth
is available tomorrow at 3:30 p.m. that
seems wrong I thought it was 2 o'clock
but anyway it's available tomorrow in
the Civic Auditorium which is across the
street finally we have our feedback
forum on Thursday an always popular
event we're looking forward to it okay
if you want to gonna contact somebody at
Apple Craig Keithley he's the guy he
does USB and firewire there's his email
address and we have a developer mailing
list where developers help each other
with questions and answers and the USB
team when it as time tries to provide a
little guidance there as well so it's a
good way to keep track of what's going
on with USB
you