Project 9: USB Identity Lab - Teensy as a USB Device

Create USB device identities (HID/MIDI/Serial) and validate descriptors against host tools.

Quick Reference

Attribute Value
Difficulty Level 3: Advanced
Time Estimate 20-30 hours
Main Programming Language C++
Alternative Programming Languages C
Coolness Level Level 4: Hardcore Tech Flex
Business Potential 3. The “Product” Model
Prerequisites C/C++ basics, Teensyduino setup, basic electronics, ability to use a multimeter/logic analyzer
Key Topics USB descriptors, endpoints, enumeration

1. Learning Objectives

By completing this project, you will:

  1. Explain the core question for this project in your own words.
  2. Implement the main workflow and validate it with measurements.
  3. Handle at least two failure modes and document recovery.
  4. Produce a deterministic report that matches hardware behavior.

2. All Theory Needed (Per-Concept Breakdown)

USB Enumeration, Descriptors, and Endpoints

Fundamentals USB devices are defined by descriptors that describe identity, configuration, interfaces, and endpoints. Enumeration is the host-driven process of reading these descriptors and assigning a device address. If descriptors are wrong, the device fails to enumerate or appears as unknown. This project makes descriptors a measurable artifact.

Deep Dive into the concept USB is hierarchical: a device has configurations, each configuration has interfaces, and interfaces have endpoints. Endpoints have direction, type, and max packet size. Firmware must match descriptor declarations or the host will misbehave. Enumeration uses control transfers on endpoint 0; debugging it means capturing descriptor requests and verifying responses. Composite devices combine multiple interfaces (e.g., HID + Serial). Ordering and IDs matter because host drivers bind to specific interface classes. A stable USB device requires versioned descriptors and careful testing on multiple OSes. This project has you create USB identities and compare host-reported descriptors to firmware expectations.

How this fit on projects This concept directly powers the implementation choices and validation steps in this project.

Definitions & key terms

  • Descriptor: Structured data describing a USB device or interface.
  • Endpoint: Logical pipe for USB data transfer.
  • Enumeration: Host process to identify and configure a USB device.
  • Interface: Group of endpoints implementing a function.

Mental model diagram (ASCII)

Host -> Control EP0 -> Descriptors -> Interfaces -> Endpoints

How it works (step-by-step)

  1. Select USB device class in firmware.
  2. Generate descriptor set and compile.
  3. Enumerate and inspect descriptors on host.
  4. Validate endpoint behavior against descriptor types.

Minimal concrete example

bDeviceClass: 0x00
bNumConfigurations: 1
Interface 0: HID
Endpoint 0x81: Interrupt IN

Common misconceptions

  • USB descriptors are optional metadata.
  • Changing descriptors is harmless.
  • Endpoint type does not matter if data flows.

Check-your-understanding questions

  • Why does the host control enumeration?
  • What happens if endpoint sizes mismatch?
  • How do you debug enumeration failures?

Check-your-understanding answers

  • USB is host-driven and devices must respond to host requests.
  • Transfers fail or are truncated, causing driver errors.
  • Capture descriptors with host tools and compare to firmware.

Real-world applications

  • MIDI controllers
  • Custom HID devices
  • USB data loggers

Where you’ll apply it

References

  • USB 2.0 specification
  • PJRC USB documentation

Key insights

Descriptors are the contract between your device and every host OS.

Summary

Correct USB identities require accurate descriptors and endpoint behavior.

Homework/Exercises to practice the concept

  • Capture descriptors for two device classes and compare differences.
  • Modify a descriptor field and observe host behavior.

Solutions to the homework/exercises

  • Use lsusb -v or USBView to dump descriptors.
  • Change bProduct and confirm new device ID on host.

3. Project Specification

3.1 What You Will Build

Create USB device identities (HID/MIDI/Serial) and validate descriptors against host tools.

3.2 Functional Requirements

  1. Implement at least two USB device classes.
  2. Generate descriptor report and compare to host view.
  3. Validate endpoint data transfers.
  4. Document VID/PID and interface layout.

3.3 Non-Functional Requirements

  • Performance: Meet the target timing/throughput for the project.
  • Reliability: Detect errors and recover without undefined behavior.
  • Usability: Provide clear logs and a repeatable workflow.

3.4 Example Usage / Output

./P09-usb-identity-lab-teensy-as-a-usb-device --run

3.5 Data Formats / Schemas / Protocols

Descriptor report in JSON or text format

3.6 Edge Cases

  • Enumeration fails on one OS
  • Descriptor mismatch to firmware
  • Endpoint size mismatch

3.7 Real World Outcome

You will run the project and see deterministic logs and measurements that match physical hardware behavior.

3.7.1 How to Run (Copy/Paste)

cd project-root
make
./P09-usb-identity-lab-teensy-as-a-usb-device --run

3.7.2 Golden Path Demo (Deterministic)

Use a fixed input configuration and a known test signal. Capture output for 60 seconds and verify it matches expected values.

3.7.3 If CLI: exact terminal transcript

$ ./P09-usb-identity-lab-teensy-as-a-usb-device --run --seed 42
[INFO] USB Identity Lab - Teensy as a USB Device starting
[INFO] Report saved to data/report.csv
[INFO] Status: OK
$ echo $?
0

Failure Demo (Deterministic)

$ ./P09-usb-identity-lab-teensy-as-a-usb-device --run --missing-device
[ERROR] Device not detected
$ echo $?
2

4. Solution Architecture

4.1 High-Level Design

Inputs -> Acquisition -> Processing -> Output/Log

4.2 Key Components

Component Responsibility Key Decisions
Acquisition Configure peripherals and capture data Use stable clock settings
Processing Convert raw data to meaningful values Apply calibration/filters
Output/Log Emit reports and logs CSV for reproducibility

4.3 Data Structures (No Full Code)

struct Sample {
    uint32_t timestamp_us;
    uint32_t value;
    uint32_t flags;
};

4.4 Algorithm Overview

Key Algorithm: Measurement + Report

  1. Initialize hardware and verify configuration.
  2. Capture data and record timestamps.
  3. Compute metrics and write report.

Complexity Analysis:

  • Time: O(n) in samples
  • Space: O(n) for log storage

5. Implementation Guide

5.1 Development Environment Setup

# Arduino IDE + Teensyduino must be installed
# Optional CLI workflow
arduino-cli core update-index
arduino-cli core install teensy:avr

5.2 Project Structure

project-root/
├── src/
│   ├── main.ino
│   ├── hw_config.h
│   └── measurements.cpp
├── tools/
│   └── analyze.py
├── data/
│   └── samples.csv
└── README.md

5.3 The Core Question You’re Answering

“How do I prove my USB descriptors match the behavior of my device?”

5.4 Concepts You Must Understand First

Stop and research these before coding:

  1. USB descriptors, endpoints, enumeration
  2. Data logging and measurement techniques
  3. Basic timing math and error analysis

5.5 Questions to Guide Your Design

  1. Which class fits your data?
  2. How will you test on multiple OSes?
  3. How will you version descriptors?

5.6 Thinking Exercise

Sketch the descriptor tree for a composite HID+Serial device.

5.7 The Interview Questions They’ll Ask

  1. What is enumeration?
  2. Why are endpoints typed?
  3. How do you debug descriptor errors?

5.8 Hints in Layers

  • Start with built-in Teensy USB types.
  • Use lsusb or USBView.
  • Validate endpoint sizes with small transfers.

5.9 Books That Will Help

| Topic | Book | Chapter | |——-|——|———| | USB basics | USB Complete | Ch. 3-5 | | Embedded comms | Making Embedded Systems | Ch. 6 | | USB classes | USB Class Specs | HID/MIDI |

5.10 Implementation Phases

Phase 1: Foundation (6 hours)

Goals:

  • Build single USB class
  • Verify enumeration

Tasks:

  1. Build single USB class
  2. Verify enumeration

Checkpoint: Device recognized

Phase 2: Core Functionality (10 hours)

Goals:

  • Add second class
  • Validate descriptors

Tasks:

  1. Add second class
  2. Validate descriptors

Checkpoint: Descriptor report

Phase 3: Polish (6 hours)

Goals:

  • Cross-OS testing
  • Document identities

Tasks:

  1. Cross-OS testing
  2. Document identities

Checkpoint: Final lab

5.11 Key Implementation Decisions

| Decision | Options | Recommendation | Rationale | |———-|———|—————-|———–| | Buffering | Single buffer, double buffer | Double buffer | Avoids data loss during processing | | Logging format | CSV, binary | CSV | Human-readable while still scriptable | | Clock speed | Default, overclock | Default | Keeps peripherals in spec |


6. Testing Strategy

6.1 Test Categories

| Category | Purpose | Examples | |———-|———|———-| | Unit Tests | Validate math, parsing, and conversions | Timer math, CRC checks | | Integration Tests | Verify peripherals and pipelines | DMA -> buffer -> log | | Edge Case Tests | Handle boundary conditions | Brownout, missing sensor |

6.2 Critical Test Cases

{test_cases}

6.3 Test Data

Use a fixed test input pattern and record outputs to data/report.csv

7. Common Pitfalls & Debugging

7.1 Frequent Mistakes

| Pitfall | Symptom | Solution | |———|———|———-| {pitfalls}

7.2 Debugging Strategies

{debug_strats}

7.3 Performance Traps

Large buffers improve stability but increase latency. Measure both throughput and jitter to choose the right size.


8. Extensions & Challenges

8.1 Beginner Extensions

{ex_begin}

8.2 Intermediate Extensions

{ex_inter}

8.3 Advanced Extensions

{ex_adv}


9. Real-World Connections

9.1 Industry Applications

{industry_apps}

{open_source}

9.3 Interview Relevance

{interview_rel}


10. Resources

10.1 Essential Reading

{resources}

10.2 Video Resources

  • Embedded systems timing walkthrough (YouTube)
  • Teensy hardware deep dive (Conference talk)

10.3 Tools & Documentation

  • Teensyduino: Toolchain for Teensy boards
  • Logic Analyzer: Timing verification
  • Multimeter: Voltage and current measurement

{related_projects}


11. Self-Assessment Checklist

11.1 Understanding

  • I can explain the main concept without notes.
  • I can explain why the measurements match (or do not match) expectations.
  • I understand at least one tradeoff made in this project.

11.2 Implementation

  • All functional requirements are met.
  • All critical test cases pass.
  • Logs and reports are reproducible.
  • Edge cases are handled.

11.3 Growth

  • I documented lessons learned.
  • I can explain this project in a job interview.
  • I identified one improvement for next iteration.

12. Submission / Completion Criteria

Minimum Viable Completion: {comp_min}

Full Completion: {comp_full}

Excellence (Going Above & Beyond): {comp_ex}