New interim release. Multiple bugs fixed.
https://github.com/netrunner01/USBDDOS/blob/m … 0.0-alpha.3.zip
## [1.0.0-alpha.3] — 2026-05-26
First fork-side release with substantive code changes since alpha.1 (the
intervening alpha.2 was a housekeeping refresh of build provenance after
upstream merged the alpha.1 patch series). Covers three buckets:
* **Defensive hardening absorbed from the alpha.2.1 release branch**:
graceful-skip handling for unsupported device classes during
enumeration (Gap I), and DPMI page-boundary correctness for OHCI DMA
structures under HDPMI32 (Gap H). Both shipped as `v1.0.0-alpha.2.1`
on a dedicated release branch in May 2026 with limited distribution;
this release brings them onto master and into the standard release
bundle.
* **EHCI bug fixes uncovered by real-hardware diagnostic work**:
full-speed/low-speed `bInterval` was treated as a log-scale exponent
(Gap H5) causing HID devices behind a USB 2.0 hub to be polled at
128 ms when they requested 10 ms, manifesting as 1-2 second per
keystroke on the affected silicon. Independent of that, the HID class
driver dispatched asynchronous control transfers from interrupt
context (Gap-K), violating EHCI_ControlTransfer's "no pending
transfers" precondition and aborting under sustained typing; the
Workaround-A patch in this release removes the trigger surface
entirely.
* **Packaging hygiene for DOS environments without working LFN**:
release bundles now use a directory-based variant taxonomy
(`RELEASE\USBDDOS.EXE`, `DEBUG\USBDDOS.EXE`) instead of suffixed
filenames (`USBDDOS-DEBUG-GAPJK.EXE`), so every file and directory
fits the 8.3 short-filename format cleanly. A new `make release`
target orchestrates the full build-and-package flow.
**Alpha designation**: real-hardware verification has been received for
the Gap-J/Gap-K investigation that motivated H5 and Workaround A
(tester reports `debugd2.TXT` and `debuge2_1_.TXT`, May 2026, on a
USB 2.0 hub topology with a Logitech HID composite). Promotion to beta
remains contingent on independent verification of the H5+Workaround-A
behavior across additional hardware.
### Added
* **`scripts/release.sh`**: orchestrator for `make release`. Builds
DJGPP release+DEBUG and Watcom release+DEBUG, extracts the latest
changelog section into `RELNOTES.TXT`, stages the bundle directory
layout, validates every file and directory for 8.3 SFN compliance,
and produces `dist/usbddos-vX.Y.Z.zip`. Refuses to run if the
requested VERSION doesn't match `CHANGELOG.md`'s latest `## [...]`
header, preventing accidental release of an undocumented version.
* **`scripts/bundle-templates/`**: in-bundle `README.TXT` (user-facing
quick-start and switch reference) and `COM1LOG.TXT` (COM1 capture
setup for DEBUG builds).
* **`make release` target** in `Make/Makefile`: invokes
`scripts/release.sh`.
### Fixed
* **Gap I — graceful skip hardening** (PR #31, originally on the
`release/v1.0.0-alpha.2.1` branch): malformed or unsupported
interface descriptors during enumeration no longer abort the whole
device. Adds Interface Association Descriptor (IAD) recognition,
`bNumInterfaces` cap, and zero-length descriptor defense. Surfaced
by tester report of audio-class composite devices freezing the host
during HID-only enumeration.
* **Gap H — DPMI page-boundary correctness** (PR #32, originally on
the `release/v1.0.0-alpha.2.1` branch): `DPMI_DMAMallocNCPB` in
`dpmi_dj2.c` was checking C-pointer-space page boundaries instead of
linear-address-space boundaries. Under HDPMI32 with a non-page-aligned
DS base, this gave OHCI DMA structures that straddled physical page
boundaries, corrupting transfers. Watcom build was unaffected
(`dpmi_bc.cpp` was already using linear addresses correctly).
* **Gap H5 — full-speed/low-speed `bInterval` log-scale conversion**:
EHCI's `EHCI_CreateEndpoint` treated the device-reported `bInterval`
(which is a linear millisecond period per USB 2.0 § 9.6.6 for
FS/LS endpoints) as if it were a log-scale exponent — the same way
the high-speed branch correctly does for high-speed endpoints. A
typical HID keyboard with `bInterval = 10` (10 ms requested) was
placed on slot 7 (128 ms polling) — a 12.8× under-sampling that
manifested as 1-2 seconds per keystroke on the affected setup. The
fix computes `floor(log2(bInterval)) + 1` and uses that as the
periodic-schedule slot index, putting `bInterval = 10` on slot 3
(8 ms polling — closest power-of-2 not exceeding 10 ms). High-speed
handling is unchanged.
* **Gap-K Workaround A — remove async control transfer from HID
interrupt callback**: `USB_HID_InputKeyboard` was dispatching
asynchronous `SET_IDLE` requests via `USB_SendRequest` from
interrupt context to toggle the device's idle state on key
transitions. This violated the explicit assumption in
`EHCI_ControlTransfer` (documented in a source-code comment next
to the relevant assertion) that "control transfers are synced
(from USBD), and there's no pending transfers". Under sustained
typing, a second async control transfer could arrive before the
first's qTD chain had fully cleaned up, tripping the assertion and
aborting USBDDOS. The H5 fix mitigates this in practice by closing
the timing window (16× faster polling = much narrower overlap
window) but doesn't fix it architecturally. Workaround A programs
`SET_IDLE(MINIMAL = 4 ms)` once at install time via the existing
synchronous path and removes the toggle entirely. Bandwidth cost:
~1 KB/sec per HID device on USB 1.1, under 0.1% of the bus.
Residual exposure: `USB_HID_Keyboard_SetupLED` still dispatches an
async `SET_REPORT` for LED state on Caps/Num/Scroll Lock keypresses,
but at human-rate trigger probability is dramatically lower. Tracked
for future Workaround B or proper-fix in alpha.4 scope.
### Changed
* **Bundle layout** is now 8.3 SFN-compliant throughout. Previous
bundles shipped names like `USBDDOSP-DEBUG-GAPJK.EXE` (20-character
base) that depended on a working LFN driver to be visible at their
full name. The new layout keeps the canonical binary names
`USBDDOS.EXE` and `USBDDOSP.EXE` at every level and moves the variant
taxonomy into the directory hierarchy:
* `RELEASE\USBDDOS.EXE` / `RELEASE\USBDDOSP.EXE`
* `DEBUG\USBDDOS.EXE` / `DEBUG\USBDDOSP.EXE`
* **Text file names** in the bundle were also brought into 8.3
compliance: `RELEASE-NOTES.txt` → `RELNOTES.TXT`,
`COM1-LOGGING.txt` → `COM1LOG.TXT`, `CHANGELOG.md` → `CHANGES.TXT`
(the repo's `CHANGELOG.md` is unchanged; the script copies it as
`CHANGES.TXT` into the bundle). `COPYING` → `COPYING.TXT`.
### Not changed
* The build system itself. `Make/Makefile`, `Make/Makefile.WC`, and
`Make/Makefile.BC` already produced 8.3-compliant binary names
(`output/usbddos.exe` and `output/usbddosp.exe`); only the
packaging step was renaming them to introduce the LFN-dependent
variants. The build's compile-and-link commands are unchanged.
* Upstream-merged code. The fork's master remains synced to
`crazii/USBDDOS:master` (rebased after the H5 fix landed) with
the fork-side commits as a clean linear delta on top.
### Field-validation status (real-hardware reports)
* **Gap I**: tester confirmation on KT133A + NEC µPD720101 chipset
(May 2026, alpha.2.1 binary).
* **Gap H**: tester confirmation on Intel ICH-style southbridge + USB
2.0 hub topology (May 2026, alpha.2.1 binary).
* **Gap H5**: tester confirmation on Intel ICH + dual-OHCI/EHCI bridge
with USB 2.0 hub + Logitech HID composite. Pre-H5: 128 ms polling
measured (assertion abort under typing). Post-H5: 8 ms polling
measured (slot=3), typing speed restored, no abort.
* **Gap-K Workaround A**: assertion was captured firing in
`debugd2.TXT` (May 2026) and verified not firing in `debuge2_1_.TXT`
with H5 in place. Workaround A removes the trigger surface
entirely so the failure mode can no longer be reproduced by code
inspection; runtime reverification is included as the standard
alpha.3 acceptance criterion.
### Reference upstream commit
Master is rebased onto upstream `crazii/USBDDOS:master` as of the
fetch immediately preceding this release. The H5, Gap-K Workaround A,
and packaging commits are the fork-side delta on top of that
upstream tip. Run `git log --oneline upstream/master..HEAD` on the
fork to see the exact three commits.
### Note on the alpha.2.1 release branch
The `release/v1.0.0-alpha.2.1` branch and the `v1.0.0-alpha.2.1` tag
remain published as historical references — they contain the
PR #31 (Gap I) + PR #32 (Gap H) patches in their original packaging
(suffixed filenames pre-dating the SFN refactor). The functionally
equivalent fixes are now on master and ship in this alpha.3 bundle
under the new layout. Anyone tracking the fork via master will get
the alpha.3 contents naturally; the alpha.2.1 release is preserved for
reproducibility of anything previously distributed against that tag.