void SoftU2FUserClient::frameReceivedGated(IOMemoryDescriptor *report) { IOLog("%s[%p]::%s(%p)\n", getName(), this, __FUNCTION__, report); IOMemoryMap *reportMap = nullptr; if (isInactive()) return; if (report->prepare() != kIOReturnSuccess) return; reportMap = report->map(); // Notify userland that we got a report. if (_notifyRef && reportMap->getLength() == sizeof(U2FHID_FRAME)) { io_user_reference_t *args = (io_user_reference_t *)reportMap->getAddress(); sendAsyncResult64(*_notifyRef, kIOReturnSuccess, args, sizeof(U2FHID_FRAME) / sizeof(io_user_reference_t)); } reportMap->release(); report->complete(); }
IOReturn SamplePCIUserClientClassName::method2( SampleStructForMethod2 * structIn, SampleResultsForMethod2 * structOut, IOByteCount inputSize, IOByteCount * outputSize ) { IOReturn err; IOMemoryDescriptor * memDesc = 0; UInt32 param1 = structIn->parameter1; uint64_t clientAddr = structIn->data_pointer; uint64_t size = structIn->data_length; // Rosetta if (fCrossEndian) { param1 = OSSwapInt32(param1); } IOLog("SamplePCIUserClient::method2(" UInt32_x_FORMAT ")\n", param1); IOLog( "fClientShared->string == \"%s\"\n", fClientShared->string ); structOut->results1 = 0x87654321; // Rosetta if (fCrossEndian) { structOut->results1 = OSSwapInt64(structOut->results1); clientAddr = OSSwapInt64(clientAddr); size = OSSwapInt64(size); } do { #if defined(__ppc__) && (MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4) // construct a memory descriptor for the out of line client memory // old 32 bit API - this will fail and log a backtrace if the task is 64 bit IOLog("The Pre-Leopard way to construct a memory descriptor\n"); memDesc = IOMemoryDescriptor::withAddress( (vm_address_t) clientAddr, (IOByteCount) size, kIODirectionNone, fTask ); if (memDesc == NULL) { IOLog("IOMemoryDescriptor::withAddress failed\n"); err = kIOReturnVMError; continue; } #else // 64 bit API - works on all tasks, whether 64 bit or 32 bit IOLog("The Leopard and later way to construct a memory descriptor\n"); memDesc = IOMemoryDescriptor::withAddressRange( clientAddr, size, kIODirectionNone, fTask ); if (memDesc == NULL) { IOLog("IOMemoryDescriptor::withAddresswithAddressRange failed\n"); err = kIOReturnVMError; continue; } #endif // Wire it and make sure we can write it err = memDesc->prepare( kIODirectionOutIn ); if (kIOReturnSuccess != err) { IOLog("IOMemoryDescriptor::prepare failed(0x%08x)\n", err); continue; } // Generate a DMA list for the client memory err = fDriver->generateDMAAddresses(memDesc); // Other methods to access client memory: // readBytes/writeBytes allow programmed I/O to/from an offset in the buffer char pioBuffer[ 200 ]; memDesc->readBytes(32, &pioBuffer, sizeof(pioBuffer)); IOLog("readBytes: \"%s\"\n", pioBuffer); // map() will create a mapping in the kernel address space. IOMemoryMap* memMap = memDesc->map(); if (memMap) { char* address = (char *) memMap->getVirtualAddress(); IOLog("kernel mapped: \"%s\"\n", address + 32); memMap->release(); } else { IOLog("memDesc map(kernel) failed\n"); } // this map() will create a mapping in the users (the client of this IOUserClient) address space. #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 memMap = memDesc->map(fTask, 0, kIOMapAnywhere); #else memMap = memDesc->createMappingInTask(fTask, 0, kIOMapAnywhere); #endif if (memMap) { #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 IOLog("The pre-Leopard way to construct a memory descriptor\n"); // old 32 bit API - this will truncate and log a backtrace if the task is 64 bit IOVirtualAddress address32 = memMap->getVirtualAddress(); IOLog("user32 mapped: " VirtAddr_FORMAT "\n", address32); #else IOLog("The Leopard and later way to construct a memory descriptor\n"); // new 64 bit API - same for 32 bit and 64 bit client tasks mach_vm_address_t address64 = memMap->getAddress(); IOLog("user64 mapped: 0x%016llx\n", address64); memMap->release(); #endif } else { IOLog("memDesc map(user) failed\n"); } // Done with the I/O now. memDesc->complete( kIODirectionOutIn ); } while ( false ); if (memDesc) memDesc->release(); return err; }
IOReturn org_pqrs_driver_KeyRemap4MacBook_UserClient_kext::callback_synchronized_communication(const BridgeUserClientStruct* inputdata, uint64_t* outputdata) { IOReturn result = kIOReturnSuccess; IOMemoryDescriptor* memorydescriptor = NULL; if (! inputdata || ! outputdata) { result = kIOReturnBadArgument; IOLOG_ERROR("UserClient_kext::callback_synchronized_communication kIOReturnBadArgument\n"); goto finish; } if (provider_ == NULL || isInactive()) { // Return an error if we don't have a provider. This could happen if the user process // called callback_synchronized_communication without calling IOServiceOpen first. // Or, the user client could be in the process of being terminated and is thus inactive. result = kIOReturnNotAttached; IOLOG_ERROR("UserClient_kext::callback_synchronized_communication kIOReturnNotAttached\n"); goto finish; } if (! provider_->isOpen(this)) { // Return an error if we do not have the driver open. This could happen if the user process // did not call callback_open before calling this function. result = kIOReturnNotOpen; IOLOG_ERROR("UserClient_kext::callback_synchronized_communication kIOReturnNotOpen\n"); goto finish; } memorydescriptor = IOMemoryDescriptor::withAddressRange(inputdata->data, inputdata->size, kIODirectionNone, task_); if (! memorydescriptor) { result = kIOReturnVMError; IOLOG_ERROR("UserClient_kext::callback_synchronized_communication kIOReturnVMError\n"); goto finish; } // wire it and make sure we can write it result = memorydescriptor->prepare(kIODirectionOutIn); if (kIOReturnSuccess != result) { IOLOG_ERROR("UserClient_kext::callback_synchronized_communication IOMemoryDescriptor::prepare failed(0x%x)\n", result); goto finish; } { // this map() will create a mapping in the users (the client of this IOUserClient) address space. IOMemoryMap* memorymap = memorydescriptor->map(); if (! memorymap) { result = kIOReturnVMError; IOLOG_ERROR("UserClient_kext::callback_synchronized_communication IOMemoryDescriptor::map failed\n"); } else { mach_vm_address_t address = memorymap->getAddress(); handle_synchronized_communication(inputdata->type, inputdata->option, address, inputdata->size, outputdata); memorymap->release(); } } // Done with the I/O now. memorydescriptor->complete(kIODirectionOutIn); finish: if (memorydescriptor) { memorydescriptor->release(); } return result; }