Beispiel #1
0
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;
}
Beispiel #2
0
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;

}
Beispiel #3
0
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;

}
Beispiel #4
0
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);
	}
}
Beispiel #5
0
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;

}
// adds all elements to queue, performing any device queue set up required
// queue is started and ready to return events on exit from this function
int  HIDQueueDevice( IOHIDDeviceRef inIOHIDDeviceRef )
{
	IOReturn result = kIOReturnSuccess;
	
	// error checking
	if ( !inIOHIDDeviceRef ) {
		HIDReportError( "Device does not exist, cannot queue device." );
		return kIOReturnBadArgument;
	}
	
	if ( !inIOHIDDeviceRef ) { // must have interface
		HIDReportError( "Device does not have hid device ref, cannot queue device." );
		return kIOReturnError;
	}
	
	IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue( inIOHIDDeviceRef );
	if ( !tIOHIDQueueRef ) {         // if no queue create queue
		result = HIDCreateQueue( inIOHIDDeviceRef );
		if ( kIOReturnSuccess == result ) {
			tIOHIDQueueRef = IOHIDDevice_GetQueue( inIOHIDDeviceRef );
		}
	}
	
	if ( ( kIOReturnSuccess != result ) || ( !tIOHIDQueueRef ) ) {
		HIDReportErrorNum( "Could not queue device due to problem creating queue.", result );
		
		if ( kIOReturnSuccess != result ) {
			return result;
		} else {
			return kIOReturnError;
		}
	}
	
	// stop queue
	IOHIDQueueStop( tIOHIDQueueRef );
	
	// queue element
	IOHIDElementRef tIOHIDElementRef = HIDGetFirstDeviceElement( inIOHIDDeviceRef, kHIDElementTypeIO );
	while ( tIOHIDElementRef ) {
		if ( !IOHIDQueueContainsElement( tIOHIDQueueRef, tIOHIDElementRef ) ) {
			IOHIDQueueAddElement( tIOHIDQueueRef, tIOHIDElementRef );
		}
		tIOHIDElementRef = HIDGetNextDeviceElement( tIOHIDElementRef, kHIDElementTypeIO );
	}
	
	// restart queue
	IOHIDQueueStart( tIOHIDQueueRef );
	
	return result;
} /* HIDQueueDevice */
pRecElement PsychHIDGetCollectionRecordFromDeviceRecordAndCollectionIndex(pRecDevice deviceRecord, int elementIndex)
{
    int				i;
    pRecElement			currentElement;

    PsychHIDVerifyInit();
    i=1;
    for(currentElement=HIDGetFirstDeviceElement(deviceRecord, kHIDElementTypeCollection); 
        currentElement != NULL; 
        currentElement=HIDGetNextDeviceElement (currentElement, kHIDElementTypeCollection))
    {    
        if(i==elementIndex)
            return(currentElement);
        ++i;
    }
    PsychErrorExitMsg(PsychError_internal, "Invalid collection index specified.  Has a device has been unplugged? Try rebuilding the device list");
    return(NULL);  //make the compiler happy.

}
/*
    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
    }
}
// ---------------------------------
// completely removes all elements from queue and releases queue and closes device interface
// does not release device interfaces, application must call ReleaseHIDDeviceList on exit
int  HIDDequeueDevice( IOHIDDeviceRef inIOHIDDeviceRef )
{
	
	IOReturn result = kIOReturnSuccess;
	
	// error checking
	if ( !inIOHIDDeviceRef ) {
		HIDReportError( "Device does not exist, cannot queue device." );
		return kIOReturnBadArgument;
	}
	
	if ( !inIOHIDDeviceRef ) { // must have interface
		HIDReportError( "Device does not have hid device ref, cannot queue device." );
		return kIOReturnError;
	}
	
	IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue( inIOHIDDeviceRef );
	
	if ( tIOHIDQueueRef ) {
		// iterate through elements and if queued, remove
		IOHIDElementRef tIOHIDElementRef = HIDGetFirstDeviceElement( inIOHIDDeviceRef, kHIDElementTypeIO );
		while ( tIOHIDElementRef ) {
			// de-queue element
			if ( IOHIDQueueContainsElement( tIOHIDQueueRef, tIOHIDElementRef ) ) {
				IOHIDQueueRemoveElement( tIOHIDQueueRef, tIOHIDElementRef );
			}
			tIOHIDElementRef = HIDGetNextDeviceElement( tIOHIDElementRef, kHIDElementTypeIO );
		}
		// ensure queue is disposed and released
		result = HIDDisposeReleaseQueue( inIOHIDDeviceRef );
		
		if ( kIOReturnSuccess != result ) {
			HIDReportErrorNum( "Failed to dispose and release queue.", result );
		}
	} else {
		HIDReportError( "No queue for device passed to HIDDequeueElement." );
		if ( kIOReturnSuccess == result ) {
			result = kIOReturnError;
		}
	}
	return result;
} /* HIDDequeueDevice */
// ---------------------------------
// returns true if queue is empty false otherwise
// error if no device, empty if no queue
static unsigned char HIDIsDeviceQueueEmpty( IOHIDDeviceRef inIOHIDDeviceRef )
{
	if ( inIOHIDDeviceRef ) { // need device and queue
		assert( IOHIDDeviceGetTypeID() == CFGetTypeID( inIOHIDDeviceRef ) );
		IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue( inIOHIDDeviceRef );
		if ( tIOHIDQueueRef ) {
			IOHIDElementRef tIOHIDElementRef = HIDGetFirstDeviceElement( inIOHIDDeviceRef, kHIDElementTypeIO );
			while ( tIOHIDElementRef ) {
				if ( IOHIDQueueContainsElement( tIOHIDQueueRef, tIOHIDElementRef ) ) {
					return false;
				}
				tIOHIDElementRef = HIDGetNextDeviceElement( tIOHIDElementRef, kHIDElementTypeIO );
			}
		} else {
			HIDReportError( "NULL device passed to HIDIsDeviceQueueEmpty." );
		}
	} else {
		HIDReportError( "NULL device passed to HIDIsDeviceQueueEmpty." );
	}
	return true;
} /* HIDIsDeviceQueueEmpty */
PsychError PsychHIDOSKbQueueCreate(int deviceIndex, int numScankeys, int* scanKeys)
{
    pRecDevice deviceRecord;

	// Valid number of keys?
	if (scanKeys && (numScankeys != 256)) {
		PsychErrorExitMsg(PsychError_user, "Second argument to KbQueueCreate must be a vector with 256 elements.");
	}

    // Do we finally have a valid keyboard or other suitable input device?
    // PsychHIDOSGetKbQueueDevice() will error out if no suitable device
    // for deviceIndex can be found. Otherwise it will return the HID
    // device record and remapped deviceIndex for use with our KbQueues:
    deviceIndex = PsychHIDOSGetKbQueueDevice(deviceIndex, &deviceRecord);

	// Keyboard queue for this deviceIndex already created?
	if (psychHIDKbQueueFirstPress[deviceIndex]) {
		// Yep. Release it, so we can start from scratch:
		PsychHIDOSKbQueueRelease(deviceIndex);
	}

	// Allocate and zero-init memory for tracking key presses and key releases:
	psychHIDKbQueueFirstPress[deviceIndex]   = calloc(256, sizeof(double));
	psychHIDKbQueueFirstRelease[deviceIndex] = calloc(256, sizeof(double));
	psychHIDKbQueueLastPress[deviceIndex]    = calloc(256, sizeof(double));
	psychHIDKbQueueLastRelease[deviceIndex]  = calloc(256, sizeof(double));
	psychHIDKbQueueScanKeys[deviceIndex]     = calloc(256, sizeof(int));
    
	// Assign scanKeys vector, if any:
	if (scanKeys) {
		// Copy it:
		memcpy(psychHIDKbQueueScanKeys[deviceIndex], scanKeys, 256 * sizeof(int));
	} else {
		// None provided. Enable all keys by default:
		memset(psychHIDKbQueueScanKeys[deviceIndex], 1, 256 * sizeof(int));        
	}
    
    // Create HIDQueue for device:
    queue[deviceIndex] = IOHIDQueueCreate(kCFAllocatorDefault, deviceRecord, 30, 0);
    if (NULL == queue[deviceIndex]) PsychErrorExitMsg(PsychError_system, "Failed to create event queue for detecting key press.");

    // Mark as a non-keyboard device, to start with:
    queueIsAKeyboard[deviceIndex] = FALSE;

    // Parse HID device to add all detected and selected keys:
    {
        // Add deviceRecord's elements to our queue, filtering unwanted keys via 'scanList'.
        // This code is almost identical to the enumeration code in PsychHIDKbCheck, to make sure we get
        // matching performance and behaviour and hopefully that it works on the latest problematic Apple
        // hardware, e.g., late 2013 MacBookAir and OSX 10.9:
        {
            uint32_t usage, usagePage;
            pRecElement currentElement, lastElement = NULL;
            
            // Step through the elements of the device and add matching ones:
            for (currentElement = HIDGetFirstDeviceElement(deviceRecord, kHIDElementTypeInput | kHIDElementTypeCollection);
                 (currentElement != NULL) && (currentElement != lastElement);
                 currentElement = HIDGetNextDeviceElement(currentElement, kHIDElementTypeInput | kHIDElementTypeCollection))
            {
                // Keep track of last queried element:
                lastElement = currentElement;
                
                usage     = IOHIDElementGetUsage(currentElement);
                usagePage = IOHIDElementGetUsagePage(currentElement);
                if (getenv("PSYCHHID_TELLME")) {
                    printf("PTB-DEBUG: [KbQueueCreate]: 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) && ( (scanKeys == NULL) || (scanKeys[usage - 1] > 0) )) {
                                // Add it for use in keyboard queue:
                                PsychHIDOSKbElementAdd(tIOHIDElementRef, queue[deviceIndex], deviceIndex);
                            }
                        }
                    }
                    
                    // Done with this currentElement, which was a collection of buttons/keys.
                    // Iterate to next currentElement:
                    continue;
                }
                
                // Classic path for non-collection elements:
                if(((usagePage == kHIDPage_KeyboardOrKeypad) || (usagePage == kHIDPage_Button)) && (usage <= 256) && (usage >= 1) &&
                   ( (scanKeys == NULL) || (scanKeys[usage - 1] > 0) ) ) {
                    // Add it for use in keyboard queue:
                    PsychHIDOSKbElementAdd(currentElement, queue[deviceIndex], deviceIndex);
                }
            }
        }
    }
    
    // Register "queue empty -> non-empty transition" callback: TODO Replace queue by reference to our keyboard queue struct:
    IOHIDQueueRegisterValueAvailableCallback(queue[deviceIndex], (IOHIDCallback) PsychHIDKbQueueCallbackFunction, (void*) (long) deviceIndex);

	// Create event buffer:
	PsychHIDCreateEventBuffer(deviceIndex);

    // Start the processing thread for this queue:
    PsychLockMutex(&KbQueueMutex);

    if (PsychCreateThread(&KbQueueThread[deviceIndex], NULL, KbQueueWorkerThreadMain, (void*) (long) deviceIndex)) {
        // We are so screwed:

        // Cleanup the mess:
        psychHIDKbQueueActive[deviceIndex] = FALSE;
        PsychUnlockMutex(&KbQueueMutex);

        // Whine a little bit:
        printf("PsychHID-ERROR: Start of keyboard queue processing for deviceIndex %i failed!\n", deviceIndex);
        PsychErrorExitMsg(PsychError_system, "Creation of keyboard queue background processing thread failed!");
    }

    PsychUnlockMutex(&KbQueueMutex);

	// Ready to use this keybord queue.
	return(PsychError_none);
}
/*
    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;
    }
  
}
Beispiel #14
0
static Boolean GetInputElements (pRecDevice pDevice)
{
	short i;
	pRecElement pElement = NULL;
   
	if (pDevice) { // if we have found a device set up elements
		// prefer correct elements, then try any
		// look for x axis	
		pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO); // get first element
		while (pElement) { // for each element
			if ((kHIDPage_GenericDesktop == pElement->usagePage) && (kHIDUsage_GD_X == pElement->usage)) { // if it is the x axis
				gActionArray [kActionXAxis].pDevice = pDevice;
				gActionArray [kActionXAxis].pElement = pElement;
				break;
			}
			pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); // get next element
		}
		// look for y axis
		pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO); // get first element
		while (pElement) { // for each element
			if ((kHIDPage_GenericDesktop == pElement->usagePage) && (kHIDUsage_GD_Y == pElement->usage)) { // if it is the y axis
				gActionArray [kActionYAxis].pDevice = pDevice;
				gActionArray [kActionYAxis].pElement = pElement;
				break;
			}
			pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); // get next element
		}
//		// look for z axis
//		pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO); // get first element
//		while (pElement) { // for each element
//			if ((kHIDPage_GenericDesktop == pElement->usagePage) && (kHIDUsage_GD_Z == pElement->usage)) { // if it is the y axis
//				gActionArray [kActionZAxis].pDevice = pDevice;
//				gActionArray [kActionZAxis].pElement = pElement;
//				break;
//			}
//			pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); // get next element
//		}
//		// look for x rotation
//		pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO); // get first element
//		while (pElement) { // for each element
//			if ((kHIDPage_GenericDesktop == pElement->usagePage) && (kHIDUsage_GD_Rx == pElement->usage)) { // if it is the x axis
//				gActionArray [kActionXRot].pDevice = pDevice;
//				gActionArray [kActionXRot].pElement = pElement;
//				break;
//			}
//			pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); // get next element
//		}
//		// look for y rotation
//		pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO); // get first element
//		while (pElement) { // for each element
//			if ((kHIDPage_GenericDesktop == pElement->usagePage) && (kHIDUsage_GD_Ry == pElement->usage)) { // if it is the y axis
//				gActionArray [kActionYRot].pDevice = pDevice;
//				gActionArray [kActionYRot].pElement = pElement;
//				break;
//			}
//			pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); // get next element
//		}
//		// look for z rotation
//		pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO); // get first element
//		while (pElement) { // for each element
//			if ((kHIDPage_GenericDesktop == pElement->usagePage) && (kHIDUsage_GD_Rz == pElement->usage)) { // if it is the y axis
//				gActionArray [kActionZRot].pDevice = pDevice;
//				gActionArray [kActionZRot].pElement = pElement;
//				break;
//			}
//			pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO); // get next element
//		}
	}
	// set device limits
	for (i = 0; i < kNumActions; i++)
	{
#if 0
		if (!gActionArray [i].pElement) { // check to ensure we have valid elements
			InitHIDInputArray ();
			return false;
		}
#endif
		if (gActionArray[i].pElement) {
			(gActionArray[i].pElement)->userMin = -100;
			(gActionArray[i].pElement)->userMax = 100;
		}
	}
	return true;
}
Beispiel #15
0
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
}
PsychError PSYCHHIDGetElements(void) 
{
    pRecDevice 			specDevice=NULL;
    UInt32                      numDeviceElements;
    
    const char 			*elementFieldNames[]={"typeMaskName", "name", "deviceIndex", "elementIndex", "typeValue", "typeName", "usagePageValue", "usageValue", 							"usageName", "dataSize", "rangeMin", "rangeMax", "scaledRangeMin", "scaledRangeMax", "relative", 
                                                        "wrapping", "nonLinear", "preferredState", "nullState", "calMin", "calMax", "scalingMin", "scalingMax"};
    int 			numElementStructElements, numElementStructFieldNames=23, elementIndex, deviceIndex;
    PsychGenericScriptType	*elementStruct;	
    pRecElement			currentElement;
    char			elementTypeName[PSYCH_HID_MAX_DEVICE_ELEMENT_TYPE_NAME_LENGTH];	
    char			usageName[PSYCH_HID_MAX_DEVICE_ELEMENT_USAGE_NAME_LENGTH];
    char			*typeMaskName;
    HIDElementTypeMask		typeMask;
    	 
    //all subfunctions should have these two lines
    PsychPushHelp(useString, synopsisString, seeAlsoString);
    if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};

    PsychErrorExit(PsychCapNumOutputArgs(1));
    PsychErrorExit(PsychCapNumInputArgs(1));
    
    PsychCopyInIntegerArg(1, TRUE, &deviceIndex);
    PsychHIDVerifyInit();
    specDevice= PsychHIDGetDeviceRecordPtrFromIndex(deviceIndex);
    PsychHIDVerifyOpenDeviceInterfaceFromDeviceRecordPtr(specDevice);
    numDeviceElements= HIDCountDeviceElements(specDevice, kHIDElementTypeIO);
    numElementStructElements = (int)numDeviceElements;
    PsychAllocOutStructArray(1, FALSE, numElementStructElements, numElementStructFieldNames, elementFieldNames, &elementStruct);
    elementIndex=0;
    for(currentElement=HIDGetFirstDeviceElement(specDevice,kHIDElementTypeIO); 
        currentElement != NULL; 
        currentElement=HIDGetNextDeviceElement(currentElement, kHIDElementTypeIO))
        {
        typeMask=HIDConvertElementTypeToMask (currentElement->type);
 	PsychHIDGetTypeMaskStringFromTypeMask(typeMask, &typeMaskName);
        PsychSetStructArrayStringElement("typeMaskName",	elementIndex, 	typeMaskName,	 			elementStruct);
        PsychSetStructArrayStringElement("name",		elementIndex, 	currentElement->name,	 		elementStruct);
        PsychSetStructArrayDoubleElement("deviceIndex",		elementIndex, 	(double)deviceIndex, 			elementStruct);
        PsychSetStructArrayDoubleElement("elementIndex",	elementIndex, 	(double)elementIndex+1, 		elementStruct);
        PsychSetStructArrayDoubleElement("typeValue",		elementIndex, 	(double)currentElement->type, 		elementStruct);
        HIDGetTypeName(currentElement->type, elementTypeName);
        PsychSetStructArrayStringElement("typeName",		elementIndex, 	elementTypeName,	 		elementStruct);
        PsychSetStructArrayDoubleElement("usagePageValue",	elementIndex, 	(double)currentElement->usagePage, 	elementStruct);
        PsychSetStructArrayDoubleElement("usageValue",		elementIndex, 	(double)currentElement->usage, 		elementStruct);
        HIDGetUsageName (currentElement->usagePage, currentElement->usage, usageName);
        PsychSetStructArrayStringElement("usageName",		elementIndex, 	usageName,	 			elementStruct);
        PsychSetStructArrayDoubleElement("dataSize",		elementIndex, 	(double)currentElement->size, 		elementStruct);
        PsychSetStructArrayDoubleElement("rangeMin",		elementIndex, 	(double)currentElement->min, 		elementStruct);
        PsychSetStructArrayDoubleElement("rangeMax",		elementIndex, 	(double)currentElement->max, 		elementStruct);
        PsychSetStructArrayDoubleElement("scaledRangeMin",	elementIndex, 	(double)currentElement->scaledMin, 	elementStruct);
        PsychSetStructArrayDoubleElement("scaledRangeMax",	elementIndex, 	(double)currentElement->scaledMax,	elementStruct);
        PsychSetStructArrayDoubleElement("relative",		elementIndex, 	(double)currentElement->relative,	elementStruct);	//psych_bool flag
        PsychSetStructArrayDoubleElement("wrapping",		elementIndex, 	(double)currentElement->wrapping,	elementStruct);	//psych_bool flag	
        PsychSetStructArrayDoubleElement("nonLinear",		elementIndex, 	(double)currentElement->nonLinear,	elementStruct);	//psych_bool flag
        PsychSetStructArrayDoubleElement("preferredState",	elementIndex, 	(double)currentElement->preferredState,	elementStruct);	//psych_bool flag
        PsychSetStructArrayDoubleElement("nullState",		elementIndex, 	(double)currentElement->nullState,	elementStruct);	//psych_bool flag

        PsychSetStructArrayDoubleElement("calMin",		elementIndex, 	(double)currentElement->calMin,		elementStruct);	
        PsychSetStructArrayDoubleElement("calMax",		elementIndex, 	(double)currentElement->calMax,		elementStruct);	
        PsychSetStructArrayDoubleElement("scalingMin",		elementIndex, 	(double)currentElement->userMin,	elementStruct);	
        PsychSetStructArrayDoubleElement("scalingMax",		elementIndex, 	(double)currentElement->userMax,	elementStruct);	
                                
        ++elementIndex; 
    }

    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);	
}
Beispiel #18
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;
    }
}
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);	
}
Beispiel #20
0
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;
	}
}
PsychError PSYCHHIDGetCollections(void) 
{
    pRecDevice 			specDevice=NULL;
    UInt32                      numDeviceElements;
    
    const char 			*elementFieldNames[]={"typeMaskName", "name", "deviceIndex", "collectionIndex", "typeValue", "typeName", "usagePageValue",
                                                        "usageValue", "usageName", "memberCollectionIndices", "memberElementIndices"};
    int 			i, numElementStructElements, numElementStructFieldNames=11, elementIndex, deviceIndex;
    PsychGenericScriptType	*elementStruct, *memberCollectionIndicesMat, *memberIOElementIndicesMat;	
    pRecElement			currentElement;
    char			elementTypeName[PSYCH_HID_MAX_DEVICE_ELEMENT_TYPE_NAME_LENGTH];	
    char			usageName[PSYCH_HID_MAX_DEVICE_ELEMENT_USAGE_NAME_LENGTH];
    char			*typeMaskName;
    HIDElementTypeMask		typeMask;
    pRecElement			*memberCollectionRecords, *memberIOElementRecords;     
    double			*memberCollectionIndices, *memberIOElementIndices; 
    int				numSubCollections, numSubIOElements;
    
    	 
    PsychPushHelp(useString, synopsisString, seeAlsoString);
    if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};

    PsychErrorExit(PsychCapNumOutputArgs(1));
    PsychErrorExit(PsychCapNumInputArgs(1));
        
    PsychCopyInIntegerArg(1, TRUE, &deviceIndex);
    PsychHIDVerifyInit();
    specDevice= PsychHIDGetDeviceRecordPtrFromIndex(deviceIndex);
    PsychHIDVerifyOpenDeviceInterfaceFromDeviceRecordPtr(specDevice);
    numDeviceElements= HIDCountDeviceElements(specDevice, kHIDElementTypeCollection);
    numElementStructElements = (int)numDeviceElements;
    PsychAllocOutStructArray(1, FALSE, numElementStructElements, numElementStructFieldNames, elementFieldNames, &elementStruct);
    elementIndex=0;
    for(currentElement=HIDGetFirstDeviceElement(specDevice,kHIDElementTypeCollection); 
        currentElement != NULL; 
        currentElement=HIDGetNextDeviceElement(currentElement, kHIDElementTypeCollection))
        {
        typeMask=HIDConvertElementTypeToMask (currentElement->type);
 	PsychHIDGetTypeMaskStringFromTypeMask(typeMask, &typeMaskName);
        PsychSetStructArrayStringElement("typeMaskName",	elementIndex, 	typeMaskName,	 			elementStruct);
        PsychSetStructArrayStringElement("name",		elementIndex, 	currentElement->name,	 		elementStruct);
        PsychSetStructArrayDoubleElement("deviceIndex",		elementIndex, 	(double)deviceIndex, 			elementStruct);
        PsychSetStructArrayDoubleElement("collectionIndex",	elementIndex, 	(double)elementIndex+1, 		elementStruct);
        PsychSetStructArrayDoubleElement("typeValue",		elementIndex, 	(double)currentElement->type, 		elementStruct);
        HIDGetTypeName(currentElement->type, elementTypeName);
        PsychSetStructArrayStringElement("typeName",		elementIndex, 	elementTypeName,	 		elementStruct);
        PsychSetStructArrayDoubleElement("usagePageValue",	elementIndex, 	(double)currentElement->usagePage, 	elementStruct);
        PsychSetStructArrayDoubleElement("usageValue",		elementIndex, 	(double)currentElement->usage, 		elementStruct);
        HIDGetUsageName (currentElement->usagePage, currentElement->usage, usageName);
        PsychSetStructArrayStringElement("usageName",		elementIndex, 	usageName,	 			elementStruct);
                          
        //find and return the indices of this collection's member collections and indices
        numSubCollections=PsychHIDCountCollectionElements(currentElement, kHIDElementTypeCollection);
        numSubIOElements=PsychHIDCountCollectionElements(currentElement, kHIDElementTypeIO);
        memberCollectionRecords=(pRecElement*)PsychMallocTemp(sizeof(pRecElement) * numSubCollections);
        memberIOElementRecords=(pRecElement*)PsychMallocTemp(sizeof(pRecElement) * numSubIOElements);
        PsychHIDFindCollectionElements(currentElement, kHIDElementTypeCollection, memberCollectionRecords, numSubCollections);
        PsychHIDFindCollectionElements(currentElement, kHIDElementTypeIO, memberIOElementRecords, numSubIOElements);
        memberCollectionIndices=NULL;
        PsychAllocateNativeDoubleMat(1, numSubCollections, 1, &memberCollectionIndices, &memberCollectionIndicesMat);
        memberIOElementIndices=NULL;
        PsychAllocateNativeDoubleMat(1, numSubIOElements, 1, &memberIOElementIndices, &memberIOElementIndicesMat);
        
        for(i=0;i<numSubCollections;i++)
            memberCollectionIndices[i]=PsychHIDGetIndexFromRecord(specDevice, memberCollectionRecords[i], kHIDElementTypeCollection);
        for(i=0;i<numSubIOElements;i++)
            memberIOElementIndices[i]=PsychHIDGetIndexFromRecord(specDevice, memberIOElementRecords[i], kHIDElementTypeIO);
        PsychFreeTemp(memberCollectionRecords);
        PsychFreeTemp(memberIOElementRecords);
        PsychSetStructArrayNativeElement("memberCollectionIndices", 	elementIndex,	memberCollectionIndicesMat,	elementStruct);
        PsychSetStructArrayNativeElement("memberElementIndices", 	elementIndex,	memberIOElementIndicesMat,	elementStruct);

        ++elementIndex; 
    }

    return(PsychError_none);	
}