Example #1
0
/**
	This function assumes that there are 2 values that can be read from the HID device which represent the DPad's state.
	This will not be true for all HID Devices. If you want to use this function, you must modify it for the correct value count.
	Furthermore, you need to update nesmapping.h, or include a different mapping file, which holds constants for the button mapping.
	(You'll have to figure out the button mapping experimentally using log statements or breakpoints)
 **/
int Controller::getDPadInput(bool * pValues)
{
	DWORD readbytecount = 0;
	_succ = ReadFile(
		_controllerHandle,
		_pInputReport,
		_pCaps->InputReportByteLength,
		&readbytecount,
		nullptr
		);

	CHECK_FAILURE(_succ, DPAD_INPUT_FAILURE);

	//use the input report to generate button usage data
	LONG value = 0;

	//reset direction flags
	for (int i = 0; i < NUM_DIRECTIONS; i++)
	{
		pValues[i] = false;
	}

	for (int valIt = 0; valIt < _pCaps->NumberInputValueCaps; valIt++)
	{
		HidP_GetUsageValue(HidP_Input, _pValueCaps[valIt].UsagePage, _pValueCaps[valIt].LinkCollection, _pValueCaps[valIt].Range.UsageMin, (PULONG)&value, _pPreparsedData,
			_pInputReport, readbytecount
			);

		if (valIt == 0)
		{
			switch (value)
			{
			case DPAD_UP:
				pValues[DPAD_UP_INDEX] = true;
				break;
			case DPAD_DOWN:
				pValues[DPAD_DOWN_INDEX] = true;
				break;
			default:
				break;
			}
		}
		else
		{
			switch (value)
			{
			case DPAD_RIGHT:
				pValues[DPAD_RIGHT_INDEX] = true;
				break;
			case DPAD_LEFT:
				pValues[DPAD_LEFT_INDEX] = true;
				break;
			default:
				break;
			}
		}

	}

	return _pCaps->NumberInputValueCaps;

DPAD_INPUT_FAILURE:
		return -1;

}
Example #2
0
static void ParseRawInputHID(PRAWINPUT pRawInput)
{
	PHIDP_PREPARSED_DATA pPreparsedData = NULL;
	HIDP_CAPS            Caps;
	PHIDP_BUTTON_CAPS    pButtonCaps = NULL;
	PHIDP_VALUE_CAPS     pValueCaps = NULL;
	UINT                 bufferSize;
	ULONG                usageLength, value;
	TCHAR                name[1024] = {0};
	UINT                 nameSize = 1024;
	RID_DEVICE_INFO      devInfo = {0};
	std::wstring         devName;
	USHORT               capsLength = 0;
	USAGE                usage[MAX_BUTTONS] = {0};
	Mappings             *mapping = NULL;
	MapVector::iterator  it;

	GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_DEVICENAME, name, &nameSize);

	devName = name;
	std::transform(devName.begin(), devName.end(), devName.begin(), ::toupper);

	for(it = mapVector.begin(); it != mapVector.end(); it++)
	{
		if((*it).hidPath == devName)
		{
			mapping = &(*it);
			break;
		}
	}

	if(mapping == NULL)
		return;

	CHECK( GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_PREPARSEDDATA, NULL, &bufferSize) == 0 );
	CHECK( pPreparsedData = (PHIDP_PREPARSED_DATA)malloc(bufferSize) );
	CHECK( (int)GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_PREPARSEDDATA, pPreparsedData, &bufferSize) >= 0 );
	CHECK( HidP_GetCaps(pPreparsedData, &Caps) == HIDP_STATUS_SUCCESS );
	//pSize = sizeof(devInfo);
	//GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_DEVICEINFO, &devInfo, &pSize);

	//Unset buttons/axes mapped to this device
	//ResetData(&mapping->data[0]);
	//ResetData(&mapping->data[1]);
	memset(&mapping->data[0], 0xFF, sizeof(wheel_data_t));
	memset(&mapping->data[1], 0xFF, sizeof(wheel_data_t));
	mapping->data[0].buttons = 0;
	mapping->data[1].buttons = 0;
	mapping->data[0].hatswitch = 0x8;
	mapping->data[1].hatswitch = 0x8;

	//Get pressed buttons
	CHECK( pButtonCaps = (PHIDP_BUTTON_CAPS)malloc(sizeof(HIDP_BUTTON_CAPS) * Caps.NumberInputButtonCaps) );
	//If fails, maybe wheel only has axes
	capsLength = Caps.NumberInputButtonCaps;
	HidP_GetButtonCaps(HidP_Input, pButtonCaps, &capsLength, pPreparsedData);

	int numberOfButtons = pButtonCaps->Range.UsageMax - pButtonCaps->Range.UsageMin + 1;
	usageLength = numberOfButtons;
	NTSTATUS stat;
	if((stat = HidP_GetUsages(
			HidP_Input, pButtonCaps->UsagePage, 0, usage, &usageLength, pPreparsedData,
			(PCHAR)pRawInput->data.hid.bRawData, pRawInput->data.hid.dwSizeHid)) == HIDP_STATUS_SUCCESS )
	{
		for(uint32_t i = 0; i < usageLength; i++)
		{
			uint16_t btn = mapping->btnMap[usage[i] - pButtonCaps->Range.UsageMin];
			for(int j=0; j<2; j++)
			{
				PS2WheelTypes wt = (PS2WheelTypes)conf.WheelType[j];
				if(PLY_IS_MAPPED(j, btn))
				{
					uint32_t wtbtn = (1 << convert_wt_btn(wt, PLY_GET_VALUE(j, btn))) & 0xFFF; //12bit mask
					mapping->data[j].buttons |= wtbtn;
				}
			}
		}
	}

	/// Get axes' values
	CHECK( pValueCaps = (PHIDP_VALUE_CAPS)malloc(sizeof(HIDP_VALUE_CAPS) * Caps.NumberInputValueCaps) );
	capsLength = Caps.NumberInputValueCaps;
	if(HidP_GetValueCaps(HidP_Input, pValueCaps, &capsLength, pPreparsedData) == HIDP_STATUS_SUCCESS )
	{
		for(USHORT i = 0; i < capsLength; i++)
		{
			if(HidP_GetUsageValue(
					HidP_Input, pValueCaps[i].UsagePage, 0,
					pValueCaps[i].Range.UsageMin, &value, pPreparsedData,
					(PCHAR)pRawInput->data.hid.bRawData, pRawInput->data.hid.dwSizeHid
				) != HIDP_STATUS_SUCCESS )
			{
				continue; // if here then maybe something is up with HIDP_CAPS.NumberInputValueCaps
			}

			//fprintf(stderr, "Min/max %d/%d\t", pValueCaps[i].LogicalMin, pValueCaps[i].LogicalMax);
			//TODO can be simpler?
			//Get mapped axis for physical axis
			uint16_t v = 0;
			switch(pValueCaps[i].Range.UsageMin)
			{
				// X-axis 0x30
				case HID_USAGE_GENERIC_X: 
					v = mapping->axisMap[0]; 
					break;
				// Y-axis
				case HID_USAGE_GENERIC_Y: 
					v = mapping->axisMap[1]; 
					break;
				// Z-axis
				case HID_USAGE_GENERIC_Z: 
					v = mapping->axisMap[2]; 
					break;
				// Rotate-X
				case HID_USAGE_GENERIC_RX: 
					v = mapping->axisMap[3]; 
					break;
				// Rotate-Y
				case HID_USAGE_GENERIC_RY: 
					v = mapping->axisMap[4]; 
					break;
				// Rotate-Z 0x35
				case HID_USAGE_GENERIC_RZ: 
					v = mapping->axisMap[5]; 
					break;
				case HID_USAGE_GENERIC_HATSWITCH:
					//fprintf(stderr, "Hat: %02X\n", value);
					v = mapping->axisMap[6];
					break;
			}

			int type = 0;
			for(int j=0; j<2; j++)
			{
				if(!PLY_IS_MAPPED(j, v))
					continue;

				type = conf.WheelType[j];

				switch(PLY_GET_VALUE(j, v))
				{
				case PAD_AXIS_X: // X-axis
					//fprintf(stderr, "X: %d\n", value);
					// Need for logical min too?
					//generic_data.axis_x = ((value - pValueCaps[i].LogicalMin) * 0x3FF) / (pValueCaps[i].LogicalMax - pValueCaps[i].LogicalMin);
					if(type == WT_DRIVING_FORCE_PRO)
						mapping->data[j].steering = (value * 0x3FFF) / pValueCaps[i].LogicalMax;
					else
						//XXX Limit value range to 0..1023 if using 'generic' wheel descriptor
						mapping->data[j].steering = (value * 0x3FF) / pValueCaps[i].LogicalMax;
					break;

				case PAD_AXIS_Y: // Y-axis
					if(!(devInfo.hid.dwVendorId == 0x046D && devInfo.hid.dwProductId == 0xCA03))
						//XXX Limit value range to 0..255
						mapping->data[j].clutch = (value * 0xFF) / pValueCaps[i].LogicalMax;
					break;

				case PAD_AXIS_Z: // Z-axis
					//fprintf(stderr, "Z: %d\n", value);
					//XXX Limit value range to 0..255
					mapping->data[j].throttle = (value * 0xFF) / pValueCaps[i].LogicalMax;
					break;

				case PAD_AXIS_RZ: // Rotate-Z
					//fprintf(stderr, "Rz: %d\n", value);
					//XXX Limit value range to 0..255
					mapping->data[j].brake = (value * 0xFF) / pValueCaps[i].LogicalMax;
					break;

				case PAD_AXIS_HAT: // TODO Hat Switch
					//fprintf(stderr, "Hat: %02X\n", value);
					//TODO 4 vs 8 direction hat switch
					if(pValueCaps[i].LogicalMax == 4 && value < 4)
						mapping->data[j].hatswitch = HATS_8TO4[value];
					else
						mapping->data[j].hatswitch = value;
					break;
				}
			}
		}
	}

	Error:
	SAFE_FREE(pPreparsedData);
	SAFE_FREE(pButtonCaps);
	SAFE_FREE(pValueCaps);
}
Example #3
0
	NTSTATUS Hid::GetUsageValue(REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, ULONG *UsageValue, void *PreparsedData, void *Report, ULONG ReportLength)
	{
		return HidP_GetUsageValue(ReportType, UsagePage, LinkCollection, Usage, UsageValue, PreparsedData, Report, ReportLength);
	}
Example #4
0
static void ParseRawInputHID(PRAWINPUT pRawInput, HIDState *hs)
{
	PHIDP_PREPARSED_DATA pPreparsedData = NULL;
	HIDP_CAPS            Caps;
	PHIDP_BUTTON_CAPS    pButtonCaps = NULL;
	PHIDP_VALUE_CAPS     pValueCaps = NULL;
	UINT                 bufferSize = 0;
	ULONG                usageLength, value;
	TCHAR                name[1024] = {0};
	UINT                 nameSize = 1024;
	RID_DEVICE_INFO      devInfo = {0};
	std::wstring         devName;
	USHORT               capsLength = 0;
	USAGE                usage[32] = {0};
	int                  numberOfButtons;

	GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_DEVICENAME, name, &nameSize);

	devName = name;
	std::transform(devName.begin(), devName.end(), devName.begin(), ::toupper);

	CHECK( GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_PREPARSEDDATA, NULL, &bufferSize) == 0 );
	CHECK( pPreparsedData = (PHIDP_PREPARSED_DATA)malloc(bufferSize) );
	CHECK( (int)GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_PREPARSEDDATA, pPreparsedData, &bufferSize) >= 0 );
	CHECK( HidP_GetCaps(pPreparsedData, &Caps) == HIDP_STATUS_SUCCESS );

	//Get pressed buttons
	CHECK( pButtonCaps = (PHIDP_BUTTON_CAPS)malloc(sizeof(HIDP_BUTTON_CAPS) * Caps.NumberInputButtonCaps) );
	//If fails, maybe wheel only has axes
	capsLength = Caps.NumberInputButtonCaps;
	HidP_GetButtonCaps(HidP_Input, pButtonCaps, &capsLength, pPreparsedData);

	numberOfButtons = pButtonCaps->Range.UsageMax - pButtonCaps->Range.UsageMin + 1;
	usageLength = countof(usage);//numberOfButtons;

	NTSTATUS stat;
	if((stat = HidP_GetUsages(
			HidP_Input, pButtonCaps->UsagePage, 0, usage, &usageLength, pPreparsedData,
			(PCHAR)pRawInput->data.hid.bRawData, pRawInput->data.hid.dwSizeHid)) == HIDP_STATUS_SUCCESS )
	{
		for(uint32_t i = 0; i < usageLength; i++)
		{
			uint16_t btn = usage[i] - pButtonCaps->Range.UsageMin;
		}
	}

	/// Get axes' values
	CHECK( pValueCaps = (PHIDP_VALUE_CAPS)malloc(sizeof(HIDP_VALUE_CAPS) * Caps.NumberInputValueCaps) );
	capsLength = Caps.NumberInputValueCaps;
	if(HidP_GetValueCaps(HidP_Input, pValueCaps, &capsLength, pPreparsedData) == HIDP_STATUS_SUCCESS )
	{
		for(USHORT i = 0; i < capsLength; i++)
		{
			if(HidP_GetUsageValue(
					HidP_Input, pValueCaps[i].UsagePage, 0,
					pValueCaps[i].Range.UsageMin, &value, pPreparsedData,
					(PCHAR)pRawInput->data.hid.bRawData, pRawInput->data.hid.dwSizeHid
				) != HIDP_STATUS_SUCCESS )
			{
				continue; // if here then maybe something is up with HIDP_CAPS.NumberInputValueCaps
			}

			switch(pValueCaps[i].Range.UsageMin)
			{
				case HID_USAGE_GENERIC_X: //0x30
				case HID_USAGE_GENERIC_Y:
				case HID_USAGE_GENERIC_Z:
				case HID_USAGE_GENERIC_RX:
				case HID_USAGE_GENERIC_RY:
				case HID_USAGE_GENERIC_RZ: //0x35
					//int axis = (value * 0x3FFF) / pValueCaps[i].LogicalMax;
					break;
				case HID_USAGE_GENERIC_HATSWITCH:
					//fprintf(stderr, "Hat: %02X\n", value);
					break;
			}
		}
	}

	Error:
	SAFE_FREE(pPreparsedData);
	SAFE_FREE(pButtonCaps);
	SAFE_FREE(pValueCaps);
}
static void ParseRawInput(PRAWINPUT pRawInput)
{
    //IwDebugTraceLinePrintf("%s(%d): Parsing raw input\n", __FUNCTION__, __LINE__);
    PHIDP_PREPARSED_DATA pPreparsedData;
    HIDP_CAPS            Caps;
    PHIDP_BUTTON_CAPS    pButtonCaps;
    PHIDP_VALUE_CAPS     pValueCaps;
    USHORT               capsLength;
    UINT                 bufferSize;
    HANDLE               hHeap;
    USAGE                usage[MAX_BUTTONS];
    ULONG                i, usageLength, value;

    pPreparsedData = NULL;
    pButtonCaps    = NULL;
    pValueCaps     = NULL;
    hHeap          = GetProcessHeap();

    //
    // Get the preparsed data block
    //

    CHECK( GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_PREPARSEDDATA, NULL, &bufferSize) == 0 );
    CHECK( pPreparsedData = (PHIDP_PREPARSED_DATA)HeapAlloc(hHeap, 0, bufferSize) );
    CHECK( (int)GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_PREPARSEDDATA, pPreparsedData, &bufferSize) >= 0 );

    //
    // Get the joystick's capabilities
    //

    // Button caps
    CHECK( HidP_GetCaps(pPreparsedData, &Caps) == HIDP_STATUS_SUCCESS )
        CHECK( pButtonCaps = (PHIDP_BUTTON_CAPS)HeapAlloc(hHeap, 0, sizeof(HIDP_BUTTON_CAPS) * Caps.NumberInputButtonCaps) );

    capsLength = Caps.NumberInputButtonCaps;
    CHECK( HidP_GetButtonCaps(HidP_Input, pButtonCaps, &capsLength, pPreparsedData) == HIDP_STATUS_SUCCESS )
        g_NumberOfButtons = pButtonCaps->Range.UsageMax - pButtonCaps->Range.UsageMin + 1;

    // Value caps
    CHECK( pValueCaps = (PHIDP_VALUE_CAPS)HeapAlloc(hHeap, 0, sizeof(HIDP_VALUE_CAPS) * Caps.NumberInputValueCaps) );
    capsLength = Caps.NumberInputValueCaps;
    CHECK( HidP_GetValueCaps(HidP_Input, pValueCaps, &capsLength, pPreparsedData) == HIDP_STATUS_SUCCESS )

    //
    // Get the pressed buttons
    //

    usageLength = g_NumberOfButtons;
    CHECK(
        HidP_GetUsages(
        HidP_Input, pButtonCaps->UsagePage, 0, usage, &usageLength, pPreparsedData,
        (PCHAR)pRawInput->data.hid.bRawData, pRawInput->data.hid.dwSizeHid
        ) == HIDP_STATUS_SUCCESS );

    ZeroMemory(bButtonStates, sizeof(bButtonStates));
    for(i = 0; i < usageLength; i++)
        bButtonStates[usage[i] - pButtonCaps->Range.UsageMin] = TRUE;

    //
    // Get the state of discrete-valued-controls
    //
//#define VALUES_DEBUG
#ifdef VALUES_DEBUG
    char str[512] = "";
#endif

    for(i = 0; i < Caps.NumberInputValueCaps; i++)
    {
        CHECK(
            HidP_GetUsageValue(
            HidP_Input, pValueCaps[i].UsagePage, 0, pValueCaps[i].Range.UsageMin, &value, pPreparsedData,
            (PCHAR)pRawInput->data.hid.bRawData, pRawInput->data.hid.dwSizeHid
            ) == HIDP_STATUS_SUCCESS );

        // NOTE: These values are only correct for the Xbox 360 controller 
        // and for the PS3 Controller (via MotioninJoy '360 Emulation' mode)
        switch(pValueCaps[i].Range.UsageMin)
        {
        case 0x30:	// X-axis (L-Stick Horizontal)
            lAxisX = (LONG)value;
            break;

        case 0x31:	// Y-axis (L-Stick Vertical)
            lAxisY = (LONG)value;
            break;

        case 0x32: // Z-axis (L-Trigger: 32K-65K, R-Trigger: 0K-32K)
            lAxisZ = (LONG)value;
            break;

        case 0x33: // U-axis (R-Stick Horizontal)
            lAxisU = (LONG)value;
            break;

        case 0x34: // R-axis (R-Stick Vertical)
            lAxisR = (LONG)value;
            break;

        // POV Hat Switch (DPAD:
        // 1: Up
        // 2: UP/RIGHT
        // 3: RIGHT
        // 4: RIGHT/DOWN
        // 5: DOWN
        // 6: DOWN/LEFT
        // 7: LEFT
        // 8: LEFT/UP
        case 0x39:
            lDPad = (LONG)value;
            break;
        }

#ifdef VALUES_DEBUG
        char s[128];
        _snprintf(s, 128, "[Usage=0x%2X, Val=%4u] ", pValueCaps[i].Range.UsageMin, value);
        strcat(str, s);
#endif
    }


    //
    // Clean up
    //

Error:
    SAFE_FREE(pPreparsedData);
    SAFE_FREE(pButtonCaps);
    SAFE_FREE(pValueCaps);
}