/*
    PSYCHHIDCheckInit() 
    
    Check to see if we need to create the USB-HID device list. If it has not been created then create it.   
*/
void PsychHIDVerifyInit(void)
{
    psych_bool success = TRUE;
    
    // Build HID device list if it doesn't already exist:
    if (!HIDHaveDeviceList()) success = (psych_bool) HIDBuildDeviceList(0, 0);
    
    // This check can only be made against the 64-Bit HID Utilities, as the older 32-Bit
    // version is even more crappy and can't report meaningful error status:
    #if defined(__LP64__)
    if (!success) {
        printf("PsychHID-ERROR: Could not enumerate HID devices (HIDBuildDeviceList() failed)! There can be various reasons,\n");
        printf("PsychHID-ERROR: ranging from bugs in Apples HID software to a buggy HID device driver for some connected device,\n");
        printf("PsychHID-ERROR: to general operating system malfunction. A reboot or device driver update for 3rd party HID devices\n");
        printf("PsychHID-ERROR: maybe could help. Check the OSX system log for possible HID related error messages or hints. Aborting...\n");
        PsychErrorExitMsg(PsychError_system, "HID device enumeration failed due to malfunction in the OSX 64 Bit Apple HID Utilities framework.");
    }
    #endif
    
    // Double-Check to protect against pathetic Apple software:
    if (!HIDHaveDeviceList()) {
        printf("PsychHID-ERROR: Could not enumerate HID devices (HIDBuildDeviceList() success, but HIDHaveDeviceList() still failed)!\n");
        printf("PsychHID-ERROR: Reasons can be ranging from bugs in Apples HID software to a buggy HID device driver for some connected device,\n");
        printf("PsychHID-ERROR: to general operating system malfunction. A reboot or device driver update for 3rd party HID devices\n");
        printf("PsychHID-ERROR: maybe could help. Check the OSX system log for possible HID related error messages or hints. Aborting...\n");
        PsychErrorExitMsg(PsychError_system, "HID device enumeration failed due to malfunction in the OSX Apple HID Utilities framework (II).");
    }
    
    // Verify no security sensitive application is blocking our low-level access to HID devices:
	PsychHIDWarnInputDisabled(NULL);
}
Example #2
0
/*
    PSYCHHIDCheckInit() 
    
    Check to see if we need to create the USB-HID device list. If it has not been created then create it.   
*/
void PsychHIDVerifyInit(void)
{
    psych_bool success = TRUE;
    
    // Build HID device list if it doesn't already exist:
    if (!HIDHaveDeviceList()) success = (psych_bool) HIDBuildDeviceList(0, 0);
    
    // This check can only be made against the 64-Bit HID Utilities, as the older 32-Bit
    // version is even more crappy and can't report meaningful error status:
    #if defined(__LP64__)
    if (!success) {
        printf("PsychHID-ERROR: Could not enumerate HID devices (HIDBuildDeviceList() failed)! There can be various reasons,\n");
        printf("PsychHID-ERROR: ranging from bugs in Apples HID software to a buggy HID device driver for some connected device,\n");
        printf("PsychHID-ERROR: to general operating system malfunction. A reboot or device driver update for 3rd party HID devices\n");
        printf("PsychHID-ERROR: maybe could help. Check the OSX system log for possible HID related error messages or hints. Aborting...\n");
        PsychErrorExitMsg(PsychError_system, "HID device enumeration failed due to malfunction in the OSX 64 Bit Apple HID Utilities framework.");
    }
    #endif
    
    // Double-Check to protect against pathetic Apple software:
    if (!HIDHaveDeviceList()) {
        printf("PsychHID-ERROR: Could not enumerate HID devices (HIDBuildDeviceList() success, but HIDHaveDeviceList() still failed)!\n");
        printf("PsychHID-ERROR: Reasons can be ranging from bugs in Apples HID software to a buggy HID device driver for some connected device,\n");
        printf("PsychHID-ERROR: to general operating system malfunction. A reboot or device driver update for 3rd party HID devices\n");
        printf("PsychHID-ERROR: maybe could help. Check the OSX system log for possible HID related error messages or hints. Aborting...\n");
        PsychErrorExitMsg(PsychError_system, "HID device enumeration failed due to malfunction in the OSX Apple HID Utilities framework (II).");
    }
    
    // Verify no security sensitive application is blocking our low-level access to HID devices:
	PsychHIDWarnInputDisabled(NULL);
    
    #if defined(__LP64__)
    // Try to load all bundles from Psychtoolbox/PsychHardware/
    // This loads the HID_Utilities.framework bundle if it is present. The whole point of it is
    // to allow our statically compiled-in version of the library to find the location of
    // the XML file with the database of (vendorId, productId) -> (VendorName, ProductName) and
    // (usagePage, usage) -> (usageName) mappings.
    //
    // In practice, the XML file only serves as a fallback, and one that doesn't contain much
    // useful info for mainstream products, only for a few niche products. Given its limited
    // value, i think we can refrain from shipping the framework as part of Psychtoolbox and
    // just provide the option to use it (== its XML file) if users decide to install it themselves.
    char tmpString[1024];
    
    sprintf(tmpString, "%sPsychHardware/", PsychRuntimeGetPsychtoolboxRoot(FALSE));
    CFStringRef urlString = CFStringCreateWithCString(kCFAllocatorDefault, tmpString, kCFStringEncodingASCII);
    CFURLRef directoryURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, urlString, kCFURLPOSIXPathStyle, false);
    CFRelease(urlString);
    CFArrayRef bundleArray = CFBundleCreateBundlesFromDirectory(kCFAllocatorDefault, directoryURL, NULL);
    CFRelease(directoryURL);
    CFRelease(bundleArray);    
    #endif
}
// *************************************************************************
//
// HIDConfigureAction(outIOHIDDeviceRef, outIOHIDElementRef, inTimeout)
//
// Purpose: polls all devices and elements for a change greater than kPercentMove.
// Times out after given time returns 1 and pointer to device and element
// if found; returns 0 and NULL for both parameters if not found
//
// Inputs:	outIOHIDDeviceRef	- address where to store the device
// outIOHIDElementRef	- address where to store the element
// inTimeout	- the timeout
// Returns: Boolean		- if successful
// outIOHIDDeviceRef	- the device
// outIOHIDElementRef	- the element
//
Boolean HIDConfigureActionOfType(actionTypeMask		inActionTypeMask,
                                 double				inTimeout,
                                 IOHIDDeviceRef *	outIOHIDDeviceRef,
                                 IOHIDElementRef *	outIOHIDElementRef) {
	// param error?
	if (!outIOHIDDeviceRef ||
	    !outIOHIDElementRef)
	{
		return (false);
	}
	if (!gDeviceCFArrayRef) {                                                   // if we do not have a device list
		                                                                        // and	we can't build another list
		if (!HIDBuildDeviceList(0,
		                        0) ||
		    !gDeviceCFArrayRef)
		{
			return (false);                                                     // bail
		}
	}

	IOHIDDeviceRef tIOHIDDeviceRef;
	IOHIDElementRef tIOHIDElementRef;

	IOHIDElementType elementType = 0;

	switch (inActionTypeMask) {
		case kActionTypeButton:
		{
			elementType = kIOHIDElementTypeInput_Button;
			break;
		}

		case kActionTypeAxis:
		{
			elementType = kIOHIDElementTypeInput_Misc;
			break;
		}

		case kActionTypeAll:
		default:
		{
			elementType = 0;
			break;
		}
	}                                                                           // switch

	// determine the maximum number of elements
	CFIndex maxElements = 0;
	CFIndex devIndex,
	        devCount = CFArrayGetCount(gDeviceCFArrayRef);
	for (devIndex = 0; devIndex < devCount; devIndex++) {
		tIOHIDDeviceRef = (IOHIDDeviceRef) CFArrayGetValueAtIndex(gDeviceCFArrayRef,
		                                                          devIndex);
		if (!tIOHIDDeviceRef) {
			continue;                                                           // skip this one
		}

		// HIDDumpDeviceInfo(tIOHIDDeviceRef);
		CFIndex count = HIDCountDeviceElementsOfType(tIOHIDDeviceRef,
		                                             elementType);
		if (count > maxElements) {
			maxElements = count;
		}
	}
	if (!(devCount *
	      maxElements))
	{
		return (false);
	}

#if true
//    NSDictionary * matchDictionary = @{@(kIOHIDElementTypeKey): @(elementType)};
	const void *keys[] = {CFSTR(kIOHIDElementTypeKey)};
	const void *vals[] = {CFNumberCreate(kCFAllocatorDefault,
		                                 kCFNumberIntType,
		                                 &elementType)};
	CFDictionaryRef matchingDict = CFDictionaryCreate(kCFAllocatorDefault,
	                                                  keys,
	                                                  vals,
	                                                  1,
	                                                  &kCFTypeDictionaryKeyCallBacks,
	                                                  &kCFTypeDictionaryValueCallBacks);
	CFRelease(vals[0]);
#endif                                                                          // if 1

	// allocate an array of int's in which to store devCount * maxElements values
	double *saveValueArray = (double *) calloc(devCount *
	                                           maxElements,
	                                           sizeof(double));                 // clear 2D array to save values

	// remember when we start; used to calculate timeout
	clock_t start = clock(),
	        end;

	// on first pass store initial values / compare current values to initial values on subsequent passes
	Boolean found = false,
	        first = true;

	while (!found) {
		double maxDeltaPercent = 0;                                             // we want to find the one that moves the most
		                                                                        // (percentage wise)
		for (devIndex = 0; devIndex < devCount; devIndex++) {
			tIOHIDDeviceRef = (IOHIDDeviceRef) CFArrayGetValueAtIndex(gDeviceCFArrayRef,
			                                                          devIndex);
			if (!tIOHIDDeviceRef) {
				continue;                                                       // skip this one
			}

			gElementCFArrayRef = IOHIDDeviceCopyMatchingElements(tIOHIDDeviceRef,
			                                                     matchingDict,
			                                                     kIOHIDOptionsTypeNone);
			if (gElementCFArrayRef) {
				CFIndex eleIndex,
				        eleCount = CFArrayGetCount(gElementCFArrayRef);
				for (eleIndex = 0; eleIndex < eleCount; eleIndex++) {
					tIOHIDElementRef = (IOHIDElementRef) CFArrayGetValueAtIndex(gElementCFArrayRef,
					                                                            eleIndex);
					if (!tIOHIDElementRef) {
						continue;
					}

					IOHIDElementType tIOHIDElementType = IOHIDElementGetType(tIOHIDElementRef);
					// only care about inputs (no outputs or features)
					if (tIOHIDElementType <= kIOHIDElementTypeInput_ScanCodes) {
						if (IOHIDElementIsArray(tIOHIDElementRef)) {
							// printf("ARRAY!\n");
							continue;                                           // skip array elements
						}
						if (elementType &&
						    ((tIOHIDElementType != elementType)))
						{
							continue;
						}

						uint32_t usagePage = IOHIDElementGetUsagePage(tIOHIDElementRef);
						uint32_t usage = IOHIDElementGetUsage(tIOHIDElementRef);
						uint32_t reportCount = IOHIDElementGetReportCount(tIOHIDElementRef);
#ifdef DEBUG
						if (first) {
							HIDDumpElementInfo(tIOHIDElementRef);
							fflush(stdout);
							uint32_t vendorID = IOHIDDevice_GetVendorID(tIOHIDDeviceRef);
							uint32_t productID = IOHIDDevice_GetProductID(tIOHIDDeviceRef);
							IOHIDElementCookie cookie = IOHIDElementGetCookie(tIOHIDElementRef);
							if ((0x054C == vendorID) &&
							    (0x0268 == productID) &&
							    (0x001E == (uint32_t) cookie))
							{
								// printf("DING!\n");
							}
						}

#endif                                                                          // ifdef DEBUG

#if true                                                                        // work-around for IOHIDValueGetScaledValue crash
						                                                        // (when element report count > 1)
						if (reportCount > 1) {
							// printf("REPORT!\n");
							continue;                                           // skip reports
						}

#endif                                                                          // if 1
						// ignore PID elements and arrays
						if ((kHIDPage_PID != usagePage) &&
						    ((-1) != usage))
						{
							// get this elements current value
							double value = 0.0;                                 // default value is zero
							IOHIDValueRef tIOHIDValueRef;
							IOReturn ioReturn = IOHIDDeviceGetValue(tIOHIDDeviceRef,
							                                        tIOHIDElementRef,
							                                        &tIOHIDValueRef);
							if (kIOReturnSuccess == ioReturn) {
								value = IOHIDValueGetScaledValue(tIOHIDValueRef,
								                                 kIOHIDValueScaleTypePhysical);
							}
							if (first) {
								saveValueArray[(devIndex *
								                maxElements) +
								               eleIndex] = value;
							} else {
								double initialValue = saveValueArray[(devIndex *
								                                      maxElements) +
								                                     eleIndex];

								CFIndex valueMin = IOHIDElementGetPhysicalMin(tIOHIDElementRef);
								CFIndex valueMax = IOHIDElementGetPhysicalMax(tIOHIDElementRef);

								double deltaPercent = fabs((initialValue -
								                            value) *
								                           100.0 /
								                           (valueMax -
								                            valueMin));
#if false                                                                       // debug code useful to dump out value info for
								                                                // specific (vendorID, productID, usagePage and
								                                                // usage) device
								if (!first) {
									// Device: 0x13b6a0 = { Logitech Inc. - WingMan Force 3D,	vendorID:	0x046D,		productID:	0xC283,
									// usage: 0x0001:0x0004, "Generic Desktop Joystick"
									if ((vendorID == 0x046D) &&
									    (productID == 0xC283))
									{
										if ((kHIDPage_GenericDesktop == usagePage) &&
										    (kHIDUsage_GD_Rz == usage))
										{
											printf("initial: %6.2f, value: %6.2f, diff: %6.2f, delta percent: %6.2f!\n",
											       initialValue,
											       value,
											       fabs(initialValue -
											            value),
											       deltaPercent);
										}
									}
								}

								deltaPercent = 0.0;
#endif // if false
								if (deltaPercent >= kPercentMove) {
									found = true;
									if (deltaPercent > maxDeltaPercent) {
										maxDeltaPercent = deltaPercent;

										*outIOHIDDeviceRef = tIOHIDDeviceRef;
										*outIOHIDElementRef = tIOHIDElementRef;
									}

									break;
								}
							}                                                   // if first
						}                                                       // if usage
					}                                                           // if type
				}                                                               // for elements...

				CFRelease(gElementCFArrayRef);
				gElementCFArrayRef = NULL;
			}                                                                   // if (gElementCFArrayRef)
			if (found) {
				// HIDDumpElementInfo(tIOHIDElementRef);
				break;                                                          // DONE!
			}
		}                                                                       // for devices

		first = false;                                                          // no longer the first pass

		// are we done?
		end = clock();
		double secs = (double) (end -
		                        start) /
		              CLOCKS_PER_SEC;
		if (secs > inTimeout) {
			break;                                                              // (yes) timeout
		}
	}                                                                           // while (!found)
	if (saveValueArray) {
		free(saveValueArray);
	}
	// return device and element moved
	if (!found) {
		*outIOHIDDeviceRef = NULL;
		*outIOHIDElementRef = NULL;
	}

	CFRelease(matchingDict);

	return (found);
}                                                                               // HIDConfigureAction
Example #4
0
unsigned char HIDConfigureAction (pRecDevice * ppDevice, pRecElement * ppElement, float timeout)
{
    unsigned long devices, maxElements = 0;
    long * saveValueArray;
    pRecDevice pDevice = NULL;
    pRecElement pElement = NULL;
    short deviceNum = 0;
    unsigned char found = 0, done = 0;
	clock_t start = clock (), end;
    unsigned long i;
    
     if (0 == HIDHaveDeviceList ())   // if we do not have a device list
		if (0 == HIDBuildDeviceList (0, 0)) // if we could not build anorther list (use generic usage and page)
			return 0; // return 0

    // build list of device and elements to save current values
    devices = HIDCountDevices ();
    pDevice = HIDGetFirstDevice ();
    while (pDevice)
    {
		if (HIDCountDeviceElements (pDevice, kHIDElementTypeIO) > maxElements)
			maxElements = HIDCountDeviceElements (pDevice, kHIDElementTypeIO);
		pDevice = HIDGetNextDevice (pDevice);
	}
	saveValueArray = (long *) malloc (sizeof (long) * devices * maxElements); // 2D array to save values
	for (i = 0; i < devices * maxElements; i++) // clear array
		*(saveValueArray + i) = 0x00000000;
		
	// store current values
	deviceNum = 0;
	pDevice = HIDGetFirstDevice ();
	while (pDevice)
	{
		short elementNum = 0;
		pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO);
		while (pElement)
		{
			*(saveValueArray + (deviceNum * maxElements) + elementNum) = HIDGetElementValue (pDevice, pElement);
			pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); 
			elementNum++;
		}
		pDevice = HIDGetNextDevice (pDevice);
		deviceNum++;
    }
    
    // poll all devices and elements, compare current value to save +/- kPercentMove
    while ((!found) && (!done))
    {
		double secs;
		// are we done?
		end = clock();
		secs = (double)(end - start) / CLOCKS_PER_SEC;
		if (secs > timeout)
			done = 1;
		deviceNum = 0;
		pDevice = HIDGetFirstDevice ();
		while (pDevice)
		{
			short elementNum = 0;
			pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO);
			while (pElement)
			{
				long initialValue = *(saveValueArray + (deviceNum * maxElements) + elementNum);
				long value = HIDGetElementValue (pDevice, pElement);
				long delta = (float)(pElement->max - pElement->min) * kPercentMove * 0.01;
				if (((initialValue + delta) < value) || ((initialValue - delta) > value))
				{
					found = 1;
					break;
				}
				pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); 
				elementNum++;
			}
			if (found)
				break;
			pDevice = HIDGetNextDevice (pDevice);
			deviceNum++;
		}
    }
    
    // return device and element moved
    if (found)
    {
		*ppDevice = pDevice;
		*ppElement = pElement;
		return 1;
    }
	else
	{
		*ppDevice = NULL;
		*ppElement = NULL;
		return 0;
	}
}
Boolean HIDConfigureAction( IOHIDDeviceRef* outIOHIDDeviceRef, IOHIDElementRef *outIOHIDElementRef, float inTimeout )
{
	// param error?
	if ( !outIOHIDDeviceRef || !outIOHIDElementRef ) {
		return 0;
	}
	
	if ( !gDeviceCFArrayRef ) { // if we do not have a device list
		// and  we can't build another list
		if ( !HIDBuildDeviceList( 0, 0 ) || !gDeviceCFArrayRef ) {
			return FALSE;	// bail
		}
	}
	
	IOHIDDeviceRef tIOHIDDeviceRef;	
	IOHIDElementRef tIOHIDElementRef;	
	
	// remember when we start; used to calculate timeout
	clock_t start = clock(), end;
	
	// determine the maximum number of elements
	CFIndex maxElements = 0;
	CFIndex devIndex, devCount = CFArrayGetCount( gDeviceCFArrayRef );
	for ( devIndex = 0; devIndex < devCount; devIndex++ ) {
		tIOHIDDeviceRef = ( IOHIDDeviceRef ) CFArrayGetValueAtIndex( gDeviceCFArrayRef, devIndex );
		
		if ( !tIOHIDDeviceRef ) {
			continue;               // skip this one
		}
		
		UInt32 count = HIDCountDeviceElements( tIOHIDDeviceRef, kHIDElementTypeInput );
		if ( count > maxElements ) {
			maxElements = count;
		}
	}
	
	// allocate an array of int's in which to store devCount * maxElements values
	double* saveValueArray = ( double * ) calloc( devCount * maxElements, sizeof( double ) ); // clear 2D array to save values
	
	// on first pass store initial values / compare current values to initial values on subsequent passes
	Boolean found = FALSE, first = TRUE;
	while ( !found ) {
		double maxDeltaPercent = 0;	// we want to find the one that moves the most ( percentage wise )
		for ( devIndex = 0; devIndex < devCount; devIndex++ ) {
			IOHIDDeviceRef tIOHIDDeviceRef = ( IOHIDDeviceRef ) CFArrayGetValueAtIndex( gDeviceCFArrayRef, devIndex );
			
			if ( !tIOHIDDeviceRef ) {
				continue;                       // skip this one
			}
#ifdef DEBUG
			long vendorID = IOHIDDevice_GetVendorID( tIOHIDDeviceRef );
			long productID = IOHIDDevice_GetProductID( tIOHIDDeviceRef );
#endif
			gElementCFArrayRef = IOHIDDeviceCopyMatchingElements( tIOHIDDeviceRef, NULL, kIOHIDOptionsTypeNone );
			
			if ( gElementCFArrayRef ) {
				CFIndex eleIndex, eleCount = CFArrayGetCount( gElementCFArrayRef );
				for ( eleIndex = 0; eleIndex < eleCount; eleIndex++ ) {
					tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( gElementCFArrayRef, eleIndex );
					
					if ( !tIOHIDElementRef ) {
						continue;
					}
					
					IOHIDElementType tIOHIDElementType = IOHIDElementGetType( tIOHIDElementRef );
					
					// only care about inputs (no outputs or features)
					if ( tIOHIDElementType <= kIOHIDElementTypeInput_ScanCodes ) {

						if ( IOHIDElementIsArray( tIOHIDElementRef ) ) {
							//printf( "ARRAY!\n" );
							continue;	// skip array elements
						}
						uint32_t usagePage = IOHIDElementGetUsagePage( tIOHIDElementRef );
						uint32_t usage = IOHIDElementGetUsage( tIOHIDElementRef );
						uint32_t reportCount = IOHIDElementGetReportCount( tIOHIDElementRef );
#ifdef DEBUG
						if ( first ) {
							IOHIDElementCookie cookie = IOHIDElementGetCookie( tIOHIDElementRef );
							printf( "%s, dev: {ref:%p, ven: 0x%08lX, pro: 0x%08lX}, ele: {ref:%p, cookie: %p, usage:%04lX:%08lX}\n",
								   __PRETTY_FUNCTION__,
								   tIOHIDDeviceRef,
								   vendorID,
								   productID,
								   tIOHIDElementRef,
								   cookie,
								   (long unsigned int) usagePage,
								   (long unsigned int) usage ); fflush( stdout );
							
							if ( ( 0x054C == vendorID ) && ( 0x0268 == productID ) && ( 0x001E == (UInt32) cookie ) ) {
								//printf( "DING!\n" );
							}
						}
#endif
#if 1					// work-around for IOHIDValueGetScaledValue crash (when element report count > 1)
						if ( reportCount > 1 ) {
							//printf( "REPORT!\n" );
							continue; // skip reports
						}
#endif					
						// ignore PID elements and arrays
						if ( ( kHIDPage_PID != usagePage ) && ( -1 != usage ) ) {
							// get this elements current value
							double value = 0.0;	// default value is zero
							IOHIDValueRef tIOHIDValueRef;
							IOReturn ioReturn = IOHIDDeviceGetValue( tIOHIDDeviceRef, tIOHIDElementRef, &tIOHIDValueRef );
							if ( kIOReturnSuccess == ioReturn ) {
								value = IOHIDValueGetScaledValue( tIOHIDValueRef, kIOHIDValueScaleTypePhysical );
							}
							
							if ( first ) {
								saveValueArray[( devIndex * maxElements ) + eleIndex] = value;
							} else {
								double initialValue = saveValueArray[( devIndex * maxElements ) + eleIndex];
								
								CFIndex valueMin = IOHIDElementGetPhysicalMin( tIOHIDElementRef );
								CFIndex valueMax = IOHIDElementGetPhysicalMax( tIOHIDElementRef );
								
								double deltaPercent = fabs( ( initialValue - value ) * 100.0 / (valueMax - valueMin) );
#if 0
								if ( !first ) {
								// Device: 0x13b6a0 = { Logitech Inc. - WingMan Force 3D, 	vendorID:	0x046D, 	productID:	0xC283, usage: 0x0001:0x0004, "Generic Desktop Joystick"
									if ( ( vendorID == 0x046D ) && ( productID == 0xC283 ) ) {
										if ( ( kHIDPage_GenericDesktop == usagePage ) && ( kHIDUsage_GD_Rz == usage ) ) {
											printf( "initial: %6.2f, value: %6.2f, diff: %6.2f, delta percent: %6.2f!\n", initialValue, value, fabs( initialValue - value ), deltaPercent );
										}
									}
								}
								deltaPercent = 0.0;
#endif
								if ( deltaPercent >= kPercentMove ) {
									found = TRUE;
									if ( deltaPercent > maxDeltaPercent ) {
										maxDeltaPercent = deltaPercent;
										
										*outIOHIDDeviceRef = tIOHIDDeviceRef;
										*outIOHIDElementRef = tIOHIDElementRef;
									}
									break;
								}
							}   // if first
						}       // if usage
					}           // if type
				}               // for elements...
				CFRelease( gElementCFArrayRef );
				gElementCFArrayRef = NULL;
			}	// if ( gElementCFArrayRef )
			if ( found ) {
				// HIDDumpElementInfo( tIOHIDElementRef );
				break; // DONE!
			}
		}                   // for devices
		
		first = FALSE;          // no longer the first pass
		
		// are we done?
		end = clock();
		double secs = (double)( end - start ) / CLOCKS_PER_SEC;
		
		if ( secs > inTimeout ) {
			break;              // ( yes ) timeout
		}
	}	//	while ( !found )
	
	// return device and element moved
	if ( !found ) {
		*outIOHIDDeviceRef = NULL;
		*outIOHIDElementRef = NULL;
	}
	return found;
}   // HIDConfigureAction
Example #6
0
void Controller::Setup()
{
	#if defined(WIN32)
		ZeroMemory( &_currentControllerRawState, sizeof(XINPUT_STATE));
		
		_dwResult = XInputGetState(_controllerID, &_currentControllerRawState);
		
		if (_dwResult == ERROR_SUCCESS)
		{
			sysLog.Printf("Controller %d connected!", _controllerID+1);
			_connected = true;
		}
		else
		{
			sysLog.Printf("Controller %d not present...", _controllerID+1);
			ZeroMemory( &_currentControllerRawState, sizeof(XINPUT_STATE));
			_currentControllerInput.LeftThumbstickX = 
			_currentControllerInput.LeftThumbstickY =
			_currentControllerInput.RightThumbstickX =
			_currentControllerInput.RightThumbstickY = 
			_currentControllerInput.LeftTriggerValue = 
			_currentControllerInput.RightTriggerValue = 
			_currentControllerInput.Buttons = 0;
			_connected = false;
		}
	
	#elif defined(__APPLE__)
		unsigned long usagePage = 0;
		unsigned long usage = 0;
		if (!HIDHaveDeviceList())
		{	
			HIDBuildDeviceList(usagePage, usage);
		}
		
		_device = HIDGetFirstDevice();
		while (_device != NULL)
		{
			//is this device already taken by another controller? 
			bool breakIt = false;
			for (int i=0; i < MAX_CONTROLLERS; i++)
			{
				Controller* check = &theControllerManager.GetController(i);
				if ((check != this) && (check->_device == _device))
				{
					_device = HIDGetNextDevice(_device);
					if (_device == NULL)
					{
						breakIt = true;
					}
				}
			}
			if (breakIt)
			{
				break;
			}
			
			std::string manufacturer = _device->manufacturer;
			std::string product = _device->product;
			if (manufacturer.length() > 0)
				manufacturer = manufacturer.substr(1, manufacturer.length()-1).c_str(); //trimming off the initial copyright symbol so matching won't be dumb
			if (
				((manufacturer == "Microsoft Corporation") && (product == "Controller"))
				|| ((manufacturer == "icrosoft") && (product == "Wireless 360 Controller"))
				)
			{
				sysLog.Printf("Controller %d connected!", _controllerID+1);
				_connected = true;
				break;
			}
			
			_device = HIDGetNextDevice(_device);
		}
		if (_device == NULL)
		{
			sysLog.Printf("Controller %d not present...", _controllerID+1);
			_connected = false;
		}
		else
		{
			pRecElement current_element = HIDGetFirstDeviceElement(_device, kHIDElementTypeIO);
			while (current_element != NULL)
			{
				_elements[(unsigned int)current_element->cookie] = current_element;
				current_element = HIDGetNextDeviceElement(current_element, kHIDElementTypeIO);
			}
		}
	#elif defined(__linux__)
		_currentControllerInput.LeftThumbstickX = 
		_currentControllerInput.LeftThumbstickY =
		_currentControllerInput.RightThumbstickX =
		_currentControllerInput.RightThumbstickY = 
		_currentControllerInput.LeftTriggerValue = 
		_currentControllerInput.RightTriggerValue = 
		_currentControllerInput.Buttons = 0;
		char* devicePath;
		if (_controllerID == 0)
			devicePath = LINUX_CONTROLLER_1_PATH;
		else
			devicePath = LINUX_CONTROLLER_2_PATH;

		_deviceFD = open(devicePath, O_RDONLY | O_NONBLOCK);
		if (_deviceFD < 0)
		{
			sysLog.Printf("Controller %d not present...", _controllerID+1);
			_connected = false;
		}
		else
		{
			sysLog.Printf("Controller %d connected!", _controllerID+1);
			_connected = true;
		}

		// Discover the force feedback device.
		bool foundFirstController = false;
		_ffFD = -1;
		for (int i = 0; i < MAX_LINUX_EVENT_INTERFACES; i++)
		{
			std::stringstream ss;
			ss << i;
			String eventDev = LINUX_EVENT_INTERFACE + ss.str();
			int fd = open(eventDev.c_str(), O_RDWR);
			if (fd >= 0)
		 	{
				char name[256] = "Unknown";
				ioctl(fd, EVIOCGNAME(sizeof(name)), name);
				if (strcmp(name, "Microsoft X-Box 360 pad") == 0)
				{
					if (_controllerID == 0)
					{
						_ffFD = fd;
						break;
					}
					else
					{
						if (foundFirstController)
						{
							_ffFD = fd;
							break;
						}
						else
						{
							foundFirstController = true;
							close(fd);
						}
					}
				}
				else
				{
					close(fd);
				}
			}
		}
		if (_ffFD < 0)
		{
			sysLog.Printf("Error opening Force Feedback device for controller %d!", _controllerID+1);
		}
		else
		{
			_ffEffect.type = FF_RUMBLE;
			_ffEffect.id = -1;
			_ffEffect.u.rumble.strong_magnitude = 0;
			_ffEffect.u.rumble.weak_magnitude = 0;
			_ffEffect.replay.length = 0x7fff;
			_ffEffect.replay.delay = 0;
			_ffPlay.type = EV_FF;
			_ffPlay.value = 1;
		}
	#endif
}
/*
    PSYCHHIDCheckInit() 
    
    Check to see if we need to create the device list.  If it has not been created then create it.   
*/
void PsychHIDVerifyInit(void)
{
    if(!HIDHaveDeviceList())HIDBuildDeviceList(NULL, NULL);
}
Example #8
0
/*
    PSYCHHIDCheckInit()

    Check to see if we need to create the USB-HID device list. If it has not been created then create it.
*/
void PsychHIDVerifyInit(void)
{
    // GenericDesktop for mice, keyboards, gamepads etc. vendor defined for things like MCC USB-DAQ boxes...
    UInt32 inUsagePages[2] = {kHIDPage_GenericDesktop, kHIDPage_VendorDefinedStart};
    UInt32 inUsages[2] = {0, 0};
    int inNumDeviceTypes = 2;
    psych_bool success = TRUE;

    // Build HID device list if it doesn't already exist:
    if (!HIDHaveDeviceList()) success = (psych_bool)HIDBuildDeviceList(0, 0);

    // This check can only be made against the 64-Bit HID Utilities, as the older 32-Bit
    // version is even more crappy and can't report meaningful error status:
    if (!success) {
        printf("PsychHID-ERROR: Could not enumerate and attach to all HID devices (HIDBuildDeviceList(0,0) failed)!\n");
        printf("PsychHID-ERROR: One reason could be that some HID devices are already exclusively claimed by some 3rd party device drivers\n");
        printf("PsychHID-ERROR: or applications. I will now retry to only claim control of a hopefully safe subset of devices like standard\n");
        printf("PsychHID-ERROR: keyboards, mice, gamepads and supported USB-DAQ devices and other vendor defined devices and hope this goes better...\n");

        // User override for special devices provided?
        if (getenv("PSYCHHID_HIDPAGEOVERRIDE")) {
            // Override via environment variable provided: Use it in addition to the generic desktop input devices:
            inUsagePages[1] = atoi(getenv("PSYCHHID_HIDPAGEOVERRIDE"));
            inUsages[1] = atoi(getenv("PSYCHHID_HIDUSAGEOVERRIDE"));
            printf("PsychHID-INFO: User override: Generic desktop page devices + usagePage 0x%x and usage value 0x%x ...\n", inUsagePages[1], inUsages[1]);
        }

        success = (psych_bool)HIDBuildMultiDeviceList(inUsagePages, inUsages, inNumDeviceTypes);
        if (!success) {
            printf("PsychHID-ERROR: Nope. Excluding everything but a few known USB-DAQ devices and standard mice, keyboards etc. Retrying ...\n");
            inUsagePages[1] = kHIDPage_VendorDefinedStart;
            inUsages[1] = 1; // Known combo is usagepage 0xff00 + usage 0x1 for MCC USB 1208-FS USB HID-DAQ device.
            success = (psych_bool)HIDBuildMultiDeviceList(inUsagePages, inUsages, inNumDeviceTypes);
        }

        if (!success) {
            printf("PsychHID-ERROR: Nope. Excluding everything but standard mice, keyboards etc. Retrying ...\n");
            success = (psych_bool)HIDBuildMultiDeviceList(inUsagePages, inUsages, 1);
            if (!success) {
                printf("PsychHID-ERROR: Could not enumerate any HID devices (HIDBuildDeviceList() still failed even for standard generic desktop input devices)!\n");
                printf("PsychHID-ERROR: Reasons can be ranging from bugs in Apples HID software to a buggy HID device driver for some connected device,\n");
                printf("PsychHID-ERROR: to general operating system malfunction. A reboot or device driver update for 3rd party HID devices\n");
                printf("PsychHID-ERROR: maybe could help. Check the OSX system log for possible HID related error messages or hints. Aborting...\n");
                PsychErrorExitMsg(PsychError_system, "HID device enumeration failed due to malfunction in the OSX 64 Bit Apple HID Utilities framework.");
            }
        }
        else {
            printf("PsychHID-INFO: That worked. A subset of regular mouse, keyboard etc. input devices and maybe some vendor defined devices will be available at least.\n");
        }
    }

    // Double-Check to protect against pathetic Apple software:
    if (!HIDHaveDeviceList()) {
        printf("PsychHID-ERROR: Could not enumerate HID devices (HIDBuildDeviceList() success, but HIDHaveDeviceList() still failed)!\n");
        printf("PsychHID-ERROR: Reasons can be ranging from bugs in Apples HID software to a buggy HID device driver for some connected device,\n");
        printf("PsychHID-ERROR: to general operating system malfunction. A reboot or device driver update for 3rd party HID devices\n");
        printf("PsychHID-ERROR: maybe could help. Check the OSX system log for possible HID related error messages or hints. Aborting...\n");
        PsychErrorExitMsg(PsychError_system, "HID device enumeration failed due to malfunction in the OSX Apple HID Utilities framework (II).");
    }

    // Verify no security sensitive application is blocking our low-level access to HID devices:
    PsychHIDWarnInputDisabled(NULL);
}
Example #9
0
int prHIDBuildDeviceList(VMGlobals *g, int numArgsPushed)
{
	//build a device list
	PyrSlot *a = g->sp - 2;
	PyrSlot *b = g->sp - 1; //usagePage
	PyrSlot *c = g->sp;		//usage

	int usagePage, usage, err;
	if(IsNil(b))
		usagePage = 0;
	else
	{
		err = slotIntVal(b, &usagePage);
		if (err) return err;
	}
	if(IsNil(c))
		usage = 0;
	else
	{
		err = slotIntVal(c, &usage);
		if (err) return err;
	}

	//pass in usage & usagepage
	//kHIDUsage_GD_Joystick kHIDUsage_GD_GamePad
	//UInt32 usagePage = kHIDPage_GenericDesktop;
	//UInt32 usage = NULL;

	Boolean result = HIDBuildDeviceList (usagePage, usage);
	// returns false if no device found (ignored in this case) - returns always false ?

	if(result) post("no HID devices found\n");

	int numdevs = HIDCountDevices();
	gNumberOfHIDDevices = numdevs;
	if(!numdevs){
		SetNil(a);
		return errNone;
	}
	//post("number of devices: %d", numdevs);
	char cstrDeviceName [256];

    pRecDevice  pCurrentHIDDevice = HIDGetFirstDevice ();
	PyrObject* allDevsArray = newPyrArray(g->gc, numdevs * sizeof(PyrObject), 0 , true);
	for(int i=0; i<numdevs; i++){
		//device:
		PyrObject* devNameArray = newPyrArray(g->gc, 8 * sizeof(PyrObject), 0 , true);
		//manufacturer:
		PyrString *devstring = newPyrString(g->gc, pCurrentHIDDevice->manufacturer, 0, true);
		SetObject(devNameArray->slots+devNameArray->size++, devstring);
		g->gc->GCWrite(devNameArray, (PyrObject*) devstring);
		//product name:
		devstring = newPyrString(g->gc, pCurrentHIDDevice->product, 0, true);
		SetObject(devNameArray->slots+devNameArray->size++, devstring);
		g->gc->GCWrite(devNameArray, (PyrObject*) devstring);
		//usage
		HIDGetUsageName (pCurrentHIDDevice->usagePage, pCurrentHIDDevice->usage, cstrDeviceName);
		devstring = newPyrString(g->gc, cstrDeviceName, 0, true);
		SetObject(devNameArray->slots+devNameArray->size++, devstring);
		g->gc->GCWrite(devNameArray, (PyrObject*) devstring);
		//vendor id
		SetInt(devNameArray->slots+devNameArray->size++, pCurrentHIDDevice->vendorID);
		//product id
		SetInt(devNameArray->slots+devNameArray->size++, pCurrentHIDDevice->productID);
		//locID
		SetInt(devNameArray->slots+devNameArray->size++, pCurrentHIDDevice->locID);

		//version
		SetInt(devNameArray->slots+devNameArray->size++, pCurrentHIDDevice->version);

		//serial
		devstring = newPyrString(g->gc, pCurrentHIDDevice->serial, 0, true);
		SetObject(devNameArray->slots+devNameArray->size++, devstring);
		g->gc->GCWrite(devNameArray, (PyrObject*) devstring);

		SetObject(allDevsArray->slots+allDevsArray->size++, devNameArray);
		g->gc->GCWrite(allDevsArray, (PyrObject*) devNameArray);
		pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice);

	}

	//UInt32 outnum =  HIDCountDeviceElements (pCurrentHIDDevice, kHIDElementTypeOutput);
	//post("number of outputs: %d \n", outnum);
	SetObject(a, allDevsArray);

	return errNone;
}