IOReturn SoftU2FUserClient::sendFrame(U2FHID_FRAME *frame, size_t frameSize) { SoftU2FDevice *device = nullptr; IOMemoryDescriptor *report = nullptr; if (isInactive()) return kIOReturnOffline; if (frameSize != HID_RPT_SIZE) return kIOReturnBadArgument; device = OSDynamicCast(SoftU2FDevice, getClient()); if (!device) return kIOReturnNotAttached; report = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, 0, HID_RPT_SIZE); if (!report) return kIOReturnNoResources; report->writeBytes(0, frame, frameSize); if (device->handleReport(report) != kIOReturnSuccess) { report->release(); return kIOReturnError; } report->release(); return kIOReturnSuccess; }
/* * GetSenseInformation * * Attempt to get SCSI sense information either from the Auto sense * mechanism or by querying manually. */ void IOSCSITape::GetSense(SCSITaskIdentifier request) { SCSI_Sense_Data senseBuffer = { 0 }; bool validSense = false; SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE; IOMemoryDescriptor *bufferDesc = IOMemoryDescriptor::withAddress((void *)&senseBuffer, sizeof(senseBuffer), kIODirectionIn); if (GetTaskStatus(request) == kSCSITaskStatus_CHECK_CONDITION) { validSense = GetAutoSenseData(request, &senseBuffer); if (validSense == false) { if (REQUEST_SENSE(request, bufferDesc, kSenseDefaultSize, 0) == true) serviceResponse = SendCommand(request, kTenSecondTimeoutInMS); if (serviceResponse == kSCSIServiceResponse_TASK_COMPLETE) validSense = true; } if (validSense == true) InterpretSense(&senseBuffer); else STATUS_LOG("invalid or unretrievable SCSI SENSE"); } bufferDesc->release(); }
void IOHIDTestDriver::issueFakeReport() { UInt8 report[][7] = { { 0x44, 0x3B, 0x49, 0x43, 0x80, 0x00, 0x00 }, { 0x44, 0x3B, 0x49, 0x43, 0x00, 0x00, 0x00 }, { 0x44, 0x3B, 0x49, 0x43, 0x20, 0x00, 0x00 }, { 0x44, 0x3B, 0x49, 0x43, 0x00, 0x00, 0x00 }, { 0x44, 0x3B, 0x49, 0x43, 0x10, 0x00, 0x00 }, { 0x44, 0x3B, 0x49, 0x43, 0x00, 0x00, 0x00 }, { 0x44, 0x3B, 0x49, 0x43, 0x00, 0x80, 0x00 }, { 0x44, 0x3B, 0x49, 0x43, 0x00, 0x00, 0x00 }, { 0x44, 0x36, 0x49, 0x43, 0x00, 0x00, 0x00 }, { 0x48, 0x19, 0x49, 0x43, 0x00, 0x00, 0x00 }, { 0x48, 0x15, 0x49, 0x43, 0x00, 0x00, 0x00 }, { 0x4C, 0x11, 0x49, 0x43, 0x00, 0x00, 0x00 } }; const UInt32 reportCount = sizeof(report)/sizeof(report[0]); static UInt32 reportIndex = 0; IOMemoryDescriptor * desc = IOMemoryDescriptor::withAddress( report[reportIndex], sizeof(report[0]), kIODirectionNone ); if (desc) { handleReport( desc ); desc->release(); } if ( ++reportIndex >= reportCount ) reportIndex = 0; }
// Received a normal HID update from the device void WirelessHIDDevice::receivedHIDupdate(unsigned char *data, int length) { IOReturn err; IOMemoryDescriptor *report; report = IOMemoryDescriptor::withAddress(data, length, kIODirectionNone); err = handleReport(report, kIOHIDReportTypeInput); report->release(); if (err != kIOReturnSuccess) IOLog("handleReport return: 0x%.8x\n", err); }
// Handle new data from the device void WirelessHIDDevice::receivedData(void) { IOMemoryDescriptor *data; WirelessDevice *device = OSDynamicCast(WirelessDevice, getProvider()); if (device == NULL) return; while ((data = device->NextPacket()) != NULL) { receivedMessage(data); data->release(); } }
IOReturn IOSCSITape::GetDeviceBlockLimits(void) { SCSITaskIdentifier task = NULL; IOReturn status = kIOReturnError; UInt8 blockLimitsData[6] = { 0 }; SCSITaskStatus taskStatus = kSCSITaskStatus_DeliveryFailure; IOMemoryDescriptor * dataBuffer = NULL; dataBuffer = IOMemoryDescriptor::withAddress(&blockLimitsData, sizeof(blockLimitsData), kIODirectionIn); require ((dataBuffer != 0), ErrorExit); task = GetSCSITask(); require ((task != 0), ErrorExit); if (READ_BLOCK_LIMITS(task, dataBuffer, 0x00) == true) taskStatus = DoSCSICommand(task, SCSI_NOMOTION_TIMEOUT); if (taskStatus == kSCSITaskStatus_GOOD) { // blkgran = blockLimitsData[0] & 0x1F; blkmin = (blockLimitsData[4] << 8) | blockLimitsData[5]; blkmax = (blockLimitsData[1] << 16) | (blockLimitsData[2] << 8) | blockLimitsData[3]; STATUS_LOG("min/max block size: %d/%d", blkmin, blkmax); status = kIOReturnSuccess; } ReleaseSCSITask(task); dataBuffer->release(); ErrorExit: return status; }
IOReturn XboxOneControllerDriver::sendHello() { IOReturn ior = kIOReturnSuccess; IOMemoryDescriptor* hello = nullptr; IOByteCount bytesWritten = 0; constexpr size_t helloSize = sizeof XboxOneControllerHelloMessage; if (_interruptPipe == nullptr) // paranoid check { IO_LOG_DEBUG("_interruptPipe is null"); ior = kIOReturnInternalError; goto cleanup; } // Create the hello message that we're about to send to the controller. hello = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, 0, helloSize); if (hello == nullptr) { IO_LOG_DEBUG("Could not allocate buffer for hello message."); ior = kIOReturnNoMemory; goto cleanup; } bytesWritten = hello->writeBytes(0, XboxOneControllerHelloMessage, helloSize); if (bytesWritten != helloSize) // paranoid check { ior = kIOReturnOverrun; goto cleanup; } // Now send the message ior = _interruptPipe->Write(hello, 0, 0, hello->getLength()); if (ior != kIOReturnSuccess) { IO_LOG_DEBUG("Couldn't send hello message to controller: %08x\n", ior); goto cleanup; } cleanup: if (hello != nullptr) { hello->release(); } return ior; }
static inline bool hpetIsInvalid() { hpetInfo_t hpetInfo; hpet_get_info(&hpetInfo); // The AppleIntelCPUPowerManagement will crash if rcbaArea and/or HPET is NULL // Ordinarily this can never happen but modified xnu can allow for this. if(hpetInfo.rcbaArea == 0) { IOLog("Forcing takeover of AppleIntelCPUPowerManagement resource due to lack of RCBA (no LPC?)\n"); return true; } // Another case is that the LPC exists but the HPET isn't really valid. // That is to say that virtual hardware provides enough to get past xnu startup // but not enough to really make the HPET work. uint32_t hptc = *(uint32_t*)(hpetInfo.rcbaArea + 0x3404); if(!(hptc & hptcAE)) { IOLog("Forcing takeover of AppleIntelCPUPowerManagement resource because HPET is not enabled\n"); return true; } // Use the RCBA's HPTC to determine which of the four possible HPET physical addresses is used uint32_t hpetAreap = hpetAddr | ((hptc & 3) << 12); IOMemoryDescriptor *hpetMemDesc = IOMemoryDescriptor::withPhysicalAddress(hpetAreap, sizeof(hpetReg_t), kIODirectionIn); // grab the GCAP_ID (note offset is actually 0) uint64_t GCAP_ID; hpetMemDesc->readBytes(offsetof(hpetReg_t, GCAP_ID), &GCAP_ID, sizeof(GCAP_ID)); // We're done with the memory descriptor now, so release it hpetMemDesc->release(); hpetMemDesc = NULL; // Extract the VENDOR_ID_CAP field from the GCAP_ID and test it uint16_t vendorId = bitfield(GCAP_ID, 31, 16); if( (vendorId == 0x0000) || (vendorId == 0xffff)) { IOLog("Forcing takeover of AppleIntelCPUPowerManagement resource due to bad HPET VENDOR_ID_CAP\n"); return true; } else if(vendorId != 0x8086) { IOLog("WARNING: HPET is not Intel. Going ahead and allowing AppleIntelCPUPowerManagement to start but beware it may behave strangely\n"); } return false; }
int st_readwrite(dev_t dev, struct uio *uio, int ioflag) { IOSCSITape *st = IOSCSITape::devices[minor(dev)]; IOMemoryDescriptor *dataBuffer = IOMemoryDescriptorFromUIO(uio); int status = ENOSYS; IOReturn opStatus = kIOReturnError; int lastRealizedBytes = 0; if (dataBuffer == 0) return ENOMEM; dataBuffer->prepare(); opStatus = st->ReadWrite(dataBuffer, &lastRealizedBytes); dataBuffer->complete(); dataBuffer->release(); if (opStatus == kIOReturnSuccess) { uio_setresid(uio, uio_resid(uio) - lastRealizedBytes); if (st->blkno != -1) { if (st->IsFixedBlockSize()) st->blkno += (lastRealizedBytes / st->blksize); else st->blkno++; } status = KERN_SUCCESS; } else if (st->sense_flags & SENSE_FILEMARK) { if (st->fileno != -1) { st->fileno++; st->blkno = 0; } status = KERN_SUCCESS; } return status; }
IOReturn IOSCSITape::SetDeviceDetails(SCSI_ModeSense_Default *modeData) { IOReturn status = kIOReturnError; IOMemoryDescriptor * dataBuffer = NULL; SCSITaskIdentifier task = NULL; SCSITaskStatus taskStatus = kSCSITaskStatus_DeviceNotResponding; dataBuffer = IOMemoryDescriptor::withAddress(modeData, sizeof(SCSI_ModeSense_Default), kIODirectionOut); require((dataBuffer != 0), ErrorExit); task = GetSCSITask(); require((task != 0), ErrorExit); if (MODE_SELECT_6(task, dataBuffer, 0x0, // PF 0x0, // SP sizeof(SCSI_ModeSense_Default), 0x00) == true) { taskStatus = DoSCSICommand(task, SCSI_NOMOTION_TIMEOUT); } if (taskStatus == kSCSITaskStatus_GOOD) { status = kIOReturnSuccess; } ReleaseSCSITask(task); dataBuffer->release(); ErrorExit: return status; }
IOReturn XboxOneControllerDriver::newReportDescriptor(IOMemoryDescriptor **descriptor) const { if (descriptor == nullptr) { return kIOReturnBadArgument; } constexpr size_t descriptorSize = sizeof XboxOneControllerReportDescriptor; IOMemoryDescriptor* buffer = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, 0, descriptorSize); if (buffer == nullptr) { return kIOReturnNoMemory; } IOByteCount written = buffer->writeBytes(0, XboxOneControllerReportDescriptor, descriptorSize); if (written != sizeof XboxOneControllerReportDescriptor) // paranoid check { buffer->release(); return kIOReturnNoSpace; } *descriptor = buffer; return kIOReturnSuccess; }
IOReturn IrDAUserClient::getIrDALog(void *pIn, void *pOut, IOByteCount inputSize, IOByteCount *outPutSize) { #if (hasTracing > 0) IOMemoryDescriptor *md; // make a memory descriptor for the client's big buffer unsigned char *input = (unsigned char *)pIn; mach_vm_address_t bigaddr; IOByteCount biglen; IrDALogInfo *info; require(inputSize == 9, Fail); require(outPutSize, Fail); require(*outPutSize == sizeof(IrDALogInfo), Fail); //bigaddr = input[1] << 24 | input[2] << 16 | input[3] << 8 | input[4]; //biglen = input[5] << 24 | input[6] << 16 | input[7] << 8 | input[8]; bcopy(&input[1], &bigaddr, sizeof(bigaddr)); bcopy(&input[5], &biglen, sizeof(biglen)); //IOLog("biglen is %d\n", biglen); // create and init the memory descriptor //md = IOMemoryDescriptor::withAddress(bigaddr, biglen, kIODirectionOutIn, fTask); // REVIEW direction //use withAddressRange() and prepare() instead md = IOMemoryDescriptor::withAddressRange(bigaddr, biglen, kIODirectionOutIn, fTask); // REVIEW direction md->prepare(kIODirectionOutIn); require(md, Fail); info = IrDALogGetInfo(); // get the info block //ELG(info->hdr, info->hdrSize, 'irda', "info hdr"); //ELG(info->eventLog, info->eventLogSize, 'irda', "info events"); //ELG(info->msgBuffer, info->msgBufferSize, 'irda', "info msg buf"); bcopy(info, pOut, sizeof(*info)); // copy the info record back to the client *outPutSize = sizeof(*info); // set the output size (nop, it already is) // copy the buffer over now if there is room if (biglen >= info->hdrSize + info->eventLogSize + info->msgBufferSize) { IOByteCount ct; IOReturn rc; rc = md->prepare(kIODirectionNone); if (rc) {ELG(-1, rc, 'irda', "prepare failed"); } ct = md->writeBytes(0, info->hdr, info->hdrSize); if (ct != info->hdrSize) ELG(-1, rc, 'irda', "write of hdr failed"); ct = md->writeBytes(info->hdrSize, info->eventLog, info->eventLogSize); if (ct != info->eventLogSize) ELG(-1, rc, 'irda', "write of events failed"); ct = md->writeBytes(info->hdrSize+info->eventLogSize, info->msgBuffer, info->msgBufferSize); if (ct != info->msgBufferSize) ELG(-1, rc, 'irda', "write of msgs failed"); ELG(0, info->hdrSize+info->eventLogSize, 'irda', "wrote msgs at offset"); rc = md->complete(kIODirectionNone); if (!rc) { ELG(0, 0, 'irda', "complete worked"); } else { ELG(-1, rc, 'irda', "complete failed"); } // todo check return code of above before resetting the buffer IrDALogReset(); // reset the buffer now } md->release(); // free it return kIOReturnSuccess; Fail: #endif // hasTracing > 0 return kIOReturnBadArgument; }
IOReturn SATSMARTUserClient::GetIdentifyData (UInt32 * dataOut, IOByteCount * outputSize) { IOReturn status = kIOReturnSuccess; IOSATCommand * command = NULL; IOMemoryDescriptor * buffer = NULL; DEBUG_LOG("%s[%p]::%s %p(%ld)\n", getClassName(), this, __FUNCTION__, dataOut, (long)(outputSize)); if (!dataOut || !outputSize || *outputSize < kATADefaultSectorSize ) { return kIOReturnBadArgument; } fOutstandingCommands++; if ( isInactive ( ) ) { status = kIOReturnNoDevice; goto ErrorExit; } fProvider->retain ( ); command = AllocateCommand ( ); if ( command == NULL ) { status = kIOReturnNoResources; goto ReleaseProvider; } buffer = IOMemoryDescriptor::withAddress(dataOut, kATADefaultSectorSize, kIODirectionIn); if ( buffer == NULL ) { status = kIOReturnNoResources; goto ReleaseCommand; } status = buffer->prepare ( ); if ( status != kIOReturnSuccess ) { goto ReleaseBuffer; } command->setBuffer ( buffer ); command->setByteCount ( kATADefaultSectorSize ); command->setTransferChunkSize ( kATADefaultSectorSize ); command->setOpcode ( kATAFnExecIO ); command->setTimeoutMS ( kATAThirtySecondTimeoutInMS ); command->setCommand ( kATAcmdDriveIdentify ); command->setFlags ( mATAFlagIORead ); command->setRegMask ( ( ataRegMask ) ( mATAErrFeaturesValid | mATAStatusCmdValid ) ); status = SendSMARTCommand ( command ); if ( status == kIOReturnSuccess ) { #if defined(__BIG_ENDIAN__) UInt8 * bufferToCopy = identifyDataPtr; // The identify device info needs to be byte-swapped on big-endian (ppc) // systems becuase it is data that is produced by the drive, read across a // 16-bit little-endian PCI interface, directly into a big-endian system. // Regular data doesn't need to be byte-swapped because it is written and // read from the host and is intrinsically byte-order correct. IOByteCount index; UInt8 temp; UInt8 * firstBytePtr; UInt8 * identifyDataPtr = ( UInt8 * )dataOut; for ( index = 0; index < buffer->getLength ( ); index += 2 ) { firstBytePtr = identifyDataPtr; // save pointer temp = *identifyDataPtr++; // Save Byte0, point to Byte1 *firstBytePtr = *identifyDataPtr; // Byte0 = Byte1 *identifyDataPtr++ = temp; // Byte1 = Byte0 } #endif *outputSize = buffer->getLength ( ); DEBUG_LOG("%s[%p]::%s cpy %p %p\n", getClassName(), this, __FUNCTION__, (void*)*outputSize, (void*)buffer->getLength()); } ReleaseBufferPrepared: buffer->complete ( ); ReleaseBuffer: buffer->release ( ); buffer = NULL; ReleaseCommand: DeallocateCommand ( command ); command = NULL; ReleaseProvider: fProvider->release ( ); ErrorExit: fOutstandingCommands--; DEBUG_LOG("%s[%p]::%s result %x\n", getClassName(), this, __FUNCTION__, status); return status; }
/* * GetDeviceDetails() * Get mode sense details and set device parameters. * * Would have ideally liked to use super::GetModeSense() but it appears * to set the DBD bit and we need the descriptor values for density, * etc. */ IOReturn IOSCSITape::GetDeviceDetails(void) { IOReturn status = kIOReturnError; SCSITaskIdentifier task = NULL; SCSITaskStatus taskStatus = kSCSITaskStatus_DeviceNotResponding; IOMemoryDescriptor * dataBuffer = NULL; SCSI_ModeSense_Default modeData = { 0 }; dataBuffer = IOMemoryDescriptor::withAddress(&modeData, sizeof(modeData), kIODirectionIn); require((dataBuffer != 0), ErrorExit); task = GetSCSITask(); require((task != 0), ErrorExit); if (MODE_SENSE_6(task, dataBuffer, 0x0, 0x0, 0x00, sizeof(SCSI_ModeSense_Default), 0x00) == true) { taskStatus = DoSCSICommand(task, SCSI_NOMOTION_TIMEOUT); } if (taskStatus == kSCSITaskStatus_GOOD) { /* copy mode data for next MODE SELECT */ bcopy(&modeData, &lastModeData, sizeof(SCSI_ModeSense_Default)); blksize = (modeData.descriptor.BLOCK_LENGTH[0] << 16) | (modeData.descriptor.BLOCK_LENGTH[1] << 8) | modeData.descriptor.BLOCK_LENGTH[2]; density = modeData.descriptor.DENSITY_CODE; flags &= ~(ST_READONLY | ST_BUFF_MODE); if (modeData.header.DEVICE_SPECIFIC_PARAMETER & SMH_DSP_WRITE_PROT) flags |= ST_READONLY; if (modeData.header.DEVICE_SPECIFIC_PARAMETER & SMH_DSP_BUFF_MODE) flags |= ST_BUFF_MODE; STATUS_LOG("density code: %d, %d-byte blocks, write-%s, %sbuffered", density, blksize, flags & ST_READONLY ? "protected" : "enabled", flags & ST_BUFF_MODE ? "" : "un"); status = kIOReturnSuccess; } ReleaseSCSITask(task); dataBuffer->release(); ErrorExit: return status; }
IOReturn SATSMARTUserClient::ReadDataThresholds (UInt32 * dataOut, IOByteCount * outputSize) { IOReturn status = kIOReturnSuccess; IOSATCommand * command = NULL; IOMemoryDescriptor * buffer = NULL; DEBUG_LOG("%s[%p]::%s\n", getClassName(), this, __FUNCTION__); if (!dataOut || !outputSize || *outputSize != sizeof ( ATASMARTDataThresholds ) ) { return kIOReturnBadArgument; } fOutstandingCommands++; if ( isInactive ( ) ) { status = kIOReturnNoDevice; goto ErrorExit; } fProvider->retain ( ); command = AllocateCommand ( ); if ( command == NULL ) { status = kIOReturnNoResources; goto ReleaseProvider; } buffer = IOMemoryDescriptor::withAddress(dataOut, sizeof ( ATASMARTDataThresholds ), kIODirectionIn); if ( buffer == NULL ) { status = kIOReturnNoResources; goto ReleaseCommand; } status = buffer->prepare ( ); if ( status != kIOReturnSuccess ) { goto ReleaseBuffer; } command->setBuffer ( buffer ); command->setByteCount ( sizeof ( ATASMARTDataThresholds ) ); command->setFeatures ( kFeaturesRegisterReadDataThresholds ); command->setOpcode ( kATAFnExecIO ); command->setTimeoutMS ( kATAThirtySecondTimeoutInMS ); command->setCylLo ( kSMARTMagicCylinderLoValue ); command->setCylHi ( kSMARTMagicCylinderHiValue ); command->setCommand ( kATAcmdSMART ); command->setFlags ( mATAFlagIORead ); status = SendSMARTCommand ( command ); if ( status == kIOReturnIOError ) { if ( command->getEndErrorReg ( ) & 0x04 ) { ERROR_LOG ( "ReadDataThresholds unsupported\n" ); status = kIOReturnUnsupported; } if ( command->getEndErrorReg ( ) & 0x10 ) { ERROR_LOG ( "ReadDataThresholds Not readable\n" ); status = kIOReturnNotReadable; } } *outputSize = buffer->getLength(); buffer->complete ( ); ReleaseBuffer: buffer->release ( ); buffer = NULL; ReleaseCommand: DeallocateCommand ( command ); command = NULL; ReleaseProvider: fProvider->release ( ); ErrorExit: fOutstandingCommands--; DEBUG_LOG("%s[%p]::%s result %d\n", getClassName(), this, __FUNCTION__, status); return status; }
IOReturn SATSMARTUserClient::WriteLogAtAddress ( ATASMARTWriteLogStruct * writeLogData, UInt32 inStructSize ) { IOReturn status = kIOReturnSuccess; IOSATCommand * command = NULL; IOMemoryDescriptor * buffer = NULL; DEBUG_LOG("%s[%p]::%s\n", getClassName(), this, __FUNCTION__); if ( inStructSize != sizeof ( ATASMARTWriteLogStruct ) || writeLogData->numSectors > 16 || writeLogData->data_length > kSATMaxDataSize) { return kIOReturnBadArgument; } fOutstandingCommands++; if ( isInactive ( ) ) { status = kIOReturnNoDevice; goto ErrorExit; } fProvider->retain ( ); command = AllocateCommand ( ); if ( command == NULL ) { status = kIOReturnNoResources; goto ReleaseProvider; } //buffer = IOMemoryDescriptor::withAddress(writeLogData->buffer, writeLogData->bufferSize, kIODirectionOut); buffer = IOMemoryDescriptor::withAddressRange(writeLogData->data_pointer, writeLogData->data_length, kIODirectionOut, fTask); if ( buffer == NULL ) { status = kIOReturnVMError; goto ReleaseCommand; } status = buffer->prepare ( ); if ( status != kIOReturnSuccess ) { goto ReleaseBuffer; } command->setBuffer ( buffer ); command->setByteCount ( writeLogData->data_length ); command->setFeatures ( kFeaturesRegisterWriteLogAtAddress ); command->setOpcode ( kATAFnExecIO ); command->setTimeoutMS ( kATAThirtySecondTimeoutInMS ); command->setSectorCount ( writeLogData->numSectors ); command->setSectorNumber ( writeLogData->logAddress ); command->setCylLo ( kSMARTMagicCylinderLoValue ); command->setCylHi ( kSMARTMagicCylinderHiValue ); command->setCommand ( kATAcmdSMART ); command->setFlags ( mATAFlagIOWrite ); status = SendSMARTCommand ( command ); if ( status == kIOReturnIOError ) { if ( command->getEndErrorReg ( ) & 0x04 ) { ERROR_LOG ( "WriteLogAtAddress %d unsupported\n", writeLogData->logAddress ); status = kIOReturnUnsupported; } if ( command->getEndErrorReg ( ) & 0x10 ) { ERROR_LOG ( "WriteLogAtAddress %d unwriteable\n", writeLogData->logAddress ); status = kIOReturnNotWritable; } } buffer->complete ( ); ReleaseBuffer: buffer->release ( ); buffer = NULL; ReleaseCommand: DeallocateCommand ( command ); command = NULL; ReleaseProvider: fProvider->release ( ); ErrorExit: fOutstandingCommands--; DEBUG_LOG("%s[%p]::%s result %d\n", getClassName(), this, __FUNCTION__, status); return status; }
// Processes a message for a controller void WirelessGamingReceiver::ProcessMessage(int index, const unsigned char *data, int length) { /* char s[1024]; int i; for (i = 0; i < length; i++) { s[(i * 2) + 0] = "0123456789ABCDEF"[(data[i] & 0xF0) >> 4]; s[(i * 2) + 1] = "0123456789ABCDEF"[data[i] & 0x0F]; } s[i * 2] = '\0'; IOLog("Got data (%d, %d bytes): %s\n", index, length, s); */ // Handle device connections if ((length == 2) && (data[0] == 0x08)) { if (data[1] == 0x00) { // Device disconnected // IOLog("process: Device detached\n"); if (connections[index].service != NULL) { connections[index].service->SetIndex(-1); if (connections[index].controllerStarted) connections[index].service->terminate(kIOServiceRequired | kIOServiceSynchronous); connections[index].service->detach(this); connections[index].service->release(); connections[index].service = NULL; connections[index].controllerStarted = false; } } else { // Device connected // IOLog("process: Attempting to add new device\n"); if (connections[index].service == NULL) { bool ready; int i, j; IOMemoryDescriptor *data; char c; ready = false; j = connections[index].inputArray->getCount(); for (i = 0; !ready && (i < j); i++) { data = OSDynamicCast(IOMemoryDescriptor, connections[index].inputArray->getObject(i)); data->readBytes(1, &c, 1); if (c == 0x0f) ready = true; } InstantiateService(index); if (ready) { // IOLog("Registering wireless device"); connections[index].controllerStarted = true; connections[index].service->registerService(); } } } return; } // Add anything else to the queue IOMemoryDescriptor *copy = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, 0, length); copy->writeBytes(0, data, length); connections[index].inputArray->setObject(copy); if (connections[index].service == NULL) InstantiateService(index); if (connections[index].service != NULL) { connections[index].service->NewData(); if (!connections[index].controllerStarted) { char c; copy->readBytes(1, &c, 1); if (c == 0x0f) { // IOLog("Registering wireless device"); connections[index].controllerStarted = true; connections[index].service->registerService(); } } } copy->release(); }
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; }
IOReturn IOSCSITape::ReadPosition(SCSI_ReadPositionShortForm *readPos, bool vendor) { SCSITaskIdentifier task = NULL; IOReturn status = kIOReturnError; SCSITaskStatus taskStatus = kSCSITaskStatus_DeviceNotResponding; IOMemoryDescriptor * dataBuffer = NULL; UInt8 readPosData[20] = { 0 }; dataBuffer = IOMemoryDescriptor::withAddress(&readPosData, sizeof(readPosData), kIODirectionIn); require((dataBuffer != 0), ErrorExit); task = GetSCSITask(); require((task != 0), ErrorExit); if (READ_POSITION(task, dataBuffer, (vendor ? kSCSIReadPositionServiceAction_ShortFormVendorSpecific : kSCSIReadPositionServiceAction_ShortFormBlockID), 0x0, 0x00) == true) { taskStatus = DoSCSICommand(task, SCSI_NOMOTION_TIMEOUT); } if (taskStatus == kSCSITaskStatus_GOOD) { readPos->flags = readPosData[0]; readPos->partitionNumber = readPosData[1]; readPos->firstLogicalObjectLocation = (readPosData[4] << 24) | (readPosData[5] << 16) | (readPosData[6] << 8) | readPosData[7]; readPos->lastLogicalObjectLocation = (readPosData[8] << 24) | (readPosData[9] << 16) | (readPosData[10] << 8) | readPosData[11]; readPos->logicalObjectsInObjectBuffer = (readPosData[13] << 16) | (readPosData[14] << 8) | readPosData[15]; readPos->bytesInObjectBuffer = (readPosData[16] << 24) | (readPosData[17] << 16) | (readPosData[18] << 8) | readPosData[19]; status = kIOReturnSuccess; } ReleaseSCSITask(task); dataBuffer->release(); ErrorExit: return status; }
bool IOFWUserLocalIsochPort::initWithUserDCLProgram ( AllocateParams * params, IOFireWireUserClient & userclient, IOFireWireController & controller ) { // sanity checking if ( params->programExportBytes == 0 ) { ErrorLog ( "No program!" ) ; return false ; } fLock = IORecursiveLockAlloc () ; if ( ! fLock ) { ErrorLog ( "Couldn't allocate recursive lock\n" ) ; return false ; } // init easy params fUserObj = params->userObj ; fUserClient = & userclient ; fDCLPool = NULL ; fProgramCount = 0; fStarted = false ; IOReturn error = kIOReturnSuccess ; // get user program ranges: IOAddressRange * bufferRanges = new IOAddressRange[ params->bufferRangeCount ] ; if ( !bufferRanges ) { error = kIOReturnNoMemory ; } if ( !error ) { error = fUserClient->copyUserData(params->bufferRanges,(mach_vm_address_t)bufferRanges, sizeof ( IOAddressRange ) * params->bufferRangeCount ) ; } // create descriptor for program buffers IOMemoryDescriptor * bufferDesc = NULL ; if ( ! error ) { IOByteCount length = 0 ; for ( unsigned index = 0; index < params->bufferRangeCount; ++index ) { length += bufferRanges[ index ].length ; } bufferDesc = IOMemoryDescriptor::withAddressRanges ( bufferRanges, params->bufferRangeCount, kIODirectionOutIn, fUserClient->getOwningTask() ) ; if ( ! bufferDesc ) { error = kIOReturnNoMemory ; } else { // IOLog( "IOFWUserLocalIsochPort::initWithUserDCLProgram - checkMemoryInRange status 0x%08lx\n", checkMemoryInRange( bufferDesc, 0x000000001FFFFFFF ) ); error = bufferDesc->prepare( kIODirectionPrepareToPhys32 ) ; FWTrace( kFWTIsoch, kTPIsochPortUserInitWithUserDCLProgram, (uintptr_t)(fUserClient->getOwner()->getController()->getLink()), error, length, 0 ); // IOLog( "IOFWUserLocalIsochPort::initWithUserDCLProgram - prep 32 checkMemoryInRange status 0x%08lx\n", checkMemoryInRange( bufferDesc, 0x000000001FFFFFFF ) ); } } // create map for buffers; we will need to get a virtual address for them IOMemoryMap * bufferMap = NULL ; if ( !error ) { bufferMap = bufferDesc->map() ; if ( !bufferMap ) { DebugLog( "Couldn't map program buffers\n" ) ; error = kIOReturnVMError ; } bufferDesc->release() ; } IOMemoryDescriptor * userProgramExportDesc = NULL ; if ( !error ) { userProgramExportDesc = IOMemoryDescriptor::withAddressRange( params->programData, params->programExportBytes, kIODirectionOut, fUserClient->getOwningTask() ) ; } // get map of program export data if ( userProgramExportDesc ) { error = userProgramExportDesc->prepare() ; } if ( !error ) { DCLCommand * opcodes = NULL ; switch ( params->version ) { case kDCLExportDataLegacyVersion : error = importUserProgram( userProgramExportDesc, params->bufferRangeCount, bufferRanges, bufferMap ) ; ErrorLogCond( error, "importUserProgram returned %x\n", error ) ; if ( ! error ) { opcodes = (DCLCommand*)fProgramBuffer ; } break ; case kDCLExportDataNuDCLRosettaVersion : fDCLPool = fUserClient->getOwner()->getBus()->createDCLPool() ; if ( ! fDCLPool ) { error = kIOReturnNoMemory ; } if ( !error ) { error = fDCLPool->importUserProgram( userProgramExportDesc, params->bufferRangeCount, bufferRanges, bufferMap ) ; } fProgramBuffer = new UInt8[ sizeof( DCLNuDCLLeader ) ] ; { DCLNuDCLLeader * leader = (DCLNuDCLLeader*)fProgramBuffer ; { leader->pNextDCLCommand = NULL ; // unused - always NULL leader->opcode = kDCLNuDCLLeaderOp ; leader->program = fDCLPool ; } opcodes = (DCLCommand*)leader ; } break ; default : ErrorLog ( "unsupported DCL program type\n" ) ; error = kIOReturnBadArgument ; break ; } ErrorLogCond( !opcodes, "Couldn't get opcodes\n" ) ; IODCLProgram * program = NULL ; if ( opcodes ) { // IOFWLocalIsochPort::printDCLProgram( opcodes ) ; IOFireWireBus::DCLTaskInfoAux infoAux ; { infoAux.version = 2 ; infoAux.u.v2.bufferMemoryMap = bufferMap ; infoAux.u.v2.workloop = params->options & kFWIsochPortUseSeparateKernelThread ? createRealtimeThread() : NULL ; infoAux.u.v2.options = (IOFWIsochPortOptions)params->options ; } IOFireWireBus::DCLTaskInfo info = { 0, 0, 0, 0, 0, 0, & infoAux } ; program = fUserClient->getOwner()->getController()->getLink()->createDCLProgram( params->talking, opcodes, & info, params->startEvent, params->startState, params->startMask ) ; bufferMap->release() ; // retained by DCL program bufferMap = NULL ; if ( infoAux.u.v2.workloop ) { // If we created a custom workloop, it will be retained by the program... // We can release our reference... infoAux.u.v2.workloop->release() ; } DebugLogCond( !program, "createDCLProgram returned nil\n" ) ; } if ( program ) { if ( ! super::init( program, & controller ) ) { ErrorLog ( "IOFWUserIsochPort::init failed\n" ) ; error = kIOReturnError ; } } else { DebugLog ( "Couldn't create DCL program\n" ) ; error = kIOReturnNoMemory ; } userProgramExportDesc->complete() ; userProgramExportDesc->release() ; userProgramExportDesc = NULL ; } delete [] bufferRanges ; InfoLog( "-IOFWUserLocalIsochPort::initWithUserDCLProgram error=%x (build date "__TIME__" "__DATE__")\n", error ) ; return ( ! error ) ; }
IOReturn SATSMARTUserClient::ReadLogAtAddress ( ATASMARTReadLogStruct * structIn, void * structOut, IOByteCount inStructSize, IOByteCount *outStructSize) { IOReturn status = kIOReturnSuccess; IOSATCommand * command = NULL; IOMemoryDescriptor * buffer = NULL; DEBUG_LOG("%s[%p]::%s %p(%ld) %p(%ld)\n", getClassName(), this, __FUNCTION__, structIn, (long)inStructSize, structOut, (long)(outStructSize)); if ( inStructSize != sizeof ( ATASMARTReadLogStruct ) || !outStructSize || *outStructSize < 1) { return kIOReturnBadArgument; } fOutstandingCommands++; if ( isInactive ( ) ) { status = kIOReturnNoDevice; goto ErrorExit; } fProvider->retain ( ); command = AllocateCommand ( ); if ( command == NULL ) { status = kIOReturnNoResources; goto ReleaseProvider; } buffer = IOMemoryDescriptor::withAddress (structOut, *outStructSize, kIODirectionIn); if ( buffer == NULL ) { status = kIOReturnNoResources; goto ReleaseCommand; } status = buffer->prepare ( ); DEBUG_LOG("%s[%p]::%s status %x\n", getClassName(), this, __FUNCTION__, status); if ( status != kIOReturnSuccess ) { goto ReleaseBuffer; } command->setBuffer ( buffer ); command->setByteCount ( buffer->getLength()); command->setFeatures ( kFeaturesRegisterReadLogAtAddress ); command->setOpcode ( kATAFnExecIO ); command->setTimeoutMS ( kATAThirtySecondTimeoutInMS ); command->setSectorCount ( structIn->numSectors ); command->setSectorNumber ( structIn->logAddress ); command->setCylLo ( kSMARTMagicCylinderLoValue ); command->setCylHi ( kSMARTMagicCylinderHiValue ); command->setCommand ( kATAcmdSMART ); command->setFlags ( mATAFlagIORead ); status = SendSMARTCommand ( command ); if ( status == kIOReturnIOError ) { if ( command->getEndErrorReg ( ) & 0x04 ) { ERROR_LOG ( "ReadLogAtAddress %d unsupported\n", structIn->logAddress ); status = kIOReturnUnsupported; } if ( command->getEndErrorReg ( ) & 0x10 ) { ERROR_LOG ( "ReadLogAtAddress %d unreadable\n", structIn->logAddress ); status = kIOReturnNotReadable; } } *outStructSize = buffer->getLength(); buffer->complete ( ); ReleaseBuffer: buffer->release ( ); buffer = NULL; ReleaseCommand: DeallocateCommand ( command ); command = NULL; ReleaseProvider: fProvider->release ( ); ErrorExit: fOutstandingCommands--; DEBUG_LOG("%s[%p]::%s result %d\n", getClassName(), this, __FUNCTION__, status); return status; }