The USB port has become ubiquitous in the digital world, allowing the use of a large choice of peripherals. The Raspberry Pi models support one to four USB ports, depending upon the model.
This chapter briefly examines some power considerations associated with USB support and powered hubs. The remainder of this chapter examines the device driver interface available to the Raspbian Linux developer by programming access to an EZ-USB FX2LP developer board.
Power
Very early models of the Raspberry Pi limited each USB port to 100 mA because of the polyfuses on board. Revision 2.0 models and later did away with these, relieving you from the different failures that could occur. The USB 2 power limit is 500 mA from a single port. Keep this in mind when designing your IoT (internet of things).
Note
Wireless USB adapters consume between 350 mA and 500 mA.
Powered Hubs
Some applications will require a powered USB hub for high-current peripherals. This is particularly true for wireless network adapters, since they require up to 500 mA. But a USB hub requires coordination with the Linux kernel and thus requires software support. A number of hubs have been reported not to work. The following web page is a good resource for listing hubs that are known to work with Raspbian Linux:
http://elinux.org/RPi_Powered_USB_Hubs

A powered USB hub
EZ-USB FX2LP
In this chapter, we’re not just going to talk about USB. Instead we’re going to interface your Pi to an economical board known as the EZ-USB FX2LP, which is available on eBay for the low cost of about $4. The chip on board is CY7C68013A and is manufactured by Cypress. If you do an eBay search for “EZ-USB FX2LP board,” you should be able to find several sources.
There is an FX3LP chip available but it is not hobby priced. Furthermore, it requires special instructions to get driver support installed. If you stay with the FX2LP, the Raspbian Linux kernel drivers should automatically support it.

The FX2LP EZ-USB developer board
Device Introduction
Anchor Chips Inc. was acquired in 1999 by Cypress Semiconductor Corp.8 Anchor had designed an 8051 chip that allowed software to be uploaded into its SRAM over USB, to support various peripheral functions. This approach allowed one hardware device to be configured by software for ultimate flexibility. Cypress has since improved and extended its capabilities in new designs like the FX2LP (USB 2.0) and later. One of the best features of this device is how much USB support is built into the hardware.
A complete PDF manual can be downloaded from:
http://www.cypress.com/file/126446/download
8051 microcontroller architecture with Cypress extensions
16 KB of SRAM, for microcontroller code and data
Hardware FIFO for fast software-free transfers (up to 96 MB/s)
GPIF (general programming interface) for fast state-machine transfers
2 x UART serial communications
I2C master peripheral for I/O with FLASH
Hardware USB 2.0 serial engine
One of the reasons I chose this product is that you can program all of the software on the Pi and try out your changes without having to flash anything. And no special microcontroller programmer is required.
USB API Support
On the Linux side, we also obviously need software support. USB devices are normally supported by device drivers and appear as generic peripherals like keyboards, mice, or storage. What is interesting about the EZ-USB device is that we have support enough in the Linux kernel to upload FX2LP firmware to the device. Once uploaded to the FX2LP’s SRAM, the device will ReNumerate™.
USB Enumeration
When a USB device is first plugged into a USB network (or first seen at boot time), it must go through the job of enumeration to discover what devices exist on the bus and know their requirements.
The master of the bus is the host (PC/laptop/Pi). All devices plugged into the bus are slave devices and must wait for the host to request a reply. With very few exceptions, slaves only speak when the master tells them to.
The process of discovery requires the host to query the device by using address zero (all devices must respond to this). The request is a Get-Descriptor-Device request that allows the device to describe some of its attributes. Next the host will assign a specific device address, with a Set-Address request. Additional Get-Descriptor requests are made by the host to gain more information. From these information transfers the host learns about the number of endpoints, power requirements, bus bandwidth required, and what driver to load, etc.
ReNumeration™
This is a term that Cypress uses to describe how an active EZ-USB device disconnects from the USB bus, and enumerates again, possibly as a different USB device. This is possible when executing the downloaded firmware in the EZ-USB SRAM. Alternatively, EZ-USB can be configured to download its firmware into SRAM from the onboard flash storage, using its I2C bus.
Raspbian Linux Installs
Install sdcc
The sync command (at the end) is a good idea on the Pi after making significant changes. It causes the kernel to flush the disk cache out to the flash file system. That way, if your Pi crashes for any reason, you can at least be sure that those changes are now saved in flash. This is a lifesaver if you have cats sniffing around your Pi.
Install cycfx2prog
Install libusb-1.0-0-dev
Blacklist usbtest
Obtain Software from github.com
Test EZ-USB FX2LP Device
If you’re an advanced user and need to make changes, be sure to examine that file. This is used to define how to upload to the FX2LP device, etc. There are also some customized FX2LP include files there.
Compile blink
This is the Intel hexadecimal format file for the compiled blink firmware that will be uploaded to the FX2LP device to be executed.
EZ-USB Program Execution
The EZ-USB FX2LP blink.c source code
If you are using a different manufactured board, you might need to track down the LED pins and make small changes to the code. As far as I know, all available boards use these same LEDs. The board I am using has the LEDs connected to GPIO port A pin 0 (PA0) and PA1. If yours are different, substitute for PA0 and PA1 in the code.
If the LEDs are located on a different port altogether, then change the “A” in OEA to match the port being used.
USB Demonstration
Now we can finally perform a demonstration of the Raspberry Pi using libusb to communicate with a USB device (FX2LP). To keep this simple, our assignment is rather trivial, except for the use of USB in between the two ends. The goal is to be able to turn on/off the LEDs on the FX2LP device from the Raspberry Pi side. At the same time the Pi will read confirmation information about the current state of the LEDs from the USB device. In effect, this demonstration exercises the sending of command information to the FX2LP, while also receiving updates from the FX2LP about the LED states.
FX2LP Source Code
FX2LP main program in ezusb.c
Lines 94 to 98 configure the GPIO pins of the FX2LP as outputs. Then it runs the loop in lines 100 to 106 forever. The if statement in line 101 tests if there is any data received in USB endpoint 2, and when not empty, it calls the function accept_cmd().
Line 104 checks to see if endpoint 6 is not full. If not full, the function send_state() is called to send status information. Now let's examine those two functions in more detail.
Function accept_cmd
The FX2LP function accept_cmd() in ezusb.c
The magic of the FX2LP is that most of the USB stuff is handled in silicon. Line 50 accesses a register in the silicon that indicates how much data was delivered to endpoint 2. If there is no data, the function simply returns in line 53.
Otherwise the data is accessed through a special pointer, which was obtained in line 49. Line 54 sets the LED output pin PA0 according to bit 0 of the first byte received (the Raspberry Pi program will only be sending one byte). PA1 is likewise set by bit 1 of that same command byte.
Last of all, line 56 tells the silicon that the data in endpoint 2 can be released. Without doing this, no more data would be received.
Function send_state
The FX2LP function send_state() in ezusb.c
Line 65 accesses the endpoint 6 FIFO buffer, for placing the message into. Lines 66 and 67 simply choose a message depending upon whether the GPIO port is a 1-bit or a 0-bit. Lines 70 to 73 then copy this message into the endpoint buffer from line 65. Lines 74 and 75 add a comma, and then the loop in lines 76 to 79 copy the second message to the endpoint buffer.
The SYNCDELAY macros are a timing issue unique to the FX2LP, when running at its top clock speed. Line 82 sets the high byte of the FIFO length to zero (our messages are less than 256 bytes). Line 84 sets the low byte of the FIFO length to the length we accumulated in variable len. Once the low byte of the FIFO length has been set, the silicon runs with the buffer and sends it up to the Pi on the USB bus.
Apart from the initialization and setup of the endpoints for the FX2LP, that is all there is to the EZ-USB implementation. The initialization source code is also in ezusb.c, for those that want to study it more closely.
EZ-USB Initialization
The EZ-USB initialization code from ezusb.c
Line 13 configures the CPU clock for 48 MHz, while line 15 configures an interface clock also for 48 MHz. Line 19 configures endpoint 6 to be used for bulk input (from the hosts perspective), while line 21 configures endpoint 2 for bulk output. Lines 23 to 31 perform a FIFO reset. Lines 37 and 39 clear the double-buffered FIFO and then the FX2LP silicon is ready to handle USB requests.
Raspberry Pi Source Code
The main program in controlusb.cpp for the Raspberry Pi
C++ was used for the Raspberry Pi code to simplify some things. The non C++ programmer need not fear. Many Arduino students are using C++ without realizing it. The Arduino folks are likely wincing at me for saying this because they don’t want to scare anyone. For this project, we’ll focus on what mostly looks and works like C.
Line 166 defines a class instance named tty. Don’t worry about its details because we’ll just use it to do some terminal I/O stuff that is unimportant to our focus.
Lines 169 and 170 define the vendor and product ID that we are going to be looking for on a USB bus somewhere. Line 174 calls upon the libusb function find_usb_device based upon these two ID numbers. If the device is not found, it returns a null pointer, which is tested in line 175.
When the device is found, control passes to line 183, where we claim interface zero. If this fails it is likely because it is claimed by another driver (like usbtest).
The alternate interface 1 is chosen in line 194. This is the last step in the sequence leading up to the successful USB device access for the loop that follows, starting in line 204. Once the loop exits (we’ll see how shortly), the interface is released in line 243 and then closed in 245. Line 247 closes the libusb library.
USB I/O Loop
Line 200 uses the tty object to enable “raw mode” for the terminal. This permits this program to receive one character at a time. Normally a RETURN key must be pressed before the program sees any input, which is inconvenient for this demo.
Within the loop, line 205 tries to read a terminal character, waiting for up to 500 ms. If none is received within that time, the call returns -1 to indicate a timeout. When that happens, the code starting in line 207 tries to read from USB endpoint 6 (the high bit in 0x86 indicates that this is an OUT port, from the host's point of view). This is the endpoint that our FX2LP will be sending us status updates on (as character string messages).
Lines 150 and 152 are executed when a character from the Raspberry Pi keyboard is received. If the character is a ‘q’, the program exits the loop in line 151. This allows for a clean program exit.
Lines 224 to 236 are executed if a ‘0’ or ‘1’ is typed. Line 224 turns the character into a 0-bit or a 1-bit in the variable mask. In other words, mask is assigned 0x01 or 0x02, depending upon the input character being a ‘0’ or ‘1’ respectively. Line 226 tracks the state of the LED bit in the variable named state. The value of mask then toggles the respective bit on or off, depending upon its prior state.
Line 227 places the state byte into the first buffer byte. This 1-byte buffer is then written to endpoint 2 (argument 0x02), timing out if necessary after 10 ms in line 228. If the timeout occurred, the return value of rc will be negative. Otherwise the bytes written are displayed on the terminal from line 235.
Line 238 is executed if the program didn't understand the character typed at the terminal.
The function find_usb_device in file controlusb.cpp
The first time libusb is called, the function libusb_init must be called. This is done in line 84 if variable usb_devs is a null pointer (note that the variable usb_devs is a static variable and is initialized as null (nullptr in C++)). After that, line 86 fetches a list of USB devices and stores a pointer into usb_devs for future use.
Once that formality is out of the way, we call upon libusb_open_device_with_vid_pid to locate and open our device.
Function bulk_read
The bulk_read function in controlusb.cpp
Essentially, this function is a simple interlude to the library function libusb_bulk_transfer in line 123. The number of bytes actually read is returned into the int variable xlen in this call. For larger packets, this could be broken into segments of data. Here we use the simple assumption that we will receive all of our data in one transfer.
Note that if the transfer times out, we can still have some data transferred (line 124 tests for this). The number of bytes read is returned at line 125. Otherwise we return the negative integer of the error code.
Function bulk_write
The bulk_write function in controlusb.cpp
The message transfer uses libusb_bulk_transfer again but knows this is being sent to the host based upon the endpoint number (the assertion in line 144 checks). The number of bytes actually sent by the call is returned in the xlen variable (argument five). The the transfer was successful, or timed out, the total number of bytes are returned as a positive number (line 153). Otherwise the negative error code is returned.
Note that the routine tracks total bytes transferred in line 149. The buffer start pointer is incremented in line 150 and the count to be sent reduced in line 151. The routine only returns when all bytes are sent or the request has timed out. Ideally, better handling should be provided for the timeout case.
The Demonstration
is written when I typed a 1. Shortly after, the LED on PA1 lights up (the LEDs are active low, so a 0-bit turns on the LED). Two lines later, the FX2LP is able to send us a message reporting that PA1=0 (LED on). This is not tardiness on the FX2LP’s part but is the reality that it was unable to send a message about it until the prior USB messages were read by the Pi.
Some other doodling with ‘0’ and ‘1’ was performed until the ‘q’ key ended the demonstration.
Summary
A lot of ground was covered in this chapter. A whirlwind introduction to the FX2LP EZ-USB device was presented. The curious mind should look at the PDF documents for the EZ-USB device and seek out books and online resources for it. This chapter only scratched the surface of what that silicon can do.
The main focus of this chapter was to see how to handle USB I/O directly from a user mode program on the Raspberry Pi. The libusb library makes this rather easy, once you know the basics. These were covered in the controlusb.cpp source code. Now that you're armed and dangerous, you can take your USB knowledge to a new level by designing new applications using USB.