- Link quality goes to macOS. The interface now calls
setLQM(slot 378, which ends inIOSkywalkNetworkInterface::reportLinkQuality) once a second while associated: 100 at -75 dBm or better, 50 down to -85 dBm, 20 below that, and -1 (unknown) when the link drops. Before,State:/Network/Interface/en1/LinkQualitywas never set, apsd loggedisBadLQ? YESandPush is connected? NO, so Apple push, and with it iMessage, FaceTime and Handoff, did not connect over Wi-Fi. Lead from the 2026-10-31 research run (an itlwm fork calls it the same way); checked live on the Legion before the change. - Scan results carry each network's real width (#1). The chanspec in each scan-result event is built from the HT and VHT Operation elements, in the Broadcom d11ac layout that
ChanSpecGetPrimaryChannelandChanSpecConvToApple80211Channeldecode on 25G332 (center channel, control sideband, 0x1800 for 40 MHz, 0x2000 for 80 MHz). 160 MHz is reported as 80, the width the core joins at. Host test intests/chanspec_test.cchecks every case against Apple's decoder math. - The country code is the associated AP's Country element (802.11d) until macOS sets one, instead of XZ. Report only: the core's regulatory domain does not change.
- The extended BSS info has the AP's HT RX MCS set (two streams) and the VHT MCS map both sides support, instead of "none".
build.shskips the kernel-collection link check withNO_LINKCHECK=1.- Booted on 26.7.2 (25G332) on the Legion 5 with MtkWlan 0.12.1.
LinkQuality : 100appears for en1, apsd logsisBadLQ? NOand received a push over Wi-Fi,wdutil infoshows Country Code US and 5g108/80, and a CoreWLAN scan reports 8 of 8 networks at 5 GHz/80 MHz.
- macOS 26.7.2 (25G332) is allow-listed (#4). The kcabi dump of 25G332's boot kernel collection, taken from Apple's OTA, has the same instance sizes, vtables and 200 request slots as 25G241, and
genhdr.pymakes headers that differ only in the build name (abi/25G332/). Every undefined symbol of the kext is exported by the 25G332 collection. Of the functions Apple changed, onlykern_netif_queue_rx_enqueue(a field moved from +0x4d8 to +0x4e8) touches the receive path, and the kext never calls it directly. Not yet booted on 25G332. - System Information showed "Firmware Version: MtkWlanNative 0.4.11" on 0.4.12 and 0.4.13:
MTK_NATIVE_VERSIONwas not bumped. It reads 0.4.13 now, andbuild.shstops when it and Info.plist differ (seen in the report on #3). tools/mtk-report.shalso replaces MACs printed without leading zeros (netstat's route table showed the router's), IPv6 addresses and the.localhost name.- README: WPA2-PSK from the Wi-Fi menu confirmed on air by oliverchu (#3); notes on OpenCore keeping an old
boot-argsand on the leftover "Ethernet 2" service.
- The Wi-Fi details in macOS are real now (#1). With MtkWlan 0.12.1,
wdutil infoon the author's Legion 5 shows PHY Mode 11ac, Channel 5g100/80, MCS Index 9, NSS 2, Guard Interval 400 and Tx Rate 866 Mbps. 0.4.11 showed 20 MHz and a fixed 54 Mbps.getMCS(slot 479),getMCS_VHT(482) andgetGUARD_INTERVAL(478) are answered, and requests 0x37, 0x39 and 0xc3 are no longer refused. The layouts were read from AppleBCMWLANCore on 25G241: getMCS_VHT has the MCS at +4, streams at +8, width in MHz at +0xc and the guard interval in ns at +0x10.- The current channel carries its real width and DFS flag, the same way Apple's
ChanSpecConvToApple80211Channelwrites them: 0x4 for 40 MHz (+0x200 when the extension is above), 0x400 for 80 MHz, 0x100 for channels 52 to 144. getRATEreports the core's rate instead of the fixed link speed.- f0xeri's qwz-macos 0.0.26 showed which requests Tahoe makes before it shows these fields.
setCOUNTRY_CODEgoes to the core (MtkWlan 0.12.1set_country) instead of only being recorded. On N-261 airportd never set a country, so this has not run yet.- A private Wi-Fi address the core refuses is tried again every 2 s, up to 6 times. Before, one refusal (for example during a join) left the firmware on the old address, and a network could look dead until Private Wi-Fi Address was turned off. Reported on an HP OMEN in Game-5040/hackintosh-hp-8f06-macos26.
- Still needs MtkWlan 0.11.x or later. With a core older than 0.12.1 the rate fields fall back to the old answers.
-
Pairs with MtkWlan 0.12.0. When the core's link supervisor resets the chip and reloads the firmware, the link goes down and comes back through the existing "link restored by core" path, so the Wi-Fi menu shows a short drop and rejoins.
-
Works in macOS Recovery on 26.7.1 (25G241): Recovery's boot kernel collection carries the same IO80211Family 1200.13.1, IOSkywalkFamily and corecapture, so the ABI guard engages there too (checked from the Recovery volume, a boot test is next).
-
Up to 128 networks go to the Wi-Fi menu instead of 48, to match the core's larger BSS cache (MtkWlan branch scan-cache-roc). With 48, weaker 2.4 GHz networks could still be left out in a crowded place. Idea from thanhnndev's ga403wm-hackintosh 4257353.
- Tx queues restart on the next 2 ms tick after the core frees a slot. They used to wait for the 10 ms control poll, which capped upload near 190 Mbit/s. Frames refused while the link was down are asked for again when it comes up.
- Tx completion moves the pending list once per tick instead of once per packet.
- Measured on the author's laptop with MtkWlan 0.11.3: about 410 Mbit/s of local UDP on VHT 80 MHz 2x2, gateway ping 3-4 ms (5 ms before).
- Claims the core at the end of
probe()(MTK_CORE_FE_CLAIM, MtkWlan 0.11.1), before Apple's interface start can outlast the core's 15 s fallback. Before this, a slowIO80211SkywalkInterfacestart (17.2 s on one boot) let the Ethernet front end win by 230 ms and the Wi-Fi menu stayed empty until the next reboot. Every placestart()gives up now declines, so the fallback still comes at once when the front end really cannot run. - Debug boot-arg
mtknativedelay=<ms>(at most 60000) holds the interface start back, to test the late path.
- Link quality update events (0x27, 0x1dc bytes) once a second while the link is up. The Family's assoc timer declares "missed beacons" when its beacon and traffic timestamps are both older than 60 s, and only this event refreshes them; the beacon counter of 0.4.7 feeds a different counter. Proven on the author's laptop: ten quiet minutes without a leave.
- Beacon-counter events are posted while the core holds the link, not only while its scan cache entry for the access point is fresh (the firmware keeps the associated AP's beacons to itself on some channels, and the Family raised BeaconLoss again).
- Beacon-counter events (0xaf, u32 count at +0x54) once a second while the link is up. Without them the Family raises the fault "missed beacons timeout" about 60 s after every join and leaves the network. Under test.
- The candidate BSSID is read at +0x21c (0.4.5 read the wrong field). Confirmed on the author's laptop: the join lands on the access point macOS chose.
setWCL_ASSOCIATEpasses the first candidate's BSSID to the core (apple80211AssocCandidates: count at +0x214, entries of 18 bytes from +0x21c, BSSID at +6). 0.4.4 joined the core's own favourite access point and the Family re-joined every 15 to 60 s. Under test.
- CoreCapture pipes and streams are started after the interface has bound the core. Starting them earlier took the native front end past the core's 15 s fallback and the Ethernet front end won the boot.
IOService::starton the CoreCapture data pipe, data stream and log pipe. The factories only alloc and init; a fault report completing on an unstarted data pipe panics inCCDataPipe::enqueueBlob.
- One version string (
MTK_NATIVE_VERSION), shown by the Family as "Firmware Version".
- ioctls 0x170
SET_MAC_ADDRESSand 0x22dDBRG_ENTROPYadmitted on the join path; a refused address answers NotPermitted.
- The Family drives the association:
WCL_ASSOCIATE,WCL_LEAVE_NETWORK,WCL_JOIN_ABORT, the events 0xd8 / 0x4e / 0xd3 / 0xd4 / 0xd5,WCL_BSS_INFO,WCL_EXTENDED_BSS_INFO(0x214 bytes on 25G241),WCL_LINK_STATE_UPDATE,WCL_LINK_UP_DONEand the link-path requests. The core's open-network fallback is off in native mode.
- The ioctl allow-list admits
WCL_SCAN_REQandWCL_SCAN_ABORT; every WCL request is gated byisCommandProhibitedfirst.
- Scan requests run the core's scan; one 0xc9 event per BSS in the 25G241 layout (IEs at +0x44), then 0xed.
- The interface follows the BSD link-layer address into the core (
set_mac, core ops v4): macOS gives the interface a private address per network and the firmware must answer to it.
- Controller and interface, Skywalk packet pool and queues, data path bridged to the core, ABI guard per macOS build.