Table of Contents
This is a brief overview of how to get a USB device driver written as rapidly as possible. Simtec Electronics have provided an example HID driver which can be used as a basis for other 3rd party proprietary module drivers and a radio application which may be used as a basis for application drivers. The terms of license are fairly broad. Simtec Electronics will not claim any interest in derivative works from this example code. Copyright is retained on the original driver source and Simtec Electronics reserve the right to develop this code as we see fit. While every precaution has been taken by Simtec Electronics to ensure the example code is as bug free as possible, no responsibility will be accepted for errors or omissions or consequential damages.
Probably the easiest to use and most tested interface is the C API. All our examples will use this API although all functionality is available through a set of SWI calls and drivers can be written in any language required. The provided RISC OS USB C API is intended for use with a C compiler. Acorn C compiler (tested with version 5.06) may be used to produce both application and module type driver. Current limitations at this time mean GCC cannot be used to produce module drivers.
The C library is provided as a set of header files and several AOF binary library files. These link objects have been compiled with both module and application link options and for debug and non-debug versions. In addition there are two further options, either fastlib or stdlib. These options are an attempt to reduce the calling overhead of function calls that ordinarily pass through the SWI vector a "fast call" method has been provided, to use this "fast call" all that is required is to ensure the USB library initialise is called (must be done in any case) and link against either the stdlib for SWI based calling or the fastlib for direct calling.
Drivers broadly fall into one of two categories.
If the driver is intended to be "long running" and possibly provide for an entire "class" of USB devices such as a HID driver for a keyboard and mouse. It should be written as a module (as the example driver is). This modules initialisation process will set up communications with the USB core using the messaging system and it will be informed of devices being plugged and unplugged on the bus as they occur.
If the driver is intended for "short term" use or a specific device it only has need to be started when a device is plugged in, such as an mp3 player, camera or a scanner, it may be written as an application.
The USB system provides two mechanisms for an application driver to obtain device information. The driver may be started by the USB system when a device is plugged in obtaining the attached device information from its command line, or it may obtain a list of connected devices which are unclaimed when it is run. See Chapter 3 for more details.
This type of driver is obviously only available when there are filesystems to load drivers from, typically after system boot, and are hence only useful for devices not needed to start a system. These driver will probably be application code, perhaps even wimp tasks and do not have the development constraints of a module (no fp etc.)
Application drivers are the simplest drivers to implement. The USB side of their implementation probably represents a small part of the total code that will be written. The general areas that need to be considered are:-
Locating a device is discussed in Chapter 3 support routines are provided for most operations a driver needs to perform, the suggested approach is that a driver should parse its command line using *usblib_parse_cmd_line(USBLib_ParseCmdLine (SWI &56340)) looking for a new device message and if that does not exist (driver not run by USB system) use the usb_devmgr_find_free(USBLib_DevMgrFindFree (SWI &56340)) calls to find and then claim the device. This simply obtains the new device message by either means and gives the driver writer the flexibility to have their driver started by the USB system if they require. The command line scanning may be omitted if required.
Once a device has been located the information in the message can be used to open pipes, and configure the device as required. Most drivers allocate several URBs at this point to use throughout the drivers lifetime, this is especially useful if the control pipe has been opened and the driver is likely to be sending a number of control messages.
The driver will then proceed to issue transactions as required using the pipes it opened during its initialisation phase. It has been noted that the waiting constructs cause some driver writers problems understanding their concept, please refer to Chapter 7 for more details on the waiting concept.
All resources including references must be suitably freed or dereferenced as appropriate. If this does not happen resources may be lost and become unavailable until the USB system is re-started. Care should be taken to release the device back into the unclaimed device pool and ensure all URBs are freed otherwise the driver will not be able to obtain the device for use a second time.