22// IntelBTPatcher.cpp
33// IntelBTPatcher
44//
5- // Created by qcwap on 2021/2/8.
5+ // Created by zxystd <[email protected] > on 2021/2/8.66//
77
88#include < Headers/kern_api.hpp>
@@ -37,7 +37,7 @@ PluginConfiguration ADDPR(config) {
3737 bootargBeta,
3838 arrsize (bootargBeta),
3939 KernelVersion::MountainLion,
40- KernelVersion::Monterey ,
40+ KernelVersion::Ventura ,
4141 []() {
4242 ibtPatcher.init ();
4343 }
@@ -54,14 +54,37 @@ static KernelPatcher::KextInfo IntelBTPatcher_IOBluetoothInfo {
5454 KernelPatcher::KextInfo::Unloaded
5555};
5656
57+ static const char *IntelBTPatcher_IOUSBHostFamily[] {
58+ " /System/Library/Extensions/IOUSBHostFamily.kext/Contents/MacOS/IOUSBHostFamily" };
59+
60+ static KernelPatcher::KextInfo IntelBTPatcher_IOUsbHostInfo {
61+ " com.apple.iokit.IOUSBHostFamily" ,
62+ IntelBTPatcher_IOUSBHostFamily,
63+ 1 ,
64+ {true , true },
65+ {},
66+ KernelPatcher::KextInfo::Unloaded
67+ };
68+
69+ void *CIntelBTPatcher::_hookPipeInstance = nullptr ;
70+ AsyncOwnerData *CIntelBTPatcher::_interruptPipeAsyncOwner = nullptr ;
71+ bool CIntelBTPatcher::_randomAddressInit = false ;
72+
5773bool CIntelBTPatcher::init ()
5874{
5975 DBGLOG (DRV_NAME, " %s" , __PRETTY_FUNCTION__);
6076 callbackIBTPatcher = this ;
61- lilu.onKextLoadForce (&IntelBTPatcher_IOBluetoothInfo, 1 ,
62- [](void *user, KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) {
63- callbackIBTPatcher->processKext (patcher, index, address, size);
64- }, this );
77+ if (getKernelVersion () < KernelVersion::Monterey) {
78+ lilu.onKextLoadForce (&IntelBTPatcher_IOBluetoothInfo, 1 ,
79+ [](void *user, KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) {
80+ callbackIBTPatcher->processKext (patcher, index, address, size);
81+ }, this );
82+ } else {
83+ lilu.onKextLoadForce (&IntelBTPatcher_IOUsbHostInfo, 1 ,
84+ [](void *user, KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) {
85+ callbackIBTPatcher->processKext (patcher, index, address, size);
86+ }, this );
87+ }
6588 return true ;
6689}
6790
@@ -91,15 +114,224 @@ void CIntelBTPatcher::processKext(KernelPatcher &patcher, size_t index, mach_vm_
91114 }
92115
93116 }
117+ } else {
118+ if (IntelBTPatcher_IOUsbHostInfo.loadIndex == index) {
119+ SYSLOG (DRV_NAME, " %s" , IntelBTPatcher_IOUsbHostInfo.id );
120+
121+ KernelPatcher::RouteRequest hostDeviceRequest {
122+ " __ZN15IOUSBHostDevice13deviceRequestEP9IOServiceRN11StandardUSB13DeviceRequestEPvP18IOMemoryDescriptorRjP19IOUSBHostCompletionj" ,
123+ newHostDeviceRequest,
124+ oldHostDeviceRequest
125+ };
126+ patcher.routeMultiple (index, &hostDeviceRequest, 1 , address, size);
127+ if (patcher.getError () == KernelPatcher::Error::NoError) {
128+ SYSLOG (DRV_NAME, " routed %s" , hostDeviceRequest.symbol );
129+ } else {
130+ SYSLOG (DRV_NAME, " failed to resolve %s, error = %d" , hostDeviceRequest.symbol , patcher.getError ());
131+ patcher.clearError ();
132+ }
133+
134+ KernelPatcher::RouteRequest asyncIORequest {
135+ " __ZN13IOUSBHostPipe2ioEP18IOMemoryDescriptorjP19IOUSBHostCompletionj" ,
136+ newAsyncIO,
137+ oldAsyncIO
138+ };
139+ patcher.routeMultiple (index, &asyncIORequest, 1 , address, size);
140+ if (patcher.getError () == KernelPatcher::Error::NoError) {
141+ SYSLOG (DRV_NAME, " routed %s" , asyncIORequest.symbol );
142+ } else {
143+ SYSLOG (DRV_NAME, " failed to resolve %s, error = %d" , asyncIORequest.symbol , patcher.getError ());
144+ patcher.clearError ();
145+ }
146+
147+ KernelPatcher::RouteRequest initPipeRequest {
148+ " __ZN13IOUSBHostPipe28initWithDescriptorsAndOwnersEPKN11StandardUSB18EndpointDescriptorEPKNS0_37SuperSpeedEndpointCompanionDescriptorEP22AppleUSBHostControllerP15IOUSBHostDeviceP18IOUSBHostInterfaceht" ,
149+ newInitPipe,
150+ oldInitPipe
151+ };
152+ patcher.routeMultiple (index, &initPipeRequest, 1 , address, size);
153+ if (patcher.getError () == KernelPatcher::Error::NoError) {
154+ SYSLOG (DRV_NAME, " routed %s" , initPipeRequest.symbol );
155+ } else {
156+ SYSLOG (DRV_NAME, " failed to resolve %s, error = %d" , initPipeRequest.symbol , patcher.getError ());
157+ patcher.clearError ();
158+ }
159+
160+ KernelPatcher::RouteRequest syncIORequest {
161+ " __ZN13IOUSBHostPipe2ioEP18IOMemoryDescriptorjRjj" ,
162+ newSyncIO,
163+ oldSyncIO
164+ };
165+ patcher.routeMultiple (index, &syncIORequest, 1 , address, size);
166+ if (patcher.getError () == KernelPatcher::Error::NoError) {
167+ SYSLOG (DRV_NAME, " routed %s" , syncIORequest.symbol );
168+ } else {
169+ SYSLOG (DRV_NAME, " failed to resolve %s, error = %d" , syncIORequest.symbol , patcher.getError ());
170+ patcher.clearError ();
171+ }
172+ }
94173 }
95174}
96175
176+ #pragma mark - For Bigsur-, patch unhandled 0x2019 opcode
177+
178+ #define HCI_OP_LE_START_ENCRYPTION 0x2019
179+
97180IOReturn CIntelBTPatcher::newFindQueueRequest (void *that, unsigned short arg1, void *addr, unsigned short arg2, bool arg3, void **hciRequestPtr)
98181{
99182 IOReturn ret = FunctionCast (newFindQueueRequest, callbackIBTPatcher->oldFindQueueRequest )(that, arg1, addr, arg2, arg3, hciRequestPtr);
100- if (ret != 0 && arg1 == 0x2019 ) {
183+ if (ret != 0 && arg1 == HCI_OP_LE_START_ENCRYPTION ) {
101184 ret = FunctionCast (newFindQueueRequest, callbackIBTPatcher->oldFindQueueRequest )(that, arg1, addr, 0xffff , arg3, hciRequestPtr);
102185 DBGLOG (DRV_NAME, " %s ret: %d arg1: 0x%04x arg2: 0x%04x arg3: %d ptr: %p" , __FUNCTION__, ret, arg1, arg2, arg3, *hciRequestPtr);
103186 }
104187 return ret;
105188}
189+
190+ #pragma mark - For Monterey+ patch for intercept HCI REQ and RESP
191+
192+ StandardUSB::DeviceRequest randomAddressRequest;
193+ // Hardcoded Random Address HCI Command
194+ const uint8_t randomAddressHci[9 ] = {0x05 , 0x20 , 0x06 , 0x94 , 0x50 , 0x64 , 0xD0 , 0x78 , 0x6B };
195+ IOBufferMemoryDescriptor *writeHCIDescriptor = nullptr ;
196+
197+ #define MAX_HCI_BUF_LEN 255
198+ #define HCI_OP_RESET 0x0c03
199+ #define HCI_OP_LE_SET_SCAN_PARAM 0x200B
200+ #define HCI_OP_LE_SET_SCAN_ENABLE 0x200C
201+
202+ IOReturn CIntelBTPatcher::newHostDeviceRequest (void *that, IOService *provider, StandardUSB::DeviceRequest &request, void *data, IOMemoryDescriptor *descriptor, unsigned int &length, IOUSBHostCompletion *completion, unsigned int timeout)
203+ {
204+ HciCommandHdr *hdr = nullptr ;
205+ uint32_t hdrLen = 0 ;
206+ char hciBuf[MAX_HCI_BUF_LEN] = {0 };
207+
208+ if (data == nullptr ) {
209+ if (descriptor != nullptr && descriptor->getLength () > 0 ) {
210+ descriptor->readBytes (0 , hciBuf, min (descriptor->getLength (), MAX_HCI_BUF_LEN));
211+ hdrLen = (uint32_t )min (descriptor->getLength (), MAX_HCI_BUF_LEN);
212+ }
213+ hdr = (HciCommandHdr *)hciBuf;
214+ if (hdr->opcode == HCI_OP_LE_SET_SCAN_PARAM) {
215+ if (!_randomAddressInit) {
216+ randomAddressRequest.bmRequestType = makeDeviceRequestbmRequestType (kRequestDirectionOut , kRequestTypeClass , kRequestRecipientInterface );
217+ randomAddressRequest.bRequest = 0xE0 ;
218+ randomAddressRequest.wIndex = 0 ;
219+ randomAddressRequest.wValue = 0 ;
220+ randomAddressRequest.wLength = 9 ;
221+ length = 9 ;
222+ if (writeHCIDescriptor == nullptr )
223+ writeHCIDescriptor = IOBufferMemoryDescriptor::withBytes (randomAddressHci, 9 , kIODirectionOut );
224+ writeHCIDescriptor->prepare (kIODirectionOut );
225+ IOReturn ret = FunctionCast (newHostDeviceRequest, callbackIBTPatcher->oldHostDeviceRequest )(that, provider, randomAddressRequest, nullptr , writeHCIDescriptor, length, nullptr , timeout);
226+ writeHCIDescriptor->complete ();
227+ const char *randAddressDump = _hexDumpHCIData ((uint8_t *)randomAddressHci, 9 );
228+ if (randAddressDump) {
229+ SYSLOG (DRV_NAME, " [PATCH] Sending Random Address HCI %lld %s" , ret, randAddressDump);
230+ IOFree ((void *)randAddressDump, 9 * 3 + 1 );
231+ }
232+ _randomAddressInit = true ;
233+ SYSLOG (DRV_NAME, " [PATCH] Resend LE SCAN PARAM HCI %lld" , ret);
234+ }
235+ }
236+ #if 0 // We don't need to fake Random address request to Public address, and it is not really fix the issue with Intel fatal firmware error after HCI_OP_LE_SET_SCAN_ENABLE.
237+ else if (hdr->opcode == HCI_OP_LE_SET_SCAN_ENABLE) {
238+ hdr->data[5] = 0x00;
239+ SYSLOG(DRV_NAME, "[FAKE REQ]: RANDOM->PUBLIC done\n");
240+ }
241+ #endif
242+ } else {
243+ hdr = (HciCommandHdr *)data;
244+ hdrLen = request.wLength - 3 ;
245+ }
246+ if (hdr) {
247+ // HCI reset, we need to send Random address again
248+ if (hdr->opcode == HCI_OP_RESET)
249+ _randomAddressInit = false ;
250+ #if DEBUG
251+ DBGLOG (DRV_NAME, " [%s] bRequest: 0x%x direction: %s type: %s recipient: %s wValue: 0x%02x wIndex: 0x%02x opcode: 0x%04x len: %d length: %d async: %d" , provider->getName (), request.bRequest , requestDirectionNames[(request.bmRequestType & kDeviceRequestDirectionMask ) >> kDeviceRequestDirectionPhase ], requestRecipientNames[(request.bmRequestType & kDeviceRequestRecipientMask ) >> kDeviceRequestRecipientPhase ], requestTypeNames[(request.bmRequestType & kDeviceRequestTypeMask ) >> kDeviceRequestTypePhase ], request.wValue , request.wIndex , hdr->opcode , hdr->len , request.wLength , completion != nullptr );
252+ if (hdrLen) {
253+ const char *dump = _hexDumpHCIData ((uint8_t *)hdr, hdrLen);
254+ if (dump) {
255+ DBGLOG (DRV_NAME, " [Request]: %s" , dump);
256+ IOFree ((void *)dump, hdrLen * 3 + 1 );
257+ }
258+ }
259+ #endif
260+ }
261+ return FunctionCast (newHostDeviceRequest, callbackIBTPatcher->oldHostDeviceRequest )(that, provider, request, data, descriptor, length, completion, timeout);
262+ }
263+
264+ // Succeeded HCI command result of HCI_OP_LE_SET_SCAN_ENABLE, on Monterey+ this will return status 0x12 if we don't set the Random address before
265+ const uint8_t fakeLEScanEnableResp[6 ] = {0x0E , 0x04 , 0x02 , 0x0C , 0x20 , 0x00 };
266+
267+ static void asyncIOCompletion (void * owner, void * parameter, IOReturn status, uint32_t bytesTransferred)
268+ {
269+ AsyncOwnerData *asyncOwner = (AsyncOwnerData *)owner;
270+ IOMemoryDescriptor* dataBuffer = asyncOwner->dataBuffer ;
271+ DBGLOG (DRV_NAME, " [COMPLETE] status: %d bytesTransferred: %d" , status, bytesTransferred);
272+ if (dataBuffer && bytesTransferred) {
273+ void *buffer = IOMalloc (bytesTransferred);
274+ dataBuffer->readBytes (0 , buffer, bytesTransferred);
275+ const char *dump = _hexDumpHCIData ((uint8_t *)buffer, bytesTransferred);
276+ if (dump) {
277+ DBGLOG (DRV_NAME, " [Response]: %s" , dump);
278+ IOFree ((void *)dump, bytesTransferred * 3 + 1 );
279+ }
280+ HciResponse *resp = (HciResponse *)buffer;
281+ if (resp->opcode == 0x200C && resp->data [0 ]) {
282+ SYSLOG (DRV_NAME, " [FAKE RESP]: done" );
283+ dataBuffer->writeBytes (0 , fakeLEScanEnableResp, 6 );
284+ }
285+ IOFree (buffer, bytesTransferred);
286+ }
287+ if (asyncOwner->action )
288+ asyncOwner->action (asyncOwner->owner , parameter, status, bytesTransferred);
289+ }
290+
291+ IOReturn CIntelBTPatcher::
292+ newAsyncIO (void *that, IOMemoryDescriptor* dataBuffer, uint32_t dataBufferLength, IOUSBHostCompletion* completion, uint32_t completionTimeoutMs)
293+ {
294+ IOReturn ret = kIOReturnSuccess ;
295+ if (that == _hookPipeInstance && completion) {
296+ _interruptPipeAsyncOwner->action = completion->action ;
297+ _interruptPipeAsyncOwner->owner = completion->owner ;
298+ _interruptPipeAsyncOwner->dataBuffer = dataBuffer;
299+ completion->action = asyncIOCompletion;
300+ completion->owner = _interruptPipeAsyncOwner;
301+ ret = FunctionCast (newAsyncIO, callbackIBTPatcher->oldAsyncIO )(that, dataBuffer, dataBufferLength, completion, completionTimeoutMs);
302+ if (ret != kIOReturnSuccess )
303+ SYSLOG (DRV_NAME, " %s failed ret: %lld" , __FUNCTION__, ret);
304+ return ret;
305+ }
306+ return FunctionCast (newAsyncIO, callbackIBTPatcher->oldAsyncIO )(that, dataBuffer, dataBufferLength, completion, completionTimeoutMs);
307+ }
308+
309+ IOReturn CIntelBTPatcher::
310+ newSyncIO (void *that, IOMemoryDescriptor *dataBuffer, uint32_t dataBufferLength, uint32_t &bytesTransferred, uint32_t completionTimeoutMs)
311+ {
312+ return FunctionCast (newSyncIO, callbackIBTPatcher->oldSyncIO )(that, dataBuffer, dataBufferLength, bytesTransferred, completionTimeoutMs);
313+ }
314+
315+ #define VENDOR_USB_INTEL 0x8087
316+
317+ int CIntelBTPatcher::
318+ newInitPipe (void *that, StandardUSB::EndpointDescriptor const *descriptor, StandardUSB::SuperSpeedEndpointCompanionDescriptor const *superDescriptor, AppleUSBHostController *controller, IOUSBHostDevice *device, IOUSBHostInterface *interface, unsigned char a7, unsigned short a8)
319+ {
320+ int ret = FunctionCast (newInitPipe, callbackIBTPatcher->oldInitPipe )(that, descriptor, superDescriptor, controller, device, interface, a7, a8);
321+ if (device) {
322+ const StandardUSB::DeviceDescriptor *deviceDescriptor = device->getDeviceDescriptor ();
323+ if (deviceDescriptor &&
324+ deviceDescriptor->idVendor == VENDOR_USB_INTEL) {
325+ uint8_t epType = StandardUSB::getEndpointType (descriptor);
326+ DBGLOG (DRV_NAME, " GOT YOU Intel bluetooth pid: %d ep type: %d" , deviceDescriptor->iProduct , epType);
327+ if (epType == kIOUSBEndpointTypeInterrupt ) {
328+ SYSLOG (DRV_NAME, " GOT YOU Interrupt PIPE" );
329+ CIntelBTPatcher::_hookPipeInstance = that;
330+ if (!CIntelBTPatcher::_interruptPipeAsyncOwner)
331+ CIntelBTPatcher::_interruptPipeAsyncOwner = new AsyncOwnerData;
332+ CIntelBTPatcher::_randomAddressInit = false ;
333+ }
334+ }
335+ }
336+ return ret;
337+ }
0 commit comments