void pci_free_consistent(void *pdev, size_t size, void *vaddr, dma_addr_t dma_handle) { // free a hw dma scatter/gather list located in host memory int index; OSArray *dma_info_array; IOBufferMemoryDescriptor *memDesc; IOVirtualAddress virt_address; // search for the correct dma_info by checking against passed virtual address dma_info_array = g_bcm_dma_info; for(index = 0; index < (int)dma_info_array->getCount(); index++) { memDesc = (IOBufferMemoryDescriptor*)dma_info_array->getObject(index); virt_address = (IOVirtualAddress)memDesc->getBytesNoCopy(); if ((IOVirtualAddress)vaddr == virt_address) { //IOLog("pci_free_consistent padd(%p), size(0x%X)\n", dma_handle, size); // found it, now complete. removeObject will release it memDesc->complete(); dma_info_array->removeObject(index); // should be able to just call memDesc->release() after memDesc->complete() // but on atv, there's something holding a ref to memDesc and so we leak memory // everytime the crystalhs driver closes. Doing the release this way fixes the mem // leak on atv and is fine under real 10.4/10.5 boxes. SAFE_RELEASE(memDesc); break; } } }
void *pci_alloc_consistent(void *pdev, size_t size, dma_addr_t *dma_handle) { IOBufferMemoryDescriptor *memDesc; IOVirtualAddress virt_address; IOPhysicalAddress phys_address; // construct a memory descriptor for a buffer below the 4Gb line, // addressable by 32 bit DMA and page aligned. memDesc = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, kIOMemoryPhysicallyContiguous, size, PAGE_SIZE); if (memDesc) { IOByteCount offset = 0; IOByteCount length; memDesc->prepare(); virt_address = (IOVirtualAddress)memDesc->getBytesNoCopy(); phys_address = memDesc->getPhysicalSegment(offset, &length); g_bcm_dma_info->setObject(memDesc); } else { virt_address = NULL; phys_address = NULL; IOLog("pci_alloc_consistent:IOBufferMemoryDescriptor::inTaskWithOptions failed\n"); } //IOLog("pci_alloc_consistent paddr(0x%X), size(0x%X)\n", (unsigned int)phys_address, size); *dma_handle = phys_address; return (void*)virt_address; }
IOReturn XboxOneControllerClass::handleReport(IOMemoryDescriptor * descriptor, IOHIDReportType reportType, IOOptionBits options) { if (descriptor->getLength() >= sizeof(XBOXONE_IN_GUIDE_REPORT)) { IOBufferMemoryDescriptor *desc = OSDynamicCast(IOBufferMemoryDescriptor, descriptor); if (desc != NULL) { XBOXONE_ELITE_IN_REPORT *report=(XBOXONE_ELITE_IN_REPORT*)desc->getBytesNoCopy(); if ((report->header.command==0x07) && (report->header.size==(sizeof(XBOXONE_IN_GUIDE_REPORT)-4))) { XBOXONE_IN_GUIDE_REPORT *guideReport=(XBOXONE_IN_GUIDE_REPORT*)report; isXboxOneGuideButtonPressed = (bool)guideReport->state; XBOX360_IN_REPORT *oldReport = (XBOX360_IN_REPORT*)lastData; oldReport->buttons ^= (-isXboxOneGuideButtonPressed ^ oldReport->buttons) & (1 << GetOwner(this)->mapping[10]); memcpy(report, lastData, sizeof(XBOX360_IN_REPORT)); } else if (report->header.command==0x20) { if (report->header.size==0x0e || report->header.size==0x1d || report->header.size==0x1a) { convertFromXboxOne(report, report->header.size); XBOX360_IN_REPORT *report360=(XBOX360_IN_REPORT*)report; if (!(GetOwner(this)->noMapping)) remapButtons(report360); GetOwner(this)->fiddleReport(report360->left, report360->right); if (GetOwner(this)->swapSticks) remapAxes(report360); memcpy(lastData, report360, sizeof(XBOX360_IN_REPORT)); } } } } IOReturn ret = IOHIDDevice::handleReport(descriptor, reportType, options); return ret; }
// Queue an asynchronous write on a controller bool WirelessGamingReceiver::QueueWrite(int index, const void *bytes, UInt32 length) { IOBufferMemoryDescriptor *outBuffer; IOUSBCompletion complete; IOReturn err; outBuffer = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, 0, length); if (outBuffer == NULL) { // IOLog("send - unable to allocate buffer\n"); return false; } outBuffer->writeBytes(0, bytes, length); complete.target = this; complete.action = _WriteComplete; complete.parameter = outBuffer; err = connections[index].controllerOut->Write(outBuffer, 0, 0, length, &complete); if (err == kIOReturnSuccess) return true; else { // IOLog("send - failed to start (0x%.8x)\n",err); return false; } }
// Returns the HID descriptor for this device IOReturn Xbox360ControllerClass::newReportDescriptor(IOMemoryDescriptor **descriptor) const { IOBufferMemoryDescriptor *buffer = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task,0,sizeof(HID_360::ReportDescriptor)); if (buffer == NULL) return kIOReturnNoResources; buffer->writeBytes(0,HID_360::ReportDescriptor,sizeof(HID_360::ReportDescriptor)); *descriptor=buffer; return kIOReturnSuccess; }
void * IOMallocContiguous(vm_size_t size, vm_size_t alignment, IOPhysicalAddress * physicalAddress) { mach_vm_address_t address = 0; if (size == 0) return 0; if (alignment == 0) alignment = 1; /* Do we want a physical address? */ if (!physicalAddress) { address = IOKernelAllocateWithPhysicalRestrict(size, 0 /*maxPhys*/, alignment, true); } else do { IOBufferMemoryDescriptor * bmd; mach_vm_address_t physicalMask; vm_offset_t alignMask; alignMask = alignment - 1; physicalMask = (0xFFFFFFFF ^ alignMask); bmd = IOBufferMemoryDescriptor::inTaskWithPhysicalMask( kernel_task, kIOMemoryPhysicallyContiguous, size, physicalMask); if (!bmd) break; _IOMallocContiguousEntry * entry = IONew(_IOMallocContiguousEntry, 1); if (!entry) { bmd->release(); break; } entry->virtualAddr = (mach_vm_address_t) bmd->getBytesNoCopy(); entry->md = bmd; lck_mtx_lock(gIOMallocContiguousEntriesLock); queue_enter( &gIOMallocContiguousEntries, entry, _IOMallocContiguousEntry *, link ); lck_mtx_unlock(gIOMallocContiguousEntriesLock); address = (mach_vm_address_t) entry->virtualAddr; *physicalAddress = bmd->getPhysicalAddress(); } while (false); if (address) { IOStatisticsAlloc(kIOStatisticsMallocContiguous, size); } return (void *) address; }
IOBufferMemoryDescriptor * IOBufferMemoryDescriptor::withOptions( IOOptionBits options, vm_size_t capacity, vm_offset_t alignment) { IOBufferMemoryDescriptor *me = new IOBufferMemoryDescriptor; if (me && !me->initWithPhysicalMask(kernel_task, options, capacity, alignment, 0)) { me->release(); me = 0; } return me; }
/* * withBytes: * * Returns a new IOBufferMemoryDescriptor preloaded with bytes (copied). * The descriptor's length and capacity are set to the input buffer's size. */ IOBufferMemoryDescriptor * IOBufferMemoryDescriptor::withBytes(const void * inBytes, vm_size_t inLength, IODirection inDirection, bool inContiguous) { IOBufferMemoryDescriptor *me = new IOBufferMemoryDescriptor; if (me && !me->initWithBytes(inBytes, inLength, inDirection, inContiguous)) { me->release(); me = 0; } return me; }
IOBufferMemoryDescriptor * IOBufferMemoryDescriptor::inTaskWithOptions( task_t inTask, IOOptionBits options, vm_size_t capacity, vm_offset_t alignment) { IOBufferMemoryDescriptor *me = new IOBufferMemoryDescriptor; if (me && !me->initWithOptions(options, capacity, alignment, inTask)) { me->release(); me = 0; } return me; }
IOReturn Xbox360ControllerClass::handleReport(IOMemoryDescriptor * descriptor, IOHIDReportType reportType, IOOptionBits options) { if (descriptor->getLength() >= sizeof(XBOX360_IN_REPORT)) { IOBufferMemoryDescriptor *desc = OSDynamicCast(IOBufferMemoryDescriptor, descriptor); if (desc != NULL) { XBOX360_IN_REPORT *report=(XBOX360_IN_REPORT*)desc->getBytesNoCopy(); if ((report->header.command==inReport) && (report->header.size==sizeof(XBOX360_IN_REPORT))) { GetOwner(this)->fiddleReport(desc); remapButtons(report); } } } IOReturn ret = IOHIDDevice::handleReport(descriptor, reportType, options); return ret; }
IOReturn it_unbit_foohid_device::newReportDescriptor(IOMemoryDescriptor **descriptor) const { IOLog("it_unbit_foohid_device::newReportDescriptor()\n"); IOBufferMemoryDescriptor *buffer = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, 0, reportDescriptor_len); if (buffer == NULL) { IOLog("OOOOPS"); return kIOReturnNoResources; } buffer->writeBytes(0, reportDescriptor, reportDescriptor_len); *descriptor = buffer; IOLog("all fine\n"); return kIOReturnSuccess; }
IOBufferMemoryDescriptor * IOBufferMemoryDescriptor::inTaskWithPhysicalMask( task_t inTask, IOOptionBits options, mach_vm_size_t capacity, mach_vm_address_t physicalMask) { IOBufferMemoryDescriptor *me = new IOBufferMemoryDescriptor; if (me && !me->initWithPhysicalMask(inTask, options, capacity, 1, physicalMask)) { me->release(); me = 0; } return me; }
IOBufferMemoryDescriptor* MemoryDmaAlloc(UInt32 buf_size, dma_addr_t *phys_add, void *virt_add) { IOBufferMemoryDescriptor *memBuffer; void *virt_address; dma_addr_t phys_address; IOMemoryMap *memMap; memBuffer = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, kIODirectionOutIn | kIOMemoryPhysicallyContiguous | \ kIOMemoryAutoPrepare | kIOMapInhibitCache, buf_size, \ PAGE_SIZE); if (memBuffer == NULL) { //IOLog("Memory Allocation failed - RLC"); return NULL; } memMap = memBuffer->map(); if (memMap == NULL) { //IOLog("mapping failed\n"); memBuffer->release(); memBuffer = NULL; return NULL; } phys_address = memMap->getPhysicalAddress(); virt_address = (void *)memMap->getVirtualAddress(); if (virt_address == NULL || phys_address == NULL) { memMap->release(); memBuffer->release(); memBuffer = NULL; return NULL; } *phys_add = phys_address; *(IOVirtualAddress*)virt_add = (IOVirtualAddress)virt_address; memMap->release(); return memBuffer; }
/* read the <partition#> sector on the root address for label and size */ void net_habitue_device_SC101::partitionCompletion(void *parameter, IOReturn status, UInt64 actualByteCount) { if (status != kIOReturnSuccess || actualByteCount != sizeof(psan_get_response_partition_t)) { KINFO("partition lookup on %s failed", getID()->getCStringNoCopy()); return; } IOBufferMemoryDescriptor *buffer = (IOBufferMemoryDescriptor *)parameter; psan_get_response_partition_t *part = (psan_get_response_partition_t *)buffer->getBytesNoCopy(); OSString *id = getID(); for (UInt32 i = 0; i < actualByteCount / sizeof(psan_get_response_partition_t); i++, part++) { KDEBUG("cmp %s", part->id); if (strncmp(part->id, id->getCStringNoCopy(), id->getLength() + 1) != 0) continue; KDEBUG("Matched!"); OSString *label = OSString::withCString(part->label); if (label) { setProperty(gSC101DeviceLabelKey, label); label->release(); } OSNumber *size = OSNumber::withNumber(getUInt48(part->sector_size) << 9, 64); if (size) { setProperty(gSC101DeviceSizeKey, size); size->release(); } if (1) // TODO(iwade) determine minimum fields needed { _mediaStateAttached = true; _mediaStateChanged = true; } break; } }
void VoodooI2CHIDDevice::i2c_hid_get_input(OSObject* owner, IOTimerEventSource* sender) { // IOLog("getting input\n"); if (hid_device->reading) return; UInt rsize; int ret; rsize = UInt16(ihid->hdesc.wMaxInputLength); unsigned char* rdesc = (unsigned char *)IOMalloc(rsize); ret = i2c_hid_command(ihid, &hid_input_cmd, rdesc, rsize); // IOLog("===Input (%d)===\n", rsize); // for (int i = 0; i < rsize; i++) // IOLog("0x%02x ", (UInt8) rdesc[i]); // IOLog("\n"); int return_size = rdesc[0] | rdesc[1] << 8; if (return_size == 0) { /* host or device initiated RESET completed */ // test/clear bit? hid_device->timerSource->setTimeoutMS(10); return; } if (return_size > rsize) { IOLog("%s: Incomplete report %d/%d\n", __func__, rsize, return_size); } IOBufferMemoryDescriptor *buffer = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, 0, return_size); buffer->writeBytes(0, rdesc + 2, return_size - 2); IOReturn err = _wrapper->handleReport(buffer, kIOHIDReportTypeInput); if (err != kIOReturnSuccess) IOLog("Error handling report: 0x%.8x\n", err); buffer->release(); IOFree(rdesc, rsize); hid_device->timerSource->setTimeoutMS(10); }
IOBufferMemoryDescriptor *kXAudioEngine::my_alloc_contiguous(mach_vm_size_t size, void **addr, dword *phys) { if(size<PAGE_SIZE) size=PAGE_SIZE; #ifdef DEBUGGING size += 2 * PAGE_SIZE; #endif //void *addr=IOMallocContiguous(size+PAGE_SIZE+PAGE_SIZE,alignment,phys); mach_vm_address_t mask = 0x000000007FFFFFFFULL & ~(PAGE_SIZE - 1); IOBufferMemoryDescriptor *desc = IOBufferMemoryDescriptor::inTaskWithPhysicalMask( kernel_task, kIODirectionInOut | kIOMemoryPhysicallyContiguous, size, mask); if(desc) { desc->prepare(); IOPhysicalAddress pa = desc->getPhysicalAddress(); if (pa & ~mask) debug("kXAudioEngine[%p]::my_alloc_contiguous() - memory misaligned or beyond 2GB limit (%p)\n", this, (void *)pa); *phys = (dword)pa; *addr = desc->getBytesNoCopy(); #ifdef DEBUGGING memset(addr,0x11,PAGE_SIZE); memset((UInt8 *)addr+PAGE_SIZE+size,0x22,PAGE_SIZE); *((UInt8 *)addr) += PAGE_SIZE; *phys += PAGE_SIZE; #endif } else debug("kXAudioEngine[%p]::my_alloc_contiguous() - allocation failed\n",this); return desc; }
IOReturn org_litio_OzoneStrikeBattle::newReportDescriptor(IOMemoryDescriptor** descriptor) const { // TODO: Define new device descriptor struct for the keyboard. // Assigning current descriptor. IOLog("OzoneStrike::%s[%p] - Setting HID report descriptor.\n", getName(), this); OSData *reportDescriptor = OSData::withBytes(Ozone::HIDReportDescriptor, sizeof(Ozone::HIDReportDescriptor)); OSData *reportDescriptorNew = OSDynamicCast(OSData, getProperty("ReportDescriptorOverride")); if (reportDescriptor == NULL) { IOLog("OzoneStrike::%s[%p] - reportDescriptor OSData not set.\n", getName(), this); return kIOReturnNoResources; } printBytes(reportDescriptorNew); printBytes(reportDescriptor); IOLog("OzoneStrike::%s[%p] - reportDescriptor OSData set (size: %d, data: %s).\n", getName(), this, reportDescriptor->getLength(), reportDescriptor->getBytesNoCopy()); //OSData *reportDescriptor = OSDynamicCast(OSData, Ozone::HIDReportDescriptor); IOBufferMemoryDescriptor *bufferDescriptor = IOBufferMemoryDescriptor::withBytes(reportDescriptor->getBytesNoCopy(), reportDescriptor->getLength(), kIODirectionOutIn); //IOBufferMemoryDescriptor *bufferDescriptor = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, // 0, // sizeof(Ozone::HIDReportDescriptor)); /* if (bufferDescriptor == NULL) { return kIOReturnNoResources; } bufferDescriptor->writeBytes(0, Ozone::HIDReportDescriptor,sizeof(Ozone::HIDReportDescriptor)); */ if (bufferDescriptor) { *descriptor = bufferDescriptor; return kIOReturnSuccess; } else { bufferDescriptor->release(); *descriptor = NULL; return kIOReturnNoMemory; } //return IOUSBHostHIDDevice::newReportDescriptor(descriptor); }
void net_habitue_device_SC101::diskCompletion(void *parameter, IOReturn status, UInt64 actualByteCount) { if (status != kIOReturnSuccess || actualByteCount != sizeof(psan_get_response_disk_t)) { KINFO("disk query on %s failed", getID()->getCStringNoCopy()); return; } IOBufferMemoryDescriptor *buffer = (IOBufferMemoryDescriptor *)parameter; psan_get_response_disk_t *disk = (psan_get_response_disk_t *)buffer->getBytesNoCopy(); OSData *partNumber = OSData::withBytes(disk->part_number, sizeof(disk->part_number)); if (partNumber) { OSString *resourceFile = NULL; if (partNumber->isEqualTo(kSC101PartNumber, sizeof(kSC101PartNumber))) resourceFile = OSString::withCString("SC101.icns"); else if (partNumber->isEqualTo(kSC101TPartNumber, sizeof(kSC101TPartNumber))) resourceFile = OSString::withCString("SC101T.icns"); if (resourceFile) { setIcon(resourceFile); resourceFile->release(); } setProperty(gSC101DevicePartNumberKey, partNumber); partNumber->release(); } OSString *version = OSString::withCString(disk->version); if (version) { setProperty(gSC101DeviceVersionKey, version); version->release(); } partition(disk->partitions); }
/* * withBytes: * * Returns a new IOBufferMemoryDescriptor preloaded with bytes (copied). * The descriptor's length and capacity are set to the input buffer's size. */ IOBufferMemoryDescriptor * IOBufferMemoryDescriptor::withBytes(const void * inBytes, vm_size_t inLength, IODirection inDirection, bool inContiguous) { IOBufferMemoryDescriptor *me = new IOBufferMemoryDescriptor; if (me && !me->initWithPhysicalMask( kernel_task, inDirection | kIOMemoryUnshared | (inContiguous ? kIOMemoryPhysicallyContiguous : 0), inLength, inLength, 0 )) { me->release(); me = 0; } if (me) { // start out with no data me->setLength(0); if (!me->appendBytes(inBytes, inLength)) { me->release(); me = 0; } } return me; }
IOReturn com_veltrop_taylor_driver_virtualhid::newReportDescriptor(IOMemoryDescriptor ** desc) const { // IOLog("newReportDescriptor\n"); IOBufferMemoryDescriptor * bufferDesc = NULL; UInt32 inOutSize = myReportDescSize; bufferDesc = IOBufferMemoryDescriptor::withCapacity(inOutSize, kIODirectionOutIn); if (bufferDesc) { UInt8* buff = (UInt8*)(bufferDesc->getBytesNoCopy()); memcpy(buff, myHIDReportDescriptor, inOutSize); } else return kIOReturnError; *desc = bufferDesc; // Note: I do not need to free bufferDesc, the caller will! return kIOReturnSuccess; }
// Set up an asynchronous write bool Xbox360Peripheral::QueueWrite(const void *bytes,UInt32 length) { IOBufferMemoryDescriptor *outBuffer; IOUSBCompletion complete; IOReturn err; outBuffer=IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task,0,length); if(outBuffer==NULL) { IOLog("send - unable to allocate buffer\n"); return false; } outBuffer->writeBytes(0,bytes,length); complete.target=this; complete.action=WriteCompleteInternal; complete.parameter=outBuffer; err=outPipe->Write(outBuffer,0,0,length,&complete); if(err==kIOReturnSuccess) return true; else { IOLog("send - failed to start (0x%.8x)\n",err); return false; } }
IOReturn IOUSBHIDDriverDescriptorOverride::newReportDescriptor(IOMemoryDescriptor **desc) const { OSData *reportDescriptor = OSDynamicCast(OSData, getProperty(REPORT_DESCRIPTOR_OVERRIDE_KEY)); if(reportDescriptor) { IOBufferMemoryDescriptor *bufferDesc = IOBufferMemoryDescriptor::withBytes(reportDescriptor->getBytesNoCopy(), reportDescriptor->getLength(), kIODirectionOutIn); if(bufferDesc) { *desc = bufferDesc; return kIOReturnSuccess; } else { bufferDesc->release(); *desc = NULL; return kIOReturnNoMemory; } } else { //IOLog("IOUSBHIDDriverDescriptorOverride(%s)[%p]::newReportDescriptor - " // "No %s data in personality, calling IOUSBHIDDriver::newReportDescriptor\n", // getName(), this, REPORT_DESCRIPTOR_OVERRIDE_KEY); return IOUSBHIDDriver::newReportDescriptor(desc); } }
OSSet * IOFDiskPartitionScheme::scan(SInt32 * score) { // // Scan the provider media for an FDisk partition map. Returns the set // of media objects representing each of the partitions (the retain for // the set is passed to the caller), or null should no partition map be // found. The default probe score can be adjusted up or down, based on // the confidence of the scan. // IOBufferMemoryDescriptor * buffer = 0; UInt32 bufferSize = 0; UInt32 fdiskBlock = 0; UInt32 fdiskBlockExtn = 0; UInt32 fdiskBlockNext = 0; UInt32 fdiskID = 0; disk_blk0 * fdiskMap = 0; IOMedia * media = getProvider(); UInt64 mediaBlockSize = media->getPreferredBlockSize(); bool mediaIsOpen = false; OSSet * partitions = 0; IOReturn status = kIOReturnError; // Determine whether this media is formatted. if ( media->isFormatted() == false ) goto scanErr; // Determine whether this media has an appropriate block size. if ( (mediaBlockSize % sizeof(disk_blk0)) ) goto scanErr; // Allocate a buffer large enough to hold one map, rounded to a media block. bufferSize = IORound(sizeof(disk_blk0), mediaBlockSize); buffer = IOBufferMemoryDescriptor::withCapacity( /* capacity */ bufferSize, /* withDirection */ kIODirectionIn ); if ( buffer == 0 ) goto scanErr; // Allocate a set to hold the set of media objects representing partitions. partitions = OSSet::withCapacity(4); if ( partitions == 0 ) goto scanErr; // Open the media with read access. mediaIsOpen = open(this, 0, kIOStorageAccessReader); if ( mediaIsOpen == false ) goto scanErr; // Scan the media for FDisk partition map(s). do { // Read the next FDisk map into our buffer. status = media->read(this, fdiskBlock * mediaBlockSize, buffer); if ( status != kIOReturnSuccess ) goto scanErr; fdiskMap = (disk_blk0 *) buffer->getBytesNoCopy(); // Determine whether the partition map signature is present. if ( OSSwapLittleToHostInt16(fdiskMap->signature) != DISK_SIGNATURE ) { goto scanErr; } // Scan for valid partition entries in the partition map. fdiskBlockNext = 0; for ( unsigned index = 0; index < DISK_NPART; index++ ) { // Determine whether this is an extended (vs. data) partition. if ( isPartitionExtended(fdiskMap->parts + index) ) // (extended) { // If peer extended partitions exist, we accept only the first. if ( fdiskBlockNext == 0 ) // (no peer extended partition) { fdiskBlockNext = fdiskBlockExtn + OSSwapLittleToHostInt32( /* data */ fdiskMap->parts[index].relsect ); if ( fdiskBlockNext * mediaBlockSize >= media->getSize() ) { fdiskBlockNext = 0; // (exceeds confines of media) } } } else if ( isPartitionUsed(fdiskMap->parts + index) ) // (data) { // Prepare this partition's ID. fdiskID = ( fdiskBlock == 0 ) ? (index + 1) : (fdiskID + 1); // Determine whether the partition is corrupt (fatal). if ( isPartitionCorrupt( /* partition */ fdiskMap->parts + index, /* partitionID */ fdiskID, /* fdiskBlock */ fdiskBlock ) ) { goto scanErr; } // Determine whether the partition is invalid (skipped). if ( isPartitionInvalid( /* partition */ fdiskMap->parts + index, /* partitionID */ fdiskID, /* fdiskBlock */ fdiskBlock ) ) { continue; } // Create a media object to represent this partition. IOMedia * newMedia = instantiateMediaObject( /* partition */ fdiskMap->parts + index, /* partitionID */ fdiskID, /* fdiskBlock */ fdiskBlock ); if ( newMedia ) { partitions->setObject(newMedia); newMedia->release(); } } } // Prepare for first extended partition, if any. if ( fdiskBlock == 0 ) { fdiskID = DISK_NPART; fdiskBlockExtn = fdiskBlockNext; } } while ( (fdiskBlock = fdiskBlockNext) ); // Release our resources. close(this); buffer->release(); return partitions; scanErr: // Release our resources. if ( mediaIsOpen ) close(this); if ( partitions ) partitions->release(); if ( buffer ) buffer->release(); return 0; }
int HoRNDIS::rndisCommand(struct rndis_msg_hdr *buf, int buflen) { int count; int rc = kIOReturnSuccess; IOUSBDevRequestDesc rq; IOBufferMemoryDescriptor *txdsc = IOBufferMemoryDescriptor::withCapacity(le32_to_cpu(buf->msg_len), kIODirectionOut); IOBufferMemoryDescriptor *rxdsc = IOBufferMemoryDescriptor::withCapacity(RNDIS_CMD_BUF_SZ, kIODirectionIn); if (buf->msg_type != RNDIS_MSG_HALT && buf->msg_type != RNDIS_MSG_RESET) { /* lock? */ buf->request_id = cpu_to_le32(xid++); if (!buf->request_id) buf->request_id = cpu_to_le32(xid++); } memcpy(txdsc->getBytesNoCopy(), buf, le32_to_cpu(buf->msg_len)); rq.bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND; rq.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBClass, kUSBInterface); rq.wValue = 0; rq.wIndex = fCommInterface->GetInterfaceNumber(); rq.pData = txdsc; rq.wLength = cpu_to_le32(buf->msg_len); if ((rc = fCommInterface->DeviceRequest(&rq)) != kIOReturnSuccess) goto bailout; /* Linux polls on the status channel, too; hopefully this shouldn't be needed if we're just talking to Android. */ /* Now we wait around a while for the device to get back to us. */ for (count = 0; count < 10; count++) { struct rndis_msg_hdr *inbuf = (struct rndis_msg_hdr *) rxdsc->getBytesNoCopy(); IOUSBDevRequestDesc rxrq; memset(inbuf, 0, RNDIS_CMD_BUF_SZ); rxrq.bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE; rxrq.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBClass, kUSBInterface); rxrq.wValue = 0; rxrq.wIndex = fCommInterface->GetInterfaceNumber(); rxrq.pData = rxdsc; rxrq.wLength = RNDIS_CMD_BUF_SZ; if ((rc = fCommInterface->DeviceRequest(&rxrq)) != kIOReturnSuccess) goto bailout; if (rxrq.wLenDone < 8) { LOG(V_ERROR, "short read on control request?"); IOSleep(20); continue; } if (inbuf->msg_type == (buf->msg_type | RNDIS_MSG_COMPLETION)) { if (inbuf->request_id == buf->request_id) { if (inbuf->msg_type == RNDIS_MSG_RESET_C) break; if (inbuf->status == RNDIS_STATUS_SUCCESS) { /* ...and copy it out! */ LOG(V_DEBUG, "RNDIS command completed"); memcpy(buf, inbuf, le32_to_cpu(rxrq.wLenDone)); break; } LOG(V_ERROR, "RNDIS command returned status %08x", inbuf->status); rc = -1; break; } else { LOG(V_ERROR, "RNDIS return had incorrect xid?"); } } else { switch (inbuf->msg_type) { case RNDIS_MSG_INDICATE: LOG(V_ERROR, "unsupported: RNDIS_MSG_INDICATE"); break; case RNDIS_MSG_KEEPALIVE: LOG(V_ERROR, "unsupported: RNDIS_MSG_KEEPALIVE"); break; default: LOG(V_ERROR, "unexpected msg type %08x, msg_len %08x", inbuf->msg_type, inbuf->msg_len); break; } } IOSleep(20); } if (count == 10) { LOG(V_ERROR, "command timed out?"); rc = kIOReturnTimeout; } bailout: txdsc->complete(); txdsc->release(); rxdsc->complete(); rxdsc->release(); return rc; }
IOReturn IOUSBController::CheckForDisjointDescriptor(IOUSBCommand *command, UInt16 maxPacketSize) { IOMemoryDescriptor *buf = command->GetBuffer(); IOBufferMemoryDescriptor *newBuf = NULL; IOByteCount length = command->GetReqCount(); IODMACommand *dmaCommand = command->GetDMACommand(); IOByteCount segLength = 0; IOByteCount offset = 0; IOReturn err; UInt64 offset64; IODMACommand::Segment64 segment64; UInt32 numSegments; // USBTrace_Start( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this ); // Zero length buffers are valid, but they are surely not disjoint, so just return success. // if ( length == 0 ) return kIOReturnSuccess; if (!dmaCommand) { USBLog(1, "%s[%p]::CheckForDisjointDescriptor - no dmaCommand", getName(), this); USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this, kIOReturnBadArgument, 0, 1 ); return kIOReturnBadArgument; } if (dmaCommand->getMemoryDescriptor() != buf) { USBLog(1, "%s[%p]::CheckForDisjointDescriptor - mismatched memory descriptor (%p) and dmaCommand memory descriptor (%p)", getName(), this, buf, dmaCommand->getMemoryDescriptor()); USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, kIOReturnBadArgument, (uintptr_t)buf, (uintptr_t)dmaCommand->getMemoryDescriptor(), 2 ); return kIOReturnBadArgument; } while (length) { offset64 = offset; numSegments = 1; err = dmaCommand->gen64IOVMSegments(&offset64, &segment64, &numSegments); if (err || (numSegments != 1)) { USBLog(1, "%s[%p]::CheckForDisjointDescriptor - err (%p) trying to generate segments at offset (%qd), length (%d), segLength (%d), total length (%d), buf (%p), numSegments (%d)", getName(), this, (void*)err, offset64, (int)length, (int)segLength, (int)command->GetReqCount(), buf, (int)numSegments); USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, offset64, length, segLength, 3 ); USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, segLength, command->GetReqCount(), numSegments, 4 ); return kIOReturnBadArgument; } // 3036056 since length might be less than the length of the descriptor, we are OK if the physical // segment is longer than we need if (segment64.fLength >= length) return kIOReturnSuccess; // this is the last segment, so we are OK // since length is a 32 bit quantity, then we know from the above statement that if we are here we are 32 bit only segLength = (IOByteCount)segment64.fLength; // so the segment is less than the rest of the length - we need to check against maxPacketSize if (segLength % maxPacketSize) { // this is the error case. I need to copy the descriptor to a new descriptor and remember that I did it USBLog(6, "%s[%p]::CheckForDisjointDescriptor - found a disjoint segment of length (%d) MPS (%d)", getName(), this, (int)segLength, maxPacketSize); length = command->GetReqCount(); // we will not return to the while loop, so don't worry about changing the value of length // allocate a new descriptor which is the same total length as the old one newBuf = IOBufferMemoryDescriptor::withOptions((command->GetDirection() == kUSBIn) ? kIODirectionIn : kIODirectionOut, length); if (!newBuf) { USBLog(1, "%s[%p]::CheckForDisjointDescriptor - could not allocate new buffer", getName(), this); USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this, kIOReturnNoMemory, 0, 5 ); return kIOReturnNoMemory; } USBLog(7, "%s[%p]::CheckForDisjointDescriptor, obtained buffer %p of length %d", getName(), this, newBuf, (int)length); // first close out (and complete) the original dma command descriptor USBLog(7, "%s[%p]::CheckForDisjointDescriptor, clearing memDec (%p) from dmaCommand (%p)", getName(), this, dmaCommand->getMemoryDescriptor(), dmaCommand); dmaCommand->clearMemoryDescriptor(); // copy the bytes to the buffer if necessary if (command->GetDirection() == kUSBOut) { USBLog(7, "%s[%p]::CheckForDisjointDescriptor, copying %d bytes from desc %p to buffer %p", getName(), this, (int)length, buf, newBuf->getBytesNoCopy()); if (buf->readBytes(0, newBuf->getBytesNoCopy(), length) != length) { USBLog(1, "%s[%p]::CheckForDisjointDescriptor - bad copy on a write", getName(), this); USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this, 0, 0, 6 ); newBuf->release(); return kIOReturnNoMemory; } } err = newBuf->prepare(); if (err) { USBLog(1, "%s[%p]::CheckForDisjointDescriptor - err 0x%x in prepare", getName(), this, err); USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this, err, 0, 7 ); newBuf->release(); return err; } err = dmaCommand->setMemoryDescriptor(newBuf); if (err) { USBLog(1, "%s[%p]::CheckForDisjointDescriptor - err 0x%x in setMemoryDescriptor", getName(), this, err); USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this, err, 0, 8 ); newBuf->complete(); newBuf->release(); return err; } command->SetOrigBuffer(command->GetBuffer()); command->SetDisjointCompletion(command->GetClientCompletion()); USBLog(7, "%s[%p]::CheckForDisjointDescriptor - changing buffer from (%p) to (%p) and putting new buffer in dmaCommand (%p)", getName(), this, command->GetBuffer(), newBuf, dmaCommand); command->SetBuffer(newBuf); IOUSBCompletion completion; completion.target = this; completion.action = (IOUSBCompletionAction)DisjointCompletion; completion.parameter = command; command->SetClientCompletion(completion); command->SetDblBufLength(length); // for the IOFree - the other buffer may change size return kIOReturnSuccess; } length -= segLength; // adjust our master length pointer offset += segLength; } USBLog(5, "%s[%p]::CheckForDisjointDescriptor - returning kIOReturnBadArgument(0x%x)", getName(), this, kIOReturnBadArgument); // USBTrace_End( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this, kIOReturnBadArgument); return kIOReturnBadArgument; }
IOReturn AppleFileSystemDriver::readHFSUUID(IOMedia *media, void **uuidPtr) { bool mediaIsOpen = false; UInt64 mediaBlockSize = 0; IOBufferMemoryDescriptor * buffer = 0; uint8_t * bytes = 0; UInt64 bytesAt = 0; UInt64 bufferReadAt = 0; vm_size_t bufferSize = 0; IOReturn status = kIOReturnError; HFSMasterDirectoryBlock * mdbPtr = 0; HFSPlusVolumeHeader * volHdrPtr = 0; VolumeUUID * volumeUUIDPtr = (VolumeUUID *)uuidPtr; DEBUG_LOG("%s::%s\n", kClassName, __func__); do { mediaBlockSize = media->getPreferredBlockSize(); bufferSize = IORound(sizeof(HFSMasterDirectoryBlock), mediaBlockSize); buffer = IOBufferMemoryDescriptor::withCapacity(bufferSize, kIODirectionIn); if ( buffer == 0 ) break; bytes = (uint8_t *) buffer->getBytesNoCopy(); // Open the media with read access. mediaIsOpen = media->open(media, 0, kIOStorageAccessReader); if ( mediaIsOpen == false ) break; bytesAt = 2 * kHFSBlockSize; bufferReadAt = IOTrunc( bytesAt, mediaBlockSize ); bytesAt -= bufferReadAt; mdbPtr = (HFSMasterDirectoryBlock *)&bytes[bytesAt]; volHdrPtr = (HFSPlusVolumeHeader *)&bytes[bytesAt]; status = media->read(media, bufferReadAt, buffer); if ( status != kIOReturnSuccess ) break; /* * If this is a wrapped HFS Plus volume, read the Volume Header from * sector 2 of the embedded volume. */ if ( OSSwapBigToHostInt16(mdbPtr->drSigWord) == kHFSSigWord && OSSwapBigToHostInt16(mdbPtr->drEmbedSigWord) == kHFSPlusSigWord) { u_int32_t allocationBlockSize, firstAllocationBlock, startBlock, blockCount; if (OSSwapBigToHostInt16(mdbPtr->drSigWord) != kHFSSigWord) { break; } allocationBlockSize = OSSwapBigToHostInt32(mdbPtr->drAlBlkSiz); firstAllocationBlock = OSSwapBigToHostInt16(mdbPtr->drAlBlSt); if (OSSwapBigToHostInt16(mdbPtr->drEmbedSigWord) != kHFSPlusSigWord) { break; } startBlock = OSSwapBigToHostInt16(mdbPtr->drEmbedExtent.startBlock); blockCount = OSSwapBigToHostInt16(mdbPtr->drEmbedExtent.blockCount); bytesAt = ((u_int64_t)startBlock * (u_int64_t)allocationBlockSize) + ((u_int64_t)firstAllocationBlock * (u_int64_t)kHFSBlockSize) + (u_int64_t)(2 * kHFSBlockSize); bufferReadAt = IOTrunc( bytesAt, mediaBlockSize ); bytesAt -= bufferReadAt; mdbPtr = (HFSMasterDirectoryBlock *)&bytes[bytesAt]; volHdrPtr = (HFSPlusVolumeHeader *)&bytes[bytesAt]; status = media->read(media, bufferReadAt, buffer); if ( status != kIOReturnSuccess ) break; } /* * At this point, we have the MDB for plain HFS, or VHB for HFS Plus and HFSX * volumes (including wrapped HFS Plus). Verify the signature and grab the * UUID from the Finder Info. */ if (OSSwapBigToHostInt16(mdbPtr->drSigWord) == kHFSSigWord) { bcopy((void *)&mdbPtr->drFndrInfo[6], volumeUUIDPtr->bytes, kVolumeUUIDValueLength); status = kIOReturnSuccess; } else if (OSSwapBigToHostInt16(volHdrPtr->signature) == kHFSPlusSigWord || OSSwapBigToHostInt16(volHdrPtr->signature) == kHFSXSigWord) { bcopy((void *)&volHdrPtr->finderInfo[24], volumeUUIDPtr->bytes, kVolumeUUIDValueLength); status = kIOReturnSuccess; } else { // status = 0 from earlier successful media->read() status = kIOReturnBadMedia; } } while (false); if ( mediaIsOpen ) media->close(media); if ( buffer ) buffer->release(); DEBUG_LOG("%s::%s finishes with status %d\n", kClassName, __func__, status); return status; }
IOReturn IOCDBlockStorageDriver::cacheTocInfo(void) { IOBufferMemoryDescriptor *buffer; IOReturn result; CDTOC *toc; UInt16 tocSize; assert(sizeof(CDTOC) == 4); /* (compiler/platform check) */ assert(sizeof(CDTOCDescriptor) == 11); /* (compiler/platform check) */ assert(_toc == NULL); /* Read the TOC header: */ buffer = IOBufferMemoryDescriptor::withCapacity(sizeof(CDTOC),kIODirectionIn); if (buffer == NULL) { return(kIOReturnNoMemory); } result = getProvider()->readTOC(buffer); if (result != kIOReturnSuccess) { buffer->release(); return(result); } toc = (CDTOC *) buffer->getBytesNoCopy(); tocSize = OSSwapBigToHostInt16(toc->length) + sizeof(toc->length); buffer->release(); /* Reject the TOC if its size is too small: */ if (tocSize <= sizeof(CDTOC)) { return(kIOReturnNotFound); } /* Read the TOC in full: */ buffer = IOBufferMemoryDescriptor::withCapacity(tocSize,kIODirectionIn); if (buffer == NULL) { return(kIOReturnNoMemory); } result = getProvider()->readTOC(buffer); if (result != kIOReturnSuccess) { buffer->release(); return(result); } toc = (CDTOC *) IOMalloc(tocSize); if (toc == NULL) { buffer->release(); return(kIOReturnNoMemory); } if (buffer->readBytes(0,toc,tocSize) != tocSize) { buffer->release(); IOFree(toc,tocSize); return(kIOReturnNoMemory); } _toc = toc; _tocSize = tocSize; buffer->release(); return(result); }
OSSet * IOGUIDPartitionScheme::scan(SInt32 * score) { // // Scan the provider media for a GUID partition map. Returns the set // of media objects representing each of the partitions (the retain for // the set is passed to the caller), or null should no partition map be // found. The default probe score can be adjusted up or down, based on // the confidence of the scan. // IOBufferMemoryDescriptor * buffer = 0; IOByteCount bufferSize = 0; UInt32 fdiskID = 0; disk_blk0 * fdiskMap = 0; UInt64 gptBlock = 0; UInt32 gptCheck = 0; UInt32 gptCount = 0; UInt32 gptID = 0; gpt_ent * gptMap = 0; UInt32 gptSize = 0; UInt32 headerCheck = 0; gpt_hdr * headerMap = 0; UInt32 headerSize = 0; IOMedia * media = getProvider(); UInt64 mediaBlockSize = media->getPreferredBlockSize(); bool mediaIsOpen = false; OSSet * partitions = 0; IOReturn status = kIOReturnError; // Determine whether this media is formatted. if ( media->isFormatted() == false ) goto scanErr; // Determine whether this media has an appropriate block size. if ( (mediaBlockSize % sizeof(disk_blk0)) ) goto scanErr; // Allocate a buffer large enough to hold one map, rounded to a media block. bufferSize = IORound(sizeof(disk_blk0), mediaBlockSize); buffer = IOBufferMemoryDescriptor::withCapacity( /* capacity */ bufferSize, /* withDirection */ kIODirectionIn ); if ( buffer == 0 ) goto scanErr; // Allocate a set to hold the set of media objects representing partitions. partitions = OSSet::withCapacity(8); if ( partitions == 0 ) goto scanErr; // Open the media with read access. mediaIsOpen = open(this, 0, kIOStorageAccessReader); if ( mediaIsOpen == false ) goto scanErr; // Read the protective map into our buffer. status = media->read(this, 0, buffer); if ( status != kIOReturnSuccess ) goto scanErr; fdiskMap = (disk_blk0 *) buffer->getBytesNoCopy(); // Determine whether the protective map signature is present. if ( OSSwapLittleToHostInt16(fdiskMap->signature) != DISK_SIGNATURE ) { goto scanErr; } // Scan for valid partition entries in the protective map. for ( unsigned index = 0; index < DISK_NPART; index++ ) { if ( fdiskMap->parts[index].systid ) { if ( fdiskMap->parts[index].systid == 0xEE ) { if ( fdiskID ) goto scanErr; fdiskID = index + 1; } } } if ( fdiskID == 0 ) goto scanErr; // Read the partition header into our buffer. status = media->read(this, mediaBlockSize, buffer); if ( status != kIOReturnSuccess ) goto scanErr; headerMap = (gpt_hdr *) buffer->getBytesNoCopy(); // Determine whether the partition header signature is present. if ( memcmp(headerMap->hdr_sig, GPT_HDR_SIG, strlen(GPT_HDR_SIG)) ) { goto scanErr; } // Determine whether the partition header size is valid. headerCheck = OSSwapLittleToHostInt32(headerMap->hdr_crc_self); headerSize = OSSwapLittleToHostInt32(headerMap->hdr_size); if ( headerSize < offsetof(gpt_hdr, padding) ) { goto scanErr; } if ( headerSize > mediaBlockSize ) { goto scanErr; } // Determine whether the partition header checksum is valid. headerMap->hdr_crc_self = 0; if ( crc32(0, headerMap, headerSize) != headerCheck ) { goto scanErr; } // Determine whether the partition entry size is valid. gptCheck = OSSwapLittleToHostInt32(headerMap->hdr_crc_table); gptSize = OSSwapLittleToHostInt32(headerMap->hdr_entsz); if ( gptSize < sizeof(gpt_ent) ) { goto scanErr; } if ( gptSize > UINT16_MAX ) { goto scanErr; } // Determine whether the partition entry count is valid. gptBlock = OSSwapLittleToHostInt64(headerMap->hdr_lba_table); gptCount = OSSwapLittleToHostInt32(headerMap->hdr_entries); if ( gptCount > UINT16_MAX ) { goto scanErr; } // Allocate a buffer large enough to hold one map, rounded to a media block. buffer->release(); bufferSize = IORound(gptCount * gptSize, mediaBlockSize); buffer = IOBufferMemoryDescriptor::withCapacity( /* capacity */ bufferSize, /* withDirection */ kIODirectionIn ); if ( buffer == 0 ) goto scanErr; // Read the partition header into our buffer. status = media->read(this, gptBlock * mediaBlockSize, buffer); if ( status != kIOReturnSuccess ) goto scanErr; gptMap = (gpt_ent *) buffer->getBytesNoCopy(); // Determine whether the partition entry checksum is valid. if ( crc32(0, gptMap, gptCount * gptSize) != gptCheck ) { goto scanErr; } // Scan for valid partition entries in the partition map. for ( gptID = 1; gptID <= gptCount; gptID++ ) { gptMap = (gpt_ent *) ( ((UInt8 *) buffer->getBytesNoCopy()) + (gptID * gptSize) - gptSize ); uuid_unswap( gptMap->ent_type ); uuid_unswap( gptMap->ent_uuid ); if ( isPartitionUsed( gptMap ) ) { // Determine whether the partition is corrupt (fatal). if ( isPartitionCorrupt( gptMap, gptID ) ) { goto scanErr; } // Determine whether the partition is invalid (skipped). if ( isPartitionInvalid( gptMap, gptID ) ) { continue; } // Create a media object to represent this partition. IOMedia * newMedia = instantiateMediaObject( gptMap, gptID ); if ( newMedia ) { partitions->setObject(newMedia); newMedia->release(); } } } // Release our resources. close(this); buffer->release(); return partitions; scanErr: // Release our resources. if ( mediaIsOpen ) close(this); if ( partitions ) partitions->release(); if ( buffer ) buffer->release(); return 0; }
static void DisjointCompletion(IOUSBController *me, IOUSBCommand *command, IOReturn status, UInt32 bufferSizeRemaining) { IOBufferMemoryDescriptor *buf = NULL; IODMACommand *dmaCommand = NULL; USBTrace_Start( kUSBTController, kTPControllerDisjointCompletion, (uintptr_t)me, (uintptr_t)command, status, bufferSizeRemaining ); if (!me || !command) { USBError(1, "DisjointCompletion sanity check failed - me(%p) command (%p)", me, command); return; } buf = OSDynamicCast(IOBufferMemoryDescriptor, command->GetBuffer()); dmaCommand = command->GetDMACommand(); if (!dmaCommand || !buf) { USBLog(1, "%s[%p]::DisjointCompletion - no dmaCommand, or buf(%p) is not an IOBMD", me->getName(), me, command->GetBuffer()); USBTrace( kUSBTController, kTPControllerDisjointCompletion, (uintptr_t)me, (uintptr_t)command->GetBuffer(), 0, 1 ); return; } if (dmaCommand->getMemoryDescriptor()) { if (dmaCommand->getMemoryDescriptor() != buf) { USBLog(1, "%s[%p]::DisjointCompletion - buf(%p) doesn't match getMemoryDescriptor(%p)", me->getName(), me, buf, dmaCommand->getMemoryDescriptor()); USBTrace( kUSBTController, kTPControllerDisjointCompletion, (uintptr_t)me, (uintptr_t)buf, (uintptr_t)dmaCommand->getMemoryDescriptor(), 2 ); } // need to complete the dma command USBLog(6, "%s[%p]::DisjointCompletion - clearing memory descriptor (%p) from dmaCommand (%p)", me->getName(), me, dmaCommand->getMemoryDescriptor(), dmaCommand); dmaCommand->clearMemoryDescriptor(); } if (command->GetDirection() == kUSBIn) { USBLog(5, "%s[%p]::DisjointCompletion, copying %d out of %d bytes to desc %p from buffer %p", me->getName(), me, (int)(command->GetDblBufLength()-bufferSizeRemaining), (int)command->GetDblBufLength(), command->GetOrigBuffer(), buf); command->GetOrigBuffer()->writeBytes(0, buf->getBytesNoCopy(), (command->GetDblBufLength()-bufferSizeRemaining)); } buf->complete(); buf->release(); // done with this buffer command->SetBuffer(NULL); // now call through to the original completion routine IOUSBCompletion completion = command->GetDisjointCompletion(); if ( !command->GetIsSyncTransfer() ) { // Free our command now that we have the completion and we are not going to use it anymore me->ReturnUSBCommand(command); } if (completion.action) { USBLog(status == kIOReturnSuccess ? 7 : 3, "%s[%p]::DisjointCompletion calling through to %p - status 0x%x!", me->getName(), me, completion.action, (uint32_t)status); (*completion.action)(completion.target, completion.parameter, status, bufferSizeRemaining); } USBTrace_End( kUSBTController, kTPControllerDisjointCompletion, (uintptr_t)completion.target, (uintptr_t)completion.parameter, status, bufferSizeRemaining); }
void VoodooI2CHIDDevice::i2c_hid_get_input(OSObject* owner, IOTimerEventSource* sender) { // IOLog("getting input\n"); UInt rsize; int ret; static unsigned char* rdesc_prev = NULL; static UInt rsize_prev = 0; bool new_report = true; rsize = UInt16(ihid->hdesc.wMaxInputLength); unsigned char* rdesc = (unsigned char *)IOMalloc(rsize); ret = i2c_hid_command(ihid, &hid_input_cmd, rdesc, rsize); // IOLog("===Input (%d)===\n", rsize); // for (int i = 0; i < rsize; i++) // IOLog("0x%02x ", (UInt8) rdesc[i]); // IOLog("\n"); int return_size = rdesc[0] | rdesc[1] << 8; if (return_size == 0) { /* host or device initiated RESET completed */ // test/clear bit? hid_device->timerSource->setTimeoutMS(10); return; } if (return_size > rsize) { IOLog("%s: Incomplete report %d/%d\n", __func__, rsize, return_size); } IOBufferMemoryDescriptor *buffer = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, 0, return_size); buffer->writeBytes(0, rdesc + 2, return_size - 2); #define FILTER_REPEATED_REPORTS /* Needed on my ASUS/Skylake ELAN1000 */ #ifdef FILTER_REPEATED_REPORTS /* Compare to previous report */ if (rdesc_prev) { /* See if they're different! */ if (rsize == rsize_prev) { if (memcmp(rdesc_prev, rdesc, rsize)) { new_report = true; } else { new_report = false; } } else { new_report = true; } /* We don't need the previous report anymore */ IOFree(rdesc_prev, rsize_prev); } else { new_report = true; } /* Keep for next comparison */ rdesc_prev = rdesc; rsize_prev = rsize; if (new_report) { IOReturn err = _wrapper->handleReport(buffer, kIOHIDReportTypeInput); if (err != kIOReturnSuccess) IOLog("Error handling report: 0x%.8x\n", err); } #else /* non filtered for repeating reports */ IOReturn err = _wrapper->handleReport(buffer, kIOHIDReportTypeInput); if (err != kIOReturnSuccess) IOLog("Error handling report: 0x%.8x\n", err); #endif buffer->release(); #ifndef FILTER_REPEATED_REPORTS IOFree(rdesc, rsize); #endif hid_device->timerSource->setTimeoutMS(10); }