emUSB-Device
User Guide & Reference Manual
Document: UM09001
Software Version: 3.64.0
Document revision: 0
Introduction
This chapter will give a short introduction to emUSB-Device, including the supported USB classes and components.
Host and target requirements are covered as well.
Overview
This guide describes how to install, configure and use emUSB-Device. It also explains the internal structure of emUSB-Device.
emUSB-Device has been designed to work on any embedded system with a USB client controller. It can be used with USB 1.1, USB 2.0 or USB 3.0 devices.
The highest possible transfer rate on USB 2.0 full-speed (12 Mbit/s) devices is approximately 1.2 MB/s.
In USB 2.0 high-speed mode (480 MBit/s) transfer rates of approx. 42 MByte/s could be achieved.
USB 3.0 SuperSpeed (5 Gbit/s) is also supported.
It depends on the capabilities of the USB controller hardware which USB version and actual speed can be used on an embedded system.
emUSB-Device features
Key features of emUSB-Device are:
- High performance
- Can be used with or without an RTOS
- Easy to use
- Easy to port
- No custom USB host driver necessary
- Start / test application supplied
- Highly efficient, portable, and commented ANSI C source code
- Hardware abstraction layer allows rapid addition of support for new devices
emUSB-Device components
emUSB-Device consists of three layers: A driver for hardware access, the emUSB-Device core and at least a USB class driver or the bulk communication component.
The different available hardware drivers, the USB class drivers, and the bulk communication component are additional packages, which can be combined and ordered as
they fit to the requirements of your project. Normally, emUSB-Device consists of a driver that fits to the used hardware, the emUSB-Device core and at least one of the
USB class drivers.
Component | Description |
Bulk / Vendor | emUSB-Device vendor component. |
MSD | emUSB-Device Mass Storage Device class component. |
IP-over-USB | emUSB-Device IP-over-USB component. |
VirtualMSD | emUSB-Device VirtualMSD Component |
CDC-ACM | emUSB-Device Communication Device Class component. |
HID | emUSB-Device Human Interface Device Class component. |
MTP | emUSB-Device Media Transfer Protocol component. |
Printer | emUSB-Device Printer Class component. |
RNDIS | emUSB-Device RNDIS component. |
CDC-ECM | emUSB-Device CDC Ethernet Control Model component. |
CDC-NCM | emUSB-Device CDC Network Control Model component. |
UVC | emUSB-Device USB video class. |
Audio | emUSB-Device USB audio class. |
DFU | emUSB-Device Device Firmware Upgrade class. |
MIDI | emUSB-Device Musical Instrument Digital Interface class. |
CCID | emUSB-Device Smart Card Interface Device class. |
emUSB-Device-Core | The emUSB-Device core is the intrinsic USB stack. |
Driver | USB controller driver. |
emUSB-Device-Bulk
emUSB-Device-Bulk allows you to quickly and smoothly develop software for an
embedded device that communicates with a PC via USB. The communication is like a
single, high-speed, reliable channel (very similar to a TCP connection). This bidirectional channel, with built-in flow control,
allows the PC to send data to the embedded target, the embedded target to receive these bytes and reply with any number of bytes.
The PC is the USB host, the target is the USB client.
emUSB-Device-MSD
Purpose of emUSB-Device-MSD
Access the target device like an ordinary disk drive
emUSB-Device-MSD enables the use of an embedded target device as a USB mass storage device.
The target device can be simply plugged-in and used like an ordinary
disk drive, without the need to develop a driver for the host operating system.
This is possible because the mass storage class is one of the standard device classes,
defined by the USB Implementers Forum (USB IF).
Virtually every major operating system on the market supports these device classes out of the box.
No custom host drivers necessary
Every major OS already provides host drivers for USB mass storage devices, there is no need to implement your own.
The target device will be recognized as a mass storage device and can be accessed directly.
Plug and Play
Assuming the target system is a digital camera using emUSB-Device-MSD, videos or
photos taken by this camera can be conveniently accessed with the file system
explorer of the used operating system when the camera is connected to the computer.
Typical applications
Typical applications are:
- Digital camera
- USB stick
- MP3 Player
- DVD player
Any target with USB interface: easy access to configuration and data files
emUSB-Device-MSD features
Key features of emUSB-Device-MSD are:
- Can be used with RAM, parallel flash, serial flash or mechanical drives
- Support for full-speed (12 Mbit/s) and high-speed (480 Mbit/s) transfer rates
- OS-abstraction: Can be used with any RTOS, but no OS is required for MSD-only devices
How does it work?
Use file system support from host OS
A device which uses emUSB-Device-MSD will be recognized as a mass storage device
and can be used like an ordinary disk drive. If the device is unformatted when
plugged-in, the host operating system will ask you to format the device. Any file system provided by the host can be used.
Typically FAT is used, but other file systems such as NTFS are possible, too. If one of those file systems is used, the host is able
to read from and write to the device using the storage functions of the emUSB-Device MSD component,
which define unstructured read and write operations.
Thus, there is no need to develop extra file system code if the application only accesses
data on the target from the host side. This is typically the case for simple storage applications, such as USB memory sticks or ATA to USB bridges.
Provide file system code on the target if necessary
There are basically two types of MSD devices, one is where the devices does not need to access the storage (e.g. USB stick, external HDD).
The other type is where the device needs to write data onto the storage medium before it is accessed from a PC (e.g. data logger)
or read data from it after it has been written onto the storage medium by a PC (e.g. a mp3 player or a device which reads configuration files from the storage).
If you are using emUSB-Device-MSD you are most likely writing software for the former device type.
emUSB-Device-MSD does not offer file-level access to the storage medium, you need a file system to access the storage.
complex and time-consuming task and increases the time-to market. Thus we recommend the use of a commercial file system like emFile,
SEGGER’s file system for embedded applications.
emFile is a high performance library that is optimized for minimum memory consumption in RAM and ROM, high-speed and versatility.
It is written in ANSI C and runs on any CPU and on any media.
Refer to https://www.segger.com/emfile for more information about emFile.
emUSB-Device IP-over-USB
emUSB-Device IP-over-USB allows to run any IP-based protocol over USB.
This component combines the advantages of RNDIS and CDC-ECM and allows plug-and-play on any major host operating system.
Using the IP-over-USB technology in combination with a built in web server, the device can easily be accessed from any host (Windows, Linux, Mac) by simply typing the device name into the web browser.
Typical applications
Typical applications are:
- Headphones
- Printer
- Data logger
- Ethernet2USB adapter
emUSB-Device-VirtualMSD
The emUSB-Device-VirtualMSD component allows to easily stream files to and from USB devices. Once the USB device is connected to the host, files can be read or written to the application without the need for dedicated storage memory.
Typical applications
Typical applications are:
- Updating firmware (e.g. Handheld Terminal)
- Updating configuration files
emUSB-Device-CDC
emUSB-Device-CDC converts the target device into a serial communication device.
A target device running emUSB-Device-CDC is recognized by the host as a serial interface
(USB2COM, virtual COM port), without the need to install a special host driver,
because the communication device class is one of the standard device classes and
every major operating system already provides host drivers for those device classes.
All PC software using a COM port will work without modifications with this virtual COM port.
Typical applications
Typical applications are:
- Modem
- Telephone system
- Fax machine
emUSB-Device-HID
The Human Interface Device class (HID) is an abstract USB class protocol defined by the USB Implementers Forum.
This protocol was defined for handling devices that humans use to control the operation of computer systems.
An installation of a custom host USB driver is not necessary because the USB human
interface device class is standardized and every major OS already provides host drivers for it.
Typical applications
Typical applications are:
- Keyboard
- Mouse and similar pointing devices
- Gamepad
- Front-panel controls - for example, switches and buttons
- Bar-code reader
- Thermometer
- Voltmeter
- Low-speed JTAG emulator
- Uninterruptible power supply (UPS)
emUSB-Device-MTP
The Media Transfer Protocol (MTP) is a USB class protocol which can be used to transfer files to and from storage devices.
MTP is an alternative to MSD as it operates on a file level rather than on a storage sector level.
The advantage of MTP is the ability to access the storage medium from the host PC and from the device at the same time.
Because MTP works at the file level this also eliminates the risk of damaging the file
system when the communication to the host has been canceled unexpectedly (e.g. the cable was removed).
MTP is supported by most operating systems without the need to install third-party drivers.
Typical applications
Typical applications are:
- Digital camera
- USB stick
- MP3 Player
- DVD player
- Telephone
Any target with USB interface: easy access to configuration and data files.
emUSB-Device-Printer
emUSB-Device-Printer converts the target device into a printing device.
A target device running emUSB-Device-Printer is recognized by the host as a printer.
Unless the device identifies itself as a printer already recognized by the host PC, you must
install a driver to be able to communicate with the USB device.
Typical applications
Typical applications are:
- Laser/Inkjet printer
- CNC machine
emUSB-Device-RNDIS
emUSB-Device-RNDIS allows to create a virtual Ethernet adapter through which the
host PC can communicate with the device using the Internet protocol suite (TCP, UDP, FTP, HTTP, Telnet).
This allows the creation of USB based devices which can host a webserver or act as a telnet terminal or a FTP server.
emUSB-Device-RNDIS offer a unique customer experience and allows to save development and hardware cost by
e.g. using a website as a user interface instead of creating an application for every
major OS and by eliminating the Ethernet hardware components from your device.
Typical applications
Typical applications are:
- USB-Webserver
- USB-Terminal (e.g. Telnet)
- USB-FTP-Server
emUSB-Device-CDC-ECM
emUSB-Device-CDC-ECM allows to create a virtual Ethernet adapter through which
the host PC can communicate with the device using the Internet protocol suite (TCP, UDP, FTP, HTTP, Telnet).
This allows the creation of USB based devices which can host a webserver or act as a telnet terminal or a FTP server.
emUSB-Device-CDC-ECM offer a unique customer experience and allows to save development and hardware cost by e.g. using a website
as a user interface instead of creating an application for every major OS
and by eliminating the Ethernet hardware components from your device.
Typical applications
Typical applications are:
- USB-Webserver
- USB-Terminal (e.g. Telnet)
- USB-FTP-Server
Requirements
Target system
Hardware
The target system must have a USB controller. The memory requirements can be
found in the chapter Performance & resource usage.
In order to have the control when the device is enumerated by the host, a switchable
attach is necessary. This is a switchable pull-up connected to the D+ Line of USB.
Software
emUSB-Device is optimized to be used with embOS but works with any other supported RTOS or without an RTOS in a superloop.
For information regarding the OS integration refer to the chapter Target OS Interface.
Development environment (compiler)
The CPU used is of no importance; only an ANSI-compliant C compiler complying with
at least one of the following international standard is required:
- ISO/IEC 9899:1999 (C99)
- ISO/IEC 14882:1998 (C++)
A C++ compiler is not required, but can be used. The application program can therefore also be programmed in C++ if desired.
File structure
The following table shows the contents of the emUSB-Device root directory:
Directory | Contents |
Application | Contains the application programs. Depending on which stack is used, several files are available for each stack. Detailed information can be found in the corresponding chapter. |
BSP | Contains example hardware-specific configurations for different eval boards. |
Config | Contains configuration files (USB_Conf.h, USB_ConfigIO.c). |
Doc | Contains the emUSB-Device documentation. |
Inc | Contains include files. |
Sample | Contains operating systems dependent files which allows to run emUSB-Device with different RTOS’s. |
SEGGER | Contains generic routines from SEGGER. |
USB | Contains the emUSB-Device source code. |
Windows | Contains host specific applications (for Windows, Linux, MacOS) which can be used in conjunction with the device application samples. |
Multithreading
The emUSB target API is not generally thread safe. But it is allowed to handle different
endpoints in different tasks in parallel. Examples are:
- A task that performs all reads of data from the host while another task sends data to the host.
- Operating on different interfaces (e.g. a BULK and a CDC interface) in independent tasks.
This is a short introduction to USB. The fundamentals of USB are explained and links
to additional resources are given.
Information provided in this chapter is not required to use the software.
USB
Short Overview
The Universal Serial Bus (USB) is a bus architecture for connecting multiple peripherals to a host computer.
It is an industry standard — maintained by the USB Implementers Forum — and because of its many advantages it enjoys a huge industry-wide acceptance.
Over the years, a number of USB-capable peripherals appeared on the market, for example printers, keyboards, mice, digital cameras etc.
Among the top benefits of USB are:
- Excellent plug-and-play capabilities allow devices to be added to the host system without reboots (“hot-plug”).
Plugged-in devices are identified by the host and the appropriate drivers are loaded instantly.
- USB allows easy extensions of host systems without requiring host-internal extension cards.
- Device bandwidths may range from a few kB/s to hundreds of MB/s.
- A wide range of packet sizes and data transfer rates are supported.
- USB provides internal error handling. Together with the already mentioned hot-plug capability this greatly improves robustness.
- The provisions for powering connected devices dispense the need for extra power supplies for many low power devices.
- Several transfer modes are supported which ensures the wide applicability of USB.
These benefits did not only lead to broad market acceptance, but it also added several advantages, such as low costs of USB cables
and connectors or a wide range of USB stack implementations.
Last but not least, the major operating systems such as Microsoft Windows, Mac OS X, or Linux provide excellent USB support.
Important USB Standard Versions
USB 1.1 (September 1998)
This standard version supports isochronous and asynchronous data transfers.
It has dual speed data transfer of 1.5 Mbit/s for low-speed and 12 Mbit/s for full-speed devices.
The maximum cable length between host and device is five meters.
Up to 500 mA of electric current may be distributed to low power devices.
USB 2.0 (April 2000)
As all previous USB standards, USB 2.0 is fully forward and backward compatible.
Existing cables and connectors may be reused.
A new high-speed transfer speed of 480 Mbit/s (40 times faster than USB 1.1 at full-speed) was added.
USB 3.0 (November 2008)
As all previous USB standards, USB 3.0 is fully forward and backward compatible.
Existing cables and connectors may be reused but the new speed can only be used with new USB 3.0 cables and devices.
The new speed class is named USB Super-Speed, which offers a maximum rate of 5 Gbit/s.
USB 3.1 (July 2013)
As all previous USB standards, USB 3.1 is fully forward and backward compatible.
The new specification replaces the 3.0 standard and introduces new transfer speeds of up to 10 Gbit/s.
USB System Architecture
A USB system is composed of three parts - a host side, a device side and a physical bus.
The physical bus is represented by the USB cable and connects the host and the device.
The USB system architecture is asymmetric. Every single host can be connected to
multiple devices in a tree-like fashion using special hub devices. You can connect up
to 127 devices to a single host, but the count must include the hub devices as well.
A USB host consists of a USB host controller hardware and a layered software stack.
This host stack contains:
- A host controller driver (HCD) which provides the functionality of the host controller hardware.
- The USB Driver (USBD) Layer which implements the high level functions used by
USB device drivers in terms of the functionality provided by the HCD.
- The USB Device drivers which establish connections to USB devices. The driver
classes are also located here and provide generic access to certain types of
devices such as printers or mass storage devices.
USB Device
Two types of devices exist: hubs and functions. Hubs provide for additional USB attachment points.
Functions provide capabilities to the host and are able to transmit or receive data or control information over the USB bus.
Every peripheral USB device represents at least one function but may implement more than one function.
A USB printer for instance may provide file system like access in addition to printing.
In this guide we treat the term USB device as synonymous with functions and will not consider hubs.
Each USB device contains configuration information which describes its capabilities and resource requirements.
A USB device must be configured by the host before its functions can be used.
When a new device is connected for the first time, the host enumerates it, requests the configuration from the device,
and performs the actual configuration.
For example, if an embedded device uses emUSB-Device-MSD, the embedded device will appear as a USB mass storage device,
and the host OS provides the driver out of the box.
In general, there is no need to develop a custom driver to communicate with target devices that use one of the USB class protocols.
Descriptors
A device reports its attributes via descriptors. Descriptors are data structures with a standard defined format.
A USB device has one device descriptor which contains information applicable to the device and all of its configurations.
It also contains the number of configurations the device supports. For each configuration, a configuration
descriptor contains configuration-specific information.
The configuration descriptor also contains the number of interfaces provided by the configuration.
An interface groups the endpoints into logical units. Each interface descriptor contains information
about the number of endpoints. Each endpoint has its own endpoint descriptor which
states the endpoint’s address, transfer types etc.
As can be seen, the descriptors form a tree. The root is the device descriptor with n
configuration descriptors as children, each of which has m interface descriptors which
in turn have o endpoint descriptors each.
Transfer Types
The USB standard defines four transfer types: control, isochronous, interrupt, and bulk.
Control transfers are used in the setup phase. The application can select one of the other three transfer types.
For most embedded applications, bulk is the best choice because it allows the highest possible data rates.
Control transfers
Typically used for configuring a device when attached to the host. It may also be
used for other device-specific purposes, including control of other pipes on the device.
Interrupt transfers
Typically used by devices that need guaranteed quick responses (fixed latency).
Bulk transfers
Typically used by devices that generate or consume data in relatively large and bursty quantities.
Bulk transfer has wide dynamic latitude in transmission constraints.
It can use all remaining available bandwidth, but with no guarantees on bandwidth or latency.
Because the USB bus is normally not very busy, there is typically 90% or more of the bandwidth available for USB transfers.
Isochronous transfers
Typically used for applications which need guaranteed speed. Isochronous transfer offers a guaranteed bandwidth but with possible data loss. A typical use is for audio data which requires a constant data rate.
Unlike bulk, control or interrupt transfers isochronous transfers do not receive an “ACK” from the other side, therefore the sender does not know whether the data was received by the other side correctly. For applications where constant data rate is more important than data integrity (audio, video) the potential data loss does not pose an issue.
Setup phase / Enumeration
The host first needs to get information from the target, before the target can start
communicating with the host. This information is gathered in the initial setup phase.
The information is contained in the descriptors, which are in the configurable section
of the USB-MSD stack. The most important part of target device identification are the
Product and Vendor IDs. During the setup phase, the host also assigns an address to
the client. This part of the setup is called enumeration.
Product / Vendor IDs
The Product and Vendor IDs are necessary to identify the USB device. The Product ID
describes a specific device type and does not need to be unique between different devices of the same type.
USB host systems like Windows use the Product ID/Vendor ID combination to identify which drivers are needed.
For example: all our J-Link devices have the Vendor ID 0x1366 and Product ID 0x0105.
A Vendor and Product ID is necessary only when development of the product is finished;
during the development phase, the supplied Vendor and Product IDs can be used as samples.
Using the sample Vendor ID (0x8765) or the SEGGER Vendor ID in a finished product is not allowed.
Possible options to obtain a Vendor ID or Product ID are described in the chapter Vendor and Product ID.
Predefined device classes
The USB Implementers Forum has defined device classes for different purposes.
In general, every device class defines a protocol for a particular type of application such
as a mass storage device (MSD), human interface device (HID), etc.
Device classes provide a standardized way of communication between host and
device and typically work with a class driver which comes with the host operating system.
Using a predefined device class where applicable minimizes the amount of work to make a device usable on different host systems.
USB hardware analyzers
A variety of USB hardware analyzers are on the market with different capabilities.
If you are developing an application using emUSB-Device it should not be necessary
to have a USB analyzer, but we still recommend you do.
References
For additional information see the following documents:
- Universal Serial Bus Specification, Revision 2.0
- Universal Serial Bus Mass Storage Class Specification Overview, Rev 1.2
- UFI command specification: USB Mass Storage Class, UFI Command Specification, Rev 1.0
Getting started
The first step in getting emUSB-Device up and running is typically to compile it for
the target system and to run it in the target system. This chapter explains how to do this.
How to setup your target system
We assume that you are familiar with the tools you have selected for your project
(compiler, project manager, linker, etc.). You should therefore be able to add files,
add directories to the include search path, and so on.
In this document the Embedded Studio IDE is used for all examples and screenshots, but every other
ANSI C toolchain can also be used. It is also possible to use makefiles; in this case,
when we say “add to the project”, this translates into “add to the makefile”.
Procedure to follow
Integration of emUSB-Device is a relatively simple process, which consists of the
following steps:
- Take a running project for your target hardware.
- Add emUSB-Device files to the project.
- Add hardware dependent configuration to the project.
- Prepare and run the application.
Take a running project
The project to start with should include the setup for
basic hardware (e.g. CPU, PLL, DDR SDRAM) and initialization of the RTOS.
emUSB-Device is designed to be used
with embOS, SEGGER’s real-time operating system. We recommend to start with an
embOS sample project and include emUSB-Device into this project.
Add emUSB-Device files
Add all necessary source files from the USB folder to your project.
You may simply add all files and let the linker drop everything not needed
for your configuration. But there are some source files containing dependencies
to emFile or emNet. If you don’t have these middleware components, remove the
respective files from your project.
Add RTOS layer
Additionally add the RTOS interface layer to your project. Choose a file from the
folder Sample/USB/OS that matches your RTOS. For embOS use USB_OS_embOSv5.c.
There is also a file USB_OS_None.c containing a layer to be used for superloop
applications without an RTOS.
Configuring the include path
The include path is the path in which the compiler looks for include files. In cases
where the included files (typically header files, .h) do not reside in the same folder
as the C file to compile, an include path needs to be set. In order to build the project
with all added files, you will need to add the following directories to your include
path:
Configuring debugging output
While developing and testing emUSB-Device, we recommend to use the DEBUG configuration of
emUSB-Device. This is enabled by setting the preprocessor symbol DEBUG to 1 (or USB_DEBUG_LEVEL to 2).
The DEBUG configuration contains many additional run-time checks and generate debug output messages
which are very useful to identify problems that may occur during development.
In case of a fatal problem (e.g. an invalid configuration)
the program will end up in the function USB_OS_Panic() with a
appropriate error message that describes the cause of the problem. Once the application
is running correctly, DEBUG can be set to 0.
Add the file USB_ConfigIO.c found in the folder Config to your project
and configure it to match the message output method used by your debugging tools.
If possible use RTT.
To later compile a release configuration, which has a significantly smaller code footprint,
simply set the preprocessor symbol DEBUG (or USB_DEBUG_LEVEL) to 0.
Add hardware dependent configuration
To perform target hardware dependent runtime configuration, the emUSB-Device stack calls
a function named USBD_X_Config. Typical tasks that may be done inside this function are:
- Select an appropriate driver for the USB controller.
- Configure I/O pins of the MCU for USB.
- Configure PLL and clock divider necessary for USB operation.
- Install an interrupt service routine for USB.
Details can be found in Target USB Driver.
Sample configurations for popular evaluation boards are supplied
with the driver shipment. They can be found in files called
USB_Config_<TargetName>.c in the folders BSP/<BoardName>/Setup.
Add the appropriate configuration file to your project.
If there is no configuration file for your target hardware, take a file for a
similar hardware and modify it if necessary.
If the file needs modifications, we recommend to copy it into the directory Config
for easy updates to later versions of emUSB-Device.
Add BSP file
Some targets require CPU specific functions for initialization, mainly for installing
an interrupt service routine. They are contained in the file BSP_USB.c.
Sample BSP_USB.c files for popular evaluation boards are supplied
with the driver shipment. They can be found in the folders BSP/<BoardName>/Setup.
Add the appropriate BSP_USB.c file to your project.
If there is no BSP file for your target hardware, take a file for a
similar hardware and modify it if necessary.
If the file needs modifications, we recommend to copy it into the directory Config
for easy updates to later versions of emUSB-Device.
Note that a BSP_USB.c file is not always required, because for some target hardware
all runtime configuration is done in USB_X_Config.
Prepare and run the application
Choose a sample application from the folder Application and add it to your project.
For example, add USB_HID_Mouse.c as your application to your project.
Compile and run the application on the target hardware.
After connecting the USB cable to the target device, the mouse pointer should hop from left to right.
Updating emUSB-Device
If an existing project should be updated to a later emUSB-Device version, only files have to be replaced.
You should have received the emUSB-Device update as a zip file. Unzip this file to the location
of your choice and replace all emUSB-Device files in your project with the newer files from the
emUSB-Device update shipment.
In general, all files from the following directories have to be updated:
- USB
- Inc
- SEGGER
- Doc
- Sample/USB/OS
Some files may contain modification required for project specific customization.
These files should reside in the folder Config and must not be overwritten.
This includes:
- USB_Conf.h
- USB_ConfigIO.c
- BSP_USB.c
- USB_Config_<TargetName>.c
emUSB-Device Configuration
An application using emUSB-Device must contain a USB_DEVICE_INFO structure containing the device
identification information.
USB_DEVICE_INFO
Description
Device information that must be provided by the application via the function
USBD_SetDeviceInfo() before the USB stack is started using USBD_Start().
Is used during enumeration of the device by the host.
Type definition
typedef struct {
U16 VendorId;
U16 ProductId;
const char * sVendorName;
const char * sProductName;
const char * sSerialNumber;
} USB_DEVICE_INFO;
Structure members
Member | Description |
VendorId | Vendor ID. Uniquely identifies the vendor on a USB device. |
ProductId | Product ID. Uniquely identifies all USB devices of a vendor. |
sVendorName | Vendor name. ASCII string of up to 126 characters. |
sProductName | Description of the USB device. ASCII string of up to 126 characters. |
sSerialNumber | Serial number of the USB device (ASCII string). May be NULL if no serial number should be provided. |
Additional information
The Product ID in combination with the Vendor ID creates a worldwide unique identifier for the product model.
The Vendor ID is assigned by the USB Implementers Forum (https://www.usb.org). For tests,
the default number above (or pretty much any other number) can be used. However,
you may not bring a product to market without having been assigned your own Vendor ID.
For emUSB-Device-CDC: If you change this value, do not forget to make the
same change to the .inf file as described in section The .inf file.
Otherwise, the Windows host will be unable to locate the driver.
The manufacturer name, product name and serial number are used during the enumeration phase.
They together should give a detailed information about which device is connected to the host.
Note
The max string length cannot be more than 126 ANSI characters.
Note for MSD: In order to confirm to the USB bootability specification, the minimum
string length of the serial number must be 12 characters where each character is a
hexadecimal digit (’0’ though ’9’ or ’A’ through ’F’).
Example
static const USB_DEVICE_INFO _DeviceInfo = {
0x8765, // VendorId
0x1234, // ProductId
"Vendor", // VendorName
"Bulk device", // ProductName
"13245678" // SerialNumber
}
...
USBD_SetDeviceInfo(&_DeviceInfo);
...
USBD_Start();
This structure and functions are included in every example application and can be
used without modifications in the development phase of your application, but you
may not bring a product on the market without modifying the Vendor ID and Product
ID.
Ids | Description |
0x8765 | Example Vendor ID for all examples. Do not use this in real products! |
0x1240 | Example Product ID for all bulk samples. |
0x1234 | Example Product ID for deprecated bulk samples (using SEGGER Windows driver) |
0x1200 | Example Product ID for the MSD CD-ROM sample. |
0x1000 | Example Product ID for all MSD samples. |
0x1088 | Example Product ID for all UVC samples. |
0x1111 | Example Product ID for all CDC samples. |
0x1112 | Example Product ID for HID mouse sample. |
0x1114 | Example Product ID for the vendor specific HID sample. |
0x1115 | Example Product ID for HID keyboard sample. |
0x1310 | Example Product ID for the Audio Speaker sample. |
0x1311 | Example Product ID for the Audio Microphone sample. |
0x1312 | Example Product ID for the Audio Headset sample. |
0x1350 | Example Product ID for the MIDI sample. |
0x2114 | Example Product ID for the Printer class sample. |
0x3000 | Example Product ID for RNDIS sample. |
0x3003 | Example Product ID for ECM sample. |
0x3004 | Example Product ID for IP-over-USB sample. |
0x3005 | Example Product ID for NCM sample. |
Additional required configuration for emUSB-MSD
Refer to MSD Configuration for more information about the required additional configuration functions for emUSB-MSD.
Descriptors
All configuration descriptors are automatically generated by emUSB-Device and do not require configuration.
Some optional descriptors may be enabled by calling the following functions:
Compile-time configuration
emUSB-Device can be used without changing any of the compile-time switches. All
compile-time configuration switches are preconfigured with valid values which match the
requirements of most applications. An exception are the audio and video classes, which
require change some of the options in order to work properly, see Configuration requirements.
All compile-time switches and their default values
can be found in the file USB_ConfDefaults.h.
To change the default configuration of emUSB-Host compile-time switches
can be added to USB_Conf.h. Don’t change the USB_ConfDefaults.h file
for easy updates of emUSB-Device.
Compile-time switches for debugging
USB_DEBUG_LEVEL
Description
emUSB-Device can be configured to display debug messages and warnings
to locate an error or potential problems. This can be useful for debugging.
In a release (production) build of a target system, they are typically not required
and should be switches off.
To output the messages, emUSB-Host uses the logging routines contained
in USB_ConfigIO.c which can be customized.
USB_DEBUG_LEVEL can be set to the following values:
- 0 - Used for release builds. Includes no debug options.
- 1 - Used in debug builds to include support for “panic” checks.
- 2 - Used in debug builds to include warning, log messages and “panic” checks. This significantly increases the code size.
Definition
#define USB_DEBUG_LEVEL 0
USB_LOG_BUFFER_SIZE
Description
Maximum size of a debug / warning message (in characters) that can be output.
A buffer of this size is created on the stack when a message is output.
Definition
#define USB_LOG_BUFFER_SIZE 100
Use of standard C-library functions
emUSB-Device calls some functions from the standard C-library. If the standard C-library should not be used,
the following macros can be changed to call user defined functions instead:
#define USBH_MEMCPY memcpy
#define USBH_MEMSET memset
#define USBH_MEMCMP memcmp
#define USBH_MEMMOVE memmove
#define USBH_STRLEN strlen
#define USBH_STRCAT strcat
#define USBH_STRRCHR strrchr
#define USBH_STRNCPY strncpy
#define USBH_STRCMP strcmp
General USB configuration
USB_SUPPORT_TRANSFER_ISO
Description
Must be set to 1 if the USB stack shall support isochronous transfers
(e.g. for audio and video applications).
If set to 0, all code that handles isochronous transfers is disabled,
which may significantly reduce the code size of the USB stack.
Definition
#define USB_SUPPORT_TRANSFER_ISO 0
USB_SUPPORT_TEST_MODE
Description
USB test mode enable. This can be set to 1 to enable support for USB
high-speed test mode. It is disabled by default to reduce memory footprint
of the USB stack.
Definition
#define USB_SUPPORT_TEST_MODE 0
USB_NUM_EPS
Description
Maximum number of endpoints that can be used in the main stack.
A table is stored in static memory with USB_NUM_EPS entries, each
allocates 56 bytes.
Definition
#define USB_NUM_EPS 8u
USB_MAX_NUM_IF
Description
Maximum number of USB interfaces the device can support. Each USB class
has one or more interfaces. For a USB composite device USB_MAX_NUM_IF
must be ≥ the sum of the number of interfaces for all classes configured.
Information about all interfaces are stored into a table, which
allocates about USB_MAX_NUM_IF * 9 words in static memory (word = sizeof(void *)).
Definition
#define USB_MAX_NUM_IF 4u
USB_MAX_NUM_ALT_IF
Description
Maximum number of USB alternate settings the device can support. Some USB interfaces
may have alternate settings to select different operating modes / configurations.
USB_MAX_NUM_ALT_IF must be ≥ the sum of the number of all alternate settings of all interfaces
of all classes configured.
Information about all alternates settings are stored into a table, which
allocates about USB_MAX_NUM_ALT_IF * 10 words in static memory (word = sizeof(void *)).
Definition
#define USB_MAX_NUM_ALT_IF 2u
Number of interfaces / alternate settings for each USB class
USB class | Number of interfacses | Number of alternate settings |
Bulk / Vendor | 1 | usually 0, but may be configured to 1 |
CDC-ACM | 2 | 0 |
CDC-ECM | 2 | 1 |
CDC-NCM | 2 | 1 |
CCID | 1 | 0 |
HID | 1 | 0 |
Mass storage | 1 | 0 |
MTP | 1 | 0 |
Printer | 1 | 0 |
DFU | 0 | 1 |
MIDI | 2 | 0 |
RNDIS | 2 | 1 |
UVC | 2 | 1 |
Audio | 1 + Number of audio streams (IN/OUT) | At least one per audio stream, see Design of audio interfaces |
USB_DESC_BUFFER_SIZE
Description
Maximum size of a USB configuration descriptor. The configuration descriptor
consists of a header and the concatenation of configurations for all configured
USB classes. The configuration descriptors are small for most classes, but for the audio
or video class it may get large and require to increase the size of this buffer.
Definition
#define USB_DESC_BUFFER_SIZE 256
USBD_SUPPORT_PROFILE
Description
Enables USB API instrumentation for SystemView.
Definition
#define USBD_SUPPORT_PROFILE 0
USBD_OS_USE_USBD_X_INTERRUPT
Description
If set emUSB-Device will use the functions USBD_X_EnableInterrupt/USBD_X_DisableInterrupt
instead of disabling/enabling the interrupts globally. Those functions only disable/enable the USB interrupt.
The functions are MCU specific and must be defined in the corresponding USB_Config_*.c file.
Definition
#define USBD_OS_USE_USBD_X_INTERRUPT 0
USBD_OS_USE_ISR_FLAG
Description
Enable flag to indicate execution of USB interrupt.
May be needed by some RTOS layer in combination with USBD_OS_USE_USBD_X_INTERRUPT=1 (experimental).
Definition
#define USBD_OS_USE_ISR_FLAG 0
Host OS specifics
Windows registry
The Windows registry is a database which stores settings for the operating system. The relevant aspect of the Windows registry in regard to USB development is the fact that Windows stores information about connected USB devices into the registry. Normally Windows stores the Vendor and Product ID pair together with the USB configuration of that particular device in the registry. During USB development this can have negative effects because, if you, the developer, change the USB configuration of a device Windows will still have the old USB configuration saved in the registry. While the USB device is functioning perfectly fine the old registry entry can result in the device not being properly recognized by Windows.
This issue is especially prevalent when developing a USB Audio device.
Cleaning the Windows registry
Easiest is to use a tool such as Uwe Sieber’s “Device Cleanup Tool”: https://www.uwe-sieber.de/misc_tools_e.html
This tool allows any not connected devices to be removed from the registry.
Alternatively the registry can be cleaned by hand using the Windows registry editor.
USB Core
This chapter describes the basic functions of the USB Core.
Overview
This chapter describes the functions of the core layer of emUSB-Device. These functions are
required for all USB class drivers and the unclassified bulk communication component.
General information
To communicate with the host, the example applications include a USB-specific header USB.h.
This file contains API functions to communicate with the USB host through the USB Core driver.
Every application using USB Core must perform the following steps:
- Initialize the USB stack. To initialize the USB stack USBD() has to be called.
USBD_Init() performs the low-level initialization of the USB stack and calls USBD_X_Config() to add a driver to the USB stack.
- Add communication endpoints. You have to add the required endpoints with the
compatible transfer type for the desired interface before you can use any of the
USB class drivers or the unclassified bulk communication component.
For the emUSB-Device bulk component, refer to USB_BULK_INIT_DATA on page
for information about the initialization structure that is required when
you want to add a bulk interface.
For the emUSB-Device MSD component, refer to USB_MSD_INIT_DATA and USB_MSD_INST_DATA for information about
the initialization structures that are required when you want to add an MSD interface.
For the emUSB-Device CDC component, refer to USB_CDC_INIT_DATA
for information about the initialization structure that is required when
you want to add a CDC interface.
For the emUSB-Device HID component, refer to USB_HID_INIT_DATA
for information about the initialization structure that is required when
you want to add a HID interface.
- Provide device information using USBD_SetDeviceInfo() .
- Start the USB stack. Call USBD_Start() to start the USB stack.
Example applications for every supported USB class and the unclassified bulk component are supplied.
We recommend using one of these examples as a starting point for
your own application. All examples are supplied in the \Application\ directory.
Target API
This section describes the functions that can be used by the target application.
USB basic functions
USBD_GetState()
Description
Returns the state of the USB device.
Prototype
unsigned USBD_GetState(void);
Return value
A bitwise combination of the USB state flags:
USB_STAT_ATTACHED | Device is attached. (Note 1) |
USB_STAT_READY | Device is ready. (Note 2) |
USB_STAT_ADDRESSED | Device is addressed. (Note 3) |
USB_STAT_CONFIGURED | Device is configured. (Note 4) |
USB_STAT_SUSPENDED | Device is suspended. (Note 5) |
Additional information
A USB device has several possible states. Some of these states are visible to the USB
and the host, while others are internal to the USB device. Refer to Universal Serial
Bus Specification, Revision 2.0, Chapter 9 for detailed information.
Notes
(1) Attached in a USB-specification sense of the word does not mean that the device is physically
connected to the host via a USB cable, it only means that the pull-up resistor on the device
side is connected. The status can be “attached” regardless of whether the device is
connected to a host or not. This state can normally be ignored.
(2) Ready denotes the USB controller state, the controller is “ready” after a bus reset.
This state can normally be ignored.
(3) A device is in an addressed state after it receives a valid (non-zero) USB address from the USB host.
This state can normally be ignored.
(4) When a device is “configured” the enumeration of the device has been successfully
completed and the host can communicate with the device.
(5) Suspend is set when the device is physically disconnected from the host or when the USB host
suspends the connected device.
Mapping of the state value returned by USBD_GetState() to the USB states described in “Universal Serial Bus Specification Revision 2.0”
chapter 9.1:
Return value of USBD_GetState() | USB state |
0x10 = 10000B | Attached |
0x11 = 10001B | Powered + Suspended |
0x18 = 11000B | Default |
0x19 = 11001B | Default + Suspended |
0x1C = 11100B | Address |
0x1D = 11101B | Address + Suspended |
0x1E = 11110B | Configured |
0x1F = 11111B | Configured + Suspended |
Other value should not occur | |
USBD_GetSpeed()
Description
Returns the current connection speed.
Prototype
int USBD_GetSpeed(void);
Return value
USB_SPEED_NONE | Unknown speed. |
USB_SPEED_FS | Full-speed. |
USB_SPEED_HS | High-speed. |
USB_SPEED_SS | SuperSpeed. |
USBD_GetDeviceState()
Description
Returns the state of the USB device, set by the host
(except USB_DEVSTAT_SELF_POWERED, which is configured by the device, see USBD_SetMaxPower()).
Prototype
unsigned USBD_GetDeviceState(void);
Return value
A bitwise combination of the USB device state flags:
USB_DEVSTAT_SELF_POWERED | Device is self-powered. |
USB_DEVSTAT_REMOTE_WAKEUP_ALLOWED | Remote Wakeup is allowed. |
USB_DEVSTAT_U1_ENABLE | Link power state U1 is enabled (SuperSpeed only). |
USB_DEVSTAT_U2_ENABLE | Link power state U2 is enabled (SuperSpeed only). |
USB_DEVSTAT_LPM_ENABLE | Link power management is enabled (SuperSpeed only). |
USBD_Init()
Description
Initializes the USB device with its settings.
Prototype
void USBD_Init(void);
Description
Checks if the USB device is initialized and ready.
Prototype
char USBD_IsConfigured(void);
Return value
0 | USB device is not configured. |
1 | USB device is configured. |
USBD_Start()
Description
Starts the emUSB-Device Core.
Prototype
void USBD_Start(void);
Additional information
This function should be called after configuring USB Core. It initiates a hardware
attach and updates the endpoint configuration. When the USB cable is connected to
the device, the host will start enumeration of the device.
USBD_Stop()
Description
Stops the USB communication. This also makes sure that the device
is detached from the HOST.
Prototype
void USBD_Stop(void);
USBD_DeInit()
Description
De-initialize the complete USB stack.
Prototype
void USBD_DeInit(void);
Additional information
This function also calls USBD_Stop() internally.
USBD_GetVersion()
Description
Returns the version of the stack.
Prototype
U32 USBD_GetVersion(void);
Return value
Format: Mmmrr; e.g: 32401 is 3.24.1
USB configuration functions
USBD_AddDriver()
Description
Adds a USB device driver to the USB stack. This function should be called from within
USBD_X_Config() which is implemented in USB_Config_*.c.
Prototype
void USBD_AddDriver(const USB_HW_DRIVER * pDriver);
Parameters
Parameter | Description |
pDriver | Pointer to the driver API structure. |
Additional information
To add the driver, use USBD_AddDriver() with the identifier of the compatible driver.
Refer to the section “Available target USB drivers” in the USB.h header file for a list of supported devices
and their valid identifiers.
Example
/*********************************************************************
*
* USBD_X_Config
*/
void USBD_X_Config(void) {
BSP_USB_Init();
USB_DRIVER_LPC17xx_ConfigAddr(0x2008C000); // USB controller of LPC1788
// is located @ 0x2008C000
USBD_AddDriver(&USB_Driver_NXPLPC17xx);
USBD_SetISREnableFunc(_EnableISR, NULL, NULL);
}
USBD_SetISREnableFunc()
Description
Register function to enable USB interrupts.
Prototype
void USBD_SetISREnableFunc(USB_ENABLE_ISR_FUNC * pfEnableISR);
Parameters
Parameter | Description |
pfEnableISR | Pointer to the function to install the interrupt handler and enable the USB interrupt. |
Additional information
This function must be called within USBD_X_Config() function.
See Adding a driver to emUSB-Device.
The functions pointer prototype is defined as follows:
typedef void USB_ENABLE_ISR_FUNC (USB_ISR_HANDLER * pfISRHandler);
Example
See USBD_AddDriver().
USBD_SetAttachFunc()
Description
Sets a function to perform hardware-specific actions to attach USB.
Prototype
void USBD_SetAttachFunc(USB_ATTACH_FUNC * pfAttach);
Parameters
Parameter | Description |
pfAttach | Pointer to the attach function. |
Additional information
This function must be called within USBD_X_Config() function.
See Adding a driver to emUSB-Device.
The functions pointer prototypes are defined as follows:
typedef void USB_ATTACH_FUNC (void);
Example
See USBD_X_Config().
USBD_AddEP()
Description
Returns an endpoint “handle” that can be used for the desired USB interface.
Prototype
unsigned USBD_AddEP(U8 InDir,
U8 TransferType,
U16 Interval,
U8 * pBuffer,
unsigned BufferSize);
Parameters
Parameter | Description |
InDir | Specifies the direction of the desired endpoint. USB_DIR_IN USB_DIR_OUT |
TransferType | Specifies the transfer type of the endpoint. The following values are allowed: USB_TRANSFER_TYPE_BULK USB_TRANSFER_TYPE_INT ISO endpoints must be created using USBD_AddEPEx(). |
Interval | Specifies the interval measured in units of 125us (micro frames). This value should be zero for a bulk endpoint. |
pBuffer | Pointer to a buffer that is used for OUT-transactions. For IN-endpoints this parameter must be NULL. |
BufferSize | Size of the buffer (OUT endpoints only). Must be a multiple of the maximum packet size. |
Return value
> 0 | A valid endpoint handle is returned. |
= 0 | Error. |
Additional information
The Interval parameter specifies the frequency in which the endpoint should be
polled for information by the host. It must be specified in units of 125 us.
Depending on the actual speed of the device during enumeration, the USB stack
converts the interval to the correct value required for the endpoint descriptor
according to the USB specification (into milliseconds for low/full-speed, into 125 us
for high-speed).
For endpoints of type USB_TRANSFER_TYPE_BULK the value is ignored and should be set to 0.
This function must be called after USBD_Init() and before USBD_Start().
USBD_AddEPEx()
Description
Returns an endpoint “handle” that can be used for the desired USB interface.
Prototype
unsigned USBD_AddEPEx(const USB_ADD_EP_INFO * pInfo,
U8 * pBuffer,
unsigned BufferSize);
Parameters
Parameter | Description |
pInfo | Pointer to a structure of type USB_ADD_EP_INFO. |
pBuffer | Pointer to an endpoint buffer that is used for OUT-transactions. For IN-endpoints or ISO endpoints this parameter should be NULL. |
BufferSize | Size of the endpoint buffer (OUT endpoints only). Must be ≥ the maximum packet size of the endpoint. For IN-endpoints or ISO endpoints this parameter should be 0. |
Return value
> 0 | A valid endpoint handle is returned. |
= 0 | Error. |
Additional information
This function must be called after USBD_Init() and before USBD_Start().
USBD_SetDeviceInfo()
Description
Sets a all information used during device enumeration.
Prototype
void USBD_SetDeviceInfo(const USB_DEVICE_INFO * pDeviceInfo);
Parameters
Parameter | Description |
pDeviceInfo | Pointer to a structure containing the device information. Must point to static data that is not changed while the stack is running. |
Additional information
See USB_DEVICE_INFO for a description of the structure.
Example
See USB_DEVICE_INFO.
USBD_SetClassRequestHook()
Description
Sets a callback function that is called when a setup class request
is sent from the host to the specified interface index.
Prototype
void USBD_SetClassRequestHook(unsigned InterfaceNum,
USB_ON_CLASS_REQUEST * pfOnClassRequest);
Parameters
Parameter | Description |
InterfaceNum | Interface index that for setting the class request callback. |
pfOnClassRequest | Pointer to the callback. |
Additional information
Note that the callback will be called within an ISR, therefore it should never block.
If it is necessary to send data from the callback function through endpoint 0, use the
function USBD_WriteEP0FromISR().
USBD_SetVendorRequestHook()
Description
Sets a callback function that is called when a setup vendor request
is sent from the host to the specified interface index.
Prototype
void USBD_SetVendorRequestHook(unsigned InterfaceNum,
USB_ON_CLASS_REQUEST * pfOnVendorRequest);
Parameters
Parameter | Description |
InterfaceNum | Interface index that for setting the class request callback. |
pfOnVendorRequest | Pointer to the callback. |
Additional information
Note that the callback will be called within an ISR, therefore it should never block.
If it is necessary to send data from the callback function through endpoint 0, use the
function USBD_WriteEP0FromISR().
USBD_SetIsSelfPowered()
Description
Sets whether the device is self-powered or not.
Obsolete function, please use USBD_SetMaxPower().
Prototype
void USBD_SetIsSelfPowered(U8 IsSelfPowered);
Parameters
Parameter | Description |
IsSelfPowered | 0 - Device is not self-powered. 1 - Device is self-powered. |
Additional information
This function has to be called before USBD_Start(), as it will specify if the device is
self-powered or not. The default value is 0 (not self-powered).
USBD_SetMaxPower()
Description
Sets the maximum power consumption reported to the host during enumeration.
This function also sets whether the device is self-powered (MaxPower = 0) or not.
Prototype
void USBD_SetMaxPower(unsigned MaxPower);
Parameters
Parameter | Description |
MaxPower | Maximum power consumption of the device given in mA. MaxPower shall be in range between 0mA - 500mA, for SuperSpeed devices up to 900mA. |
Additional information
This function shall be called before USBD_Start(), as it will specify how much power
the device will consume from the host.
If this function is not called, a default value of 100 mA will be used.
USBD_SetOnEvent()
Description
Sets a callback function for an endpoint that will be called on every RX or TX event
for that endpoint.
Prototype
void USBD_SetOnEvent(unsigned EPIndex,
USB_EVENT_CALLBACK * pEventCb,
USB_EVENT_CALLBACK_FUNC * pfEventCb,
void * pContext);
Parameters
Parameter | Description |
EPIndex | Endpoint index returned by USBD_AddEP(). |
pEventCb | Pointer to a USB_EVENT_CALLBACK structure (will be initialized by this function). |
pfEventCb | Pointer to the callback routine that will be called on every event on the USB endpoint. |
pContext | A pointer which is used as parameter for the callback function. |
Additional information
The USB_EVENT_CALLBACK structure is private to the USB stack. It will be initialized by USBD_SetOnEvent().
The USB stack keeps track of all event callback functions using a linked list. The
USB_EVENT_CALLBACK structure will be included into this linked list and must reside
in static memory.
The callback function is called only, if a read or write operation was started for the endpoint using one
of the USBD_Read…() or USBD_Write…() functions.
Additional information
The callback function has the following prototype:
typedef void USB_EVENT_CALLBACK_FUNC(unsigned Events, void *pContext);
Parameter | Description |
Events | A bit mask indicating which events occurred on the endpoint. |
pContext | The pointer which was provided to the USBD_SetOnEvent() function. |
Note that the callback function will be called within an ISR, therefore it should never
block. The first parameter to the callback function will contain a bit mask for all
events that triggered the call:
Event | Description |
USB_EVENT_DATA_READ | Some data was received from the host on the endpoint. |
USB_EVENT_DATA_SEND | Some data was sent to the host, so that (part of) the user
write buffer may be reused by the application. |
USB_EVENT_DATA_ACKED | Some data was acknowledged by the host. |
USB_EVENT_READ_COMPLETE | The last read operation was completed. |
USB_EVENT_READ_ABORT | A read transfer was aborted. |
USB_EVENT_WRITE_ABORT | A write transfer was aborted. |
USB_EVENT_WRITE_COMPLETE | All write operations were completed. |
Example
// The callback function.
static void _OnEvent(unsigned Events, void *pContext) {
if ((Events & USB_EVENT_DATA_SEND) != 0 &&
// Check for last write transfer to be completed.
USBD_GetNumBytesRemToWrite(EPIndex) == 0) {
<.. prepare next data for writing..>
// Send next packet of data.
r = USBD_Write(EPIndex, &ac[0], 200, 0, -1);
if (r < 0) {
<.. error handling..>
}
}
}
// Main programm.
// Register callback function.
static USB_EVENT_CALLBACK _usb_callback;
USBD_SetOnEvent(EPIndex, &_usb_callback, _OnEvent, NULL);
// Send the first packet of data using an asynchronous write operation.
r = USBD_Write(EPIndex, &ac[0], 200, 0, -1);
if (r < 0) {
<.. error handling..>
}
<.. do anything else here while the whole data is send..>
USBD_RemoveOnEvent()
Description
Removes a callback function which was added via USBD_SetOnEvent from the callback list.
Prototype
void USBD_RemoveOnEvent( unsigned EPIndex,
const USB_EVENT_CALLBACK * pEventCb);
Parameters
Parameter | Description |
EPIndex | Endpoint index returned by USBD_AddEP(). |
pEventCb | Pointer to a USB_EVENT_CALLBACK structure which was used with USBD_SetOnEvent. |
USBD_SetOnRxEP0()
Description
Sets a callback when data are received in the data stage of
the setup request.
Prototype
void USBD_SetOnRxEP0(USB_ON_RX_FUNC * pfOnRx);
Parameters
Parameter | Description |
pfOnRx | Pointer to a function that should be called when receiving data other than setup packets on EP0. |
Additional information
Please note that this function can be called multiple times
from different classes in order to check the data.
Note that the callback will be called within an ISR, therefore it should never block.
If it is necessary to send data from the callback function through endpoint 0, use the
function USBD_WriteEP0FromISR().
USB_ON_RX_FUNC is defined as follows:
typedef void USB_ON_RX_FUNC(const U8 * pData, unsigned NumBytes);
USBD_SetOnRXHookEP()
Description
Sets a callback whenever data are received from a given
endpoint handle.
The callback function is called within the interrupt context and must not block.
Prototype
void USBD_SetOnRXHookEP(unsigned EPIndex,
USB_ON_RX_FUNC * pfOnRx);
Parameters
Parameter | Description |
EPIndex | Any valid endpoint handle > 0. |
pfOnRx | Pointer to the callback. |
USB_ON_RX_FUNC is defined as follows:
typedef void USB_ON_RX_FUNC(const U8 * pData, unsigned NumBytes);
USBD_SetOnSetup()
Description
Sets a callback function that is called when any setup request
is sent from the host.
Prototype
void USBD_SetOnSetup(USB_SETUP_HOOK * pHook,
USB_ON_SETUP * pfOnSetup);
Parameters
Parameter | Description |
pHook | Pointer to a USB_SETUP_HOOK structure (will be initialized by this function). |
pfOnSetup | Pointer to the callback function. |
Additional information
The USB_SETUP_HOOK structure is private to the USB stack. It will be initialized by USBD_SetOnSetup().
The USB stack keeps track of all setup callback functions using a linked list. The
USB_SETUP_HOOK structure will be included into this linked list and must reside in static memory.
Note that the callback will be called within an ISR, therefore it should never block.
If it is necessary to send data from the callback function through endpoint 0, use the
function USBD_WriteEP0FromISR().
USBD_SetOnSetupHook()
Description
Obsolete, use USBD_SetOnSetup().
Sets a callback function that is called when any setup request
is sent from the host.
Prototype
void USBD_SetOnSetupHook(unsigned InterfaceNum,
USB_ON_SETUP * pfOnSetup);
Parameters
Parameter | Description |
InterfaceNum | Interface index that for setting the setup request callback. |
pfOnSetup | Pointer to the callback function. |
Additional information
Note that the callback will be called within an ISR, therefore it should never block.
If it is necessary to send data from the callback function through endpoint 0, use the
function USBD_WriteEP0FromISR().
USBD_SetOnSOF()
Description
Installs a function that will be called, when a SOF was received from the host.
The callback function is called within the interrupt context and must not block.
Prototype
int USBD_SetOnSOF(void ( *pfSOFCallback)(void * pContext ),
U16 Interval,
void * pContext,
USB_SOF_CALLBACK_HOOK * pHook);
Parameters
Parameter | Description |
pfSOFCallback | Pointer to the callback function. |
Interval | Function will be called every time a number of ’Interval’ SOFs were received. |
pContext | A pointer which is used as parameter for the callback function. |
pHook | Pointer to a USB_SOF_CALLBACK_HOOK structure (will be initialized by this function). |
Return value
= 0 | Callback function successfully installed. |
≠ 0 | SOF callback not supported by the driver. |
Additional information
The USB_EVENT_CALLBACK structure is private to the USB stack. It will be initialized by USBD_SetOnEvent().
The USB stack keeps track of all event callback functions using a linked list. The
USB_EVENT_CALLBACK structure will be included into this linked list and must reside
in static memory.
USBD_RemoveOnSOF()
Description
Removes a callback function which was added via USBD_SetOnSOF() from the callback list.
Prototype
void USBD_RemoveOnSOF(const USB_SOF_CALLBACK_HOOK * pHook);
Parameters
USBD_WriteEP0FromISR()
Description
Write data to EP0 (control endpoint).
This function may be called in an interrupt context.
Prototype
void USBD_WriteEP0FromISR(const void * pData,
unsigned NumBytes,
char Send0PacketIfRequired);
Parameters
Parameter | Description |
pData | Data that should be written. |
NumBytes | Number of bytes to write. |
Send0PacketIfRequired | Specifies that a zero-length packet should be sent when the last data packet to the host is a multiple of MaxPacketSize. Normally MaxPacketSize for control mode transfer is 64 byte. |
USBD_EnableIAD()
Description
Enables combination of multi-interface device classes with single-interface classes or
other multi-interface classes.
Prototype
void USBD_EnableIAD(void);
Additional information
Simple device classes such as HID and MSD or BULK use only one interface descriptor
to describe the class. The interface descriptor also contains the device class code.
Multi-interface device classes, such as CDC, Audio, MIDI use more than one interface
descriptor to describe the class.
The device class code will then be written into the device descriptor. It may be possible
to add an interface which does not belong to a multi-interface class, but it may not be correctly
recognized by the host, this is not standardized and depends on the host.
In order to allow this, a new descriptor type was introduced:
IAD (Interface Association Descriptor), this descriptor will encapsulate the multi-interface
class into this IA descriptor, so that it will be seen as one single interface
and will then allow to add other device classes.
If you intend to use a multi-interface component with any other component, please call
USBD_EnableIAD() before adding the multi-interface component through USBD_*_Add().
USBD_SetCacheConfig()
Description
Configures cache related functionality that might be required by
the stack for cache handling in drivers.
Prototype
void USBD_SetCacheConfig(const SEGGER_CACHE_CONFIG * pConfig,
unsigned ConfSize);
Parameters
Parameter | Description |
pConfig | Pointer to an element of SEGGER_CACHE_CONFIG . |
ConfSize | Size of the passed structure in case library and header size of the structure differs. |
Additional information
This function has to called in USBD_X_Config().
This function replaces the legacy cache functions BSP_CACHE_CleanRange
and BSP_CACHE_InvalidateRange.
If you still want to use these routines please set USBD_USE_LEGACY_CACHE_ROUTINES
to 1 in your USB_Conf.h file.
USBD_RegisterSCHook()
Description
Sets a callback function that will be called on every state change of the USB device.
Prototype
int USBD_RegisterSCHook(USB_HOOK * pHook,
USB_STATE_CALLBACK_FUNC * pfStateCb,
void * pContext);
Parameters
Parameter | Description |
pHook | Pointer to a USB_HOOK structure (will be initialized by this function). |
pfStateCb | Pointer to the callback routine that will be called on every state change. |
pContext | A pointer which is used as parameter for the callback function. |
Return value
0 | OK. |
1 | Error, specified hook already exists. |
Additional information
The USB_HOOK structure is private to the USB stack. It will be initialized by USBD_RegisterSCHook().
The USB stack keeps track of all state change callback functions using a linked list. The
USB_HOOK structure will be included into this linked list and must reside
in static memory.
Note that the callback function will be called within an ISR, therefore it should never block.
Example
// The callback function.
static void _OnStateChange(void *pContext, U8 NewState) {
if ((NewState & (USB_STAT_CONFIGURED | USB_STAT_SUSPENDED)) == USB_STAT_CONFIGURED) {
// Device is enumerated
} else {
// Device not enumerated
}
}
// Main programm.
static USB_HOOK Hook;
USBD_Init();
...
USBD_RegisterSCHook(&Hook, _OnStateChange, NULL);
...
USBD_Start();
USBD_AssignMemory()
Description
Assigns an area of RAM to be used for the endpoint buffers and
transfer descriptors by the USB driver. This function should be called
from within the USBD_X_Config() function. Not all drivers support this function.
If the driver uses DMA, the USB controller must have DMA access to this area.
For some drivers, the memory should be aligned to a given boundary.
If not aligned, the driver will increase the start address and reduce the size of
the area to achieve proper alignment. This results in wasting of RAM
and may cause the driver to run out of memory.
Prototype
void USBD_AssignMemory(void * pMem,
U32 MemSize);
Parameters
Parameter | Description |
pMem | Pointer to the start of the RAM area to be used by the driver. |
MemSize | Size of the RAM area in bytes. |
Additional information
If the memory is not sufficient for the class and endpoint configuration,
the USB driver will run into the USB_OS_Panic() function during initialization,
if compiled for DEBUG mode (USB_DEBUG_LEVEL > 0).
After successful initialization, the driver will usually issue a
USB_LOG() message to report, how many bytes of the assigned memory are not
used. The size of the memory area may then be adjusted.
Information how to calculate the size of the endpoint buffer memory and about any alignment requirements
can be found in Device driver specifics.
USBD_UseV210()
Description
Enable use of USB V2.10 specification revision. Must be called in USBD_X_Config().
It enables providing a BOS descriptor to the host and also enables
link power management (LPM), if supported by the driver and the USB controller.
Prototype
void USBD_UseV210(void);
USBD_SetBESLValues()
Description
Set recommended BESL (Best Effort Service Latency) values to be used in the BOS descriptor
when using LPM (Link Power Management).
See “Errata for USB 2.0 ECN: Link Power Management (LPM) - 7/2007” from usb.org for
an explanation of these values.
Calling this function has no effect, if LPM is not enabled (see USBD_UseV210()) or
not supported by the driver or USB controller.
Prototype
void USBD_SetBESLValues(int BaselineBESL,
int DeepBESL);
Parameters
Parameter | Description |
BaselineBESL | Recommended Baseline BESL value. Must be in range -1 to 15. A value of -1 means, no BESL value is stored in the BOS descriptor (the default). Values of 0,1,…,14,15 specify a BESL of 125us,150us,…,9000us,10000us respectively (see LPM document from usb.org). |
DeepBESL | Recommended Deep BESL value. Must be in range -1 to 15 (see above). |
USBD_SetOnLPMChange()
Description
Sets a call back to report LPM transition on the USB lines (L0 <-> L1).
Prototype
void USBD_SetOnLPMChange(USB_ON_LPM_CHANGE * pfOnLPMChange);
Parameters
Parameter | Description |
pfOnLPMChange | Pointer to callback. |
USBD_SetLPMResponse()
Description
Defines the behavior of the device on LPM requests from the host.
Calling this function has no effect, if LPM is not enabled (see USBD_UseV210()) or
not supported by the driver or USB controller.
Prototype
void USBD_SetLPMResponse(U8 Response);
Parameters
Parameter | Description |
Response | 0 - LPM requests are rejected (NYET). 1 - LPM requests are acknowledged. |
USBD_EnableSuperSpeed()
Description
Enable SuperSpeed in the USB stack. Must be called in USBD_X_Config().
If the USB driver or USB controller does not support SuperSpeed,
calling this function has no effect.
Prototype
void USBD_EnableSuperSpeed(void);
USBD_SetWebUSBInfo()
Description
For WebUSB capable USB devices this function may be called before USBD_Start()
to enable WebUSB specific descriptors. This function can be used only, if the
USB controller supports USB 2.1 compatibility, especially link power management (LPM).
Prototype
void USBD_SetWebUSBInfo(const USB_WEBUSB_INFO * pWebUSBInfo);
Parameters
Parameter | Description |
pWebUSBInfo | Pointer to a structure containing the device information. Must point to static data that is not changed while the stack is running. |
USBD_SetCheckAddress()
Description
Installs a function that checks if an address can be used for DMA transfers.
Installed function must return 0, if DMA access is allowed for the given address,
any value ≠ 0 otherwise.
Prototype
void USBD_SetCheckAddress(USB_CHECK_ADDRESS_FUNC * pfCheckValidDMAAddress);
Parameters
Parameter | Description |
pfCheckValidDMAAddress | Pointer to the function. |
Additional information
If the function reports a memory region not valid for DMA, the driver uses a temporary
transfer buffer to copy data to and from this area.
USBD_SetGetStringHook()
Description
Sets a call to determine the string of a specified string index.
Prototype
void USBD_SetGetStringHook(USB_GET_STRING_DESC_HOOK * pHook,
USB_GET_STRING_FUNC * pfOnGetString);
Parameters
Parameter | Description |
pHook | Pointer to static USB_GET_STRING_DESC_HOOK structure. |
pfOnGetString | Pointer to GetString callback. |
Additional information
The USB_GET_STRING_DESC_HOOK structure is private to the USB stack. It will be initialized by USBD_SetGetStringHook().
The USB stack keeps track of all ’GetString’ callback functions using a linked list. The
USB_GET_STRING_DESC_HOOK structure will be included into this linked list and must reside in static memory.
USB I/O functions
USBD_Read()
Description
Reads data from the host.
Prototype
int USBD_Read(unsigned EPOut,
void * pData,
unsigned NumBytesReq,
unsigned Timeout);
Parameters
Parameter | Description |
EPOut | Handle to an OUT endpoint returned by USBD_AddEP(). |
pData | Pointer to a buffer where the received data will be stored. |
NumBytesReq | Number of bytes to read. |
Timeout | Timeout given in milliseconds. A zero value results in an infinite timeout. |
Return value
= NumBytes | Requested data was successfully read within the given timeout. |
≥ 0 && < NumBytes | Timeout has occurred (Number of bytes read before timeout). |
< 0 | An error occurred. |
Additional information
This function blocks the task until all data has been read or a timeout occurs. In case of
a reset or a disconnect USB_STATUS_ERROR is returned.
If the USB stack receives a data packet from the host containing more bytes than requested,
the remaining bytes are stored into the internal buffer of the endpoint,
that was provided via the USBD_AddEP() function. This data can be retrieved by a later call to
USBD_Receive() or USBD_Read(). See also USBD_GetNumBytesInBuffer().
In case of a timeout, the read transfer is aborted (see Timeout handling).
USBD_ReadOverlapped()
Description
Reads data from the host asynchronously.
Prototype
int USBD_ReadOverlapped(unsigned EPOut,
void * pData,
unsigned NumBytesReq);
Parameters
Parameter | Description |
EPOut | Handle to an OUT endpoint returned by USBD_AddEP(). |
pData | Pointer to a buffer where the received data will be stored. |
NumBytesReq | Number of bytes to read. |
Return value
≥ 0 | Number of bytes that have been read from the internal buffer (success). |
= 0 | No data was found in the internal buffer, read transfer started (success). |
< 0 | An error occurred. |
Additional information
This function will not block the calling task. The read transfer will be initiated and the
function returns immediately. In order to synchronize, USBD_WaitForEndOfTransfer() needs
to be called.
Another synchronization method would be to periodically call
USBD_GetNumBytesRemToRead() in order to see how many bytes still need to be
received (this method is preferred when a non-blocking solution is necessary).
The read operation can be canceled using USBD_CancelIO().
The buffer pointed to by pData must be valid until the read operation is terminated.
USBD_Receive()
Description
Reads data from host. The function blocks until any data have been received. In contrast
to USBD_Read() this function does not wait for all of NumBytes to be
received, but returns after the first packet has been received or after the timeout occurs.
In case of a timeout, the read transfer is aborted (see Timeout handling).
Prototype
int USBD_Receive(unsigned EPOut,
void * pData,
unsigned NumBytesReq,
int Timeout);
Parameters
Parameter | Description |
EPOut | Handle to an OUT endpoint returned by USBD_AddEP(). |
pData | Pointer to a buffer where the received data will be stored. |
NumBytesReq | Number of bytes to read. |
Timeout | Timeout given in milliseconds. A zero value results in an infinite timeout. If Timeout is -1, the function never blocks and only reads data from the internal endpoint buffer. |
Return value
> 0 | Number of bytes that have been read within the given timeout. |
= 0 | A timeout occurred (if Timeout > 0), zero packet received (not every controller supports this!), no data in buffer (if Timeout < 0) or the target was disconnected during the function call and no data was read so far. |
< 0 | An error occurred. |
Additional information
If no error occurs, this function returns the number of bytes received.
Calling USBD_Receive() will return as much data as is currently available up to
the size of the buffer specified within the specified timeout. This function also returns
when the target is disconnected from the host or when a USB reset occurred during the function
call, it will then return the number of bytes read so far. If the target was disconnected
before this function was called, it returns USB_STATUS_ERROR.
If the USB stack receives a data packet from the host containing more bytes than requested,
the remaining bytes are stored into the internal buffer of the endpoint,
that was provided via USBD_AddEP(). This data can be retrieved by a later call to
USBD_Receive() / USBD_Read(). See also USBD_GetNumBytesInBuffer().
A call of USBD_Receive(EPOut, NULL, 0, -1) can be used to trigger an asynchronous read that
stores the data into the internal buffer.
USBD_ReceivePoll()
Description
Reads data from host. The function blocks until any data have been received. In contrast
to USBD_Read() this function does not wait for all of NumBytes to be
received, but returns after the first packet has been received or after the timeout occurs.
In contrast to USBD_Receive() this function will continue the read transfer asynchronously in case of a timeout.
Prototype
int USBD_ReceivePoll(unsigned EPOut,
void * pData,
unsigned NumBytesReq,
unsigned Timeout);
Parameters
Parameter | Description |
EPOut | Handle to an OUT endpoint returned by USBD_AddEP(). |
pData | Pointer to a buffer where the received data will be stored. |
NumBytesReq | Number of bytes to read. |
Timeout | Timeout given in milliseconds. A zero value results in an infinite timeout. |
Return value
> 0 | Number of bytes that have been read within the given timeout. |
= 0 | A timeout occurred (if Timeout > 0) or a zero packet received (not every controller supports this!), or the target was disconnected during the function call and no data was read so far. |
< 0 | An error occurred. |
Additional information
If no error occurs, this function returns the number of bytes received.
Calling USBD_ReceivePoll() will return as much data as is currently available up to
the size of the buffer specified within the specified timeout. This function also returns
when the target is disconnected from the host or when a USB reset occurred during the function
call, it will then return the number of bytes read so far. If the target was disconnected
before this function was called, it returns USB_STATUS_ERROR.
If the USB stack receives a data packet from the host containing more bytes than requested,
the remaining bytes are stored into the internal buffer of the endpoint,
that was provided via USBD_AddEP(). This data can be retrieved by a later call to
USBD_Receive() / USBD_Read(). See also USBD_GetNumBytesInBuffer().
If a timeout occurs, the read transfer is not affected. Data send from the host after the timeout
is stored into the internal buffer of the endpoint and can be read by later calls to USBD_ReceivePoll().
If Timeout = 0, the function behaves like USBD_Receive().
USBD_ReadAsync()
Description
Reads data from the host asynchronously. The function does not wait for
the data to be received. A callback function is called after the transfer
has completed successfully, an error occurred or the transfer was canceled.
Prototype
void USBD_ReadAsync(unsigned EPIndex,
USB_ASYNC_IO_CONTEXT * pContext,
int ShortRead);
Parameters
Parameter | Description |
EPIndex | Handle to an OUT endpoint returned by USBD_AddEP(). |
pContext | Pointer to an I/O context containing parameters and pointer to the callback function. |
ShortRead | 0: The transfer is completed successfully after all bytes have been read. 1: The transfer is completed successfully after one packet has been read. |
USBD_Write()
Description
Writes data to the host. Depending on the Timeout parameter, the function may block
until NumBytes have been written or a timeout occurs.
Prototype
int USBD_Write( unsigned EPIndex,
const void * pData,
unsigned NumBytes,
char Send0PacketIfRequired,
int ms);
Parameters
Parameter | Description |
EPIndex | Handle to an IN endpoint returned by USBD_AddEP(). |
pData | Pointer to data that should be sent to the host. |
NumBytes | Number of bytes to be written. |
Send0PacketIfRequired | Specifies that a zero-length packet should be sent when the last data packet to the host is a multiple of MaxPacketSize. |
ms | Timeout in milliseconds. 0 means infinite. If Timeout is -1, the function returns immediately and the transfer is processed asynchronously. |
Return value
= 0 | Successful started an asynchronous write transfer or a timeout has occurred and no data was written. |
> 0 && < NumBytes | Number of bytes that have been written before a timeout occurred. |
= NumBytes | Write transfer successful completed. |
< 0 | An error occurred. |
Additional information
This function also returns when the target is disconnected from host or when a USB reset
occurred.
The USB stack is able to queue a small number of asynchronous write
transfers (Timeout = -1). If a write transfer is still in progress when this
function is called and the USB stack can not accept another write transfer request,
the functions returns USB_STATUS_EP_BUSY. A synchronous write transfer
(Timeout ≥ 0) will always block until the transfer (including all
pending transfers) are finished.
In order to synchronize, USBD_WaitForEndOfTransfer() needs to be called. Another synchronization
method would be to periodically call USBD_GetNumBytesRemToWrite() in
order to see how many bytes still need to be written (this method is preferred when
a non-blocking solution is necessary).
In case of a timeout, the write transfer is aborted (see Timeout handling).
The write operation can be canceled using USBD_CancelIO().
If pData = NULL and NumBytes = 0, a zero-length packet is sent to the host.
The content of the buffer pointed to by pData must not be changed until the transfer
has been completed.
USBD_WriteAsync()
Description
Sends data to the host asynchronously. The function does not wait for
the data to be sent. A callback function is called after the transfer
has completed successfully, an error occurred or the transfer was canceled.
Prototype
void USBD_WriteAsync(unsigned EPIndex,
USB_ASYNC_IO_CONTEXT * pContext,
char Send0PacketIfRequired);
Parameters
Parameter | Description |
EPIndex | Handle to an IN endpoint returned by USBD_AddEP(). |
pContext | Pointer to an I/O context containing parameters and pointer to the callback function. |
Send0PacketIfRequired | Specifies that a zero-length packet shall be sent when the last data packet is a multiple of MaxPacketSize. |
USBD_CancelIO()
Description
Cancel any read or write operation.
Prototype
void USBD_CancelIO(unsigned EPIndex);
Parameters
Parameter | Description |
EPIndex | Handle to an endpoint returned by USBD_AddEP(). |
USBD_WaitForEndOfTransferEx()
Description
Wait until the current transfer on a particular EP has completed.
This function must be called from a task.
Prototype
int USBD_WaitForEndOfTransferEx(unsigned EPIndex,
unsigned Timeout,
int AbortOnTimeout);
Parameters
Parameter | Description |
EPIndex | Handle to the endpoint returned by USBD_AddEP(). |
Timeout | Timeout in milliseconds, 0 means infinite wait. |
AbortOnTimeout | If a timeout occurs, then the current transfer is terminated if AbortOnTimeout ≠ 0. The current transfer is not affected in case of a timeout if AbortOnTimeout = 0. See also Timeout handling. |
Return value
0 | Transfer completed. |
1 | Timeout occurred. |
USBD_WaitForTXReady()
Description
Waits (blocking) until the TX queue can accept another data packet.
This function is used in combination with a non-blocking call to USBD_Write(), it
waits until a new asynchronous write data transfer will be accepted by the USB stack.
Prototype
int USBD_WaitForTXReady(unsigned EPIndex,
int Timeout);
Parameters
Parameter | Description |
EPIndex | Handle to an IN endpoint returned by USBD_AddEP(). |
Timeout | Timeout in milliseconds. 0 means infinite. If Timeout is negative, the function will return immediately. |
Return value
= 0 | A new asynchronous write data transfer will be accepted. |
= 1 | The write queue is full, a call to USBD_Write() would return USB_STATUS_EP_BUSY. |
< 0 | Error occurred. |
Additional information
If Timeout is 0, the function never returns 1.
If Timeout is -1, the function will not wait, but immediately return the current state.
USBD_GetNumBytesInBuffer()
Description
Returns the number of bytes that are available in the internal BULK-OUT endpoint buffer.
This function does not start a read transfer.
Prototype
unsigned USBD_GetNumBytesInBuffer(unsigned EPIndex);
Parameters
Parameter | Description |
EPIndex | Handle to an OUT endpoint returned by USBD_AddEP(). |
Return value
Number of bytes which have been stored in the internal buffer.
Additional information
The number of bytes returned by this function can be read using USBD_Read() or USBD_Receive()
without blocking.
USBD_GetNumBytesRemToRead()
Description
This function is to be used in combination with USBD_ReadOverlapped(). It
returns the number of bytes which still have to be read during the transaction.
Prototype
unsigned USBD_GetNumBytesRemToRead(unsigned EPIndex);
Parameters
Parameter | Description |
EPIndex | Handle to an OUT endpoint returned by USBD_AddEP(). |
Return value
Number of bytes which still have to be read.
Additional information
Note that this function does not return the number of bytes that have been read, but
the number of bytes which still have to be read.
This function does not block.
USBD_GetNumBytesRemToWrite()
Description
This function is to be used in combination with a non-blocking call to
USBD_Write(). It returns the number of bytes which still have to be written during
the transaction.
Prototype
unsigned USBD_GetNumBytesRemToWrite(unsigned EPIndex);
Parameters
Parameter | Description |
EPIndex | Handle to an IN endpoint returned by USBD_AddEP(). |
Return value
Number of bytes which still have to be written.
Additional information
Note that this function does not return the number of bytes that have been written,
but the number of bytes which still have to be written.
This function does not block.
USBD_StallEP()
Description
Stalls an endpoint.
Prototype
void USBD_StallEP(unsigned EPIndex);
Parameters
Parameter | Description |
EPIndex | Handle to the endpoint handle returned by USBD_AddEP(). |
USB Remote wakeup functions
Remote wakeup is a feature that allows a device to wake a host system from a USB
suspend state.
In order to do this a special resume signal is sent over the USB data lines.
Additionally the USB host controller and operating system has to be able to handle
this signaling.
Windows OS
Currently Windows OS only supports the wakeup feature on devices based on HID
mouse/keyboard, CDC Modem and RNDIS Ethernet class. Remote wakeup for MSD,
generic bulk and CDC serial is not supported by Windows. So therefore a HID mouse
class even as dummy interface within your USB configuration is currently mandatory.
Windows must also be told that the device shall wake the PC from the suspend state.
This is done by setting the option “Allow this device to bring the computer out of standby”.
macOS
macOS supports remote wakeup for all device classes.
USBD_SetAllowRemoteWakeUp()
Description
Allows the device to publish that remote wake is available.
Prototype
void USBD_SetAllowRemoteWakeUp(U8 AllowRemoteWakeup);
Parameters
Parameter | Description |
AllowRemoteWakeup | 1 - Allows and publishes that remote wakeup is available. 0 - Publish that remote wakeup is not available. |
Additional information
This function must be called before the function USBD_Start() is called. This ensures
that the Host is informed that USB remote wake up is available.
USBD_DoRemoteWakeup()
Description
Performs a remote wakeup in order to wake up the host from the
standby/suspend state.
This will only work, when the USB device driver supports this.
The function must be called only, if either:
A) The USB device is in suspend state: (USBD_GetState() & USB_STAT_SUSPENDED) ≠ 0
and remote wakeup is allowed by the host: (USBD_GetDeviceState() & USB_DEVSTAT_REMOTE_WAKEUP_ALLOWED) ≠ 0.
OR
B) The USB bus is in L1 state and remote wakeup is allowed by the host, see USBD_SetOnLPMChange().
Prototype
void USBD_DoRemoteWakeup(void);
Additional information
This function cannot be called from an ISR context.
Data structures
USB_ADD_EP_INFO
Description
Structure used by USBD_AddEPEx() when adding an endpoint.
Type definition
typedef struct {
unsigned MaxPacketSize;
U16 Interval;
U8 Flags;
U8 InDir;
U8 TransferType;
U8 ISO_Type;
} USB_ADD_EP_INFO;
Structure members
Member | Description |
MaxPacketSize | Maximum packet size for the endpoint. |
Interval | Specifies the interval measured in units of 125us (microframes). This value should be zero for a bulk endpoint. |
Flags | Specifies whether optional parameters are used. 0x00 - Ignore optional parameters. USB_ADD_EP_FLAG_USE_ISO_SYNC_TYPES - Use ISO_Type. If not set the endpoint will have the sync type USB_ISO_SYNC_TYPE_NONE. |
InDir | Specifies the direction of the desired endpoint. USB_DIR_IN USB_DIR_OUT |
TransferType | Specifies the transfer type of the endpoint. The following values are allowed: USB_TRANSFER_TYPE_BULK USB_TRANSFER_TYPE_ISO USB_TRANSFER_TYPE_INT |
ISO_Type | Allows to set the synchronization type for isochronous endpoints. The following types are supported: USB_ISO_SYNC_TYPE_NONE (default) USB_ISO_SYNC_TYPE_ASYNCHRONOUS USB_ISO_SYNC_TYPE_ADAPTIVE USB_ISO_SYNC_TYPE_SYNCHRONOUS |
Additional information
The Interval parameter specifies the frequency in which the endpoint should be
polled for information by the host. It must be specified in units of 125 us.
Depending on the actual speed of the device during enumeration, the USB stack
converts the interval to the correct value required for the endpoint descriptor
according to the USB specification (into milliseconds for low/full-speed, into 125 us
for high-speed).
For endpoints of type USB_TRANSFER_TYPE_BULK the value is ignored and should be set to 0.
The actual maximum packet size for bulk endpoints may be smaller than given in the ’MaxPacketSize’
field to meet the requirements of the actual USB speed.
For SuperSpeed bulk endpoints, MaxPacketSize can be N * 1024, where N = 1…16.
Values of N > 1 enables the usage of burst transfers.
USB_SETUP_PACKET
Description
Structure containing a USB setup packet received from the host.
Type definition
typedef struct {
U8 bmRequestType;
U8 bRequest;
U8 wValueLow;
U8 wValueHigh;
U8 wIndexLow;
U8 wIndexHigh;
U8 wLengthLow;
U8 wLengthHigh;
} USB_SETUP_PACKET;
Structure members
Member | Description |
bmRequestType | Setup request type. |
bRequest | Setup request number. |
wValueLow | Low byte of the value field. |
wValueHigh | High byte of the value field. |
wIndexLow | Low byte of the index field. |
wIndexHigh | High byte of the index field. |
wLengthLow | Low byte of the length field. |
wLengthHigh | High byte of the length field. |
SEGGER_CACHE_CONFIG
Description
Used to pass cache configuration and callback function pointers to the stack.
Prototype
typedef struct {
int CacheLineSize;
void (*pfDMB) (void);
void (*pfClean) (void *p, unsigned long NumBytes);
void (*pfInvalidate)(void *p, unsigned long NumBytes);
} SEGGER_CACHE_CONFIG;
Member | Description |
CacheLineSize | Cache line size of the CPU in bytes. Most Systems such as ARM9 use a 32 bytes cache line size. |
pfDMB | Unused. |
pfClean | Pointer to a callback function that executes a clean operation on cached memory.
The parameter ’p’ is always cache aligned. ’NumBytes’ must be rounded up by the function
to the next multiple of the cache line size, if necessary. |
pfInvalidate | Pointer to a callback function that executes an invalidate operation on cached memory.
The parameter ’p’ is always cache aligned. ’NumBytes’ must be rounded up by the function
to the next multiple of the cache line size, if necessary. |
Additional information
For further information about how this structure is used please refer to
USBD_SetCacheConfig.
USB_CHECK_ADDRESS_FUNC
Description
Checks if an address can be used for DMA transfers.
The function must return 0, if DMA access is allowed for the given address,
1 otherwise.
Type definition
typedef int USB_CHECK_ADDRESS_FUNC(const void * pMem);
Parameters
Parameter | Description |
pMem | Pointer to the memory. |
Return value
= 0 | Memory can be used for DMA access. |
≠ 0 | DMA access not allowed for the given address. |
USB_ASYNC_IO_CONTEXT
Description
Contains information for asynchronous transfers.
Type definition
typedef struct {
unsigned NumBytesToTransfer;
void * pData;
USB_ASYNC_CALLBACK_FUNC * pfOnComplete;
void * pContext;
int Status;
unsigned NumBytesTransferred;
} USB_ASYNC_IO_CONTEXT;
Structure members
Member | Description |
NumBytesToTransfer | Number of bytes to transfer. Must be set by the application. |
pData | Pointer to the buffer for read operations, pointer to the data for write operations. Must be set by the application. |
pfOnComplete | Pointer to the function called on completion of the transfer. Must be set by the application. |
pContext | Pointer to a user context. Can be arbitrarily used by the application. |
Status | Result status of the asynchronous transfer. Set by the USB stack before calling pfOnComplete. |
NumBytesTransferred | Number of bytes transferred. Set by the USB stack before calling pfOnComplete. |
USB_WEBUSB_INFO
Description
Information that may be provided by the application for WebUSB capable USB devices.
Can be set via the function USBD_SetWebUSBInfo() before the USB stack is started using USBD_Start().
Is used during enumeration of the device by the host.
Type definition
typedef struct {
U8 VendorCode;
U8 DescIndex;
U8 URLPrefix;
const char * sURL;
} USB_WEBUSB_INFO;
Structure members
Member | Description |
VendorCode | Vendor code used for the setup request. |
DescIndex | Descriptor index of the descriptor containing the URL of the landing page. |
URLPrefix | Prefix of the URL: 0 = “http://”, 1 = “https://”, 255 = none. |
sURL | URL of the landing page. UTF-8 string. |
Function Types
USB_ON_CLASS_REQUEST
Description
Type of callback set in USBD_SetClassRequestHook() or USBD_SetVendorRequestHook().
This function is called when a setup class request
is sent from the host to the specified interface index.
Type definition
typedef int USB_ON_CLASS_REQUEST(const USB_SETUP_PACKET * pSetupPacket);
Parameters
Parameter | Description |
pSetupPacket | Pointer to the setup packet received from the host. |
Return value
If the function has processed the setup packet, it must acknowledge the packet
by either sending a response packet using USBD_WriteEP0FromISR() or an empty packet with
USBD_WriteEP0FromISR(NULL, 0, 0) and must return 0.
If the function can’t process the packet, it must return 1.
In this case the USB stacks tries to process the packet and will send a STALL
if that fails.
USB_ON_SETUP
Description
Type of callback set in USBD_SetOnSetup().
This function is called when a setup request was sent from the host.
Type definition
typedef int USB_ON_SETUP(const USB_SETUP_PACKET * pSetupPacket);
Parameters
Parameter | Description |
pSetupPacket | Pointer to the setup packet received from the host. |
Return value
If the function has processed the setup packet, it must acknowledge the packet
by either sending a response packet using USBD_WriteEP0FromISR() or an empty packet with
USBD_WriteEP0FromISR(NULL, 0, 0) and must return 0.
If the function can’t process the packet, it must return 1.
In this case the USB stacks tries to process the packet and will send a STALL
if that fails.
USB_GET_STRING_FUNC
Description
Type of callback set in USBD_SetGetStringHook().
This function is called when a string descriptor is requested from the host.
Type definition
typedef const char * USB_GET_STRING_FUNC(int Index);
Parameters
Parameter | Description |
Index | Index of the requested string. |
Return value
If the function is able to provide a string for the given index, it should return a pointer to
an ASCII string. Otherwise it should return a NULL pointer.
USB_ON_LPM_CHANGE
Description
Type of callback set in USBD_SetOnLPMChange().
This function is called when a LPM transition on the USB lines (L0 <-> L1) is detected.
Type definition
typedef void USB_ON_LPM_CHANGE(int State,
unsigned BESL);
Parameters
Parameter | Description |
State | -1 - Transition to L0. 0 - Transition to L1. Remote wakeup not allowed. 1 - Transition to L1. Remote wakeup allowed. |
BESL | BESL value (Best Effort Service Latency) in range 0…15 reported by the host when requesting a transition to L1 state. Values of 0,1,…,14,15 specify a BESL of 125us,150us,…,9000us,10000us respectively, see “Errata for USB 2.0 ECN: Link Power Management (LPM) - 7/2007” from usb.org for an explanation of these values. |
Timeout handling
Many API functions have a timeout parameter that causes the functions to return, if the desired transaction can not be finished
within the given time. Hardware USB controllers usually do not have a mechanism for timeouts. Therefore the USB stack has to
handle timeouts as follows:
- Start a transaction.
- Wait for the transaction to complete or the timeout to expire.
- If the timeout has expired: Abort the current transaction.
Aborting a transaction is always a critical operation. The USB software is informed by the hardware only
if a transaction has been completed. The software usually does not know, if a data transfer on the USB lines is still in progress.
So if the USB stack decides to abort a transaction, this transaction may already be in progress at that time.
In this case the abort of the transfer may cause the data currently transferred to be discarded without any notice to the software.
Although the data packet was successfully transferred on the USB bus and acknowledged by the host, the data is lost from the target application’s viewpoint.
Because this is usually not the behavior intended by the application, timeouts should be used to handle fatal errors only.
Timeouts should not be used to repeatedly poll for data.
Bad example
NOT RECOMMENDED
for (;;) {
// Try to read some data with 5 ms timeout
NumBytesRead = USBD_Receive(EP, Buffer, 100, 5);
if (NumBytesRead < 0) {
<handle error>
break;
}
if (NumBytesRead > 0) {
<process the data>
continue;
}
// NumBytesRead is 0 here, that means a timeout has occurred
<execute other tasks>
// Repeat the loop and retry to read data
}
In this example, data packets may be lost if they arrive exactly when the 5 ms timeout expires.
There are several options to avoid this problem:
- Using non-blocking API functions, like USBD_Receive() whereas the Timeout value = -1 eg. USBD_Receive(EP, Buffer, 100, -1).
- Using asynchronous API functions, line USBD_ReadOverlapped(), USBD_ReadAsync().
- Using blocking API functions with a timeout, that don’t abort the transaction. They usually have a “Poll” in their name.
The above example works well when using the function USBD_ReceivePoll() instead of USBD_Receive().
The same applies when writing data to the host.
Low power mode
emUSB-Device does not directly support low power modes of the device running USB, because it is very specific
to the actual hardware and requirements of the application and there may be several different low power states.
Low power mode may include:
- Shutting down peripherals (including the USB controller and/or the PHY)
- Shutting down PLLs
- Lowering the system clock
- CPU sleep modes
The device is usually put into low power state only, if there is no USB connection to the host.
Since the host supplies the device via (5 Volt) VBUS, there is no need for power saving.
Without a USB host connection, the device may run from a battery which requires low power consumption.
The application is responsible to determine when low power state should be entered or exited.
In most cases it depends on VBUS: Enter low power mode while no VBUS is present.
There is no general way to detect VBUS with the USB controller, especially if the USB controller is shut down.
Therefore VBUS detection must be managed by the application.
To enter low power mode, the application should:
To leave low power mode, the application should:
Alternately the USB stack may be re-initialized completely.
To enter low power mode:
To leave low power mode:
The second approach is necessary for example, if the configuration which was done in the USBD_X_Config()
function should be executed after resuming from low power mode, or if the memory used by the USB stack
was shut down in low power mode and has lost its contents.
USB suspend
If the application wants to respond to a USB suspend from the host while the device stays connected to
the host, it may simply monitor the status bit USB_STAT_SUSPENDED returned by the function USBD_GetState().
The USB stack must remain active to get correct states from USBD_GetState().
The USB controller is usually not able to distinguish between suspend state and USB disconnect.
Therefore the VBUS state has to be considered: If the stack turns into suspend state while
VBUS is still present, the host has issued a suspend and a later resume (or remote wake-up) may be possible.
If the stack signals a suspend event and VBUS is off, then the host was disconnected and no resume (or remote wake-up)
is possible.
The device may be put into low power mode during suspend. If the USB controller is affected by the low power mode
(for example if the USB controller register settings are not retained), then the application has to save and restore
the USB controllers state before entering / after leaving low power state.
Link Power Management (LPM)
To enable LPM, the application has to call USBD_UseV210() within the configuration function USBD_X_Config().
This sets the USB version of the device to 2.10.
The host will then request the LPM capabilities from the device (contained in the BOS descriptor) during enumeration.
The USB stack will offer LPM support only, if the driver and the USB controller supports it.
For SuperSpeed devices LPM is enabled by default.
Please notice that common USB hosts (Windows/Linux/MacOS) use LPM for full- and high-speed devices only in special situations.
If the host contains a controller hardware other than a XHCI type controller, then LPM is not used.
Also if the device is not directly connected to that USB controller, but instead via a hub, then LPM is not used.
See also:
Bulk communication
This chapter describes how to get emUSB-Device-Bulk up and running.
Generic bulk stack
The generic bulk stack is located in the directory USB. All C files in the directory should be
included in the project (compiled and linked as part of your project).
The files in this directory are maintained by SEGGER and should not require any modification. All files requiring
modifications have been placed in other directories.
Requirements for the Host (PC)
In order to communicate with a target (client) running emUSB-Device, the operating system
running on the host must recognize the device connected to it.
Windows
Microsoft’s Windows operating systems (Starting with XP Service Pack 2) contains a
generic driver called WinUSB.sys that is used to handle all communication to a emUSB-Device
running a BULK interface. If a emUSB bulk device is connected to a Windows 8, 8.1 and 10 PC
for the first time, Windows will install the WinUSB driver automatically.
For Windows versions less than Windows 8, Microsoft provides a driver for Windows Vista and Windows 7
but this needs to be installed manually. A driver installation tool including the mentioned driver is available
in the Windows\USB\Bulk\WinUSBInstall.
Windows XP user can use the driver package located under Windows\USB\Bulk\WinUSB_USBBulk_XP.
In order to get emUSB BULK running with the WinUSB driver the following must be considered:
- The function USBD_BULK_SetMSDescInfo() must be called in the target application.
- The Product IDs 1234 and 1121 must not be used.
Linux
Linux can handle emUSB BULK devices out of the box.
By default a USB device can only be accessed by a process that is running with “root”
rights. In order to use the USB bulk device from normal user programs an udev rule has to
be configured for the device (refer to the linux udev documentation). The emUSB-Device
release contains a sample configuration file 99-emUSBD.rules, which may be modified
and copied to /etc/udev/rules.d on the host machine.
macOS
macOS can handle emUSB BULK devices out of the box.
Example application
Example applications for both the target (client) and the PC (host) are supplied. These can
be used for testing the correct installation and proper function of the device running emUSB-Device.
The host sample applications can be used for Windows, Linux and MacOSX.
Precompiled executables for Windows can be found in the subfolder Windows/USB/Bulk/SampleApplication/Exe.
The application USB_BULK_Test.c is a modified echo server; the application receives data,
modifies the first byte and sends it back to the host. It also contains the functionality to
measure USB transfer speed.
To use this application, make sure to use the corresponding example files both on the
host-side as on the target side. The example applications on the PC host are named in the
same way, just without the prefix USB_BULK_.
The example applications for the target-side are supplied in source code in the Application directory.
For information how to compile the host examples (especially for Linux and MacOSX) refer
to Compiling the PC example application.
The start application will of course later on be replaced by the real application program.
For the purpose of getting emUSB-Device up and running as well as doing an initial test,
the start application should not be modified.
Running the example applications
To test the emUSB-Device-Bulk component, build and download the application of choice
for the target-side.
To run one of the example applications, simply start the executable, for example by double clicking it.
If a connection can be established, it exchanges data with the target, testing the USB connection.
Example output of Test.exe:
Compiling the PC example application
Windows
For compiling the example application you need Visual C++ 2010 (or later).
The source code of the sample application is located in the subfolder Windows/USB/BULK/SampleApplication/Src.
Open the file USBBULK_Start.sln and compile the source.
Linux
The subfolder Windows/USB/Bulk/SampleApplication contains a Makefile for Linux.
Change to this folder and execute “make”.
macOS
The subfolder Windows/USB/Bulk/SampleApplication contains a Makefile for
macOS. Change to this folder and execute “make -f Makefile_MacOSX”.
Target API
This chapter describes the functions that can be used with the target system.
General information
To communicate with the host, the sample application project includes USB-specific
header and source files (USB.h, USB_Main.c, USB_Setup.c, USB_Bulk.c, USB_Bulk.h).
These files contain API functions to communicate with the USB host through the emUSB-Device driver.
Purpose of the USB Device API functions
To have an easy start up when writing an application on the device side, these API functions have a simple interface
and handle all operations that need to be done to communicate with the hosts kernel.
Therefore, all operations that need to write to or read from the emUSB-Device are handled internally by the provided API functions.
Target interface function list
USB-Bulk functions
USBD_BULK_Add()
Description
Adds interface for USB-Bulk communication to emUSB-Device.
Prototype
USB_BULK_HANDLE USBD_BULK_Add(const USB_BULK_INIT_DATA * pInitData);
Parameters
Return value
Handle to a valid BULK instance. The handle of the first BULK
instance is always 0.
Example
Example excerpt from BULK_Echo1.c:
static void _AddBULK(void) {
static U8 _abOutBuffer[USB_HS_BULK_MAX_PACKET_SIZE];
USB_BULK_INIT_DATA Init;
Init.EPIn = USBD_AddEP(USB_DIR_IN,
USB_TRANSFER_TYPE_BULK,
USB_HS_BULK_MAX_PACKET_SIZE,
NULL,
0);
Init.EPOut = USBD_AddEP(USB_DIR_OUT,
USB_TRANSFER_TYPE_BULK,
USB_HS_BULK_MAX_PACKET_SIZE,
_abOutBuffer,
USB_HS_BULK_MAX_PACKET_SIZE);
USBD_BULK_Add(&Init);
}
USBD_BULK_Add_Ex()
Description
Adds interface for USB-Bulk communication to emUSB-Device.
Prototype
USB_BULK_HANDLE USBD_BULK_Add_Ex(const USB_BULK_INIT_DATA_EX * pInitData);
Parameters
Return value
Handle to a valid BULK instance. The handle of the first BULK
instance is always 0.
Example
static void _AddBULK(void) {
static U8 _abOutBuffer[USB_HS_BULK_MAX_PACKET_SIZE];
USB_BULK_INIT_DATA_EX Init;
Init.Flags = 0;
Init.EPIn = USBD_AddEP(USB_DIR_IN,
USB_TRANSFER_TYPE_BULK,
USB_HS_BULK_MAX_PACKET_SIZE,
NULL,
0);
Init.EPOut = USBD_AddEP(USB_DIR_OUT,
USB_TRANSFER_TYPE_BULK,
USB_HS_BULK_MAX_PACKET_SIZE,
_abOutBuffer,
USB_HS_BULK_MAX_PACKET_SIZE);
Init.pInterfaceName = "BULK Interface";
USBD_BULK_Add_Ex(&Init);
}
USBD_BULK_AddAlternateInterface()
Description
Adds an alternative interface for USB-Bulk interface.
Prototype
void USBD_BULK_AddAlternateInterface( USB_BULK_HANDLE hInst,
const USB_BULK_INIT_DATA_EX * pInitData,
USB_ON_USER_SET_INTERFACE * pfOnUser);
Parameters
Parameter | Description |
hInst | Handle to a valid BULK instance, returned by USBD_BULK_Add(). |
pInitData | Pointer to USB_BULK_INIT_DATA_EX structure. |
pfOnUser | Callback function that is called, when the host changes the interface. |
USBD_BULK_SetMSDescInfo()
Description
Enables use of Microsoft OS Descriptors. A USB bulk device providing
these descriptors is detected by Windows to be handled by the generic
WinUSB driver. For such devices no other driver needs to be installed.
Prototype
void USBD_BULK_SetMSDescInfo(USB_BULK_HANDLE hInst);
Parameters
Parameter | Description |
hInst | Handle to a valid BULK instance, returned by USBD_BULK_Add(). |
Additional information
This function must be called after the call to the function USBD_BULK_Add()
and before USBD_Start().
USBD_BULK_CancelRead()
Description
Cancels any non-blocking/blocking read operation that is pending.
Prototype
void USBD_BULK_CancelRead(USB_BULK_HANDLE hInst);
Parameters
Parameter | Description |
hInst | Handle to a valid BULK instance, returned by USBD_BULK_Add(). |
Additional information
This function shall be called when a pending asynchronous read operation should be canceled.
The function can be called from any task. In case of canceling a blocking operation,
this function must be called from another task.
USBD_BULK_CancelWrite()
Description
Cancels any non-blocking/blocking write operation that is pending.
Prototype
void USBD_BULK_CancelWrite(USB_BULK_HANDLE hInst);
Parameters
Parameter | Description |
hInst | Handle to a valid BULK instance, returned by USBD_BULK_Add(). |
Additional information
This function shall be called when a pending asynchronous write operation should be canceled.
The function can be called from any task. In case of canceling a blocking operation,
this function must be called from another task.
USBD_BULK_GetNumBytesInBuffer()
Description
Returns the number of bytes that are available in the internal BULK-OUT endpoint buffer.
This function does not start a read transfer.
Prototype
unsigned USBD_BULK_GetNumBytesInBuffer(USB_BULK_HANDLE hInst);
Parameters
Parameter | Description |
hInst | Handle to a valid BULK instance, returned by USBD_BULK_Add(). |
Return value
Number of bytes that are available in the internal BULK-OUT endpoint buffer.
Additional information
If the host is sending more data than your target application has requested, the remaining
data will be stored in an internal buffer. This function shows how many bytes are available
in this buffer.
The number of bytes returned by this function can be read using USBD_BULK_Read()
without blocking.
Example
Your host application sends 50 bytes.
Your target application only requests to receive 1 byte.
In this case the target application will get 1 byte and the remaining 49 bytes are
stored in an internal buffer.
When your target application now calls USBD_BULK_GetNumBytesInBuffer() it will
return the number of bytes that are available in the internal buffer (49).
USBD_BULK_GetNumBytesRemToRead()
Description
Get the number of remaining bytes to read by an active read operation.
This function is to be used in combination with USBD_BULK_ReadOverlapped().
After starting the read operation this function can be used to periodically check how many
bytes still have to be read.
Prototype
unsigned USBD_BULK_GetNumBytesRemToRead(USB_BULK_HANDLE hInst);
Parameters
Parameter | Description |
hInst | Handle to a valid BULK instance, returned by USBD_BULK_Add(). |
Return value
≥ 0 | Number of bytes which have not yet been read. |
< 0 | Error occurred. |
Additional information
Alternatively the blocking function USBD_BULK_WaitForRX() can be used.
Example
NumBytesReceived = USBD_BULK_ReadOverlapped(hInst, &ac[0], 50);
if (NumBytesReceived < 0) {
<.. error handling..>
}
if (NumBytesReceived > 0) {
// Already had some data in the internal buffer.
// The first 'NumBytesReceived' bytes may be processed here.
<...>
} else {
// Wait until we get all 50 bytes
while (USBD_BULK_GetNumBytesRemToRead(hInst) > 0) {
USB_OS_Delay(50);
}
}
USBD_BULK_GetNumBytesRemToWrite()
Description
After starting a non-blocking write operation this function can be used to periodically
check how many bytes still have to be written.
Prototype
unsigned USBD_BULK_GetNumBytesRemToWrite(USB_BULK_HANDLE hInst);
Parameters
Parameter | Description |
hInst | Handle to a valid BULK instance, returned by USBD_BULK_Add(). |
Return value
Number of bytes which have not yet been written.
Additional information
Alternatively the blocking function USBD_BULK_WaitForTX() can be used.
Example
r = USBD_BULK_Write(hInst, &ac[0], TRANSFER_SIZE, -1);
if (r < 0) {
<.. error handling..>
}
// NumBytesToWrite shows how many bytes still have to be written.
while (USBD_BULK_GetNumBytesRemToWrite(hInst) > 0) {
USB_OS_Delay(50);
}
USBD_BULK_Read()
Description
Reads data from the host with a given timeout.
Prototype
int USBD_BULK_Read(USB_BULK_HANDLE hInst,
void * pData,
unsigned NumBytes,
unsigned Timeout);
Parameters
Parameter | Description |
hInst | Handle to a valid BULK instance, returned by USBD_BULK_Add(). |
pData | Pointer to a buffer where the received data will be stored. |
NumBytes | Number of bytes to read. |
Timeout | Timeout in milliseconds, 0 means infinite. |
Return value
= NumBytes | Requested data was successfully read within the given timeout. |
≥ 0 && < NumBytes | Timeout has occurred. Number of bytes that have been read within the given timeout. |
< 0 | Error occurred. |
Additional information
This function blocks a task until all data have been read or a timeout expires. This function
also returns when the device is disconnected from host or when a USB reset occurs.
If the USB stack receives a data packet from the host containing more bytes than requested,
the remaining bytes are stored into the internal buffer of the endpoint,
that was provided via USBD_AddEP(). This data can be retrieved by a later call to
USBD_BULK_Receive() / USBD_BULK_Read(). See also USBD_BULK_GetNumBytesInBuffer().
In case of a timeout, the read transfer is aborted (see Timeout handling).
If a read transfer was still pending while the function is called, it returns
USB_STATUS_EP_BUSY.
USBD_BULK_ReadAsync()
Description
Reads data from the host asynchronously. The function does not wait for
the data to be received. A callback function is called after the transfer
has completed successfully, an error occurred or the transfer was canceled.
Prototype
void USBD_BULK_ReadAsync(USB_BULK_HANDLE hInst,
USB_ASYNC_IO_CONTEXT * pContext,
int ShortRead);
Parameters
Parameter | Description |
hInst | Handle to a valid BULK instance, returned by USBD_BULK_Add(). |
pContext | Pointer to a structure of type USB_ASYNC_IO_CONTEXT containing parameters and a pointer to the callback function. |
ShortRead | 0: The transfer is completed successfully after all bytes have been read. 1: The transfer is completed successfully after one packet has been read. |
Example
static void _AsyncCb(USB_ASYNC_IO_CONTEXT * pIOContext) {
U8 *p;
p = (U8 *)pIOContext->pContext;
*p = 1;
}
<...>
USB_ASYNC_IO_CONTEXT IOContext;
U8 AsyncComplete;
IOContext.NumBytesToTransfer = 5000;
IOContext.pData = pBuff;
IOContext.pfOnComplete = _AsyncCb;
IOContext.pContext = (void *)&AsyncComplete;
AsyncComplete = 0;
USBD_BULK_ReadAsync(hInst, &IOContext, 0);
while (AsyncComplete == 0) {
<.. Do other work. ..>
}
// Transaction is complete.
if (IOContext.Status < 0 || IOContext.NumBytesTransferred != 5000) {
<.. error handling ..>
} else {
<.. Process the data ..>
}
<...>
USBD_BULK_ReadOverlapped()
Description
Reads data from the host asynchronously.
Prototype
int USBD_BULK_ReadOverlapped(USB_BULK_HANDLE hInst,
void * pData,
unsigned NumBytes);
Parameters
Parameter | Description |
hInst | Handle to a valid BULK instance, returned by USBD_BULK_Add(). |
pData | Pointer to a buffer where the received data will be stored. |
NumBytes | Number of bytes to read. |
Return value
> 0 | Number of bytes that have been read from the internal buffer (success). |
= 0 | No data was found in the internal buffer, read transfer started (success). |
< 0 | Error occurred. |
Additional information
This function will not block the calling task. The read transfer will be initiated and the
function returns immediately. In order to synchronize, USBD_BULK_WaitForRX() needs to
be called. Alternatively the function USBD_BULK_GetNumBytesRemToRead() can be
called periodically to check whether all bytes have been read or not.
The read operation can be canceled using USBD_BULK_CancelRead().
The buffer pointed to by pData must be valid until the read operation is terminated.
If a read transfer was still pending while the function is called, it returns
USB_STATUS_EP_BUSY.
Example
See USBD_BULK_GetNumBytesRemToRead.
USBD_BULK_Receive()
Description
Reads data from the host. The function blocks until any data has been received or a timeout
occurs (if Timeout ≥ 0). In contrast to USBD_BULK_Read() this function does
not wait for all of NumBytes to be received, but returns after the first packet has been
received.
In case of a timeout, the read transfer is aborted (see Timeout handling).
Prototype
int USBD_BULK_Receive(USB_BULK_HANDLE hInst,
void * pData,
unsigned NumBytes,
int Timeout);
Parameters
Parameter | Description |
hInst | Handle to a valid BULK instance, returned by USBD_BULK_Add(). |
pData | Pointer to a buffer where the received data will be stored. |
NumBytes | Maximum number of bytes to read. |
Timeout | Timeout in milliseconds. 0 means infinite. If Timeout is -1, the function never blocks and only reads data from the internal endpoint buffer. |
Return value
> 0 | Number of bytes that have been read. |
= 0 | A timeout occurred (if Timeout > 0), zero packet received (not every controller supports this!), no data in buffer (if Timeout < 0) or the target was disconnected during the function call and no data was read so far. |
< 0 | Error occurred. |
Additional information
If no error occurs, this function returns the number of bytes received.
Calling USBD_BULK_Receive() will return as much data as is currently available -- up to
the size of the buffer specified. This function also returns when the target is
disconnected from the host or when a USB reset occurred during the function call, it will
then return USB_STATUS_ERROR.
If a read transfer was pending while the function is called, it returns
USB_STATUS_EP_BUSY.
If the USB stack receives a data packet from the host containing more bytes than requested,
the remaining bytes are stored into the internal buffer of the endpoint,
that was provided via USBD_AddEP(). This data can be retrieved by a later call to
USBD_BULK_Receive() / USBD_BULK_Read(). See also USBD_BULK_GetNumBytesInBuffer().
A call of USBD_BULK_Receive(Inst, NULL, 0, -1) can be used to trigger an asynchronous read that
stores the data into the internal buffer.
USBD_BULK_ReceivePoll()
Description
Reads data from the host. The function blocks until any data has been received or a timeout
occurs (if Timeout ≥ 0). In contrast to USBD_BULK_Read() this function does
not wait for all of NumBytes to be received, but returns after the first packet has been
received.
In contrast to USBD_BULK_Receive() this function will continue the read transfer
asynchronously in case of a timeout.
Prototype
int USBD_BULK_ReceivePoll(USB_BULK_HANDLE hInst,
void * pData,
unsigned NumBytes,
unsigned Timeout);
Parameters
Parameter | Description |
hInst | Handle to a valid BULK instance, returned by USBD_BULK_Add(). |
pData | Pointer to a buffer where the received data will be stored. |
NumBytes | Maximum number of bytes to read. |
Timeout | Timeout in milliseconds. 0 means infinite. |
Return value
> 0 | Number of bytes that have been read. |
= 0 | A timeout occurred (if Timeout > 0), zero packet received (not every controller supports this!) or the target was disconnected during the function call and no data was read so far. |
< 0 | Error occurred. |
Additional information
If no error occurs, this function returns the number of bytes received.
Calling USBD_BULK_ReceivePoll() will return as much data as is currently available -- up to
the size of the buffer specified. This function also returns when the target is
disconnected from the host or when a USB reset occurred during the function call, it will
then return USB_STATUS_ERROR.
If a read transfer was pending while the function is called, it returns
USB_STATUS_EP_BUSY.
If the USB stack receives a data packet from the host containing more bytes than requested,
the remaining bytes are stored into the internal buffer of the endpoint,
that was provided via USBD_AddEP(). This data can be retrieved by a later call to
USBD_BULK_Receive() / USBD_BULK_Read(). See also USBD_BULK_GetNumBytesInBuffer().
If a timeout occurs, the read transfer is not affected. Data send from the host after the timeout
is stored into the internal buffer of the endpoint and can be read by later calls to USBD_BULK_ReceivePoll().
If Timeout = 0, the function behaves like USBD_BULK_Receive().
USBD_BULK_SetContinuousReadMode()
Description
Enables continuous read mode for the RX endpoint. In this mode every finished read transfer
will automatically trigger another read transfer, as long as there is enough space in the
internal buffer to receive another packet.
Prototype
void USBD_BULK_SetContinuousReadMode(USB_BULK_HANDLE hInst);
Parameters
Parameter | Description |
hInst | Handle to a valid BULK instance, returned by USBD_BULK_Add(). |
Additional information
To check how many bytes have been read into the buffer, the function
USBD_BULK_GetNumBytesInBuffer() may be called.
In order to read the data the function USBD_BULK_Receive() needs to be called (non-blocking).
The USB stack will use the buffer that was provided by the application with
USBD_AddEP(). The transfer speed may be improved, if this buffer has a size of at least
2 * MaxPacketSize. Normally MaxPacketSize for full-speed devices is 64 bytes and for
high-speed devices 512 bytes.
Example
USBD_BULK_SetContinuousReadMode(hInst);
<...>
for(;;) {
//
// Fetch data that was already read (non-blocking).
//
NumBytesReceived = USBD_BULK_Receive(hInst, &ac[0], sizeof(ac), -1);
if (NumBytesReceived > 0) {
//
// We got some data
//
<.. Process data..>
} else {
<.. Nothing received yet, do application processing..>
}
}
USBD_BULK_SetOnSetupRequest()
Description
Sets a callback function that is called when any setup request
is sent from the host.
Prototype
void USBD_BULK_SetOnSetupRequest(USB_BULK_HANDLE hInst,
USB_ON_SETUP * pfOnSetupRequest);
Parameters
Parameter | Description |
hInst | Handle to a valid BULK instance, returned by USBD_BULK_Add(). |
pfOnSetupRequest | Pointer to the callback function. |
USBD_BULK_SetOnRXEvent()
Description
Sets a callback function for the OUT endpoint that will be called on every RX event
for that endpoint.
Prototype
void USBD_BULK_SetOnRXEvent(USB_BULK_HANDLE hInst,
USB_EVENT_CALLBACK * pEventCb,
USB_EVENT_CALLBACK_FUNC * pfEventCb,
void * pContext);
Parameters
Parameter | Description |
hInst | Handle to a valid BULK instance, returned by USBD_BULK_Add(). |
pEventCb | Pointer to a USB_EVENT_CALLBACK structure. The structure is initialized by this function. |
pfEventCb | Pointer to the callback routine that will be called on every event on the USB endpoint. |
pContext | A pointer which is used as parameter for the callback function. |
Additional information
The USB_EVENT_CALLBACK structure is private to the USB stack. It will be initialized by USBD_BULK_SetOnRXEvent().
The USB stack keeps track of all event callback functions using a linked list. The
USB_EVENT_CALLBACK structure will be included into this linked list and must reside
in static memory.
The callback function is called only, if a read operation was started using one of the USBD_BULK_Read…() functions.
The callback function has the following prototype:
typedef void USB_EVENT_CALLBACK_FUNC(unsigned Events, void *pContext);
Parameter | Description |
Events | A bit mask indicating which events occurred on the endpoint. |
pContext | The pointer which was provided to the USBD_SetOnEvent() function. |
Note that the callback function will be called within an ISR, therefore it should never
block. The first parameter to the callback function will contain a bit mask for all
events that triggered the call:
Event | Description |
USB_EVENT_DATA_READ | Some data was received from the host on the endpoint. |
USB_EVENT_READ_COMPLETE | The last read operation was completed. |
USB_EVENT_READ_ABORT | A read transfer was aborted. |
Example
// The callback function.
static void _OnEvent(unsigned Events, void *pContext) {
unsigned NumBytes;
if (Events & USB_EVENT_DATA_READ) {
NumBytes = USBD_BULK_GetNumBytesInBuffer(hInst);
if (NumBytes) {
r = USBD_BULK_Receive(hInst, Buff, NumBytes, -1);
if (r > 0) {
<.. process data in Buff..>
}
}
}
}
// Main program.
// Register callback function.
static USB_EVENT_CALLBACK _usb_callback;
USBD_BULK_SetOnRXEvent(hInst, &_usb_callback, _OnEvent, NULL);
USBD_BULK_SetContinuousReadMode(hInst);
// Trigger first read
USBD_BULK_Receive(Inst, NULL, 0, -1);
<.. do anything else here while the data is processed in the callback ..>
USBD_BULK_SetOnTXEvent()
Description
Sets a callback function for the IN endpoint that will be called on every TX event for
that endpoint.
Prototype
void USBD_BULK_SetOnTXEvent(USB_BULK_HANDLE hInst,
USB_EVENT_CALLBACK * pEventCb,
USB_EVENT_CALLBACK_FUNC * pfEventCb,
void * pContext);
Parameters
Parameter | Description |
hInst | Handle to a valid BULK instance, returned by USBD_BULK_Add(). |
pEventCb | Pointer to a USB_EVENT_CALLBACK structure. The structure is initialized by this function. |
pfEventCb | Pointer to the callback routine that will be called on every event on the USB endpoint. |
pContext | A pointer which is used as parameter for the callback function. |
Additional information
The USB_EVENT_CALLBACK structure is private to the USB stack. It will be initialized by USBD_BULK_SetOnTXEvent().
The USB stack keeps track of all event callback functions using a linked list. The
USB_EVENT_CALLBACK structure will be included into this linked list and must reside
in static memory.
The callback function is called only, if a write operation was started using one of the USBD_BULK_Write…() functions.
The callback function has the following prototype:
typedef void USB_EVENT_CALLBACK_FUNC(unsigned Events, void *pContext);
Parameter | Description |
Events | A bit mask indicating which events occurred on the endpoint. |
pContext | The pointer which was provided to the USBD_SetOnEvent() function. |
Note that the callback function will be called within an ISR, therefore it should never
block. The first parameter to the callback function will contain a bit mask for all
events that triggered the call:
Event | Description |
USB_EVENT_DATA_SEND | Some data was sent to the host, so that (part of) the user
write buffer may be reused by the application. |
USB_EVENT_DATA_ACKED | Some data was acknowledged by the host. |
USB_EVENT_WRITE_ABORT | A write transfer was aborted. |
USB_EVENT_WRITE_COMPLETE | All write operations were completed. |
Example
// The callback function.
static void _OnEvent(unsigned Events, void *pContext) {
if ((Events & USB_EVENT_DATA_SEND) != 0 &&
// Check for last write transfer to be completed.
USBD_BULK_GetNumBytesRemToWrite(_hInst) == 0) {
<.. prepare next data for writing..>
// Send next packet of data.
r = USBD_BULK_Write(_hInst, &ac[0], 200, -1);
if (r < 0) {
<.. error handling..>
}
}
}
// Main program.
// Register callback function.
static USB_EVENT_CALLBACK _usb_callback;
USBD_BULK_SetOnTXEvent(hInst, &_usb_callback, _OnEvent, NULL);
// Send the first packet of data using an asynchronous write operation.
r = USBD_BULK_Write(_hInst, &ac[0], 200, -1);
if (r < 0) {
<.. error handling..>
}
<.. do anything else here while the whole data is send..>
USBD_BULK_TxIsPending()
Description
Checks whether the TX (IN endpoint) is currently pending.
Can be called in any context.
Prototype
int USBD_BULK_TxIsPending(USB_BULK_HANDLE hInst);
Parameters
Parameter | Description |
hInst | Handle to a valid BULK instance, returned by USBD_BULK_Add(). |
Return value
1 | We have queued data to be sent. |
0 | Queue is empty. |
USBD_BULK_WaitForRX()
Description
Waits (blocking) until the triggered USBD_BULK_ReadOverlapped()
has received the desired data.
Prototype
int