//************************************************************************* // // IOHIDElement_SetupCalibration( inElementRef ) // // Purpose: set default values for the element calibration parameters // // Inputs: inElementRef - the IOHIDElementRef for this element // // Returns: nothing // void IOHIDElement_SetupCalibration( IOHIDElementRef inIOHIDElementRef ) { // these are the min/max values returned by IOHIDValueGetScaledValue( v, kIOHIDValueScaleTypeCalibrated ); IOHIDElement_SetCalibrationMin( inIOHIDElementRef, IOHIDElementGetLogicalMin( inIOHIDElementRef ) ); IOHIDElement_SetCalibrationMax( inIOHIDElementRef, IOHIDElementGetLogicalMax( inIOHIDElementRef ) ); // this is the granularity of the values returned by IOHIDValueGetScaledValue( v, kIOHIDValueScaleTypeCalibrated ); // for example if set to 0.1 the values returned will be multiples of 0.1 ( 0.1, 0.2, 0.3, etc. ) IOHIDElement_SetCalibrationGranularity( inIOHIDElementRef, 0. ); // these define the dead zone (like in the middel of joystick axis) IOHIDElement_SetCalibrationDeadZoneMin( inIOHIDElementRef, 0 ); IOHIDElement_SetCalibrationDeadZoneMax( inIOHIDElementRef, 0 ); #if 1 // get the current value of this element double value = IOHIDElement_GetValue( inIOHIDElementRef, kIOHIDValueScaleTypePhysical ); // use it as our min/mas saturation IOHIDElement_SetCalibrationSaturationMin( inIOHIDElementRef, value ); IOHIDElement_SetCalibrationSaturationMax( inIOHIDElementRef, value ); #else // calculate the middle physical value we would expect from this element CFIndex valueMin = IOHIDElementGetPhysicalMin( inIOHIDElementRef ); CFIndex valueMax = IOHIDElementGetPhysicalMax( inIOHIDElementRef ); CFIndex valueMid = ( valueMin + valueMax ) / 2; // use it as our min/mas saturation // this value determines the min/max values that have been recieved from the device element IOHIDElement_SetCalibrationSaturationMin( inIOHIDElementRef, valueMid ); IOHIDElement_SetCalibrationSaturationMax( inIOHIDElementRef, valueMid ); // get the current value of this element double value = IOHIDElement_GetValue( inIOHIDElementRef, kIOHIDValueScaleTypePhysical ); // and use it to adjust the current saturation values if it's outside their range if ( value < IOHIDElement_GetCalibrationSaturationMin( inIOHIDElementRef ) ) { IOHIDElement_SetCalibrationSaturationMin( inIOHIDElementRef, value ); } if ( value > IOHIDElement_GetCalibrationSaturationMax( inIOHIDElementRef ) ) { IOHIDElement_SetCalibrationSaturationMax( inIOHIDElementRef, value ); } #endif } // IOHIDElement_SetupCalibration
// ************************************************************************* // // IOHIDElement_SetupCalibration(inIOHIDElementRef) // // Purpose: set default values for the element calibration parameters // // Inputs: inIOHIDElementRef - the IOHIDElementRef for this element // // Returns: nothing // void IOHIDElement_SetupCalibration(IOHIDElementRef inIOHIDElementRef) { // these are the min/max values returned by IOHIDValueGetScaledValue(v, kIOHIDValueScaleTypeCalibrated); IOHIDElement_SetCalibrationMin(inIOHIDElementRef, IOHIDElementGetLogicalMin(inIOHIDElementRef)); IOHIDElement_SetCalibrationMax(inIOHIDElementRef, IOHIDElementGetLogicalMax(inIOHIDElementRef)); CFIndex phyMin = IOHIDElementGetPhysicalMin(inIOHIDElementRef); CFIndex phyMax = IOHIDElementGetPhysicalMax(inIOHIDElementRef); CFIndex phyRange = phyMax - phyMin; // calculate the middle physical value we would expect from this element double phyMid = (phyMin + phyMax) / 2.f; // this is the granularity of the values returned by IOHIDValueGetScaledValue(v, kIOHIDValueScaleTypeCalibrated); // for example if set to 0.1 the values returned will be multiples of 0.1 (0.1, 0.2, 0.3, etc.) IOHIDElement_SetCalibrationGranularity(inIOHIDElementRef, 0.); Boolean isRelative = IOHIDElementIsRelative(inIOHIDElementRef); Boolean hasPreferredState = IOHIDElementHasPreferredState(inIOHIDElementRef); // define the dead zone (like in the middle of joystick axis) if (!isRelative && hasPreferredState && (phyRange > 3)) { IOHIDElement_SetCalibrationDeadZoneMin(inIOHIDElementRef, phyMid - 1.0); IOHIDElement_SetCalibrationDeadZoneMax(inIOHIDElementRef, phyMid + 1.0); } else { IOHIDElement_SetCalibrationDeadZoneMin(inIOHIDElementRef, 0.); IOHIDElement_SetCalibrationDeadZoneMax(inIOHIDElementRef, 0.); } // get the current value of this element double phyValue = IOHIDElement_GetValue(inIOHIDElementRef, kIOHIDValueScaleTypePhysical); #if true // use that that value to determine the min/max saturation values used for calibration IOHIDElement_SetCalibrationSaturationMin(inIOHIDElementRef, phyValue); IOHIDElement_SetCalibrationSaturationMax(inIOHIDElementRef, phyValue); #else // if 1 #if true // this value determines the min/max values that have been recieved from the device element IOHIDElement_SetCalibrationSaturationMin(inIOHIDElementRef, (phyMin + phyMid) / 2.f); IOHIDElement_SetCalibrationSaturationMax(inIOHIDElementRef, (phyMid + phyMax) / 2.f); #else // if 1 // use it as our min/max saturation // this value determines the min/max values that have been recieved from the device element IOHIDElement_SetCalibrationSaturationMin(inIOHIDElementRef, phyMid); IOHIDElement_SetCalibrationSaturationMax(inIOHIDElementRef, phyMid); #endif // if 1 // and the current value to adjust the current saturation values if it's outside their range if (phyValue < IOHIDElement_GetCalibrationSaturationMin(inIOHIDElementRef)) { IOHIDElement_SetCalibrationSaturationMin(inIOHIDElementRef, phyValue); } if (phyValue > IOHIDElement_GetCalibrationSaturationMax(inIOHIDElementRef)) { IOHIDElement_SetCalibrationSaturationMax(inIOHIDElementRef, phyValue); } #endif // if 1 } // IOHIDElement_SetupCalibration
PsychError PsychHIDOSGamePadAxisQuery(int deviceIndex, int axisId, double* min, double* max, double* val, char* axisLabel) { double elementValue; pRecDevice deviceRecord; pRecElement elementRecord; int elementIndex = axisId; PsychHIDVerifyInit(); deviceRecord= PsychHIDGetDeviceRecordPtrFromIndex(deviceIndex); elementRecord= PsychHIDGetElementRecordFromDeviceRecordAndElementIndex(deviceRecord, elementIndex); #ifndef __LP64__ elementValue = (double) HIDGetElementValue(deviceRecord, elementRecord); #else elementValue = IOHIDElement_GetValue(elementRecord, kIOHIDValueScaleTypePhysical); #endif if (val) *val = elementValue; return(PsychError_none); }
PsychError PsychHIDOSKbCheck(int deviceIndex, double* scanList) { pRecDevice deviceRecord; pRecElement currentElement, lastElement = NULL; int i, debuglevel = 0; static int numDeviceIndices = -1; int numDeviceUsages=NUMDEVICEUSAGES; long KbDeviceUsagePages[NUMDEVICEUSAGES]= {kHIDPage_GenericDesktop, kHIDPage_GenericDesktop, kHIDPage_GenericDesktop, kHIDPage_GenericDesktop, kHIDPage_GenericDesktop, kHIDPage_GenericDesktop, kHIDPage_GenericDesktop}; long KbDeviceUsages[NUMDEVICEUSAGES]={kHIDUsage_GD_Keyboard, kHIDUsage_GD_Keypad, kHIDUsage_GD_Mouse, kHIDUsage_GD_Pointer, kHIDUsage_GD_Joystick, kHIDUsage_GD_GamePad, kHIDUsage_GD_MultiAxisController}; static int deviceIndices[PSYCH_HID_MAX_KEYBOARD_DEVICES]; static pRecDevice deviceRecords[PSYCH_HID_MAX_KEYBOARD_DEVICES]; psych_bool isDeviceSpecified, foundUserSpecifiedDevice; double *timeValueOutput, *isKeyDownOutput, *keyArrayOutput; int m, n, p, nout; double dummyKeyDown; double dummykeyArrayOutput[256]; uint32_t usage, usagePage; int value; // We query keyboard and keypad devices only on first invocation, then cache and recycle the data: if (numDeviceIndices == -1) { PsychHIDVerifyInit(); PsychHIDGetDeviceListByUsages(numDeviceUsages, KbDeviceUsagePages, KbDeviceUsages, &numDeviceIndices, deviceIndices, deviceRecords); } // Choose the device index and its record isDeviceSpecified = (deviceIndex != INT_MAX); if(isDeviceSpecified){ //make sure that the device number provided by the user is really a keyboard or keypad. if (deviceIndex < 0) { debuglevel = 1; deviceIndex = -deviceIndex; } for(i=0;i<numDeviceIndices;i++){ if ((foundUserSpecifiedDevice=(deviceIndices[i]==deviceIndex))) break; } if(!foundUserSpecifiedDevice) PsychErrorExitMsg(PsychError_user, "Specified device number is not a keyboard or keypad device."); } else { // set the keyboard or keypad device to be the first keyboard device or, if no keyboard, the first keypad i=0; if(numDeviceIndices==0) PsychErrorExitMsg(PsychError_user, "No keyboard or keypad devices detected."); else{ deviceIndex=deviceIndices[i]; } } deviceRecord=deviceRecords[i]; // Allocate and init out return arguments. // Either alloc out the arguments, or redirect to // internal dummy variables. This to avoid mxMalloc() call overhead // inside the PsychAllocOutXXX() routines: nout = PsychGetNumNamedOutputArgs(); // keyDown flag: if (nout >= 1) { PsychAllocOutDoubleArg(1, FALSE, &isKeyDownOutput); } else { isKeyDownOutput = &dummyKeyDown; } *isKeyDownOutput= (double) FALSE; // key state vector: if (nout >= 3) { PsychAllocOutDoubleMatArg(3, FALSE, 1, 256, 1, &keyArrayOutput); } else { keyArrayOutput = &dummykeyArrayOutput[0]; } memset((void*) keyArrayOutput, 0, sizeof(double) * 256); // Query timestamp: if (nout >= 2) { PsychAllocOutDoubleArg(2, FALSE, &timeValueOutput); // Get query timestamp: PsychGetPrecisionTimerSeconds(timeValueOutput); } // Make sure our keyboard query mechanism is not blocked for security reasons, e.g., // secure password entry field active in another process, i.e., EnableSecureEventInput() active. if (PsychHIDWarnInputDisabled("PsychHID('KbCheck')")) return(PsychError_none); //step through the elements of the device. Set flags in the return array for down keys. for(currentElement=HIDGetFirstDeviceElement(deviceRecord, kHIDElementTypeInput | kHIDElementTypeCollection); (currentElement != NULL) && (currentElement != lastElement); currentElement=HIDGetNextDeviceElement(currentElement, kHIDElementTypeInput | kHIDElementTypeCollection)) { // Keep track of last queried element: lastElement = currentElement; #ifndef __LP64__ usage = currentElement->usage; usagePage = currentElement->usagePage; #else usage = IOHIDElementGetUsage(currentElement); usagePage = IOHIDElementGetUsagePage(currentElement); // printf("PTB-DEBUG: [KbCheck]: ce %p page %d usage: %d isArray: %d\n", currentElement, usagePage, usage, IOHIDElementIsArray(currentElement)); if (IOHIDElementGetType(currentElement) == kIOHIDElementTypeCollection) { CFArrayRef children = IOHIDElementGetChildren(currentElement); if (!children) continue; CFIndex idx, cnt = CFArrayGetCount(children); for ( idx = 0; idx < cnt; idx++ ) { IOHIDElementRef tIOHIDElementRef = (IOHIDElementRef) CFArrayGetValueAtIndex(children, idx); if (tIOHIDElementRef && ((IOHIDElementGetType(tIOHIDElementRef) == kIOHIDElementTypeInput_Button) || (IOHIDElementGetType(tIOHIDElementRef) == kIOHIDElementTypeInput_ScanCodes))) { usage = IOHIDElementGetUsage(tIOHIDElementRef); if ((usage <= 256) && (usage >= 1) && ( (scanList == NULL) || (scanList[usage - 1] > 0) )) { value = (int) IOHIDElement_GetValue(tIOHIDElementRef, kIOHIDValueScaleTypePhysical); if (debuglevel > 0) printf("PTB-DEBUG: [KbCheck]: usage: %x value: %d \n", usage, value); keyArrayOutput[usage - 1] = (value || (int) keyArrayOutput[usage - 1]); *isKeyDownOutput = keyArrayOutput[usage - 1] || *isKeyDownOutput; } } } // Done with this currentElement, which was a collection of buttons/keys. // Iterate to next currentElement: continue; } #endif // Classic path, or 64-Bit path for non-collection elements: if(((usagePage == kHIDPage_KeyboardOrKeypad) || (usagePage == kHIDPage_Button)) && (usage <= 256) && (usage >= 1) && ( (scanList == NULL) || (scanList[usage - 1] > 0) ) ) { #ifndef __LP64__ value = (int) HIDGetElementValue(deviceRecord, currentElement); #else value = (int) IOHIDElement_GetValue(currentElement, kIOHIDValueScaleTypePhysical); #endif if (debuglevel > 0) printf("PTB-DEBUG: [KbCheck]: usage: %x value: %d \n", usage, value); keyArrayOutput[usage - 1]=(value || (int) keyArrayOutput[usage - 1]); *isKeyDownOutput= keyArrayOutput[usage - 1] || *isKeyDownOutput; } } return(PsychError_none); }