Mar 02 Cover Story
Volume Number: 18 (2002)
Issue Number: 03
Column Tag: Network Management
by John C. Welch
With all the hype about USB 2.0, I thought it would be a good idea to actually take a look at its protocol, its fundamental parts, and how it works. While USB 2.0 is not everything its backers insist that it is, (and nothing is ever as good as fans would have us believe), it is an improvement on the USB spec, and a way for companies to get higher data rates without having to separately develop for a different standard.
USB 2.0 Background
The original impetus for USB was the need for an easily configurable, expandable, fast interface. While the PC and the Mac both had many ways to attach devices, they all had drawbacks. Serial ports were slow, and difficult to configure; parallel ports were limited as to how many devices they could use. PS/2 was a one-device-per-port standard, and it wasn't dynamic; ADB was slow, etc. So Intel, and later others, devised Universal Serial Bus, or USB. USB is an auto-configuring serial bus that allows devices to connect at different speeds (1.5 and 12Mbps) without having to manually assign ids and without needing termination. It is able to (dis)connect without having to shut down the host device. A host device is required (although there is work being done to alleviate this in USB 2.0) so data transfers require host CPU interrupts. The problem with USB 1.X was that after a while, 12Mbps was too slow, especially for things like CD burners, digital cameras, and hard drives. So, USB 2.0 has added a third speed option, 480Mbps.
USB 2.0 also adds support for real-time data transfers, important for video conferencing; support for isochronous transfers, important for devices that need to have guaranteed bandwidth, such as video cameras; and support for mixed mode, or simultaneous asynchronous and isochronous transfers. Because of these new features, USB 2.0 can also support more device types than USB 1.X could.
The benefits for the end user have not changed. You still have hot - swappable devices, an easy to attach connector, 127 devices per USB channel, automatic driver setup, etc. But as I said, you get isochronous transfers, which are critical for audio and video applications. You also get better support for different packet sizes, error handling, and error recovery.
Like any other bus system, USB has both a physical and a logical topology that it follows. With USB, the physical topology is a tiered, or layered star(think of a star overlaid on a pyramid with specific layers, and that's the general layout.) This topology is limited to seven tiers, with certain tiers having limits as to the type of devices that can be used there. Within this tier, there are two basic types of devices, hubs and functions. Tier 1 is the host, and root hub, and that is the only device at that level. Tier 7 can only have functional devices. You can have a compound device that is both a hub and a function, but those occupy two tiers, with the hub one tier higher than the function. So, you cannot have compound devices at Tier 7. A hub provides attachment points to a USB bus, and a function actually does something, such as a mouse, or a hard drive.
With USB, like SCSI, you have a single host that controls all operations on the bus. Within USB, this is called the host controller, and can be a combination of hardware, software, and/or firmware. All host controllers have a root hub, which provides one or more attachment points, such as the USB ports on the back of your Mac.
USB has both a physical standard for the interfaces on the system, and an electrical standard that provides the signaling characteristics for the bus. In general, USB utilizes a four-wire cable, with two wires used for point-to-point signaling. Three data rates are used in USB:
- High, or 480Mbps in USB 2
- Full, or 12Mbps
- Low, or 1.5Mbps
Note that with USB 2, you can transmit full and lowspeed data between the host controller and the hub at the high speed rate, and then between the hub and the end device at either full (high?) or low speed, to minimize the impact of slower devices on faster ones. Lowspeed support is locked down to a minimal number of devices, such as mice, in order to avoid speed degradation on the bus. In addition to the two data lines on the bus, D- and D+, the other two lines carry power, (Vbus) and the ground, (GND).
USB 2 is a polled bus, with the Host Controller initiating all data transfers. Typically, bus transactions involve three packets, all initiated on a schedule by the Host Controller. The first packet, or ‘token packet', describes the type and direction of the transaction, the USB Device address, and the endpoint number. Data transfers from host to device, or from device to host. This information is used by the selected USB device to make sure that it is grabbing data that is intended for it. The source of the data transfer then sends a data packet, or indicates that it has no data. The final packet is then a handshake packet indicating the successful data transmission, or lack thereof. In the case of bus transactions between hubs and host controllers, the transfers involve four packets, and are used to handle data transfers between the host controller and full or low speed devices.
All attachments on a USB bus occur through hubs, which use status bits to report the attachment, or removal of a device to the host when the hub is polled. If the event is an attachment, then the host enables the port, and addresses the USB device via the control pipe at the default address. The host then assigns the device a unique address, and determines if the device is a hub, or a function. The host creates its end of the control pipe using the assigned USB address, and an endpoint of zero. At this time, the USB device also provides the information to completely describe itself, such as the USB standard it is using, the class of the device, and the device vendor. If the attached device was a hub with attached devices, then this happens once for each device on that hub. If the attached device is a function, then the software for that function handles attachment notifications. This is where you will get the notice that you need to go out and get a proper driver for your new USB doohickey.
When a device is detached, the hub disables that port, and sends a removal indication to the host. This is handled on the host by the appropriate software. If the removed device was a hub with attached devices, then the detachment for each of those devices must be handled as well.
The USB 2 spec sets up four basic data transfer types:
- Control: Used for device configuration, control, and similar types of data, such as attachment notifications
- Bulk Data: For large, bursty data types, with great flexibility in how the data is transmitted. Scanners or printers are examples of this kind of data. Error correction happens in hardware, and the amount of data can vary widely.
- Interrupt Data: For timely, but reliable data delivery, where human notice of the data is important, such as the cursor movements from your mouse. This is a limited - latency transfer type, and the speed is determined by the device. Explicit timing is not required, although if the data is interactive, that may pose time limitations.
- Isochronous Data: For data that needs a specific amount of reserved bandwidth, such as videoconferencing. This data is continuous, and real-time during all phases of data use, so timing related data is critical and explicit. Latency issues are resolved via buffering at the endpoints. This kind of data has less error correction, as things like retries will have a detrimental effect on data timing.
The first part of any USB system is the host, or the computer. This is the central entity for a USB implementation, and is involved with all aspects of USB functionality, such as bus access and data flow. There is only one host per USB, and each host has three major layers:
- USB Bus interface
- USB System
The bus interface handles the electrical and protocol layers. This is similar to the interface provided by USB devices, but the bus interface has additional duties imposed on the host of a USB system.
The USB System uses the Host Controller to manage data transfers between the host and USB devices. The actual interface between the USB System and the Host Controller depends on the Host Controller hardware. The USB System works with the host controller to perform translations between the USB clients and the USB interconnect, including various USB features such as protocol wrappers. The USB System is also the layer that handles USB resource management, including bandwidth and bus power, so that clients can access the USB. The USB System is itself made up of three components:
- Host Controller Driver
- USB Driver
- Host Software
The Host Controller Driver, or HCD, maps the various Host Controller implementations into the USB system, so that a client can communicate with its device, without having to know which Host Controller the device is connected to. The USB Driver, or USBD, provides the interface for client to device communications. There is an interface between the HCD and the USBD, know as the Host Controller Driver Interface, HCDI. This is defined by the operating system the Host Controller is running under, and is not directly available to clients.
The USBD also provides methods for data transfer, called I/O Request Packets, (IRP). This are a request to transport data across a specific USB pipe. In addition to this, the USBD gives clients an abstraction of USB devices for configuration and state management purposes. To do this, the USBD owns the default pipe, which is the connection that all USB devices are accessed through for control needs. This pipe is a logical communication between the USBD and the USB device abstraction. If an operating system provides non-USB software for the loading and configuration of device drivers, then those are used by the drivers, instead of the USBD interface.
The Client layer is the container for the software that directly interact with the USB hardware. This allows the USB system software to manage the client to device communications correctly, preventing the client from directly manipulating the hardware.
Generally, the host, and host layers deal with the following USB functions:
- Attachment and removal of USB devices
- Managing the flow of control data between the host and USB devices
- Managing the flow of non-control data between the host and USB devices
- Status and activity statistic collection
- Managing the electrical interface between the Host Controller and the USB devices, including power management.
There are two ways control information can be passed between a USB device and its host: in-band, or out-of-band. In-band means that the control information is intermixed with the data, whereas out-of-band signaling uses a separate pipe for control information. Every USB device has a pipe that is used for USB standard control flow, called the default pipe. This pipe is only used for standard control information. If the device requires any device-unique information, then it can use the default pipe for this as well. The device can also create additional pipes for specific communications that may not be a part of the standard USB specification. The USBD allows for the sharing of the default pipe with its clients, and provides access to any other control pipes associated with a given device.
As we stated earlier, there are four basic ways to transfer data on a USB: Control, Isochronously, Interrupt, and Bulk. Regardless of the type, all data transfers are managed by the Host Controller. Each device has an interface, or interfaces, that allow a client to communicate with it. Interfaces are made up of pipes that handle the actual data flow between the client and the device, via endpoints on the device. The pipes and interfaces are created by the USBD at the request of the Host Software, which also gives the Host Controller the needed service parameters for configuration requests.
Pipes, which are used for all data transfers on a USB have a number of characteristics based on data rate, is the data steady or sporadic, how long the data can be delayed prior to delivery, and if the lost of the data being transferred will be catastrophic or not. We'll go into more detail on pipes a bit later.
Host Controllers have to manage the various device states that occur on a USB. There are many possible states that a USB device can have, some visible to the USB and the host, some are only visible to the device. The visible states are:
- Attached. The most basic state, this determines if a device is physically on the USB or not. This state does not deal with any other states.
- Powered. A USB device can obtain power either through the USB, (Bus - powered), or via its own power supply, (Self - powered). One note here, even though a self-powered device can be plugged in and turned on, it is not considered to be in a Powered state until attached to the USB, and Vbus is applied. A device can support multiple powered configurations, depending on the power source. This allows devices to avoid configurations when bus powered that could cause damage to the USB or the host.
- Default. This state follows the powered state. Once power is applied, then the device must wait for a reset from the bus before responding to any commands. After the reset is received, then the device is usable. Post-reset, the device speed is determined. The device termination resistors determine if the device is low or full speed is used. If the device is capable of high - speed operation, then the decision as to whether it will operate at high speed is determined by the reset. If a high - speed device is operating in a full - speed environment, then it must reset correctly in that environment, and respond correctly to device and configuration requests, even if it cannot support all intended functionality at full - speed.
- Address. Immediately after the reset, the device is using a default address. Once the reset is complete, then the host assigns it a unique address, which is maintained if the device is suspended. Regardless of address, the device responds to any requests on its default pipe
- Configured. Once the addressing has been set, the device must be configured. The device receives a SetConfiguration() request, ,and responds with a non - zero value.
- Suspended. If the device has gone a specified period without seeing any bus traffic, then it goes into the Suspended state. In this stated, all addressing and configuration data is retained. In addition to this inactivity timeout, the device can also be suspended if the port it is attached to is disabled. Any activity on the device's bus causes it to exit the Suspended state. If the host has entered a suspended state, the device can request the host to wakeup via the use of remote wakeup signaling. This remote wakeup ability must be host configurable.
The overall state of the Host Controller is linked to the states of both the root hub and the USB, as any changes in the Host Controller and/or the attached devices have to be reflected in such a manner that both components stay in consistent states, as in when a resume event occurs following a system waking up from sleep.
Regardless of the function of the end device, all data across the USB is a serial bit stream, that is (de)serialized by the Serial Interface Engine, (SIE) in the Host Controller. To manage the flow of data on the USB, the Host Controller generates frames, (for full speed devices), and microframes, (for high speed devices). To create either, the Host Controller issues a Start Of Frame Token, or SOF. SOFs are issued on a regular basis whenever the Host Controller is in a normal operating state, every 125µsec for high speed devices and every 1msec for full speed devices. SOFs are generated regardless of bus activity, or lack thereof. If the Host Controller is about to enter a power - reduced state, then it will stop generating SOFs. The SOF token holds the highest priority access to the bus. To ensure that the bus is idle for SOF transmission, the USB hubs contain circuitry to isolate any active transmitters during the End Of (micro)Frame period. To track the current (micro)frame, the host uses two separate methods for full and high speed frames. Full speed frame numbers are at least eleven bits in length, and are incremented every 1msec, the rate of SOF transmission. The lower eleven bits of the frame number id included in each SOF. For high speed devices, the microframe numbers are at least fourteen bits, and increment every 125µsec. Bits three through thirteen are included in each SOF transmission, which means that the same SOF packet value is transmitted for eight consecutive microframes before the SOF packet value increments.
Regardless of speed, when a (micro)frame number is requested from the Host Controller, the number used is the current number at the time the request was fulfilled. The (micro)frame number returned by the host is a 32 - bit number whether the device is full or high speed. At the end of the (micro)frame, there is a quiet period, known as the End Of Frame, or EOF period. During the EOF, the Host Controller ceases transmission, and any transmissions scheduled for the (micro)frame that just passed are retired. If the Host controller was executing a transaction when the EOF starts, that transmission is terminated.
Transmission error handling is the host's responsibility on a USB. While there are many types of transmission errors on a USB, they are all handled in the same manner. Each time an error occurs for a given transmission, an error count is kept, and the transmission is tried again. If the transmission is successful, the error count is reset to zero. If the error count reaches three, then the transmission is retired by the host. In the case of high speed isochronous transfers, there is only one attempt at transmitting data, so no error count is kept.
There are also a number of software mechanisms that are used by the USB host components to allow it to interact efficiently with the USB devices. While there is no real hard division of labor between the host and device interfaces, one requirement for the host is that it supports multiple Host Controller implementations, as defined by the host computer's operating system. The purpose of the host and device interfaces is to allow for different levels of abstraction, while allowing the system to operate together according to the USB spec. Therefore, the HCD provides the abstractions for the Host Controller, and its view of data transfers, and the USBD provides the abstractions for the USB device(s), and their view of USB data transfers. The overall USB system acts as facilitator for these two parts, and their data transfers. Part of this includes things like buffer management and data speed synchronization.
One thing to remember is that when you are talking about software mechanisms, is that they are very dependant on the operating system of the host computer. Linux, Windows, Mac OS X, and Mac OS 9 all have differences in how they do things, and this extends to USB interactions. In any USB system, on any operating system, there are still basic tasks that need to be fulfilled. Depending on the operating system, the host handles these tasks, in others, the USB system handles them. For any operating system, the USB assumes the existence of a specialized client, called a hub driver, that acts as a central ‘clearinghouse' for the addition and removal of devices from a particular hub. When the hub driver receives notification of these events, it uses the host software, other USBD clients, and the operating system to recognize and configure the devices.
In the case of device attachment, the hub driver is notified by the physical hub that detects the change. The hub driver uses this hub information to get a device driver from the USBD, which sets up the default pipe for the device, and returns a device identifier to the hub driver. From here, there are three configurations that have to happen for the device to be ready for use. First, the Device Configuration. This sets up all the USB parameters for the device, and allocates all the USB host resources that are visible to the device. This is done by setting the configuration value for the device. A limited set of configuration changes/alternate settings are allowed without having to reconfigure the device. Once this step is done, the device is ready, as far as it's concerned.
The next step is the USB Configuration. This is because in order to actually create the USBD pipe that is ready for client use, additional information, not visible to the device has to be specified by the client. This is information such as the maximum amount of data the client can transfer per IRP, the maximum service interval for the client, the client notification ID, etc. These values are collectively known as the pipe's Policy, and are used to describe how the client uses the pipe.
The final step is the Function Configuration. Once the first two steps are done, the pipe is ready for use, as far as the USB is concerned. This last step is used for any vendor or class - specific setup the client may need to use the pipe. This is private data between the device and the client, and is not standardized by the USBD.
The Host Controller Driver
The HCD itself is an abstraction of the Host Controller data and the Host Controller's view of USB data transmission. The HCDI has the following requirements:
It has to provide abstractions of both the Host Controller hardware, and the data transfers by the Host Controller across the USB, as well as an abstraction for the (de)allocation of Host Controller resources to support guaranteed service to the USB devices. It also has to present the root hub and its behavior in accordance with the hub class definition. This means that the hub driver has to be able to interact with the root hub in the same way as it would for any other hub. Even though the root hub can be implemented in a combination of hardware and software, it has to be able to respond to the device default address, it has to return descriptor information, it has to support having its device address set etc., just like any other hub. The only difference is, with the root hub, since it is closely integrated with the Host Controller, may not require bus transactions for these functions. The HCD is the lowest tier in the USB software stack, and as such, has only one client, the USBD, which maps requests from many clients to the appropriate HCD, which may be managing many Host Controllers. The HCDI is not client accessible.
The USB Driver
The USBD is a collection of mechanisms that are used by operating system components, such as device drivers, to access USB devices. The USBD is the only access to a USB device, and USBD implementations are all operating system - specific. A single instance of the USBD directs access to the HCDs that connect to the Host Controller, and from the client's point of view, the USBD that the client connects to is managing all the USB devices attached to the USB. The USBD presents two types of software mechanisms to clients: command and pipe mechanisms. The command mechanism allow clients to configure and control USBD operations and USB devices, by providing all access to the device's default pipe. The pipe mechanisms allow a USBD client to manage device - specific data and control transfers, but do not allow a client to directly address the device's default pipe.
The specifics of USBD initialization are dependent on the operating system being used. When a USB is initialized, the management information for that USB is also created, and contains the default address device, and the default pipe used to communicate with a newly reset device. When a device is attached to the USB, it responds to a default address until the USB can assign it a unique address, and it's default pipe is made available to the hub driver. This occurs during device initialization.
The default pipes are managed by the USBD, and never accessed directly by clients, although they can be used to help fulfill client requests by various command mechanisms. Examples of default pipe data transfers are things like setting a device address. The USBD is directly responsible for allocation and managing appropriate buffering for these transfers. All other pipes are client pips and are managed by the USBD clients. All buffering and other management of client pipes are handled by the client. There are four types of client pipes, to handle the four types of data transfers we spoke about earlier, namely Isochronous, Interrupt, Bulk, and Control. Along with these four pipe types, there are three basic pipe mechanisms: Abort, for pipe abortion, Pipe Policy Management, and Queuing. These mechanisms in turn support certain basic capabilities, such as Configuration Services, Configuration Management, Initial Device Configuration, Device Configuration Modification Management, Device Removal, Power Control, Event Notification, Status Reporting, Error Recovery, and Remote Wakeup Device Management.
Finally, there are systems, Macs among them, that implement USB services before the operating system loads. This is so you can use Open Firmware with a USB keyboard. In these cases, as the operating system loads, the Host Controller provides a mechanism that disables this preboot access, and allows the operating system to gain control. Once the operating system gains control, it is responsible for fully configuring the USB. If the operating system has to pass control of the USB back to the preboot system, then the preboot system should treat this as a power up event.
The next USB component to look at are the devices themselves. Each device has three basic parts: The bus interface that handles packet I/O, the middle layer that routes data between the bus interface and the device endpoints, and the top layer that is the device functionality, such as a mouse or keyboard.
When a device is attached, or detached from a USB, the host uses bus enumeration to handle these changes. For example, when a device is attached to a powered port, you get these actions:
- The hub with the new device tells the host via the status change pipe. At this point, the device is Powered, but the port it is attached to is disabled.
- The host queries the hub to determine the precise nature of the change.
- Now the that the host has the port for the new device, it waits for at least 100msec to allow the insertion to complete, and the power at the device to be stable. The host then issues a port enable command, followed by a reset command to that port.
- The hub performs the actual port reset. Once this reset signal is released, the port is enabled. The USB device is in the Default state, and can draw no greater than 100mA from Vbus. All of the device's registers and states have been reset, and it answers on the default address.
- The host assigns a unique address to the device, and the device moves to the Address state.
- The host then reads the device descriptor to determine what the maximum data payload that the device's default pipe can handle is, then assigns the device a unique address.
- The host reads the configuration information for all of the device's configurations.
- Based on this information, and the purpose of the device, the host assigns a configuration value to the device. The device is now in the Configured state, and all the endpoints for this configuration are set. The device can now draw needed power from Vbus, and is ready for use.
When a device is detached, the host is notified by the hub. The host then disables the port the device had been attached to, updates its topological information, and releases the device's address.
To support the dynamic environment of the USB, a device can begin interacting with the USB almost as soon as it has returned an ACK following its initial setup, and there are various time limits to facilitate the different stages of device setup. Following a reset, the device has a 10msec interval before it is expected to start processing requests. This is considered a recovery period, also applicable to resuming operation following a suspend. After a recovery interval, of the device receives a request to set its address, it has to be able to complete this request within 50msec. Once the device has processed the set address command, it sends an acknowledgement back to the USB indicating that the device address was successfully set. At this point, there is another recovery interval of 2msec, following which the device must be able to respond to Setup packets sent to the new address.
If the device handles device requests that need a data stage transfer to the host, then the device must be able to return the first data packet to the host within 500msec of the first request. All subsequent packets must be returned within 500msec of the successful transmission of the previous packet. After returning the final data packet, the device must finish the status stage within 50msec of returning the final data packet.
If the device is handling device requests that need a data stage transfer to the device, then the USB has an upper limit of 5 seconds to process a command, although this is not a hard limit, and can change depending on need.
Since a high - speed device has to be able to operate at both high - and full - speeds, it has to be set for the speed of the USB, depending on bus speed limits. This is normally done as part of the reset processing. Once the device speed has been set, it doesn't change until the next time it is reset. The high - speed device must report to the USB any limitations in its functionality that may exist for a given speed. It does this during configuration by returning descriptors for its current operating speed. If need be, the USB can get descriptors for both modes, and set the device to the USB's limitation, or device use on that USB.
All USB devices respond to host requests on their default pipe via control transfers sent in a Setup packet, which is eight bytes in length. Each Setup packet has five fields that define the request, and its parameters. The first field is bmRequestType, and identifies the specific request parameters, such as direction of data transfer, the type of transfer, and the recipient of the transfer. bmRequestType is one byte long The next field, bRequest specifies the particular request, is one byte long, and is modified by the type information in bmRequestType. wValue, the third field, is two bytes long, and is used to pass a request - specific parameter to the device. The next field, wIndex, is similar in function to wValue, and is also two bytes long. The final field, wLength, is also two bytes long, and shows the length of the data that will be transferred during the second phase of the control transfer. Note that the data transferred may have a length that is less than wLength, but never greater.
As we saw earlier, USB devices respond to configuration information requests via descriptors. A descriptor is simply a way of storing device capability descriptions in an easy - to - retrieve manner, that can reuse parts of other configuration descriptions for that device, much like a database record can use similar information that may be contained in other records or fields. Each descriptor starts with a one byte field that contains the total number of bytes in the descriptor, followed by a one byte descriptor identifier. If appropriate, the descriptor can contain human - readable information in the form of strings. If the descriptor length value is less than the specification - defined length for that descriptor, then it is rejected by the host. If the descriptor is larger than the defined length, then the extra data is ignored.
If the descriptors are class or vendor - specific, then there are two ways for the device to deal with them. If thy use the standard descriptor format, then they are returned as a standard descriptor would be returned, and can be interleaved with standard descriptors. If they modify a standard descriptor, then they must follow that descriptor. If they use a non-standard format, then the descriptor request specifies the class/vendor - specific descriptor and index, to retrieve that descriptor from the device.
There are seven standard device descriptors, which can only be modified by modifying the USB specification, and are:
- Device. This descriptor gives general, global, non-configuration - specific information about the device. If the device is a high - speed device, and has different information for high and full - speed operations, it must also have a device_qualifier descriptor. If the device is capable of high-speed operation, then it returns a 2.0 as its version number. If the device is a full or low - speed only device, then it returns an error to a request for the device_qualifier descriptor.
- Device_qualifier. This descriptor contains the information about a high - speed device that will change if the device is operating at a different speed.
- Configuration. The configuration descriptor contains a specific configuration's information. So if a USB camera has different operational characteristics depending on the camera's settings, each of these gets its own configuration descriptor.
- Interface. This describes a specific interface within a given configuration, and a given configuration can have multiple interfaces, each with its own descriptor. The interface descriptor is always returned as part of a configuration descriptor, and cannot be accessed separately.
- Endpoint. This descriptor is for each endpoint within a given interface. Like the interface descriptor, it is returned as part of the configuration descriptor, and cannot be accessed separately.
- String. These descriptors are optional, and are UNICODE strings. They are used if there is a need for human - readable descriptors.
The third physical component of the USB spec is the hub. USB hubs are a critical part of the USB, and do much of the work involved in making USB as easy to use as it is. Hubs must deal with connection behavior, power management, device (dis)connection management, fault detection and recover, and support for high/full/low - speed devices. Hubs in a high - speed environment must also isolate the high - speed signaling from the full/low - speed signaling to ensure that both interoperate correctly.
There are three basic components to the USB hub. The first is the Hub Repeater, which manages connectivity between same - speed upstream and downstream ports. The repeater also handles the hub entering and leaving the suspend state, including remote wakeups. The next component is the Hub Controller which manages host access to the hub along with providing status and control. Finally the Transaction Translator handles split transactions, (Split transactions are, for example, a full - or low - speed transaction on a high speed hub that has low or full speed devices attached.) The speed of a device on a downstream port determines whether the port is connected to the Hub Repeater, or the Transaction Translator.
If the upstream port on the hub is attached to a full or low speed environment, any high - speed functionality is disabled. This also disables the transaction translator, and all ports are connected to the hub repeater. If the upstream port is attached to a high - speed environment, then the full/low - speed repeater is disabled, and the hub repeater is a high - speed repeater. If a full/low - speed device is attached, then the port must connect to the transaction translator.
For data traveling upstream, the connection is a line, in that one downstream port connects to the upstream port of the hub. If there are many hubs in line to the host, then each hub only connects a single downstream to upstream port. If the data is flowing downstream, then the transmission is more of a broadcast, whereby all active downstream ports on that hub get the data from the upstream port, regardless of what device the data is actually intended for. If the device isn't supposed to get the packet, then it discards the packet.
USB Bus Electro/Mechanical Characteristics.
The next thing to look at is the actual USB physical bus characteristics. USB 2's different operating modes have different mechanical and electrical requirements, and there is a nominal dividing line, with low speed, (1.5Mbps) on one side, and High/Full speed, (480/12Mbps) on the other. For example, High and Full speed both require a shielded cable with twisted pair wiring , whereas that cable is only recommended for low speed operation.
USB uses a keyed connector protocol, both for ease of use, and to minimize termination issues. There are two types of connectors, Series "A" and Series "B". Series "A" connectors are the familiar flat connectors that you see on the back of modern Macs, and are used for upstream, (towards the host system or hub), connections. Series "B" connectors are the smaller, square - looking connectors and are normally only used for downstream, (towards the device) connections. In any case, a Series "A" connector can only attach to a Series "A" receptacle, and the same holds true for Series "B". (you may be asking about devices that have a Series "A" receptacle requiring a cable with two Series "A" connectors. Remember that a device can also be a hub, and that hub connectors are Series "A" connectors. So things like keyboards that can be hubs and devices use Series "A" connectors, whereas a printer that is only a device would use the Series "B" connectors.)
USB cable consists of four conductors. Two are used for power, Vbus and GND, the other two are used for data, D+ and D-. Within the cable, the conductors are color coded as follows: Red=Vbus , Black=GND, Green=D+, White=D-. The pinout of USB connectors is standardized as well: 1=Vbus , 2=D-, 3=D+, 4=GND, and the cable shell acts as a shield and drain wire. There are three types of cables in the USB spec, standard detachable cable, high/full - speed captive cable, and low - speed captive cable. (In plain English, a captive cable is hardwired to the device, ala an Apple keyboard.)
Standard detachable cable has a Series "A" connector on the hub end and a Series "B" connector on the device end. These cables should only be used for high/full - speed devices, as they can exceed the length limitations for low speed devices. This cable must also meet impedance, signal pair propagation and delay requirements for high/full - speed devices. The GND conductor doesn't actually earth the device or hub, but provides a common ground reference between the up and downstream ports. The maximum cable length is limited by the voltage drop across the GND conductor.
High/full - speed captive cable is identical to standard detachable cable, except that one end is hardwired to the device, and that it can be used with low - speed devices as well as high/full - speed devices. If it is used with a low speed device, then the cable must meet all low - speed requirements.
Low - speed captive cable is identical in design to high/full - speed captive cable, but may only be used with low - speed devices. Any other cable designs are prohibited by the USB spec.
USB Electrical Characteristics
In addition to the bus electrical characteristics we just looked at, there are quite a few other electrical characteristics in USB, such as power distribution, signaling, and physical layer specifications. With the addition of high - speed mode in USB 2, there are some additional requirements that affect the electrical characteristics of USB. Things like the requirement that all USB 2 - compliant hubs support high - speed mode, any downstream transceiver must support all three modes, and that the cabling used support all three modes are examples of this.
The new 480Mbps data rates in USB 2 require new signaling and termination characteristics to enable reliable operation at these speeds. High speed cable is terminated on both ends with a resistance from each wire to ground. This resistance is set to one - half the overall differential impedance of the cable, which is 45 ohms, for a total differential termination of 90 ohms
When initiating a high - speed transmission, the transceiver starts an internal current source, derived from the positive supply voltage for the transceiver, and sends that current down either D+ or D- via a high - speed current switch. If the current is sent down the D+ line, then a J state is being signaled, and if the D- line is used, then a K state is signaled. Data encoding follows an NZRI scheme(NZRI is an encoding scheme where each time a ‘o' is sent, the value of the signal changes from low to high, and vice-versa. USB 2 uses NZRI with bit stuffing, which adds a ‘0' after any six consecutive ‘1's, to force a transitions, and aid with clock synchronization.) The actual voltage levels are determined by the magnitude of the current source, and the value of the termination resistors As stated before, the resistance from either D+ or D- to ground is 45 ohms, and the output voltage differential between lines is plus or minus 400mV at that resistance. The differential voltage is used to detect things like a bad connection, or that the device has been disconnected.
As far as actual signal levels go, in general, the difference between a ‘1' and a ‘0' is 200mV for differential systems. When in a J state, low speed connections are signaling a differential 1, and full speed connections are signaling a differential 0. For the K state, these are reversed.
In low/full - speed systems, the SOP is signaled at the origination port by driving both D+ and D- from the idle state to the K state. To signal the End of Packet, EOP, D+ and D- are driven to a J state, then to the Idle state, and the bus termination hold the bus in that state. In a high speed connection, the Idle state is when both D+ and D- are nominally at GND. The SOP is signaled by driving both data lines into a K state. The EOP and idle state are achieved by simply halting current flow into the data lines, and returning them to GND.
Another function of the USB electrical system is that of power distribution. As wit h ADB, and PS/2 even, the bus supplies power for devices to operate. Unlike the other two though, you can also have a self-powered device that doesn't need bus power, an important consideration when you are trying to hook up over a hundred devices on a single bus. Finally, there are also facilities to warn that a device needs too much power, and disable that device, without shutting down the whole bus, or worse yet, burning out any components.
To facilitate easier operation of the power distribution system, USB introduces the concept of a unit load. A unit load is a 100mA load on the bus. A device that only draws 100mA is said to use one unit load, and is a low power device. A device can draw up to 500mA, or five unit loads, and is then considered a high power device. All devices default to low-power, but can transition to high power, although that is under software control. The software has to make sure that going to high power will not damage the bus, before allowing that transition to happen, thereby avoiding some of the problems that an overloaded ADB bus could cause.
There are a number of both power source, and power consumption devices, including:
- Root port hubs. These attach directly to the USB Host Controller, and derive power from the same source as the host controller. If the hub is powered via AC or DC external power, then it must supply at least five unit loads to each port. If the hub is battery powered, then it can supply either one or five unit loads. A five unit load port is a high power port, and a one unit load port is a low power port.
- Bus - powered hubs. These draw all power from Vbus on the hub's upstream port. They can only draw up to one unit load on power up, and up to five following configuration. This is split amongst the hub, its ports, and any other hub functions. The ports on this hub are low power ports, and must maintain that current when the hub is in the Active, or the Suspend states. This type of hub can have five ports, one upstream, and four downstream. If more downstream ports are required, then the hub must be self-powered.
- Self - powered hubs. These do not use Vbus as a power source. This hub may draw a unit load from Vbus to keep the interface working if the rest of the hub is powered down. As with the root port hubs, if a self - powered hub is supplied by external AC or DC power, then all ports must be high power ports, if the hub is battery powered, then the ports may be high or low power ports.
- Low - power bus functions. All power comes from Vbus, and they can draw no more than one unit load.
- High - power functions. Uses Vbus as its power source. Draws up to one unit load on power up, and up to five unit loads following configuration.
- Self - powered function. No operating power from Vbus, but may use one unit load from Vbus to keep the interface working when the function is powered down.
To avoid problems in wrong - way power distribution, no device supplies power to Vbus on the upstream facing port.
USB Bus Protocol
Like any other networking protocol, USB has a protocol layer that defines packet layout, media access, etc. USB is a little-endian protocol, in that it sends data across the line starting with the least significant bit, and ending with the most significant bit. (Considering that USB was started by Intel, the largest supplier of little-endian CPUs, this is not surprising.) Byte - ordering is more important to lower layer functions than user - level applications, as the upper layers of the OSI model handle byte - order issues.
All packets begin with a SYNC field that is used to align the data with the local clock. The size of the SYNC field depends on the speed of the USB, with 8 bits being used for low/full speed and 32 bits used for high speed. This field is only used for synchronization. The last two bits of the field are used to identify the end of the sync field. The Start of Packet delimiter is also part of the Sync field.
Immediately after the SYNC field is the Packet Identifier Field, or PID. The PID is made up of a four - bit packet type, and a four - bit check field. The type field indicates the type and format of the packet, and the check field assists in the reliability of decoding the packet. Each bit in the check field is a complement of it's respective bit in the type field.
Addressing is done via two fields, function address and endpoint. Functions must always decode both fields, and a mismatch on either causes the packet to be ignored. Aliasing of either field is not permitted. The function address field specifies either the source or the destination of the data packet. The endpoint field is used when more than one endpoint per function is required.
The frame number field is eleven bits in size, and is incremented by the host on a per - frame basis. The maximum frame number is 7FFH, and the counter rolls over upon hitting this.
The data field can be anywhere from zero to 1024 bytes in size. Data within each byte is shifted out LSB first.
USB 2.0 uses two CRC checks, one for the token, and a second separate one for the data bits. The token CRC is five bits, the data CRC is sixteen bits. The token CRC does not cover the PID, which has its own check field.
USB Data Flow
Our final section deals with the data flow within USB 2.0 This is where all the various sections of the bus work together to get your device to operate cleanly with your Mac, PC, whatever.
The first aspect we have to look at here is the endpoint. The formal definition of a USB endpoint is that it is "a uniquely identifiable portion of a USB device that is the terminus of a communication flow between the host and device." Remember that each USB device can have multiple endpoints, all grouped together in a logical device. This logical device is what is given an address by the USB when it is attached and configured. Within the logical device, each endpoint has it's own unique identifier that is determined by the device. Each endpoint also has its direction of data flow determined by the device. The combination of logical device number, endpoint number, and directional flow ensures that every endpoint is able to be uniquely referenced. (This is logical, as you wouldn't want data for your USB printer sent to your keyboard.) Because all endpoints are simplex, the direction of data flow is able to be used to help reference that endpoint. (More simply put: Endpoints are either gozintas or gozoutas, not both.)
In addition to the other identifiers, the endpoint has other characteristics that help describe it and its capabilities, such as bus access frequency requirements, bandwidth requirements, error handling requirements, maximum packets size, and transfer types. All endpoints other than endpoint zero are in an unknown state until after device configuration, and cannot be handled until configuration happens.
Endpoint zero is used to implement a default control method to and from the device. The USB system software uses endpoint zero to initialize and manipulate the device as the default control pipe, which supplies access to the device configuration information, and allows for generic status and control access. The default control pipe supports control transfers, and is available once the device is attached, powered, and has received a bus reset.
Functions can have additional endpoints as needed, limited by the device speed. Low speed functions can only have two additional endpoints, whereas full speed endpoints can have an additional 30 endpoints, (15 input, 15 output.) These endpoints are unavailable until the device has finished configuration.
The next structure is the Pipe, which is the association between the endpoint on a device, and the host software. Pipes are how data moves between memory buffers on the host, and the device endpoints. There are two types of pipe communications, each mutually exclusive: Stream, or unstructured data flow through the pipe, and Message, or structured data flow through the pipe. Regardless of structure, or lack thereof, the USB doesn't interpret the data moving through the pipe(s).
In addition to data structure, pipes have some other characteristics, such as bus access and bandwidth usage, transfer types, and the characteristics of the endpoint the pipe is connected to. If the pipe is connecting two endpoint numbers zero, then it is known as the Default Control Pipe. This pipe is available after the bus reset, but prior to configuration, whereas other pipes are unavailable until after configuration. This is because the default control pipe is used to configure the device, and to determine the device identification. Once this is done, then the default control pipe can be used by the device specific software. However, the USB system software owns the default control pipe, and mediates its usage by other client software.
As we said before, there are both stream and message pipes in a USB. Stream pipes deliver unstructured data between endpoints. Data flows in one end and out of the other, and stream pipes are always unidirectional. Stream pipes interact with what the USB sees as a single client. If multiple clients are using a single stream pipe, then no synchronization is provided for those clients by the USB. Data flow in a stream pipe is sequential, in a FIFO method. Since stream pipes are unidirectional, they are bound to a single endpoint that is handling data in the appropriate direction. Stream pipes support bulk, isochronous, and interrupt transfer types.
As we said before, message pipes pass structured data. There is also a different method towards how the data is transferred. Instead of just jamming data down the pipe, a request is sent to the device from the host. Then the data transfer happens in the appropriate direction, followed by a status stage. This data flow procedure is the reason for the structuring of the data in the pipe, so that the different data types can be identified. Message pipes can be bidirectional, and the default control pipe is always a message pipe.
Since the device is only required to service a single message request at a time per message pipe, the USB system software ensures that multiple concurrent requests are not sent to the pipe. Multiple software clients on the host can make requests via the default control pipe, but they are sent to the device on a first - come, first served basis. Data flow during the data and status stages is determined by the device. A message pipe to a device request a single device endpoint number in both directions, and are used for the control transfer type.
We have previously stated that there are four data transfer types in a USB: Control, Isochronous, Interrupt, and Bulk. Let's take a look at these in more detail.
Control transfers allow access to different parts of a device. They are designed to support configuration - type commands, such as configuration and status types of communication between client software and the function it needs to access. These communications, done via message pipes, again, use the three part request/data/status model for data flow.
All USB devices have at least one control pipe, the default control pipe, but can have more if need be. The packets that travel via control transfers have four possible sizes, depending on the speed of the transfer: 8 bytes for low - speed transfers, 8, 16, 32, or 64 bytes for full - speed transfers, and 64 bytes for high - speed transfers. This size applies to the payloads of data packets, and is signaled by the endpoint via the device descriptor. Status packets are always 8 bytes.
Although control transfers can run as fast as the USB will let them, there is no way to guarantee a specific speed for a control transfer. Although the USB requires that part of each (micro)frame be available for control transfer usage, they are not allowed to take needed bandwidth from data transfers. If need be, the USB system software can also alter the speed of control transfers. As well, the total number of control transfer bandwidth usage is limited, to avoid control transfers stealing too much bandwidth.
The next transfer type in USB 2.0 is Isochronous, familiar to Mac users via FireWire. In USB 2.0, a request for an isochronous transfers gains the requester three features of that transfer, namely guaranteed access to USB bandwidth, including latency bounding, guaranteed data rats through the pipe as long as there is data to deliver, and no retrying of data delivery in case of error. (This may sound odd at first, but error recovery takes time, extra packets and bandwidth. This means that during error recovery, keeping the guaranteed bandwidth available is difficult, so error recovery is ignored.)
Isochronous data is transferred via a stream pipe, with no structure imposed on it by the USB. Since this is a stream pipe transfer, isochronous data flows are unidirectional as well. Maximum data payload sizes are established by the endpoints of an isochronous pipe within the limits of the bus speed for that pipe, (1023 bytes for full - speed, and 1024 bytes for high - speed.) During configuration, the USB system software tries to ensure there is sufficient bandwidth for the maximum data size of the transfer. If there is, only then is the configuration established.
Isochronous transfers are limited to full/high - speed USB implementations, and USB limits the percentage of a (micro)frame that can be used for isochronous transfers at 90% for full - speed transfers, and 80% for high - speed transfers. In general, hosts must not issue more than one transaction per (micro)frame, unless the endpoint is high - speed and high - bandwidth, which allows for multiple transactions per (micro)frame, and a maximum speed of 192Mbps. Due to limitations in the USB bus frequency and (micro)frame timing, no more than 151 full - speed one byte data payloads per frame, and no more than 193 one byte payloads per microframe for high - speed transfers.
To allow for guaranteed bandwidth in isochronous transfers, there is no error retransmission on the bus. This means that things like handshakes are not used either. Basically, it is assumed that all isochronous data transfers succeed.
The third type of data transfer is the Interrupt transfer. This is used for devices that don't need to send data often, but require bounded service periods for their data transfers. Characteristics of an interrupt transfer are a guaranteed maximum service period for the pipe, and a retry of transfer attempts for failed delivery during the next service period. Like isochronous transfers, interrupt transfers use stream pipes, and have no structure imposed on them by the USB. They are also unidirectional.
Data payload size limitations for interrupt transfers are 8 bytes for low speed transfers, 64 bytes for full - speed transfers, and 1024 bytes for high - speed transfers. As well, high - speed transfers can request two or three transactions per microframe. The maximum size in an interrupt transfer is determined during device configuration, and remains constant for the life of that configuration. If there is sufficient bus time for that data payload size in the assigned period, then the configuration is established.
Frame usage maximums for interrupt transfers are limited to 80% for high - speed and 90% for full/low - speed transfers. Per - frame one byte payloads are limited as follows: low: 10, full: 108, high: 134. Maximum data speed for high speed endpoints in an interrupt transfer is 192Mbps.
Bus access periods for interrupt transfers are determined by the speed of the endpoint. Low speed endpoint periods range from 10 to 255msec, full - speed transfers need from 1 to 255msec, and high - speed period times are based on the equation (2bInterval-1)x125 µs, where bInterval is a value from 1 to 16. The periods between access times will be no longer than determined by the configuration, but can be shorter, depending on bus needs. As well, the access period is only used to check for IRP packets from the software client. If the access time for an endpoint comes around, and there is no IRP packet, then the endpoint is not polled. This avoids the overhead of polling endpoints with no data transfer needs. Like isochronous transfers, the maximum data rate for a high - speed endpoint is 192Mbps.
The fourth transfer type is the Bulk transfer. This is for devices that need to move large amounts of data, but at irregular intervals, and need to be able to get as much bandwidth as possible. Characteristics of a bulk transfer include USB access on a bandwidth available basis, error retransmission, and guaranteed delivery of data, but no bandwidth or latency guarantees. Since the transfers are on a bandwidth available basis, the speed of the transfers is dependent on available bandwidth. As with Isochronous and interrupt transfers, bulk transfers use stream pipes, are unidirectional, and have no USB - imposed structure.
Packet sizes for bulk transfers are 8, 16, 32, or 64 bytes for full speed endpoints, and 512 bytes for high - speed endpoints. Low speed endpoints do not use bulk transfers. If a data payload is not exactly one of the usable sizes for the endpoint, there is no requirement for padding the data out to those sizes. This also applies to isochronous and interrupt transfers.
When an endpoint needs to use a bulk transfer, it cannot ‘reserve' bandwidth, ala isochronous, nor can it reserve an access time, ala interrupt. The USB notes the size of the transfer, the speed of the endpoint, and makes the best effort it can to move the bulk transfer data as fast as possible given the conditions on a specific bus. Essentially, bulk transfers get what is left over from interrupt and/or isochronous transfers. The ‘fairness' of this policy is determined by the Host Controller. Due to the way bulk transfers work, client software cannot, and should not assume any specific speeds or access times for this transfer type, nor should it assume any particular order with regard to control transfers.
Bus frequency and frame timing limit the data payloads for bulk transfers to less than 72 full - speed eight byte payloads and less than 14 high - speed 512 byte payloads. Regardless of payload size, bulk transfers do not guarantee that the payload will be delivered in any number of (micro)frames. Due to USB conditions, a transfer could be spread out across multiple (micro)frames, even if it is small enough to fit in a single (micro)frame. As with isochronous and interrupt transfers, maximum speed for a high -speed endpoint is 192Mbps. High - speed endpoints can have between one and three transactions per microframe to support high - bandwidth endpoints.
Regardless of the type of transfer, there is a great deal of management that occurs to ensure that the USB functions smoothly, and efficiently. To handle this task, there are a number of USB entities that shared the load of transfer management, mainly the client software, the USBD, and the HCD.
One of the critical tasks in bus management is obviously transfer management. To ensure that all transfers are serviced correctly requires that the various USB entities work in a coordinated fashion. The first of these entities is the client software, which determines what transfers need to be made with a given function. It makes use of the appropriate operating system interfaces to request IRPs, ensures the proper pipes are used for the various transfer types, and helps manage the requirements of the different transfer types. All requests made by client software are presented via the USBD interface.
Another component involved with transfer management is the USB Driver, which is involved with bus access mediation, primarily during device attachment and normal transfers. During attachment, the USBD is involved with making sure that a desired configuration will actually be able to function on a given bus. If the configuration can be used, then the USBD creates the appropriate pipes for the different transfer types, and deals with things like bandwidth allocation, etc. USBD characteristics are usually heavily OS - dependent.
The HCD ensures that all IRPs area tracked correctly, and that bus bandwidth and (micro)frame time maximums are never exceeded. The HCD maintains the transaction list for the various IRPs on a given pipe, and handles client notification of completed IRPs. The transaction list is simply a list of all outstanding transactions for a USB. Each entry in the list contains the transaction description items, such as data sizes, device address, endpoint numbers, etc.
The host controller uses the HCD's transaction list to create the appropriate transactions on the USB. The host controller also provides the reporting mechanism for transaction status tracking. The host controller ensures that various bus access rules are obeyed, such as timeouts, inter-packet timings, etc, and works with the HCD to determine if a new pipe can access the USB.
Another bus management issue is proper handling of Isochronous transfers. Remember that these transfers are time dependent, and have no error correction, so ensuring reliability is important. One of the key components in this is the device itself. It has to provide the device descriptors so that the isochronous transfers it will need can be set up correctly. Because there is no error retry in an isochronous transfer, both ends of the transfer must be both time and data - synchronized so that robust delivery of the data is achieved. Normally, this is done via a well - defined clock system.
Because USB is implemented on such a wide array of hardware and software, a single clock specification wouldn't work. Instead, USB defines a clock model that various systems can adhere to in the best way for that system. There are multiple clocks provided by the USB to help with this. The first is the Sample Clock, which determines the natural data rate of sample moving between the host's client software, and various functions. The Bus Clock is either a 1KHz clock on full - speed segments, or 8KHz clocks on high - speed segments. In a USB, the bus clock is usually a lower frequency than the sample clock. The third clock used is the Service Clock, and this is determined by the rate the client software runs at to service accumulated IRPs.
To ensure that a broad range of isochronous transfers can be handled, there are often multiple samples used so that the transfers aren't interrupted for every sample. The multiple samples are negotiated ahead of time, so that the host controller can set up the most appropriate one for use. Although the bus clock is intended to act as a master clock, real-time data needs make locking to this clock impossible. However, since the data on the bus is packetized, it is easy to just move one unit of data once per (micro)frame, as the (micro)frame clock is reasonably precise.
The USB also provides a frame work for isochronous devices that defines synchronization types, (such as asynchronous, with data rate feedback, Synchronous, locked to the USB SOF rate, and Adaptive, using feedback, or data rate information), methods for endpoints to provide data rate feedback, and connectivity requirements. Endpoints are classified here by their capability to synchronize their data rate to the date rate of the endpoint at the other end of the connection. The endpoints provide feedback by indicating, relative to the SOF frequency, what their data rates are.
If a device is asynchronous, it cannot be locked to either the SOF rate, or any of the USB clocks. Therefore, they clock at either a fixed data rate, one of a limited set of data rates, or a single, continuously programmable data rate. Asynchronous devices must report their programmatic capabilities during endpoint initialization. Their data rate is then locked to either an external clock, or a free-running internal clock outside of the usual three USB clocks. These devices still have to deal with data rate matching, but it is done elsewhere in the USB environment. The asynchronous devices carry their data rate as an implicit part of their sample rat, and must provide explicit feedback information to adaptive drivers.
Synchronous devices can have their clocks controlled via SOF synchronization. These endpoints slave their sample clocks to the 1ms SOF clock tick via a programmable phase - lock - loop, (PLL). Like asynchronous devices, synchronized endpoints can run at a single fixed data rate, one of a limited number of data rates, or a continuously programmable data rate.
Adaptive devices are the most flexible isochronous endpoints. They can send data at any rate in their operating range, and synchronize via constant communications on the bus. The data rate is embedded in the data stream, and can be adjusted on the fly during the transmission.
Well, there is a lot of information about USB here, and I haven't even come close to dealing with all of it. To get all of the information, including the source documents I used for this article, please go to http://www.usb.org/ There is a wealth of information there that is of use to anyone wanting a greater understanding of USB 2.0 While USB 2.0 is not nearly what the people hyping it say it is, (and what ever meets its own hype?), it is a very capable upgrade to a solid standard, and should be a very capable partner along with FireWire in making connecting devices to our Macs faster and easier.
Bibliography and References
As already mentioned, you may wish to include a bibliography at the end of your article, especially if you wish to cite work in the body of the article. Here is some typical bibliography format, to serve as a model:
Compaq, Hewlett-Packard, Intel, Lucent, Microsoft, NEC, Phillips. "Universal Serial Bus Specification Revision 2.0". April 27th, 2000.
John Welch email@example.com is the IT manager for the MIT Police department. He has over fifteen years of experience at making computers work. He specializes in figuring out ways in which to make the Mac do what nobody thinks it can, showing that the Mac is the superior administrative platform, and teaching others how to use it.