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

Steam Deck - No inputs are detected if controller disconnects #14524

Open
dyllan500 opened this issue Oct 16, 2022 · 12 comments
Open

Steam Deck - No inputs are detected if controller disconnects #14524

dyllan500 opened this issue Oct 16, 2022 · 12 comments

Comments

@dyllan500
Copy link

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 389ef31, Build Oct 4 2022

Environment information

  • OS: SteamOS 3.2
@dyllan500
Copy link
Author

dyllan500 commented Oct 17, 2022

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 dyllan500 changed the title Stream Deck - No inputs are detected if controller disconnects Steam Deck - No inputs are detected if controller disconnects Oct 17, 2022
@martyfuhry
Copy link

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!

@hizzlekizzle
Copy link
Contributor

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.

@martyfuhry
Copy link

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

@FishOrBear
Copy link
Contributor

Similar question here
#15732

@FishOrBear
Copy link
Contributor

@martyfuhry #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
Copy link
Contributor

@martyfuhry try this
#15819

@mikew
Copy link

mikew commented Feb 11, 2024

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
Copy link

mikew commented Feb 11, 2024

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.

@whatnowmax
Copy link

Can confirm this is still an issue.

@eduardrudko
Copy link

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

@chanksworld
Copy link

Confirming this is still an issue..

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

8 participants