// 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 */
void PsychHIDOSKbQueueStart(int deviceIndex)
{
	psych_bool queueActive;
	int i;

    // Get true keyboardqueue index assigned to deviceIndex from original user provided deviceIndex:
    deviceIndex = PsychHIDOSGetKbQueueDevice(deviceIndex, NULL);

	// Does Keyboard queue for this deviceIndex already exist?
	if (NULL == psychHIDKbQueueFirstPress[deviceIndex]) {
		// No. Bad bad...
		printf("PsychHID-ERROR: Tried to start processing on non-existent keyboard queue for deviceIndex %i! Call KbQueueCreate first!\n", deviceIndex);
		PsychErrorExitMsg(PsychError_user, "Invalid keyboard 'deviceIndex' specified. No queue for that device yet!");
	}

	// Keyboard queue already stopped? Then we ain't nothing to do:
	if (psychHIDKbQueueActive[deviceIndex]) return;

	// Queue is inactive. Start it:

	// Will this be the first active queue, ie., aren't there any queues running so far?
	queueActive = FALSE;
	for (i = 0; i < PSYCH_HID_MAX_DEVICES; i++) {
		queueActive |= psychHIDKbQueueActive[i];
	}

	PsychLockMutex(&KbQueueMutex);

	// Clear out current state for this queue:
	memset(psychHIDKbQueueFirstPress[deviceIndex]   , 0, (256 * sizeof(double)));
	memset(psychHIDKbQueueFirstRelease[deviceIndex] , 0, (256 * sizeof(double)));
	memset(psychHIDKbQueueLastPress[deviceIndex]    , 0, (256 * sizeof(double)));
	memset(psychHIDKbQueueLastRelease[deviceIndex]  , 0, (256 * sizeof(double)));
    modifierKeyState[deviceIndex] = 0;

    // Start event collection in the queue:
    IOHIDQueueStart(queue[deviceIndex]);
    
	// Mark this queue as logically started:
	psychHIDKbQueueActive[deviceIndex] = TRUE;

	// Queue started.
	PsychUnlockMutex(&KbQueueMutex);

	return;
}
// ---------------------------------
// removes element for queue, if last element in queue will release queue and closes device interface
int  HIDDequeueElement( 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 ) {
				// stop queue
				IOHIDQueueStop( tIOHIDQueueRef );
				
				// de-queue element
				if ( IOHIDQueueContainsElement( tIOHIDQueueRef, inIOHIDElementRef ) ) {
					IOHIDQueueRemoveElement( tIOHIDQueueRef, inIOHIDElementRef );
				}
				
				// release device queue and close interface if queue empty
				if ( HIDIsDeviceQueueEmpty( inIOHIDDeviceRef ) ) {
					result = HIDDisposeReleaseQueue( inIOHIDDeviceRef );
					
					if ( kIOReturnSuccess != result ) {
						HIDReportErrorNum( "Failed to dispose and release queue.", result );
					}
				} else { // not empty so restart queue
					IOHIDQueueStart( tIOHIDQueueRef );
				}
			} else {
				HIDReportError( "No queue for device passed to HIDDequeueElement." );
				if ( kIOReturnSuccess == result ) {
					result = kIOReturnError;
				}
			}
		} else {
			HIDReportError( "NULL element passed to HIDDequeueElement." );
			result = kIOReturnBadArgument;
		}
	} else {
		HIDReportError( "NULL device passed to HIDDequeueElement." );
		result = kIOReturnBadArgument;
	}
	return result;
} /* HIDDequeueElement */
// 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 */
Ejemplo n.º 5
0
  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) ;
    }

    // ----------------------------------------------------------------
  }