Skip to content

AirportItlwm: report Link Quality via Skywalk setLQM to fix iServices on macOS 14.4+#1056

Open
DexterSLamb wants to merge 1 commit into
OpenIntelWireless:masterfrom
DexterSLamb:fix-iservices-sonoma14.4
Open

AirportItlwm: report Link Quality via Skywalk setLQM to fix iServices on macOS 14.4+#1056
DexterSLamb wants to merge 1 commit into
OpenIntelWireless:masterfrom
DexterSLamb:fix-iservices-sonoma14.4

Conversation

@DexterSLamb
Copy link
Copy Markdown

@DexterSLamb DexterSLamb commented Apr 25, 2026

Summary

On macOS Sonoma 14.4 and later, AirportItlwm V2 (Skywalk) leaves
State:/Network/Interface/<if>/LinkQuality at the default "no signal"
value, because the setLinkQualityMetric(100) call from V1 was commented
out (the API was renamed when IO80211SkywalkInterface replaced
IO80211Interface) but never ported to the new
IO80211InfraInterface::setLQM(uint64). As a result, the entire iServices
stack (iMessage / FaceTime / AirDrop / Continuity) refuses to use Wi-Fi:
+[PCInterfaceUsabilityMonitor isBadLinkQuality:] (literal threshold
lq < 11) marks the interface unusable, and apsd._connectStreamWithInterfacePreference:
rejects every interface in the APNS path.

This PR ports link-quality reporting to the new path.

What changed

AirportItlwm/AirportItlwmV2.cpp and .hpp:

  • New helper updateLQMIfChanged() that maps the current ni_rssi to one
    of three tiers (100 / 50 / 25) and calls
    IO80211InfraInterface::setLQM(uint64) (resolved via virtual dispatch
    on IO80211SkywalkInterface*) only when the tier changes. The lowest
    tier (25) deliberately stays above the iServices threshold of 11 so
    that weak-but-recoverable links don't break iMessage on Hackintosh
    systems without cellular fallback.
  • Hook into the existing 1 Hz watchdogAction so that signal degradation
    during a session is reflected.
  • Call from the setLinkStateGated link-up branch so the value
    propagates immediately on association rather than waiting up to 1 s
    for the watchdog tick.
  • Reset the cached value to 0 on link-down so the next link-up always
    re-reports, even if the freshly-computed value happens to match the
    cache.

Defensive checks

  • Initialize fLastReportedLQM = 0 in init()
    OSDeclareDefaultStructors only zero-initializes OSObject base
    members, leaving derived ivars with uninitialized memory; the first
    cache-compare could spuriously match one of {0, 25, 50, 100} and
    skip the initial setLQM call.
  • Early-return when not associated (ic_state != IEEE80211_S_RUN) so
    we don't write a bogus "good" LQ to SCDynamicStore before the link is
    actually up.
  • Snapshot ic_bss to a local — the ieee80211 layer can clear it from
    another workloop between the null check and the ni_rssi deref.
  • Null-check fHalServicereleaseAll() releases it before
    cancelling the watchdog timer, so a tick already in flight on
    fWatchdogWorkLoop could otherwise observe a NULL fHalService and
    crash on get80211Controller(). Reordering releaseAll() is out of
    scope for this PR; the cheap defensive check prevents this code path
    from making the existing race observable.

ABI / compatibility

IO80211SkywalkInterface.h in this repository already declares setLQM
unconditionally (line 108 on master), and IO80211InfraInterface
provides the working override in IO80211Family.kext. No new external
symbol is introduced — the binary's undefined-symbol set against
__ZN21IO80211InfraInterface6setLQMEy is unchanged from existing
2.3.0/2.4.0 builds. So this is safe to ship for all macOS targets the
project currently supports; on macOS versions where IO80211Family
provides only the empty IO80211SkywalkInterface::setLQM stub at that
vtable slot, the call is a no-op rather than a crash.

Verification (Intel AX201, macOS 14.8.5)

Before:

  • scutil show State:/Network/Interface/en0/LinkQuality-2
  • apsd log: Push is connected? NO networkIsHistoricallyUsable? YES isBadLQ? YES
  • iMessage / FaceTime fail to register

After this patch:

  • scutil show State:/Network/Interface/en0/LinkQuality100
  • apsd log: Push is connected? NO networkIsHistoricallyUsable? YES isBadLQ? NO
  • apsd log: courier <private>: Sending outgoing message N onInterface: NonCellular. Connected on 1 interfaces.
  • iMessage / FaceTime / AirDrop work after a single reboot.

Test plan

  • Builds against MacKernelSDK on macos-latest runner for all eight
    macOS targets (Big Sur through Sonoma 14.4) via the existing CI.
  • Verified on real hardware: HP EliteBook x360 1030 G3 (Intel AX201),
    Sonoma 14.8.5, OpenCore boot.
  • iServices recovery confirmed via APNS courier log + iMessage
    send/receive after reboot.
  • Reviewer to verify on additional Intel chipset (iwn / iwm Gen 1)
    to confirm ni_rssi units are normalized identically across HALs.

The V2 (Skywalk) AirportItlwm path commented out the V1 setLinkQualityMetric(100)
call because the API was renamed in IO80211SkywalkInterface, but never ported
to the replacement setLQM(uint64). Without it, SCDynamicStore key
State:/Network/Interface/<if>/LinkQuality stays at the default "no signal"
value, +[PCInterfaceUsabilityMonitor isBadLinkQuality:] (literal threshold
lq < 11) marks the WiFi interface as unusable, and apsd refuses every
interface in _connectStreamWithInterfacePreference: — breaking the entire
iServices stack (iMessage / FaceTime / AirDrop / Continuity).

This change ports link-quality reporting to the new path:

 * Add updateLQMIfChanged() that maps current ni_rssi to one of three tiers
   (100 / 50 / 25) and calls IO80211InfraInterface::setLQM(uint64) only
   when the value changes. The lowest tier (25) stays above the iServices
   threshold of 11 so weak-but-recoverable links don't break iMessage on
   Hackintosh systems without cellular fallback.
 * Hook into the existing 1 Hz watchdogAction so signal degradation during
   a session is reflected.
 * Call from setLinkStateGated link-up branch so the value propagates
   immediately on association rather than waiting up to 1 s for the
   watchdog.
 * Reset the cached value to 0 on link-down so the next link-up always
   re-reports, even if the freshly-computed value matches the cache.

Defensive checks:
 * Initialize fLastReportedLQM in init() — OSDeclareDefaultStructors only
   zero-initializes OSObject base members, leaving derived ivars with
   uninitialized memory whose first cache-compare could spuriously match
   one of {0, 25, 50, 100} and skip the initial setLQM call.
 * Early-return when not associated (ic_state != IEEE80211_S_RUN) so we
   don't write a bogus "good" LQ to SCDynamicStore before the link is up.
 * Snapshot ic_bss to a local — the ieee80211 layer can clear it from
   another workloop between the null check and the ni_rssi deref.
 * Null-check fHalService — releaseAll() releases it before cancelling
   watchdogTimer, so a tick already in flight on fWatchdogWorkLoop could
   otherwise observe a NULL fHalService and crash on get80211Controller().
   Reordering releaseAll() is out of scope for this PR; the cheap
   defensive check prevents this path from making the existing race
   observable.

Verified on macOS 14.8.5 / Intel AX201:
 * scutil 'show State:/Network/Interface/en0/LinkQuality' goes from -2 to 100.
 * apsd log: "Push is connected? NO networkIsHistoricallyUsable? YES isBadLQ? NO"
   (was "isBadLQ? YES").
 * apsd log: "courier <private>: Sending outgoing message N onInterface:
   NonCellular. Connected on 1 interfaces." — APNS courier connects.
 * iMessage / FaceTime / AirDrop work after reboot.

The existing IO80211SkywalkInterface.h header in the project already declares
setLQM unconditionally, and IO80211InfraInterface (the actual class behind
the AirportItlwmSkywalkInterface vtable) provides the working override in
IO80211Family. No new external symbol is introduced — the binary's
undefined-symbol set against IO80211InfraInterface::setLQM is unchanged from
the existing 2.3.0/2.4.0 builds.
@jzrodriguez98
Copy link
Copy Markdown

jzrodriguez98 commented Apr 26, 2026

@DexterSLamb This sounds promising. Would this work with Sequoia and Tahoe if successfully tested and merged with the main branch?

@DexterSLamb
Copy link
Copy Markdown
Author

@DexterSLamb This sounds promising. Would this work with Sequoia and Tahoe if successfully tested and merged with the main branch?

I only tested on Sonoma 14.8.5 (Intel AX201).

The fix targets IO80211InfraInterface::setLQM(uint64), a Skywalk API
introduced in 14.4 and inherited unchanged into Sequoia and Tahoe AFAIK. The
OS-side threshold check (lq < 11 in +[PCInterfaceUsabilityMonitor isBadLinkQuality:]) is also stable across these versions. So in principle it
should work on 15.x / 26.x with no code change — but I have no first-hand
confirmation.

If anyone running Sequoia or Tahoe can build from this branch and report back,
that would confirm it. Two checks:

  1. scutilshow State:/Network/Interface/en0/LinkQuality should show
    LinkQuality : 100 (or 50 / 25 on weak signal).
  2. sudo log show --last 60s --predicate 'process == "apsd"' --style compact
    should show isBadLQ? NO and Connected on N interfaces.

If both pass, iServices (iMessage / FaceTime / Continuity / iCloud Drive push)
should come back.

@newhacker1746
Copy link
Copy Markdown

newhacker1746 commented Apr 27, 2026

Hi, I have AX200 on an AMD 7730U platform (Zenbook UM3402Y) on Sequoia 15.7.1 and full Xcode locally. I'm building the Sonoma144 target right now from this branch and will report back

I had a local tahoe as well, but I installed the 26.4 beta and it bricked boot, so I might need to fix that first

@newhacker1746
Copy link
Copy Markdown

newhacker1746 commented Apr 27, 2026

Both the built from actions and my own compile of the Sonoma144 variant produce failures, before the kext is even loaded:

00:000 00:000 OC: Prelinked injection AirportItlwm-Sonoma144.kext (AirportItlwm-Sonoma144.kext) - Invalid Parameter

It seems that the symbols in the kernel collection for Sequoia have changed sufficiently as to prevent loading? It's the only kext that produces this issue. I don't have a Sonoma partition to attempt to distinguish if it's my configuration that's an issue or not, but I doubt that the kext injection configuration I'm using is causing issues. Here's the snippet:

			<dict>
				<key>Arch</key>
				<string>Any</string>
				<key>BundlePath</key>
				<string>AirportItlwm-Sonoma144.kext</string>
				<key>Comment</key>
				<string>AirportItlwm-Sonoma144.kext</string>
				<key>Enabled</key>
				<true/>
				<key>ExecutablePath</key>
				<string>Contents/MacOS/AirportItlwm</string>
				<key>MaxKernel</key>
				<string></string>
				<key>MinKernel</key>
				<string>23.4.0</string>
				<key>PlistPath</key>
				<string>Contents/Info.plist</string>
			</dict>

FYI:

% uname -a
Darwin usb3eth.lan.local.cmu.edu 24.6.0 Darwin Kernel Version 24.6.0: Mon Aug 11 21:16:05 PDT 2025; root:xnu-11417.140.69.701.11~1/RELEASE_X86_64 x86_64
oled@usb3eth ocvalidate % ./ocvalidate /Volumes/efi/EFI/OC/config.plist 

NOTE: This version of ocvalidate is only compatible with OpenCore version 1.0.5!


Completed validating /Volumes/efi/EFI/OC/config.plist in 7 ms. No issues found.

^ ocvalidate would diagnose kext loading issues (parent/children relationships not in order), and I didn't think there were any here

@newhacker1746
Copy link
Copy Markdown

newhacker1746 commented Apr 27, 2026

Changing AppleSecureBoot to Default (was disabled) doesn't do anything either. Sometimes this was recommended to replace the OC kernelcollection generation with Apple's, and also attempted forcing IO80211Family to load which used to be required. neither did anything

For a while, one had to use OCLP on Sequoia to downgrade the 80211 stack to load AirportItlwm at all, and then it would be from Ventura (https://github.com/5T33Z0/OCLP4Hackintosh/blob/main/Enable_Features/AirportItllwm_Sequoia.md)

Which of course would bypass the issue entirely since the wifi stack is just being downgraded.

I can also try to kill AMFI and SIP enough to load the kext at runtime with kmutil but this is a daily use laptop so I fear touching it that much

--

So

The fix targets IO80211InfraInterface::setLQM(uint64), a Skywalk API
introduced in 14.4 and inherited unchanged into Sequoia and Tahoe AFAIK. The
OS-side threshold check (lq < 11 in +[PCInterfaceUsabilityMonitor isBadLinkQuality:]) is also stable across these versions. So in principle it
should work on 15.x / 26.x with no code change

Presumably this is true for the fix, but not necessarily the rest of the code stack--surely it wouldn't work on Sequoia without other updates/function patches? That would have to be achieved first

Hmm, but checking for symbol resolution in userspace doesn't show any issues:

oled@usb3eth Documents % kmutil libraries -p AirportItlwm-Sonoma144.kext

<no symbols fail resolution; output of this command is attached)

kmutil.txt -- output

So is this an OpenCore issue? I can't test injecting on known-working Sonoma, because I don't have that install available...

@DexterSLamb
Copy link
Copy Markdown
Author

That kmutil libraries output is super useful, thanks for grabbing it. It rules out the simple missing-symbol case I was first suspecting, and shifts the
suspicion to the dependency version check that OC performs at prelinked injection time, which kmutil libraries -p doesn't enforce as strictly.

Our Info.plist for the Sonoma144 target declares these OSBundleLibraries:

com.apple.iokit.IO80211Family   = 1.5.0                                                                                                                
com.apple.iokit.IOSkywalkFamily = 1.0                         
com.apple.iokit.IOPCIFamily     = 2.9                                                                                                                  
com.apple.iokit.IONetworkingFamily = 3.2                                                                                                               

If Apple bumped the OSBundleCompatibleVersion of IO80211Family (or its successor IO80211FamilyV2) or IOSkywalkFamily on Sequoia past those numbers, OC's
KC injection will reject the kext with exactly that "Invalid Parameter" symptom while kmutil userspace checks still pass. That's by far the most likely
cause given everything you've shown.

Two things that would help confirm:

  1. The OSBundleCompatibleVersion lines from Sequoia's:
    /System/Library/Extensions/IO80211FamilyV2.kext/Contents/Info.plist
    /System/Library/Extensions/IOSkywalkFamily.kext/Contents/Info.plist
    (just plutil -p those and grep for OSBundleCompatibleVersion / CFBundleVersion)

  2. Anything in the OC log right before the Invalid Parameter line, especially any "OCAK" prefixed messages.

You're right that the setLQM patch is one piece, and the rest of the V2 stack absolutely needs to be checked for runtime ABI breakage on 15.x. But right
now we're failing before load, not at runtime, so the immediate blocker is this prelinked-injection check rather than vtable/offset drift.

Re OCLP: I'd like to avoid that route on principle, the goal here is to make AirportItlwm itself work on the new OS, not to downgrade the OS to fit
AirportItlwm. And I agree, no need to disable AMFI/SIP on a daily driver, the OSBundleLibraries hypothesis can be tested cheaply.

I'm setting up Sequoia 15.7.5 locally so I can do the binary/Info.plist diff myself rather than ping-ponging through your machine. Will report back once
that's up.

@newhacker1746
Copy link
Copy Markdown

Lines from Sequoia:

oled@usb3eth Documents % plutil -p /System/Library/Extensions/IO80211Family.kext/Contents/Info.plist | grep -i bundleversion
  "CFBundleVersion" => "1200.13.1"

(notice that there's no IO80211FamilyV2.. ?)

oled@usb3eth Documents % plutil -p /System/Library/Extensions/IOSkywalkFamily.kext/Contents/Info.plist| grep -i bundlevers
  "CFBundleVersion" => "1.0"

I couldn't figure out how to get OC to log more than that single line... probably has to do with the Target/DisplayLevel... DisplayLevel I changed but only produced that one line, which I know is incorrect, and I should probably do the bitmask math manually to enable specific options that I want rather than just using the one from the dortnaia guide)

What's your progress setting up 15.7.5 Sequoia on your machine? It's within the ballpark of mine at 15.7.1 anyway, so I really doubt updating it would do anything. certianly by now the API/ABIs are stable for Sequoia drivers

@jzrodriguez98
Copy link
Copy Markdown

@DexterSLamb have you looked at this repo which has reversed engineered Apple WiFi services?

https://github.com/willh34/apple-unofficial-ecosystem

@DexterSLamb
Copy link
Copy Markdown
Author

Quick update. Did some symbol diffing today between Sonoma 14.8.5 and Sequoia 15.7.5 IO80211Family. The "massive API rewrite" framing turns out to be
overstated, of the 271 IO80211/Skywalk symbols our kext imports, only 23 are actually missing in Sequoia, and 4 of those are just signature tweaks
(extra/missing bool, etc). So the real work looks more like "fix 23 call sites + add a Sequoia15 build target" than a months-long rewrite.

Going to take a real shot at this over the May 1 long weekend. Plan: add the Sequoia15 target, patch the 4 confirmed signature changes, push to fork,
then bring up a Sequoia install on an external SSD on my own AX201 box for iteration. Should get an Invalid-Parameter-free build out before tackling the
remaining 19.

@jzrodriguez98 thanks for the apple-unofficial-ecosystem pointer, looked at it but it's userspace stuff, not relevant here. Appreciated anyway.

Wish me luck.

@newhacker1746
Copy link
Copy Markdown

@DexterSLamb Sounds good, I might also take a crack at the fix or rather try to document some more of the call sites. Could you possibly provide the symbol diff from 14.8.5 and 15.7.5 and possible 14.8.5 IO80211Family

@DexterSLamb
Copy link
Copy Markdown
Author

Yes happy to. Easiest is I push the raw lists and methodology notes into a research/sequoia-port/ directory on the fork so you can pull them, will do
that next.

The headline files:

  • our-kext-IO80211-needs.txt — the 271 IO80211/Skywalk symbols our AirportItlwm-Sonoma14.4 binary undefined-imports (output of nm -u on the kext,
    filtered)
  • sonoma-missing-baseline.txt — 12 of those 271 that are also missing in Sonoma 14.8.5 BootKernelExtensions.kc. These are NOT real misses, they live in
    SystemKernelExtensions.kc on a running 14.8.5 box. Sanity baseline.
  • sequoia-missing-all.txt — 35 of those 271 missing in Sequoia 15.7.5 BootKernelExtensions.kc.
  • real-delta.txt — 35 minus 12 = 23 truly Sequoia-only-missing.

The 4 confirmed signature renames I found by fuzzy-matching same-name same-class methods:

IO80211Controller::postMessage(uint, void*, ulong, uint, void*)                                                                                        
  -> postMessage(IO80211SkywalkInterface*, uint, void*, ulong, bool)                                                                                   
                                                                                                                                                       
IO80211InfraInterface::inputPacket(IO80211NetworkPacket*, packet_info_tag*, ether_header*, bool)                                                       
  -> inputPacket(IO80211NetworkPacket*, packet_info_tag*, ether_header*, bool, bool) 
                                                                                                                                                       
IO80211InfraInterface::setLinkStateInternal(IO80211LinkState, uint, bool, uint, apple80211_link_changed_event_data&)                                   
  -> setLinkStateInternal(IO80211LinkState, uint, bool, uint)                                                                                          
                                                                                                                                                       
IO80211InfraInterface::logTxCompletionPacket(IO80211NetworkPacket*, PacketSkywalkScratch*, uchar, apple80211_wme_ac, int, bool)                        
  -> logTxCompletionPacket(IO80211NetworkPacket*, PacketSkywalkScratch*, uchar, apple80211_wme_ac, int, bool, bool)                                    

Reproducing on your end (you have the better data point, a Sequoia install with full SystemKernelExtensions.kc):

kmutil emit-macho -a x86_64 -M -B /System/Library/KernelCollections/BootKernelExtensions.kc                                                            
kmutil emit-macho -a x86_64 -M -S /System/Library/KernelCollections/SystemKernelExtensions.kc                                                          
# output ends up under /tmp/KMUtilProducts/                                                                                                            
nm /tmp/KMUtilProducts/BootKernelCollection.kc /tmp/KMUtilProducts/SystemKernelCollection.kc \                                                         
  | awk '$2 != "U" && $2 != "" {print $NF}' | sort -u > sequoia-defined.txt          
nm -u AirportItlwm.kext/Contents/MacOS/AirportItlwm | grep -E "IO80211|Skywalk" | sort -u > our-needs.txt                                              
comm -23 our-needs.txt sequoia-defined.txt   # truly missing in Sequoia, full picture                                                                  

That last comm is the one I really want — it'll cut the 19 unknowns down to whatever is actually deleted vs just relocated to System KC. If you do that
diff against your 15.7.1 SystemKernelExtensions.kc and post the result, that saves me the most time. If not no worries, I'll get there once I have my own
Sequoia install up.

Pushing the data to fork shortly.

@newhacker1746
Copy link
Copy Markdown

I can get some stuff in a bit... I saw you've been committing to your repo, last like 15 minutes even?
DexterSLamb@500e87c

The fuzzy matching seems good. What has been your progress on those commits you've been doing overall?

@DexterSLamb
Copy link
Copy Markdown
Author

Hey, thanks for following along! Yeah, I've been pushing a lot — spent the last few days deep in this. Honest summary: real progress on the discovery/visibility side, but not yet at "WiFi actually connects". Let me share what I've nailed down so the next person doesn't have to re-discover it.
What works on Sequoia 15.7.5 (Intel AX201, MacBookAir9,1 SMBIOS):

Driver loads cleanly, no boot panic
BSD ifnet en99 created via private KPI ifnet_allocate_extended with IFNET_SUBFAMILY_WIFI=3 and type=IFT_ETHER(6) — passes _getIfListCopy's acceptance check (RE'd from IO80211.framework)
A stub IOService child published with IOInterfaceName=en99, IO80211InterfaceRole=Infrastructure, IOUserClientClass=IO80211APIUserClient — passes _isInfraInterface filter (RE'd: it's IOPropertyMatch lookup + role string compare)
Apple80211GetIfListCopy returns ifCount[1] instead of -3903
wdutil info reports en99 as Wi-Fi, Power=On (faked via APPLE80211_IOC_POWER GET handler)
All apple80211 GET ioctls reach our bsd_wlan_ioctl (kernel routes SIOCGA80211/SIOCSA80211 through ifnet ioctl) — currently returning permissive zero-buffer success for all req_types
airportd treats en99 as a real Wi-Fi interface, polls CARD_CAPABILITIES/STATE/CHANNELS/SSID/CURRENT_NETWORK/POWER constantly

Wall I hit (the actual scan/associate path):
dmesg confirmed 0 SET ioctls to en99. airportd's control plane bypasses BSD ioctl in Sequoia — it goes:
airportd → IOServiceOpen(en99-stub-IOService) → Apple80211UserClient → driver
Three locked-down gates:

Sandbox MACF (mac_iokit_check_open_service in xnu): airportd's entitlement com.apple.security.temporary-exception.iokit-user-client-class is whitelisted to only IOUserUserClient and IO80211APIUserClient. Custom UserClient class names get kIOReturnNotPermitted (0xe00002e2). Can't bypass without AMFI patch.
IO80211APIUserClient::commonStart (KDK 15.7.4 IO80211Family.kext reverse engineered, vmaddr 0x1b5f50):

provider OSDynamicCast IO80211SkywalkInterface // Cast 1
provider->GetProvider() OSDynamicCast IO80211Controller // Cast 2
controller->vtable0xc78 != NULL // = getWorkQueue() returning _fWorkloop
My bare IOService stub fails Cast 1. OSTypeAlloc(IO80211SkywalkInterface) returns NULL (abstract). new AirportItlwmSkywalkInterface (our existing IO80211SkywalkInterface subclass via IO80211InfraProtocol → IO80211InfraInterface → IO80211SkywalkInterface) for a second instance broke driver start() — looks like singleton/global state in the instance member.

vtable alignment: re-enabling fNetIf->attach(this) (the H1-H4 era hack — was originally skipped to avoid a panic in framework dispatch) on Sequoia 15.7.5 currently causes super::start (IO80211Controller::start) to silently return false, before any of our Plan A code runs. I have a tracing build in flight to figure out which vtable slot the framework is calling that's wrong.

Notable RE finds others might want:

Sequoia 15.7.5 actual SIOCGA80211 cmd is 0xc02869c9 (size=40, modern 64-bit struct). The apple80211_ioctl.h header in this fork has the value baked from old 32-bit struct (size=48 → 0xc03069c9) — so cmd == SIOCGA80211 comparison silently never matches. Use the literal.
Apple80211BindToInterfaceWithIOCTL only ever sends two ioctls: SIOCGIFFLAGS (kernel handles directly) and SIOCGA80211 type=12 CARD_CAPABILITIES len=19. So passing IOCTL fallback gets you "bound" but nothing else flows through ioctl.

Where I'm going next:

Drilling into why super::start fails on the re-enabled-attach build (TRACE_STEP gives a postmortem via ioreg -k airportitlwm_trace — already proved that's the failure point)
KDK 15.7.4 IO80211Family vtable comparison for any slot we might have moved
Once that's clear, the path is: fNetIf→attach OK → publish properties on fNetIf so it's the Apple80211FindService target → IO80211APIUserClient instantiates with fNetIf as provider → commonStart 3 checks all pass → externalMethod selectors get RE'd one by one for scan/associate

Will keep pushing. If anyone has the IO80211Controller::start RE for 15.7.5 already done, that'd save me a lot of cycles.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants