Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411423 Posts in 69363 Topics- by 58416 Members - Latest Member: JamesAGreen

April 18, 2024, 10:51:30 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Detecting the 360 controller's Guide button in Windows [SOLVED]
Pages: [1]
Print
Author Topic: Detecting the 360 controller's Guide button in Windows [SOLVED]  (Read 13276 times)
Dataflashsabot
Level 2
**


View Profile
« on: June 21, 2012, 11:15:25 AM »

This is not officially supposed to be possible, and XInput certainly doesn't define any way to do it. But GFWL games (such as GTA IV) use it, so clearly it's possible somehow. I'm making a small library to simplify using the 360 controller, and I'd like it to be able to see the guide button; anyone here found any clever hack to use it?
« Last Edit: February 08, 2013, 11:19:02 AM by Dataflashsabot » Logged
VortexCortex
Level 2
**


Engram Architect


View Profile WWW
« Reply #1 on: June 22, 2012, 12:05:26 PM »

I'm still dreading porting input beyond keyboard and mouse to Windows.

On Linux, I use xboxdrv to support the Xbox & Xbox360 controllers with userland code (no kernel driver required). It makes use of libusb...

I haven't figured out if it's worth it or even possible to port xboxdrv to Windows on top of libusb-win32, but I'm considering exploring it as an option rather than giving up the silver button.

I'll likely just go with XInput and lose the silver button.  Sorry I can't be more help, haven't crossed this bridge yet.

Logged

ThemsAllTook
Administrator
Level 10
******



View Profile WWW
« Reply #2 on: June 22, 2012, 12:20:30 PM »

I wrote a gamepad library that uses the older joystick API, and it doesn't give me a way to detect presses on that button. If XInput doesn't give it to you either, I'm not sure what you'd need to do for it. Presumably there's some way to drop down a level and get raw HID data from the USB driver, but that sounds potentially quite painful. Let us know if you figure out a way to do it though!
Logged

Kaelan
Level 1
*


Malcontent


View Profile WWW
« Reply #3 on: June 23, 2012, 02:45:41 AM »

http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinput_gamepad%28v=vs.85%29.aspx doesn't list the xbox button as one of the standard 'buttons' or other pieces of data returned by the XINPUT state, but it's possible that it's encoded into the state as an undocumented enumeration value. Have you tried logging the state when the button is held?

If you're using XNA, the xinput state is in a hidden field of GamePadState.

It's also possible that presses on the xbox button are treated as keypresses (like a keyboard key); maybe you have to fetch them with http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputgetkeystroke%28v=vs.85%29.aspx ?
Logged

Dataflashsabot
Level 2
**


View Profile
« Reply #4 on: June 23, 2012, 02:59:01 AM »

http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinput_gamepad%28v=vs.85%29.aspx doesn't list the xbox button as one of the standard 'buttons' or other pieces of data returned by the XINPUT state, but it's possible that it's encoded into the state as an undocumented enumeration value. Have you tried logging the state when the button is held?

If you're using XNA, the xinput state is in a hidden field of GamePadState.

It's also possible that presses on the xbox button are treated as keypresses (like a keyboard key); maybe you have to fetch them with http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputgetkeystroke%28v=vs.85%29.aspx ?
Tried both already, sorry...
Logged
Dataflashsabot
Level 2
**


View Profile
« Reply #5 on: February 07, 2013, 12:56:01 PM »

Just gonna bump this 'cos I found out and people might be interested.

Use LoadLibrary to load xinput1_3.dll from the system directory and use GetProcAddress on the resultant handle to load a function from ordinal 100 matching this signature:
Code:
__stdcall int secret_get_gamepad (int, XINPUT_GAMEPAD_SECRET*);

function pointer syntax:
Code:
int(__stdcall *secret_get_gamepad) (int, XINPUT_GAMEPAD_SECRET*);

The int is the controller index.
The struct it outputs to (I called it XINPUT_GAMEPAD_SECRET) is very similar to but different from XINPUT_GAMEPAD and looks like this:


Code:
typedef struct 
{
    unsigned long eventCount;
    WORD                                wButtons;
    BYTE                                bLeftTrigger;
    BYTE                                bRightTrigger;
    SHORT                               sThumbLX;
    SHORT                               sThumbLY;
    SHORT                               sThumbRX;
    SHORT                               sThumbRY;
} XINPUT_GAMEPAD_SECRET;


Create such a struct and pass its address to secret_get_gamepad. It returns 0 on success or 1167 on failure.

Then bitiwse AND wButtons against 0x00400 to see if the guide button is down.

With thanks to this code on some guy's github: https://github.com/DieKatzchen/GuideButtonPoller/blob/master/GuideButtonPoller.cpp
No clue how he figured it out.

I made a Game Maker DLL to do this: http://gmc.yoyogames.com/index.php?showtopic=570472&st=0&p=4210058&#entry4210058 (source also available).
Logged
ThemsAllTook
Administrator
Level 10
******



View Profile WWW
« Reply #6 on: February 07, 2013, 01:22:01 PM »

Sneaky, nice find!
Logged

Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW
« Reply #7 on: February 07, 2013, 06:48:05 PM »

That button does show up when using the raw input API, in that it triggers WM_INPUT messages.  My code isn't picking it up as a button, though.  I'm not sure what the API thinks it actually is.

Of course, my code could also be wrong.  It's rather sketchy at the moment.
Logged



What would John Carmack do?
J. Kyle Pittman
Level 6
*


PostCount++;


View Profile WWW
« Reply #8 on: February 07, 2013, 06:56:28 PM »

Awesome find, Dataflashsabot! I had been wondering about this for a while.

That button does show up when using the raw input API, in that it triggers WM_INPUT messages.  My code isn't picking it up as a button, though.  I'm not sure what the API thinks it actually is.

Of course, my code could also be wrong.  It's rather sketchy at the moment.

I was seeing the same thing last time I looked into this. A friend of mine suggested that an easy way to trap it would be to watch for WM_INPUT events in which no buttons are flagged as being pressed. Not totally convinced it couldn't ever throw any false positives, but it could be an easy workaround.
Logged

Dataflashsabot
Level 2
**


View Profile
« Reply #9 on: February 08, 2013, 07:44:48 AM »

Here's some complete C example code. You don't need to link with XInput or anything, it just uses the WinAPI to load the function at runtime.
Code:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>

static const int guide_button_value = 0x0400;

/* the secret function outputs a different struct than the official GetState. */
typedef struct
{
    unsigned long eventCount;
    WORD                                wButtons;
    BYTE                                bLeftTrigger;
    BYTE                                bRightTrigger;
    SHORT                               sThumbLX;
    SHORT                               sThumbLY;
    SHORT                               sThumbRX;
    SHORT                               sThumbRY;
} XINPUT_GAMEPAD_SECRET;

// returns 0 on success, 1167 on not connected. Might be others.
int(__stdcall *secret_get_gamepad) (int, XINPUT_GAMEPAD_SECRET*); // function pointer to secret (guide compatible) getstate */

int main(int argc, char** argv)
{
TCHAR xinput_dll_path[MAX_PATH];
GetSystemDirectory(xinput_dll_path, sizeof(xinput_dll_path));
strcat(xinput_dll_path, "\\xinput1_3.dll");
HINSTANCE xinput_dll = LoadLibrary(xinput_dll_path);
secret_get_gamepad = GetProcAddress(xinput_dll, (LPCSTR)100); // load ordinal 100

XINPUT_GAMEPAD_SECRET pad1;

if (secret_get_gamepad(0, &pad1) != 0)
{
printf("Error, make sure your player 1 pad is connected.\n");
return -1;
}

for(;;) // forever
{
secret_get_gamepad(0, &pad1);
if (pad1.wButtons & guide_button_value)
{
printf("Guide button is down.\n");
}
Sleep(33);
}

// you should probably clean up by unloading the DLL.
return 0;
}

Logged
ircluzar
TIGBaby
*


View Profile
« Reply #10 on: January 10, 2015, 03:49:27 PM »

Hello !

Here's a ported version to C# on how to detect the Guide Button

Code:
        [DllImport("xinput1_3.dll", EntryPoint = "#100")]
        static extern int secret_get_gamepad(int playerIndex, out XINPUT_GAMEPAD_SECRET struc);

        public struct XINPUT_GAMEPAD_SECRET
        {
                public UInt32 eventCount;
                public ushort wButtons;
                public Byte bLeftTrigger;
                public Byte bRightTrigger;
                public short sThumbLX;
                public short sThumbLY;
                public short sThumbRX;
                public short sThumbRY;
        }
       
        public XINPUT_GAMEPAD_SECRET xgs;

        bool testHomeButton()
        {
            int stat;
            bool value;


            for (int i = 0; i < 4; i++)
            {
                stat = secret_get_gamepad(0, out xgs);

                if (stat != 0)
                    continue;

                value = ((xgs.wButtons & 0x0400) != 0);

                if (value)
                    return true;
            }
            return false;
        }
Logged
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic