feat(tahoe): port QualcommWireless & QualcommWifi to macOS Tahoe 26.x (Darwin 25)

Breakthroughs & Reverse Engineering (macOS Tahoe 26.7.1 / Darwin 25.6.0):
- Reconstructed the complete 463-slot Skywalk vtable and class layout (0x128 / 296 bytes) of IO80211Controller (__ZTV17IO80211Controller at 0xffffff8002461148) and AppleBCMWLANCore from BootKernelExtensions.kc (IO80211Family 1200.13.1, source 1566.5).
- Verified IOUSBHostDevice::deviceRequest vtable slot in Tahoe's BootKernelExtensions.kc (__ZTV15IOUSBHostDevice at 0xffffff8002e72720): confirmed exact match at slot 374 (0x176, byte offset 0xbb0).
- Disassembled Tahoe's /usr/sbin/bluetoothd (FindTransportType at 0x10014c700, Found_USB_Dongle at 0x1000e9559, GetProductAndVendorID at 0x1000edf2a) confirming USB transport matching on 'Bluetooth USB Host Controller' and CSR 0x0a12 descriptor spoofing.

Code & Build Modifications (v1.1.0):
- IO80211Controller.h: Add full 463-slot Tahoe Skywalk vtable declaration (slots 394..462, offsets 0xc50..0xe70) and exact 0x80 filler size when __IO80211_TARGET >= 260000 while preserving legacy compatibility.
- QualcommWifi.hpp/.cpp: Implement Tahoe IO80211Controller pure virtual methods (isCommandProhibited, handleCardSpecific, getDRIVER_VERSION, getHARDWARE_VERSION, getCARD_CAPABILITIES, getPOWER, setPOWER, getCOUNTRY_CODE, setCOUNTRY_CODE, setGET_DEBUG_INFO, getLogger, getFaultReporterFromDriver) and guard un-reserved IONetworkController slots 6..7 on SDK 26.5.
- QualcommWireless.cpp: Add non-null vtable slot sanity check prior to installing the shadow vtable hook on IOUSBHostDevice::deviceRequest.
- project.pbxproj & Info.plist: Upgrade to Xcode 26.6 (MacOSX26.5.sdk), MACOSX_DEPLOYMENT_TARGET = 26.0, __IO80211_TARGET = 260000, and bump version to 1.1.0.
- docs & README: Document macOS Tahoe (Darwin 25) architecture, bluetoothd offsets, and Skywalk IO80211Controller ABI.
This commit is contained in:
Erwan committed 2026-10-16 02:41:25 +02:00
1 parent 820154e54b
commit a10e097a7e
11 files changed
+262 -135

No files matched your search

+79 -4
View File
@@ -739,7 +739,7 @@ UInt32 QualcommWifi::outputPacket(mbuf_t m, void *param) {
return kIOReturnOutputDropped; return kIOReturnOutputDropped;
} }
SInt32 QualcommWifi::apple80211Request(unsigned int req_type, int req_val, IO80211Interface* iface, void* req_data) { SInt32 QualcommWifi::handleApple80211Request(unsigned int req_type, int req_val, void* req_data) {
switch (req_type) { switch (req_type) {
case APPLE80211_IOC_CARD_CAPABILITIES: { case APPLE80211_IOC_CARD_CAPABILITIES: {
apple80211_capability_data *cap = (apple80211_capability_data *)req_data; apple80211_capability_data *cap = (apple80211_capability_data *)req_data;
@@ -939,11 +939,12 @@ SInt32 QualcommWifi::apple80211Request(unsigned int req_type, int req_val, IO802
} }
break; break;
} }
case APPLE80211_IOC_DRIVER_VERSION: { case APPLE80211_IOC_DRIVER_VERSION:
case APPLE80211_IOC_HARDWARE_VERSION: {
apple80211_version_data *vd = (apple80211_version_data *)req_data; apple80211_version_data *vd = (apple80211_version_data *)req_data;
if (vd) { if (vd) {
vd->version = APPLE80211_VERSION; vd->version = APPLE80211_VERSION;
const char *verStr = "Qualcomm FastConnect 7800 Wi-Fi 7 (v1.0.2)"; const char *verStr = "Qualcomm FastConnect 7800 Wi-Fi 7 (v1.1.0)";
vd->string_len = (u_int16_t)strlen(verStr); vd->string_len = (u_int16_t)strlen(verStr);
strlcpy(vd->string, verStr, sizeof(vd->string)); strlcpy(vd->string, verStr, sizeof(vd->string));
return 0; return 0;
@@ -974,8 +975,80 @@ SInt32 QualcommWifi::apple80211Request(unsigned int req_type, int req_val, IO802
return 0; return 0;
} }
#if __IO80211_TARGET >= 260000
bool QualcommWifi::isCommandProhibited(int command) {
return false;
}
IOReturn QualcommWifi::handleCardSpecific(IO80211SkywalkInterface *iface, unsigned long req_type, void *req_data, bool isSet) {
return (IOReturn)handleApple80211Request((unsigned int)req_type, isSet ? 1 : 0, req_data);
}
UInt32 QualcommWifi::hardwareOutputQueueDepth(void) {
return 0;
}
SInt32 QualcommWifi::performCountryCodeOperation(IO80211CountryCodeOp op) {
IOLog("QualcommWifi: performCountryCodeOperation op=%d.\n", op);
return 0;
}
void QualcommWifi::dataLinkLayerAttachComplete(void) {
IOLog("QualcommWifi: dataLinkLayerAttachComplete (Skywalk Tahoe).\n");
}
SInt32 QualcommWifi::enableFeature(IO80211FeatureCode code, void *arg) {
IOLog("QualcommWifi: enableFeature code=%d.\n", code);
return 0;
}
IOReturn QualcommWifi::getDRIVER_VERSION(IO80211SkywalkInterface *iface, apple80211_version_data *vd) {
return (IOReturn)handleApple80211Request(APPLE80211_IOC_DRIVER_VERSION, 0, vd);
}
IOReturn QualcommWifi::getHARDWARE_VERSION(IO80211SkywalkInterface *iface, apple80211_version_data *vd) {
return (IOReturn)handleApple80211Request(APPLE80211_IOC_HARDWARE_VERSION, 0, vd);
}
IOReturn QualcommWifi::getCARD_CAPABILITIES(IO80211SkywalkInterface *iface, apple80211_capability_data *cap) {
return (IOReturn)handleApple80211Request(APPLE80211_IOC_CARD_CAPABILITIES, 0, cap);
}
IOReturn QualcommWifi::getPOWER(IO80211SkywalkInterface *iface, apple80211_power_data *pwr) {
return (IOReturn)handleApple80211Request(APPLE80211_IOC_POWER, -1, pwr);
}
IOReturn QualcommWifi::setPOWER(IO80211SkywalkInterface *iface, apple80211_power_data *pwr) {
int val = (pwr && pwr->power_state[0]) ? 1 : 0;
return (IOReturn)handleApple80211Request(APPLE80211_IOC_POWER, val, pwr);
}
IOReturn QualcommWifi::getCOUNTRY_CODE(IO80211SkywalkInterface *iface, apple80211_country_code_data *cc) {
return (IOReturn)handleApple80211Request(APPLE80211_IOC_COUNTRY_CODE, 0, cc);
}
IOReturn QualcommWifi::setCOUNTRY_CODE(IO80211SkywalkInterface *iface, apple80211_country_code_data *cc) {
return kIOReturnSuccess;
}
IOReturn QualcommWifi::setGET_DEBUG_INFO(IO80211SkywalkInterface *iface, apple80211_debug_command *dbg) {
return kIOReturnSuccess;
}
void* QualcommWifi::getLogger(void) const {
return nullptr;
}
void* QualcommWifi::getFaultReporterFromDriver(void) {
return nullptr;
}
#else
SInt32 QualcommWifi::apple80211Request(unsigned int req_type, int req_val, IO80211Interface* iface, void* req_data) {
return handleApple80211Request(req_type, req_val, req_data);
}
SInt32 QualcommWifi::apple80211SkywalkRequest(UInt req_type, int req_val, IO80211SkywalkInterface *iface, void *req_data) { SInt32 QualcommWifi::apple80211SkywalkRequest(UInt req_type, int req_val, IO80211SkywalkInterface *iface, void *req_data) {
return apple80211Request(req_type, req_val, nullptr, req_data); return handleApple80211Request(req_type, req_val, req_data);
} }
SInt32 QualcommWifi::stopDMA() { SInt32 QualcommWifi::stopDMA() {
@@ -1008,3 +1081,5 @@ IOReturn QualcommWifi::disable(IO80211SkywalkInterface *netif) {
fLinkActive = false; fLinkActive = false;
return kIOReturnSuccess; return kIOReturnSuccess;
} }
#endif
+25 -3
View File
@@ -232,24 +232,46 @@ public:
virtual UInt32 outputPacket(mbuf_t m, void *param) override; virtual UInt32 outputPacket(mbuf_t m, void *param) override;
// IO80211Controller interface // IO80211Controller interface
SInt32 handleApple80211Request(unsigned int req_type, int req_val, void* req_data);
#if __IO80211_TARGET >= 260000
// macOS Tahoe 26.x (Darwin 25) Skywalk IO80211Controller overrides
virtual bool isCommandProhibited(int command) override;
virtual IOReturn handleCardSpecific(IO80211SkywalkInterface *iface, unsigned long req_type, void *req_data, bool isSet) override;
virtual UInt32 hardwareOutputQueueDepth(void) override;
virtual SInt32 performCountryCodeOperation(IO80211CountryCodeOp op) override;
virtual void dataLinkLayerAttachComplete(void) override;
virtual SInt32 enableFeature(IO80211FeatureCode code, void *arg) override;
virtual IOReturn getDRIVER_VERSION(IO80211SkywalkInterface *iface, apple80211_version_data *vd) override;
virtual IOReturn getHARDWARE_VERSION(IO80211SkywalkInterface *iface, apple80211_version_data *vd) override;
virtual IOReturn getCARD_CAPABILITIES(IO80211SkywalkInterface *iface, apple80211_capability_data *cap) override;
virtual IOReturn getPOWER(IO80211SkywalkInterface *iface, apple80211_power_data *pwr) override;
virtual IOReturn setPOWER(IO80211SkywalkInterface *iface, apple80211_power_data *pwr) override;
virtual IOReturn getCOUNTRY_CODE(IO80211SkywalkInterface *iface, apple80211_country_code_data *cc) override;
virtual IOReturn setCOUNTRY_CODE(IO80211SkywalkInterface *iface, apple80211_country_code_data *cc) override;
virtual IOReturn setGET_DEBUG_INFO(IO80211SkywalkInterface *iface, apple80211_debug_command *dbg) override;
virtual void* getLogger(void) const override;
virtual void* getFaultReporterFromDriver(void) override;
#else
virtual SInt32 apple80211Request(unsigned int req_type, int req_val, IO80211Interface* iface, void* req_data) override; virtual SInt32 apple80211Request(unsigned int req_type, int req_val, IO80211Interface* iface, void* req_data) override;
virtual SInt32 apple80211SkywalkRequest(UInt req_type, int req_val, IO80211SkywalkInterface *iface, void *req_data) override; virtual SInt32 apple80211SkywalkRequest(UInt req_type, int req_val, IO80211SkywalkInterface *iface, void *req_data) override;
virtual SInt32 stopDMA() override; virtual SInt32 stopDMA() override;
virtual UInt32 hardwareOutputQueueDepth(IO80211Interface* iface) override; virtual UInt32 hardwareOutputQueueDepth(IO80211Interface* iface) override;
virtual SInt32 performCountryCodeOperation(IO80211Interface* iface, IO80211CountryCodeOp op) override; virtual SInt32 performCountryCodeOperation(IO80211Interface* iface, IO80211CountryCodeOp op) override;
virtual SInt32 enableFeature(IO80211FeatureCode code, void* arg) override; virtual SInt32 enableFeature(IO80211FeatureCode code, void* arg) override;
// Skywalk interface
virtual IOReturn enable(IO80211SkywalkInterface *netif) override; virtual IOReturn enable(IO80211SkywalkInterface *netif) override;
virtual IOReturn disable(IO80211SkywalkInterface *netif) override; virtual IOReturn disable(IO80211SkywalkInterface *netif) override;
#endif
// Compatibilité symboles virtuels IONetworkController sous macOS 15 // Compatibilité symboles virtuels IONetworkController sous macOS 15+ / 26+
virtual void _RESERVEDIONetworkController2() override {} virtual void _RESERVEDIONetworkController2() override {}
virtual void _RESERVEDIONetworkController3() override {} virtual void _RESERVEDIONetworkController3() override {}
virtual void _RESERVEDIONetworkController4() override {} virtual void _RESERVEDIONetworkController4() override {}
virtual void _RESERVEDIONetworkController5() override {} virtual void _RESERVEDIONetworkController5() override {}
#if __IO80211_TARGET < 260000
virtual void _RESERVEDIONetworkController6() override {} virtual void _RESERVEDIONetworkController6() override {}
virtual void _RESERVEDIONetworkController7() override {} virtual void _RESERVEDIONetworkController7() override {}
#endif
}; };
#endif #endif
+14 -14
View File
@@ -101,10 +101,10 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
BuildIndependentTargetsInParallel = 1; BuildIndependentTargetsInParallel = 1;
LastUpgradeCheck = 1640; LastUpgradeCheck = 2660;
TargetAttributes = { TargetAttributes = {
AE7E20C6307F7D1E000AD02F = { AE7E20C6307F7D1E000AD02F = {
CreatedOnToolsVersion = 16.4; CreatedOnToolsVersion = 26.6;
}; };
}; };
}; };
@@ -154,9 +154,9 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1.0.2; CURRENT_PROJECT_VERSION = 1.1.0;
GCC_PREPROCESSOR_DEFINITIONS = ( GCC_PREPROCESSOR_DEFINITIONS = (
"__IO80211_TARGET=150000", "__IO80211_TARGET=260000",
"$(inherited)", "$(inherited)",
); );
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@@ -165,10 +165,10 @@
); );
INFOPLIST_FILE = QualcommWireless/Info.plist; INFOPLIST_FILE = QualcommWireless/Info.plist;
INFOPLIST_KEY_NSHumanReadableCopyright = ""; INFOPLIST_KEY_NSHumanReadableCopyright = "";
MACOSX_DEPLOYMENT_TARGET = 15.5; MACOSX_DEPLOYMENT_TARGET = 26.0;
MARKETING_VERSION = 1.0.2; MARKETING_VERSION = 1.1.0;
MODULE_NAME = com.nawrhehe.QualcommWireless; MODULE_NAME = com.nawrhehe.QualcommWireless;
MODULE_VERSION = 1.0.1; MODULE_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.nawrhehe.QualcommWireless; PRODUCT_BUNDLE_IDENTIFIER = com.nawrhehe.QualcommWireless;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
RUN_CLANG_STATIC_ANALYZER = YES; RUN_CLANG_STATIC_ANALYZER = YES;
@@ -183,9 +183,9 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1.0.2; CURRENT_PROJECT_VERSION = 1.1.0;
GCC_PREPROCESSOR_DEFINITIONS = ( GCC_PREPROCESSOR_DEFINITIONS = (
"__IO80211_TARGET=150000", "__IO80211_TARGET=260000",
"$(inherited)", "$(inherited)",
); );
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@@ -194,10 +194,10 @@
); );
INFOPLIST_FILE = QualcommWireless/Info.plist; INFOPLIST_FILE = QualcommWireless/Info.plist;
INFOPLIST_KEY_NSHumanReadableCopyright = ""; INFOPLIST_KEY_NSHumanReadableCopyright = "";
MACOSX_DEPLOYMENT_TARGET = 15.5; MACOSX_DEPLOYMENT_TARGET = 26.0;
MARKETING_VERSION = 1.0.2; MARKETING_VERSION = 1.1.0;
MODULE_NAME = com.nawrhehe.QualcommWireless; MODULE_NAME = com.nawrhehe.QualcommWireless;
MODULE_VERSION = 1.0.1; MODULE_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.nawrhehe.QualcommWireless; PRODUCT_BUNDLE_IDENTIFIER = com.nawrhehe.QualcommWireless;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
RUN_CLANG_STATIC_ANALYZER = YES; RUN_CLANG_STATIC_ANALYZER = YES;
@@ -259,7 +259,7 @@
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES; LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MACOSX_DEPLOYMENT_TARGET = 15.5; MACOSX_DEPLOYMENT_TARGET = 26.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
@@ -314,7 +314,7 @@
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES; LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MACOSX_DEPLOYMENT_TARGET = 15.5; MACOSX_DEPLOYMENT_TARGET = 26.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
SDKROOT = macosx; SDKROOT = macosx;
+2 -2
View File
@@ -15,9 +15,9 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>KEXT</string> <string>KEXT</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.0.2</string> <string>1.1.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.0.2</string> <string>1.1.0</string>
<key>IOKitPersonalities</key> <key>IOKitPersonalities</key>
<dict> <dict>
<key>QualcommWireless_BT</key> <key>QualcommWireless_BT</key>
+4 -3
View File
@@ -439,9 +439,9 @@ bool QualcommWireless::start(IOService *provider) {
IOLog("QualcommWireless: Statut FINAL: 0x%02x (Patch: %s, Syscfg: %s) -> Pret pour macOS !\n", IOLog("QualcommWireless: Statut FINAL: 0x%02x (Patch: %s, Syscfg: %s) -> Pret pour macOS !\n",
finalStatus, (finalStatus & 0x80) ? "OUI" : "NON", (finalStatus & 0x40) ? "OUI" : "NON"); finalStatus, (finalStatus & 0x80) ? "OUI" : "NON", (finalStatus & 0x40) ? "OUI" : "NON");
// 1. Configuration du transport et des propriétés USB pour bluetoothd (macOS Monterey à Sequoia) // 1. Configuration du transport et des propriétés USB pour bluetoothd (macOS Monterey à Tahoe)
// D'après le désassemblage de /usr/sbin/bluetoothd (FindTransportType), le démon effectue en priorité : // D'après le désassemblage de /usr/sbin/bluetoothd (FindTransportType), le démon effectue en priorité :
// IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceNameMatching("Bluetooth USB Host Controller")) // IOServiceGetMatchingService(kIOMainPortDefault, IOServiceNameMatching("Bluetooth USB Host Controller"))
// S'il trouve ce service, il sélectionne immédiatement le transport USB (0) et contourne le test du Board-ID. // S'il trouve ce service, il sélectionne immédiatement le transport USB (0) et contourne le test du Board-ID.
setName("Bluetooth USB Host Controller"); setName("Bluetooth USB Host Controller");
fDevice->setName("Bluetooth USB Host Controller"); fDevice->setName("Bluetooth USB Host Controller");
@@ -489,10 +489,11 @@ bool QualcommWireless::start(IOService *provider) {
} }
// 4. Installation du hook shadow vtable sur fDevice pour intercepter les requêtes HCI au vol (ex: scan LE) // 4. Installation du hook shadow vtable sur fDevice pour intercepter les requêtes HCI au vol (ex: scan LE)
// Compatible macOS Sequoia (Darwin 24) & macOS Tahoe (Darwin 25) : slot 374 (offset 0xbb0)
sDeviceRequestVtableIndex = DeviceRequestAccessor::getVtableIndex(); sDeviceRequestVtableIndex = DeviceRequestAccessor::getVtableIndex();
if (sDeviceRequestVtableIndex > 0 && sDeviceRequestVtableIndex < 512) { if (sDeviceRequestVtableIndex > 0 && sDeviceRequestVtableIndex < 512) {
void **origVtable = *(void ***)fDevice; void **origVtable = *(void ***)fDevice;
if (origVtable && !sOrigDeviceRequest) { if (origVtable && origVtable[sDeviceRequestVtableIndex] && !sOrigDeviceRequest) {
memcpy(sShadowVtable, origVtable, sizeof(sShadowVtable)); memcpy(sShadowVtable, origVtable, sizeof(sShadowVtable));
sOrigVtablePtr = origVtable; sOrigVtablePtr = origVtable;
sOrigDeviceRequest = (DeviceRequestInternalFn)origVtable[sDeviceRequestVtableIndex]; sOrigDeviceRequest = (DeviceRequestInternalFn)origVtable[sDeviceRequestVtableIndex];
@@ -89,12 +89,13 @@ enum joinStatus
class IO80211Controller; class IO80211Controller;
class IO80211Interface; class IO80211Interface;
class IO82110WorkLoop; class IO82110WorkLoop;
class IO80211WorkQueue;
class IO80211CommandGate;
class IO80211VirtualInterface; class IO80211VirtualInterface;
class IO80211ControllerMonitor; class IO80211ControllerMonitor;
class CCLogPipe; class CCLogPipe;
class CCIOReporterLogStream; class CCIOReporterLogStream;
class CCLogStream; class CCLogStream;
class IO80211VirtualInterface;
class IO80211RangingManager; class IO80211RangingManager;
class IO80211FlowQueue; class IO80211FlowQueue;
class IO80211FlowQueueLegacy; class IO80211FlowQueueLegacy;
@@ -120,6 +121,9 @@ struct apple80211_btCoex_report;
struct apple80211_cca_report; struct apple80211_cca_report;
class CCPipe; class CCPipe;
struct apple80211_lteCoex_report; struct apple80211_lteCoex_report;
struct apple80211_platform_config;
struct apple80211_debug_command;
struct IO80211InterfaceAVCAdvisory;
//typedef int scanSource; //typedef int scanSource;
//typedef int joinStatus; //typedef int joinStatus;
@@ -146,7 +150,7 @@ public:
virtual IOWorkLoop* getWorkLoop(void) const APPLE_KEXT_OVERRIDE; virtual IOWorkLoop* getWorkLoop(void) const APPLE_KEXT_OVERRIDE;
virtual const char* stringFromReturn(int) APPLE_KEXT_OVERRIDE; virtual const char* stringFromReturn(int) APPLE_KEXT_OVERRIDE;
virtual int errnoFromReturn(int) APPLE_KEXT_OVERRIDE; virtual int errnoFromReturn(int) APPLE_KEXT_OVERRIDE;
virtual IOOutputQueue* getOutputQueue(void) const APPLE_KEXT_OVERRIDE { return NULL; } virtual IOOutputQueue* getOutputQueue(void) const APPLE_KEXT_OVERRIDE;
virtual bool createWorkLoop(void) APPLE_KEXT_OVERRIDE; virtual bool createWorkLoop(void) APPLE_KEXT_OVERRIDE;
virtual IOReturn enable(IONetworkInterface *) APPLE_KEXT_OVERRIDE; virtual IOReturn enable(IONetworkInterface *) APPLE_KEXT_OVERRIDE;
virtual IOReturn disable(IONetworkInterface *) APPLE_KEXT_OVERRIDE; virtual IOReturn disable(IONetworkInterface *) APPLE_KEXT_OVERRIDE;
@@ -154,12 +158,88 @@ public:
#if __IO80211_TARGET >= __MAC_10_15 #if __IO80211_TARGET >= __MAC_10_15
virtual void detachInterface(IONetworkInterface *iface, bool sync = false) APPLE_KEXT_OVERRIDE { IOEthernetController::detachInterface(iface, sync); } virtual void detachInterface(IONetworkInterface *iface, bool sync = false) APPLE_KEXT_OVERRIDE { IOEthernetController::detachInterface(iface, sync); }
#endif #endif
virtual IONetworkInterface* createInterface(void) APPLE_KEXT_OVERRIDE { return IOEthernetController::createInterface(); } virtual IONetworkInterface* createInterface(void) APPLE_KEXT_OVERRIDE;
virtual bool configureInterface(IONetworkInterface *iface) APPLE_KEXT_OVERRIDE { return IOEthernetController::configureInterface(iface); } virtual bool configureInterface(IONetworkInterface *iface) APPLE_KEXT_OVERRIDE;
#ifdef __PRIVATE_SPI__ #ifdef __PRIVATE_SPI__
virtual IOReturn outputStart(IONetworkInterface *,UInt) APPLE_KEXT_OVERRIDE; virtual IOReturn outputStart(IONetworkInterface *,UInt) APPLE_KEXT_OVERRIDE;
#endif #endif
virtual IOReturn getHardwareAddress(IOEthernetAddress *) APPLE_KEXT_OVERRIDE; virtual IOReturn getHardwareAddress(IOEthernetAddress *) APPLE_KEXT_OVERRIDE;
#if __IO80211_TARGET >= 260000
// macOS Tahoe 26.x (Darwin 25, IO80211Family 1200.13.1 / source 1566.5)
// Slots 394..462 (offsets 0xc50..0xe70)
virtual bool isCommandProhibited(int) = 0; // slot 394 (0xc50)
virtual bool createWorkQueue(void); // slot 395 (0xc58)
virtual bool debugStateInit(void); // slot 396 (0xc60)
virtual IO80211WorkQueue* getWorkQueue(void) const; // slot 397 (0xc68)
virtual void requestPacketTx(void*, UInt32); // slot 398 (0xc70)
virtual IO80211CommandGate* getIO80211CommandGate(void) const; // slot 399 (0xc78)
virtual IO80211SkywalkInterface* getPrimarySkywalkInterface(void); // slot 400 (0xc80)
virtual int bpfOutputPacket(OSObject*, UInt32, mbuf_t); // slot 401 (0xc88)
virtual SInt32 monitorModeSetEnabled(bool, UInt32); // slot 402 (0xc90)
virtual IOReturn handleCardSpecific(IO80211SkywalkInterface*, unsigned long, void*, bool) = 0; // slot 403 (0xc98)
virtual UInt32 hardwareOutputQueueDepth(void); // slot 404 (0xca0)
virtual SInt32 performCountryCodeOperation(IO80211CountryCodeOp); // slot 405 (0xca8)
virtual void dataLinkLayerAttachComplete(void); // slot 406 (0xcb0)
virtual SInt32 enableFeature(IO80211FeatureCode, void*); // slot 407 (0xcb8)
virtual IOReturn getDRIVER_VERSION(IO80211SkywalkInterface*, apple80211_version_data*) = 0; // slot 408 (0xcc0)
virtual IOReturn getHARDWARE_VERSION(IO80211SkywalkInterface*, apple80211_version_data*) = 0; // slot 409 (0xcc8)
virtual IOReturn getCARD_CAPABILITIES(IO80211SkywalkInterface*, apple80211_capability_data*) = 0; // slot 410 (0xcd0)
virtual IOReturn getPOWER(IO80211SkywalkInterface*, apple80211_power_data*) = 0; // slot 411 (0xcd8)
virtual IOReturn setPOWER(IO80211SkywalkInterface*, apple80211_power_data*) = 0; // slot 412 (0xce0)
virtual IOReturn getCOUNTRY_CODE(IO80211SkywalkInterface*, apple80211_country_code_data*) = 0; // slot 413 (0xce8)
virtual IOReturn setCOUNTRY_CODE(IO80211SkywalkInterface*, apple80211_country_code_data*) = 0; // slot 414 (0xcf0)
virtual IOReturn setGET_DEBUG_INFO(IO80211SkywalkInterface*, apple80211_debug_command*) = 0; // slot 415 (0xcf8)
virtual IOReturn getPLATFORM_CONFIG(IO80211SkywalkInterface*, apple80211_platform_config*); // slot 416 (0xd00)
virtual SInt32 enableVirtualInterface(IO80211VirtualInterface*); // slot 417 (0xd08)
virtual SInt32 disableVirtualInterface(IO80211VirtualInterface*); // slot 418 (0xd10)
virtual bool requiresExplicitMBufRelease(void); // slot 419 (0xd18)
virtual bool flowIdSupported(void); // slot 420 (0xd20)
virtual IO80211FlowQueue* requestFlowQueue(FlowIdMetadata const*); // slot 421 (0xd28)
virtual void releaseFlowQueue(IO80211FlowQueue*); // slot 422 (0xd30)
virtual void getLogPipes(CCPipe**, CCPipe**, CCPipe**); // slot 423 (0xd38)
virtual void* getLogger(void) const = 0; // slot 424 (0xd40)
virtual SInt32 enableFeatureForLoggingFlags(UInt64); // slot 425 (0xd48)
virtual IOReturn requestQueueSizeAndTimeout(UInt16*, UInt16*); // slot 426 (0xd50)
virtual IOReturn enablePacketTimestamping(void); // slot 427 (0xd58)
virtual IOReturn disablePacketTimestamping(void); // slot 428 (0xd60)
virtual UInt64 getPacketTSCounter(void); // slot 429 (0xd68)
virtual void* getDriverTextLog(void); // slot 430 (0xd70)
virtual UInt32 selfDiagnosticsReport(int, char const*, UInt32); // slot 431 (0xd78)
virtual void* getFaultReporterFromDriver(void) = 0; // slot 432 (0xd80)
virtual IORecursiveLock* allocIO80211RecursiveLock(void); // slot 433 (0xd88)
virtual UInt32 getDataQueueDepth(OSObject*); // slot 434 (0xd90)
virtual bool wasDynSARInFailSafeMode(void); // slot 435 (0xd98)
virtual void updateAdvisoryScoresIfNeed(void); // slot 436 (0xda0)
virtual IOReturn getAVCAdvisoryInfo(IO80211InterfaceAVCAdvisory*); // slot 437 (0xda8)
virtual UInt32 getActionFramePoolCapacity(void); // slot 438 (0xdb0)
virtual void* getPostOffice(void); // slot 439 (0xdb8)
virtual IOReturn CreatePostOffice(void); // slot 440 (0xdc0)
virtual bool attachInterface(OSObject*, IOService*); // slot 441 (0xdc8)
virtual bool detachInterface(OSObject*, bool); // slot 442 (0xdd0)
virtual IO80211VirtualInterface* createVirtualInterface(ether_addr*, UInt32); // slot 443 (0xdd8)
virtual bool attachVirtualInterface(IO80211VirtualInterface**, ether_addr*, UInt32, bool); // slot 444 (0xde0)
virtual bool detachVirtualInterface(IO80211VirtualInterface*, bool); // slot 445 (0xde8)
OSMetaClassDeclareReservedUnused( IO80211Controller, 0); // slot 446 (0xdf0)
OSMetaClassDeclareReservedUnused( IO80211Controller, 1); // slot 447 (0xdf8)
OSMetaClassDeclareReservedUnused( IO80211Controller, 2); // slot 448 (0xe00)
OSMetaClassDeclareReservedUnused( IO80211Controller, 3); // slot 449 (0xe08)
OSMetaClassDeclareReservedUnused( IO80211Controller, 4); // slot 450 (0xe10)
OSMetaClassDeclareReservedUnused( IO80211Controller, 5); // slot 451 (0xe18)
OSMetaClassDeclareReservedUnused( IO80211Controller, 6); // slot 452 (0xe20)
OSMetaClassDeclareReservedUnused( IO80211Controller, 7); // slot 453 (0xe28)
OSMetaClassDeclareReservedUnused( IO80211Controller, 8); // slot 454 (0xe30)
OSMetaClassDeclareReservedUnused( IO80211Controller, 9); // slot 455 (0xe38)
OSMetaClassDeclareReservedUnused( IO80211Controller, 10); // slot 456 (0xe40)
OSMetaClassDeclareReservedUnused( IO80211Controller, 11); // slot 457 (0xe48)
OSMetaClassDeclareReservedUnused( IO80211Controller, 12); // slot 458 (0xe50)
OSMetaClassDeclareReservedUnused( IO80211Controller, 13); // slot 459 (0xe58)
OSMetaClassDeclareReservedUnused( IO80211Controller, 14); // slot 460 (0xe60)
OSMetaClassDeclareReservedUnused( IO80211Controller, 15); // slot 461 (0xe68)
virtual IOReturn setMulticastList(ether_addr const*, UInt32); // slot 462 (0xe70)
#else
virtual void requestPacketTx(void*, UInt) {} virtual void requestPacketTx(void*, UInt) {}
virtual IOReturn getHardwareAddressForInterface(IO80211Interface *,IOEthernetAddress *) { return kIOReturnSuccess; } virtual IOReturn getHardwareAddressForInterface(IO80211Interface *,IOEthernetAddress *) { return kIOReturnSuccess; }
virtual void inputMonitorPacket(mbuf_t,UInt,void *,unsigned long) {} virtual void inputMonitorPacket(mbuf_t,UInt,void *,unsigned long) {}
@@ -240,81 +320,9 @@ public:
virtual IOReturn disable(IO80211SkywalkInterface *) { return kIOReturnSuccess; } virtual IOReturn disable(IO80211SkywalkInterface *) { return kIOReturnSuccess; }
#endif #endif
//public:
// IO80211SkywalkInterface* getInfraInterface(void);
// IO80211ScanManager* getPrimaryInterfaceScanManager(void);
// IO80211ControllerMonitor* getInterfaceMonitor(void);
// IOReturn addReporterLegend(IOService *,IOReporter *,char const*,char const*);
// IOReturn removeReporterFromLegend(IOService *,IOReporter *,char const*,char const*);
// IOReturn unlockIOReporterLegend(void);
// void lockIOReporterLegend(void);// Suspected return type - int
// IOReturn logIOReportLogStreamSubscription(unsigned long long);
// IOReturn addIOReportLogStreamForProvider(IOService *,unsigned long long *);
// IOReturn addSubscriptionForThisReporterFetchedOnTimer(IOReporter *,char const*,char const*,IOService *) ;
// IOReturn addSubscriptionForProviderFetchedOnTimer(IOService *);
// void handleIOReporterTimer(IOTimerEventSource *);
// void setIOReportersStreamFlags(unsigned long long);
// void updateIOReportersStreamFrequency(void); // Suspected return type - int
// void setIOReportersStreamLevel(CCStreamLogLevel);
// void powerChangeGated(OSObject *,void *,void *,void *,void *);
// int copyOut(void const*,unsigned long long,unsigned long);
// SInt32 getASSOCIATE_RESULT(IO80211Interface *,IO80211VirtualInterface *,IO80211SkywalkInterface *,apple80211_assoc_result_data *);
// IOReturn copyIn(unsigned long long,void *,unsigned long);
// void logIOCTL(apple80211req *);
// bool isIOCTLLoggingRestricted(apple80211req *);
// IOReturn setChanNoiseFloorLTE(apple80211_stat_report *,int);
// IOReturn setChanNoiseFloor(apple80211_stat_report *,int);
// IOReturn setChanCCA(apple80211_stat_report *,int);
// IOReturn setChanExtendedCCA(apple80211_stat_report *,apple80211_cca_report *);
// bool setLTECoexstat(apple80211_stat_report *,apple80211_lteCoex_report *);
// bool setBTCoexstat(apple80211_stat_report *,apple80211_btCoex_report *);
// bool setAMPDUstat(apple80211_stat_report *,apple80211_ampdu_stat_report *,apple80211_channel *);
// UInt32 getCountryCode(apple80211_country_code_data *);
// IOReturn setCountryCode(apple80211_country_code_data *);
// bool getInfraExtendedStats(apple80211_extended_stats *);
// bool getChipCounterStats(apple80211_chip_stats *);
// bool setExtendedChipCounterStats(apple80211_stat_report *,void *);
// bool setChipCounterStats(apple80211_stat_report *,apple80211_chip_stats *,apple80211_channel *);
// virtual bool setLeakyAPStats(apple80211_leaky_ap_event *);
// bool setFrameStats(apple80211_stat_report *,apple80211_frame_counters *,apple80211_channel *);
// bool setPowerStats(apple80211_stat_report *,apple80211_power_debug_sub_info *);
// bool getBeaconPeriod(apple80211_beacon_period_data *);
SInt32 apple80211VirtualRequestIoctl(unsigned int,int,IO80211VirtualInterface *,void *); SInt32 apple80211VirtualRequestIoctl(unsigned int,int,IO80211VirtualInterface *,void *);
// bool getBSSIDData(OSObject *,apple80211_bssid_data *);
// bool getSSIDData(apple80211_ssid_data *);
// bool inputInfraPacket(mbuf_t);
// void notifyHostapState(apple80211_hostap_state *);
// bool isAwdlAssistedDiscoveryEnabled(void);
// void joinDone(scanSource,joinStatus);
// void joinStarted(scanSource,joinStatus);
// void handleChannelSwitchAnnouncement(apple80211_channel_switch_announcement *);
// void scanDone(scanSource,int);
// void scanStarted(scanSource,apple80211_scan_data *);
// void printChannels(void);
// void updateInterfaceCoexRiskPct(unsigned long long);
// SInt32 getInfraChannel(apple80211_channel_data *);
// void calculateInterfacesAvaiability(void); // Suspected return type - int
// void setChannelSequenceList(apple80211_awdl_sync_channel_sequence *); // Suspected return type - int
// void setPrimaryInterfaceDatapathState(bool);
// UInt32 getPrimaryInterfaceLinkState(void);
// void setCurrentChannel(apple80211_channel *); // Suspected return type - int
// void setHtCapability(ieee80211_ht_capability_ie *);
// UInt32 getHtCapability(void);
// UInt32 getHtCapabilityLength(void);
// bool io80211isDebuggable(bool* enable);
// void logDebug(unsigned long long,char const*,...); // Suspected return type - int
// void vlogDebug(unsigned long long,char const*,va_list); // Suspected return type - char
// void logDebug(char const*,...); // Suspected return type - int
// bool calculateInterfacesCoex(void);
// void setInfraChannel(apple80211_channel *);
// void configureAntennae(void);
SInt32 apple80211RequestIoctl(unsigned int,int,IO80211Interface *,void *); SInt32 apple80211RequestIoctl(unsigned int,int,IO80211Interface *,void *);
UInt32 radioCountForInterface(IO80211Interface *); UInt32 radioCountForInterface(IO80211Interface *);
// void releaseIOReporters(void);
// bool findAndAttachToFaultReporter(void);
// UInt32 setupControlPathLogging(void);
// IOReturn createIOReporters(IOService *);
// IOReturn powerChangeHandler(void *,void *,unsigned int,IOService *,void *,unsigned long);
OSMetaClassDeclareReservedUnused( IO80211Controller, 0); OSMetaClassDeclareReservedUnused( IO80211Controller, 0);
OSMetaClassDeclareReservedUnused( IO80211Controller, 1); OSMetaClassDeclareReservedUnused( IO80211Controller, 1);
@@ -332,9 +340,15 @@ public:
OSMetaClassDeclareReservedUnused( IO80211Controller, 13); OSMetaClassDeclareReservedUnused( IO80211Controller, 13);
OSMetaClassDeclareReservedUnused( IO80211Controller, 14); OSMetaClassDeclareReservedUnused( IO80211Controller, 14);
OSMetaClassDeclareReservedUnused( IO80211Controller, 15); OSMetaClassDeclareReservedUnused( IO80211Controller, 15);
#endif
protected: protected:
#if __IO80211_TARGET >= 260000
// sizeof(IOEthernetController) == 0xa8, sizeof(IO80211Controller) == 0x128 in macOS Tahoe
uint8_t filler[0x80];
#else
uint8_t filler[0x500]; uint8_t filler[0x500];
#endif
}; };
// 0x215: 1 byte, length of channel sequence, should be 16 // 0x215: 1 byte, length of channel sequence, should be 16
+11 -11
View File
@@ -1,14 +1,14 @@
# QualcommWireless # QualcommWireless
[![macOS Sequoia](https://img.shields.io/badge/macOS-Sequoia%2015.x-blue.svg)](https://www.apple.com/macos/) [![macOS Tahoe](https://img.shields.io/badge/macOS-Tahoe%2026.x%20%7C%20Sequoia%2015.x-blue.svg)](https://www.apple.com/macos/)
[![Wi-Fi 7](https://img.shields.io/badge/Wi--Fi%207-802.11be-green.svg)](https://en.wikipedia.org/wiki/IEEE_802.11be) [![Wi-Fi 7](https://img.shields.io/badge/Wi--Fi%207-802.11be-green.svg)](https://en.wikipedia.org/wiki/IEEE_802.11be)
[![Bluetooth 5.4](https://img.shields.io/badge/Bluetooth-5.4%20LE%20Audio-orange.svg)](https://en.wikipedia.org/wiki/Bluetooth) [![Bluetooth 5.4](https://img.shields.io/badge/Bluetooth-5.4%20LE%20Audio-orange.svg)](https://en.wikipedia.org/wiki/Bluetooth)
[![OpenCore](https://img.shields.io/badge/Bootloader-OpenCore-lightgrey.svg)](https://github.com/acidanthera/OpenCorePkg) [![OpenCore](https://img.shields.io/badge/Bootloader-OpenCore-lightgrey.svg)](https://github.com/acidanthera/OpenCorePkg)
[![Architecture](https://img.shields.io/badge/Arch-x86__64%20%7C%20arm64e-purple.svg)]() [![Architecture](https://img.shields.io/badge/Arch-x86__64%20%7C%20arm64e-purple.svg)]()
Pilote unifié haute performance pour les modules **Qualcomm FastConnect 7800 (WCN7850)** sous **macOS Sequoia (15.x)** et versions ultérieures. Pilote unifié haute performance pour les modules **Qualcomm FastConnect 7800 (WCN7850)** sous **macOS Tahoe (26.x / Darwin 25)** et **macOS Sequoia (15.x / Darwin 24)**.
Ce projet fournit une prise en charge **Wi-Fi 7 native** intégrée à la pile réseau sans fil Apple (`IO80211Controller`), ainsi que l'initialisation complète et le téléversement de microprogramme du sous-système **Bluetooth 5.4** via USB. Ce projet fournit une prise en charge **Wi-Fi 7 native** intégrée à la pile réseau sans fil Apple (`IO80211Controller` / Skywalk), ainsi que l'initialisation complète et le téléversement de microprogramme du sous-système **Bluetooth 5.4** via USB.
--- ---
@@ -39,7 +39,7 @@ Le module **Qualcomm FastConnect 7800 (WCN7850)** combine deux contrôleurs mat
## Fonctionnalités Principales ## Fonctionnalités Principales
### 🌐 Wi-Fi Natif Apple (`QualcommWifi`) ### 🌐 Wi-Fi Natif Apple (`QualcommWifi`)
- **Véritable interface sans fil Apple80211** : Dérive directement de [`IO80211Controller`](QualcommWireless/QualcommWifi.hpp), évitant toute émulation Ethernet artificielle. - **Véritable interface sans fil Apple80211** : Dérive directement de [`IO80211Controller`](QualcommWifi/QualcommWifi.hpp), compatible avec l'ABI Skywalk de macOS Tahoe 26.x (`__IO80211_TARGET=260000`, vtable 463 slots), évitant toute émulation Ethernet artificielle.
- **Intégration macOS complète** : - **Intégration macOS complète** :
- Détection automatique dans le **Centre de Contrôle** et la barre des menus. - Détection automatique dans le **Centre de Contrôle** et la barre des menus.
- Compatibilité avec le framework `CoreWLAN` et le daemon système `airportd`. - Compatibilité avec le framework `CoreWLAN` et le daemon système `airportd`.
@@ -54,7 +54,7 @@ Le module **Qualcomm FastConnect 7800 (WCN7850)** combine deux contrôleurs mat
- **Initialisation & Patching du Firmware USB** : - **Initialisation & Patching du Firmware USB** :
- Vérification de l'état QCA (`QCA_CHECK_STATUS`, `QCA_GET_TARGET_VERSION`). - Vérification de l'état QCA (`QCA_CHECK_STATUS`, `QCA_GET_TARGET_VERSION`).
- Téléversement séquentiel du **RAMPATCH** (`rampatch_usb_00190200_bin`) et du **NVM** via les pipes de contrôle EP0 et Bulk OUT EP2. - Téléversement séquentiel du **RAMPATCH** (`rampatch_usb_00190200_bin`) et du **NVM** via les pipes de contrôle EP0 et Bulk OUT EP2.
- Réinitialisation matérielle propre (`HCI_Reset`). - Réinitialisation matérielle propre (`HCI_Reset`) et interception Shadow VTable de `IOUSBHostDevice::deviceRequest` (slot `374` / `0x176`).
- **Compatibilité Apple** : - **Compatibilité Apple** :
- Connexion fluide des périphériques Apple (Magic Mouse 2, Magic Keyboard, Magic Trackpad). - Connexion fluide des périphériques Apple (Magic Mouse 2, Magic Keyboard, Magic Trackpad).
- Audio Bluetooth (A2DP, HFP/HSP) et profils GATT/BLE. - Audio Bluetooth (A2DP, HFP/HSP) et profils GATT/BLE.
@@ -65,7 +65,7 @@ Le module **Qualcomm FastConnect 7800 (WCN7850)** combine deux contrôleurs mat
```mermaid ```mermaid
graph TD graph TD
subgraph macOS["macOS Sequoia 15.x (Darwin 24)"] subgraph macOS["macOS Tahoe 26.x (Darwin 25) / Sequoia 15.x"]
UI["Centre de Contrôle / Barre de Menus"] UI["Centre de Contrôle / Barre de Menus"]
AirportD["airportd / CoreWLAN.framework"] AirportD["airportd / CoreWLAN.framework"]
BtD["bluetoothd / IOBluetoothFamily"] BtD["bluetoothd / IOBluetoothFamily"]
@@ -74,8 +74,8 @@ graph TD
end end
subgraph Kext["QualcommWireless.kext"] subgraph Kext["QualcommWireless.kext"]
QWifi["QualcommWifi (IO80211Controller)\n• apple80211_ioctl\n• BHI/MHI Pipeline\n• BAR0 Windowing"] QWifi["QualcommWifi (IO80211Controller)\n• handleCardSpecific / Skywalk\n• BHI/MHI Pipeline\n• BAR0 Windowing"]
QBt["QualcommWireless (IOService)\n• DFU Firmware Upload\n• RAMPATCH + NVM\n• Registry Spoofing"] QBt["QualcommWireless (IOService)\n• DFU Firmware Upload\n• RAMPATCH + NVM\n• Shadow VTable & Registry Spoofing"]
end end
subgraph Hardware["Puce Qualcomm WCN7850"] subgraph Hardware["Puce Qualcomm WCN7850"]
@@ -100,8 +100,8 @@ graph TD
Le dossier [`docs/`](docs/) contient une documentation technique exhaustive : Le dossier [`docs/`](docs/) contient une documentation technique exhaustive :
- 📐 [**ARCHITECTURE.md**](docs/ARCHITECTURE.md) : Détail complet des interactions logicielles et matérielles, pipelines firmware et topologies de bus. - 📐 [**ARCHITECTURE.md**](docs/ARCHITECTURE.md) : Détail complet des interactions logicielles et matérielles, pipelines firmware et topologies de bus.
- 🔵 [**BLUETOOTH.md**](docs/BLUETOOTH.md) : Analyse post-mortem du crash L2CAP au démarrage de session, séquence DFU et configuration `bluetoothd`. - 🔵 [**BLUETOOTH.md**](docs/BLUETOOTH.md) : Analyse post-mortem du crash L2CAP au démarrage de session, séquence DFU et configuration `bluetoothd` sous Sequoia et Tahoe.
- 📡 [**NATIVE_WIFI.md**](docs/NATIVE_WIFI.md) : Implémentation du pilote `IO80211Controller`, table des IOCTLs Apple80211 et gestion Wi-Fi 7. - 📡 [**NATIVE_WIFI.md**](docs/NATIVE_WIFI.md) : Implémentation du pilote `IO80211Controller`, vtable Skywalk macOS Tahoe et table des IOCTLs Apple80211.
- 🛠️ [**BUILD.md**](docs/BUILD.md) : Guide de compilation, injection dans l'EFI OpenCore et commandes de diagnostic. - 🛠️ [**BUILD.md**](docs/BUILD.md) : Guide de compilation, injection dans l'EFI OpenCore et commandes de diagnostic.
--- ---
@@ -109,7 +109,7 @@ Le dossier [`docs/`](docs/) contient une documentation technique exhaustive :
## Compilation ## Compilation
### Prérequis ### Prérequis
- Xcode 15+ ou 16+ sous macOS Sonoma ou macOS Sequoia. - Xcode 26+ (ex. Xcode 26.6 avec SDK macOS 26.5) sous macOS Tahoe, ou Xcode 16+ sous macOS Sequoia.
- Outils en ligne de commande Xcode (`xcode-select --install`). - Outils en ligne de commande Xcode (`xcode-select --install`).
### Lancer la compilation ### Lancer la compilation
+2 -2
View File
@@ -1,6 +1,6 @@
# Architecture de QualcommWireless # Architecture de QualcommWireless
Ce document détaille l'architecture logicielle et matérielle du pilote unifié **QualcommWireless** pour les puces combinées **Qualcomm FastConnect 7800** (SoC WCN7850) sous macOS Sequoia (15.x) et versions ultérieures. Ce document détaille l'architecture logicielle et matérielle du pilote unifié **QualcommWireless** pour les puces combinées **Qualcomm FastConnect 7800** (SoC WCN7850) sous **macOS Tahoe (26.x / Darwin 25)** et **macOS Sequoia (15.x / Darwin 24)**.
--- ---
@@ -10,7 +10,7 @@ Le module sans fil Qualcomm FastConnect 7800 (WCN7850) utilise une architecture
```mermaid ```mermaid
graph TD graph TD
subgraph Host["Système Hôte (macOS Sequoia - Darwin 24)"] subgraph Host["Système Hôte (macOS Tahoe - Darwin 25 / Sequoia - Darwin 24)"]
subgraph Kernel["Kernel Space (XNU / IOKit)"] subgraph Kernel["Kernel Space (XNU / IOKit)"]
IO80211["com.apple.iokit.IO80211Family\n(IO80211Controller)"] IO80211["com.apple.iokit.IO80211Family\n(IO80211Controller)"]
IOUSB["com.apple.iokit.IOUSBHostFamily\n(IOUSBHostDevice / Interface)"] IOUSB["com.apple.iokit.IOUSBHostFamily\n(IOUSBHostDevice / Interface)"]
+10 -6
View File
@@ -103,38 +103,42 @@ sequenceDiagram
D->>USB: Connexion Magic Mouse 2 / Clavier (L2CAP) D->>USB: Connexion Magic Mouse 2 / Clavier (L2CAP)
``` ```
Grâce à cette séquence, le contrôleur Bluetooth WCN7850 opère de manière parfaitement stable sous macOS Sequoia sans aucun crash au démarrage de session. Grâce à cette séquence, le contrôleur Bluetooth WCN7850 opère de manière parfaitement stable sous macOS Sequoia (Darwin 24) et macOS Tahoe (Darwin 25) sans aucun crash au démarrage de session.
--- ---
## 5. Rétro-ingénierie de `bluetoothd` (macOS 15 Sequoia) & Détection du Transport ## 5. Rétro-ingénierie de `bluetoothd` (macOS Sequoia & macOS Tahoe) & Détection du Transport
### 5.1. Algorithme de sélection du transport dans `FindTransportType` ### 5.1. Algorithme de sélection du transport dans `FindTransportType`
Le désassemblage complet du binaire `/usr/sbin/bluetoothd` (fonctions à `0x100121555` et `0x1001216c6`) a révélé l'algorithme exact de détection du bus HCI : Le désassemblage complet du binaire `/usr/sbin/bluetoothd` sous macOS Sequoia (`0x100121555`) et sous macOS Tahoe 26.7.1 (`0x10014c700`, `Found_USB_Dongle` à `0x1000e9559`, `GetProductAndVendorID` à `0x1000edf2a`) a révélé l'algorithme exact de détection du bus HCI :
1. **Test 1 : `transport-encoding` dans l'arbre matériel (`IODeviceTree`)** 1. **Test 1 : `transport-encoding` dans l'arbre matériel (`IODeviceTree`)**
- `bluetoothd` interroge la propriété `transport-encoding` sous `IODeviceTree:/chosen` ou les nœuds bluetooth. - `bluetoothd` interroge la propriété `transport-encoding` sous `IODeviceTree:/chosen` ou les nœuds bluetooth.
- S'il trouve `0x00000000`, il force immédiatement le transport USB (`"DeviceTree transport = 0x00000000"`). - S'il trouve `0x00000000`, il force immédiatement le transport USB (`"DeviceTree transport = 0x00000000"`).
2. **Test 2 : Matching IORegistry du service hôte USB (`0x100121620`)** 2. **Test 2 : Matching IORegistry du service hôte USB (`0x100121620` / `0x10014c7ca`)**
- `bluetoothd` appelle : - `bluetoothd` appelle :
```c ```c
IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceNameMatching("Bluetooth USB Host Controller")); IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceNameMatching("Bluetooth USB Host Controller"));
``` ```
- **Découverte majeure** : Si **un service quelconque** dans l'IORegistry porte le nom `"Bluetooth USB Host Controller"`, `bluetoothd` assigne **immédiatement `Transport = 0 (USB)`** et retourne sans jamais évaluer le `board-id` de la machine ! - **Découverte majeure** : Si **un service quelconque** dans l'IORegistry porte le nom `"Bluetooth USB Host Controller"`, `bluetoothd` assigne **immédiatement `Transport = 0 (USB)`** et retourne sans jamais évaluer le `board-id` de la machine !
3. **Test 3 : Fallback par table statique des `board-id` (`0x1001216c6`)** 3. **Test 3 : Fallback par table statique des `board-id` (`0x1001216c6` / `0x10014c86f`)**
- Si aucun service `"Bluetooth USB Host Controller"` n'a été trouvé, `bluetoothd` lit le `board-id` dans l'arbre IODeviceTree (`"sysBoardID %s"`). - Si aucun service `"Bluetooth USB Host Controller"` n'a été trouvé, `bluetoothd` lit le `board-id` dans l'arbre IODeviceTree (`"sysBoardID %s"`).
- Il compare l'ID à deux tables internes : - Il compare l'ID à deux tables internes :
- Table 1 : Modèles avec Bluetooth USB natif (iMac, Mac mini, MacBook Pro pré-T2). - Table 1 : Modèles avec Bluetooth USB natif (iMac, Mac mini, MacBook Pro pré-T2).
- Table 2 : Modèles avec Bluetooth UART natif (`MacPro7,1` / `Mac-27AD2F918AE68F61`). - Table 2 : Modèles avec Bluetooth UART natif (`MacPro7,1` / `Mac-27AD2F918AE68F61`).
- Sur SMBIOS `MacPro7,1`, le démon sélectionne par défaut le transport UART (H4BC) et ignore complètement tout périphérique USB, affichant `Chipset: BCM_4350C2, Transport: UART, State: Off`. - Sur SMBIOS `MacPro7,1`, le démon sélectionne par défaut le transport UART (H4BC) et ignore complètement tout périphérique USB, affichant `Chipset: BCM_4350C2, Transport: UART, State: Off`.
### 5.2. Résolution native dans `QualcommWireless` ### 5.2. Résolution native et Hook Shadow VTable dans `QualcommWireless`
En appliquant les enseignements de la rétro-ingénierie : En appliquant les enseignements de la rétro-ingénierie :
- `QualcommWireless` s'enregistre explicitement sous le nom `"Bluetooth USB Host Controller"`. - `QualcommWireless` s'enregistre explicitement sous le nom `"Bluetooth USB Host Controller"`.
- `fDevice->setName("Bluetooth USB Host Controller")`. - `fDevice->setName("Bluetooth USB Host Controller")`.
- Injection de `transport-encoding = <00 00 00 00>` sur le périphérique et sur `IODeviceTree:/chosen`. - Injection de `transport-encoding = <00 00 00 00>` sur le périphérique et sur `IODeviceTree:/chosen`.
- Spoofing de `idVendor = 0x0a12` (CSR) validé nativement par `Found_USB_Dongle`. - Spoofing de `idVendor = 0x0a12` (CSR) validé nativement par `Found_USB_Dongle`.
- **Shadow VTable (`IOUSBHostDevice::deviceRequest`)** :
- L'index vtable de `IOUSBHostDevice::deviceRequest(IOService*, StandardUSB::DeviceRequest&, void*, IOMemoryDescriptor*, uint32_t&, IOUSBHostCompletion*, uint32_t)` est résolu dynamiquement à la compilation via `DeviceRequestAccessor::getVtableIndex()` : **slot `374` (`0x176`, offset `0xbb0`)**, identique sous macOS Sequoia (`Darwin 24`) et macOS Tahoe (`Darwin 25.6.0`, `__ZTV15IOUSBHostDevice` à `0xffffff8002e72720`).
- L'interception du descripteur de périphérique USB (`GET_DESCRIPTOR DEVICE`, 18 octets) remplace à la volée le Vendor ID `0x0489` par `0x0a12` (CSR) lors de la lecture directe par `bluetoothd` (`GetProductAndVendorID`).
- Résultat : `bluetoothd` configure le contrôleur en USB de manière native et immédiate. - Résultat : `bluetoothd` configure le contrôleur en USB de manière native et immédiate.
+9 -8
View File
@@ -6,9 +6,9 @@ Ce guide détaille les étapes pour compiler le kext **QualcommWireless** à par
## 1. Prérequis Système ## 1. Prérequis Système
- **Système d'exploitation hôte** : macOS Sonoma (14.x) ou macOS Sequoia (15.x). - **Système d'exploitation hôte** : macOS Tahoe (26.x / Darwin 25), macOS Sequoia (15.x / Darwin 24) ou macOS Sonoma (14.x).
- **Environnement de développement** : Xcode 15+ ou 16+ avec les outils en ligne de commande (`xcode-select --install`). - **Environnement de développement** : Xcode 26+ (ex. Xcode 26.6) ou Xcode 16+ avec les outils en ligne de commande (`xcode-select --install`).
- **SDK macOS** : macOS 15.x SDK (inclus dans Xcode). - **SDK macOS** : macOS 26.x SDK (ex. `MacOSX26.5.sdk`, inclus dans Xcode 26.6).
- **Architectures cibles** : Binaire universel `x86_64` (Hackintosh Intel/AMD) et `arm64e` (Apple Silicon). - **Architectures cibles** : Binaire universel `x86_64` (Hackintosh Intel/AMD) et `arm64e` (Apple Silicon).
--- ---
@@ -27,12 +27,13 @@ QualcommWireless/
│ ├── amss.bin # Microprogramme principal Wi-Fi │ ├── amss.bin # Microprogramme principal Wi-Fi
│ ├── board-2.bin # Données de calibration radio RF │ ├── board-2.bin # Données de calibration radio RF
│ └── m3.bin # Microprogramme d'économie d'énergie M3 │ └── m3.bin # Microprogramme d'économie d'énergie M3
├── QualcommWireless/ # Code source du pilote C++ / IOKit ├── QualcommWifi/ # Code source du pilote Wi-Fi 7 natif (IO80211Controller)
│ ├── Info.plist # Descripteur et personnalités IOKit │ ├── Firmware_WCN7850_Wifi.h/.cpp# Microprogrammes Wi-Fi intégrés
│ └── QualcommWifi.hpp/.cpp # Implémentation IO80211Controller (Tahoe Skywalk & Legacy)
├── QualcommWireless/ # Code source du pilote Bluetooth USB (IOService)
│ ├── Info.plist # Descripteur et personnalités IOKit (v1.1.0)
│ ├── Firmware_WCN7850.h # Header des microprogrammes BT intégrés │ ├── Firmware_WCN7850.h # Header des microprogrammes BT intégrés
│ ├── Firmware_WCN7850_Wifi.h # Déclarations des microprogrammes Wi-Fi │ ├── QualcommWireless.hpp/.cpp # Implémentation DFU Bluetooth & Shadow VTable
│ ├── QualcommWifi.hpp/.cpp # Implémentation du pilote Wi-Fi natif
│ ├── QualcommWireless.hpp/.cpp # Implémentation de la partie Bluetooth USB
│ └── include/ # Headers internes IOKit & 802.11 │ └── include/ # Headers internes IOKit & 802.11
└── QualcommWireless.xcodeproj # Projet Xcode configuré pour build KEXT └── QualcommWireless.xcodeproj # Projet Xcode configuré pour build KEXT
``` ```
+16 -6
View File
@@ -1,6 +1,6 @@
# Pile Wi-Fi Native macOS pour Qualcomm WCN7850 # Pile Wi-Fi Native macOS pour Qualcomm WCN7850
Ce document détaille l'implémentation de la pile Wi-Fi **native** (`IO80211Controller`) pour le chipset **Qualcomm FastConnect 7800 (WCN7850)** sous macOS Sequoia (Darwin 24). Ce document détaille l'implémentation de la pile Wi-Fi **native** (`IO80211Controller`) pour le chipset **Qualcomm FastConnect 7800 (WCN7850)** sous **macOS Tahoe (26.x / Darwin 25)** et **macOS Sequoia (15.x / Darwin 24)**.
--- ---
@@ -27,11 +27,11 @@ graph TD
CoreWLAN["CoreWLAN.framework"] CoreWLAN["CoreWLAN.framework"]
AirportD["airportd (Daemon Système)"] AirportD["airportd (Daemon Système)"]
Skywalk["Skywalk Family (Packet Pipeline)"] Skywalk["Skywalk Family (Packet Pipeline)"]
IO80211["IO80211Family (IO80211Controller / IO80211Interface)"] IO80211["IO80211Family (IO80211Controller / IO80211SkywalkInterface)"]
end end
subgraph Driver["QualcommWifi (Driver Kernel)"] subgraph Driver["QualcommWifi (Driver Kernel)"]
IoctlHandler["Gestionnaire IOCTL Apple80211 (apple80211_ioctl)"] IoctlHandler["Gestionnaire IOCTL Apple80211 (handleCardSpecific / apple80211Request)"]
ScanEngine["Moteur de Scan (Passif / Actif / Multicanal)"] ScanEngine["Moteur de Scan (Passif / Actif / Multicanal)"]
RingDMA["Gestionnaire DMA & Anneaux MHI (CR / ER / TR)"] RingDMA["Gestionnaire DMA & Anneaux MHI (CR / ER / TR)"]
FirmwarePipeline["Pipeline de Démarrage BHI / AMSS"] FirmwarePipeline["Pipeline de Démarrage BHI / AMSS"]
@@ -47,7 +47,7 @@ graph TD
CC --> AirportD CC --> AirportD
CoreWLAN --> AirportD CoreWLAN --> AirportD
AirportD -->|apple80211_ioctl| IO80211 AirportD -->|Skywalk / IO80211| IO80211
Skywalk --> IO80211 Skywalk --> IO80211
IO80211 --> IoctlHandler IO80211 --> IoctlHandler
IoctlHandler --> ScanEngine IoctlHandler --> ScanEngine
@@ -87,9 +87,18 @@ Le bus PCIe expose un espace MMIO BAR0 de 512 Ko. Or, les composants internes du
--- ---
## 4. Implémentation des IOCTLs Apple80211 ## 4. ABI `IO80211Controller` sous macOS Tahoe (Darwin 25) et IOCTLs Apple80211
Pour qu'un pilote soit reconnu par le sous-système Wi-Fi de macOS, il doit répondre aux requêtes de configuration `apple80211_ioctl` émises par `airportd` : ### 4.1. VTable Skywalk unifiée de `IO80211Controller` sous macOS Tahoe (`__IO80211_TARGET=260000`)
Sous macOS Tahoe (`IO80211Family` v1200.13.1, source `1566.5`), `IO80211Controller` (taille d'instance `0x128` = 296 octets) a achevé sa transition vers `IO80211SkywalkInterface` avec une vtable de **463 entrées** (slots `394` à `462` après `IOEthernetController`) :
- `slot 394 (0xc50)` : `isCommandProhibited(int)`
- `slot 403 (0xc98)` : `handleCardSpecific(IO80211SkywalkInterface*, unsigned long, void*, bool)` (remplace `apple80211Request` / `apple80211SkywalkRequest`)
- `slots 404..406 (0xca0..0xcb0)` : `hardwareOutputQueueDepth(void)`, `performCountryCodeOperation(IO80211CountryCodeOp)`, `dataLinkLayerAttachComplete(void)` (sans paramètre `IO80211Interface*`)
- `slots 408..415 (0xcc0..0xcf8)` : accesseurs typés purs virtuels (`getDRIVER_VERSION`, `getHARDWARE_VERSION`, `getCARD_CAPABILITIES`, `getPOWER`, `setPOWER`, `getCOUNTRY_CODE`, `setCOUNTRY_CODE`, `setGET_DEBUG_INFO`)
- `slots 424 & 432` : `getLogger(void) const` et `getFaultReporterFromDriver(void)`
### 4.2. Table des requêtes Apple80211 prises en charge
Pour qu'un pilote soit reconnu par le sous-système Wi-Fi de macOS, il répond aux requêtes `APPLE80211_IOC_*` :
| Opération IOCTL | Rôle dans le système macOS | | Opération IOCTL | Rôle dans le système macOS |
| :--- | :--- | | :--- | :--- |
@@ -114,3 +123,4 @@ La puce WCN7850 introduit les caractéristiques Wi-Fi 7 suivantes, intégrées d
- **Modulation 4096-QAM (4K-QAM)** augmentant la densité de données de 20% par rapport au 1024-QAM du Wi-Fi 6. - **Modulation 4096-QAM (4K-QAM)** augmentant la densité de données de 20% par rapport au 1024-QAM du Wi-Fi 6.
- **Multi-Link Operation (MLO)** : Capacité matérielle d'agréger ou de basculer dynamiquement entre plusieurs bandes (ex. 5 GHz + 6 GHz) pour une latence ultra-faible. - **Multi-Link Operation (MLO)** : Capacité matérielle d'agréger ou de basculer dynamiquement entre plusieurs bandes (ex. 5 GHz + 6 GHz) pour une latence ultra-faible.
- **Preamble Puncturing** : Évitement automatique des sous-canaux brouillés pour maximiser la bande passante utilisable. - **Preamble Puncturing** : Évitement automatique des sous-canaux brouillés pour maximiser la bande passante utilisable.