Example #1
0
void HIDGamepad::getCurrentValueForElement(const HIDGamepadElement& gamepadElement)
{
    IOHIDElementRef element = gamepadElement.iohidElement.get();
    IOHIDValueRef value;
    if (IOHIDDeviceGetValue(IOHIDElementGetDevice(element), element, &value) == kIOReturnSuccess)
        valueChanged(value);
}
Example #2
0
// *************************************************************************
//
// IOHIDElement_GetValue(inIOHIDElementRef, inIOHIDValueScaleType)
//
// Purpose:	returns the current value for an element(polling)
//
// Notes:	will return 0 on error conditions which should be accounted for by application
//
// Inputs:	inIOHIDElementRef		- the element
// 			inIOHIDValueScaleType	- scale type (calibrated or physical)
//
// Returns:	double		- current value for element
//
double IOHIDElement_GetValue(IOHIDElementRef inIOHIDElementRef, IOHIDValueScaleType inIOHIDValueScaleType) {
	double result = NAN;
	IOHIDValueRef tIOHIDValueRef;
	if (kIOReturnSuccess == IOHIDDeviceGetValue(IOHIDElementGetDevice(inIOHIDElementRef), inIOHIDElementRef, &tIOHIDValueRef)) {
		result = IOHIDValueGetScaledValue(tIOHIDValueRef, inIOHIDValueScaleType);
	}
    
	return (result);
}   // IOHIDElement_GetValue
Example #3
0
void HIDGamepadProvider::valuesChanged(IOHIDValueRef value)
{
    IOHIDDeviceRef device = IOHIDElementGetDevice(IOHIDValueGetElement(value));

    HIDGamepad* gamepad = m_gamepadMap.get(device);

    // When starting monitoring we might get a value changed callback before we even know the device is connected.
    if (!gamepad)
        return;

    gamepad->valueChanged(value);

    // This isActive check is necessary as we want to delay input notifications from the time of the first input,
    // and not push the notification out on every subsequent input.
    if (!m_inputNotificationTimer.isActive())
        m_inputNotificationTimer.startOneShot(InputNotificationDelay);
}
Example #4
0
static int get_osx_device_name(int id, char *name, int length)
{
    CFStringRef str;
    IOHIDElementRef tIOHIDElementRef;
    IOHIDDeviceRef tIOHIDDeviceRef;

    if (!gCollections)
        return 0;

    tIOHIDElementRef = (IOHIDElementRef)CFArrayGetValueAtIndex(gCollections, id);

    if (!tIOHIDElementRef)
    {
        ERR("Invalid Element requested %i\n",id);
        return 0;
    }

    tIOHIDDeviceRef = IOHIDElementGetDevice(tIOHIDElementRef);

    if (name)
        name[0] = 0;

    if (!tIOHIDDeviceRef)
    {
        ERR("Invalid Device requested %i\n",id);
        return 0;
    }

    str = IOHIDDeviceGetProperty(tIOHIDDeviceRef, CFSTR( kIOHIDProductKey ));
    if (str)
    {
        CFIndex len = CFStringGetLength(str);
        if (length >= len)
        {
            CFStringGetCString(str,name,length,kCFStringEncodingASCII);
            return len;
        }
        else
            return (len+1);
    }
    return 0;
}
Example #5
0
static IOHIDDeviceRef get_device_ref(int id)
{
    IOHIDElementRef tIOHIDElementRef;
    IOHIDDeviceRef tIOHIDDeviceRef;

    if (!gCollections)
        return 0;

    tIOHIDElementRef = (IOHIDElementRef)CFArrayGetValueAtIndex(gCollections, id);
    if (!tIOHIDElementRef)
    {
        ERR("Invalid Element requested %i\n",id);
        return 0;
    }

    tIOHIDDeviceRef = IOHIDElementGetDevice(tIOHIDElementRef);
    if (!tIOHIDDeviceRef)
    {
        ERR("Invalid Device requested %i\n",id);
        return 0;
    }

    return tIOHIDDeviceRef;
}
Example #6
0
void Burger::Mouse::InputCallback(void *pData, int iReturn,void * /* pSender */,IOHIDValueRef pValue)
{
	if (iReturn == kIOReturnSuccess) {
		Mouse *pMouse = static_cast<Mouse *>(pData);
		Word uCount = pMouse->m_uMiceCount;
		if (uCount) {
			IOHIDElementRef pElement = IOHIDValueGetElement(pValue);
			IOHIDDeviceRef pDevice = IOHIDElementGetDevice(pElement);
#if 0
			Word uRatNumber = BURGER_MAXUINT;
			const DeviceStruct *pRat = pMouse->m_Mice;
			do {
				if (pRat->m_pDevice == pDevice) {
					uRatNumber = pMouse->m_uMiceCount-uCount;
					break;
				}
				++pRat;
			} while (--uCount);
			if (uRatNumber==BURGER_MAXUINT) {
			}
#endif
			Word32 uTime = static_cast<Word32>(IOHIDValueGetTimeStamp(pValue));
			CFIndex iValue = IOHIDValueGetIntegerValue(pValue);
			
			uint32_t uPage = IOHIDElementGetUsagePage(pElement);
			uint32_t uUsage = IOHIDElementGetUsage(pElement);
			switch (uPage) {
			case kHIDPage_GenericDesktop:
				if (iValue) {
					switch (uUsage) {
					case kHIDUsage_GD_X:
						pMouse->PostMouseMotion(static_cast<Int32>(iValue),0,uTime);
						break;
					case kHIDUsage_GD_Y:
						pMouse->PostMouseMotion(0,static_cast<Int32>(iValue),uTime);
						break;
					case kHIDUsage_GD_Wheel:
						pMouse->PostMouseWheel(0,static_cast<Int32>(iValue),uTime);
						break;
					default:
						printf("Unknown usage %u\n",uUsage);
						break;
					}
				}
				break;
			case kHIDPage_Button:
				// iValue == down
				// Usage = which 1.2.3.4
				if (iValue) {
					pMouse->PostMouseDown(1<<(uUsage-1));
				} else {
					pMouse->PostMouseUp(1<<(uUsage-1));
				}
				break;
				// Ignore this one
			case kHIDPage_Consumer:
				break;
			default:
				printf("Unknown page found %u\n",uPage);
				break;
			}
		}
	}
}
Example #7
0
JoystickState JoystickImpl::update()
{
    static const JoystickState disconnectedState; // return this if joystick was disconnected
    JoystickState       state; // otherwise return that
    state.connected = true;

    // Note: free up is done in close() which is called, if required,
    //       by the joystick manager. So we don't release buttons nor axes here.

    // First, let's determine if the joystick is still connected
    Location selfLoc = m_locationIDs[m_index];

    // Get all devices
    CFSetRef devices = HIDJoystickManager::getInstance().copyJoysticks();
    if (devices == NULL)
        return disconnectedState;

    // Get a usable copy of the joysticks devices.
    CFIndex joysticksCount = CFSetGetCount(devices);
    CFTypeRef devicesArray[joysticksCount];
    CFSetGetValues(devices, devicesArray);

    // Search for it
    bool found = false;
    for (CFIndex i(0); i < joysticksCount; ++i)
    {
        IOHIDDeviceRef d = (IOHIDDeviceRef)devicesArray[i];
        if (selfLoc == HIDInputManager::getLocationID(d))
        {
            found = true;
            break; // Stop looping
        }
    }

    // Release unused stuff
    CFRelease(devices);

    // If not found we consider it disconnected
    if (!found)
        return disconnectedState;

    // Update buttons' state
    unsigned int i = 0;
    for (ButtonsVector::iterator it(m_buttons.begin()); it != m_buttons.end(); ++it, ++i)
    {
        IOHIDValueRef value = 0;
        IOHIDDeviceGetValue(IOHIDElementGetDevice(*it), *it, &value);

        // Check for plug out.
        if (!value)
        {
            // No value? Hum... Seems like the joystick is gone
            return disconnectedState;
        }

        // 1 means pressed, others mean released
        state.buttons[i] = IOHIDValueGetIntegerValue(value) == 1;
    }

    // Update axes' state
    for (AxisMap::iterator it = m_axis.begin(); it != m_axis.end(); ++it)
    {
        IOHIDValueRef value = 0;
        IOHIDDeviceGetValue(IOHIDElementGetDevice(it->second), it->second, &value);

        // Check for plug out.
        if (!value)
        {
            // No value? Hum... Seems like the joystick is gone
            return disconnectedState;
        }

        // We want to bind [physicalMin,physicalMax] to [-100=min,100=max].
        //
        // General formula to bind [a,b] to [c,d] with a linear progression:
        //
        // f: [a, b] -> [c, d]
        //        x  |->  (x-a)(d-c)/(b-a)+c
        //
        // This method might not be very accurate (the "0 position" can be
        // slightly shift with some device) but we don't care because most
        // of devices are so sensitive that this is not relevant.
        double  physicalMax   = IOHIDElementGetPhysicalMax(it->second);
        double  physicalMin   = IOHIDElementGetPhysicalMin(it->second);
        double  scaledMin     = -100;
        double  scaledMax     =  100;
        double  physicalValue = IOHIDValueGetScaledValue(value, kIOHIDValueScaleTypePhysical);
        float   scaledValue   = (((physicalValue - physicalMin) * (scaledMax - scaledMin)) / (physicalMax - physicalMin)) + scaledMin;
        state.axes[it->first] = scaledValue;
    }

    return state;
}
Example #8
0
// utility routine to dump element info
void HIDDumpElementInfo(IOHIDElementRef inIOHIDElementRef) {
	if (inIOHIDElementRef) {
		printf("    Element: %p = { ", inIOHIDElementRef);
#if false
		IOHIDDeviceRef tIOHIDDeviceRef = IOHIDElementGetDevice(inIOHIDElementRef);
		printf("Device: %p, ", tIOHIDDeviceRef);
#endif // if 0
		IOHIDElementRef parentIOHIDElementRef = IOHIDElementGetParent(inIOHIDElementRef);
		printf("parent: %p, ", parentIOHIDElementRef);
#if false
		CFArrayRef childrenCFArrayRef = IOHIDElementGetChildren(inIOHIDElementRef);
		printf("children: %p: { ", childrenCFArrayRef);
		fflush(stdout);
		CFShow(childrenCFArrayRef);
		fflush(stdout);
		printf(" }, ");
#endif // if 0
		IOHIDElementCookie tIOHIDElementCookie = IOHIDElementGetCookie(inIOHIDElementRef);
		printf("cookie: 0x%08lX, ", (long unsigned int) tIOHIDElementCookie);
		
		IOHIDElementType tIOHIDElementType = IOHIDElementGetType(inIOHIDElementRef);
		
		switch (tIOHIDElementType) {
			case kIOHIDElementTypeInput_Misc:
			{
				printf("type: Misc, ");
				break;
			}
				
			case kIOHIDElementTypeInput_Button:
			{
				printf("type: Button, ");
				break;
			}
				
			case kIOHIDElementTypeInput_Axis:
			{
				printf("type: Axis, ");
				break;
			}
				
			case kIOHIDElementTypeInput_ScanCodes:
			{
				printf("type: ScanCodes, ");
				break;
			}
				
			case kIOHIDElementTypeOutput:
			{
				printf("type: Output, ");
				break;
			}
				
			case kIOHIDElementTypeFeature:
			{
				printf("type: Feature, ");
				break;
			}
				
			case kIOHIDElementTypeCollection:
			{
				IOHIDElementCollectionType tIOHIDElementCollectionType = IOHIDElementGetCollectionType(inIOHIDElementRef);
				
				switch (tIOHIDElementCollectionType) {
					case kIOHIDElementCollectionTypePhysical:
					{
						printf("type: Physical Collection, ");
						break;
					}
						
					case kIOHIDElementCollectionTypeApplication:
					{
						printf("type: Application Collection, ");
						break;
					}
						
					case kIOHIDElementCollectionTypeLogical:
					{
						printf("type: Logical Collection, ");
						break;
					}
						
					case kIOHIDElementCollectionTypeReport:
					{
						printf("type: Report Collection, ");
						break;
					}
						
					case kIOHIDElementCollectionTypeNamedArray:
					{
						printf("type: Named Array Collection, ");
						break;
					}
						
					case kIOHIDElementCollectionTypeUsageSwitch:
					{
						printf("type: Usage Switch Collection, ");
						break;
					}
						
					case kIOHIDElementCollectionTypeUsageModifier:
					{
						printf("type: Usage Modifier Collection, ");
						break;
					}
						
					default:
					{
						printf("type: %p Collection, ", (void *) tIOHIDElementCollectionType);
						break;
					}
				} // switch
				
				break;
			}
				
			default:
			{
				printf("type: %p, ", (void *) tIOHIDElementType);
				break;
			}
		}     /* switch */
		
		uint32_t usagePage = IOHIDElementGetUsagePage(inIOHIDElementRef);
		uint32_t usage     = IOHIDElementGetUsage(inIOHIDElementRef);
		printf("usage: 0x%04lX:0x%04lX, ", (long unsigned int) usagePage, (long unsigned int) usage);

		CFStringRef tCFStringRef = HIDCopyUsageName(usagePage, usage);
		if (tCFStringRef) {
			char usageString[256] = "";
			(void) CFStringGetCString(tCFStringRef, usageString, sizeof(usageString), kCFStringEncodingUTF8);
			printf("\"%s\", ", usageString);
			CFRelease(tCFStringRef);
		}

		CFStringRef nameCFStringRef = IOHIDElementGetName(inIOHIDElementRef);
		char        buffer[256];
		if ( nameCFStringRef && CFStringGetCString(nameCFStringRef, buffer, sizeof(buffer), kCFStringEncodingUTF8) ) {
			printf("name: %s, ", buffer);
		}
		
		uint32_t reportID    = IOHIDElementGetReportID(inIOHIDElementRef);
		uint32_t reportSize  = IOHIDElementGetReportSize(inIOHIDElementRef);
		uint32_t reportCount = IOHIDElementGetReportCount(inIOHIDElementRef);
		printf("report: { ID: %lu, Size: %lu, Count: %lu }, ",
		       (long unsigned int) reportID, (long unsigned int) reportSize, (long unsigned int) reportCount);
		
		uint32_t unit    = IOHIDElementGetUnit(inIOHIDElementRef);
		uint32_t unitExp = IOHIDElementGetUnitExponent(inIOHIDElementRef);
		if (unit || unitExp) {
			printf("unit: %lu * 10^%lu, ", (long unsigned int) unit, (long unsigned int) unitExp);
		}
		
		CFIndex logicalMin = IOHIDElementGetLogicalMin(inIOHIDElementRef);
		CFIndex logicalMax = IOHIDElementGetLogicalMax(inIOHIDElementRef);
		if (logicalMin != logicalMax) {
			printf("logical: {min: %ld, max: %ld}, ", logicalMin, logicalMax);
		}
		
		CFIndex physicalMin = IOHIDElementGetPhysicalMin(inIOHIDElementRef);
		CFIndex physicalMax = IOHIDElementGetPhysicalMax(inIOHIDElementRef);
		if (physicalMin != physicalMax) {
			printf("physical: {min: %ld, max: %ld}, ", physicalMin, physicalMax);
		}
		
		Boolean isVirtual = IOHIDElementIsVirtual(inIOHIDElementRef);
		if (isVirtual) {
			printf("isVirtual, ");
		}
		
		Boolean isRelative = IOHIDElementIsRelative(inIOHIDElementRef);
		if (isRelative) {
			printf("isRelative, ");
		}
		
		Boolean isWrapping = IOHIDElementIsWrapping(inIOHIDElementRef);
		if (isWrapping) {
			printf("isWrapping, ");
		}
		
		Boolean isArray = IOHIDElementIsArray(inIOHIDElementRef);
		if (isArray) {
			printf("isArray, ");
		}
		
		Boolean isNonLinear = IOHIDElementIsNonLinear(inIOHIDElementRef);
		if (isNonLinear) {
			printf("isNonLinear, ");
		}
		
		Boolean hasPreferredState = IOHIDElementHasPreferredState(inIOHIDElementRef);
		if (hasPreferredState) {
			printf("hasPreferredState, ");
		}
		
		Boolean hasNullState = IOHIDElementHasNullState(inIOHIDElementRef);
		if (hasNullState) {
			printf("hasNullState, ");
		}
		
		printf(" }\n");
	}
}   // HIDDumpElementInfo
Example #9
0
static void poll_osx_device_state(LPDIRECTINPUTDEVICE8A iface)
{
    JoystickImpl *device = impl_from_IDirectInputDevice8A(iface);
    IOHIDElementRef tIOHIDTopElementRef;
    IOHIDDeviceRef tIOHIDDeviceRef;
    CFArrayRef gElementCFArrayRef = device->elementCFArrayRef;

    TRACE("polling device %i\n",device->id);

    if (!gCollections)
        return;

    tIOHIDTopElementRef = (IOHIDElementRef) CFArrayGetValueAtIndex(gCollections, device->id);
    tIOHIDDeviceRef = IOHIDElementGetDevice(tIOHIDTopElementRef);

    if (!tIOHIDDeviceRef)
        return;

    if (gElementCFArrayRef)
    {
        int button_idx = 0;
        int pov_idx = 0;
        int slider_idx = 0;
        int inst_id;
        CFIndex idx, cnt = CFArrayGetCount( gElementCFArrayRef );

        for ( idx = 0; idx < cnt; idx++ )
        {
            IOHIDValueRef valueRef;
            int val, oldVal, newVal;
            IOHIDElementRef tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( gElementCFArrayRef, idx );
            int eleType = IOHIDElementGetType( tIOHIDElementRef );

            switch(eleType)
            {
            case kIOHIDElementTypeInput_Button:
                if(button_idx < 128)
                {
                    IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &valueRef);
                    val = IOHIDValueGetIntegerValue(valueRef);
                    newVal = val ? 0x80 : 0x0;
                    oldVal = device->generic.js.rgbButtons[button_idx];
                    device->generic.js.rgbButtons[button_idx] = newVal;
                    if (oldVal != newVal)
                    {
                        inst_id = DIDFT_MAKEINSTANCE(button_idx) | DIDFT_PSHBUTTON;
                        queue_event(iface,inst_id,newVal,GetCurrentTime(),device->generic.base.dinput->evsequence++);
                    }
                    button_idx ++;
                }
                break;
            case kIOHIDElementTypeInput_Misc:
            {
                uint32_t usage = IOHIDElementGetUsage( tIOHIDElementRef );
                switch(usage)
                {
                case kHIDUsage_GD_Hatswitch:
                {
                    IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &valueRef);
                    val = IOHIDValueGetIntegerValue(valueRef);
                    oldVal = device->generic.js.rgdwPOV[pov_idx];
                    if (val >= 8)
                        newVal = -1;
                    else
                        newVal = val * 4500;
                    device->generic.js.rgdwPOV[pov_idx] = newVal;
                    if (oldVal != newVal)
                    {
                        inst_id = DIDFT_MAKEINSTANCE(pov_idx) | DIDFT_POV;
                        queue_event(iface,inst_id,newVal,GetCurrentTime(),device->generic.base.dinput->evsequence++);
                    }
                    pov_idx ++;
                    break;
                }
                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:
                {
                    int wine_obj = -1;

                    IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &valueRef);
                    val = IOHIDValueGetIntegerValue(valueRef);
                    newVal = joystick_map_axis(&device->generic.props[idx], val);
                    switch (usage)
                    {
                    case kHIDUsage_GD_X:
                        wine_obj = 0;
                        oldVal = device->generic.js.lX;
                        device->generic.js.lX = newVal;
                        break;
                    case kHIDUsage_GD_Y:
                        wine_obj = 1;
                        oldVal = device->generic.js.lY;
                        device->generic.js.lY = newVal;
                        break;
                    case kHIDUsage_GD_Z:
                        wine_obj = 2;
                        oldVal = device->generic.js.lZ;
                        device->generic.js.lZ = newVal;
                        break;
                    case kHIDUsage_GD_Rx:
                        wine_obj = 3;
                        oldVal = device->generic.js.lRx;
                        device->generic.js.lRx = newVal;
                        break;
                    case kHIDUsage_GD_Ry:
                        wine_obj = 4;
                        oldVal = device->generic.js.lRy;
                        device->generic.js.lRy = newVal;
                        break;
                    case kHIDUsage_GD_Rz:
                        wine_obj = 5;
                        oldVal = device->generic.js.lRz;
                        device->generic.js.lRz = newVal;
                        break;
                    case kHIDUsage_GD_Slider:
                        wine_obj = 6 + slider_idx;
                        oldVal = device->generic.js.rglSlider[slider_idx];
                        device->generic.js.rglSlider[slider_idx] = newVal;
                        slider_idx ++;
                        break;
                    }
                    if ((wine_obj != -1) &&
                            (oldVal != newVal))
                    {
                        inst_id = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
                        queue_event(iface,inst_id,newVal,GetCurrentTime(),device->generic.base.dinput->evsequence++);
                    }

                    break;
                }
                default:
                    FIXME("unhandled usage %i\n",usage);
                }
                break;
            }
            default:
                FIXME("Unhandled type %i\n",eleType);
            }
        }
    }
}
Example #10
0
static void poll_osx_device_state(LPDIRECTINPUTDEVICE8A iface)
{
    JoystickImpl *device = (JoystickImpl*)iface;
    IOHIDElementRef tIOHIDTopElementRef;
    IOHIDDeviceRef tIOHIDDeviceRef;
    CFArrayRef gElementCFArrayRef = device->elementCFArrayRef;

    TRACE("polling device %i\n",device->id);

    if (!gCollections)
        return;

    tIOHIDTopElementRef = (IOHIDElementRef) CFArrayGetValueAtIndex(gCollections, device->id);
    tIOHIDDeviceRef = IOHIDElementGetDevice(tIOHIDTopElementRef);

    if (!tIOHIDDeviceRef)
        return;

    if (gElementCFArrayRef)
    {
        int button_idx = 0;
        int pov_idx = 0;
        int slider_idx = 0;
        CFIndex idx, cnt = CFArrayGetCount( gElementCFArrayRef );

        for ( idx = 0; idx < cnt; idx++ )
        {
            IOHIDValueRef valueRef;
            int val;
            IOHIDElementRef tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( gElementCFArrayRef, idx );
            int eleType = IOHIDElementGetType( tIOHIDElementRef );

            switch(eleType)
            {
                case kIOHIDElementTypeInput_Button:
                    if(button_idx < 128)
                    {
                        IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &valueRef);
                        val = IOHIDValueGetIntegerValue(valueRef);
                        device->generic.js.rgbButtons[button_idx] = val ? 0x80 : 0x00;
                        button_idx ++;
                    }
                    break;
                case kIOHIDElementTypeInput_Misc:
                {
                    uint32_t usage = IOHIDElementGetUsage( tIOHIDElementRef );
                    switch(usage)
                    {
                        case kHIDUsage_GD_Hatswitch:
                        {
                            IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &valueRef);
                            val = IOHIDValueGetIntegerValue(valueRef);
                            if (val >= 8)
                                device->generic.js.rgdwPOV[pov_idx] = -1;
                            else
                                device->generic.js.rgdwPOV[pov_idx] = val * 4500;
                            pov_idx ++;
                            break;
                        }
                        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:
                        {
                            IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &valueRef);
                            val = IOHIDValueGetIntegerValue(valueRef);
                            switch (usage)
                            {
                            case kHIDUsage_GD_X:
                                device->generic.js.lX = joystick_map_axis(&device->generic.props[idx], val);
                                break;
                            case kHIDUsage_GD_Y:
                                device->generic.js.lY = joystick_map_axis(&device->generic.props[idx], val);
                                break;
                            case kHIDUsage_GD_Z:
                                device->generic.js.lZ = joystick_map_axis(&device->generic.props[idx], val);
                                break;
                            case kHIDUsage_GD_Rx:
                                device->generic.js.lRx = joystick_map_axis(&device->generic.props[idx], val);
                                break;
                            case kHIDUsage_GD_Ry:
                                device->generic.js.lRy = joystick_map_axis(&device->generic.props[idx], val);
                                break;
                            case kHIDUsage_GD_Rz:
                                device->generic.js.lRz = joystick_map_axis(&device->generic.props[idx], val);
                                break;
                            case kHIDUsage_GD_Slider:
                                device->generic.js.rglSlider[slider_idx] = joystick_map_axis(&device->generic.props[idx], val);
                                slider_idx ++;
                                break;
                            }
                            break;
                        }
                        default:
                            FIXME("unhandled usage %i\n",usage);
                    }
                    break;
                }
                default:
                    FIXME("Unhandled type %i\n",eleType);
            }
        }
    }
}
/**************************************************************************
 *                              driver_joyGetPosEx
 */
LRESULT driver_joyGetPosEx(DWORD_PTR device_id, JOYINFOEX* info)
{
    static const struct {
        DWORD flag;
        off_t offset;
    } axis_map[NUM_AXES] = {
        { JOY_RETURNX, FIELD_OFFSET(JOYINFOEX, dwXpos) },
        { JOY_RETURNY, FIELD_OFFSET(JOYINFOEX, dwYpos) },
        { JOY_RETURNZ, FIELD_OFFSET(JOYINFOEX, dwZpos) },
        { JOY_RETURNU, FIELD_OFFSET(JOYINFOEX, dwUpos) },
        { JOY_RETURNV, FIELD_OFFSET(JOYINFOEX, dwVpos) },
        { JOY_RETURNR, FIELD_OFFSET(JOYINFOEX, dwRpos) },
    };

    joystick_t* joystick;
    IOHIDDeviceRef device;
    CFIndex i, count;
    IOHIDValueRef valueRef;
    long value;

    if ((joystick = joystick_from_id(device_id)) == NULL)
        return MMSYSERR_NODRIVER;

    if (!open_joystick(joystick))
        return JOYERR_PARMS;

    device = IOHIDElementGetDevice(joystick->element);

    if (info->dwFlags & JOY_RETURNBUTTONS)
    {
        info->dwButtons = 0;
        info->dwButtonNumber = 0;

        count = CFArrayGetCount(joystick->buttons);
        for (i = 0; i < count; i++)
        {
            IOHIDElementRef button = (IOHIDElementRef)CFArrayGetValueAtIndex(joystick->buttons, i);
            IOHIDDeviceGetValue(device, button, &valueRef);
            value = IOHIDValueGetIntegerValue(valueRef);
            if (value)
            {
                info->dwButtons |= 1 << i;
                if (!info->dwButtonNumber)
                    info->dwButtonNumber = i + 1;
            }
        }
    }

    for (i = 0; i < NUM_AXES; i++)
    {
        if (info->dwFlags & axis_map[i].flag)
        {
            DWORD* field = (DWORD*)((char*)info + axis_map[i].offset);
            if (joystick->axes[i].element)
            {
                IOHIDDeviceGetValue(device, joystick->axes[i].element, &valueRef);
                value = IOHIDValueGetIntegerValue(valueRef) - joystick->axes[i].min_value;
                *field = MulDiv(value, 0xFFFF, joystick->axes[i].max_value - joystick->axes[i].min_value);
            }
            else
            {
                *field = 0;
                info->dwFlags &= ~axis_map[i].flag;
            }
        }
    }

    if (info->dwFlags & JOY_RETURNPOV)
    {
        if (joystick->hatswitch)
        {
            IOHIDDeviceGetValue(device, joystick->hatswitch, &valueRef);
            value = IOHIDValueGetIntegerValue(valueRef);
            if (value >= 8)
                info->dwPOV = JOY_POVCENTERED;
            else
                info->dwPOV = value * 4500;
        }
        else
        {
            info->dwPOV = 0;
            info->dwFlags &= ~JOY_RETURNPOV;
        }
    }

    TRACE("x: %d, y: %d, z: %d, r: %d, u: %d, v: %d, buttons: 0x%04x, pov %d, flags: 0x%04x\n",
          info->dwXpos, info->dwYpos, info->dwZpos, info->dwRpos, info->dwUpos, info->dwVpos, info->dwButtons, info->dwPOV, info->dwFlags);

    return JOYERR_NOERROR;
}
/**************************************************************************
 *                              driver_joyGetDevCaps
 */
LRESULT driver_joyGetDevCaps(DWORD_PTR device_id, JOYCAPSW* caps, DWORD size)
{
    joystick_t* joystick;
    IOHIDDeviceRef device;

    if ((joystick = joystick_from_id(device_id)) == NULL)
        return MMSYSERR_NODRIVER;

    if (!open_joystick(joystick))
        return JOYERR_PARMS;

    caps->szPname[0] = 0;

    device = IOHIDElementGetDevice(joystick->element);
    if (device)
    {
        CFStringRef product_name = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
        if (product_name)
        {
            CFRange range;

            range.location = 0;
            range.length = min(MAXPNAMELEN - 1, CFStringGetLength(product_name));
            CFStringGetCharacters(product_name, range, (UniChar*)caps->szPname);
            caps->szPname[range.length] = 0;
        }
    }

    caps->wMid = MM_MICROSOFT;
    caps->wPid = MM_PC_JOYSTICK;
    caps->wXmin = 0;
    caps->wXmax = 0xFFFF;
    caps->wYmin = 0;
    caps->wYmax = 0xFFFF;
    caps->wZmin = 0;
    caps->wZmax = joystick->axes[AXIS_Z].element ? 0xFFFF : 0;
    caps->wNumButtons = CFArrayGetCount(joystick->buttons);
    if (size == sizeof(JOYCAPSW))
    {
        int i;

        /* complete 95 structure */
        caps->wRmin = 0;
        caps->wRmax = 0xFFFF;
        caps->wUmin = 0;
        caps->wUmax = 0xFFFF;
        caps->wVmin = 0;
        caps->wVmax = 0xFFFF;
        caps->wMaxAxes = 6; /* same as MS Joystick Driver */
        caps->wNumAxes = 0;
        caps->wMaxButtons = 32; /* same as MS Joystick Driver */
        caps->szRegKey[0] = 0;
        caps->szOEMVxD[0] = 0;
        caps->wCaps = 0;

        for (i = 0; i < NUM_AXES; i++)
        {
            if (joystick->axes[i].element)
            {
                caps->wNumAxes++;
                switch (i)
                {
                    case AXIS_Z:  caps->wCaps |= JOYCAPS_HASZ; break;
                    case AXIS_RX: caps->wCaps |= JOYCAPS_HASU; break;
                    case AXIS_RY: caps->wCaps |= JOYCAPS_HASV; break;
                    case AXIS_RZ: caps->wCaps |= JOYCAPS_HASR; break;
                }
            }
        }

        if (joystick->hatswitch)
            caps->wCaps |= JOYCAPS_HASPOV | JOYCAPS_POV4DIR;
    }

    TRACE("name %s buttons %u axes %d caps 0x%08x\n", debugstr_w(caps->szPname), caps->wNumButtons, caps->wNumAxes, caps->wCaps);

    return JOYERR_NOERROR;
}
static const char* debugstr_element(IOHIDElementRef element)
{
    return wine_dbg_sprintf("<IOHIDElement %p type %d usage %u/%u device %p>", element,
                            IOHIDElementGetType(element), IOHIDElementGetUsagePage(element),
                            IOHIDElementGetUsage(element), IOHIDElementGetDevice(element));
}
Example #14
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 */
void GamepadManager::onDeviceValueChanged(IOHIDValueRef value)
{
    
    IOHIDElementRef element = IOHIDValueGetElement(value);
    IOHIDDeviceRef device = IOHIDElementGetDevice(element);

    int vendorID = getIntDeviceProperty(device, CFSTR(kIOHIDVendorIDKey));
    int productID = getIntDeviceProperty(device, CFSTR(kIOHIDProductIDKey));
    
    uint32_t usagePage = IOHIDElementGetUsagePage(element);
    uint32_t usage = IOHIDElementGetUsage(element);

    // The following controller mapping is based on the Logitech F710, however we use it for
    // all Logitech devices on the assumption that they're likely to share the same mapping.
    if (vendorID == Logitech_F710_VendorID)
    {
        // Logitech F710 mapping.
        if (usagePage == kHIDPage_Button)
        {
            bool buttonState = IOHIDValueGetIntegerValue(value);

            switch(usage)
            {
                case kHIDUsage_Button_1:
                    manipulateBitField(State.Buttons, Gamepad_X, buttonState);
                    break;
                case kHIDUsage_Button_2:
                    manipulateBitField(State.Buttons, Gamepad_A, buttonState);
                    break;
                case kHIDUsage_Button_3:
                    manipulateBitField(State.Buttons, Gamepad_B, buttonState);
                    break;
                case kHIDUsage_Button_4:
                    manipulateBitField(State.Buttons, Gamepad_Y, buttonState);
                    break;
                case 0x05:
                    manipulateBitField(State.Buttons, Gamepad_L1, buttonState);
                    break;
                case 0x06:
                    manipulateBitField(State.Buttons, Gamepad_R1, buttonState);
                    break;
                case 0x07:
                    State.LT = buttonState ? 1.0f:0.0f;
                    break;
                case 0x08:
                    State.RT = buttonState ? 1.0f:0.0f;
                    break;
                case 0x09:
                    manipulateBitField(State.Buttons, Gamepad_Back, buttonState);
                    break;
                case 0x0A:
                    manipulateBitField(State.Buttons, Gamepad_Start, buttonState);
                    break;
                case 0x0B:
                    manipulateBitField(State.Buttons, Gamepad_LStick, buttonState);
                    break;
                case 0x0C:
                    manipulateBitField(State.Buttons, Gamepad_RStick, buttonState);
                    break;
                default:
                    return;
            }
        }
        else if (usagePage == kHIDPage_GenericDesktop)
        {
            float v;
            switch(usage)
            {
                case kHIDUsage_GD_X:
                    v = mapAnalogAxis(value, element);
                    if (!setStateIfDifferent(State.LX, v))
                        return;
                    break;
                case kHIDUsage_GD_Y:
                    v = mapAnalogAxis(value, element);
                    if (!setStateIfDifferent(State.LY, -v))
                        return;
                    break;
                case kHIDUsage_GD_Z:
                    v = mapAnalogAxis(value, element);
                    if (!setStateIfDifferent(State.RX, v))
                        return;
                    break;
                case kHIDUsage_GD_Rz:
                    v = mapAnalogAxis(value, element);
                    if (!setStateIfDifferent(State.RY, -v))
                        return;
                    break;
                case kHIDUsage_GD_Hatswitch:
                    {
                        CFIndex integerValue = IOHIDValueGetIntegerValue(value);
                 
                        manipulateBitField(State.Buttons,
                                           Gamepad_Up,
                                           integerValue == 7 || integerValue == 0 || integerValue == 1);
                        manipulateBitField(State.Buttons,
                                           Gamepad_Down,
                                           integerValue == 3 || integerValue == 4 || integerValue == 5);
                        manipulateBitField(State.Buttons,
                                           Gamepad_Left,
                                           integerValue == 5 || integerValue == 6 || integerValue == 7);
                        manipulateBitField(State.Buttons,
                                           Gamepad_Right,
                                           integerValue == 1 || integerValue == 2 || integerValue == 3);
                    }
                    break;
                default:
                    return;
            }
        }
    }
    // The following controller mapping is based on the Sony DualShock3, however we use it for
    // all Sony devices on the assumption that they're likely to share the same mapping.
    else if (vendorID == Sony_DualShock3_VendorID)
    {
        // PS3 Controller.
        if (usagePage == kHIDPage_Button)
        {
            bool buttonState = IOHIDValueGetIntegerValue(value);
            
            switch(usage)
            {
                case kHIDUsage_Button_1:
                    manipulateBitField(State.Buttons, Gamepad_Back, buttonState);
                    break;
                case kHIDUsage_Button_2:
                    manipulateBitField(State.Buttons, Gamepad_LStick, buttonState);
                    break;
                case kHIDUsage_Button_3:
                    manipulateBitField(State.Buttons, Gamepad_RStick, buttonState);
                    break;
                case kHIDUsage_Button_4:
                    manipulateBitField(State.Buttons, Gamepad_Start, buttonState);
                    break;
                case 0x05:
                    manipulateBitField(State.Buttons, Gamepad_Up, buttonState);
                    break;
                case 0x06:
                    manipulateBitField(State.Buttons, Gamepad_Right, buttonState);
                    break;
                case 0x07:
                    manipulateBitField(State.Buttons, Gamepad_Down, buttonState);
                    break;
                case 0x08:
                    manipulateBitField(State.Buttons, Gamepad_Left, buttonState);
                    break;
                case 0x09:
                    State.LT = buttonState ? 1.0f:0.0f;
                    break;
                case 0x0A:
                    State.RT = buttonState ? 1.0f:0.0f;
                    break;
                case 0x0B:
                    manipulateBitField(State.Buttons, Gamepad_L1, buttonState);
                    break;
                case 0x0C:
                    manipulateBitField(State.Buttons, Gamepad_R1, buttonState);
                    break;
                case 0x0D:
                    // PS3 Triangle.
                    manipulateBitField(State.Buttons, Gamepad_TRIANGLE, buttonState);
                    break;
                case 0x0E:
                    // PS3 Circle
                    manipulateBitField(State.Buttons, Gamepad_CIRCLE, buttonState);
                    break;
                case 0x0F:
                    // PS3 Cross
                    manipulateBitField(State.Buttons, Gamepad_CROSS, buttonState);
                    break;
                case 0x10:
                    // PS3 Square
                    manipulateBitField(State.Buttons, Gamepad_SQUARE, buttonState);
                    break;
                default:
                    return;
            }
        }
        else if (usagePage == kHIDPage_GenericDesktop)
        {
            float v;
            switch(usage)
            {
                case kHIDUsage_GD_X:
                    v = mapAnalogAxis(value, element);
                    if (!setStateIfDifferent(State.LX, v))
                        return;
                    break;
                case kHIDUsage_GD_Y:
                    v = mapAnalogAxis(value, element);
                    if (!setStateIfDifferent(State.LY, -v))
                        return;
                    break;
                case kHIDUsage_GD_Z:
                    v = mapAnalogAxis(value, element);
                    if (!setStateIfDifferent(State.RX, v))
                        return;
                    break;
                case kHIDUsage_GD_Rz:
                    v = mapAnalogAxis(value, element);
                    if (!setStateIfDifferent(State.RY, -v))
                        return;
                    break;
                default:
                    return;
            }
        }
    }
    
    bStateChanged = true;
}