int prHIDDequeueElement(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); while (pCurrentHIDElement && (pCurrentHIDElement->cookie != cookie)) pCurrentHIDElement = HIDGetNextDeviceElement (pCurrentHIDElement, kHIDElementTypeAll); if(!pCurrentHIDElement) return errFailed; HIDDequeueElement(pCurrentHIDDevice, pCurrentHIDElement); return errNone; }
/* PsychHIDGetDeviceRecordPtrFromIndex() The inverse of PsychHIDGetIndexFromRecord() Accept the index from the list of device records and return a pointer to the indicated record. Externally the list is one-indexed. */ pRecDevice PsychHIDGetDeviceRecordPtrFromIndex(int deviceIndex) { int i; pRecDevice currentDevice=NULL; PsychHIDVerifyInit(); i=1; for(currentDevice=HIDGetFirstDevice(); currentDevice != NULL; currentDevice=HIDGetNextDevice(currentDevice)){ if(i==deviceIndex) { #if PSYCH_SYSTEM != PSYCH_OSX if (!currentDevice->interface) { currentDevice->interface = (void*) hid_open_path(currentDevice->transport); if (!currentDevice->interface) PsychErrorExitMsg(PsychError_system, "HIDLIB Failed to open USB device!"); // Set read ops on device to non-blocking: hid_set_nonblocking((hid_device*) currentDevice->interface, 1); } #endif return(currentDevice); } ++i; } PsychErrorExitMsg(PsychError_user, "Invalid device index specified. Has a device been unplugged? Try rebuilding the device list"); return(NULL); //make the compiler happy. }
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; }
int prHIDBuildElementList(VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 2; //class PyrSlot *b = g->sp - 1; //locID device PyrSlot *c = g->sp; //array int locID; int err = slotIntVal(b, &locID); if (err) return err; //look for the right device: pRecDevice pCurrentHIDDevice = HIDGetFirstDevice (); while (pCurrentHIDDevice && (pCurrentHIDDevice->locID !=locID)) pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice); if(!pCurrentHIDDevice) return errFailed; pRecElement devElement = HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeAll ); UInt32 numElements = HIDCountDeviceElements (pCurrentHIDDevice, kHIDElementTypeAll ); // PyrObject* devAllElementsArray = newPyrArray(g->gc, numElements * sizeof(PyrObject), 0 , true); PyrObject *devAllElementsArray = c->uo; // post("numElements: %d\n", numElements); numElements = sc_clip(numElements, 0, devAllElementsArray->size); for(uint i=0; i<numElements; i++){ if(devElement){ char cstrElementName [256]; PyrObject* devElementArray = newPyrArray(g->gc, 8 * sizeof(PyrObject), 0 , true); // type name (1) HIDGetTypeName((IOHIDElementType) devElement->type, cstrElementName); PyrString *devstring = newPyrString(g->gc, cstrElementName, 0, true); SetObject(devElementArray->slots+devElementArray->size++, devstring); //g->gc->GCWrite(devElementArray, (PyrObject*) devstring); //usage (2) HIDGetUsageName (devElement->usagePage, devElement->usage, cstrElementName); PyrString *usestring = newPyrString(g->gc, cstrElementName, 0, true); SetObject(devElementArray->slots+devElementArray->size++, usestring); //g->gc->GCWrite(devElementArray, (PyrObject*) usestring); //cookie (3) SetInt(devElementArray->slots+devElementArray->size++, (long) devElement->cookie); // min (4) SetInt(devElementArray->slots+devElementArray->size++, (long) devElement->min); // max (5) SetInt(devElementArray->slots+devElementArray->size++, (long) devElement->max); // IO type as int: (6) SetInt(devElementArray->slots+devElementArray->size++, (int) devElement->type); // Usage page as int: (7) SetInt(devElementArray->slots+devElementArray->size++, (long) devElement->usagePage); // Usage type as int: (8) SetInt(devElementArray->slots+devElementArray->size++, (long) devElement->usage); SetObject(devAllElementsArray->slots+i, devElementArray); //g->gc->GCWrite(devAllElementsArray, (PyrObject*) devElementArray); } devElement = HIDGetNextDeviceElement (devElement, kHIDElementTypeAll); } SetObject(a, devAllElementsArray); return errNone; }
void PushQueueEvents_CalibratedValue (){ IOHIDEventStruct event; pRecDevice pCurrentHIDDevice = HIDGetFirstDevice (); int numdevs = gNumberOfHIDDevices; unsigned char result; for(int i=0; i< numdevs; i++){ result = HIDGetEvent(pCurrentHIDDevice, (void*) &event); if(result && compiledOK) { SInt32 value = event.value; int vendorID = pCurrentHIDDevice->vendorID; int productID = pCurrentHIDDevice->productID; int locID = pCurrentHIDDevice->locID; IOHIDElementCookie cookie = (IOHIDElementCookie) event.elementCookie; pRecElement pCurrentHIDElement = HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeAll); // use gElementCookie to find current element while (pCurrentHIDElement && ( (pCurrentHIDElement->cookie) != cookie)) pCurrentHIDElement = HIDGetNextDeviceElement (pCurrentHIDElement, kHIDElementTypeAll); if (pCurrentHIDElement) { value = HIDCalibrateValue(value, pCurrentHIDElement); //find element to calibrate VMGlobals *g = gMainVMGlobals; pthread_mutex_lock (&gLangMutex); g->canCallOS = false; // cannot call the OS ++g->sp; SetObject(g->sp, s_hid->u.classobj); // Set the class HIDService //set arguments: ++g->sp;SetInt(g->sp, vendorID); ++g->sp;SetInt(g->sp, productID); ++g->sp;SetInt(g->sp, locID); ++g->sp;SetInt(g->sp, (int) cookie); ++g->sp;SetInt(g->sp, value); runInterpreter(g, s_hidAction, 6); g->canCallOS = false; // cannot call the OS pthread_mutex_unlock (&gLangMutex); } } /* FIXME: this does not seem to be working! if ( !HIDIsValidDevice(pCurrentHIDDevice) ) { // readError post("HID: read Error\n"); int locID = pCurrentHIDDevice->locID; VMGlobals *g = gMainVMGlobals; pthread_mutex_lock (&gLangMutex); g->canCallOS = false; // cannot call the OS ++g->sp; SetObject(g->sp, s_hid->u.classobj); // Set the class HIDService ++g->sp;SetInt(g->sp, locID); runInterpreter(g, s_readError, 2); g->canCallOS = false; // cannot call the OS pthread_mutex_unlock (&gLangMutex); }*/ pCurrentHIDDevice = HIDGetNextDevice(pCurrentHIDDevice); } }
int prHIDSetValue(VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 3; //class PyrSlot *b = g->sp - 2; //locID PyrSlot *c = g->sp - 1; //element device PyrSlot *d = g->sp; //value cookie int locID, cookieNum, value; int err = slotIntVal(b, &locID); if (err) return err; err = slotIntVal(c, &cookieNum); if (err) return err; IOHIDElementCookie cookie = (IOHIDElementCookie) cookieNum; err = slotIntVal(d, &value); if (err) return err; //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); //struct IOHIDEventStruct //{ // IOHIDElementType type; // IOHIDElementCookie elementCookie; // SInt32 value; // AbsoluteTime timestamp; // UInt32 longValueSize; // void * longValue; //}; if (pCurrentHIDElement) { IOHIDEventStruct event = { kIOHIDElementTypeOutput, pCurrentHIDElement->cookie, value, {0}, sizeof(int), NULL }; SInt32 value = HIDSetElementValue (pCurrentHIDDevice, pCurrentHIDElement, &event); // 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; }
PsychError PSYCHHIDGetDevices(void) { pRecDevice currentDevice=NULL; const char *deviceFieldNames[]={"usagePageValue", "usageValue", "usageName", "index", "transport", "vendorID", "productID", "version", "manufacturer", "product", "serialNumber", "locationID", "totalElements", "features", "inputs", "outputs", "collections", "axes", "buttons", "hats", "sliders", "dials", "wheels"}; int numDeviceStructElements, numDeviceStructFieldNames=23, deviceIndex; PsychGenericScriptType *deviceStruct; char usageName[PSYCH_HID_MAX_DEVICE_ELEMENT_USAGE_NAME_LENGTH]; PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumOutputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(0)); PsychHIDVerifyInit(); numDeviceStructElements=(int)HIDCountDevices(); PsychAllocOutStructArray(1, FALSE, numDeviceStructElements, numDeviceStructFieldNames, deviceFieldNames, &deviceStruct); deviceIndex=0; for(currentDevice=HIDGetFirstDevice(); currentDevice != NULL; currentDevice=HIDGetNextDevice(currentDevice)){ PsychSetStructArrayDoubleElement("usagePageValue", deviceIndex, (double)currentDevice->usagePage, deviceStruct); PsychSetStructArrayDoubleElement("usageValue", deviceIndex, (double)currentDevice->usage, deviceStruct); HIDGetUsageName (currentDevice->usagePage, currentDevice->usage, usageName); PsychSetStructArrayStringElement("usageName", deviceIndex, usageName, deviceStruct); PsychSetStructArrayDoubleElement("index", deviceIndex, (double)deviceIndex+1, deviceStruct); PsychSetStructArrayStringElement("transport", deviceIndex, currentDevice->transport, deviceStruct); PsychSetStructArrayDoubleElement("vendorID", deviceIndex, (double)currentDevice->vendorID, deviceStruct); PsychSetStructArrayDoubleElement("productID", deviceIndex, (double)currentDevice->productID, deviceStruct); PsychSetStructArrayDoubleElement("version", deviceIndex, (double)currentDevice->version, deviceStruct); PsychSetStructArrayStringElement("manufacturer", deviceIndex, currentDevice->manufacturer, deviceStruct); PsychSetStructArrayStringElement("product", deviceIndex, currentDevice->product, deviceStruct); PsychSetStructArrayStringElement("serialNumber", deviceIndex, currentDevice->serial, deviceStruct); PsychSetStructArrayDoubleElement("locationID", deviceIndex, (double)currentDevice->locID, deviceStruct); PsychSetStructArrayDoubleElement("totalElements", deviceIndex, (double)currentDevice->totalElements, deviceStruct); PsychSetStructArrayDoubleElement("features", deviceIndex, (double)currentDevice->features, deviceStruct); PsychSetStructArrayDoubleElement("inputs", deviceIndex, (double)currentDevice->inputs, deviceStruct); PsychSetStructArrayDoubleElement("outputs", deviceIndex, (double)currentDevice->outputs, deviceStruct); PsychSetStructArrayDoubleElement("collections", deviceIndex, (double)currentDevice->collections, deviceStruct); PsychSetStructArrayDoubleElement("axes", deviceIndex, (double)currentDevice->axis, deviceStruct); PsychSetStructArrayDoubleElement("buttons", deviceIndex, (double)currentDevice->buttons, deviceStruct); PsychSetStructArrayDoubleElement("hats", deviceIndex, (double)currentDevice->hats, deviceStruct); PsychSetStructArrayDoubleElement("sliders", deviceIndex, (double)currentDevice->sliders, deviceStruct); PsychSetStructArrayDoubleElement("dials", deviceIndex, (double)currentDevice->dials, deviceStruct); PsychSetStructArrayDoubleElement("wheels", deviceIndex, (double)currentDevice->wheels, deviceStruct); ++deviceIndex; } return(PsychError_none); }
// releases all device queues for quit or rebuild (must be called) // does not release device interfaces, application must call ReleaseHIDDeviceList on exit IOReturn HIDReleaseAllDeviceQueues( void ) { IOReturn result = kIOReturnSuccess; IOHIDDeviceRef tIOHIDDeviceRef = HIDGetFirstDevice(); while ( tIOHIDDeviceRef ) { result = HIDDequeueDevice( tIOHIDDeviceRef ); if ( kIOReturnSuccess != result ) { HIDReportErrorNum( "Could not dequeue device.", result ); } tIOHIDDeviceRef = HIDGetNextDevice( tIOHIDDeviceRef ); } return result; } /* HIDReleaseAllDeviceQueues */
/* PsychHIDGetDeviceRecordPtrFromIndex() The inverse of PsychHIDGetIndexFromRecord() Accept the index from the list of device records and return a pointer to the indicated record. Externally the list is one-indexed. */ pRecDevice PsychHIDGetDeviceRecordPtrFromIndex(int deviceIndex) { int i; pRecDevice currentDevice=NULL; PsychHIDVerifyInit(); i=1; for(currentDevice=HIDGetFirstDevice(); currentDevice != NULL; currentDevice=HIDGetNextDevice(currentDevice)){ if(i==deviceIndex) return(currentDevice); ++i; } PsychErrorExitMsg(PsychError_internal, "Invalid device index specified. Has a device has been unplugged? Try rebuilding the device list"); return(NULL); //make the compiler happy. }
int prHIDGetElementListSize(VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 1; //class PyrSlot *b = g->sp; //locID device int locID; int err = slotIntVal(b, &locID); if (err) return err; pRecDevice pCurrentHIDDevice = HIDGetFirstDevice (); while (pCurrentHIDDevice && (pCurrentHIDDevice->locID !=locID)) pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice); if(!pCurrentHIDDevice) return errFailed; UInt32 numElements = HIDCountDeviceElements (pCurrentHIDDevice, kHIDElementTypeAll ); SetInt(a, numElements); return errNone; }
int prHIDDequeueDevice(VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 1; //class PyrSlot *b = g->sp; //locID device int locID; int err = slotIntVal(b, &locID); if (err) return err; //look for the right device: pRecDevice pCurrentHIDDevice = HIDGetFirstDevice (); while (pCurrentHIDDevice && (pCurrentHIDDevice->locID !=locID)) pCurrentHIDDevice = HIDGetNextDevice (pCurrentHIDDevice); if(!pCurrentHIDDevice) return errFailed; HIDDequeueDevice(pCurrentHIDDevice); return errNone; }
/* PsychHIDGetDeviceListByUsage() */ void PsychHIDGetDeviceListByUsage(long usagePage, long usage, int *numDeviceIndices, int *deviceIndices, pRecDevice *deviceRecords) { pRecDevice currentDevice; int currentDeviceIndex; PsychHIDVerifyInit(); currentDeviceIndex=0; *numDeviceIndices=0; for(currentDevice=HIDGetFirstDevice(); currentDevice != NULL; currentDevice=HIDGetNextDevice(currentDevice)){ ++currentDeviceIndex; if(currentDevice->usagePage==usagePage && currentDevice->usage==usage){ deviceRecords[*numDeviceIndices]=currentDevice; deviceIndices[*numDeviceIndices]=currentDeviceIndex; //the array is 0-indexed, devices are 1-indexed. ++(*numDeviceIndices); } } }
/* PsychHIDGetDeviceListByUsages() */ void PsychHIDGetDeviceListByUsages(int numUsages, long *usagePages, long *usages, int *numDeviceIndices, int *deviceIndices, pRecDevice *deviceRecords) { pRecDevice currentDevice; int currentDeviceIndex; int currentUsage; long *usagePage; long *usage; PsychHIDVerifyInit(); *numDeviceIndices = 0; for (usagePage = usagePages, usage = usages, currentUsage = 0; currentUsage < numUsages; usagePage++, usage++, currentUsage++) { currentDeviceIndex = 0; for (currentDevice = HIDGetFirstDevice(); currentDevice != NULL; currentDevice = HIDGetNextDevice(currentDevice)) { ++currentDeviceIndex; if (IOHIDDevice_GetPrimaryUsagePage(currentDevice) == *usagePage && IOHIDDevice_GetPrimaryUsage(currentDevice) == *usage) { deviceRecords[*numDeviceIndices] = currentDevice; deviceIndices[*numDeviceIndices] = currentDeviceIndex; //the array is 0-indexed, devices are 1-indexed. ++(*numDeviceIndices); } } } }
static Boolean SetupHIDInputs (void) { UInt32 aUsage = 0; UInt32 aUsagePage = 0; pRecDevice pDevice = NULL; InitHIDInputArray (); HIDUpdateDeviceList(&aUsagePage, &aUsage, 1); // will do the right thing the first time pDevice = HIDGetFirstDevice(); // get the first device while(pDevice) { printf("Device: %s, %s.\n", pDevice->manufacturer, pDevice->product); // if the device has 4 axis try to use it if ((pDevice->axis >= 3) && (GetInputElements (pDevice))) // if we can find the axis needed use else continue break; pDevice = HIDGetNextDevice(pDevice); // check next device } if (pDevice) // means we found a valid device { printf("Using Device: %s, %s.\n", pDevice->manufacturer, pDevice->product); return true; } else return false; }
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; } }
// Get matching element from config record // takes a pre-allocated and filled out config record // search for matching device // return pDevice, pElement and cookie for action long HIDGetElementConfig (pRecSaveHID pConfigRec, pRecDevice * ppDevice, pRecElement * ppElement) { if (!pConfigRec->locID && !pConfigRec->vendorID && !pConfigRec->productID && !pConfigRec->usage && !pConfigRec->usagePage) { // early out *ppDevice = NULL; *ppElement = NULL; return pConfigRec->actionCookie; } pRecDevice pDevice, pFoundDevice = NULL; pRecElement pElement, pFoundElement = NULL; // compare to current device list for matches // look for device if (pConfigRec->locID && pConfigRec->vendorID && pConfigRec->productID) { // look for specific device type plug in to same port pDevice = HIDGetFirstDevice (); while (pDevice) { if ((pConfigRec->locID == pDevice->locID) && (pConfigRec->vendorID == pDevice->vendorID) && (pConfigRec->productID == pDevice->productID)) pFoundDevice = pDevice; if (pFoundDevice) break; pDevice = HIDGetNextDevice (pDevice); } if (pFoundDevice) { pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO); while (pElement) { if (pConfigRec->cookie == pElement->cookie) pFoundElement = pElement; if (pFoundElement) break; pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); } // if no cookie match (should NOT occur) match on usage pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO); while (pElement) { if ((pConfigRec->usageE == pElement->usage) && (pConfigRec->usagePageE == pElement->usagePage)) pFoundElement = pElement; if (pFoundElement) break; pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); } if (pElement) { // set min and max values if same device pElement->minReport = pConfigRec->minReport; pElement->maxReport = pConfigRec->maxReport; } } } // if we have not found a match, look at just vendor and product if ((NULL == pFoundDevice) && (pConfigRec->vendorID && pConfigRec->productID)) { pDevice = HIDGetFirstDevice (); while (pDevice) { if ((pConfigRec->vendorID == pDevice->vendorID) && (pConfigRec->productID == pDevice->productID)) pFoundDevice = pDevice; if (pFoundDevice) break; pDevice = HIDGetNextDevice (pDevice); } // match elements by cookie since same device type if (pFoundDevice) { pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO); while (pElement) { if (pConfigRec->cookie == pElement->cookie) pFoundElement = pElement; if (pFoundElement) break; pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); } // if no cookie match (should NOT occur) match on usage pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO); while (pElement) { if ((pConfigRec->usageE == pElement->usage) && (pConfigRec->usagePageE == pElement->usagePage)) pFoundElement = pElement; if (pFoundElement) break; pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); } if (pElement) { // set min and max values if same device pElement->minReport = pConfigRec->minReport; pElement->maxReport = pConfigRec->maxReport; } } } // can't find matching device return NULL, do not return first device if ((NULL == pFoundDevice) || (NULL == pFoundElement)) { // no HID device *ppDevice = NULL; *ppElement = NULL; return pConfigRec->actionCookie; } else { // HID device *ppDevice = pFoundDevice; *ppElement = pFoundElement; return pConfigRec->actionCookie; } }
/* PsychHIDGetDeviceListByUsage() */ void PsychHIDGetDeviceListByUsage(long usagePage, long usage, int *numDeviceIndices, int *deviceIndices, pRecDevice *deviceRecords) { pRecDevice currentDevice; int currentDeviceIndex; PsychHIDVerifyInit(); currentDeviceIndex=0; *numDeviceIndices=0; for(currentDevice=HIDGetFirstDevice(); currentDevice != NULL; currentDevice=HIDGetNextDevice(currentDevice)){ ++currentDeviceIndex; #ifndef __LP64__ if(currentDevice->usagePage==usagePage && currentDevice->usage==usage){ #else if(IOHIDDevice_GetUsagePage(currentDevice) == usagePage && IOHIDDevice_GetUsage(currentDevice) == usage){ #endif deviceRecords[*numDeviceIndices]=currentDevice; deviceIndices[*numDeviceIndices]=currentDeviceIndex; //the array is 0-indexed, devices are 1-indexed. ++(*numDeviceIndices); } } } /* PsychHIDGetDeviceListByUsages() */ void PsychHIDGetDeviceListByUsages(int numUsages, long *usagePages, long *usages, int *numDeviceIndices, int *deviceIndices, pRecDevice *deviceRecords) { pRecDevice currentDevice; int currentDeviceIndex; int currentUsage; long *usagePage; long *usage; PsychHIDVerifyInit(); *numDeviceIndices=0; for(usagePage=usagePages, usage=usages, currentUsage=0; currentUsage<numUsages; usagePage++, usage++, currentUsage++){ currentDeviceIndex=0; for(currentDevice=HIDGetFirstDevice(); currentDevice != NULL; currentDevice=HIDGetNextDevice(currentDevice)){ ++currentDeviceIndex; #ifndef __LP64__ if(currentDevice->usagePage==*usagePage && currentDevice->usage==*usage){ #else if(IOHIDDevice_GetPrimaryUsagePage(currentDevice) == *usagePage && IOHIDDevice_GetPrimaryUsage(currentDevice) == *usage){ #endif deviceRecords[*numDeviceIndices]=currentDevice; deviceIndices[*numDeviceIndices]=currentDeviceIndex; //the array is 0-indexed, devices are 1-indexed. ++(*numDeviceIndices); } } } } /* PsychHIDGetIndexFromRecord() The inverse of PsychHIDGetDeviceRecordPtrFromIndex. This O(n) where n is the number of device elements. We could make it O(1) if we modified the element structure in the HID Utilities library to include a field specifying the index of the element or collection. Note that if PsychHIDGetIndexFromRecord() is O(n) then its caller, PsychHIDGetCollections, is O(n^2) for each device, whereas if PsychHIDGetIndexFromRecord() is O(1) then psychHIDGetCollections becomes O(n) for each device. */ int PsychHIDGetIndexFromRecord(pRecDevice deviceRecord, pRecElement elementRecord, HIDElementTypeMask typeMask) { int elementIndex; pRecElement currentElement; if(elementRecord==NULL) return(0); elementIndex=1; for(currentElement=HIDGetFirstDeviceElement(deviceRecord, typeMask); currentElement != elementRecord && currentElement != NULL; currentElement=HIDGetNextDeviceElement(currentElement, typeMask)) ++elementIndex; if(currentElement==elementRecord) return(elementIndex); else{ PsychErrorExitMsg(PsychError_internal, "Element record not found within device record"); return(0); //make the compiler happy } }
long HIDRestoreElementConfig (FILE * fileRef, pRecDevice * ppDevice, pRecElement * ppElement) { // Device: serial,vendorID, productID, location, usagePage, usage // Element: cookie, usagePage, usage, pRecDevice pDevice, pFoundDevice = NULL; pRecElement pElement, pFoundElement = NULL; recSaveHID restoreRec; fread ((void *) &restoreRec, 1, sizeof (recSaveHID), fileRef); // compare to current device list for matches // look for device if (restoreRec.locID && restoreRec.vendorID && restoreRec.productID) { // look for specific device type plug in to same port pDevice = HIDGetFirstDevice (); while (pDevice) { if ((restoreRec.locID == pDevice->locID) && (restoreRec.vendorID == pDevice->vendorID) && (restoreRec.productID == pDevice->productID)) pFoundDevice = pDevice; if (pFoundDevice) break; pDevice = HIDGetNextDevice (pDevice); } if (pFoundDevice) { pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO); while (pElement) { if (restoreRec.cookie == pElement->cookie) pFoundElement = pElement; if (pFoundElement) break; pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); } // if no cookie match (should NOT occur) match on usage pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO); while (pElement) { if ((restoreRec.usageE == pElement->usage) && (restoreRec.usagePageE == pElement->usagePage)) pFoundElement = pElement; if (pFoundElement) break; pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); } } } // if we have not found a match, look at just vendor and product if ((NULL == pFoundDevice) && (restoreRec.vendorID && restoreRec.productID)) { pDevice = HIDGetFirstDevice (); while (pDevice) { if ((restoreRec.vendorID == pDevice->vendorID) && (restoreRec.productID == pDevice->productID)) pFoundDevice = pDevice; if (pFoundDevice) break; pDevice = HIDGetNextDevice (pDevice); } // match elements by cookie since same device type if (pFoundDevice) { pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO); while (pElement) { if (restoreRec.cookie == pElement->cookie) pFoundElement = pElement; if (pFoundElement) break; pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); } // if no cookie match (should NOT occur) match on usage pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO); while (pElement) { if ((restoreRec.usageE == pElement->usage) && (restoreRec.usagePageE == pElement->usagePage)) pFoundElement = pElement; if (pFoundElement) break; pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); } } } // if we have not found a match look for just same type of device if ((NULL == pFoundDevice) && (restoreRec.usage && restoreRec.usagePage)) { pDevice = HIDGetFirstDevice (); while (pDevice) { if ((restoreRec.usage == pDevice->usage) && (restoreRec.usagePage == pDevice->usagePage)) pFoundDevice = pDevice; if (pFoundDevice) break; pDevice = HIDGetNextDevice (pDevice); } // match elements by type if (pFoundDevice) { pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO); while (pElement) { if ((restoreRec.usageE == pElement->usage) && (restoreRec.usagePageE == pElement->usagePage)) pFoundElement = pElement; if (pFoundElement) break; pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); } } } // if still not found just get first device if (NULL == pFoundDevice) { pFoundDevice = HIDGetFirstDevice (); // match elements by type if (pFoundDevice) { pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO); while (pElement) { if ((restoreRec.usageE == pElement->usage) && (restoreRec.usagePageE == pElement->usagePage)) pFoundElement = pElement; if (pFoundElement) break; pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); } } } if ((NULL == pFoundDevice) || (NULL == pFoundElement)) { // no HID device *ppDevice = NULL; *ppElement = NULL; return restoreRec.actionCookie; } else { // no HID device *ppDevice = pFoundDevice; *ppElement = pFoundElement; return restoreRec.actionCookie; } }
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 }
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; }