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:
- Explain the core question for this project in your own words.
- Implement the main workflow and validate it with measurements.
- Handle at least two failure modes and document recovery.
- 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)
- Select USB device class in firmware.
- Generate descriptor set and compile.
- Enumerate and inspect descriptors on host.
- 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
- See §3.2 Functional Requirements and §5.10 Implementation Phases in this file.
- Also used in: P10-dma-streamer-continuous-data-pipeline.md, P17-teensy-instrument-platform.md
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
- Implement at least two USB device classes.
- Generate descriptor report and compare to host view.
- Validate endpoint data transfers.
- 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
- Initialize hardware and verify configuration.
- Capture data and record timestamps.
- 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:
- USB descriptors, endpoints, enumeration
- Data logging and measurement techniques
- Basic timing math and error analysis
5.5 Questions to Guide Your Design
- Which class fits your data?
- How will you test on multiple OSes?
- 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
- What is enumeration?
- Why are endpoints typed?
- 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:
- Build single USB class
- Verify enumeration
Checkpoint: Device recognized
Phase 2: Core Functionality (10 hours)
Goals:
- Add second class
- Validate descriptors
Tasks:
- Add second class
- Validate descriptors
Checkpoint: Descriptor report
Phase 3: Polish (6 hours)
Goals:
- Cross-OS testing
- Document identities
Tasks:
- Cross-OS testing
- 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}
9.2 Related Open Source Projects
{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
10.4 Related Projects in This Series
{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}