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