示例#1
0
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;
}