Skip to content

Using USB Serial Tools

A Rockface USB serial tool allows communication with a USB target device that provides a serial interface (e.g. USB CDC-ACM).


In the rockface python library, USB serial tools are represented using the rockface.tools.usb_serial.USBSerial type:

py
from rockface import Rig
from rockface.tools.usb_serial import USBSerial

rig = Rig.find_by_name("my-rig")
serial = rig.tools["usb"]

assert isinstance(serial, USBSerial)

Examples continue from the above

For brevity, the rest of the examples on this page will continue on from the above example, with the serial variable set to a USBSerial instance.

Availability

A USB device must enumerate with its host before it can be used. The USB serial tool communicates whether a device is currently available through its is_available property:

py
import time

print("Waiting for USB serial device to become available")
while not serial.is_available:
    time.sleep(1)

Reading

While the target device is available, the USB serial tool will continuously read data from the target device into a "read buffer" within the tool. Data can be retrieved and removed from this buffer using the read method, which takes the maximum number of bytes to retrieve as an argument:

py
data = serial.read(1000)
print(f"len(data) bytes received")

If the buffer reaches maximum capacity (usually 1 MiB), then the oldest data in the buffer will be discarded.

read does not block

When read is called, it will provide up to the number of requested bytes from the read buffer. It will not wait until the requested number of bytes have been received from the target device.

For example, if the read buffer contained 3 bytes and read requests 10 bytes, only 3 bytes will be returned. If there is no data available, then an empty bytestring will be returned.

Writing

Data can be written to the USB serial target using the write method:

py
serial.write(b"Hello World!")

write will append the provided data to the tool's "write buffer", and then return almost instantly. The tool will continuously take data from this buffer and write it to the target device until there is no more data in the buffer.

Write Buffer Capacity Limit

write will put as much of the provided data in the buffer as possible. If the buffer reaches maximum capacity (usually 1 MiB), then not all of the provided data will be appended to the buffer. The number of bytes that were successfully added to the buffer is returned:

py
written = serial.write(b"Hello World!")
print(f"{written} bytes were written")

Buffer Clearing

The read and write buffers are both emptied when the tool is reset. The buffers will also be cleared when the device availability changes as follows:

  • The read buffer is emptied when the device becomes available.
  • The write buffer is emptied when the device becomes unavailable.
Interacting with transiently available target devices

Sometimes the target device may not be available for very long. It might power up, send some data over USB, and then power down. The read buffer is not cleared when the device becomes unavailable, so any data it sent while it was available can still be read from the tool.

Data can be enqueued in the write buffer before the target device becomes available. The tool will start writing data to the target device as soon as it becomes available.

Reading USB Descriptors

The standard USB device string descriptors provided by the target device can be accessed using the descriptors property of the tool:

py
print("Manufacturer:", serial.descriptors["manufacturer"])
print("Serial number:", serial.descriptors["serial_number"])
print("Product:", serial.descriptors["product"])