Android joystick mapping bug after SDL update to 2.0.8

SDL doesn’t detect DPAD or axis for gmepads for android after update from 2.0.4 to 2.0.8
all buttons seem ok but nod d-pad or axis…
can you help me?

SDL_JoystickGetButton is doing nothing for me on Android with SDL2 2.0.8.

I get DPAD state with SDL_JOYHATMOTION event doing checks like (e->jhat.value & SDL_HAT_UP)

(I get the other button events with SDL_JOYBUTTONDOWN and SDL_JOYBUTTONUP).

Mee too I use (e->jhat.value & SDL_HAT_UP) to get value.
DPAD doesn’t show button names (show unknown) and dpad doesn’t work.
using SDL_GetScancodeName(keycode)…
Other buttons are ok…
Is it a bug?

Yes, the Android joystick device detection is flawed. If you look at the java code, it tries to identify different devices: mouse, keyboard, dpad, buttons, game controllers. And then allocate then devices to different handlers. I’ve found keyboards are coming up listed as joysticks. It’s been changed a lot recently, but still not working how it should.

Another thing, loading gamecontrollerdb.txt on Android ( https://github.com/gabomdq/SDL_GameControllerDB/blob/master/gamecontrollerdb.txt ) doesn’t work, but the way it doesn’t work is interesting.

On Windows that file will load 108 mappings using SDL_GameControllerAddMappingsFromFile (path_to_file). On Android, it will load 1 mapping, despite there being 8 mappings in the text file if you look at it. Additionally, adding or removing joystick/gamepad doesn’t trigger an event like SDL_CONTROLLERDEVICEADDED or SDL_CONTROLLERDEVICEREMOVED.

I do have every single button and every stick on game controllers working in Android including DPAD. for game controllers intended for Android and for several different gamepads, but the code that works on (for example) Windows doesn’t work on Android … I just have to go about it limiting the code to the functions and methods that do work on Android, which involved some experimentation.

Version tmp here:
https://www.libsdl.org/tmp/SDL/
Works bit better.
Some news?
Is This tmp repository the last updated repository?

I’d test it, but I’m not sure what to do with that because it is a folder with 2800 separate files.

Is there a .zip to download or am I missing something obvious?

If that is the same as 11953 I’ve already tried that and it reports false for Android controllers with SDL_IsGameController().

(Thread where I tried 11953 Android GamePad vs. Desktop (Assertions) )

I’ve just tested (SDL2.0.8) my Android build and the reverse is happening. Using a generic Chinese game controller and an Xbox 360 one using both the Joystick and Controller interface: Axis and HATs are working, but no buttons. This used to work in 2.0.5.

White_Dragon, can you describe what changes you made so we can make them to our local builds, rather than trying to set up from scratch from your .zip? Not able to integrate it into my project that way.

Sure!

CATCHING D-PAD:

	SDL_Event ev;
	while(SDL_PollEvent(&ev))
	{
		switch(ev.type)
		{
  	case SDL_JOYHATMOTION:
  		for(i=0; i<JOY_LIST_TOTAL; i++)
  		{
  			if(ev.jhat.which == i)
  			{
  				int hatfirst = 1 + i * JOY_MAX_INPUTS + joysticks[i].NumButtons + 2*joysticks[i].NumAxes + 4*ev.jhat.hat;
  				x = (joysticks[i].Hats >> (4*ev.jhat.hat)) & 0x0F; // hat's previous state
  				if(ev.jhat.value & SDL_HAT_UP && !(x & SDL_HAT_UP))			lastjoy = hatfirst;
  				if(ev.jhat.value & SDL_HAT_RIGHT && !(x & SDL_HAT_RIGHT))	lastjoy = hatfirst + 1;
  				if(ev.jhat.value & SDL_HAT_DOWN && !(x & SDL_HAT_DOWN))		lastjoy = hatfirst + 2;
  				if(ev.jhat.value & SDL_HAT_LEFT && !(x & SDL_HAT_LEFT))		lastjoy = hatfirst + 3;
  				//if(lastjoy) fprintf(stderr, "SDL_JOYHATMOTION - Joystick %i Hat %i (Index %i)\n", i, ev.jhat.hat, lastjoy);
  			}
  		}
  		break;
          ...

MAPPING:

  // new PC joystick code - forget about SDL joystick events, just do a state check
  SDL_JoystickUpdate();
  for(i=0; i<JOY_LIST_TOTAL; i++)
  {
  	// reset state
  	joysticks[i].Axes = joysticks[i].Hats = joysticks[i].Buttons = 0;

  	// check buttons
  	for(j=0; j<joysticks[i].NumButtons; j++)
  		joysticks[i].Buttons |= SDL_JoystickGetButton(joystick[i], j) << j;

  	// check axes
  	for(j=0; j<joysticks[i].NumAxes; j++)
  	{
  		axis = SDL_JoystickGetAxis(joystick[i], j);
  		if(axis < -7000)  { joysticks[i].Axes |= 1 << (j*2); }
  		if(axis > +7000)  { joysticks[i].Axes |= 2 << (j*2); }
  	}

  	// check hats
  	for(j=0; j<joysticks[i].NumHats; j++)
  		joysticks[i].Hats |= SDL_JoystickGetHat(joystick[i], j) << (j*4);

  	// combine axis, hat, and button state into a single value
  	joysticks[i].Data = joysticks[i].Buttons;
  	joysticks[i].Data |= joysticks[i].Axes << joysticks[i].NumButtons;
  	joysticks[i].Data |= joysticks[i].Hats << (joysticks[i].NumButtons + 2*joysticks[i].NumAxes);
  }

SCAN:

void joystick_scan(int scan)
{
int i, j, k;
if(!scan) return;
numjoy = SDL_NumJoysticks();
if(!numjoy && scan != 2)
{
printf(“No Joystick(s) Found!\n”);
return;
}
else
{
printf("\n%d joystick(s) found!\n", numjoy);
}
for(i=0, k=0; i<numjoy; i++, k+=JOY_MAX_INPUTS)
{
joystick[i] = SDL_JoystickOpen(i);
joysticks[i].NumHats = SDL_JoystickNumHats(joystick[i]);
joysticks[i].NumAxes = SDL_JoystickNumAxes(joystick[i]);
joysticks[i].NumButtons = SDL_JoystickNumButtons(joystick[i]);

  joysticks[i].Name = SDL_JoystickName(i);

1 Like

Tested latest SDL Mercurial and it works a little better!

SDL gamepads source:

You can see the full project here:

Ant then in SDLActivity.java

Remap button like these:

 // Key events
@Override
public boolean onKey(View  v, int keyCode, KeyEvent event) {
    //uTunnels: remap keys, for sdl doesn't support them
    switch(keyCode)
    {
        /*
        case KeyEvent.KEYCODE_BUTTON_1://	Key code constant: Generic Game Pad Button #1.
            keyCode=KeyEvent.KEYCODE_1; break;
        case KeyEvent.KEYCODE_BUTTON_10: //key code constant: Generic Game Pad Button #10.
            keyCode=KeyEvent.KEYCODE_2; break;
        case KeyEvent.KEYCODE_BUTTON_11: //key code constant: Generic Game Pad Button #11.
            keyCode=KeyEvent.KEYCODE_3; break;
        case KeyEvent.KEYCODE_BUTTON_12: //key code constant: Generic Game Pad Button #12.
            keyCode=KeyEvent.KEYCODE_4; break;
        case KeyEvent.KEYCODE_BUTTON_13: //key code constant: Generic Game Pad Button #13.
            keyCode=KeyEvent.KEYCODE_5; break;
        case KeyEvent.KEYCODE_BUTTON_14: //key code constant: Generic Game Pad Button #14.
            keyCode=KeyEvent.KEYCODE_6; break;
        case KeyEvent.KEYCODE_BUTTON_15: //key code constant: Generic Game Pad Button #15.
            keyCode=KeyEvent.KEYCODE_7; break;
        case KeyEvent.KEYCODE_BUTTON_16: //key code constant: Generic Game Pad Button #16.
            keyCode=KeyEvent.KEYCODE_8; break;
        case KeyEvent.KEYCODE_BUTTON_2: //key code constant: Generic Game Pad Button #2.
            keyCode=KeyEvent.KEYCODE_9; break;
        case KeyEvent.KEYCODE_BUTTON_3: //key code constant: Generic Game Pad Button #3.
            keyCode=KeyEvent.KEYCODE_0; break;
        case KeyEvent.KEYCODE_BUTTON_4: //key code constant: Generic Game Pad Button #4.
            keyCode=KeyEvent.KEYCODE_A; break;
        case KeyEvent.KEYCODE_BUTTON_5: //key code constant: Generic Game Pad Button #5.
            keyCode=KeyEvent.KEYCODE_B; break;
        case KeyEvent.KEYCODE_BUTTON_6: //key code constant: Generic Game Pad Button #6.
            keyCode=KeyEvent.KEYCODE_C; break;
        case KeyEvent.KEYCODE_BUTTON_7: //key code constant: Generic Game Pad Button #7.
            keyCode=KeyEvent.KEYCODE_D; break;
        case KeyEvent.KEYCODE_BUTTON_8: //key code constant: Generic Game Pad Button #8.
            keyCode=KeyEvent.KEYCODE_E; break;
        case KeyEvent.KEYCODE_BUTTON_9: //key code constant: Generic Game Pad Button #9.
            keyCode=KeyEvent.KEYCODE_F; break;*/
        case KeyEvent.KEYCODE_BUTTON_A: //key code constant: A Button key.
            keyCode=KeyEvent.KEYCODE_G; break;
        case KeyEvent.KEYCODE_BUTTON_B: //key code constant: B Button key.
            keyCode=KeyEvent.KEYCODE_H; break;
        case KeyEvent.KEYCODE_BUTTON_C: //key code constant: C Button key.
            keyCode=KeyEvent.KEYCODE_I; break;
        case KeyEvent.KEYCODE_BUTTON_L1: //key code constant: L1 Button key.
            keyCode=KeyEvent.KEYCODE_J; break;
        case KeyEvent.KEYCODE_BUTTON_L2: //key code constant: L2 Button key.
            keyCode=KeyEvent.KEYCODE_K; break;
        case KeyEvent.KEYCODE_BUTTON_MODE: //key code constant: Mode Button key.
            keyCode=KeyEvent.KEYCODE_L; break;
        case KeyEvent.KEYCODE_BUTTON_R1: //key code constant: R1 Button key.
            keyCode=KeyEvent.KEYCODE_M; break;
        case KeyEvent.KEYCODE_BUTTON_R2: //key code constant: R2 Button key.
            keyCode=KeyEvent.KEYCODE_N; break;
        case KeyEvent.KEYCODE_BUTTON_SELECT: //key code constant: Select Button key.
            keyCode=KeyEvent.KEYCODE_O; break;
        case KeyEvent.KEYCODE_BUTTON_START: //key code constant: Start Button key.
            keyCode=KeyEvent.KEYCODE_P; break;
        case KeyEvent.KEYCODE_BUTTON_THUMBL: //key code constant: Left Thumb Button key.
            keyCode=KeyEvent.KEYCODE_Q; break;
        case KeyEvent.KEYCODE_BUTTON_THUMBR: //key code constant: Right Thumb Button key.
            keyCode=KeyEvent.KEYCODE_R; break;
        case KeyEvent.KEYCODE_BUTTON_X: //key code constant: X Button key.
            keyCode=KeyEvent.KEYCODE_S; break;
        case KeyEvent.KEYCODE_BUTTON_Y: //key code constant: Y Button key.
            keyCode=KeyEvent.KEYCODE_T; break;
        case KeyEvent.KEYCODE_BUTTON_Z: //key code constant: Z Button key.
            keyCode=KeyEvent.KEYCODE_U; break;
    }

And how do your buttons work?
About you, why dpad doesn’t work in my project?

I confirm that for many joysticks there is a bug for:
SDL_JoystickNumHats() that return 0 hats
and that SDL_JoystickGetHat() that it doesn’t work…
Also for some joysticks no response from axis and/or buttons…