RetroPie forum home
    • Recent
    • Tags
    • Popular
    • Home
    • Docs
    • Register
    • Login
    Please do not post a support request without first reading and following the advice in https://retropie.org.uk/forum/topic/3/read-this-first

    RetroArch crashes when any joystick direction is pressed, EmulationStation fine.

    Scheduled Pinned Locked Moved Help and Support
    uinputretropieemulationstaton
    2 Posts 2 Posters 286 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • T
      The_Next_Guy
      last edited by

      I am writing an input driver for my device that talks to a pico to relay button presses and analog readings. I am having issues with RetroArch crashing on axis input, giving a not so detailed Floating Point Exception in /dev/shm/runcommand.log, or not recognizing DPAD input if I change it to button presses. Here is my relevant code for the driver. Everything responds in EmulationStation just fine, just RetroArch crashes. here are the relevant sections of my code:

      void ControllerManager::setup_uinput_device(int joystick_id) {
          struct uinput_setup usetup;
          int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
          if (fd < 0) {
              perror("Unable to open /dev/uinput");
              exit(EXIT_FAILURE);
          }
      
          ioctl(fd, UI_SET_EVBIT, EV_KEY);
          ioctl(fd, UI_SET_KEYBIT, BTN_A);
          ioctl(fd, UI_SET_KEYBIT, BTN_B);
          ioctl(fd, UI_SET_KEYBIT, BTN_X);
          ioctl(fd, UI_SET_KEYBIT, BTN_Y);
          ioctl(fd, UI_SET_KEYBIT, BTN_START);
          ioctl(fd, UI_SET_KEYBIT, BTN_SELECT);
          ioctl(fd, UI_SET_KEYBIT, BTN_TL);
          ioctl(fd, UI_SET_KEYBIT, BTN_TR);
      
          ioctl(fd, UI_SET_EVBIT, EV_ABS);
          ioctl(fd, UI_SET_ABSBIT, ABS_X);
          ioctl(fd, UI_SET_ABSBIT, ABS_Y);
      
          memset(&usetup, 0, sizeof(usetup));
          usetup.id.bustype = BUS_USB;
          usetup.id.vendor = 0x5348; // Sample Vendor
          usetup.id.product = 0x0100 + joystick_id; // Unique product ID for each joystick
          snprintf(usetup.name, UINPUT_MAX_NAME_SIZE, "Xemplar PicoTroller %d", joystick_id);
      
          ioctl(fd, UI_DEV_SETUP, &usetup);
          ioctl(fd, UI_DEV_CREATE);
      
          fds[fd_count++] = fd;
      }
      
      void ControllerManager::monitorJoystick(byte controller_index, byte button_count, const byte* button_values, byte axis_count, const int16_t* axis_values) {
      	if(controller_index < 0 || controller_index > fd_count) return; // Invalid controller index
      	if(controller_index == 0){
      		pluggedIn = (button_values[0] & 0x01) > 0;
      		bool isFan = (button_values[0] & 0x02) > 0;
      		if(isFan){
      		  fanValue = axis_values[0];
      		} else {
      		  batteryValue = axis_values[0];
      		}
      		return;
      	}
      	controller_index--;
      	
      	if(controllers[controller_index].button_count < button_count){
      		controllers[controller_index].button_count = button_count;
      		controllers[controller_index].axis_count = axis_count;
      	}
      	for(int i = 0; i < button_count; i++){
      		byte byte_index = i / 8;
              byte bit_index = i % 8;
              byte button_state = (button_values[byte_index] >> bit_index) & 1;
      			
      		controllers[controller_index].button_states[i] = button_state == 1;
      	}
      	for (byte i = 0; i < axis_count; ++i) {
              controllers[controller_index].axis[i].x = axis_values[i * 2];
              controllers[controller_index].axis[i].y = axis_values[i * 2 + 1];
          }
      	
      	if(checkSpecial(controller_index)) return;
      	
      	controller_index++;
      	emulateJoystick(controller_index, button_count, button_values, axis_count, axis_values);
      }
      
      void ControllerManager::emulateJoystick(byte controller_index, byte button_count, const byte* button_values, byte axis_count, const int16_t* axis_values) {
          int fd = fds[controller_index - 1]; // Convert to 0-based index
          sendEvent(fd, EV_SYN, SYN_REPORT, 0);
      
          for (byte i = 0; i < button_count; ++i) {
      		int code;
              switch (i + 1) {
                  case 1: code = BTN_A; break;
                  case 2: code = BTN_B; break;
                  case 3: code = BTN_X; break;
                  case 4: code = BTN_Y; break;
                  case 5: code = BTN_START; break;
                  case 6: code = BTN_SELECT; break;
                  case 7: code = BTN_TL; break;
                  case 8: code = BTN_TR; break;
                  default: continue;
              }
              sendEvent(fd, EV_KEY, code, controllers[controller_index - 1].button_states[i]);
          }
      	
          sendEvent(fd, EV_SYN, SYN_REPORT, 0);
      	
      	sendEvent(fd, EV_ABS, ABS_X, controllers[controller_index - 1].axis[0].x);
          sendEvent(fd, EV_ABS, ABS_Y, controllers[controller_index - 1].axis[0].y);
      
          sendEvent(fd, EV_SYN, SYN_REPORT, 0);
      
          if (DEBUG) {
              std::cout << "\rAxes: ";
              for (byte i = 0; i < axis_count * 2; ++i) {
                  std::cout << std::setw(3) << static_cast<int>(i) << ":" << std::setw(6) << controllers[controller_index - 1].axis[i].x << " " << controllers[controller_index - 1].axis[i].y << " ";
              }
              std::cout << "Buttons: ";
              for (byte i = 0; i < button_count; ++i) {
                  std::cout << std::setw(2) << static_cast<int>(i) << ":" << (controllers[controller_index - 1].button_states[i] ? "on " : "off ");
              }
              std::cout << std::flush;
      		if(!ONE_LINE) std::cout << std::endl;
          }
      }
      
      1 Reply Last reply Reply Quote 0
      • mituM
        mitu Global Moderator
        last edited by

        RetroPie just packages RetroArch - you may want to report to the upstream project. You should add a way to reproduce the issue without relying on a specific device, so that any developer familiar with RetroArch's input system may be able to analyze and maybe fix your issue.

        1 Reply Last reply Reply Quote 0
        • First post
          Last post

        Contributions to the project are always appreciated, so if you would like to support us with a donation you can do so here.

        Hosting provided by Mythic-Beasts. See the Hosting Information page for more information.