Пример #1
0
void HIDGamepad::initElementsFromArray(CFArrayRef elements)
{
    for (CFIndex i = 0, count = CFArrayGetCount(elements); i < count; ++i) {
        IOHIDElementRef element = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, i);
        if (CFGetTypeID(element) != IOHIDElementGetTypeID())
            continue;

        // As a physical element can appear in the device twice (in different collections) and can be
        // represented by different IOHIDElementRef objects, we look at the IOHIDElementCookie which
        // is meant to be unique for each physical element.
        IOHIDElementCookie cookie = IOHIDElementGetCookie(element);
        if (m_elementMap.contains(cookie))
            continue;

        IOHIDElementType type = IOHIDElementGetType(element);

        if ((type == kIOHIDElementTypeInput_Misc || type == kIOHIDElementTypeInput_Button) && maybeAddButton(element))
            continue;

        if ((type == kIOHIDElementTypeInput_Misc || type == kIOHIDElementTypeInput_Axis) && maybeAddAxis(element))
            continue;

        if (type == kIOHIDElementTypeCollection)
            initElementsFromArray(IOHIDElementGetChildren(element));
    }
}
Пример #2
0
//*************************************************************************
//
// HIDIsValidElement( inIOHIDElementRef )
//
// Purpose:	validate this element
//
// Inputs:	inIOHIDElementRef	- the element
//
// Returns:	Boolean			- TRUE if this is a valid element ref
//
Boolean HIDIsValidElement( IOHIDElementRef inIOHIDElementRef )
{
	Boolean result = FALSE;	// assume failure (pessimist!)
	if ( inIOHIDElementRef ) {
		if ( CFGetTypeID( inIOHIDElementRef ) == IOHIDElementGetTypeID() ) {
			result = TRUE;
		}
	}
	return result;
}
Пример #3
0
// *************************************************************************
//
// HIDIsValidElement(inIOHIDElementRef)
//
// Purpose:	validate this element
//
// Inputs:	inIOHIDElementRef	- the element
//
// Returns:	Boolean			- true if this is a valid element ref
//
Boolean HIDIsValidElement(IOHIDElementRef inIOHIDElementRef) {
	bool result = false; // assume failure (pessimist!)
	if (inIOHIDElementRef) {
		if (CFGetTypeID(inIOHIDElementRef) == IOHIDElementGetTypeID()) {
			result = true;
		}
	}
    
	return (result);
} // HIDIsValidElement
// ---------------------------------
// removes element for queue, if last element in queue will release queue and closes device interface
int  HIDDequeueElement( IOHIDDeviceRef inIOHIDDeviceRef, IOHIDElementRef inIOHIDElementRef )
{
	IOReturn result = kIOReturnSuccess;
	
	if ( inIOHIDDeviceRef ) {
		assert( IOHIDDeviceGetTypeID() == CFGetTypeID( inIOHIDDeviceRef ) );
		if ( inIOHIDElementRef ) {
			assert( IOHIDElementGetTypeID() == CFGetTypeID( inIOHIDElementRef ) );
			IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue( inIOHIDDeviceRef );
			if ( tIOHIDQueueRef ) {
				// stop queue
				IOHIDQueueStop( tIOHIDQueueRef );
				
				// de-queue element
				if ( IOHIDQueueContainsElement( tIOHIDQueueRef, inIOHIDElementRef ) ) {
					IOHIDQueueRemoveElement( tIOHIDQueueRef, inIOHIDElementRef );
				}
				
				// release device queue and close interface if queue empty
				if ( HIDIsDeviceQueueEmpty( inIOHIDDeviceRef ) ) {
					result = HIDDisposeReleaseQueue( inIOHIDDeviceRef );
					
					if ( kIOReturnSuccess != result ) {
						HIDReportErrorNum( "Failed to dispose and release queue.", result );
					}
				} else { // not empty so restart queue
					IOHIDQueueStart( tIOHIDQueueRef );
				}
			} else {
				HIDReportError( "No queue for device passed to HIDDequeueElement." );
				if ( kIOReturnSuccess == result ) {
					result = kIOReturnError;
				}
			}
		} else {
			HIDReportError( "NULL element passed to HIDDequeueElement." );
			result = kIOReturnBadArgument;
		}
	} else {
		HIDReportError( "NULL device passed to HIDDequeueElement." );
		result = kIOReturnBadArgument;
	}
	return result;
} /* HIDDequeueElement */
// queues specific element, performing any device queue set up required
// queue is started and ready to return events on exit from this function
int  HIDQueueElement( IOHIDDeviceRef inIOHIDDeviceRef, IOHIDElementRef inIOHIDElementRef )
{
	IOReturn result = kIOReturnSuccess;
	
	if ( inIOHIDDeviceRef ) {
		assert( IOHIDDeviceGetTypeID() == CFGetTypeID( inIOHIDDeviceRef ) );
		if ( inIOHIDElementRef ) {
			assert( IOHIDElementGetTypeID() == CFGetTypeID( inIOHIDElementRef ) );
			IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue( inIOHIDDeviceRef );
			if ( !tIOHIDQueueRef ) {         // if no queue create queue
				result = HIDCreateQueue( inIOHIDDeviceRef );
				if ( kIOReturnSuccess == result ) {
					tIOHIDQueueRef = IOHIDDevice_GetQueue( inIOHIDDeviceRef );
				}
			}
			if ( tIOHIDQueueRef ) {
				
				// stop queue
				IOHIDQueueStop( tIOHIDQueueRef );
				
				// queue element
				if ( !IOHIDQueueContainsElement( tIOHIDQueueRef, inIOHIDElementRef ) ) {
					IOHIDQueueAddElement( tIOHIDQueueRef, inIOHIDElementRef );
				}
				
				// restart queue
				IOHIDQueueStart( tIOHIDQueueRef );
			} else {
				HIDReportError( "No queue for device passed to HIDQueueElement." );
				if ( kIOReturnSuccess == result ) {
					result = kIOReturnError;
				}
			}
		} else {
			HIDReportError( "NULL element passed to HIDQueueElement." );
			result = kIOReturnBadArgument;
		}
	} else {
		HIDReportError( "NULL device passed to HIDQueueElement." );
		result = kIOReturnBadArgument;
	}
	return result;
} /* HIDQueueElement */
Пример #6
0
void joypad::add_hid_element(IOHIDElementRef p_element) {
	const CFTypeID elementTypeID = p_element ? CFGetTypeID(p_element) : 0;

	if (p_element && (elementTypeID == IOHIDElementGetTypeID())) {
		const IOHIDElementCookie cookie = IOHIDElementGetCookie(p_element);
		const uint32_t usagePage = IOHIDElementGetUsagePage(p_element);
		const uint32_t usage = IOHIDElementGetUsage(p_element);
		Vector<rec_element> *list = NULL;

		switch (IOHIDElementGetType(p_element)) {
			case kIOHIDElementTypeInput_Misc:
			case kIOHIDElementTypeInput_Button:
			case kIOHIDElementTypeInput_Axis: {
				switch (usagePage) {
					case kHIDPage_GenericDesktop:
						switch (usage) {
							case kHIDUsage_GD_X:
							case kHIDUsage_GD_Y:
							case kHIDUsage_GD_Z:
							case kHIDUsage_GD_Rx:
							case kHIDUsage_GD_Ry:
							case kHIDUsage_GD_Rz:
							case kHIDUsage_GD_Slider:
							case kHIDUsage_GD_Dial:
							case kHIDUsage_GD_Wheel:
								if (!has_element(cookie, &axis_elements)) {
									list = &axis_elements;
								}
								break;

							case kHIDUsage_GD_Hatswitch:
								if (!has_element(cookie, &hat_elements)) {
									list = &hat_elements;
								}
								break;
							case kHIDUsage_GD_DPadUp:
							case kHIDUsage_GD_DPadDown:
							case kHIDUsage_GD_DPadRight:
							case kHIDUsage_GD_DPadLeft:
							case kHIDUsage_GD_Start:
							case kHIDUsage_GD_Select:
								if (!has_element(cookie, &button_elements)) {
									list = &button_elements;
								}
								break;
						}
						break;

					case kHIDPage_Simulation:
						switch (usage) {
							case kHIDUsage_Sim_Rudder:
							case kHIDUsage_Sim_Throttle:
								if (!has_element(cookie, &axis_elements)) {
									list = &axis_elements;
								}
								break;

							default:
								break;
						}
						break;

					case kHIDPage_Button:
					case kHIDPage_Consumer:
						if (!has_element(cookie, &button_elements)) {
							list = &button_elements;
						}
						break;

					default:
						break;
				}
			} break;

			case kIOHIDElementTypeCollection: {
				CFArrayRef array = IOHIDElementGetChildren(p_element);
				if (array) {
					add_hid_elements(array);
				}
			} break;

			default:
				break;
		}

		if (list) { /* add to list */
			rec_element element;

			element.ref = p_element;
			element.usage = usage;

			element.min = (SInt32)IOHIDElementGetLogicalMin(p_element);
			element.max = (SInt32)IOHIDElementGetLogicalMax(p_element);
			element.cookie = IOHIDElementGetCookie(p_element);
			list->push_back(element);
			list->sort_custom<rec_element::Comparator>();
		}
	}
}
Пример #7
0
/* See if we care about this HID element, and if so, note it in our recDevice. */
static void
AddHIDElement(const void *value, void *parameter)
{
    recDevice *pDevice = (recDevice *) parameter;
    IOHIDElementRef refElement = (IOHIDElementRef) value;
    const CFTypeID elementTypeID = refElement ? CFGetTypeID(refElement) : 0;

    if (refElement && (elementTypeID == IOHIDElementGetTypeID())) {
        const IOHIDElementCookie cookie = IOHIDElementGetCookie(refElement);
        const uint32_t usagePage = IOHIDElementGetUsagePage(refElement);
        const uint32_t usage = IOHIDElementGetUsage(refElement);
        recElement *element = NULL;
        recElement **headElement = NULL;

        /* look at types of interest */
        switch (IOHIDElementGetType(refElement)) {
            case kIOHIDElementTypeInput_Misc:
            case kIOHIDElementTypeInput_Button:
            case kIOHIDElementTypeInput_Axis: {
                switch (usagePage) {    /* only interested in kHIDPage_GenericDesktop and kHIDPage_Button */
                    case kHIDPage_GenericDesktop:
                        switch (usage) {
                            case kHIDUsage_GD_X:
                            case kHIDUsage_GD_Y:
                            case kHIDUsage_GD_Z:
                            case kHIDUsage_GD_Rx:
                            case kHIDUsage_GD_Ry:
                            case kHIDUsage_GD_Rz:
                            case kHIDUsage_GD_Slider:
                            case kHIDUsage_GD_Dial:
                            case kHIDUsage_GD_Wheel:
                                if (!ElementAlreadyAdded(cookie, pDevice->firstAxis)) {
                                    element = (recElement *) SDL_calloc(1, sizeof (recElement));
                                    if (element) {
                                        pDevice->axes++;
                                        headElement = &(pDevice->firstAxis);
                                    }
                                }
                                break;

                            case kHIDUsage_GD_Hatswitch:
                                if (!ElementAlreadyAdded(cookie, pDevice->firstHat)) {
                                    element = (recElement *) SDL_calloc(1, sizeof (recElement));
                                    if (element) {
                                        pDevice->hats++;
                                        headElement = &(pDevice->firstHat);
                                    }
                                }
                                break;
                        }
                        break;

                    case kHIDPage_Simulation:
                        switch (usage) {
                            case kHIDUsage_Sim_Rudder:
                            case kHIDUsage_Sim_Throttle:
                                if (!ElementAlreadyAdded(cookie, pDevice->firstAxis)) {
                                    element = (recElement *) SDL_calloc(1, sizeof (recElement));
                                    if (element) {
                                        pDevice->axes++;
                                        headElement = &(pDevice->firstAxis);
                                    }
                                }
                                break;

                            default:
                                break;
                        }
                        break;

                    case kHIDPage_Button:
                        if (!ElementAlreadyAdded(cookie, pDevice->firstButton)) {
                            element = (recElement *) SDL_calloc(1, sizeof (recElement));
                            if (element) {
                                pDevice->buttons++;
                                headElement = &(pDevice->firstButton);
                            }
                        }
                        break;

                    default:
                        break;
                }
            }
            break;

            case kIOHIDElementTypeCollection: {
                CFArrayRef array = IOHIDElementGetChildren(refElement);
                if (array) {
                    AddHIDElements(array, pDevice);
                }
            }
            break;

            default:
                break;
        }

        if (element && headElement) {       /* add to list */
            recElement *elementPrevious = NULL;
            recElement *elementCurrent = *headElement;
            while (elementCurrent && usage >= elementCurrent->usage) {
                elementPrevious = elementCurrent;
                elementCurrent = elementCurrent->pNext;
            }
            if (elementPrevious) {
                elementPrevious->pNext = element;
            } else {
                *headElement = element;
            }

            element->elementRef = refElement;
            element->usagePage = usagePage;
            element->usage = usage;
            element->pNext = elementCurrent;

            element->minReport = element->min = (SInt32) IOHIDElementGetLogicalMin(refElement);
            element->maxReport = element->max = (SInt32) IOHIDElementGetLogicalMax(refElement);
            element->cookie = IOHIDElementGetCookie(refElement);

            pDevice->elements++;
        }
    }
}
Пример #8
0
// get next element of given device in list given current element as parameter
// will walk down each collection then to next element or collection (depthwise traverse)
// returns NULL if end of list
// uses mask of HIDElementTypeMask to restrict element found
// use kHIDElementTypeIO to get previous HIDGetNextDeviceElement functionality
IOHIDElementRef HIDGetNextDeviceElement( IOHIDElementRef inIOHIDElementRef, HIDElementTypeMask typeMask )
{
	IOHIDElementRef result = NULL;

	if ( inIOHIDElementRef ) {
		assert( IOHIDElementGetTypeID() == CFGetTypeID( inIOHIDElementRef ) );

		IOHIDDeviceRef tIOHIDDeviceRef = IOHIDElementGetDevice( inIOHIDElementRef );

		if ( tIOHIDDeviceRef ) {
			Boolean found = FALSE;

			gElementCFArrayRef = IOHIDDeviceCopyMatchingElements( tIOHIDDeviceRef, NULL, kIOHIDOptionsTypeNone );

			if ( gElementCFArrayRef ) {
				CFIndex idx, cnt = CFArrayGetCount( gElementCFArrayRef );
				for ( idx = 0; idx < cnt; idx++ ) {
					IOHIDElementRef tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( gElementCFArrayRef, idx );

					if ( !tIOHIDElementRef ) {
						continue;
					}

					if ( !found ) {
						if ( inIOHIDElementRef == tIOHIDElementRef ) {
							found = TRUE;
						}
						continue;   // next element
					} else {
						// we've found the current element; now find the next one of the right type
						IOHIDElementType type = IOHIDElementGetType( tIOHIDElementRef );
						switch ( type ) {
							case kIOHIDElementTypeInput_Misc:
							case kIOHIDElementTypeInput_Button:
							case kIOHIDElementTypeInput_Axis:
							case kIOHIDElementTypeInput_ScanCodes:
							{
								if ( typeMask & kHIDElementTypeInput ) {
									result = tIOHIDElementRef;
								}
								break;
							}

							case kIOHIDElementTypeOutput:
							{
								if ( typeMask & kHIDElementTypeOutput ) {
									result = tIOHIDElementRef;
								}
								break;
							}

							case kIOHIDElementTypeFeature:
							{
								if ( typeMask & kHIDElementTypeFeature ) {
									result = tIOHIDElementRef;
								}
								break;
							}

							case kIOHIDElementTypeCollection:
							{
								if ( typeMask & kHIDElementTypeCollection ) {
									result = tIOHIDElementRef;
								}
								break;
							}
						}           // switch ( type )

						if ( result ) {
							break;  // DONE!
						}
					}               // if ( !found )
				}                   // next idx
				CFRelease( gElementCFArrayRef );
				gElementCFArrayRef = NULL;
			}                       // 		if ( gElementCFArrayRef )
		}                           // 	if ( inIOHIDDeviceRef )
	}                               // 	if ( inIOHIDElementRef )
	return result;
} /* HIDGetNextDeviceElement */