Releases: netrunner01/USBDDOS
Release list
USBDDOS USB-for-DOS tester v2.0.0-alpha.1.1 - skip controllers with no BAR base
USBDDOS USB-for-DOS tester — v2.0.0-alpha.1.1
Point release on top of v2.0.0-alpha.1: one fix and a packaging change.
Fix — controllers with no base address are skipped, not hung
When USB is disabled in the BIOS, the host controller is still listed on the PCI
bus but its base address register (BAR) is left unprogrammed and reads 0. The
driver used to read that 0 and then issue port I/O / map memory at address 0,
which hangs the machine. UHCI, OHCI, and EHCI controller init now detect a base
of 0, log a clear "skipping controller" line, and ignore that controller. PCI
hardwires unassigned BARs to 0, and on a PC a working USB controller is never
based at address 0, so 0 is an unambiguous "not usable" signal.
Packaging — one archive
UDD2A211.ZIP now contains the driver, tester menu, tools, docs, and a
ready-to-write 1.44 MB bootable floppy image (UDD2A211.IMG) in a single flat
download. All names are 8.3, so it extracts cleanly under plain DOS.
Validation
- Regression: identical pass/fail across the full UHCI/OHCI/EHCI x
keyboard/mouse/mass-storage/hub matrix versus the previous build. The guard is
dormant whenever a BAR is programmed, so normal enumeration is unchanged. - Base-0 path: with the base forced to 0 for each controller type, the
driver detects it, logs the skip, and returns to DOS without hanging. - Still emulator-only. Real-hardware USB-to-PS/2 mouse cursor and button
behaviour remains the highest-value thing to confirm this round.
Reporting
Please file bugs as GitHub issues: https://github.com/netrunner01/USBDDOS/issues
A capture showing a hang or crash (rather than a device being safely ignored) is
the most important thing to report.
License
GPL-2.0 (fork of crazii/USBDDOS). Bundled FreeDOS components and the Japheth HX
HDPMI runtime are open-source / freely redistributable; see LICENSE.TXT.
USBDDOS USB-for-DOS tester - 386/486+ real-mode, UHCI/OHCI/EHCI
Binding constraint: real-mode DOS on 386/486-class or later PCs with a UHCI, OHCI (USB 1.x) or EHCI (USB 2.0) host controller. USB 3.0 / xHCI is out of scope.
Base / runtime: FreeDOS 1.4 — kernel, FreeCOM, HIMEMX, JEMM386 and CWSDPMI extracted unmodified from the official FreeDOS 1.4 LiveCD. The driver runs under an HDPMI port-trapping DPMI host. This is a DEBUG/diagnostic build: it logs to COM1 at 9600 8-N-1.
Licensing (up front): everything here is open-source or freeware with explicit redistribution rights — no abandonware, no grayware. USBDDOS is GPL-2.0 (fork of crazii/USBDDOS); the FreeDOS components are GPL/open-source; HDPMI is Japheth's HX runtime (freeware, freely distributable); MODE is FreeDOS GPL-2.0. Per-file detail in LICENSE.TXT.
What this is: a major testing release. The goal of this round is to gather real-hardware results across a range of 386/486-and-later machines and USB chipsets for USB keyboard, mouse, and mass-storage support.
Downloads
usbddos-tester-v2.0.0-alpha.1.zip— driver + tester menu + tools + docs. Copy onto a DOS medium that already has HIMEM/EMM386, then runSTART.usbddos-tester-bootdisk-v2.0.0-alpha.1.zip— the above plus a ready-to-write 1.44 MB bootable FreeDOS floppy image that boots straight into the tester menu with memory management already configured.
Validation status
- Confirmed in emulation (QEMU 8.2.2 + Bochs): UHCI/OHCI/EHCI enumeration of keyboard, mouse and mass storage; devices behind a USB hub enumerate; idle mouse reports are skipped and the 8042 injection waits are bounded (no hangs).
- NOT yet confirmed — and the reason this round exists: end-to-end USB-mouse cursor motion and button behaviour reaching a PS/2 consumer on real hardware (emulators cannot exercise the USB-to-PS/2 8042 hand-off faithfully), plus timing/foreground responsiveness under load. Real-hardware mouse and button captures are the highest-value results.
Reporting
Fill in REPORT.TXT and attach your full COM1 capture log. A capture that shows a hang or crash (rather than a device being safely ignored) is the most important thing to report.
v1.0.0-alpha.3
v1.0.0-alpha.3 release
v1.0.0-alpha.2.1 — defensive-hardening
v1.0.0-alpha.2.1 — defensive-hardening
Released: May 19, 2026
Tag: v1.0.0-alpha.2.1
Upstream base: crazii/USBDDOS at b1308fb + PR crazii#31 + PR crazii#32 carried as fork-side commits
Type of release
Defensive-hardening release. Two functional patch series targeting USB enumeration freezes and OHCI DMA-structure page-crossing risks. Both patch series are also open as PRs against upstream crazii/USBDDOS (PR crazii#31 and PR crazii#32 in this fork's release set) and are carried as fork-side commits in the alpha.2.1 binaries until they merge upstream.
This is NOT a housekeeping release. Alpha.2 was housekeeping. Alpha.2.1 is not. There are real code changes in:
USBDDOS/usb.c— descriptor parser hardeningUSBDDOS/HCD/ohci.c— no-page-crossing DMA allocationUSBDDOS/usballoc.c— pool arena no-page-crossingUSBDDOS/DPMI/dpmi_dj2.c— linear-address-space NCPB check fix
What's new
Gap I (PR crazii#31) — graceful-skip hardening for unsupported device classes
Four edits in USBDDOS/usb.c plus one new constant in USBDDOS/usb.h:
-
Improved no-driver-found log surfaces the full
bDeviceClass/bDeviceSubClass/bDeviceProtocoltriplet plus a human-readable class name (audio,wireless,miscellaneous(IAD),vendor, etc.):- Was:
No driver found at port: 0 for device (class 01), skip - Now:
No driver found at port: 0 for device (class 01/01/04 audio), skip
- Was:
-
Explicit Interface Association Descriptor recognition (
USB_DT_INTERFACE_ASSOCIATION = 0x0B) in the descriptor walker, with informational_LOGoffirstIf/count/funcClass. No semantic change — USBDDOS continues to bind class drivers at device level, not function level, and does NOT use IAD'sbFunctionClassfor driver lookup. -
bNumInterfaces > 32cap mirroring Linux'sUSB_QUIRK_HONOR_BNUMINTERFACESdefensive pattern. The cap value is persisted topConfigList[].bNumInterfacesso subsequent malloc and memset operate on the same size (regression guard against heap buffer overrun). -
Zero-length descriptor defensive break:
if (len == 0) break;in the walker loop. Without this, a malformed device emitting any descriptor withbLength = 0causes a hard infinite loop oni = i + len. Strong candidate fix for the tester's KT133A+NEC+mixed-class-hub freeze.
Gap H (PR crazii#32) — no-page-crossing enforcement for OHCI DMA structures
Three coordinated changes:
-
USBDDOS/HCD/ohci.c: apply theDPMI_DMAMalloc → DPMI_DMAMallocNCPBmacro override at the top of the file, mirroring the pattern EHCI has used since its bring-up (ehci.c:25-30). OHCI's HCData allocation is the highest-risk site: it embeds the 256-byte HCCA plus 8 static EDs (~548 bytes total) and a plainDPMI_DMAMalloccould place it straddling a 4KB page boundary, silently breaking DMA for either the HCCA or the static EDs. -
USBDDOS/HCD/ohci.c: add DEBUG-build defense-in-depth assertions at the HCCA register-write site verifying the produced allocation actually fits within a single physical page. -
USBDDOS/usballoc.c: switch pool-arena allocations (both the on-demandUSBALLOC_GetMemorypath and theUSBALLOC_Initpre-allocation path) fromDPMI_DMAMalloctoDPMI_DMAMallocNCPB. Variable-size paths stay on plainDMAMallocbecause transfer buffers may legitimately exceed a page (OHCI § 3.1.1.1 supports buffers spanning one page boundary via the TD'sCBP/BEmechanism).
Bug fixed in the same commit: DPMI_DMAMallocNCPB in dpmi_dj2.c (DJGPP build path) was checking page boundaries in C-pointer-relative space rather than linear-address space. Under HDPMI32 with a non-page-aligned XMS mapping base — observed XMS lbase 002e1c00 (offset 0xC00 within its page) on QEMU — C-pointer "pages" and linear "pages" live on different grids offset by (DPMI_DSBase & 0xFFF). An allocation that NCPB previously declared page-contained in C-pointer space could still straddle a linear page boundary, which is what the hardware sees for DMA. The fix translates via DPMI_DSBase before the boundary test.
The Watcom/Borland path (dpmi_bc.cpp:991) was already correct — it uses DPMI_PTR2L(ptr) to get the linear address before the check, so only the DJGPP build was affected. EHCI was latently exposed to the same bug since its bring-up but evidently has not been hit in practice because its DMA structures (QH 96B, QTD 32B, iTD 64B) are small enough that the probability of crossing a linear-page boundary is much lower than for OHCI's 548-byte HCData.
Recommended upgrade triggers
- Hit the unsupported-class enumeration freeze. Typical: USB audio, Bluetooth dongle, or wireless-USB device behind a hub alongside HID devices. Specifically reported on KT133A + NEC µPD720101 + 4-port hub with USB microphone (class 0x01), BT dongle (class 0xE0), and two composite HID devices.
- Suspect OHCI DMA corruption on a DJGPP build using HDPMI32. XMS heap linear base may not be page-aligned, exposing the latent NCPB bug fixed in this release.
- Running alpha.1 or alpha.2 without observed symptoms: upgrade is optional but recommended.
Real-hardware verification status
The alpha label is retained for this release.
Both patch series were verified in QEMU (OHCI + usb-audio enumeration, mixed-class kbd + audio scenario across two OHCI controllers) and via a native-Linux unit test exercising the descriptor parser against synthetic descriptors (5 cases: audio with CSINTERFACE chain, IAD composite, bNumInterfaces=200 cap, malformed zero-length descriptor, interface overrun — all pass).
Real-hardware report against the original tester's KT133A+NEC configuration is still pending. If you can test on real silicon and file a report, please open an issue at Netrunner01/USBDDOS/issues.
The "alpha" label means real-hardware verification on the silicon the patches target is still pending — it does NOT mean the code is unstable or broken. Promotion to beta or v1.0.0 still requires at least one independent real-hardware test report per patched gap.
Build provenance
All four binaries in usbddos-v1.0.0-alpha.2.1-bundle.zip were built from the release-branch tip at commit 810b58b on a Linux x86_64 sandbox with DJGPP gcc 12.2.0 and Open Watcom v2.0 beta. DJGPP binaries embed the build-ID string 810b58b, DJGPP. Watcom binaries are bit-stable across rebuilds at the same commit.
| Binary | Toolchain | Mode | Size |
|---|---|---|---|
USBDDOS.EXE |
Open Watcom v2 | release | 65,402 |
USBDDOS-DEBUG.EXE |
Open Watcom v2 | DEBUG | 95,348 |
USBDDOSP.EXE |
DJGPP 12.2.0 | release | 208,384 |
USBDDOSP-DEBUG.EXE |
DJGPP 12.2.0 | DEBUG | 368,295 |
All four builds compile clean with the project's existing -Werror -Wconversion -Wsign-compare -pedantic-errors flag set.
Notes
- No CWSDPMI / HDPMI32 host preference change recommended. The NCPB fix is in the DJGPP build path (
USBDDOSP.EXE). The Watcom build (USBDDOS.EXE) was never affected. - QEMU regression test coverage: 7-test ladder still passes 7/7, plus an 8th test case (OHCI + usb-audio with HDPMI32 capturing the graceful-skip log line) passes.
- After PRs crazii#31 and crazii#32 merge upstream, a future alpha.3 release will cut from that new upstream tip (mirroring the alpha.1 → alpha.2 cycle).
License
GPL-2.0. See COPYING inside the release bundle. Source for these binaries is at this tag.
v1.0.0-alpha.2 (housekeeping) — binaries refreshed from upstream after PRs merged
v1.0.0-alpha.2 — housekeeping release
This is a housekeeping release. No new code, no functional
changes, no bug fixes. If v1.0.0-alpha.1 is already running on your
system, there is no reason to update.
What this release actually is
Between May 13 and May 15, 2026, upstream crazii/USBDDOS merged
every patch from this fork's v1.0.0-alpha.1 series — PRs crazii#22 through
crazii#30, covering the full 8-gap OHCI/HCD/hub catalog. The patches now
live at upstream master (b1308fb) and are no longer carried as
fork-side cherry-picks.
This v1.0.0-alpha.2 release exists to refresh the attached binaries'
build provenance: alpha.1's binaries were built from a fork-side
tag, alpha.2's are built directly from a public upstream commit.
Anyone can verify the alpha.2 binaries by running:
git clone https://github.com/crazii/USBDDOS.git
cd USBDDOS && git checkout b1308fb && cd Make
wmake -f Makefile.WC DEBUG=1 # produces USBDDOS.EXE
make -f Makefile # produces USBDDOSP.EXE
The MD5 of the resulting USBDDOS.EXE should match
39962c2092961ba679467ba46ab24c43 (the Watcom toolchain produces
deterministic output for identical source).
What's actually different between alpha.1 and alpha.2
Nothing functional. Specifically:
USBDDOS.EXE(Watcom debug): byte-identical to alpha.1's. Same
94,380 bytes, same MD539962c2092961ba679467ba46ab24c43. This
match confirms that Crazii merged each patch unmodified.USBDDOSP.EXE(DJGPP release): differs by exactly 7 bytes from
alpha.1's — the embedded git short-hash in theUSBDDOS_BUILD
define (b1308fbhere vsafb2b84in alpha.1). All other bytes
identical.
If you have one of the affected target platforms and were testing
alpha.1: keep going with what you have. Your reports against
alpha.1 are valid for alpha.2 and vice versa. Don't restart your
testing.
Why a separate release at all
A few practical reasons:
- The fork's release page is the public-facing artifact people find
via search; "binaries built from upstream commit X" is more useful
guidance than "binaries built from this fork's afb2b84." - The CHANGELOG and README needed to be updated to reflect upstream's
resumed activity. Cutting a release marks the corresponding
documentation state. - If a future bug is reported against the binaries, it's clearer to
reference alpha.2 (which points at a verifiable upstream commit)
than alpha.1 (which points at a fork-side tag whose relationship
to upstream needs explanation).
What this release does NOT do
- Add new fixes (Gap 7 and EHCI USBLEGSUP/USBLEGCTLSTS still pending)
- Bump the alpha label — real-hardware verification is still pending
and is unrelated to where the source lives. Promotion to beta or
v1.0.0 still requires at least one independent real-hardware test
report per patched gap. - Change any user-facing behavior
Upstream PRs merged (recap for the historical record)
- PR crazii#17 — stanwebber: case-correct
#includepaths - PR crazii#22 — Debug: enable COM1 logging in
_LOGpath - PR crazii#23 — HCD: relax
HCD_RemoveDeviceteardown asserts - PR crazii#24 — Gap 4: fix invalid
ClearPortFeature(PORT_RESET) - PR crazii#25 — Gap 8: wait POTPGT × 2ms after SetPortPower
- PR crazii#26 — Gap 2: INITRESET-equivalent verify-and-retry
- PR crazii#27 — Gap 3: bound the OHCI SMM-handoff wait loop
- PR crazii#28 — Gap 1: OHCI UnrecoverableError recovery
- PR crazii#29 — Gap 6: skip HcFmInterval access on ALi M5237
- PR crazii#30 — Gap 5: disable OHCI Legacy Support emulation
License
GPL-2.0, inherited unchanged from upstream crazii/USBDDOS.
v1.0.0-alpha.1 — OHCI compatibility fixes for legacy DOS hardware
v1.0.0-alpha.1 — OHCI compatibility fixes for legacy DOS hardware
What this is
A research fork of crazii/USBDDOS
maintained at upstream commit 54345d0 (Feb 2024). Upstream has been
functionally dormant since early 2024; this fork is a public home for
a focused set of OHCI compatibility patches targeting 386–486 /
early-Pentium DOS hardware (NEC, ALi, SiS, OPTi OHCI silicon).
About the -alpha.1 designation: this version is alpha because
real-hardware verification on the silicon the patches target is
pending — NOT because the code is unstable or broken. Specifically:
- All 12 commits build clean with
-Werroron both Open Watcom v2 and DJGPP gcc 12.2.0. - The 7-test QEMU regression suite passes 7 / 7.
- Every patch is derived from authoritative documentation (USB 2.0
spec, Linux
pci-quirks.c, Apple DarwinIOUSBFamily, chip vendor datasheets, FYSOS Book 8).
What's missing is a regression pass against the actual silicon each chip-quirk fix targets. QEMU emulates spec-compliant USB devices; the patched paths exist precisely because real silicon deviates from spec. So the code works in the emulator and addresses identifiable bugs from upstream reports — but the proof that each fix behaves correctly against the real chip is missing.
This release moves to beta when at least one independent real-hardware test report exists per patched gap. If you have any of the affected hardware listed below and can run a smoke test, please file an issue with results either way.
What's fixed (vs upstream crazii/USBDDOS@54345d0)
The full per-gap detail is in CHANGELOG.md. Short version:
| Gap | Symptom | Hardware most affected |
|---|---|---|
| 1 | OHCI driver dies silently after Unrecoverable Error interrupt | NEC OHCI, generic |
| 2 | OHCI init silently fails on first try; HcFmInterval doesn't latch | OPTi 82C861 (FireLink), older SiS |
| 3 | USBDDOS hangs at load on BIOSes that don't release SMM ownership | Intel ICH/PCH, some VIA |
| 4 | Devices behind a USB hub fail to enumerate; assertion at hcd.c(91) | Any USB hub topology |
| 5 | PS/2-emulated keyboard ghosting, spurious interrupts | NEC µPD720101, SiS 7001 |
| 6 | System hard-hangs on USBDDOS load with no log output | ALi M5237, ALi M1543C, ULi |
| 8 | Hot-plugged USB device intermittently fails first-try enumeration | NEC µPD720101 (POTPGT race) |
| HCD | Plugging in unsupported device class triggers assertion | Anyone plugging in audio / printer / vendor-specific class |
Plus: case-correct #include paths for cross-build on Linux,
COM1 _LOG output enabled in debug builds, README discoverability
sections, and CHANGELOG.md.
Affected hardware
NEC µPD720101 / µPD720100A / NEC USB 2.0 PCI card · ALi M5237 · ALi M1543C · ULi · SiS 7001 / 630 / 5595 · OPTi 82C861 / FireLink · VIA VT82C686A/B / VT8231/8233/8235/8237 · Intel ICH4–ICH10 / Cougar Point / Panther Point / NM10 · AMD-756 / AMD-768 · KT133A · Mac Mini 2011 · Sandy Bridge ThinkPads · Compaq Evo N600c · Toshiba Portege M200 / Satellite 2410 · Lenovo ThinkPad T540p · Asus Eee PC (Atom / Cedarview) · Gigabyte P67-DS3-B3.
(Listed silicon and platforms are those for which authoritative documentation or upstream bug reports identify a specific USBDDOS-side fix. Other hardware may benefit indirectly from the defensive HCD changes.)
How to use this release
This release ships as source patches, not binaries.
To build:
- Clone this repo:
git clone https://github.com/Netrunner01/USBDDOS.git - Check out this version:
git checkout v1.0.0-alpha.1 - Build with Open Watcom v2 (May 2026 snapshot or later) for the
deployment binary
usbddos.exe, or DJGPP gcc 12.2.0+ forusbddosp.exe. Build instructions are in upstream's README, unchanged in this fork.
To test on your hardware:
- Replace your existing USBDDOS.EXE with the freshly built one.
- Run
USBDDOS /hidorUSBDDOS /diskper upstream's documentation. - File an issue on this repo with the results — what hardware, which mode, what happened. Reports of "it worked fine" are just as valuable as bug reports for moving to beta.
What this release does NOT do
- No xHCI support (upstream-planned, out of scope here).
- No EHCI USBLEGSUP/USBLEGCTLSTS BIOS handoff yet — likely root cause of remaining hangs on Intel Cougar Point / Panther Point systems (Gigabyte P67-DS3-B3, Mac Mini 2011 EFI-class platforms).
- No Gap 7 fix yet — NEC
kErrataNECIncompleteWritewrite-1-to-clear retries onHcRhPortStatusis sketched but not patched. - No real-hardware test reports yet (see "About the alpha designation" above).
Acknowledgements
- crazii — original author of USBDDOS.
- stanwebber — independent case-
sensitivity fix work in
stanwebber/USBDDOS(April 2025), filed upstream issues crazii#17 and crazii#19. The Build commit in this fork arrives at the same fix shape independently. - philippe-85 — diagnosed and reported the hub-feature-confusion symptom in upstream #16; the Gap 4 fix here is in the same code region.
- hjnijlunsing, volkertb, AudrenThibault, L10N37, wxpc8 — upstream issue reports that helped scope this fork.
- Linux USB host-controller code (
drivers/usb/host/). - Apple Darwin
IOUSBFamily. - Benjamin Lunt (fysnet), FYSOS Book 8.
License
GPL-2.0, inherited unchanged from upstream crazii/USBDDOS. See the
COPYING file in the repo for the full text.