-
Notifications
You must be signed in to change notification settings - Fork 26
Run usbdevfs URBs asynchronously over IOKit #375
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| # Keep the USB loopback fixture out of the shipped binary by construction. | ||
| # | ||
| # USB_LOOPBACK_FIXTURE=1 swaps src/syscall/usbdev-fixture-stub.c for | ||
| # src/syscall/usbdev-fixture.c (the SRCS block in the top-level Makefile). That | ||
| # changes SRCS, not CFLAGS, and the stale-object guard in mk/common.mk is keyed | ||
| # on $(strip $(CFLAGS)) alone, so it has nothing to say about the switch: while | ||
| # both flavors linked to build/elfuse, building one and then asking for the | ||
| # other printed "Nothing to be done for 'elfuse'" and handed back whichever had | ||
| # been linked last. Measured before the split below, on the tree as it stood | ||
| # then: make clean; make elfuse; make USB_LOOPBACK_FIXTURE=1 elfuse; make elfuse | ||
| # left _usbdev_fixture_lock in build/elfuse until make clean. No byte counts | ||
| # here on purpose. That build needed both flavors to write one path, so it | ||
| # cannot be produced again to re-measure, and the pair this comment used to | ||
| # quote had gone stale against the tree twice over. The dated figures are in | ||
| # docs/internals.md; what reproduces today is what the check below asserts. | ||
| # | ||
| # What keeps them apart now is the path: mk/config.mk points ELFUSE_BIN at | ||
| # $(ELFUSE_LOOPBACK_BIN) when the fixture is asked for, so the two flavors never | ||
| # write the same file and the shipped one cannot be a stale copy of the other. | ||
| # That is one variable, in a file nothing stops a later change from | ||
| # re-simplifying, which is what this check is for. It asks make itself rather | ||
| # than reading the makefile, so a change that moves the decision elsewhere is | ||
| # still covered as long as the answer stays right. | ||
| # | ||
| # Cheap on purpose: two variable expansions, no compilation. The whole-tree | ||
| # reproduction above is what it stands in for. | ||
|
|
||
| set -e -u -o pipefail | ||
|
|
||
| MAKE_BIN="${MAKE:-make}" | ||
| ROOT="$(cd "$(dirname "$0")/.." && pwd)" | ||
|
|
||
| plain="$("$MAKE_BIN" -C "$ROOT" -s --no-print-directory print-elfuse-bin)" | ||
| fixture="$("$MAKE_BIN" -C "$ROOT" -s --no-print-directory \ | ||
| USB_LOOPBACK_FIXTURE=1 print-elfuse-bin)" | ||
|
|
||
| if [ -z "$plain" ] || [ -z "$fixture" ]; then | ||
| echo "check-usb-fixture-bin: print-elfuse-bin produced nothing" >&2 | ||
| exit 2 | ||
| fi | ||
|
|
||
| if [ "$plain" = "$fixture" ]; then | ||
| echo "Error: USB_LOOPBACK_FIXTURE=1 links to $fixture, the same path a" >&2 | ||
| echo " plain build writes, so a fixture build leaves the shipped" >&2 | ||
| echo " binary carrying the loopback model until a make clean." >&2 | ||
| echo " Point ELFUSE_BIN at \$(ELFUSE_LOOPBACK_BIN) for that flavor" >&2 | ||
| echo " (mk/config.mk), or make the choice invalidate the binary." >&2 | ||
| exit 1 | ||
| fi |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,11 +33,11 @@ linker resolved against an external sysroot via `--sysroot`. | |
| - Synthetic `/proc` and selected `/dev` emulation for user-space probes | ||
| - USB device passthrough: `/dev/bus/usb` and `/sys/bus/usb/devices` are | ||
| built from the IOKit registry, and opening a device node yields a | ||
| usbdevfs fd whose synchronous ioctls (interface claim, control and bulk | ||
| transfers) drive the attached device through IOKit. Asynchronous URB | ||
| submission is not implemented; a udev-backed `lsusb` also needs | ||
| `name_to_handle_at`, and macOS publishes no root hubs, so there are no | ||
| `usbN` entries and `lsusb -t` lists devices without their bus rows | ||
| usbdevfs fd whose ioctls -- interface claim, control and bulk transfers, | ||
| and asynchronous URBs -- drive the attached device through IOKit. A | ||
| udev-backed `lsusb` also needs `name_to_handle_at`, and macOS publishes | ||
| no root hubs, so there are no `usbN` entries and `lsusb -t` lists devices | ||
| without their bus rows | ||
| - Guest-internal FUSE: `/dev/fuse` and `mount("fuse")` work without | ||
| macFUSE / FUSE-T / FSKit | ||
| - Built-in GDB Remote Serial Protocol stub usable from `gdb` or `lldb` | ||
|
|
@@ -223,6 +223,13 @@ do. | |
| mask); the host scheduler picks the actual CPU. | ||
| - `/proc`, `/dev`, and mount data are synthetic compatibility views, | ||
| not host pass-throughs. | ||
| - USB interfaces bound to an Apple class driver (CDC serial, HID, FTDI) | ||
| cannot be claimed; `CLAIMINTERFACE` reports `EBUSY`, and root-mode | ||
| device capture is not implemented. CDC serial devices are reachable by | ||
| opening the host's `/dev/cu.*` node instead. | ||
| - USB mass storage will never be claimable, even with capture; macOS | ||
| does not release it. | ||
| - Isochronous URBs are unimplemented; submitting one reports `EINVAL`. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it feasible to implement isochronous URB?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Feasible, and I did not find a structural blocker. It is bounded work rather than a redesign. Today's The IOKit side is Worth saying, since you asked before this existed: the async URB engine in this PR changes the calculus. I am not committing to it in this PR. If you want it scoped as a follow-up, say so and I will size it properly. |
||
| - `uname` and `/proc/version` report Linux 6.18 LTS, a floor for | ||
| version-gated userspace; `src/syscall/dispatch.tbl` states what is | ||
| implemented. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BUILD_FLAVORis$(strip $(CFLAGS))(mk/common.mk) and the fixture switch changesSRCS, notCFLAGS, so flipping it wipes nothing. Run the command mk/config.mk documents,make USB_LOOPBACK_FIXTURE=1, and the model is linked intobuild/elfuse; a later plainmakefindsbuild/elfusenewer than every object in the rebuiltOBJSand relinks nothing, so the default binary keeps the model until someone runsmake clean. Themake checkpath is safe becauseelfuse-loopbackoverridesELFUSE_BIN, which is what thenmevidence measured. Either fold the fixture selection into the flavor stamp so the tree wipes on a flip, or make the documented manual command target$(ELFUSE_LOOPBACK_BIN)too.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Confirmed.
BUILD_FLAVORnever moves when the flavor flips, so nothing invalidated the tree and a plainmakeaftermake USB_LOOPBACK_FIXTURE=1handed back abuild/elfusestill linked against the model.I took the second option you offered rather than folding the switch into the flavor stamp:
mk/config.mknow pointsELFUSE_BINat$(ELFUSE_LOOPBACK_BIN)whenUSB_LOOPBACK_FIXTURE=1, so the two builds write different paths and neither can be a stale copy of the other..ci/check-usb-fixture-bin.shasksmake print-elfuse-binunder both flavors and fails if they ever collapse back to one path.Validation: the four-command sequence you gave (
make clean; make elfuse; make USB_LOOPBACK_FIXTURE=1 elfuse; make elfuse) now leavesbuild/elfuseat 815984 bytes with no_usbdev_fixture_lockbesidebuild/elfuse-loopbackat 834304 with it. Before the change the same sequence left the model inbuild/elfuseuntilmake clean.