// 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; }
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; }
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); }
// 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; } }
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); }