📄 emUSB-Host User Guide & Reference Manual
📄 emWeb User Guide & Reference Manual
📄 emWin User Guide & Reference Manual
📄 IoT Toolkit User Guide & Reference Manual
📄 SEGGER Assembler User Guide & Reference Manual
📄 SEGGER Floating-point Library User Guide & Reference Manual
📄 SEGGER Linker User Guide & Reference Manual
📄 SEGGER Runtime Library User Guide & Reference Manual
📄 AppWizard User Guide & Reference Manual
📄 embOS & embOS-MPU User Guide & Reference Manual
📄 emCompress-Embed User Guide & Reference Manual
📄 emCompress-Flex User Guide & Reference Manual
📄 emCompress-ToGo User Guide & Reference Manual
📄 emCrypt User Guide & Reference Manual
📄 emDropbox User Guide & Reference Manual
📄 emFile User Guide & Reference Manual
📄 emNet User Guide & Reference Manual
📄 emSecure-ECDSA User Guide & Reference Manual
📄 emSecure-RSA User Guide & Reference Manual
📄 emSSH User Guide & Reference Manual
📄 emSSL User Guide & Reference Manual
📄 emUSB-Device User Guide & Reference Manual

emUSB-Device User Guide & Reference Manual

USB Device stack.

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 or USB 2.0 devices.

The highest possible transfer rate on USB 2.0 full-speed (12 Mbit/s) devices is approximately 1 MB/s. This data rate can indeed be achieved on fast systems, such as Cortex-M devices running at 48 MHz and above.

USB 2.0 high-speed mode (480 MBit/s) is also fully supported and is automatically handled. Using USB high-speed mode with an Cortex-M or faster could achieve values of approx. 44 MByte/s.

The USB standard defines four types of communication: Control, isochronous, interrupt, and bulk. Experience shows that for most embedded devices the bulk mode is the communication mode of choice because applications can utilize the full bandwidth of the Universal Serial Bus.

emUSB-Device features

Key features of emUSB-Device are:

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
USB protocol layer
Bulk emUSB-Device bulk 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.
Core layer
emUSB-Device-Core The emUSB-Device core is the intrinsic USB stack.
Hardware layer
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:

Any target with USB interface: easy access to configuration and data files

emUSB-Device-MSD features

Key features of emUSB-Device-MSD are:

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:

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:

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:

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:

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:

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:

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:

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:

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:

If your compiler has some limitations, let us know and we will inform you if these will be a problem when compiling the software. Any compiler for 16/32/64-bit CPUs or DSPs that we know of can be used.

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 (e.g. memcpy).
USB Contains the emUSB-Device source code.
Windows Contains Windows specific applications 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:

Background information

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:

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:

USB Host system

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.

USB Descriptor order

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:

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

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 USBD 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:

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.

Dummy

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:

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:

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
Default Vendor ID for all applications
0x8765 Example Vendor ID for all examples. Do not use this in real products!
Used Product IDs
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

This chapter describes the optional defines which can be used in the file USB_Conf.h can be used to set configuration defines for emUSB-Device.

emUSB-Device can be used without changing any of the compile-time flags. All compile-time configuration flags are pre-configured with valid values which match the requirements of most applications.

The default configuration of emUSB-Device can be changed via compile-time flags which can be added to USB_Conf.h. This is the main configuration file for the emUSB-Device stack.

Define Default Description
USBD_OS_LAYER_EX 1 Chooses which RTOS layer version should be used
0 - Old (deprecated) API version.
1 - New API version.
USBD_OS_USE_USBD_X_INTERRUPT 0 If set emUSB-Device will use the functions USBD_X_EnableInterrupt() / USBD_X_DisableInterrupt()
USB_DEBUG_LEVEL 2 Sets the debug level.
0 - No checks and no logs.
1 - Support “Panic” checks.
2 - Support warn & log messages.
USB_SUPPORT_TRANSFER_ISO 0 Should isochronous transfers be supported? ISO is only required for audio and video classes.
USB_MAX_POWER 50 The maximum current consumption of the device in x*2 mA (e.g. 50 means 100 mA).
USBD_SUPPORT_PROFILE 0 Support profiling via SystemView?

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:

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.

Function Description
USB basic functions
USBD_Init() Initializes the USB device with its settings.
USBD_Start() Starts the emUSB-Device Core.
USBD_GetVersion() Returns the version of the stack.
USBD_GetState() Returns the state of the USB device.
USBD_IsConfigured() Checks if the USB device is initialized and ready.
USBD_GetSpeed() Returns the current connection speed.
USBD_Stop() Stops the USB communication.
USBD_DeInit() De-initialize the complete USB stack.
USB configuration functions
USBD_AddDriver() Adds a USB device driver to the USB stack.
USBD_SetISREnableFunc() Register function to enable USB interrupts.
USBD_SetAttachFunc() Sets a function to perform hardware-specific actions to attach USB.
USBD_AddEP() Returns an endpoint “handle” that can be used for the desired USB interface.
USBD_AddEPEx() Returns an endpoint “handle” that can be used for the desired USB interface.
USBD_SetDeviceInfo() Sets a all information used during device enumeration.
USBD_SetClassRequestHook() Sets a callback function that is called when a setup class request is sent from the host to the specified interface index.
USBD_SetVendorRequestHook() Sets a callback function that is called when a setup vendor request is sent from the host to the specified interface index.
USBD_SetIsSelfPowered() Sets whether the device is self-powered or not.
USBD_SetMaxPower() Sets the maximum power consumption reported to the host during enumeration.
USBD_SetOnEvent() Sets a callback function for an endpoint that will be called on every RX or TX event for that endpoint.
USBD_RemoveOnEvent() Removes a callback function which was added via USBD_SetOnEvent from the callback list.
USBD_SetOnRxEP0() Sets a callback when data are received in the data stage of the setup request.
USBD_SetOnRXHookEP() Sets a callback whenever data are received from a given endpoint handle.
USBD_SetOnSetup() Sets a callback function that is called when any setup request is sent from the host.
USBD_SetOnSetupHook() Obsolete, use USBD_SetOnSetup().
USBD_WriteEP0FromISR() Write data to EP0 (control endpoint).
USBD_EnableIAD() Enables combination of multi-interface device classes with single-interface classes or other multi-interface classes.
USBD_SetCacheConfig() Configures cache related functionality that might be required by the stack for cache handling in drivers.
USBD_RegisterSCHook() Sets a callback function that will be called on every state change of the USB device.
USBD_AssignMemory() Assigns an area of RAM to be used for the endpoint buffers and transfer descriptors by the USB driver.
USBD_UseV210() Enable use of USB V2.10 specification revision.
USBD_EnableSuperSpeed() Enable SuperSpeed in the USB stack.
USBD_SetWebUSBInfo() For WebUSB capable USB devices this function may be called before USBD_Start() to enable WebUSB specific descriptors.
USBD_SetCheckAddress() Installs a function that checks if an address can be used for DMA transfers.
USB I/O functions
USBD_Read() Reads data from the host.
USBD_ReadOverlapped() Reads data from the host asynchronously.
USBD_Receive() Reads data from host.
USBD_ReceivePoll() Reads data from host.
USBD_Write() Writes data to the host.
USBD_CancelIO() Cancel any read or write operation.
USBD_WaitForEndOfTransferEx() Wait until the current transfer on a particular EP has completed.
USBD_WaitForTXReady() Waits (blocking) until the TX queue can accept another data packet.
USBD_GetNumBytesInBuffer() Returns the number of bytes that are available in the internal BULK-OUT endpoint buffer.
USBD_GetNumBytesRemToRead() This function is to be used in combination with USBD_ReadOverlapped().
USBD_GetNumBytesRemToWrite() This function is to be used in combination with a non-blocking call to USBD_Write().
USBD_StallEP() Stalls an endpoint.
USB RemoteWakeUp functions
USBD_SetAllowRemoteWakeUp() Allows the device to publish that remote wake is available.
USBD_DoRemoteWakeup() Performs a remote wakeup in order to wake up the host from the standby/suspend state.
Data structures
USB_ASYNC_IO_CONTEXT Contains information for asynchronous transfers.
USB_SETUP_PACKET Structure containing a USB setup packet.
SEGGER_CACHE_CONFIG Used to pass cache configuration and callback function pointers to the stack.
USB_CHECK_ADDRESS_FUNC Checks if an address can be used for DMA transfers.
USB_WEBUSB_INFO Information that may be provided by the application for WebUSB capable USB devices.

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.

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_Init()

Description

Initializes the USB device with its settings.

Prototype

void USBD_Init(void);
USBD_IsConfigured()

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.24a

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 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

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().

USB_ON_CLASS_REQUEST is defined as follows:

typedef  int  USB_ON_CLASS_REQUEST(const  USB_SETUP_PACKET  *  pSetupPacket);
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().

USB_ON_CLASS_REQUEST is defined as follows:

typedef  int  USB_ON_CLASS_REQUEST(const  USB_SETUP_PACKET  *  pSetupPacket);
USBD_SetIsSelfPowered()

Description

Sets whether the device is self-powered or not.

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.

Prototype

void USBD_SetMaxPower(unsigned MaxPower);

Parameters

Parameter Description
MaxPower Current consumption of the device given in mA. MaxPower shall be in range between 0mA - 500mA.

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().

USB_ON_SETUP is defined as follows:

typedef int USB_ON_SETUP(const USB_SETUP_PACKET * pSetupPacket);
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_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. This function should be called before after USBD_Start(). Use only, if the device supports link power management (LPM).

Prototype

void USBD_UseV210(void);
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, 1 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.

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().

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.

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_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).

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_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.

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.

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”.

Dummy

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.

Data structures

USB_ADD_EP_INFO

Description

Structure used by USBD_AddEPEx() when adding an endpoint.

Type definition

typedef struct {
  U8        Flags;
  U8        InDir;
  U8        TransferType;
  U16       Interval;
  unsigned  MaxPacketSize;
  U8        ISO_Type;
} USB_ADD_EP_INFO;

Structure members

Member Description
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
Interval Specifies the interval measured in units of 125us (microframes). This value should be zero for a bulk endpoint.
MaxPacketSize Maximum packet size for the endpoint.
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

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.

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:

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/WindowsApplication/Exe.

For example: The application USB_BULK_Echo1.c is a modified echo server; the application receives data byte by byte, increments every single byte and sends it back to the host.

Bulk Application

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_ , for example, if the host runs Echo1.exe, USB_BULK_Echo1.c has to be included into your project, compiled and downloaded into your target. There are additional examples that can be used for testing emUSB-Device.

The following start application files are provided:

File Description
USB_BULK_Echo1.c This application was described in the upper text.
USB_BULK_Test.c This application can be used to test emUSB-Device-Bulk with different packet sizes received from and sent to the PC host.
USB_BULK_Performance.c Measures BULK data throughput.

The example applications for the target-side are supplied in source code in the Application directory.

Depending on which application is running on the emUSB-Device device, use one of the following example applications:

File Description
Echo1.exe If the USB_BULK_Echo1.c sample application is running on the emUSB-Device-Bulk device, use this application.
Test.exe If the USB_BULK_Test.c application is running on the emUSB-Device-Bulk device, use this application to test the emUSB-Device-Bulk stack.
Performance.exe If the USB_BULK_Performace.c application is running on the emUSB-Device-Bulk device, use this application to measures BULK data throughput.

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 Echo1.exe:

Bulk Echo1

If the host example application can communicate with the emUSB-Device device, the example application will be in interactive mode for the Echo1 and the EchoFast application. In case of an error, a message box is displayed.

Error Messages Description
Unable to connect to USB BULK device The USB device is not connected to the PC or the connection is faulty.
Could not write to device The PC sample application was not able to write.
Could not read from device (time-out) The PC sample application was not able to read.
Wrong data read The result of the target sample application is not correct.

Compiling the PC example application

Windows

For compiling the example application you need Visual C++ 2010 (or later).

USB Bulk workspace

The source code of the sample application is located in the subfolder Windows\USB\Bulk\WindowsApplication. Open the file USBBULK_Start.sln and compile the source.

Linux

The subfolder Windows\USB\Bulk\WindowsApplication contains a Makefile for Linux. Change to this folder and execute “make”.

macOS

The subfolder Windows\USB\Bulk\WindowsApplication 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

Routine Explanation
USB-Bulk functions
USBD_BULK_Add() Adds interface for USB-Bulk communication to emUSB-Device.
USBD_BULK_Add_Ex() Adds interface for USB-Bulk communication to emUSB-Device.
USBD_BULK_AddAlternateInterface() Adds an alternative interface for USB-Bulk interface.
USBD_BULK_SetMSDescInfo() Enables use of Microsoft OS Descriptors.
USBD_BULK_CancelRead() Cancels any non-blocking/blocking read operation that is pending.
USBD_BULK_CancelWrite() Cancels any non-blocking/blocking write operation that is pending.
USBD_BULK_GetNumBytesInBuffer() Returns the number of bytes that are available in the internal BULK-OUT endpoint buffer.
USBD_BULK_GetNumBytesRemToRead() Get the number of remaining bytes to read by an active read operation.
USBD_BULK_GetNumBytesRemToWrite() After starting a non-blocking write operation this function can be used to periodically check how many bytes still have to be written.
USBD_BULK_Read() Reads data from the host with a given timeout.
USBD_BULK_ReadAsync() Reads data from the host asynchronously.
USBD_BULK_ReadOverlapped() Reads data from the host asynchronously.
USBD_BULK_Receive() Reads data from the host.
USBD_BULK_ReceivePoll() Reads data from the host.
USBD_BULK_SetContinuousReadMode() Enables continuous read mode for the RX endpoint.
USBD_BULK_SetOnRXEvent() Sets a callback function for the OUT endpoint that will be called on every RX event for that endpoint.
USBD_BULK_SetOnTXEvent() Sets a callback function for the IN endpoint that will be called on every TX event for that endpoint.
USBD_BULK_TxIsPending() Checks whether the TX (IN endpoint) is currently pending.
USBD_BULK_WaitForRX() Waits (blocking) until the triggered USBD_BULK_ReadOverlapped() has received the desired data.
USBD_BULK_PollForRX() Waits (blocking) until the triggered USBD_BULK_ReadOverlapped() has received the desired data.
USBD_BULK_WaitForTX() Waits (blocking) until the triggered USBD_BULK_WriteOverlapped() has sent the desired data.
USBD_BULK_WaitForTXReady() Waits (blocking) until the TX queue can accept another data packet.
USBD_BULK_Write() Sends data to the USB host.
USBD_BULK_WriteAsync() Sends data to the host asynchronously.
USBD_BULK_WriteEx() Send data to the USB host with NULL packet control.

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

Parameter Description
pInitData Pointer to USB_BULK_INIT_DATA structure.

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

Parameter Description
pInitData Pointer to USB_BULK_INIT_DATA_EX structure.

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.

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().

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.

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_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 USBD_BULK_WaitForRX(USB_BULK_HANDLE hInst,
                        unsigned        Timeout);

Parameters

Parameter Description
hInst Handle to a valid BULK instance, returned by USBD_BULK_Add().
Timeout Timeout in milliseconds. 0 means infinite.

Return value

= 0 Transfer completed.
= 1 Timeout occurred.
< 0 An error occurred (e.g. target disconnected)

Additional information

In case of a timeout, the current transfer is canceled.

Example

if (USBD_BULK_ReadOverlapped(hInst, &ac[0], 50) < 0) {
  <.. error handling..>
  return;
}
//
// USBD_BULK_ReadOverlapped() will return immediately.
// Do something else while data may be transferred.
//
<...>
//
// Now wait until we get all 50 bytes.
// USBD_BULK_WaitForRX() will block, until total of
// 50 bytes are read or timeout occurs.
//
if (USBD_BULK_WaitForRX(hInst, timeout) != 0) {
  <.. timeout error handling..>
  return;
}
// Now we have 50 bytes of data.
// Process 50 bytes of data from ac[] here.
USBD_BULK_PollForRX()

Description

Waits (blocking) until the triggered USBD_BULK_ReadOverlapped() has received the desired data.

Prototype

int USBD_BULK_PollForRX(USB_BULK_HANDLE hInst,
                        unsigned        Timeout);

Parameters

Parameter Description
hInst Handle to a valid BULK instance, returned by USBD_BULK_Add().
Timeout Timeout in milliseconds. 0 means infinite.

Return value

= 0 Transfer completed.
= 1 Timeout occurred.
< 0 An error occurred (e.g. target disconnected)

Additional information

In case of a timeout, the current transfer is not affected. The function may be called repeatedly until it does not report a timeout any more.

USBD_BULK_WaitForTX()

Description

Waits (blocking) until the triggered USBD_BULK_WriteOverlapped() has sent the desired data.

Prototype

int USBD_BULK_WaitForTX(USB_BULK_HANDLE hInst,
                        unsigned        Timeout);

Parameters

Parameter Description
hInst Handle to a valid BULK instance, returned by USBD_BULK_Add().
Timeout Timeout in milliseconds. 0 means infinite.

Return value

= 0 Transfer completed.
= 1 Timeout occurred.
< 0 An error occurred (e.g. target disconnected)

Additional information

In case of a timeout, a current transfer is canceled.

USBD_BULK_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_BULK_Write() , it waits until a new asynchronous write data transfer will be accepted by the USB stack.

Prototype

int USBD_BULK_WaitForTXReady(USB_BULK_HANDLE hInst,
                             int             Timeout);

Parameters

Parameter Description
hInst Handle to a valid BULK instance, returned by USBD_BULK_Add().
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_BULK_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.

Example

// Always keep the write queue full for maximum send speed.
for (;;) {
  pData = GetNextData(&NumBytes);
  // Wait until stack can accept a new write.
  USBD_BULK_WaitForTxReady(hInst, 0);
  // Issue write transfer.
  if (USBD_BULK_Write(hInst, pData, NumBytes, -1) < 0) {
    <.. error handling..>
  }
}
USBD_BULK_Write()

Description

Sends data to the USB host. Depending on the Timeout parameter, the function blocks until NumBytes have been written or a timeout occurs.

Prototype

int USBD_BULK_Write(      USB_BULK_HANDLE   hInst,
                    const void            * pData,
                          unsigned          NumBytes,
                          int               Timeout);

Parameters

Parameter Description
hInst Handle to a valid BULK instance, returned by USBD_BULK_Add().
pData Data that should be written.
NumBytes Number of bytes to write.
Timeout 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 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 (when using 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 or a timeout occurs.

In order to synchronize, USBD_BULK_WaitForTX() needs to be called. Another synchronization method would be to periodically call USBD_BULK_GetNumBytesRemToWrite() in order to see how many bytes still need to be written (this method is preferred when a non-blocking solution is necessary). The write operation can be canceled using USBD_BULK_CancelWrite().

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.

Example

NumBytesWritten = USBD_BULK_Write(hInst, &ac[0], DataSize, 500);
if (NumBytesWritten <= 0) {
  <.. error handling..>
}
if (NumBytesWritten < DataSize) {
  <.. timeout occurred, data partially written within 500ms ..>
} else {
  <.. write completed successfully..>
}

See also USBD_BULK_GetNumBytesRemToWrite.

USBD_BULK_WriteAsync()

Description

Sends data to the host asynchronously. The function does not block. A callback function is called after the transfer has completed successfully, an error occurred or the transfer was canceled.

Prototype

void USBD_BULK_WriteAsync(USB_BULK_HANDLE        hInst,
                          USB_ASYNC_IO_CONTEXT * pContext,
                          char                   Send0PacketIfRequired);

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.
Send0PacketIfRequired Specifies that a zero-length packet shall be sent when the last data packet is a multiple of MaxPacketSize.

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_WriteAsync(hInst, &IOContext, 1);
while (AsyncComplete == 0) {
  <.. Do other work. ..>
}
// Transaction is complete.
if (IOContext.Status < 0 || IOContext.NumBytesTransferred != 5000) {
  <.. error handling ..>
} else {
  <.. data written successfully ..>
}
<...>
USBD_BULK_WriteEx()

Description

Send data to the USB host with NULL packet control. This function behaves exactly like USBD_BULK_Write(). Additionally sending of a zero length packet after sending the data can be suppressed by setting Send0PacketIfRequired = 0.

Prototype

int USBD_BULK_WriteEx(      USB_BULK_HANDLE   hInst,
                      const void            * pData,
                            unsigned          NumBytes,
                            char              Send0PacketIfRequired,
                            int               Timeout);

Parameters

Parameter Description
hInst Handle to a valid BULK instance, returned by USBD_BULK_Add().
pData Pointer to a buffer that contains the written data.
NumBytes Number of bytes to write.
Send0PacketIfRequired Specifies that a zero-length packet shall be sent when the last data packet is a multiple of MaxPacketSize. Normally MaxPacketSize for full-speed devices is 64 bytes. For high-speed devices the normal packet size is between 64 and 512 bytes.
Timeout 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 Error occurred.

Additional information

Normally USBD_BULK_Write() is called to let the stack send the data to the host and send an optional zero-length packet to tell the host that this was the last packet. This is the case when the last packet sent is MaxPacketSize bytes in size. When using this function, the zero-length packet handling can be controlled. This means the function can be called when sending data in multiple steps.

Example

// for high-speed devices
USBD_BULK_Write(hInst, _aBuffer1, 512, 0);
USBD_BULK_Write(hInst, _aBuffer2, 512, 0);
USBD_BULK_Write(hInst, _aBuffer3, 512, 0);
// this will send 6 packets to the host with sizes: 512, 0, 512, 0, 512, 0
USBD_BULK_WriteEx(hInst, _aBuffer1, 512, 0, 0);
USBD_BULK_WriteEx(hInst, _aBuffer2, 512, 0, 0);
USBD_BULK_WriteEx(hInst, _aBuffer3, 512, 1, 0);
// this will send 4 packets to the host with sizes: 512, 512, 512, 0

Data structures

USB_BULK_INIT_DATA

Description

Initialization structure that is needed when adding a BULK interface to emUSB-Device.

Type definition

typedef struct {
  U8  EPIn;
  U8  EPOut;
} USB_BULK_INIT_DATA;

Structure members

Member Description
EPIn Endpoint for sending data to the host.
EPOut Endpoint for receiving data from the host.
USB_BULK_INIT_DATA_EX

Description

Initialization structure that is needed when adding a BULK interface to emUSB-Device.

Type definition

typedef struct {
  U16          Flags;
  U8           EPIn;
  U8           EPOut;
  const char * pInterfaceName;
} USB_BULK_INIT_DATA_EX;

Structure members

Member Description
Flags Reserved for future use, must be 0.
EPIn Endpoint for sending data to the host.
EPOut Endpoint for receiving data from the host.
pInterfaceName Name of the interface.

Host API

This chapter describes the functions that can be used with the host system.

To communicate with the target USB-Bulk stack an API is provided that can be used on Windows, Linux and macOS systems.

To have an easy start-up when writing an application on the host side, these API functions have a simple interface and handle all required operations to communicate with the target USB-Bulk stack.

Therefore, all operations that need to open a channel, writing to or reading from the USB-Bulk stack, are handled internally by the provided API functions.

To use the API in an application the header file USBBULK.h must be included. Depending on the host operating system used the following components must be added to the host application:

Bulk Host API list

The functions below are available on the host (PC) side.

Function Description
USB-Bulk Basic functions
USBBULK_Init() This function needs to be called first.
USBBULK_Exit() This is a cleanup function, it shall be called when exiting the application.
USBBULK_AddAllowedDeviceItem() Adds the Vendor and Product ID to the list of devices the USBBULK API should look for.
USBBULK_GetNumAvailableDevices() Returns the number of connected USB-Bulk devices.
USBBULK_Open() Opens an existing device.
USBBULK_Close() Closes an opened device.
USB-Bulk direct input/output functions
USBBULK_Read() Reads data from target device running emUSB-Device-Bulk.
USBBULK_ReadTimed() Reads data from target device running emUSB-Device-Bulk within a given timeout.
USBBULK_Write() Writes data to the device.
USBBULK_WriteTimed() Writes data to the device within a given timeout.
USBBULK_CancelRead() This cancels an initiated read.
USBBULK_FlushRx() Flush the any received data.
USB-Bulk Control functions
USBBULK_SetMode() Sets the read and write mode for a specified device running emUSB-Device-Bulk.
USBBULK_GetMode() Returns the current mode of the device.
USBBULK_SetReadTimeout() Sets the default read timeout for an opened device.
USBBULK_SetWriteTimeout() Sets a default write timeout for an opened device.
USBBULK_ResetINPipe() Resets the IN pipe that is opened to the device.
USBBULK_ResetOUTPipe() Resets the OUT pipe that is opened to the device.
USBBULK_ResetDevice() Resets the device via a USB reset.
USB-Bulk general GET functions
USBBULK_GetVersion() Returns the version number of the USBBULK API.
USBBULK_GetDevInfo() Retrieves information about an opened USBBULK device.
USBBULK_GetDevInfoByIdx() Retrieves information about a USB device.
USBBULK_GetUSBId() Returns the Product and Vendor ID of an opened device.
USBBULK_GetProductName() Retrieves the device/product name if available.
USBBULK_GetVendorName() Retrieves the vendor name of an opened USBBULK device.
USBBULK_GetSN() Retrieves the USB serial number as a string which was sent by the device during the enumeration.
USBBULK_GetConfigDescriptor() Gets the received target USB configuration descriptor of a specified device.
Data structures
USBBULK_DEV_INFO

USB-Bulk basic functions

USBBULK_Init()

Description

This function needs to be called first. This makes sure to have all structures and thread have been initialized. It also sets a callback in order to be notified when a device is added or removed.

Prototype

void USBBULK_Init(USBBULK_NOTIFICATION_FUNC * pfNotification,
                  void                      * pContext);

Parameters

Parameter Description
pfNotification Pointer to the user callback.
pContext Context data that shall be called with the callback function.

Example

/*********************************************************************
*
*       _OnDevNotify
*
*  Function description:
*    Is called when a new device is found or an existing device is removed.
*
*  Parameters:
*    pContext  - Pointer to a context given when USBBULK_Init is called
*    Index     - Device Index that has been added or removed.
*    Event     - Type of event, currently the following are available:
*                  USBBULK_DEVICE_EVENT_ADD
*                  USBBULK_DEVICE_EVENT_REMOVE
*
*/
static void _OnDevNotify(void * pContext,
                         unsigned Index,
                         USBBULK_DEVICE_EVENT Event) {
  switch(Event) {
  case USBBULK_DEVICE_EVENT_ADD:
    printf("The following DevIndex has been added: %d", Index);
    NumDevices = USBBULK_GetNumAvailableDevices(&DeviceMask);
    break;
  case USBBULK_DEVICE_EVENT_REMOVE:
    printf("The following DevIndex has been removed: %d", Index);
    NumDevices = USBBULK_GetNumAvailableDevices(&DeviceMask);
    break;
  }
}
void MainTask(void) {
<...>
  USBBULK_Init(_OnDevNotify, NULL);
<...>
}
USBBULK_Exit()

Description

This is a cleanup function, it shall be called when exiting the application.

Prototype

void USBBULK_Exit(void);

Additional information

We recommend to call this function before exiting the application in order to remove all handles and resources that have been allocated.

USBBULK_AddAllowedDeviceItem()

Description

Adds the Vendor and Product ID to the list of devices the USBBULK API should look for.

Prototype

void USBBULK_AddAllowedDeviceItem(U16 VendorId,
                                  U16 ProductId);

Parameters

Parameter Description
VendorId The desired Vendor ID mask that shall be used with the USBBULK API.
ProductId The desired Product ID mask that shall be used with the USBBULK API.

Additional information

It is necessary to call this function first before calling USBBULK_GetNumAvailableDevices() or opening any connection to a device.

The function can be called multiple times to handle more than one pair of Vendor and Product IDs with the API.

USBBULK_GetNumAvailableDevices()

Description

Returns the number of connected USB-Bulk devices.

Prototype

unsigned USBBULK_GetNumAvailableDevices(U32 * pMask);

Parameters

Parameter Description
pMask Pointer to a U32 variable to receive the connected device mask. This parameter can be NULL.

Return value

Number of available devices running emUSB-Device-Bulk.

Additional information

For each emUSB-Device device that is connected, a bit in pMask is set. For example if device 0 and device 2 are connected to the host, the value pMask points to will be 0x00000005.

USBBULK_Open()

Description

Opens an existing device. The ID of the device can be retrieved by the function USBBULK_GetNumAvailableDevices() via the pDeviceMask parameter. Each bit set in the DeviceMask represents an available device. Currently 32 devices can be managed at once.

Prototype

USB_BULK_HANDLE USBBULK_Open(unsigned Id);

Parameters

Parameter Description
Id Device ID to be opened (0..31).

Return value

≠ 0 Handle to the opened device.
= 0 Error occurred.
USBBULK_Close()

Description

Closes an opened device.

Prototype

void USBBULK_Close(USB_BULK_HANDLE hDevice);

Parameters

Parameter Description
hDevice Handle to the device that shall be closed.

USB-Bulk direct input/output functions

USBBULK_Read()

Description

Reads data from target device running emUSB-Device-Bulk.

Prototype

int USBBULK_Read(USB_BULK_HANDLE   hDevice,
                 void            * pBuffer,
                 int               NumBytes);

Parameters

Parameter Description
hDevice Handle to the opened device.
pBuffer Pointer to a buffer that shall receive the data.
NumBytes Number of bytes to be read.

Return value

= NumBytes All bytes have been successfully read.
> 0, < NumBytes Number of bytes that have been read. If short read transfers are not allowed (normal mode) this indicates a timeout.
= 0 A timeout occurred, no data was read.
< 0 Error occurred.

Additional information

If short read transfers are allowed (see USBBULK_SetMode()) the function returns as soon as data is available, even if just a single byte was read. Otherwise the function blocks until NumBytes were read. In both cases the function returns if a timeout occurs. The default timeout used can be set with USBBULK_SetReadTimeout().

If NumBytes exceeds the maximum read size the driver can handle (the default value is 64 Kbytes), USBBULK_Read() will read the desired NumBytes in chunks of the maximum read size.

USBBULK_ReadTimed()

Description

Reads data from target device running emUSB-Device-Bulk within a given timeout.

Prototype

int USBBULK_ReadTimed(USB_BULK_HANDLE   hDevice,
                      void            * pBuffer,
                      int               NumBytes,
                      unsigned          ms);

Parameters

Parameter Description
hDevice Handle to the opened device.
pBuffer Pointer to a buffer that shall receive the data.
NumBytes Maximum number of bytes to be read.
ms Timeout in milliseconds.

Return value

> 0 Number of bytes that have been read.
= 0 A timeout occurred during read.
< 0 Error, cannot read from the device.

Additional information

The function returns as soon as data is available, even if just a single byte was read. If no data is available, the functions return after the given timeout was expired.

If NumBytes exceeds the maximum read size the driver can handle (the default value is 64 Kbytes), USBBULK_ReadTimed() will read the desired NumBytes in chunks of the maximum read size.

USBBULK_Write()

Description

Writes data to the device.

Prototype

int USBBULK_Write(      USB_BULK_HANDLE   hDevice,
                  const void            * pBuffer,
                        int               NumBytes);

Parameters

Parameter Description
hDevice Handle to the opened device.
pBuffer Pointer to a buffer that contains the data.
NumBytes Number of bytes to be written. If NumBytes = 0, a zero length packet is written to the device.

Return value

= NumBytes All bytes have been successfully written.
> 0, < NumBytes Number of bytes that have been written. If short read transfers are not allowed (normal mode) this indicates a timeout.
= 0 A timeout occurred, no data was written.
< 0 Error, cannot write to the device.

Additional information

If short write transfers are allowed (see USBBULK_SetMode()) the function returns after writing the minimal amount of data (either NumBytes or the maximal write transfer size). Otherwise the function blocks until NumBytes were written. In both cases the function returns if a timeout occurs. The default timeout used can be set with USBBULK_SetWriteTimeout().

If NumBytes exceeds the maximum write size the driver can handle (the default value is 64 Kbytes), USBBULK_Write() will write the desired NumBytes in chunks of the maximum write size.

USBBULK_WriteTimed()

Description

Writes data to the device within a given timeout.

Prototype

int USBBULK_WriteTimed(      USB_BULK_HANDLE   hDevice,
                       const void            * pBuffer,
                             int               NumBytes,
                             unsigned          ms);

Parameters

Parameter Description
hDevice Handle to the opened device.
pBuffer Pointer to a buffer that contains the data.
NumBytes Number of bytes to be written. If NumBytes = 0, a zero length packet is written to the device.
ms Timeout in milliseconds.

Return value

= NumBytes All bytes have been successfully written.
> 0, < NumBytes Number of bytes that have been written. If short read transfers are not allowed (normal mode) this indicates a timeout.
= 0 A timeout occurred, no data was written.
< 0 Error, cannot write to the device.

Additional information

If short write transfers are allowed (see USBBULK_SetMode()) the function returns after writing the minimal amount of data (either NumBytes or the maximal write transfer size). Otherwise the function blocks until NumBytes were written. In both cases the function returns if a timeout occurs.

If NumBytes exceeds the maximum write size the driver can handle (the default value is 64 Kbytes), USBBULK_WriteTimed() will write the desired NumBytes in chunks of the maximum write size.

USBBULK_CancelRead()

Description

This cancels an initiated read.

Prototype

void USBBULK_CancelRead(USB_BULK_HANDLE hDevice);

Parameters

Parameter Description
hDevice Handle to the opened device.

Additional information

Not supported on Linux and MacOSX.

USBBULK_FlushRx()

Description

Flush the any received data.

Prototype

int USBBULK_FlushRx(USB_BULK_HANDLE hDevice);

Parameters

Parameter Description
hDevice Handle to the opened device.

Return value

= 0 Error, bad handle.
≠ 0 Success, flushing the RX buffer was successful.

USB-Bulk control functions

USBBULK_SetMode()

Description

Sets the read and write mode for a specified device running emUSB-Device-Bulk.

Prototype

unsigned USBBULK_SetMode(USB_BULK_HANDLE hDevice,
                         unsigned        Mode);

Parameters

Parameter Description
hDevice Handle to the opened device.
Mode Read and write mode for the USB-Bulk driver. This is a combination of the following flags, combined by binary or: USBBULK_MODE_BIT_ALLOW_SHORT_READ USBBULK_MODE_BIT_ALLOW_SHORT_WRITE

Return value

= 0 Operation failed (invalid handle).
≠ 0 The operation was successful.

Additional information

USBBULK_MODE_BIT_ALLOW_SHORT_READ allows short read transfers. Short transfers are transfers of less bytes than requested. If this bit is specified, the read function USBBULK_Read() returns as soon as data is available, even if it is just a single byte.

USBBULK_MODE_BIT_ALLOW_SHORT_WRITE allows short write transfers. USBBULK_Write() and USBBULK_WriteTimed() return after writing the minimal amount of data (either NumBytes or the maximal write transfer size).

Example

static void _TestMode(USB_BULK_HANDLE hDevice) {
  unsigned  Mode;
  char    * pText;
  Mode = USBBULK_GetMode(hDevice);
  if (Mode & USBBULK_MODE_BIT_ALLOW_SHORT_READ) {
    pText = "USE_SHORT_MODE";
  } else {
    pText = "USE_NORMAL_MODE";
  }
  printf("USB-Bulk driver is in %s for device %d\n", pText, (int)hDevice);
  printf("Set mode to USBBULK_MODE_BIT_ALLOW_SHORT_READ\n");
  USBBULK_SetMode(hDevice, USBBULK_MODE_BIT_ALLOW_SHORT_READ);
  Mode = USBBULK_GetMode(hDevice);
  if (Mode & USBBULK_MODE_BIT_ALLOW_SHORT_READ) {
    pText = "USE_SHORT_MODE";
  } else {
    pText = "USE_NORMAL_MODE";
  }
  printf("USB-Bulk driver is now in %s for device %d\n", pText,(int)hDevice);
}
USBBULK_GetMode()

Description

Returns the current mode of the device.

Prototype

unsigned USBBULK_GetMode(USB_BULK_HANDLE hDevice);

Parameters

Parameter Description
hDevice Handle to the opened device.

Return value

A combination of the following flags, combined by binary or:

USBBULK_SetReadTimeout()

Description

Sets the default read timeout for an opened device.

Prototype

void USBBULK_SetReadTimeout(USB_BULK_HANDLE hDevice,
                            int             Timeout);

Parameters

Parameter Description
hDevice Handle to the opened device.
Timeout Timeout in milliseconds.
USBBULK_SetWriteTimeout()

Description

Sets a default write timeout for an opened device.

Prototype

void USBBULK_SetWriteTimeout(USB_BULK_HANDLE hDevice,
                             int             Timeout);

Parameters

Parameter Description
hDevice Handle to the opened device.
Timeout Timeout in milliseconds.
USBBULK_ResetINPipe()

Description

Resets the IN pipe that is opened to the device. It also flushes any data the USB bulk driver would cache.

Prototype

int USBBULK_ResetINPipe(USB_BULK_HANDLE hDevice);

Parameters

Parameter Description
hDevice Handle to the opened device.

Return value

≠ 0 The operation was successful.
= 0 Operation failed. Either an invalid handle was used or the pipe cannot be flushed.
USBBULK_ResetOUTPipe()

Description

Resets the OUT pipe that is opened to the device.

Prototype

int USBBULK_ResetOUTPipe(USB_BULK_HANDLE hDevice);

Parameters

Parameter Description
hDevice Handle to the opened device.

Return value

≠ 0 The operation was successful.
= 0 Operation failed. Either an invalid handle was used or the pipe cannot be flushed.
USBBULK_ResetDevice()

Description

Resets the device via a USB reset. This can be used when the device does not work properly and may be reactivated via USB reset. This will force a re-enumeration of the device.

Prototype

int USBBULK_ResetDevice(USB_BULK_HANDLE hDevice);

Parameters

Parameter Description
hDevice Handle to the opened device.

Return value

≠ 0 The operation was successful.
= 0 Operation failed. Either an invalid handle was used or the device cannot be reset.

Additional information

After the device has been reset it is necessary to re-open the device as the current handle will become invalid.

USB-Bulk general GET functions

USBBULK_GetVersion()

Description

Returns the version number of the USBBULK API.

Prototype

unsigned USBBULK_GetVersion(void);

Return value

Version number, format:

< Major Version><Minor Version><Subversion> (Mmmrr, decimal).

Example: 30203 is 3.02c

USBBULK_GetDevInfo()

Description

Retrieves information about an opened USBBULK device.

Prototype

void USBBULK_GetDevInfo(USB_BULK_HANDLE    hDevice,
                        USBBULK_DEV_INFO * pDevInfo);

Parameters

Parameter Description
hDevice Handle to the opened device.
pDevInfo Pointer to a device info structure of type USBBULK_DEV_INFO
USBBULK_GetDevInfoByIdx()

Description

Retrieves information about a USB device.

Prototype

int USBBULK_GetDevInfoByIdx(unsigned           Idx,
                            USBBULK_DEV_INFO * pDevInfo);

Parameters

Parameter Description
Idx Index of the device.
pDevInfo Pointer to a device info structure of type USBBULK_DEV_INFO

Return value

= 0; Error, bad device index.
≠ 0 Success
USBBULK_GetUSBId()

Description

Returns the Product and Vendor ID of an opened device.

Prototype

void USBBULK_GetUSBId(USB_BULK_HANDLE   hDevice,
                      U16             * pVendorId,
                      U16             * pProductId);

Parameters

Parameter Description
hDevice Handle to the opened device.
pVendorId Pointer to a variable that receives the Vendor ID.
pProductId Pointer to a variable that receives the Product ID.
USBBULK_GetProductName()

Description

Retrieves the device/product name if available.

Prototype

int USBBULK_GetProductName(USB_BULK_HANDLE   hDevice,
                           char            * sProductName,
                           unsigned          BufferSize);

Parameters

Parameter Description
hDevice Handle to the opened device.
sProductName Pointer to a buffer that should receive the string.
BufferSize Size of the buffer, given in bytes.

Return value

= 0 Error, product name not available or buffer to small.
≠ 0 Success, product name stored in buffer pointed by sProductName as 0-terminated string.
USBBULK_GetVendorName()

Description

Retrieves the vendor name of an opened USBBULK device.

Prototype

int USBBULK_GetVendorName(USB_BULK_HANDLE   hDevice,
                          char            * sVendorName,
                          unsigned          BufferSize);

Parameters

Parameter Description
hDevice Handle to the opened device.
sVendorName Pointer to a buffer that should receive the string.
BufferSize Size of the buffer, given in bytes.

Return value

= 0 Error, bad handle.
≠ 0 Success, vendor name stored in buffer pointed by sVendorName as 0-terminated string.
USBBULK_GetSN()

Description

Retrieves the USB serial number as a string which was sent by the device during the enumeration.

Prototype

int USBBULK_GetSN(USB_BULK_HANDLE   hDevice,
                  U8              * pBuffer,
                  unsigned          BuffSize);

Parameters

Parameter Description
hDevice Handle to the opened device.
pBuffer Pointer to a buffer which shall receive the serial number of the device.
BuffSize Size of the buffer in bytes.

Return value

= 0 Operation failed. Either an invalid handle was used or the serial number is not available.
≠ 0 The operation was successful.

Additional information

If the function succeeds, the buffer pointed by pBuffer contains the serial number of the device as 0-terminated string. If BuffSize is too small, the serial number is truncated.

USBBULK_GetConfigDescriptor()

Description

Gets the received target USB configuration descriptor of a specified device.

Prototype

int USBBULK_GetConfigDescriptor(USB_BULK_HANDLE   hDevice,
                                void            * pBuffer,
                                int               Size);

Parameters

Parameter Description
hDevice Handle to the opened device.
pBuffer Pointer to the buffer that shall store the descriptor.
Size Size of the buffer, given in bytes.

Return value

≠ 0 Size of the returned USB configuration descriptor (Success).
= 0 Operation failed. Either an invalid handle was used or the buffer that shall store the config descriptor is too small.

USB-Bulk data structures

USBBULK_DEV_INFO

Type definition

typedef struct {
  U16   VendorId;
  U16   ProductId;
  char  acSN[];
  char  acDevName[];
  U8    InterfaceNo;
  U8    Speed;
} USBBULK_DEV_INFO;

Structure members

Member Description
VendorId Vendor ID of the device.
ProductId Product ID of the device.
acSN 0-terminated string which holds the serial number of the device.
acDevName 0-terminated string which holds the device name.
InterfaceNo Interface number used by this device.
Speed Device speed. One of the following: USBBULK_SPEED_UNKNOWN USBBULK_SPEED_LOW USBBULK_SPEED_FULL USBBULK_SPEED_HIGH USBBULK_SPEED_SUPER

Mass Storage Device Class (MSD)

This chapter gives a general overview of the MSD class and describes how to get the MSD component running on the target.

Overview

The Mass Storage Device (MSD) is a USB class protocol defined by the USB Implementers Forum. The class itself is used to access one or more storage devices such as flash drives or memory sticks.

As the USB mass storage device class is well standardized, every major operating system such as Microsoft Windows (after Windows 2000), Apple OS X, Linux and many more support it. So therefore an installation of a custom host USB driver is normally not necessary.

emUSB-Device-MSD comes as a whole packet and contains the following:

MSD Configuration

Initial configuration

To get emUSB-Device-MSD up and running as well as doing an initial test, the configuration as it is delivered should not be modified.

Final configuration

The configuration must only be modified, when emUSB-Device is deployed in your final product. Refer to emUSB-Device Configuration for detailed information about the generic information functions which must be adapted.

In order to comply with the Mass Storage Device Bootability specification, the serial number provided by the function USBD_SetDeviceInfo() must be a string with at least 12 characters, where each character is a hexadecimal digit (’0’ through ’9’ or ’A’ through ’F’).

MSD class specific configuration functions

Beside the generic emUSB-Device configuration functions (emUSB-Device Configuration), the following should be adapted before the emUSB-Device MSD component is used in a final product. Example implementations are supplied in the MSD example application USB_MSD_FS_Start.c, located in the Application directory of emUSB-Device.

Each logical unit (storage) which is added to the MSD component has it’s own set of name and id values which is supplied when the logical unit is first added through USBD_MSD_AddUnit()

Example

static const USB_MSD_LUN_INFO _Lun0Info = {
  "Vendor",     // MSD VendorName
  "MSD Volume", // MSD ProductName
  "1.00",       // MSD ProductVer
  "134657890"   // MSD SerialNo
};
...
InstData.pLunInfo = &_Lun0Info;
...
USB_MSD_AddUnit(&InstData);

Running the example application

The directory Application contains example applications that can be used with emUSB-Device and the MSD component. To test the emUSB-Device-MSD component, build and download the application of choice into the target. Remove the USB connection and reconnect the target to the host. The target will enumerate and can be accessed via a file browser.

MSD_Start_StorageRAM.c in detail

The main part of the example application USB_MSD_Start_StorageRAM.c is implemented in a single task called MainTask().

/* MainTask() - excerpt from USB_MSD_Start_StorageRAM.c */
void MainTask(void);
void MainTask(void) {
  USBD_Init();
  _AddMSD();
  USBD_Start();
  while (1) {
    while ((USBD_GetState() & (USB_STAT_CONFIGURED | USB_STAT_SUSPENDED))
            != USB_STAT_CONFIGURED) {
      BSP_ToggleLED(0);
      USB_OS_Delay(50);
    }
    BSP_SetLED(0);
    USBD_MSD_Task();
  }
}

The first step is to initialize the USB core stack using USBD_Init(). The function _AddMSD() configures all required endpoints and assigns the used storage medium to the MSD component.

/* _AddMSD() - excerpt from MSD_Start_StorageRAM.c */
static void _AddMSD(void) {
  static U8 _abOutBuffer[USB_HS_BULK_MAX_PACKET_SIZE];
  USB_MSD_INIT_DATA     InitData;
  USB_MSD_INST_DATA     InstData;
  InitData.EPIn  = USBD_AddEP(1, USB_TRANSFER_TYPE_BULK,
                              USB_HS_BULK_MAX_PACKET_SIZE, NULL, 0);
  InitData.EPOut = USBD_AddEP(0, USB_TRANSFER_TYPE_BULK,
                              USB_HS_BULK_MAX_PACKET_SIZE,
                              _abOutBuffer, sizeof(_abOutBuffer));
  USBD_MSD_Add(&InitData);
  //
  // Add logical unit 0: RAM drive
  //
  memset(&InstData, 0,  sizeof(InstData));
  InstData.pAPI                    = &USB_MSD_StorageRAM;
  InstData.DriverData.pStart       = (void*)MSD_RAM_ADDR;
  InstData.DriverData.NumSectors   = MSD_RAM_NUM_SECTORS;
  InstData.DriverData.SectorSize   = MSD_RAM_SECTOR_SIZE;
  InstData.pLunInfo = &_Lun0Info;
  USBD_MSD_AddUnit(&InstData);
}

The example application uses a RAM disk as storage medium.

The example RAM disk has a size of 23 kB (46 sectors with a sector size of 512 bytes). You can increase the size of the RAM disk by modifying the macros MSD_RAM_NUM_SECTORS and MSD_RAM_SECTOR_SIZE (in multiples of 512), but the size must be at least 23 kB otherwise a Windows host cannot format the disk.

/* AddMSD() - excerpt from MSD_Start_StorageRAM.c */
#define MSD_RAM_NUM_SECTORS  46
#define MSD_RAM_SECTOR_SIZE  512

Target API

Function Description
API functions
USBD_MSD_Add() Adds an MSD-class interface to the USB stack.
USBD_MSD_AddUnit() Adds a mass storage device to emUSB-Device-MSD.
USBD_MSD_AddCDRom() Adds a CD-ROM device to emUSB-Device-MSD.
USBD_MSD_SetPreventAllowRemovalHook() Sets a callback function to prevent/allow removal of storage medium.
USBD_MSD_SetReadWriteHook() Sets a callback function which gives information about the read and write block-wise operations to the storage medium.
USBD_MSD_Task() Task that handles the MSD-specific protocol.
USBD_MSD_Poll() Function which handles MSD commands.
USBD_MSD_SetStartStopUnitHook() Sets a callback function which is called when the command StartStopUnit is called.
Extended API functions
USBD_MSD_Connect() Connects the storage medium to the MSD component.
USBD_MSD_Disconnect() Disconnects the storage medium from the MSD.
USBD_MSD_RequestDisconnect() Sets the DisconnectRequest flag.
USBD_MSD_RequestRefresh() Performs a disconnect (optional), a detach and optionally a re-attach, to inform host that volume contents has changed.
USBD_MSD_UpdateWriteProtect() This function updates the write protect status of the storage medium.
USBD_MSD_WaitForDisconnection() Waits for disconnection while time out is not reached.
Data structures
USB_MSD_INIT_DATA emUSB-Device-MSD initialization structure that is required when adding an MSD interface.
USB_MSD_INFO emUSB-Device-MSD storage interface.
USB_MSD_INST_DATA USB-MSD initialization structure that is required when adding an MSD interface.
PREVENT_ALLOW_REMOVAL_HOOK Callback function to prevent/allow removal of storage medium.
READ_WRITE_HOOK Callback function which is called with every read/write access to the storage medium.
USB_MSD_INST_DATA_DRIVER USB-MSD initialization structure that is required when adding an MSD interface.
USB_MSD_STORAGE_API USB-MSD initialization structure that is required when adding an MSD interface.
START_STOP_UNIT_HOOK Callback function which is called when a START STOP UNIT SCSI command is received.

API functions

USBD_MSD_Add()

Description

Adds an MSD-class interface to the USB stack.

Prototype

void USBD_MSD_Add(const USB_MSD_INIT_DATA * pInitData);

Parameters

Parameter Description
pInitData Pointer to a USB_MSD_INIT_DATA structure.

Additional information

After the initialization of general emUSB-Device, this is the first function that needs to be called when an MSD interface is used with emUSB-Device. The structure USB_MSD_INIT_DATA must be initialized before USBD_MSD_Add() is called.

USBD_MSD_AddUnit()

Description

Adds a mass storage device to emUSB-Device-MSD.

Prototype

void USBD_MSD_AddUnit(const USB_MSD_INST_DATA * pInstData);

Parameters

Parameter Description
pInstData Pointer to a USB_MSD_INST_DATA structure containing the information of the added storage device.

Additional information

It is necessary to call this function immediately after USBD_MSD_Add(). It will then add an R/W storage device to emUSB-Device-MSD. The structure USB_MSD_INST_DATA must be initialized before calling USBD_MSD_AddUnit().

USBD_MSD_AddCDRom()

Description

Adds a CD-ROM device to emUSB-Device-MSD.

Prototype

void USBD_MSD_AddCDRom(const USB_MSD_INST_DATA * pInstData);

Parameters

Parameter Description
pInstData Pointer to a USB_MSD_INST_DATA structure containing the information of the added storage device.

Additional information

Similar to USBD_MSD_AddUnit(), this function should be called after USBD_MSD_Add(). The structure USB_MSD_INST_DATA must be initialized before USBD_MSD_AddCDRom() is called.

USBD_MSD_SetPreventAllowRemovalHook()

Description

Sets a callback function to prevent/allow removal of storage medium.

Prototype

void USBD_MSD_SetPreventAllowRemovalHook
                            (U8                           Lun,
                             PREVENT_ALLOW_REMOVAL_HOOK * pfOnPreventAllowRemoval);

Parameters

Parameter Description
Lun Logical Unit Number. Using only one storage medium, this parameter is 0.
pfOnPreventAllowRemoval Pointer to the callback function that shall be called.

Additional information

The callback is called within the MSD task context. The callback must not block.

USBD_MSD_SetReadWriteHook()

Description

Sets a callback function which gives information about the read and write block-wise operations to the storage medium.

Prototype

void USBD_MSD_SetReadWriteHook(U8                Lun,
                               READ_WRITE_HOOK * pfOnReadWrite);

Parameters

Parameter Description
Lun Zero-based index for the unit number. Using only one storage medium, this parameter is 0.
pfOnReadWrite Pointer to the callback function that shall be called.
USBD_MSD_Task()

Description

Task that handles the MSD-specific protocol.

Prototype

void USBD_MSD_Task(void);

Additional information

After the USB device has been successfully enumerated and configured, the USBD_MSD_Task() should be called. This function blocks until the device is detached or is suspended. After a detach or suspend USBD_MSD_Task() will return.

Check USBD_MSD_Poll() if you need a non-blocking version.

USBD_MSD_Poll()

Description

Function which handles MSD commands. Using this function is only necessary if you want to avoid using the blocking USB_MSD_Task function. This can be necessary if you are not using an RTOS.

Prototype

int USBD_MSD_Poll(void);

Return value

≥ 0 O.K.
< 0 Error detected.

Additional information

This function must be called periodically, otherwise the host can time out the device since it does not process commands. It normally blocks for USB_MSD_POLL_TIMEOUT milliseconds while waiting for a command from the host. Should a command arrive during the timeout it will be processed, which could potentially increase the block duration. The duration could also decrease because the function returns as soon as a command is finished.

USBD_MSD_SetStartStopUnitHook()

Description

Sets a callback function which is called when the command StartStopUnit is called.

Prototype

void USBD_MSD_SetStartStopUnitHook(U8                     Lun,
                                   START_STOP_UNIT_HOOK * pfOnStartStopUnit);

Parameters

Parameter Description
Lun Zero-based index for the unit number. Using only one storage medium, this parameter is 0.
pfOnStartStopUnit Pointer to the callback function that shall be called. For detailed information about the function pointer, refer to START_STOP_UNIT_HOOK.

Extended API functions

USBD_MSD_Connect()

Description

Connects the storage medium to the MSD component.

Prototype

void USBD_MSD_Connect(U8 Lun);

Parameters

Parameter Description
Lun Zero-based index for the unit number. Using only one storage medium, this parameter is 0.

Additional information

The storage medium is initially always connected to the MSD component. This function is normally used after the storage medium was disconnected via USBD_MSD_Disconnect() to carry out file system operations on the device application side. Because the device can not actively perform a connect operation this function sets an internal flag and the next time when the host requests the status of the storage medium the storage medium is connected back to the MSD component.

USBD_MSD_Disconnect()

Description

Disconnects the storage medium from the MSD.

Prototype

void USBD_MSD_Disconnect(U8 Lun);

Parameters

Parameter Description
Lun Zero-based index for the unit number. Using only one storage medium, this parameter is 0.

Additional information

This function will force the storage medium to be disconnected. The host will be informed that the medium is not present. In order to reconnect the device to the host, the function USBD_MSD_Connect() shall be used. See USBD_MSD_RequestDisconnect() and USBD_MSD_WaitForDisconnection() for a graceful disconnection method.

USBD_MSD_RequestDisconnect()

Description

Sets the DisconnectRequest flag.

Prototype

void USBD_MSD_RequestDisconnect(U8 Lun);

Parameters

Parameter Description
Lun Zero-based index for the unit number. Using only one storage medium, this parameter is 0.

Additional information

This function sets the disconnect flag for the storage medium. As soon as the next MSD command is sent to the device, the host will be informed that the device is currently not available. To reconnect the storage medium, USBD_MSD_Connect() shall be called.

Notes

If the host tries to access the storage medium while this flag is set to 1, the status of the storage medium changes to disconnected.

USBD_MSD_RequestRefresh()

Description

Performs a disconnect (optional), a detach and optionally a re-attach, to inform host that volume contents has changed.

Prototype

void USBD_MSD_RequestRefresh(U8  Lun,
                             U32 Flags);

Parameters

Parameter Description
Lun Zero-based index for the unit number. Using only one storage medium, this parameter is 0.
Flags Request flags, a bit-ored combination of the following flags: USB_MSD_TRY_DISCONNECT - Try a medium disconnect before doing a USB detach. USB_MSD_RE_ATTACH - Automatically re-attach after detach has been done.

Additional information

If the flag USB_MSD_TRY_DISCONNECT is given, the function sets the disconnect flag for the storage medium. As soon as the next MSD command is sent to the device, the host will be informed that the device is currently not available. If the host acknowledges the disconnect, the medium is reconnected and the function USBD_MSD_Task() will return.

If the flag USB_MSD_TRY_DISCONNECT is not set or the host ignores the disconnection of the medium, the USB device is detached from the host (using USBD_Stop()).

If the flag USB_MSD_RE_ATTACH is set, the device is re-attached after some delay using USBD_Start(). Then the function USBD_MSD_Task() will return. The function USBD_MSD_RequestRefresh() returns immediately while the procedure is executed in the USBD_MSD_Task().

Returning of the function USBD_MSD_Task() allows the application to reinitialize the volume (or calling USBD_Start(), if USB_MSD_RE_ATTACH was not set) before calling USBD_MSD_Task() again.

Detaching the USB device not only affects the specified volume (Lun) but all volumes of the device and any other USB class interfaces.

USBD_MSD_UpdateWriteProtect()

Description

This function updates the write protect status of the storage medium.

Prototype

void USBD_MSD_UpdateWriteProtect(U8 Lun,
                                 U8 IsWriteProtected);

Parameters

Parameter Description
Lun Zero-based index for the unit number. Using only one storage medium, this parameter is 0.
IsWriteProtected Set the write protect flag: 1 - Medium is write-protected. 0 - Medium is NOT write-protected.

Additional information

Please make sure that this function is called when the LUN is disconnected from the host, otherwise the change in the WriteProtected flag is normally not recognized.

USBD_MSD_WaitForDisconnection()

Description

Waits for disconnection while time out is not reached.

Prototype

int USBD_MSD_WaitForDisconnection(U8  Lun,
                                  U32 TimeOut);

Parameters

Parameter Description
Lun Zero-based index for the unit number. Using only one storage medium, this parameter is 0.
TimeOut Timeout give in ms. How long should this function wait, until it stops waiting.

Return value

0 Error - Time out reached. Device not disconnected.
1 Success - Device disconnected.

Additional information

After triggering the disconnection via USBD_MSD_RequestDisconnect() the stack disconnects the storage medium as soon as the host requests the status of the storage medium. Win2k does not periodically check the status of a USB MSD. Therefore, the timeout is required to leave the loop. The return value can be used to decide if the disconnection should be forced. In this case, USBD_MSD_Disconnect() shall be called.

Data structures

USB_MSD_INIT_DATA

Description

emUSB-Device-MSD initialization structure that is required when adding an MSD interface.

Type definition

typedef struct {
  U8  EPIn;
  U8  EPOut;
  U8  InterfaceNum;
} USB_MSD_INIT_DATA;

Structure members

Member Description
EPIn Bulk IN endpoint for sending data to the host.
EPOut Bulk OUT endpoint for receiving data from the host.
InterfaceNum Interface number. This member is used internally, set to 0.

Additional information

This structure holds the endpoints that should be used with the MSD interface. Refer to USBD_AddEP() for more information about how to add an endpoint.

USB_MSD_INFO

Description

emUSB-Device-MSD storage interface.

Type definition

typedef struct {
  U32  NumSectors;
  U16  SectorSize;
} USB_MSD_INFO;

Structure members

Member Description
NumSectors Number of available sectors.
SectorSize Size of one sector in bytes.
USB_MSD_INST_DATA

Description

USB-MSD initialization structure that is required when adding an MSD interface.

Type definition

typedef struct {
  const USB_MSD_STORAGE_API * pAPI;
  USB_MSD_INST_DATA_DRIVER    DriverData;
  U8                          DeviceType;
  U8                          IsPresent;
  USB_MSD_HANDLE_CMD        * pfHandleCmd;
  U8                          IsWriteProtected;
  const USB_MSD_LUN_INFO    * pLunInfo;
} USB_MSD_INST_DATA;

Structure members

Member Description
pAPI Pointer to a structure that holds the storage device driver API.
DriverData Driver data that are passed to the storage driver. Refer to USB_MSD_INST_DATA_DRIVER for detailed information about how to initialize this structure.
DeviceType Determines the type of the device: 0: Direct access block device 5: CD/DVD
IsPresent Determines if the medium is storage is present. For non-removable devices always 1.
pfHandleCmd Optional pointer to a callback function which handles SCSI commands.
IsWriteProtected Specifies whether the storage medium shall be write-protected.
pLunInfo Pointer to a USB_MSD_LUN_INFO structure. Filling this structure is mandatory for each LUN.

Additional information

All non-optional members of this structure need to be initialized correctly, except DeviceType and pfHandleCmd because it is done by the functions USBD_MSD_AddUnit() or USBD_MSD_AddCDROM().

USB_MSD_LUN_INFO

Description

Structure that is used when adding a logical volume to emUSB-Device-MSD.

Type definition

typedef struct {
  const char * pVendorName;
  const char * pProductName;
  const char * pProductVer;
  const char * pSerialNo;
} USB_MSD_LUN_INFO;

Structure members

Member Description
pVendorName Vendor name of the mass storage device. The string should be no longer than 8 bytes.
pProductName Product name of the mass storage device. The product name string should be no longer than 16 bytes.
pProductVer Product version number of the mass storage device. The product version string should be no longer than 4 bytes.
pSerialNo Product serial number of the mass storage device. The serial number string must be exactly 12 bytes, in order to satisfy the USB bootability specification requirements.

Additional information

The setting of these values is mandatory, if these values remain NULL at initialisation emUSB-Device will report a panic error in debug builds (USB_PANIC).

PREVENT_ALLOW_REMOVAL_HOOK

Description

Callback function to prevent/allow removal of storage medium. See USBD_MSD_SetPreventAllowRemovalHook().

Type definition

typedef void (PREVENT_ALLOW_REMOVAL_HOOK)(U8 PreventRemoval);

Parameters

Parameter Description
PreventRemoval Show whether the device shall be locked or not. 0 - The device shall be removable. 1 - The device shall be locked.

Additional information

Most OSes call the prevent/allow removal before any write operation. This callback will be called for all LUNs that are available on the host.

READ_WRITE_HOOK

Description

Callback function which is called with every read/write access to the storage medium.

Type definition

typedef void (READ_WRITE_HOOK)(U8  Lun,
                               U8  IsRead,
                               U8  OnOff,
                               U32 StartLBA,
                               U32 NumBlocks);

Parameters

Parameter Description
Lun Specifies the logical unit number which was accessed through read or write.
IsRead Specifies whether a read or a write access was used: 1 : read 0 : write
OnOff States whether the read or write request has been initialized (1) or whether it is complete (0).
StartLBA The first Logical Block Address accessed by the transfer.
NumBlocks The number of blocks accessed by the transfer, starting from the StartLBA.
USB_MSD_INST_DATA_DRIVER

Description

USB-MSD initialization structure that is required when adding an MSD interface.

Type definition

typedef struct {
  void    * pStart;
  U32       StartSector;
  U32       NumSectors;
  U16       SectorSize;
  void    * pSectorBuffer;
  unsigned  NumBytes4Buffer;
  U8        NumBuffers;
} USB_MSD_INST_DATA_DRIVER;

Structure members

Member Description
pStart A pointer defining the start address
StartSector The start sector that is used for the driver.
NumSectors The available number of sectors available for the driver.
SectorSize The sector size that should be used by the driver.
pSectorBuffer Pointer to an application provided buffer to be used as temporary buffer for storing the sector data.
NumBytes4Buffer Size of the application provided buffer.
NumBuffers Number of buffer that are available. This is only used when using the MT storage layer.

Additional information

This structure is passed to the storage driver. Therefore, the member of this structure can depend on the driver that is used. For the storage driver that are shipped with this software the members of USB_MSD_INST_DATA_DRIVER have the following meaning:

USB_MSD_StorageRAM:

Member Description
pStart A pointer defining the start address of the RAM disk.
StartSector This member is ignored.
NumSectors The available number of sectors available for the RAM disk.
SectorSize The sector size that should be used by the driver.

USB_MSD_StorageByName:

Member Description
pStart Pointer to a string holding the name of the volumes that shall be used, for example “nand:” “mmc:1:”
StartSector Specifies the start sector.
NumSectors Number of sector that shall be used.
SectorSize This member is ignored.
pSectorBuffer Pointer to an application provided buffer to be used as temporary buffer for storing the sector data
NumBytes4Buffer Size of the buffer provided by the application. Please make sure that the buffer can at least 3 sectors otherwise, pSectorBuffer and NumBytes4Buffer are ignored and an internal sector buffer is used. This sector-buffer is then allocated by using the FS-Storage-Layer functions.
USB_MSD_STORAGE_API

Description

USB-MSD initialization structure that is required when adding an MSD interface.

Type definition

typedef struct {
  USB_MSD_STORAGE_INIT            * pfInit;
  USB_MSD_STORAGE_GETINFO         * pfGetInfo;
  USB_MSD_STORAGE_GETREADBUFFER   * pfGetReadBuffer;
  USB_MSD_STORAGE_READ            * pfRead;
  USB_MSD_STORAGE_GETWRITEBUFFER  * pfGetWriteBuffer;
  USB_MSD_STORAGE_WRITE           * pfWrite;
  USB_MSD_STORAGE_MEDIUMISPRESENT * pfMediumIsPresent;
  USB_MSD_STORAGE_DEINIT          * pfDeInit;
} USB_MSD_STORAGE_API;

Structure members

Member Description
pfInit Initializes the storage medium.
pfGetInfo Retrieves storage medium information such as sector size and number of sectors available.
pfGetReadBuffer Prepares read function and returns a pointer to a buffer that is used by the storage driver.
pfRead Reads one or multiple sectors from the storage medium.
pfGetWriteBuffer Prepares write function and returns a pointer to a buffer that is used by the storage driver.
pfWrite Writes one or more sectors to the storage medium.
pfMediumIsPresent Checks if medium is present.
pfDeInit De-initializes the storage medium.

Additional information

USB_MSD_STORAGE_API is used to retrieve information from the storage device driver or access data that needs to be read or written. Detailed information can be found in MSD Storage Driver.

START_STOP_UNIT_HOOK

Description

Callback function which is called when a START STOP UNIT SCSI command is received.

Type definition

typedef void (START_STOP_UNIT_HOOK)(U8 Lun,
                                    U8 StartLoadEject);

Parameters

Parameter Description
Lun Specifies the logical unit number.
StartLoadEject Specifies which operation is executed by the host: 0 : Stop disk 1 : Start disk and make ready for access 2 : Eject disk if permitted 3 : Load, start and make disk ready.

MSD Storage Driver

General information

The storage interface is handled through an API-table, which contains all relevant functions necessary for read/write operations and initialization. Its implementation handles the details of how data is actually read from or written to memory. Additionally, MSD knows two different media types:

Supported storage types

The supported storage types include:

Storage drivers supplied with this release

This release comes with the following drivers:

Note

If you are not using emFile or the RAM driver you will have to provide your own sector write/read routines for your storage medium.

Interface function list

As described above, access to a storage medium is realized through an API-function table (USB_MSD_STORAGE_API). The storage functions are declared in USB_MSD.h.

USB_MSD_STORAGE_API in detail

USB_MSD_STORAGE_INIT

Description

Initializes the storage medium.

Type definition

typedef void (USB_MSD_STORAGE_INIT)(      U8                         Lun,
                                    const USB_MSD_INST_DATA_DRIVER * pDriverData);

Parameters

Parameter Description
Lun Logical unit number. Specifies for which drive the function is called.
pDriverData Pointer to a USB_MSD_INST_DATA_DRIVER structure that contains all information that is necessary for the driver initialization. Refer to USB_MSD_INST_DATA_DRIVER structure for detailed information.
USB_MSD_STORAGE_GETINFO

Description

Retrieves storage medium information such as sector size and number of sectors available.

Type definition

typedef void (USB_MSD_STORAGE_GETINFO)(U8             Lun,
                                       USB_MSD_INFO * pInfo);

Parameters

Parameter Description
Lun Logical unit number. Specifies for which drive the function is called.
pInfo Pointer to a USB_MSD_INFO structure. For detailed information about the USB_MSD_INFO structure, refer to USB_MSD_INFO.
USB_MSD_STORAGE_GETREADBUFFER

Description

Prepares the read function and returns a pointer to a buffer that is used by the storage driver.

Type definition

typedef U32 (USB_MSD_STORAGE_GETREADBUFFER)(U8      Lun,
                                            U32     SectorIndex,
                                            void ** ppData,
                                            U32     NumSectors);

Parameters

Parameter Description
Lun Logical unit number. Specifies for which drive the function is called.
SectorIndex Specifies the start sector for the read operation.
ppData Pointer to a pointer to store the read buffer address of the driver.
NumSectors Number of sectors to read.

Return value

Maximum number of consecutive sectors that can be read at once by the driver.

USB_MSD_STORAGE_READ

Description

Reads one or multiple consecutive sectors from the storage medium.

Type definition

typedef I8 (USB_MSD_STORAGE_READ)(U8     Lun,
                                  U32    SectorIndex,
                                  void * pData,
                                  U32    NumSectors);

Parameters

Parameter Description
Lun Logical unit number. Specifies for which drive the function is called.
SectorIndex Specifies the start sector from where the read operation is started.
pData Pointer to buffer to store the read data.
NumSectors Number of sectors to read.

Return value

= 0 Success.
≠ 0 Failed.
USB_MSD_STORAGE_GETWRITEBUFFER

Description

Prepares the write function and returns a pointer to a buffer that is used by the storage driver.

Type definition

typedef U32 (USB_MSD_STORAGE_GETWRITEBUFFER)(U8      Lun,
                                             U32     SectorIndex,
                                             void ** ppData,
                                             U32     NumSectors);

Parameters

Parameter Description
Lun Logical unit number. Specifies for which drive the function is called.
SectorIndex Specifies the start sector for the write operation.
ppData</