RetroArch icon indicating copy to clipboard operation
RetroArch copied to clipboard

Steam Deck - No inputs are detected if controller disconnects

Open dyllan500 opened this issue 3 years ago • 12 comments

Description

When you have a Bluetooth device connected to the steam deck. Disconnecting and reconnecting it causes RetroArch to not show any devices connected in the Port Controls settings. This causes an issue of the reconnecting controller being set to port 2 and having no way of changing, which port it is on. The System Information screen shows that the input devices are connected to ports. The problem is that you can not change, which ports they are connected to since the Device Index does not appear to show them.

Expected behavior

I expected the correct number of inputs be available in the Port Controls settings.

Actual behavior

I get no inputs or sometimes only 1 input in the Port Controls settings, Device Index.

Steps to reproduce the bug

  1. Connect a Bluetooth controller.
  2. Play a rom.
  3. Disconnect then reconnect the Bluetooth controller.
  4. If you check RetroArch input settings, in every Port Controls settings the Device Index will contain no controllers.

Version/Commit

You can find this information under Information/System Information

  • RetroArch: Git https://github.com/libretro/RetroArch/commit/389ef31, Build Oct 4 2022

Environment information

  • OS: SteamOS 3.2

dyllan500 avatar Oct 16 '22 21:10 dyllan500

I did some more testing and found that the steam version of RetroArch on the Desktop also has the issue.

I also found that the issue lies in how the inputs are counted. This code is in input_driver.c.

unsigned input_config_get_device_count(void)
{
  unsigned num_devices;
  input_driver_state_t *input_st = &input_driver_st;

  for (num_devices = 0; num_devices < MAX_INPUT_DEVICES; ++num_devices)
  {
     if (string_is_empty(input_st->input_device_info[num_devices].name))
        break;
  }
  return num_devices;
}

This is expecting that inputs are connected in order. The problem is for say, you have three controllers connected. Then controller 1 disconnects. Since there is no input 1, RetroArch will not display the connected controllers on inputs 2 and 3.

I tried changing the code to count only the connected inputs. By doing the following.

unsigned input_config_get_device_count(void)
{
  unsigned num_devices;
  input_driver_state_t *input_st = &input_driver_st;

  for (unsigned i = 0; i < MAX_INPUT_DEVICES; i++)
  {
     if (!string_is_empty(input_st->input_device_info[i].name))
        num_devices++;
  }
  return num_devices;
}

The problem now is if 3 controllers are connected and controller 1 is disconnected. The Input settings will display input 1 with nothing connected and input 2. The problem being input 3 will not be displayed. This code is in menu_displaylist.c.

static int menu_displaylist_parse_input_device_index_list(
     menu_displaylist_info_t *info, settings_t *settings)
{
  char device_id[10];
  char device_label[128];
  const char *val_port         = NULL;
  const char *val_na           = NULL;
  const char *val_disabled     = NULL;
  rarch_system_info_t *system  = &runloop_state_get_ptr()->system;
  enum msg_hash_enums enum_idx = (enum msg_hash_enums)atoi(info->path);
  rarch_setting_t     *setting = menu_setting_find_enum(enum_idx);
  size_t menu_index            = 0;
  unsigned count               = 0;

  unsigned i                   = 0;
  unsigned port                = 0;
  unsigned map                 = 0;
  int current_device           = -1;
  unsigned max_devices         = input_config_get_device_count();

  device_id[0]                 = '\0';
  device_label[0]              = '\0';

  if (!system || !settings || !setting)
     goto end;

  port         = setting->index_offset;
  map          = settings->uints.input_joypad_index[port];

  if (port >= MAX_USERS)
     goto end;

  val_disabled = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISABLED);
  val_na       = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE);
  val_port     = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PORT);

  for (i = max_devices + 1; i--;)
  {
     snprintf(device_id, sizeof(device_id), "%d", i);

     device_label[0] = '\0';

     if (i < max_devices)
     {
        const char *device_name = input_config_get_device_display_name(i) ?
              input_config_get_device_display_name(i) : input_config_get_device_name(i);

        if (!string_is_empty(device_name))
        {
           unsigned idx = input_config_get_device_name_index(i);
           size_t _len  = strlcpy(device_label, device_name,
                 sizeof(device_label));

           /*if idx is non-zero, it's part of a set*/
           if (idx > 0)
              snprintf(device_label         + _len,
                       sizeof(device_label) - _len, " (#%u)", idx);
        }
        else
           snprintf(device_label, sizeof(device_label), "%s (%s %u)", val_na,
                 val_port, map);
     }
     else
        strlcpy(device_label, val_disabled, sizeof(device_label));

     /* Add menu entry */
     if (menu_entries_append(info->list,
           device_label,
           device_id,
           MENU_ENUM_LABEL_INPUT_BIND_DEVICE_INDEX,
           MENU_SETTING_DROPDOWN_ITEM_INPUT_DEVICE_INDEX,
           0, i, NULL))
     {
        /* Add checkmark if input is currently
         * mapped to this entry */
        if (i == map)
        {
           menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info->list->list[menu_index].actiondata;
           if (cbs)
              cbs->checked = true;
           menu_navigation_set_selection(menu_index);
           current_device = i;
        }

        count++;
        menu_index++;
     }
  }

  /* Disabled is the last device, which is the first entry */
  if (current_device < 0)
  {
     menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info->list->list[0].actiondata;
     if (cbs)
        cbs->checked = true;
     menu_navigation_set_selection(0);
  }

end:
  /* Fallback */
  if (count == 0)
     if (menu_entries_append(info->list,
           msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY),
           msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY),
           MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY,
           FILE_TYPE_NONE, 0, 0, NULL))
        count++;

  return count;
}

My thought is just show all the inputs even if they are not connected. This is definitely the easiest solution to the issue.

I just hope this helps to solve it. This would make the steam deck so much better. I wouldn't have to worry about one controller disconnecting during Mary Party ruining the whole fun, because we have to start over.

dyllan500 avatar Oct 17 '22 05:10 dyllan500

I was glad to see someone else report this! Unfortunately, I'm still having this issue today on my SteamDeck with all the latest configurations and emulators from EmuDeck. I saw there was a merged PR above last year, but I just wanted to report that this issue is still around.

I'm happy to help with testing if there's anything I can do!

martyfuhry avatar Sep 18 '23 15:09 martyfuhry

If what I've heard is correct, this is related to the flatpak sandboxing and is partially alleviated by using the SDL2 gamepad driver in RetroArch. This same issue affects the snap package and the default udev driver causes it to lose the controller after each game closure, requiring an unplug/replug, but SDL2 only requires that at first launch. Still not ideal, but definitely less of a hassle than udev.

hizzlekizzle avatar Sep 18 '23 19:09 hizzlekizzle

Interesting. Unfortunately, my RetroArch settings are already set to use the SDL2 driver, yet I'm able to reliably reproduce this bug.

martyfuhry avatar Sep 20 '23 11:09 martyfuhry

Similar question here https://github.com/libretro/RetroArch/issues/15732

FishOrBear avatar Oct 18 '23 01:10 FishOrBear

@martyfuhry https://github.com/libretro/RetroArch/pull/13527 https://github.com/FishOrBear/RetroArch/actions/runs/6582404887

I don't know if it can be solved. I built a version and tested it tonight.

FishOrBear avatar Oct 20 '23 02:10 FishOrBear

@martyfuhry try this https://github.com/libretro/RetroArch/pull/15819

FishOrBear avatar Oct 20 '23 15:10 FishOrBear

Willing to test any fixes here too. Once the deck goes to sleep, the controller input isn't passed to any games. Oddly, I can still use my menu shortcut to bring up the menu, and that can be navigated with the controller. Just no input is passed to any games.

mikew avatar Feb 11 '24 00:02 mikew

And somewhat confusingly, when using the AppImage the reverse is true. When coming back from sleep, controls work in the game, but don't in the menu.

Edit: I'm having better luck with the udev driver, in both the Flatpak and AppImage variants of RetroArch.

Annoyingly with the udev driver, I had to configure both the Steam Deck controls, and since I also use a Dual sense controller, that too. Sometimes the DualSense will default to "Wireless Controller" instead of "Microsoft X-Box 360 Pad" (a.k.a. the same controller just through Steam Input), and the controls won't work.

So, in the end it's a little better, but still annoying.

mikew avatar Feb 11 '24 17:02 mikew

Can confirm this is still an issue.

whatnowmax avatar Jun 28 '24 20:06 whatnowmax

Can confirm this still an issue. When i put my steam deck on sleep and back only steam recognizes my inputs.

eduardrudko avatar Jul 05 '24 11:07 eduardrudko

Confirming this is still an issue..

chanksworld avatar Nov 22 '24 05:11 chanksworld

I have the same issue. Im trying to set up my amiga emulation on Retrodeck with Retroarch using PUAE. When I reconnect disconnected Xbox One controller my in-game input stops working the correct way. Analog sticks are starting to act as a invisible mouse making an in-game character jumping, runing and ducking like crazy all over the place (2d platformer "Lionheart"). Normal buttons dont work at all. Controller works fine in Retroarch menu.

PSA: The only thing that helps getting controls back to normal is restarting Retroarch by quiting the game and reopening it from the Retrodeck app. Normal emulation restart won't work!

Sooo I can also confirm that the problem presists.

Legin2137 avatar Apr 01 '25 18:04 Legin2137

I can confirm that this happens with plain Steam running on Windows 11 desktop, using xinput controller driver.

In my case, using up and down (among others, I think) is complete non-functional, but I can press some buttons or button combinations. But I cannot close RetroArch with the gamepad or keep playing a normal session.

SDL2 driver works fine.

notNSANE avatar May 07 '25 06:05 notNSANE

This is very much still an issue.

salgadopietrini avatar Oct 22 '25 19:10 salgadopietrini

Hi,

Please provide some log to get at least the joypad controller driver and bluetooth driver.

Also to avoid any sandbox issue, if possible to make a test with AppImage or self compiled.

Thank you.

gouchi avatar Oct 23 '25 08:10 gouchi