// adds all elements to queue, performing any device queue set up required // queue is started and ready to return events on exit from this function int HIDQueueDevice( IOHIDDeviceRef inIOHIDDeviceRef ) { IOReturn result = kIOReturnSuccess; // error checking if ( !inIOHIDDeviceRef ) { HIDReportError( "Device does not exist, cannot queue device." ); return kIOReturnBadArgument; } if ( !inIOHIDDeviceRef ) { // must have interface HIDReportError( "Device does not have hid device ref, cannot queue device." ); return kIOReturnError; } IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue( inIOHIDDeviceRef ); if ( !tIOHIDQueueRef ) { // if no queue create queue result = HIDCreateQueue( inIOHIDDeviceRef ); if ( kIOReturnSuccess == result ) { tIOHIDQueueRef = IOHIDDevice_GetQueue( inIOHIDDeviceRef ); } } if ( ( kIOReturnSuccess != result ) || ( !tIOHIDQueueRef ) ) { HIDReportErrorNum( "Could not queue device due to problem creating queue.", result ); if ( kIOReturnSuccess != result ) { return result; } else { return kIOReturnError; } } // stop queue IOHIDQueueStop( tIOHIDQueueRef ); // queue element IOHIDElementRef tIOHIDElementRef = HIDGetFirstDeviceElement( inIOHIDDeviceRef, kHIDElementTypeIO ); while ( tIOHIDElementRef ) { if ( !IOHIDQueueContainsElement( tIOHIDQueueRef, tIOHIDElementRef ) ) { IOHIDQueueAddElement( tIOHIDQueueRef, tIOHIDElementRef ); } tIOHIDElementRef = HIDGetNextDeviceElement( tIOHIDElementRef, kHIDElementTypeIO ); } // restart queue IOHIDQueueStart( tIOHIDQueueRef ); return result; } /* HIDQueueDevice */
// queues specific element, performing any device queue set up required // queue is started and ready to return events on exit from this function int HIDQueueElement( IOHIDDeviceRef inIOHIDDeviceRef, IOHIDElementRef inIOHIDElementRef ) { IOReturn result = kIOReturnSuccess; if ( inIOHIDDeviceRef ) { assert( IOHIDDeviceGetTypeID() == CFGetTypeID( inIOHIDDeviceRef ) ); if ( inIOHIDElementRef ) { assert( IOHIDElementGetTypeID() == CFGetTypeID( inIOHIDElementRef ) ); IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue( inIOHIDDeviceRef ); if ( !tIOHIDQueueRef ) { // if no queue create queue result = HIDCreateQueue( inIOHIDDeviceRef ); if ( kIOReturnSuccess == result ) { tIOHIDQueueRef = IOHIDDevice_GetQueue( inIOHIDDeviceRef ); } } if ( tIOHIDQueueRef ) { // stop queue IOHIDQueueStop( tIOHIDQueueRef ); // queue element if ( !IOHIDQueueContainsElement( tIOHIDQueueRef, inIOHIDElementRef ) ) { IOHIDQueueAddElement( tIOHIDQueueRef, inIOHIDElementRef ); } // restart queue IOHIDQueueStart( tIOHIDQueueRef ); } else { HIDReportError( "No queue for device passed to HIDQueueElement." ); if ( kIOReturnSuccess == result ) { result = kIOReturnError; } } } else { HIDReportError( "NULL element passed to HIDQueueElement." ); result = kIOReturnBadArgument; } } else { HIDReportError( "NULL device passed to HIDQueueElement." ); result = kIOReturnBadArgument; } return result; } /* HIDQueueElement */
// Put element into the dictionary and into the queue: PsychError PsychHIDOSKbElementAdd(IOHIDElementRef element, IOHIDQueueRef queue, int deviceIndex) { // If at least one keyboard style device is detected, mark this queue as keyboard queue: if (IOHIDElementGetUsagePage(element) == kHIDPage_KeyboardOrKeypad) queueIsAKeyboard[deviceIndex] = TRUE; // Avoid redundant assignment to same keycode: if (IOHIDQueueContainsElement(queue, element)) { if (getenv("PSYCHHID_TELLME")) printf("--> Key %i Already assigned --> Skipping.\n", IOHIDElementGetUsage(element) - 1); return(PsychError_none); } if (getenv("PSYCHHID_TELLME")) { printf("--> Accepting key %i as new KbQueue element%s.\n", IOHIDElementGetUsage(element) - 1, (queueIsAKeyboard) ? " for a keyboard" : ""); } // Put the element cookie into the queue: IOHIDQueueAddElement(queue, element); return(PsychError_none); }
void osxHIDInputDevice::AddDevice(void *context, IOReturn /*result*/, void */*sender*/, IOHIDDeviceRef device) { osxHIDInputDevice *self = (osxHIDInputDevice*)context ; URI devUri = hidDeviceURI(device) ; // std::cerr << std::endl << self->uri.asString() << std::endl << devUri.asString() << std::endl << std::endl ; bool match = self->theDevice==0 && (self->uri.isEmpty() || self->uri.scheme=="any" || self->uri.resemble(devUri)) ; if (self->debugLevel>0) { std::cerr << (match?"+ ":" ") ; hidDebugDevice(device, std::cerr) ; std::cerr << std::endl ; } if (!match) return ; self->theDevice = new __device(device) ; self->uri = devUri ; CFDataRef descriptor = (CFDataRef)IOHIDDeviceGetProperty(self->theDevice->device, CFSTR(kIOHIDReportDescriptorKey)) ; if (descriptor) { const UInt8 *bytes = CFDataGetBytePtr(descriptor) ; CFIndex length = CFDataGetLength(descriptor) ; if (self->inputreport_callback && !self->parser->setDescriptor(bytes, length)) std::cerr << "osxHIDInputDevice::AddDevice: unable to parse the HID report descriptor" << std::endl; if (self->debugLevel > 1) { std::cerr << " HID report descriptor: [ " << std::flush ; for (int i=0; i<length; ++i) std::cerr << std::hex << std::setfill('0') << std::setw(2) << (int)bytes[i] << " " ; std::cerr << "]" << std::endl ; } } #if DEBUG_MODE std::cerr << "Setting up callbacks" << std::endl ; #endif // ---------------------------------------------------------------- if (self->inputreport_callback) { #if DEBUG_MODE std::cerr << "Setting up report callback" << std::endl ; #endif #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000 IOHIDDeviceRegisterInputReportWithTimeStampCallback(device, self->theDevice->report, sizeof(self->theDevice->report), self->inputreport_callback, self->inputreport_context) ; #else IOHIDDeviceRegisterInputReportCallback(device, self->theDevice->report, sizeof(self->theDevice->report), self->inputreport_callback, self->inputreport_context) ; #endif } // ---------------------------------------------------------------- if (self->value_callback) { #if DEBUG_MODE std::cerr << "Setting up value callback" << std::endl ; #endif IOHIDDeviceSetInputValueMatchingMultiple(device, self->elements_match) ; IOHIDDeviceRegisterInputValueCallback(device, self->value_callback, self->value_context) ; } // ---------------------------------------------------------------- if (self->queue_callback) { #if DEBUG_MODE std::cerr << "Setting up queue callback" << std::endl ; #endif self->theDevice->queue = IOHIDQueueCreate(kCFAllocatorDefault, device, queueSize, kIOHIDOptionsTypeNone) ; if (self->elements_match) { #if DEBUG && DEBUG_MATCHING_ELEMENTS std::cerr << "Queue, elements_match" << std::endl ; #endif CFIndex mcount = CFArrayGetCount(self->elements_match) ; for (CFIndex mindex=0; mindex<mcount; ++mindex) { CFDictionaryRef matching = (CFDictionaryRef)CFArrayGetValueAtIndex(self->elements_match, mindex) ; CFArrayRef elements = IOHIDDeviceCopyMatchingElements(device, matching, kIOHIDOptionsTypeNone) ; if (!elements) continue ; CFIndex ecount = CFArrayGetCount(elements) ; for (CFIndex eindex=0; eindex<ecount; ++eindex) { IOHIDElementRef e = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, eindex) ; IOHIDQueueAddElement(self->theDevice->queue, e) ; #if DEBUG && DEBUG_MATCHING_ELEMENTS std::cerr << "elements_match EINDEX: " << eindex << ", usagepage: " << IOHIDElementGetUsagePage(e) << ", usage: " << IOHIDElementGetUsage(e) << std::endl ; #endif } } } else { #if DEBUG && DEBUG_MATCHING_ELEMENTS std::cerr << "Queue, no elements_match" << std::endl ; #endif CFArrayRef elements = IOHIDDeviceCopyMatchingElements(device, 0, kIOHIDOptionsTypeNone) ; if (elements) { CFIndex ecount = CFArrayGetCount(elements) ; for (CFIndex eindex=0; eindex<ecount; ++eindex) { IOHIDElementRef e = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, eindex) ; IOHIDQueueAddElement(self->theDevice->queue, e) ; #if DEBUG && DEBUG_MATCHING_ELEMENTS std::cerr << "!elements_match EINDEX: " << eindex << ", usagepage: " << IOHIDElementGetUsagePage(e) << ", usage: " << IOHIDElementGetUsage(e) << std::endl ; #endif } } } IOHIDQueueRegisterValueAvailableCallback(self->theDevice->queue, self->queue_callback, self->queue_context) ; IOHIDQueueScheduleWithRunLoop(self->theDevice->queue, CFRunLoopGetMain(), kCFRunLoopDefaultMode) ; IOHIDQueueStart(self->theDevice->queue) ; } // ---------------------------------------------------------------- }