Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic USB controller and Logitech Precision controller not working #137

Open
1 of 7 tasks
Abasz opened this issue Oct 26, 2023 · 28 comments
Open
1 of 7 tasks

Generic USB controller and Logitech Precision controller not working #137

Abasz opened this issue Oct 26, 2023 · 28 comments
Assignees

Comments

@Abasz
Copy link

Abasz commented Oct 26, 2023

Bug report

Describe the bug

I have a Nvidia Shield (the older one not the new) running SW9.1.1 and I have been trying to set up some joysticks to work with the retroplayer. I was not really able to make it work. I came across this thread on kodi forum: https://forum.kodi.tv/showthread.php?tid=373412 while searching for solution.

The games works with the Shield Controller if that is the only one connected (apart from the virtual-search and the shiled-ask-remote). But as soon as I attach one of the USB joysticks everything stops working...

All the joysticks work solely as kodi remote controller (i.e. any button press is an enter). In the players view I can see the following:
20231026_230040
20231026_230314

This is the only constellation that works
20231026_233958

I think if I was able to change the controller assignment to the ports it could be a solution, as when the Shield Controller works it is assigned to Port 1, but any other joysitck is assigned to none. 

Expected Behavior

I expect controllers to work

Actual Behavior

Joysticks are not recognised and only act as general kodi remote

Debuglog

The debuglog can be found here:
logs: https://paste.kodi.tv/ubicejaquf.kodi

Your Environment

Used Operating system:

  • Android

  • iOS

  • tvOS

  • Linux

  • OSX

  • Windows

  • Windows UWP

  • Operating system version/name: 9.1.1 Shield Experience

  • Kodi version: kodi-20231024-ef080027-retroplayer-21beta1-arm64-v8a.apk

note: Once the issue is made we require you to update it with new information or Kodi versions should that be required.
Team Kodi will consider your problem report however, we will not make any promises the problem will be solved.

@garbear garbear self-assigned this Oct 27, 2023
@garbear
Copy link
Owner

garbear commented Nov 18, 2023

Sorry, I forgot about this issue. I can help get controllers to work. You can see in the new "Player Viewer" dialog how Kodi assigns android controllers, in this case imperfectly.

I was working on a "Player Manager" that lets you actually change controller ports, but I decided to merge the Viewer part so at least we can see what's going wrong. Until a full-blown player manager, Kodi just needs to be smart enough to assign ports automatically. Currently we sort joysticks in order of last button pressed (reset every time Kodi is restarted).

Can you think of a better way to automatically assign controllers? The idea is that false controllers like "virtual-search" never send button presses so are assigned last, but maybe restarting Kodi clears the state and we should store controller activity in an XML file between restarts.

The ultimate solution is finishing the "Player Manager", of course, but I don't have time currently, and I figured the hundred hours I put in so far could at least be somewhat valuable as a "Player Viewer" in the meantime. It'll be some time before I can work on finishing the "Manager" part so I'm open to ideas on quick fixes in the meantime.

@Abasz
Copy link
Author

Abasz commented Nov 19, 2023

Hi thanks for your help, I appreciate the work you have done. I have been thinking about the best quick and dirty fix for assigning the controllers and it is rather difficult as it needs to be balanced between allowing the user control and excluding false positives, while there is need to differentiate between Bluetooth controllers and USB controllers.

I think a good approach can be if ports are assigned based on the last connected and controllers are shifted when a new one is connected, i.e. the last connected controller is assigned to port 1 and when a new one is connected everything is shifted with one port up.

This could have the benefit of providing the ability to clear out a controller from a port that is inappropriately assigned (compared to your proposed method when only restart can clear it out) as well as assignment is more explicit and tied to a specific user action. This could work both USB and Bluetooth as both can be connected/disconnected. Of course in this case saving to an xml is not really feasible as it would make handling the reloading and detection of connect/disconnect cycle rather difficult (in such case what would "last connected" mean?, how one handles already connected but then a new one is connected etc.). So I would not bother with this as this solution is temporary.

The above is based on the assumption that virtual search and all these are never disconnected.

@Abasz
Copy link
Author

Abasz commented Nov 19, 2023

I was working on a "Player Manager" that lets you actually change controller ports, but I decided to merge the Viewer part so at least we can see what's going wrong. Until a full-blown player manager, Kodi just needs to be smart enough to assign ports automatically. Currently we sort joysticks in order of last button pressed (reset every time Kodi is restarted).

Which version handles controllers this way? I am asking as in 20.2 I used to test this is not the behavior. Technically speaking last button press should work too, though if the user is unhappy with the layout only a restart can clear it out that is rather cumbersome.

thanks

@Abasz
Copy link
Author

Abasz commented Dec 11, 2023

I've tested the 2023-12-05 release and now things seems even wors as the controllers do not show up in the player view any more (the virtual ones are gone that is good, but also the normal controllers). The strange part is that I can still control kodi with the D pad and hit enter (back does not work, only the enter).

@Abasz
Copy link
Author

Abasz commented Jan 22, 2024

I have tested the new 16 January 2024 version (21 beta 2) and the issue changed slightly. Now I can see the controllers correctly getting mapped in the Players view (I can even see the controller icon flashing when pressing a button).

The only issue now, is that I am not able to map the buttons. The D-pad can be mapped it works, but not the other buttons. Every button is treated as confirm (enter). It almost seems that kodi does not differentiate between the buttons, so when I try to map a new button it treats it as an already mapped button (ignoring the push).

@garbear
Copy link
Owner

garbear commented Jan 28, 2024

@Abasz Sorry for not getting to this for a while, but now that others are having issues (xbmc#24502) with controllers on v20.3, I want to figure out the controller scourge on Android once and for all.

The new release of peripheral.joystick (v21.1.11) should help with the new problem you reported last week. Then if controllers are still broke (I suspect this may still be the case) I'll hunt down the problems and get them fixed.

@Abasz
Copy link
Author

Abasz commented Jan 28, 2024

I have peripheral.joystick v21.2 as far I was able to check.
kodi.log
I created a log of when I was trying to the button mapping may be that helps. The part where I try to map starts here: 2024-01-28 08:31:03.843 T:29439.

I've read in one of the issue reports the same issue I have, namely that when I try to map a button the first one works, but then the rest is ignored. There is a log that confirms this: 2024-01-28 08:31:19.709 T:29438

Hope the above helps

@garbear
Copy link
Owner

garbear commented Jan 28, 2024

Looking at the log, I see that both buttons and key presses are being sent:

debug <general>: FEATURE [ right ] on game.controller.default pressed (ignored)
debug <general>: FEATURE [ right ] on game.controller.default pressed (handled)
debug <general>: FEATURE [ right ] on game.controller.default released
 info <general>: Skipped 1 duplicate messages..
debug <general>: FEATURE [ left ] on game.controller.default pressed (ignored)
debug <general>: FEATURE [ left ] on game.controller.default pressed (handled)
debug <general>: FEATURE [ left ] on game.controller.default released
 info <general>: Skipped 1 duplicate messages..
debug <general>: CAndroidKey: key down (dev: -1; src: 33554433; code: 20; repeat: 0; flags: 0x8; alt: no; shift: no; sym: no)
debug <general>: Keyboard: scancode: 0x14, sym: 0x112, unicode: 0x00, modifier: 0x0
debug <general>: HandleKey: down (0xf081) pressed, window 10000, action is Down

This is the root of the problem. See what happens when you try to map "a":

debug <general>: game.controller.snes: Waiting for input for feature "a"
debug <general>: CAndroidKey: key ignored (code: 190)
debug <general>: CAndroidKey: key down (dev: 132; src: 257; code: 23; repeat: 0; flags: 0x8; alt: no; shift: no; sym: no)
debug <general>: Keyboard: scancode: 0x17, sym: 0x0d, unicode: 0x00, modifier: 0x0
debug <general>: game.controller.snes: mapping feature "a" for device keyboard
debug <general>: game.controller.snes: Waiting for input for feature "b"
debug <general>: CAndroidKey: key ignored (code: 190)
debug <general>: CAndroidKey: key up (dev: 132; src: 257; code: 23; repeat: 0; flags: 0x8; alt: no; shift: no; sym: no)
debug <general>: Keyboard: scancode: 0x17, sym: 0x0d, unicode: 0x00, modifier: 0x0

Android is sending keyboard presses instead of button presses. I'm not sure why. It doesn't do this when I test Android.

We need to solve this problem in order to fix joysticks. I don't know how, but I'll keep testing on Android to see if I can reproduce or find a fix. If not we'll need an Android developer to help out.

@Abasz
Copy link
Author

Abasz commented Jan 28, 2024

Just to add some things: I am using Nvidia Shield latest firmware:

20240128_120431

I tested with the controller with an app (Gamecontroller tester or something) and it detects buttons properly

20240128_120527

So I am not 100% sure if this indeed and android matter. It seems to me that android can send / detect the buttons properly.

@garbear
Copy link
Owner

garbear commented Jan 29, 2024

@Abasz Can you test my latest 2024-01-29 build with the fixes included from xbmc#24604?

@Abasz
Copy link
Author

Abasz commented Jan 29, 2024

I tested the new build (Joystick is 21.2 and the issue is the same. I attached the log
kodi.log

So basically I can map the D pad and one button to any of the SNES controller buttons.

The interesting thing I noticed is that when I open the players view I can see the keyboard and my controller and when I press the D pad button on the controller the the controller lights up blue. But when I press any other button the keyboard lights up.
20240129_172150

Also for the sake of testing I downloaded RetroArch that correctly recognizes the buttons but uses slightly different button numbers:

20240129_173057

Now when I look at the logs for the part where I try to do the mapping it shows that the code 189 for instance gets ignored and then remapped to keyboard as you mentioned,

2024-01-29 17:14:14.936 T:3266    debug <general>: CAndroidKey: key ignored (code: 189)
2024-01-29 17:14:14.939 T:3266    debug <general>: CAndroidKey: key down (dev: 140; src: 257; code: 23; repeat: 0; flags: 0x8; alt: no; shift: no; sym: no)

BUT I dont think it is not android that is sending keyboard codee. The machine is able to pick up the right controller key code, it sends that correct code (retorArch can pick this up) and then Kodi (Kodi android may be) ignores and remaps that to keyboard code 23. And it does this for all the controller buttons, so from Kodi's perspective I am pushing the same button every time.

I wonder if changing the driver from linux to like Udev in the joystick setting would make a difference?

Let me know how I could hep further.

@garbear
Copy link
Owner

garbear commented Jan 30, 2024

The interesting thing I noticed is that when I open the players view I can see the keyboard and my controller and when I press the D pad button on the controller the the controller lights up blue. But when I press any other button the keyboard lights up.

Did you find this new window valuable for debugging? I figured that by showing the input in realtime, it would show the user where input was being dropped. Now on to the fixing it part :)

In your log I see the complete definition of your controller, as seen by Android:

debug <general>: CPeripheralBusAndroid: Device discovered:
debug <general>:   Name: "Logitech Logitech(R) Precision(TM) Gamepad"
debug <general>:     ID: 140
debug <general>:     Controller number: 0
debug <general>:     Descriptor: "4704e7c96f110c..."
debug <general>:     Product ID: C21A
debug <general>:     Vendor ID: 046D
debug <general>:     Has microphone: false
debug <general>:     Is virtual: false
debug <general>:     Source flags: 0x1000111
debug <general>:     Has source: SOURCE_JOYSTICK (0x1000010)
debug <general>:     Has source: SOURCE_KEYBOARD (0x000101)
debug <general>:     Has key: AKEYCODE_BUTTON_1 (188)
debug <general>:     Has key: AKEYCODE_BUTTON_2 (189)
debug <general>:     Has key: AKEYCODE_BUTTON_3 (190)
debug <general>:     Has key: AKEYCODE_BUTTON_4 (191)
debug <general>:     Has key: AKEYCODE_BUTTON_5 (192)
debug <general>:     Has key: AKEYCODE_BUTTON_6 (193)
debug <general>:     Has key: AKEYCODE_BUTTON_7 (194)
debug <general>:     Has key: AKEYCODE_BUTTON_8 (195)
debug <general>:     Has key: AKEYCODE_BUTTON_9 (196)
debug <general>:     Has key: AKEYCODE_BUTTON_10 (197)
debug <general>:     Has axis: AMOTION_EVENT_AXIS_X (0)
debug <general>:       Endpoints: [-1.000000, 1.000000]
debug <general>:       Center: 0.117647
debug <general>:       Fuzz: 0.000000
debug <general>:     Has axis: AMOTION_EVENT_AXIS_Y (1)
debug <general>:       Endpoints: [-1.000000, 1.000000]
debug <general>:       Center: 0.117647
debug <general>:       Fuzz: 0.000000
 info <general>: CPeripheralBusAndroid: added input device

The controller doesn't work in v20.2 because the keycodes used are "generic" button keycodes (e.g. AKEYCODE_BUTTON_1) instead of the A/B/X/Y/etc buttons used by most controllers, and we only detected the mapped button keycodes.

Android is in charge of providing the A/B/X/Y/etc button using its internal buttonmaps. Google has currated a shitload of controllers, but they can't map everyone. So when they don't have an internal buttonmap for a controller, it uses the generic button keycodes.

In xbmc#24604 I added these generic button keycodes to the list of buttons we look for. Can you try clearing all your buttonmaps, restarting Kodi, and then mapping this controller in the UI?

Looking in the log during button mapping, I see:

debug <general>: game.controller.snes: Waiting for input for feature "a"
debug <general>: CAndroidKey: key ignored (code: 190)
debug <general>: CAndroidKey: key down (dev: 140; src: 257; code: 23; repeat: 0; flags: 0x8; alt: no; shift: no; sym: no)
debug <general>: Keyboard: scancode: 0x17, sym: 0x0d, unicode: 0x00, modifier: 0x0
debug <general>: game.controller.snes: mapping feature "a" for device keyboard to "key enter"

Clearly input for AKEYCODE_BUTTON_3 (190) is getting dropped before it hit the button mapper. In fact, I fixed this exact problem for PS4 triggers in xbmc#24604 - once it stopped dropping input they could be mapped, and then they could be used for games.

The solution is to walk through the code, find where the input is dropped, and fix it. As I don't have a controller with generic button keycodes like AKEYCODE_BUTTON_3, I can't locate which return false; is being hit. Are you able to debug at the source level?

@garbear
Copy link
Owner

garbear commented Jan 30, 2024

There's one more debugging tool we have at our disposal. Can you try the "Ignore Input" dialog? Don't confirm any input, but it will show you in realtime which buttons Kodi sees.

@Abasz
Copy link
Author

Abasz commented Jan 30, 2024

I did a full clean of Kodi and tride. Please find attach the log. It is the same, no improvements.
kodi.log

There's one more debugging tool we have at our disposal. Can you try the "Ignore Input" dialog? Don't confirm any input, but it will show you in realtime which buttons Kodi sees.

The log includes this scenario, I am not sure if it provides more information than what

The solution is to walk through the code, find where the input is dropped, and fix it. As I don't have a controller with generic button keycodes like AKEYCODE_BUTTON_3, I can't locate which return false; is being hit. Are you able to debug at the source level?

I checked the how to compile for android page and, lets say I dont have experience with compiling and debugging android especially not sure how to run it with the debugger on the shield. I can read the source code and can edit that is ok. I will try to compile for my self and add custom string debug messages so it is added to put those to the debug log file and compile. Not the most efficient way but for limited purposes can work.

Also as part of me going through the code I have been trying to identify the part of the code that gets triggered based on the log messages and I think its might be here: https://github.com/xbmc/xbmc/blob/9a87e4d657d0f39559f56b567db7c6f59492db19/xbmc/platform/android/activity/AndroidKey.cpp#L239

This log gets triggered repeatedly and the only part in the code that has this is the above line.
2024-01-30 09:26:17.335 T:19913 debug <general>: CAndroidKey: key ignored (code: 189)

Also, by looking at the code, would it be possible that since the keyMap array in this file does not include AKEYCODE_BUTTON_10 (or any of these numbers) the button gets ignored and this line uint16_t sym = XBMCK_UNKNOWN; keeps the ˙sym` variable XBMCK_UNKNOWN and we get returned false?

The other keys in the AndroidJoystickTranslator.cpp seems to be present (not all of course).

@garbear
Copy link
Owner

garbear commented Jan 30, 2024

From the log, I can see that the axes are mapped correctly, but the buttons with generic button keycodes are not, indeed the same result as before:

debug <general>: game.controller.snes: Waiting for input for feature "up"
debug <general>: Normal axis detected on axis 1
debug <general>: game.controller.snes: mapping feature "up" for device android/inputdevice/151 to "semiaxis -1"
debug <general>: game.controller.snes: Waiting for input for feature "right"
debug <general>: Normal axis detected on axis 0
debug <general>: game.controller.snes: mapping feature "right" for device android/inputdevice/151 to "semiaxis +0"
...
debug <general>: game.controller.snes: Waiting for input for feature "leftbumper"
debug <general>: CAndroidKey: key ignored (code: 192)
debug <general>: CAndroidKey: key down (dev: 151; src: 257; code: 23; repeat: 0; flags: 0x8; alt: no; shift: no; sym: no)
debug <general>: Keyboard: scancode: 0x17, sym: 0x0d, unicode: 0x00, modifier: 0x0
debug <general>: CAndroidKey: key ignored (code: 192)
debug <general>: CAndroidKey: key up (dev: 151; src: 257; code: 23; repeat: 0; flags: 0x8; alt: no; shift: no; sym: no)
debug <general>: Keyboard: scancode: 0x17, sym: 0x0d, unicode: 0x00, modifier: 0x0

The log includes this scenario, I am not sure if it provides more information than what

I can't see the capture input dialog in the log? It should have a line containing capturing input for device, but I didn't add further logging in this dialog so the log wouldn't be useful. I was more concerned with what you observed in the GUI, specifically does "Axis 1" show up (confirm positive result) and does "Button 1" show up (confirm negative result).

I will try to compile for my self and add custom string debug messages so it is added to put those to the debug log file and compile. Not the most efficient way but for limited purposes can work.

I call this "printf debugging", and it's what I do these days, and how I fixed the PS4 triggers. It's how I'd fix the problem if I had a controller with generic button keycodes. Not efficient but, given enough time, sufficient. Also not for the feint of heart, but one of the best learning experiences you can get.

Also as part of me going through the code I have been trying to identify the part of the code that gets triggered based on the log messages and I think its might be here:

Thanks for pointing this out, I searched the function onKeyboardEvent() to see where it came from and found CEventLoop::processInput(), which shows why unhandled joystick events get interpreted as keyboard presses. Mystery solved for me after all these years :)

So the log line you found is a symptom of the joystick event not being handled. m_inputHandler->onJoyStickEvent(event) must return true and it returns false. Somewhere within that call is a return false; that is being hit when it shouldn't, and finding that will show exactly where the problem is, then I can fix it.

Also, by looking at the code, would it be possible that since the keyMap array in this file does not include AKEYCODE_BUTTON_10 (or any of these numbers) the button gets ignored and this line uint16_t sym = XBMCK_UNKNOWN; keeps the ˙sym` variable XBMCK_UNKNOWN and we get returned false?

That's exactly what's occuring, and as I analyzed above by the time we hit this line it's too late. As Android doesn't know what generic "button 10" maps to, neither does Kodi, hence the XBMCK_UNKNOWN. Button 10 will always be XBMCK_UNKNOWN so we need to handle it in the joystick event handler.

The other keys in the AndroidJoystickTranslator.cpp seems to be present (not all of course).

The translator in this file should have all keys, and I see AKEYCODE_BUTTON_10. What keys do you see that are missing?


So we've found the problem. m_inputHandler->onJoyStickEvent(event) is incorrectly returning false for the generic button keycodes. Find where the false comes from and we can fix the problem.

@Abasz
Copy link
Author

Abasz commented Jan 30, 2024

Ok so I am compiling, it has been doing that for most part of the day :)

In the mean time I was looking through the code in my IDE (VSCode) and this is what happening I think:

In AndroidJoyStick.cpp there is an if statement:

if ((source & (AINPUT_SOURCE_GAMEPAD | AINPUT_SOURCE_JOYSTICK)) != 0)
    return CXBMCApp::Get().onInputDeviceEvent(event);

Below that there is a log that I dont see in the log so we can assume that we dont get there in the code (https://github.com/xbmc/xbmc/blob/9a87e4d657d0f39559f56b567db7c6f59492db19/xbmc/platform/android/activity/AndroidJoyStick.cpp#L23C1-L25C1))

Meaning that the return of the onInputDeviceEvent(event) is relevant. Now in there, the code checks whether the device event handler is not a null pointer and if not it returns. Here is the first potential false statement. I will put a log message here to check if this is the one or further down

  if (m_inputDeviceEventHandler != nullptr)
    return m_inputDeviceEventHandler->OnInputDeviceEvent(event);

  return false;

Now if I go into the OnInputDeviceEvent function there is also a log message:

    CLog::Log(LOGWARNING,
              "CPeripheralBusAndroid: ignoring input event for unknown input device with ID {}",
              deviceId);

which I never see so I assume the false does not come from here. It can come from where it check whether the event is a null pointer, or it can pass further on to joystickState->second.ProcessEvent(event);

I was able to compile, it took ages though... and then on install I realized I compiled for the wrong target ... So now I restarted :)

@Abasz
Copy link
Author

Abasz commented Jan 31, 2024

FYI - Meanwhile I fight with compilation, I tested the 30 Jan version. No change, but I added the logs:
kodi.log

@garbear
Copy link
Owner

garbear commented Jan 31, 2024

Sounds good, I've gotten lots of positive reports so it looks like we're just lacking controllers that have generic button keycodes like yours.

@Abasz
Copy link
Author

Abasz commented Jan 31, 2024

Ok so after setting up a lot of logging statements I made some progress. The issue is that these controllers get mapped to keyboard right at the start.

So basically in the int32_t CEventLoop::processInput(AInputEvent* event) function the source (int32_t source = AInputEvent_getSource(event);) gets set to 257. That is equivalent (I think) to AINPUT_SOURCE_KEYBOARD = 0x00000100 | AINPUT_SOURCE_CLASS_BUTTON

Therefore, when the code checks for this if (IS_FROM_SOURCE(source, AINPUT_SOURCE_GAMEPAD) || IS_FROM_SOURCE(source, AINPUT_SOURCE_JOYSTICK)), this returns false. Which means that we never actually get to the if (m_inputHandler->onJoyStickEvent(event))

Due to this the button trigger gets sym == XBMCK_UNKNOWN in the bool CAndroidKey::onKeyboardEvent(AInputEvent *event)

Here are the logs, you can look for the Debug Step and the numbers which shows my added debug messages.
kodi.log

Its clear that even though at the begging my controller gets mapped to JOYSTICK as well as KEYBOARD when getting the source from the input event, only keyboard is returned and that is filtered out by the IS_FROM_SOURCE call. Is it possible to add KEYBOARD to this check?

2024-01-31 20:41:57.975 T:30491   debug <general>:   Name: "Logitech Logitech(R) Precision(TM) Gamepad"
2024-01-31 20:41:57.975 T:30491   debug <general>:     ID: 163
2024-01-31 20:41:57.975 T:30491   debug <general>:     Controller number: 0
2024-01-31 20:41:57.975 T:30491   debug <general>:     Descriptor: "4704e7c96f110c..."
2024-01-31 20:41:57.975 T:30491   debug <general>:     Product ID: C21A
2024-01-31 20:41:57.975 T:30491   debug <general>:     Vendor ID: 046D
2024-01-31 20:41:57.975 T:30491   debug <general>:     Has microphone: false
2024-01-31 20:41:57.975 T:30491   debug <general>:     Is virtual: false
2024-01-31 20:41:57.975 T:30491   debug <general>:     Source flags: 0x1000111
2024-01-31 20:41:57.975 T:30491   debug <general>:     Has source: SOURCE_JOYSTICK (0x1000010)
2024-01-31 20:41:57.975 T:30491   debug <general>:     Has source: SOURCE_KEYBOARD (0x000101)
2024-01-31 20:41:57.976 T:30491   debug <general>:     Has key: AKEYCODE_BUTTON_1 (188)
2024-01-31 20:41:57.976 T:30491   debug <general>:     Has key: AKEYCODE_BUTTON_2 (189)
2024-01-31 20:41:57.976 T:30491   debug <general>:     Has key: AKEYCODE_BUTTON_3 (190)
2024-01-31 20:41:57.976 T:30491   debug <general>:     Has key: AKEYCODE_BUTTON_4 (191)
2024-01-31 20:41:57.976 T:30491   debug <general>:     Has key: AKEYCODE_BUTTON_5 (192)
2024-01-31 20:41:57.976 T:30491   debug <general>:     Has key: AKEYCODE_BUTTON_6 (193)
2024-01-31 20:41:57.976 T:30491   debug <general>:     Has key: AKEYCODE_BUTTON_7 (194)
2024-01-31 20:41:57.976 T:30491   debug <general>:     Has key: AKEYCODE_BUTTON_8 (195)
2024-01-31 20:41:57.976 T:30491   debug <general>:     Has key: AKEYCODE_BUTTON_9 (196)
2024-01-31 20:41:57.976 T:30491   debug <general>:     Has key: AKEYCODE_BUTTON_10 (197)
2024-01-31 20:41:57.976 T:30491   debug <general>:     Has axis: AMOTION_EVENT_AXIS_X (0)
2024-01-31 20:41:57.976 T:30491   debug <general>:       Endpoints: [-1.000000, 1.000000]
2024-01-31 20:41:57.977 T:30491   debug <general>:       Center: 0.117647
2024-01-31 20:41:57.977 T:30491   debug <general>:       Fuzz: 0.000000
2024-01-31 20:41:57.977 T:30491   debug <general>:     Has axis: AMOTION_EVENT_AXIS_Y (1)
2024-01-31 20:41:57.977 T:30491   debug <general>:       Endpoints: [-1.000000, 1.000000]
2024-01-31 20:41:57.977 T:30491   debug <general>:       Center: 0.117647
2024-01-31 20:41:57.977 T:30491   debug <general>:       Fuzz: 0.000000

EDIT:

Of course as I suspected adding || IS_FROM_SOURCE(source, AINPUT_SOURCE_KEYBOARD) to the if check solves the problem, mapping works, navigation works with controller in kodi (including enter, back etc.), game works (after mapping).

I have no idea whether this messes anything up, but what I know is that this line was added in 2016 but as part of a refactoring and the check was since the biggining of adding joystick handling in 2013 (just placed differently).

I actually remember that many years ago (like 2019) I had these controllers working with the same shield. So I suppose something has changed on the android driver side and the input of these do not get correctly mapped.

@garbear
Copy link
Owner

garbear commented Jan 31, 2024

Yes, we can add KEYBOARD to the check, or remove the check altogether. I hit another issue where a user had a controller that only identified as a mouse, and I added this hack which I'm not too thrilled about: xbmc@d6e9f41

It seems that source attribution is unreliable overall. Most reliable is the keycode itself of course. If a keyboard or mouse sends a BUTTON keycode then it should always be handled as if it was from a controller, and it's likely mapped in the UI so it'll probably have the desired effect.

Adding IS_FROM_SOURCE(source, AINPUT_SOURCE_KEYBOARD) means that all keypresses are sent to the joystick handler, which is probably OK because the joystick handler only processes buttons anyway. The only exception is the keys AKEYCODE_HOME, AKEYCODE_BACK and AKEYCODE_MENU. But because these are mapped in the joystick handler, it's OK because the Kodi action will be the same whether it comes from a keyboard or joystick handler.

If we add KEYBOARD to the source check does controller input then work for you?

@Abasz
Copy link
Author

Abasz commented Jan 31, 2024

If we add KEYBOARD to the source check does controller input then work for you?

Please see my edit. Yes it does.

@garbear
Copy link
Owner

garbear commented Jan 31, 2024

Then I think we should add the KEYBOARD check. My most recent push to the PR adds automatic mapping on Android, which means that the three keyboard buttons will by default have the desired effect whether they come from a joystick or keyboard. There's no risk to other keys, as they'll be ignored by the joystick handler and then processed as keys anyway.

@Abasz
Copy link
Author

Abasz commented Jan 31, 2024

on a second thought:

Just a side note: removing I dont think is a good idea, as there are like touch motions that my need different handling. Also I think mouse is something that needs different handling. Treating keyboard as joystick is probably ok I agree.

Just to throw something in here that may be a more long term solution: I am thinking what if the checks are slightly different and not based on source but rather first on ID and then check this HAS_SOURCE property that gets populated

2024-01-31 21:25:02.255 T:3506    debug <general>:     Has source: SOURCE_JOYSTICK (0x1000010)
2024-01-31 21:25:02.255 T:3506    debug <general>:     Has source: SOURCE_KEYBOARD (0x000101)

And if that includes SOURCE_JOYSTICK or GAMEPAD than handle as joystick.

I dont know the mouse issue you mention but that is probably a niche problem :)

@Abasz
Copy link
Author

Abasz commented Feb 1, 2024

Tested the new release and everything works. I tested other "Generic USB controllers" and they work as they should. Thanks for your help.

@Abasz Abasz closed this as completed Feb 1, 2024
@Abasz
Copy link
Author

Abasz commented Aug 12, 2024

This issue is back in your build for 10 may 2024. It works in the may 5 version but not in the subsequent one. It is broken for all builds after that

@Abasz Abasz reopened this Aug 12, 2024
@garbear
Copy link
Owner

garbear commented Aug 15, 2024

Yes, in that build I reverted the old joystick fixes PR and replaced it with the new one, which didn't include the change that made keyboards look like controllers. This broke virtually all remotes.

See my comment here: xbmc#25177 (comment)

@Abasz
Copy link
Author

Abasz commented Aug 15, 2024

I have done some tests in the past two days and strangely android maps the the dpad and other button presses differently.

The DPad presses are correctly mapped to AINPUT_SOURCE_JOYSTICK but the button presses are mapped to keyboard. I have been checking the event in the processInput() method in the EventLoop class to try to find a way to filter out this anomaly.

The thing is that Android correctly maps the controller it self (I attached the log file:
kodi.log

and it is able to decipher that it has Joystick capabilities:

2024-08-15 15:29:44.317 T:26249 debug : CPeripheralBusAndroid: Device discovered:
2024-08-15 15:29:44.317 T:26249 debug : Name: "Logitech Logitech(R) Precision(TM) Gamepad"
2024-08-15 15:29:44.317 T:26249 debug : ID: 43
2024-08-15 15:29:44.317 T:26249 debug : Controller number: 0
2024-08-15 15:29:44.317 T:26249 debug : Descriptor: "4704e7c96f110c..."
2024-08-15 15:29:44.317 T:26249 debug : Product ID: C21A
2024-08-15 15:29:44.317 T:26249 debug : Vendor ID: 046D
2024-08-15 15:29:44.317 T:26249 debug : Has microphone: false
2024-08-15 15:29:44.317 T:26249 debug : Is virtual: false
2024-08-15 15:29:44.317 T:26249 debug : Source flags: 0x1000111
2024-08-15 15:29:44.318 T:26249 debug : Has source: SOURCE_JOYSTICK (0x1000010)
2024-08-15 15:29:44.318 T:26249 debug : Has source: SOURCE_KEYBOARD (0x000101)

So I think it should be possible to check somehow based on device ID if the given device has joystick capabilities or not (rather checking per event based on the event data) and if yes regardless allow it to go down the joystick path.

I have checked all remotes (shield, IR other bluetooth, keyboard - both wired and a usb reciver one - etc.) which I have and I think this pairing (i.e. keyboard and Joystick) is only applicable for actual joysticks. The only problematic is the keyboard with the usb receiver as it has all sources:

2024-08-15 15:50:32.818 T:25990 debug : Has source: SOURCE_DPAD (0x000201)
2024-08-15 15:50:32.819 T:25990 debug : Has source: SOURCE_JOYSTICK (0x1000010)
2024-08-15 15:50:32.819 T:25990 debug : Has source: SOURCE_KEYBOARD (0x000101)
2024-08-15 15:50:32.819 T:25990 debug : Has source: SOURCE_MOUSE (0x002002)

But interestingly this is remapped later on as only keyboard and on button press properly handled (please see log with deviceID 55). So I dont think it would interfere with my proposed filtering logic.

What needs to be done is to have access to the saved devices list and match the deviceID of the event and check its capabilities. It think this is a robust (and potentially permanent) solution and does not require Android controller handling to also handle keyboards. Of course I dont know how it would impact performance if there are a lot of peripheral devices in the device list to search in. But I suppose these lookups can be rather efficient to have only negligible performance hits.

@garbear
Copy link
Owner

garbear commented Aug 28, 2024

Just a heads up, I merged the backport PR for joystick fixes: xbmc#25389

It looks like more work is needed to support your USB joysticks. The hard part is that I don't have one myself for testing. But next time I work on Android joysticks (probably when a problem arises from the merged backport) then I'll see if I can implement your suggestions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants