/* 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 }
/* PsychHIDCleanup() Cleanup before flushing the mex file. */ PsychError PsychHIDCleanup(void) { long error; error=PsychHIDReceiveReportsCleanup(); // PsychHIDReceiveReport.c if(HIDHaveDeviceList())HIDReleaseDeviceList(); return(PsychError_none); }
void EndHIDInput (void) { // remove timer if (gHIDTimer) RemoveEventLoopTimer (gHIDTimer); gHIDTimer = NULL; // dump array InitHIDInputArray (); // dump devices if (HIDHaveDeviceList()) HIDReleaseDeviceList (); }
unsigned char HIDConfigureSingleDeviceAction(IOHIDDeviceRef inIOHIDDeviceRef, IOHIDElementRef * outIOHIDElementRef, double timeout) { if (!inIOHIDDeviceRef) { return (0); } if (0 == HIDHaveDeviceList()) { // if we do not have a device list return (0); // return 0 } Boolean found = false; // build list of device and elements to save current values CFIndex maxElements = HIDCountDeviceElements(inIOHIDDeviceRef, kHIDElementTypeInput); double *saveValueArray = (double *) calloc(maxElements, sizeof(double)); // 2D array to save values // store initial values on first pass / compare to initial value on subsequent passes Boolean first = true; // get all the elements from this device CFArrayRef elementCFArrayRef = IOHIDDeviceCopyMatchingElements(inIOHIDDeviceRef, NULL, kIOHIDOptionsTypeNone); // if that worked... if (elementCFArrayRef) { clock_t start = clock(), end; // poll all devices and elements while (!found) { uint32_t currElementIndex = 0; CFIndex idx, cnt = CFArrayGetCount(elementCFArrayRef); for (idx = 0; idx < cnt; idx++) { *outIOHIDElementRef = (IOHIDElementRef) CFArrayGetValueAtIndex(elementCFArrayRef, idx); if (!*outIOHIDElementRef) { continue; } // is this an input element? IOHIDElementType type = IOHIDElementGetType(*outIOHIDElementRef); switch (type) { // these types are inputs case kIOHIDElementTypeInput_Misc: case kIOHIDElementTypeInput_Button: case kIOHIDElementTypeInput_Axis: case kIOHIDElementTypeInput_ScanCodes: default: { break; } case kIOHIDElementTypeOutput: case kIOHIDElementTypeFeature: case kIOHIDElementTypeCollection: { *outIOHIDElementRef = NULL; // these types are not (Skip them) break; } } /* switch */ if (!*outIOHIDElementRef) { continue; // skip this element } // get this elements current value double value = 0; // default value is zero IOHIDValueRef tIOHIDValueRef; IOReturn ioReturn = IOHIDDeviceGetValue(inIOHIDDeviceRef, *outIOHIDElementRef, &tIOHIDValueRef); if (kIOReturnSuccess == ioReturn) { value = IOHIDValueGetScaledValue(tIOHIDValueRef, kIOHIDValueScaleTypePhysical); } if (first) { saveValueArray[currElementIndex] = value; } else { CFIndex min = IOHIDElementGetLogicalMin(*outIOHIDElementRef); CFIndex max = IOHIDElementGetLogicalMax(*outIOHIDElementRef); double initialValue = saveValueArray[currElementIndex]; double delta = (double) (max - min) * kPercentMove * 0.01f; // is the new value within +/- delta of the initial value? if (((initialValue + delta) < value) || ((initialValue - delta) > value)) { found = 1; // (yes!) mark as found break; } } // if (first) currElementIndex++; // bump element index } // next idx if (first) { first = false; // no longer the first pass } else { // are we done? end = clock(); double secs = (double) (end - start) / CLOCKS_PER_SEC; if (secs > timeout) { break; // (yes) timeout } } } // while (!found) CFRelease(elementCFArrayRef); } // if (elementCFArrayRef) if (saveValueArray) { free(saveValueArray); } // return device and element moved if (found) { return (1); } else { *outIOHIDElementRef = NULL; return (0); } } // HIDConfigureSingleDeviceAction
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; } }
/* PsychHIDCleanup() Cleanup before flushing the mex file. */ PsychError PsychHIDCleanup(void) { long error; pRecDevice curdev = NULL; // Disable online help system: PsychClearGiveHelp(); // Disable any kind of low-level stdin<->tty magic for character reception // or suppression in console mode (for octave and matlab -nojvm): ConsoleInputHelper(-10); // Shutdown USB-HID report low-level functions, e.g., for DAQ toolbox on OS/X: error = PsychHIDReceiveReportsCleanup(); // PsychHIDReceiveReport.c // Shutdown os specific interfaces and routines: PsychHIDShutdownHIDStandardInterfaces(); // Release all other HID device data structures: #if PSYCH_SYSTEM == PSYCH_OSX // Via Apple HIDUtils: #if (PSYCH_SYSTEM == PSYCH_OSX) && defined(__LP64__) int i; for (i = 0; i < MAXDEVICEINDEXS; i++) { if (deviceInterfaces[i]) { IOHIDDeviceInterface** interface = (IOHIDDeviceInterface**) deviceInterfaces[i]; (*interface)->close(interface); (*interface)->Release(interface); deviceInterfaces[i] = NULL; } } #endif if(HIDHaveDeviceList()) HIDReleaseDeviceList(); #else // Then our high-level list: while (hid_devices) { // Get current device record to release: curdev = hid_devices; // Advance to the next one for next loop iteration: hid_devices = hid_devices->pNext; // Interface attached aka device opened? If so we need to close the device handle: if (curdev->interface) hid_close((hid_device*) curdev->interface); // Release: free(curdev); } // Reset last hid device for error handling: last_hid_device = NULL; // Release the HIDLIB low-level device list: if (hidlib_devices) hid_free_enumeration(hidlib_devices); hidlib_devices = NULL; // Shutdown HIDAPI: hid_exit(); #endif // Close and release all open generic USB devices: PsychHIDCloseAllUSBDevices(); return(PsychError_none); }
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); }