Tools: What Happens When You Plug Something In (2026)

Tools: What Happens When You Plug Something In (2026)

What Happens When You Plug Something In

USB: The Protocol That Ate Every Port

A Brief History of Cable Hell

The Physical Layer: Two Wires and a Clever Trick

The Speed Naming Disaster

Enumeration: The Descriptor Dance

Device Classes: Why Your Webcam and Keyboard Share a Protocol

Endpoints and Pipes: Four Flavors of Data Transfer

Hubs and the Tiered Star Topology

How Many Devices Can You Actually Connect?

USB-C: The Connector That Knows Too Much

Why "Safely Remove" Exists

Power Delivery: From 500mA to Charging Laptops

The Polled Bus: Everything Waits for the Host

What's Next

Further Reading Reading time: ~15 minutes You plugged in a USB drive. A notification popped up. You dragged some files over. You yanked the cable out without clicking "safely remove" and felt a tiny pang of guilt. That guilt is warranted, but not for the reason you think. Between the moment you pushed that connector in and the moment your OS mounted a filesystem, your computer conducted a multi-round negotiation involving device identity, power budgets, endpoint capabilities, and transfer scheduling — all over two twisted wires carrying differential signals at 480 million bits per second. The drive didn't announce itself. Your computer had to ask. That's the first thing most people get wrong about USB. It's not a peer-to-peer protocol. It's a polled, host-controlled bus where nothing speaks unless spoken to. Before USB, connecting a peripheral to a PC was an exercise in suffering. Serial ports (RS-232) needed specific baud rates, stop bits, and flow control settings. Parallel ports (DB-25) were faster but required fat cables and had timing problems. PS/2 ports worked for keyboards and mice but nothing else. SCSI gave you throughput but demanded termination resistors and SCSI IDs and the patience of a monk, I am no monk. Every peripheral type had its own connector, its own driver model, its own failure mode. In 1994, a consortium of seven companies — Compaq, DEC, IBM, Intel, Microsoft, NEC, and Nortel — decided this was insane. Ajay Bhatt at Intel led the architecture work. The goal: one connector, one protocol, hot-pluggable, self-describing, and capable of powering small devices. USB 1.0 shipped in January 1996. It took another two years and the iMac G3 for anyone to actually care. Apple dropped every legacy port on that machine and bet the entire peripheral story on USB. It was either visionary or reckless. It was both. A USB 2.0 cable has four wires: VBUS (+5V power), GND, D+, and D-. The data travels on D+ and D- using differential signaling — the receiver doesn't look at the voltage on either wire individually. It looks at the difference between them. Why? Noise immunity. If electromagnetic interference hits your cable, it hits both wires roughly equally. The voltage on D+ goes up by 50mV, and the voltage on D- goes up by 50mV. The difference stays the same. The signal survives. This is the same trick used by Ethernet, HDMI, and every other protocol that needs to work in environments full of switching power supplies and WiFi radios. A logical 1 (called a "J state" in USB-speak) is D+ high, D- low. A logical 0 ("K state") is the reverse. The encoding scheme is NRZI — Non-Return-to-Zero Inverted — which means a 0 bit causes a transition and a 1 bit doesn't. To prevent long runs of 1s from losing clock sync, the protocol uses bit stuffing: after six consecutive 1 bits, a 0 is inserted. The receiver strips it out. This means USB's actual data throughput is slightly less than the raw bit rate. USB 3.0 (SuperSpeed) added a completely separate set of wires — two differential pairs for a full-duplex link — on top of the existing USB 2.0 wires. That's why USB 3.0 cables are thicker. That's also why a USB 3.0 device works in a USB 2.0 port at USB 2.0 speeds: the old wires are still there, doing the same job they always did. USB's speed grades are a masterclass in how not to name things. The USB Implementers Forum — the standards body that governs USB — has renamed speeds multiple times, creating a layered mess where the marketing name, the spec name, and the thing developers actually say are three different strings. Here's what actually matters: Note that "Full Speed" is the slow one. 12 Mbit/s. It was full speed in 1998. The name stuck forever. This is what happens when you name speeds after marketing adjectives instead of numbers. Also note that what was once called "USB 3.0" was retroactively renamed to "USB 3.2 Gen 1" — a spec version number that didn't exist when the product shipped. Cable and device manufacturers print whichever name they feel like. The result is that "USB 3.2" on a box could mean 5, 10, or 20 Gbit/s. Good luck out there! This is the part most developers never see, and it's the part that makes USB actually work. When you plug in a device, here's what happens: Step 1: Electrical detection. The host sees a voltage change on D+ or D-. A full-speed or high-speed device pulls D+ high through a 1.5kΩ resistor. A low-speed device pulls D- high instead. The host now knows something is there, and it knows the speed class. Step 2: Reset. The host drives both D+ and D- low for at least 10ms. This is a bus reset. It tells the device to abandon any previous state and start fresh. Step 3: Default address. After the reset, the device listens on address 0. Every USB device starts its life as address 0. Only one device can be at address 0 at a time — this is why there's a brief period after plugging in where the host won't detect a second new device. Step 4: Get Device Descriptor. The host sends a control transfer to address 0, asking for the device's device descriptor — an 18-byte structure containing the vendor ID, product ID, device class, number of configurations, and the USB spec version the device supports. This is the handshake. "Who are you?" Step 5: Set Address. The host assigns a unique address (1–127) to the device. From now on, the device only responds to that address. Address 0 is free for the next newcomer. Step 6: Get Configuration Descriptor. The host asks for the full configuration descriptor, which describes every interface and endpoint the device offers. A webcam might report a video interface with an isochronous endpoint and an audio interface with another isochronous endpoint. A USB drive reports a mass storage interface with two bulk endpoints (in and out). Step 7: Set Configuration. The host picks a configuration (most devices have exactly one) and activates it. That's 7 steps, multiple round-trip transactions, all before a single byte of actual data moves. The whole process takes somewhere between 100ms and a few seconds, depending on the device and the OS. That's why some USB devices take a moment to "appear" — your OS isn't being lazy. Nobody expects the Spanish Inquisition! 🦜 USB defines device classes — standardized interfaces that let any OS talk to any device of that type without a vendor-specific driver. This is the reason you can plug a keyboard into any computer and have it work immediately. The keyboard announces "I'm a HID device" during enumeration, and the OS loads its built-in HID driver. The beauty of the class system is substitutability. Any UVC-compliant webcam works with any UVC driver. That's not a given — it's an engineering achievement. Go try plugging a random printer into a random computer and watch it fail because the printer class (Printing) is a thin spec and most printers ship with vendor-specific protocols. Every USB device exposes one or more endpoints — numbered channels (0–15, each direction) that carry data in or out. Endpoint 0 is special: it's the control endpoint, used for enumeration and device management. Every device must have it. The other endpoints use one of three transfer types, and which one a device picks determines everything about its performance characteristics: Bulk transfers — reliable, no timing guarantee. The host sends data when the bus is free. If a packet gets corrupted, it's retried. Used by mass storage devices and printers. You get correctness, but the data arrives "whenever." Bulk transfers get the leftover bandwidth after all other transfer types are served. Interrupt transfers — small, periodic, guaranteed latency. The host polls the device at a fixed interval (between 1ms and 255ms for USB 2.0). The device either has data or it doesn't. Used by HID devices. Your keyboard gets polled every 1ms for its current key state. The word "interrupt" is misleading — this is still polling, not a hardware interrupt. The device can't yell at the host. It waits to be asked. Isochronous transfers — What an amazing word, iso same, chronous to do with time, so these are for real time feeds, guaranteed bandwidth, no retries. A fixed amount of bus time is reserved at a fixed interval. If a packet is corrupted, it's gone. No do-overs. Used by audio and video devices, because a retransmitted audio sample that arrives 5ms late is worse than a dropped sample. Your ears interpolate. Your audio stack doesn't have time to wait. That's why audio uses isochronous transfers — correctness is less important than timing. A glitch in audio is a brief click. A stall while waiting for a retransmission is a gap in playback. The protocol picks the lesser evil. USB's physical topology is a tiered star. The host controller is at the root. Hubs branch outward. Devices connect to hubs (or directly to the host's root hub). The spec allows up to 5 levels of hubs and 127 devices total on one bus — a 7-bit address space, because address 0 is reserved for devices mid-enumeration. Every host controller has a root hub built in — that's what your motherboard's USB ports connect to internally. When you plug a hub into a port, the hub itself goes through enumeration (it's a USB device too, class 09h). Then the hub monitors its downstream ports for new connections and reports them to the host. The host manages all traffic. A hub doesn't make routing decisions. It's a repeater with port management. At USB 2.0 speeds, all devices on a hub share bandwidth. A hub connected to a 480 Mbit/s port gives each downstream device a time slice of that 480 Mbit/s, not 480 Mbit/s each. USB 3.0 changed this — SuperSpeed hubs have separate transaction translators for USB 2.0 and USB 3.0 traffic, so a slow device on one port doesn't starve a fast device on another. But the fundamental model — host-scheduled, star-topology, no peer-to-peer — remains. Your laptop has, say, 3 USB-C ports. Each is a root hub port. Plug a 7-port hub into each, and those hubs can cascade further. The math: 3 ports × 5 tiers of 7-port hubs = far more than 127. The address space is the hard ceiling, not the physical ports. But long before you hit 127 devices, reality intervenes: Power. Each USB 2.0 port supplies 500mA at 5V (2.5W). A 7-port hub without its own power adapter divides that 2.5W across all downstream devices. Four bus-powered hubs deep and each device gets fractions of a watt. External hard drives spin down. Webcams refuse to enumerate. Your Keychron keyboard works fine because it draws 100mA — keyboards are cheap dates. Bandwidth. All USB 2.0 devices behind a hub share 480 Mbit/s (realistically ~280 Mbit/s after protocol overhead). Two external drives on the same USB 2.0 hub will each get ~140 Mbit/s. Add a webcam streaming 1080p and the drives slow to a crawl. USB 3.x helps — each device gets its own 5 Gbit/s lane — but only if every hub in the chain is USB 3.x. One USB 2.0 hub in the chain and everything downstream drops to 2.0 speeds. Enumeration storms. Plug in a powered hub with 7 devices attached and the host controller has to enumerate all of them — sequentially. Each device goes through the descriptor dance: reset, address 0, Get Device Descriptor, Set Address, Get Configuration, Set Configuration. Seven devices × ~100ms each = nearly a second of the host controller doing nothing but paperwork. Plug in a hub with daisy-chained hubs below it and you can stall enumeration for several seconds. That's the pause you feel when you plug in a USB dock. The real limit for most people isn't 127 devices. It's power and bandwidth. This is why every serious USB setup has powered hubs, and why Thunderbolt docks exist — they provide dedicated PCIe lanes and power delivery that USB's shared-bus model can't match. USB-C is not a speed. It's a connector — a reversible (remember trying to plug in the older version in the dark 😖) 24-pin plug that can carry USB 2.0, USB 3.x, USB4, Thunderbolt 3/4, DisplayPort, HDMI (via alt mode), analog audio, and power delivery up to 240W. All through the same physical port. This flexibility is also why USB-C cables are a minefield. The connector has 24 pins, but not all cables wire all 24. A USB-C cable that only carries USB 2.0 has 4 active data pins (D+/D-) plus power and ground. A USB 3.2 cable adds the SuperSpeed pairs. A Thunderbolt 4 cable wires everything and includes signal conditioning electronics in the connector itself (active cable). They all look identical from the outside. Buyer beware ! Configuration Channel (CC) pins — two pins on the connector used for cable detection, orientation (which way is "up" for the reversible plug), and capability negotiation. When you plug in a USB-C cable, the CC pins are the first thing that talks. They determine what the cable can carry before any data flows. USB Power Delivery (PD) runs over the CC pins as a separate protocol layer. It negotiates voltage and current between source and sink. The original USB spec allowed 5V at 100mA (500mW). USB PD 3.1 allows up to 48V at 5A (240W). That's a 480x increase in power delivery through a connector lineage that started as a peripheral attachment protocol. PD negotiation uses structured messages — the source advertises what it can provide (called PDOs — Power Data Objects), and the sink requests what it needs. Alternate Modes let the USB-C connector carry non-USB protocols. DisplayPort alt mode repurposes the SuperSpeed lanes to carry DisplayPort signals. Thunderbolt alt mode does the same for Thunderbolt/PCIe. The CC pins negotiate which alt mode to use. This is why a single USB-C port on a laptop can drive a 4K display, charge the laptop, and connect a USB hub — different pin functions running simultaneously. That's why "some USB-C cables don't work" — a cable that only wires USB 2.0 pins physically cannot carry a DisplayPort signal. The electronics aren't there. The connector fits, the protocol fails, and you blame the monitor. You've yanked a USB drive out mid-use. Maybe nothing happened. Maybe you lost a file. The reason "safely remove" exists is a combination of write caching and in-flight transfers. When your OS writes to a USB mass storage device, it doesn't necessarily send every write immediately. The OS may write-cache — hold dirty pages in RAM and flush them to the device in batches. This is faster (fewer small transactions on a bulk endpoint) but means that at any given moment, the device's on-disk state may be behind what the OS thinks it wrote. Clicking "safely remove" does three things: flushes all cached writes, completes any in-flight transfers, and then tells the device it's safe to power down. The OS unmounts the filesystem first, so no new writes can start. On Linux, the kernel's block layer handles this via sync and cache flush commands sent as SCSI SYNCHRONIZE CACHE over the USB mass storage protocol. On macOS, the same logic runs through IOKit. On Windows, it's the "surprise removal" path if you yank without ejecting. Modern operating systems (macOS since Catalina, Windows 10 since 1809) default to a "quick removal" policy for USB drives — write caching is disabled by default, so every write goes to the device immediately. This makes safe removal less critical but makes writes slower. The trade-off: you can yank the cable guilt-free, but large file copies take longer. That's why copying to a USB drive feels slower than copying between internal disks — beyond the raw interface speed difference, the default write policy adds per-transaction latency. The original USB 1.0 spec in 1996 provided 5V at 100mA — 500mW, barely enough to power a mouse. A device could request a "high-power" configuration of 500mA (2.5W) during enumeration. This was elegant: the host knew exactly how much power each device needed because the device said so in its configuration descriptor. Then phones happened. People wanted to charge phones via USB. The Battery Charging Specification (BC 1.2) introduced "dedicated charging ports" that could supply 1.5A at 5V — 7.5W. Detection used the D+/D- lines (shorting them together signaled a charging port). It worked, sort of. It also created a mess of proprietary "quick charge" protocols where chargers and phones did voltage negotiation outside the USB spec. USB Power Delivery cleaned this up. PD is a protocol that runs on the CC pins of USB-C connectors, completely independent of the data lines. It supports multiple voltage levels (5V, 9V, 15V, 20V, and with PD 3.1's Extended Power Range, 28V, 36V, and 48V) and programmable current limits. A PD source advertises its capabilities. A PD sink requests what it needs. The negotiation happens in milliseconds. A laptop charger providing 20V at 5A (100W) and a phone requesting 9V at 3A (27W) use the same protocol, the same connector, and potentially the same cable. PD 3.1 Extended Power Range (EPR) pushes this to 48V at 5A — 240W. That's enough to power a high-end gaming laptop. From a protocol that started powering mice. The specification required new safety mechanisms: EPR cables must be electronically marked (the cable has a chip in its plug that reports its voltage rating to the source), and the source and sink continuously monitor for faults. I keep coming back to this because it's the thing that surprises developers most: nothing on a USB bus talks unless the host asks it to. Your keyboard doesn't fire an interrupt when you press a key. The host controller sends an IN token packet to the keyboard's interrupt endpoint every 1ms. The keyboard either responds with data or responds with NAK (nothing to report). The host controller is doing this for every device on the bus, continuously, interleaving transactions across all active endpoints. The host controller hardware (EHCI for USB 2.0, xHCI for USB 3.x) maintains a schedule — a frame-based timeline of transactions. Each USB frame is 1ms (USB 2.0) or 125 microseconds (USB 2.0 microframes / USB 3.x). The controller walks through the schedule every frame, issuing IN and OUT token packets, collecting responses, and reporting results to the OS via DMA. This is fundamentally different from PCIe, where devices can initiate transactions (bus mastering). USB's host-controlled model is simpler, more predictable, and easier to secure — a malicious USB device can't flood the bus because it never gets to talk without permission. But it also means latency is bounded by the polling rate. You can't go faster than "one sample per frame." Every wire we've talked about today requires a physical connection. That cable between your keyboard and your computer is a guarantee — a dedicated channel, a known speed, a predictable latency. Bluetooth throws all of that away. It shares a radio band with WiFi, microwaves, and baby monitors. It hops between 79 channels, 1600 times per second, to avoid interference. It negotiates connections in a mesh where every device is both a peer and a potential relay. And somehow, your AirPods still manage to play music while your keyboard types and your mouse tracks — all on the same 2.4 GHz band. And then there's a Viking ... ⣴⣶⣶⠶⢤⣄⠀⣤⣤⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

⠈⠉⠛⢿⣆⠈⠻⢮⡙⢿⣯⠓⢤⣀⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⣇⠀⠀⠹⣆⢹⣿⣿⣿⣿⣿⣿⣍⠛⠳⢦⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⣆⠀⠀⠈⢻⣿⣿⣿⣿⣿⣿⣿⣷⡘⢆⠙⢷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⡄⠀⠀⠀⠹⣿⣿⣿⣿⣿⣿⣿⣷⠘⣯⡀⠙⢷⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⡀⢻⣀⠀⠈⠙⠛⢿⣿⠿⠿⠿⠷⠤⠤⠤⠴⠿⠦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣷⡄⠙⢧⣄⠀⠀⠈⣿⣶⣶⣶⠖⠒⠒⠒⠒⠒⠒⠒⠂⠀⠀⠀⠀⠀⠀⠀⢠⣿⣏⣿⣦⡀⠈⠀⣀⣼⣯⠙⣿⣇⠐⠿⠀⠀⠿⠂⠀⠺⠇⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⣿⣿⣿⣿⣿⡿⢿⣿⡿⣿⠷⣶⡶⢶⣶⣶⣶⣶⡶⠆⠀⠀⠀⠀⠀⣀⣿⣿⡯⢂⣿⣿⣿⣿⣫⡄⢠⡿⢡⡟⠀⠉⠙⣿⣿⣿⡿⣯⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣾⡿⠛⠙⠻⣿⣯⣶⠟⢠⠞⠀⠀⠉⠉⠛⠋⠀⢣⠹⣷⡀⠀⠀⠀⠀⢸⣿⣿⣿⡟⠉⠙⠢⠀⠘⠋⠀⢊⣁⣤⢷⣤⣠⣄⡀⠀⢠⣆⣀⣽⡿⠀⠀⠀⢀⣼⣿⣴⡿⠉⠓⠄⠀⣴⡿⠿⠿⠛⠋⠈⠀⠀⠀⢀⣤⡶⡾⠛⠛⣿⠀⠀⠀⠀⠀⢻⠿⣿⡉⠑⠀⠀⣼⣿⣷⠂⠢⣄⣀⠀⢀⣤⠆⡽⢀⣤⣦⣴⡶⠋⠀⠀⠀⠀⠀⠀⣾⢿⣿⣷⠀⠘⢿⣿⠳⣄⠀⣬⣿⣾⠟⢋⣄⣠⠟⠻⠶⢶⣆⠀⠀⠀⠀⠀⠀⠀⣿⣼⣿⣿⡆⠀⠀⠙⣦⡙⣷⣾⠟⠛⢛⣛⣋⡁⠀⡀⢀⢀⣿⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⠀⠀⠀⠘⣿⣿⠷⠚⠋⠉⠉⢻⣿⠿⣷⣿⣾⣿⠀⠀⠀⠀⠀⠀⠀⠚⠛⠉⠼⠟⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠈⠀⠀⠼⣿⠿⠋⠀⠀ That's the next layer below. I'm writing a book about what makes developers irreplaceable in the age of AI. Join the early access list → Naz Quadri owns more USB cables than any reasonable person should and still can't find one that does Thunderbolt. He blogs at nazquadri.dev. Rabbit holes all the way down 🐇🕳️. Templates let you quickly answer FAQs or store snippets for re-use. as well , this person and/or - HID (Human Interface Device) — keyboards, mice, game controllers, touchscreens. Reports are small fixed-size packets sent on interrupt endpoints. The HID spec defines a report descriptor language that lets devices describe their own button layouts and axis mappings. It's surprisingly expressive and surprisingly painful to parse.- Mass Storage — USB drives, external SSDs. Uses bulk transfers and speaks SCSI commands over USB (a protocol called BOT — Bulk-Only Transport). Your thumb drive is pretending to be a SCSI disk from the 1990s.- CDC (Communications Device Class) — serial ports, network adapters. This is what Arduino boards use to show up as /dev/ttyACM0. CDC-ACM (Abstract Control Model) emulates a serial port. CDC-ECM and CDC-NCM emulate Ethernet interfaces.- Audio — microphones, speakers, DACs. Uses isochronous transfers for guaranteed timing. The class defines controls for volume, mute, sample rate selection.- Video — webcams (UVC — USB Video Class). Also isochronous. Defines format negotiation so the host can request specific resolutions and frame rates. - USB 2.0/3.2/4 Specifications — the official specs from USB-IF. Dense but definitive; start with the architecture overview chapters.- USB in a NutShell — Beyond Logic's classic tutorial that walks through USB concepts from endpoints to descriptors. The best free introduction to the protocol.- lsusb(8) man page — the Linux utility for listing USB devices and decoding their descriptors. Pair with lsusb -v to see what your kernel actually negotiated.- USB Type-C and USB Power Delivery — USB-IF's overview of the USB-C connector spec and Power Delivery protocol. Explains why one cable shape now carries data, video, and 240W of power.- NVM Express Base Specification — the NVMe spec provides an instructive contrast: where USB polls for device status, NVMe uses submission and completion queues with MSI-X interrupts for near-zero-latency I/O.