How USB Devices Are Detected by the OS: A Guide (2026)

USB devices are detected by the OS through a host-driven handshake called USB enumeration: the host controller resets the port, then asks the device for a set of descriptors over the control pipe, and uses what comes back to choose a driver. The device never introduces itself, and nothing is sent unsolicited at plug-in. That single fact explains most of the confusing USB behaviour people run into.

It also matters that detection and driver binding are two separate stages. Your OS can detect a device perfectly well and still have no driver for it, which is exactly what an “Unknown Device” entry in Device Manager is. This guide walks the whole path, then shows you how to inspect it on your own machine.

Table of Contents

What Happens When a USB Device Is Connected?

Detection begins electrically, before any software is involved. The port supplies 5 V from the bus, and a device that has power pulls one of the two data lines up through a resistor: D+ for full and high speed, D- for low speed. Which line is pulled is how the host learns the speed the device wants to talk at.

The host controller sees the change on the port status register and waits out a short debounce period before believing it. That wait is deliberate. A slightly loose connector chatters, and without debouncing every one of those bounces would look like a fresh plug-in event.

From there the host takes over completely. It resets the bus, reads the device descriptor at address zero, gives the device a unique address, reads the rest of the descriptors, selects a configuration, matches each interface against a driver, and finally hands the device to user space. Applications only see a device after all of that has finished.

One common misconception deserves clearing out now. The device does not broadcast a name or a product ID when you plug it in; the host asks, and the device answers only on endpoint zero, the default control pipe. Everything the OS knows about your device came from a question it asked first.

What USB Information Does the OS Read?

The answers arrive as descriptors, which are just small binary blocks with fixed fields. The OS reads a chain of them, and each one narrows down what the device can do and how it should be treated.

DescriptorWhat it containsWhat the OS decides from it
DeviceVendor ID, product ID, device release, class codes, number of configurations, indexes pointing at the string descriptorsThe device’s identity, and whether it declares more than one interface
ConfigurationInterface count, configuration value, attributes such as self-powered or bus-powered, maximum power drawWhich configuration to activate and whether the bus can supply the device
InterfaceInterface number, alternate setting, endpoint count, class, subclass and protocol codesWhich driver binds. This is the field that matters most in practice
EndpointEndpoint number and direction, transfer type, maximum packet size, polling intervalHow data moves, and how much of the 1 ms frame the device reserves
StringManufacturer name, product name, serial number, stored as UTF-16The friendly name you see in Device Manager, and the serial used for per-device rules

Descriptors describe, they do not prove. A device reports a device class of mass storage whether or not the hardware behind it behaves like one, and the OS takes those reports at face value until something fails at run time. That gap between what a device claims and what it does is behind a surprising number of “detected but unusable” cases.

Why the interface descriptor drives driver selection

A composite device is one physical box exposing several independent functions, such as a webcam that is also a microphone. Because each interface carries its own class code, the OS can bind a different driver to each function of the same cable, which is why one plug can produce several entries in your device list.

How Does the USB Host Controller Find a Device?

The host controller is the piece of hardware that owns the bus, usually an xHCI controller on a modern machine. Its root hub has ports, and each port has a small state machine that walks from unoccupied through attach, debounce, reset and enabled, ending at assigned once the device has an address.

The controller learns about the change from its status interrupt, reads the port change bits, and then drives the port through that sequence itself. Any hub between the controller and your device repeats the same process for its downstream ports, so a device three boxes deep is enumerated port by port rather than in one leap.

Once the port is enabled, the controller exposes the device as a structure in host memory and the operating system’s bus driver starts issuing control transfers against it. From that point, detection is software talking to software.

How USB Devices Are Detected by the OS: The Enumeration Sequence

Enumeration is a fixed handshake with a fixed order. Knowing the steps in order turns a vague “USB is not working” into “step four failed”, which is the difference between a ten-minute fix and a hardware swap.

  1. Attach. The port powers VBUS and the device pulls up D+ or D- to declare its speed.
  2. Bus reset. The host resets the port and waits for the device to return to a known default state at address zero.
  3. Read the first 8 bytes. The host requests the device descriptor header just to learn the real length of the descriptor.
  4. Set the address. The host sends SET_ADDRESS and the device adopts a unique address on the bus.
  5. Read the full descriptors. With the address set, the host reads the complete configuration, interface and endpoint descriptors, plus the string descriptors.
  6. Set the configuration. SET_CONFIGURATION activates one configuration and selects the alternate setting for each interface.
  7. Match drivers. Each interface is matched against hardware IDs and class codes, and a driver is bound or a child device is created.
  8. Publish to user space. A device node and sysfs entry appear, udev or Plug and Play rules run, and applications can finally open the device.
StepTransferPurposeResult
ResetBus resetReturn device to default stateDevice listening on address zero
Descriptor headerControl, INLearn descriptor lengthHost knows how much to read
AddressControl, OUTGive the device a unique addressDevice addressable on the bus
Full descriptorsControl, INRead identity, interfaces, endpointsComplete device picture
ConfigurationControl, OUTActivate a configurationSelected interfaces powered up
Interface selectionControl, OUTChoose the active alternate settingEndpoints become usable
Driver bindingSoftwareMatch IDs and class codesFunction driver loaded
Node creationSoftwareExpose the device to user spaceApplications can open it

Control transfers are the backbone of all of this. Endpoint zero is the only endpoint guaranteed to exist on every device, and every step above uses it. Bulk, interrupt and isochronous transfers only become available once configuration is set, which is why nothing else works before step six.

How Do USB Drivers Get Selected?

On Windows, the bus driver compares what the device reported against hardware IDs stored in INF files. The pair USBVID_046D&PID_C52B is the match key, where the vendor and product IDs come straight from the device descriptor. Windows also builds compatible IDs that include the interface class codes, so a driver can match “any HID device” as well as one exact model.

When the class codes match an in-box driver, you are done. Keyboards, mice, mass storage and many serial adapters ship with working drivers already installed. When they do not, Windows creates the device object, finds no matching driver, and shows you a warning-marked entry instead of a working one.

Composite devices get special handling through Usbccgp, the composite parent driver. It creates a separate child device per interface, so a single keyboard with media keys and a storage function can end up with a different driver on each function.

Linux works the same way with different names. The usbcore driver keeps tables of vendor and product IDs that map to class drivers, interface class codes route each interface to the right subsystem, and udev rules then act on what showed up in sysfs and create a device node under /dev/bus/usb. macOS does the same matching inside IOKit.

One ID pair is worth recognising because it confuses everyone eventually: VID_0000&PID_0002. Those zeros are not a real manufacturer, they mean the host never managed to read a valid descriptor at all. The device is physically present and electrically alive, but enumeration stalled before it could identify itself.

How USB Detection Differs on Windows and Linux

The sequence itself is identical on both platforms because the USB specification defines it. What differs is the stack that implements it, the naming, and what you see when something goes wrong.

LayerWindowsLinux
Bus driverUSB host controller driver stackusbcore plus xhci-pci, ehci-pci or similar
Bus managerPlug and Play managerudev and the kernel hotplug path
Device databaseINF files and driver storeKernel driver tables plus udev rules
Generic function driverWinUSBusbfs or libusb on a device node
Composite handlingUsbccgp parent and child devicesOne device per interface in sysfs
Visible resultDevice Manager treesysfs tree and lsusb output

The practical difference shows up in debugging. On Windows you read a device tree and a code in Properties. On Linux you read sysfs attributes and kernel log lines, which tend to tell you the failing step more precisely.

How Can You Inspect USB Detection on Your System?

Everything below is read-only and safe to run. Command names and output fields vary between versions and device classes, so treat the labels as a guide rather than a contract.

On Windows

  • Run devmgmt.msc for Device Manager, then switch View to “by connection” to see the physical port topology.
  • Select a device and open Properties to read the hardware IDs tab, which shows the exact VID and PID strings used for matching.
  • Use pnputil /enum-devices /connected to list connected devices from the command line.
  • Use USBView from the Windows Driver Kit if you want to watch the descriptors and transfers themselves rather than the end result.
  • Attach WinDbg to the kernel to see the PnP stack trace while you plug the device in.

On Linux

  • lsusb lists devices, lsusb -t shows the bus tree, and lsusb -v -d VID:PID dumps the descriptors of one device.
  • cat /sys/kernel/debug/usb/devices prints a readable dump of everything the kernel enumerated. Mount debugfs first if the path is empty.
  • cat /sys/bus/usb/devices/1-2/ shows the attributes for one device, where the bus and port number appear in the directory name.
  • dmesg | tail or journalctl -k shows enumeration failures with the reason attached.
  • udevadm monitor watches hotplug events live as you plug something in.

On macOS, system_profiler SPUSBDataType and ioreg -p IOUSB cover the same ground. Watch a live view during plug-in if you can, because the moment you can see is the fastest way to tell a physical connection problem from an enumeration problem.

What Are the Common USB Detection Problems?

Almost every USB detection complaint maps to a small number of stages. Matching the symptom to the stage tells you where to look.

SymptomWhat it meansStage that failed
VID_0000&PID_0002 or Unknown DeviceNo valid descriptor was ever readDescriptor read
Device Manager shows a warning triangle, no error codeDetected fine, no driver matchedDriver binding
Code 43Driver loaded but the device reported it cannot startAfter configuration
Device appears then disappearsReset loop, usually power or signal integrityBus reset or later
Nothing at all, no soundNothing powered or nothing responded on the portAttach
Works on one port onlyPort or hub fault rather than a device faultAttach or reset

Insufficient power is the usual culprit for devices that enumerate then vanish. A bus-powered device that asks for more current than the port or an unpowered hub can supply will reset continuously, and that reads exactly like a flaky cable.

Cables and ports fail more often than people expect, particularly cheap multi-port chargers and hubs that share one upstream supply. Firmware settings matter too: a controller disabled in BIOS or UEFI, or a legacy USB support option turned off, stops detection before the OS ever sees the port.

Virtual machines add a layer of their own. With USB passthrough, the guest OS runs the same enumeration sequence but against hardware presented by the hypervisor, so a passthrough failure looks identical to a hardware failure on the guest side. On the host, the device may have already enumerated normally.

Frequently Asked Questions

Does a USB device announce itself to the computer, or does the computer ask?

The computer asks. A USB device never sends unsolicited data when it is plugged in; the host controller resets the port and then issues GET_DESCRIPTOR requests on endpoint zero, the default control pipe. The device answers those requests and nothing else. This is why a device with a broken descriptor block can be detected physically but never identified.

What does USB VID_0000 and PID_0002 mean?

It means the host controller never successfully read a valid device descriptor. The zeros are a placeholder, not a manufacturer code, and PID_0002 marks the failure state. The device is present and drawing power, but enumeration stalled before the identity fields could be read, usually because of a bad cable, signal integrity, a stalled device firmware, or a port that cannot supply it.

Why is there a delay between the connect sound and the drive appearing?

The sound fires when the OS notification arrives, which is partway through enumeration. After that the host still has to finish setting the address, reading descriptors, matching drivers, mounting the filesystem and indexing it. For a hard disk the indexing is often the slowest part, so a sound followed by several seconds of nothing is normal behaviour rather than a fault.

Do I need to write a driver for my custom USB device?

Only if your device does not use a class the operating system already supports. Keyboards, mice, mass storage, hubs and CDC serial devices work with in-box class drivers. For anything else you can pick a class that is already supported, or supply a generic driver such as WinUSB on Windows or a udev rule plus a device node on Linux, and skip writing a kernel driver entirely.

Can an operating system block a USB device after it has been enumerated?

Yes, and that is what device allow-listing does. The hardware enumerates normally, then a policy check rejects the matching hardware ID before the function driver is allowed to load. The device shows up in the system as a rejected or unknown entry. This is also why BadUSB-style attacks work: they ride the same enumeration path as legitimate hardware.

Conclusion

Start with the simplest question: did enumeration complete, or did it stop early. On Windows, open Device Manager in view-by-connection mode and read the hardware ID of anything that looks wrong. On Linux, run lsusb and then dmesg while you replug the device. That pair of commands tells you which of the eight steps failed, and everything else follows from there. Current as of 2026.

Leave a Comment