int prHIDGetValue(VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 2; //class PyrSlot *b = g->sp - 1; //locID device PyrSlot *c = g->sp; //element cookie int locID, cookieNum; int err = slotIntVal(b, &locID); if (err) return err; err = slotIntVal(c, &cookieNum); if (err) return err; IOHIDElementCookie cookie = (IOHIDElementCookie) cookieNum; //look for the right device: pRecDevice pCurrentHIDDevice = HIDGetFirstDevice (); while (pCurrentHIDDevice && (pCurrentHIDDevice->locID !=locID)) pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice); if(!pCurrentHIDDevice) return errFailed; //look for the right element: pRecElement pCurrentHIDElement = HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeAll); // use gElementCookie to find current element while (pCurrentHIDElement && (pCurrentHIDElement->cookie != cookie)) pCurrentHIDElement = HIDGetNextDeviceElement (pCurrentHIDElement, kHIDElementTypeAll); if (pCurrentHIDElement) { SInt32 value = HIDGetElementValue (pCurrentHIDDevice, pCurrentHIDElement); // if it's not a button and it's not a hatswitch then calibrate if(( pCurrentHIDElement->type != kIOHIDElementTypeInput_Button ) && ( pCurrentHIDElement->usagePage == 0x01 && pCurrentHIDElement->usage != kHIDUsage_GD_Hatswitch)) value = HIDCalibrateValue ( value, pCurrentHIDElement ); SetInt(a, value); } else SetNil(a); return errNone; }
static SInt32 HIDScaledCalibratedValue (recDevice *pDevice, recElement *pElement, long min, long max) { float deviceScale = max - min; float readScale = pElement->maxReport - pElement->minReport; SInt32 value = HIDGetElementValue(pDevice, pElement); if (readScale == 0) return value; // no scaling at all else return ((value - pElement->minReport) * deviceScale / readScale) + min; }
static void GetInput (void) { short a; for (a = 0; a < kNumActions; a++) { if (gActionArray [a].pDevice && gActionArray [a].pElement) { gActionArray [a].value = HIDGetElementValue (gActionArray [a].pDevice, gActionArray [a].pElement); // gActionArray [a].value = HIDCalibrateValue (gActionArray [a].value, gActionArray [a].pElement); gActionArray [a].value = HIDScaleValue (gActionArray [a].value, gActionArray [a].pElement); } else gActionArray [a].value = 0; } }
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); }
/* Function to update the state of a joystick - called as a device poll. * This function shouldn't update the joystick structure directly, * but instead should call SDL_PrivateJoystick*() to deliver events * and update joystick device state. */ void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) { recDevice *device = joystick->hwdata; recElement *element; SInt32 value; int i; if (device->removed) /* device was unplugged; ignore it. */ { if (device->uncentered) { device->uncentered = 0; /* Tell the app that everything is centered/unpressed... */ for (i = 0; i < device->axes; i++) SDL_PrivateJoystickAxis(joystick, i, 0); for (i = 0; i < device->buttons; i++) SDL_PrivateJoystickButton(joystick, i, 0); for (i = 0; i < device->hats; i++) SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED); } return; } element = device->firstAxis; i = 0; while (element) { value = HIDScaledCalibratedValue(device, element, -32768, 32767); if ( value != joystick->axes[i] ) SDL_PrivateJoystickAxis(joystick, i, value); element = element->pNext; ++i; } element = device->firstButton; i = 0; while (element) { value = HIDGetElementValue(device, element); if (value > 1) /* handle pressure-sensitive buttons */ value = 1; if ( value != joystick->buttons[i] ) SDL_PrivateJoystickButton(joystick, i, value); element = element->pNext; ++i; } element = device->firstHat; i = 0; while (element) { Uint8 pos = 0; value = HIDGetElementValue(device, element); if (element->max == 3) /* 4 position hatswitch - scale up value */ value *= 2; else if (element->max != 7) /* Neither a 4 nor 8 positions - fall back to default position (centered) */ value = -1; switch(value) { case 0: pos = SDL_HAT_UP; break; case 1: pos = SDL_HAT_RIGHTUP; break; case 2: pos = SDL_HAT_RIGHT; break; case 3: pos = SDL_HAT_RIGHTDOWN; break; case 4: pos = SDL_HAT_DOWN; break; case 5: pos = SDL_HAT_LEFTDOWN; break; case 6: pos = SDL_HAT_LEFT; break; case 7: pos = SDL_HAT_LEFTUP; break; default: /* Every other value is mapped to center. We do that because some * joysticks use 8 and some 15 for this value, and apparently * there are even more variants out there - so we try to be generous. */ pos = SDL_HAT_CENTERED; break; } if ( pos != joystick->hats[i] ) SDL_PrivateJoystickHat(joystick, i, pos); element = element->pNext; ++i; } return; }
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; } }
/* Function to update the state of a joystick - called as a device poll. * This function shouldn't update the joystick structure directly, * but instead should call SDL_PrivateJoystick*() to deliver events * and update joystick device state. */ void SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) { recDevice *device = joystick->hwdata; recElement *element; SInt32 value, range; int i; if ( !device ) return; if (device->removed) { /* device was unplugged; ignore it. */ recDevice *devicelist = gpDeviceList; joystick->closed = 1; joystick->uncentered = 1; if ( devicelist == device ) { gpDeviceList = device->pNext; } else { while ( devicelist->pNext != device ) { devicelist = devicelist->pNext; } devicelist->pNext = device->pNext; } DisposePtr((Ptr) device); joystick->hwdata = NULL; #if !SDL_EVENTS_DISABLED SDL_Event event; event.type = SDL_JOYDEVICEREMOVED; if (SDL_GetEventState(event.type) == SDL_ENABLE) { event.jdevice.which = joystick->instance_id; if ((SDL_EventOK == NULL) || (*SDL_EventOK) (SDL_EventOKParam, &event)) { SDL_PushEvent(&event); } } #endif /* !SDL_EVENTS_DISABLED */ return; } element = device->firstAxis; i = 0; while (element) { value = HIDScaledCalibratedValue(device, element, -32768, 32767); if (value != joystick->axes[i]) SDL_PrivateJoystickAxis(joystick, i, value); element = element->pNext; ++i; } element = device->firstButton; i = 0; while (element) { value = HIDGetElementValue(device, element); if (value > 1) /* handle pressure-sensitive buttons */ value = 1; if (value != joystick->buttons[i]) SDL_PrivateJoystickButton(joystick, i, value); element = element->pNext; ++i; } element = device->firstHat; i = 0; while (element) { Uint8 pos = 0; range = (element->max - element->min + 1); value = HIDGetElementValue(device, element) - element->min; if (range == 4) /* 4 position hatswitch - scale up value */ value *= 2; else if (range != 8) /* Neither a 4 nor 8 positions - fall back to default position (centered) */ value = -1; switch (value) { case 0: pos = SDL_HAT_UP; break; case 1: pos = SDL_HAT_RIGHTUP; break; case 2: pos = SDL_HAT_RIGHT; break; case 3: pos = SDL_HAT_RIGHTDOWN; break; case 4: pos = SDL_HAT_DOWN; break; case 5: pos = SDL_HAT_LEFTDOWN; break; case 6: pos = SDL_HAT_LEFT; break; case 7: pos = SDL_HAT_LEFTUP; break; default: /* Every other value is mapped to center. We do that because some * joysticks use 8 and some 15 for this value, and apparently * there are even more variants out there - so we try to be generous. */ pos = SDL_HAT_CENTERED; break; } if (pos != joystick->hats[i]) SDL_PrivateJoystickHat(joystick, i, pos); element = element->pNext; ++i; } return; }
static pascal OSStatus ControllerEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) { OSStatus err, result = eventNotHandledErr; WindowRef tWindowRef; tWindowRef = (WindowRef) inUserData; switch (GetEventClass(inEvent)) { case kEventClassWindow: switch (GetEventKind(inEvent)) { case kEventWindowClose: QuitAppModalLoopForWindow(tWindowRef); result = noErr; break; } break; case kEventClassCommand: switch (GetEventKind(inEvent)) { HICommand tHICommand; case kEventCommandUpdateStatus: err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); if (err == noErr && tHICommand.commandID == 'clos') { UpdateMenuCommandStatus(true); result = noErr; } break; case kEventCommandProcess: err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); if (err == noErr) { if (tHICommand.commandID == 'CLRa') { ClearPadSetting(); result = noErr; } else { SInt32 command = -1, count; for (count = 0; count < kNeedCount; count++) if (tHICommand.commandID == gControlIDs[count].signature) command = count; if (command >= 0) { pRecDevice pDevice; pRecElement pElement; FlushEventQueue(GetCurrentEventQueue()); if (HIDConfigureAction(&pDevice, &pElement, 2.5f)) { if (command < MAC_MAX_PLAYERS * 4) // Direction { int i = command >> 2; // Player long curv = HIDGetElementValue(pDevice, pElement); if (pElement->usage == kHIDUsage_GD_Hatswitch) // Hat Switch { gActionRecs[kUp(i)].fDevice = gActionRecs[kDn(i)].fDevice = gActionRecs[kLf(i)].fDevice = gActionRecs[kRt(i)].fDevice = pDevice; gActionRecs[kUp(i)].fElement = gActionRecs[kDn(i)].fElement = gActionRecs[kLf(i)].fElement = gActionRecs[kRt(i)].fElement = pElement; if (pDevice->vendorID == 1103) // Thrustmaster gDirectionInfo[i].type = (pElement->max > 4) ? kPadElemTypeOtherHat8 : kPadElemTypeOtherHat4; else { if (pElement->max > 4) { if (((command % 4 == 0) && (curv == 0)) || // Up : 0 ((command % 4 == 1) && (curv == 4)) || // Down : 4 ((command % 4 == 2) && (curv == 6)) || // Left : 6 ((command % 4 == 3) && (curv == 2))) // Right : 2 gDirectionInfo[i].type = kPadElemTypeOtherHat8; else gDirectionInfo[i].type = kPadElemTypeHat8; } else { if (((command % 4 == 0) && (curv == 0)) || // Up : 0 ((command % 4 == 1) && (curv == 2)) || // Down : 2 ((command % 4 == 2) && (curv == 3)) || // Left : 3 ((command % 4 == 3) && (curv == 1))) // Right : 1 gDirectionInfo[i].type = kPadElemTypeOtherHat4; else gDirectionInfo[i].type = kPadElemTypeHat4; } } gDirectionInfo[i].device [kPadHat] = pDevice; gDirectionInfo[i].element[kPadHat] = pElement; gDirectionInfo[i].max [kPadHat] = pElement->max; gDirectionInfo[i].min [kPadHat] = pElement->min; } else if (pElement->max - pElement->min > 1) // Axis (maybe) { if ((command % 4 == 0) || (command % 4 == 1)) // Up or Dn { gActionRecs[kUp(i)].fDevice = gActionRecs[kDn(i)].fDevice = pDevice; gActionRecs[kUp(i)].fElement = gActionRecs[kDn(i)].fElement = pElement; gDirectionInfo[i].type = kPadElemTypeAxis; gDirectionInfo[i].device [kPadYAxis] = pDevice; gDirectionInfo[i].element[kPadYAxis] = pElement; gDirectionInfo[i].max [kPadYAxis] = pElement->max; gDirectionInfo[i].min [kPadYAxis] = pElement->min; gDirectionInfo[i].mid [kPadYAxis] = (gDirectionInfo[i].max[kPadYAxis] + gDirectionInfo[i].min[kPadYAxis]) >> 1; gDirectionInfo[i].maxmid [kPadYAxis] = (gDirectionInfo[i].max[kPadYAxis] + gDirectionInfo[i].mid[kPadYAxis]) >> 1; gDirectionInfo[i].midmin [kPadYAxis] = (gDirectionInfo[i].mid[kPadYAxis] + gDirectionInfo[i].min[kPadYAxis]) >> 1; } else // Lf or Rt { gActionRecs[kLf(i)].fDevice = gActionRecs[kRt(i)].fDevice = pDevice; gActionRecs[kLf(i)].fElement = gActionRecs[kRt(i)].fElement = pElement; gDirectionInfo[i].type = kPadElemTypeAxis; gDirectionInfo[i].device [kPadXAxis] = pDevice; gDirectionInfo[i].element[kPadXAxis] = pElement; gDirectionInfo[i].max [kPadXAxis] = pElement->max; gDirectionInfo[i].min [kPadXAxis] = pElement->min; gDirectionInfo[i].mid [kPadXAxis] = (gDirectionInfo[i].max[kPadXAxis] + gDirectionInfo[i].min[kPadXAxis]) >> 1; gDirectionInfo[i].maxmid [kPadXAxis] = (gDirectionInfo[i].max[kPadXAxis] + gDirectionInfo[i].mid[kPadXAxis]) >> 1; gDirectionInfo[i].midmin [kPadXAxis] = (gDirectionInfo[i].mid[kPadXAxis] + gDirectionInfo[i].min[kPadXAxis]) >> 1; } } else // Button (maybe) { gActionRecs[command].fDevice = pDevice; gActionRecs[command].fElement = pElement; gDirectionInfo[i].type = kPadElemTypeButton; } gDirectionHint[i] = gDirectionInfo[i].type; } else { gActionRecs[command].fDevice = pDevice; gActionRecs[command].fElement = pElement; } }
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); }
PsychError PSYCHHIDKbCheck(void) { pRecDevice deviceRecord; pRecElement currentElement; int i, deviceIndex, numDeviceIndices; long KeysUsagePage=7; long KbDeviceUsagePage= 1, KbDeviceUsage=6; int deviceIndices[PSYCH_HID_MAX_KEYBOARD_DEVICES]; pRecDevice deviceRecords[PSYCH_HID_MAX_KEYBOARD_DEVICES]; boolean isDeviceSpecified, foundUserSpecifiedDevice, isKeyArgPresent, isTimeArgPresent; double *timeValueOutput, *isKeyDownOutput; PsychNativeBooleanType *keyArrayOutput; PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumOutputArgs(3)); PsychErrorExit(PsychCapNumInputArgs(1)); //Specifies the number of the keyboard to scan. PsychHIDVerifyInit(); //Choose the device index and its record PsychHIDGetDeviceListByUsage(KbDeviceUsagePage, KbDeviceUsage, &numDeviceIndices, deviceIndices, deviceRecords); isDeviceSpecified=PsychCopyInIntegerArg(1, FALSE, &deviceIndex); if(isDeviceSpecified){ //make sure that the device number provided by the user is really a keyboard. for(i=0;i<numDeviceIndices;i++){ if(foundUserSpecifiedDevice=(deviceIndices[i]==deviceIndex)) break; } if(!foundUserSpecifiedDevice) PsychErrorExitMsg(PsychError_user, "Specified device number is not a keyboard device."); }else{ // set the keyboard device to be the first keyboard device i=0; if(numDeviceIndices==0) PsychErrorExitMsg(PsychError_user, "No keyboard devices detected."); else{ deviceIndex=deviceIndices[i]; } } deviceRecord=deviceRecords[i]; //Allocate and init out return arguments. isKeyArgPresent = PsychAllocOutBooleanMatArg(3, FALSE, 1, 256, 1, &keyArrayOutput); isTimeArgPresent = PsychAllocOutDoubleArg(2, FALSE, &timeValueOutput); PsychGetPrecisionTimerSeconds(timeValueOutput); PsychAllocOutDoubleArg(1, FALSE, &isKeyDownOutput); *isKeyDownOutput=(double)FALSE; //step through the elements of the device. Set flags in the return array for down keys. for(currentElement=HIDGetFirstDeviceElement(deviceRecord, kHIDElementTypeInput); currentElement != NULL; currentElement=HIDGetNextDeviceElement(currentElement, kHIDElementTypeInput)) { if(currentElement->usagePage==KeysUsagePage && currentElement->usage <= 256 && currentElement->usage >=1){ //printf("usage: %x value: %d \n", currentElement->usage, HIDGetElementValue(deviceRecord, currentElement)); keyArrayOutput[currentElement->usage - 1]=(PsychNativeBooleanType)(HIDGetElementValue(deviceRecord, currentElement) || keyArrayOutput[currentElement->usage - 1]); *isKeyDownOutput= keyArrayOutput[currentElement->usage - 1] || *isKeyDownOutput; } } return(PsychError_none); }