int main(int argc, char* argv[]) { int result = 0; int rd, ctr, combo = 0, use_combos = 1; char keyStates[256]; int detach = 0; int opt; while ((opt = getopt(argc, argv, "+dsc")) != -1) { switch (opt) { case 'd': detach = 1; break; case 's': use_syslog = 1; break; case 'c': printf("Combos disabled\n"); use_combos = 0; break; default: fprintf(stderr, "Usage: %s [-d] [-s]\n", argv[0]); exit(EXIT_FAILURE); break; } } SYSLOG(LOG_NOTICE, "Starting."); printf("[Xarcade2Joystick] Getting exclusive access: "); result = input_xarcade_open(&xarcdev, INPUT_XARC_TYPE_TANKSTICK); if (result != 0) { if (errno == 0) { printf("Not found.\n"); SYSLOG(LOG_ERR, "Xarcade not found, exiting."); } else { printf("Failed to get exclusive access to Xarcade: %d (%s)\n", errno, strerror(errno)); SYSLOG(LOG_ERR, "Failed to get exclusive access to Xarcade, exiting: %d (%s)", errno, strerror(errno)); } exit(EXIT_FAILURE); } SYSLOG(LOG_NOTICE, "Got exclusive access to Xarcade."); uinput_gpad_open(&uinp_gpads[0], UINPUT_GPAD_TYPE_XARCADE, 1); uinput_gpad_open(&uinp_gpads[1], UINPUT_GPAD_TYPE_XARCADE, 2); uinput_kbd_open(&uinp_kbd); if (detach) { if (daemon(0, 1)) { perror("daemon"); return 1; } } signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); SYSLOG(LOG_NOTICE, "Running."); while (1) { rd = input_xarcade_read(&xarcdev); if (rd < 0) { break; } for (ctr = 0; ctr < rd; ctr++) { if (xarcdev.ev[ctr].type == 0) continue; if (xarcdev.ev[ctr].type == EV_MSC) continue; if (EV_KEY == xarcdev.ev[ctr].type) { keyStates[xarcdev.ev[ctr].code] = xarcdev.ev[ctr].value; switch (xarcdev.ev[ctr].code) { /* ---------------- Player 1 controls ------------------- */ /* buttons */ case KEY_LEFTCTRL: uinput_gpad_write(&uinp_gpads[0], BTN_A, xarcdev.ev[ctr].value > 0, EV_KEY); break; case KEY_LEFTALT: uinput_gpad_write(&uinp_gpads[0], BTN_B, xarcdev.ev[ctr].value > 0, EV_KEY); break; case KEY_SPACE: uinput_gpad_write(&uinp_gpads[0], BTN_C, xarcdev.ev[ctr].value > 0, EV_KEY); break; case KEY_LEFTSHIFT: uinput_gpad_write(&uinp_gpads[0], BTN_X, xarcdev.ev[ctr].value > 0, EV_KEY); break; case KEY_Z: uinput_gpad_write(&uinp_gpads[0], BTN_Y, xarcdev.ev[ctr].value > 0, EV_KEY); break; case KEY_X: uinput_gpad_write(&uinp_gpads[0], BTN_Z, xarcdev.ev[ctr].value > 0, EV_KEY); break; case KEY_C: uinput_gpad_write(&uinp_gpads[0], BTN_TL, xarcdev.ev[ctr].value > 0, EV_KEY); break; case KEY_5: uinput_gpad_write(&uinp_gpads[0], BTN_TR, xarcdev.ev[ctr].value > 0, EV_KEY); break; case KEY_1: if (!use_combos) uinput_gpad_write(&uinp_gpads[0], BTN_START, xarcdev.ev[ctr].value > 0, EV_KEY); else { /* handle combination */ if (keyStates[KEY_3] && xarcdev.ev[ctr].value) { uinput_kbd_write(&uinp_kbd, KEY_TAB, 1, EV_KEY); uinput_kbd_sleep(); uinput_kbd_write(&uinp_kbd, KEY_TAB, 0, EV_KEY); combo = 2; continue; } /* it's a key down, ignore */ if (xarcdev.ev[ctr].value) continue; if (!combo) { uinput_gpad_write(&uinp_gpads[0], BTN_START, 1, EV_KEY); uinput_gpad_sleep(); uinput_gpad_write(&uinp_gpads[0], BTN_START, 0, EV_KEY); } else combo--; } break; case KEY_3: if (!use_combos) uinput_gpad_write(&uinp_gpads[0], BTN_SELECT, xarcdev.ev[ctr].value > 0, EV_KEY); else { /* it's a key down, ignore */ if (xarcdev.ev[ctr].value) continue; if (!combo) { uinput_gpad_write(&uinp_gpads[0], BTN_SELECT, 1, EV_KEY); uinput_gpad_sleep(); uinput_gpad_write(&uinp_gpads[0], BTN_SELECT, 0, EV_KEY); } else combo--; } break; /* joystick */ case KEY_KP4: case KEY_LEFT: uinput_gpad_write(&uinp_gpads[0], ABS_X, xarcdev.ev[ctr].value == 0 ? 2 : 0, EV_ABS); // center or left break; case KEY_KP6: case KEY_RIGHT: uinput_gpad_write(&uinp_gpads[0], ABS_X, xarcdev.ev[ctr].value == 0 ? 2 : 4, EV_ABS); // center or right break; case KEY_KP8: case KEY_UP: uinput_gpad_write(&uinp_gpads[0], ABS_Y, xarcdev.ev[ctr].value == 0 ? 2 : 0, EV_ABS); // center or up break; case KEY_KP2: case KEY_DOWN: uinput_gpad_write(&uinp_gpads[0], ABS_Y, xarcdev.ev[ctr].value == 0 ? 2 : 4, EV_ABS); // center or down break; /* ---------------- Player 2 controls ------------------- */ /* buttons */ case KEY_A: uinput_gpad_write(&uinp_gpads[1], BTN_A, xarcdev.ev[ctr].value > 0, EV_KEY); break; case KEY_S: uinput_gpad_write(&uinp_gpads[1], BTN_B, xarcdev.ev[ctr].value > 0, EV_KEY); break; case KEY_Q: uinput_gpad_write(&uinp_gpads[1], BTN_C, xarcdev.ev[ctr].value > 0, EV_KEY); break; case KEY_W: uinput_gpad_write(&uinp_gpads[1], BTN_X, xarcdev.ev[ctr].value > 0, EV_KEY); break; case KEY_E: uinput_gpad_write(&uinp_gpads[1], BTN_Y, xarcdev.ev[ctr].value > 0, EV_KEY); break; case KEY_LEFTBRACE: uinput_gpad_write(&uinp_gpads[1], BTN_Z, xarcdev.ev[ctr].value > 0, EV_KEY); break; case KEY_RIGHTBRACE: uinput_gpad_write(&uinp_gpads[1], BTN_TL, xarcdev.ev[ctr].value > 0, EV_KEY); break; case KEY_6: uinput_gpad_write(&uinp_gpads[1], BTN_TR, xarcdev.ev[ctr].value > 0, EV_KEY); break; case KEY_2: if (!use_combos) uinput_gpad_write(&uinp_gpads[1], BTN_START, xarcdev.ev[ctr].value > 0, EV_KEY); else { /* handle combination */ if (keyStates[KEY_4] && xarcdev.ev[ctr].value) { uinput_kbd_write(&uinp_kbd, KEY_ESC, 1, EV_KEY); uinput_kbd_sleep(); uinput_kbd_write(&uinp_kbd, KEY_ESC, 0, EV_KEY); combo = 2; continue; } /* it's a key down, ignore */ if (xarcdev.ev[ctr].value) continue; if (!combo) { uinput_gpad_write(&uinp_gpads[1], BTN_START, 1, EV_KEY); uinput_gpad_sleep(); uinput_gpad_write(&uinp_gpads[1], BTN_START, 0, EV_KEY); } else combo--; } break; case KEY_4: if (!use_combos) uinput_gpad_write(&uinp_gpads[1], BTN_SELECT, xarcdev.ev[ctr].value > 0, EV_KEY); else { /* it's a key down, ignore */ if (xarcdev.ev[ctr].value) continue; if (!combo) { uinput_gpad_write(&uinp_gpads[1], BTN_SELECT, 1, EV_KEY); uinput_gpad_sleep(); uinput_gpad_write(&uinp_gpads[1], BTN_SELECT, 0, EV_KEY); } else combo--; } break; /* joystick */ case KEY_D: uinput_gpad_write(&uinp_gpads[1], ABS_X, xarcdev.ev[ctr].value == 0 ? 2 : 0, EV_ABS); // center or left break; case KEY_G: uinput_gpad_write(&uinp_gpads[1], ABS_X, xarcdev.ev[ctr].value == 0 ? 2 : 4, EV_ABS); // center or right break; case KEY_R: uinput_gpad_write(&uinp_gpads[1], ABS_Y, xarcdev.ev[ctr].value == 0 ? 2 : 0, EV_ABS); // center or up break; case KEY_F: uinput_gpad_write(&uinp_gpads[1], ABS_Y, xarcdev.ev[ctr].value == 0 ? 2 : 4, EV_ABS); // center or down break; default: break; } } } } teardown(); return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { uint8_t ctr = 0; GPAD_ST gpads[GPADSNUM]; BTN_DEV_ST button; int16_t clockpin; int16_t strobepin; int16_t data1pin; int16_t data2pin; int16_t clockpin_v2; int16_t strobepin_v2; int16_t data1pin_v2; int16_t data2pin_v2; if (!bcm2835_init()) return 1; if (readConfigurationfile() != 0 ) { return 1; } if (strcmp(confres.adapter_version,"1x")==0) { clockpin = RPI_GPIO_P1_19; strobepin = RPI_GPIO_P1_23; data1pin = RPI_GPIO_P1_05; data2pin = RPI_GPIO_P1_07; clockpin_v2 = RPI_V2_GPIO_P1_19; strobepin_v2 = RPI_V2_GPIO_P1_23; data1pin_v2 = RPI_V2_GPIO_P1_05; data2pin_v2 = RPI_V2_GPIO_P1_07; printf("[SNESDev-Rpi] Using pin setup for RetroPie GPIO-Adapter Version 1.X\n"); } else if (strcmp(confres.adapter_version,"2x")==0) { clockpin = RPI_GPIO_P1_16; strobepin = RPI_GPIO_P1_18; data1pin = RPI_GPIO_P1_15; data2pin = RPI_GPIO_P1_13; clockpin_v2 = RPI_V2_GPIO_P1_16; strobepin_v2 = RPI_V2_GPIO_P1_18; data1pin_v2 = RPI_V2_GPIO_P1_15; data2pin_v2 = RPI_V2_GPIO_P1_13; printf("[SNESDev-Rpi] Using pin setup for RetroPie GPIO-Adapter Version 2.X\n"); } else { clockpin = RPI_GPIO_P1_16; strobepin = RPI_GPIO_P1_18; data1pin = RPI_GPIO_P1_15; data2pin = RPI_GPIO_P1_13; clockpin_v2 = RPI_V2_GPIO_P1_16; strobepin_v2 = RPI_V2_GPIO_P1_18; data1pin_v2 = RPI_V2_GPIO_P1_15; data2pin_v2 = RPI_V2_GPIO_P1_13; printf("[SNESDev-Rpi] Using pin setup for RetroPie GPIO-Adapter Version 2.X\n"); } if (confres.gamepad1_enabled || confres.gamepad2_enabled) { gpads[0].port = 1; gpads[1].port = 1; // check board revision and set pins to be used // these are acutally also used by the gamecon driver if (get_rpi_revision()==1) { gpads[0].pin_clock = clockpin; gpads[0].pin_strobe = strobepin; gpads[0].pin_data = data1pin; gpads[1].pin_clock = clockpin; gpads[1].pin_strobe = strobepin; gpads[1].pin_data = data2pin; } else { gpads[0].pin_clock = clockpin_v2; gpads[0].pin_strobe = strobepin_v2; gpads[0].pin_data = data1pin_v2; gpads[1].pin_clock = clockpin_v2; gpads[1].pin_strobe = strobepin_v2; gpads[1].pin_data = data2pin_v2; } if (strcmp(confres.gamepad1_type,"nes")==0) { gpads[0].type = GPAD_TYPE_NES; } else { gpads[0].type = GPAD_TYPE_SNES; } if (strcmp(confres.gamepad2_type,"nes")==0) { gpads[1].type = GPAD_TYPE_NES; } else { gpads[1].type = GPAD_TYPE_SNES; } if (confres.gamepad1_enabled) { printf("[SNESDev-Rpi] Enabling game pad 1 with type '%s'.\n", confres.gamepad1_type); gpad_open(&gpads[0]); switch (gpads->type) { case GPAD_TYPE_SNES: uinput_gpad_open(&uinp_gpads[0], UINPUT_GPAD_TYPE_SNES); break; case GPAD_TYPE_NES: uinput_gpad_open(&uinp_gpads[0], UINPUT_GPAD_TYPE_NES); break; default: break; } } if (confres.gamepad2_enabled) { printf("[SNESDev-Rpi] Enabling game pad 2 with type '%s'.\n", confres.gamepad2_type); gpad_open(&gpads[1]); switch (gpads->type) { case GPAD_TYPE_SNES: uinput_gpad_open(&uinp_gpads[1], UINPUT_GPAD_TYPE_SNES); break; case GPAD_TYPE_NES: uinput_gpad_open(&uinp_gpads[1], UINPUT_GPAD_TYPE_NES); break; default: break; } } } if (confres.button_enabled) { printf("[SNESDev-Rpi] Enabling button.\n"); button.port = 1; if (get_rpi_revision()==1) { button.pin = BUTTONPIN; } else { button.pin = BUTTONPIN_V2; } btn_open(&button); uinput_kbd_open(&uinp_kbd); } register_signalhandlers(); ///* enter the main loop */ doRun = 1; while (doRun) { if (confres.gamepad1_enabled || confres.gamepad2_enabled) { /* read states of the buttons */ for (ctr = 0; ctr < GPADSNUM; ctr++) { gpad_read(&gpads[ctr]); } ///* send an event (pressed or released) for each button */ for (ctr = 0; ctr < GPADSNUM; ctr++) { if ((ctr==0 && !(confres.gamepad1_enabled)) || (ctr==1 && !(confres.gamepad2_enabled))) { continue; } gpad_read(&gpads[ctr]); processPadBtn(gpads[ctr].state, EV_KEY, GPAD_SNES_A, BTN_A, &uinp_gpads[ctr]); processPadBtn(gpads[ctr].state, EV_KEY, GPAD_SNES_B, BTN_B, &uinp_gpads[ctr]); processPadBtn(gpads[ctr].state, EV_KEY, GPAD_SNES_X, BTN_X, &uinp_gpads[ctr]); processPadBtn(gpads[ctr].state, EV_KEY, GPAD_SNES_Y, BTN_Y, &uinp_gpads[ctr]); processPadBtn(gpads[ctr].state, EV_KEY, GPAD_SNES_L, BTN_TL, &uinp_gpads[ctr]); processPadBtn(gpads[ctr].state, EV_KEY, GPAD_SNES_R, BTN_TR, &uinp_gpads[ctr]); processPadBtn(gpads[ctr].state, EV_KEY, GPAD_SNES_SELECT, BTN_SELECT, &uinp_gpads[ctr]); processPadBtn(gpads[ctr].state, EV_KEY, GPAD_SNES_START, BTN_START, &uinp_gpads[ctr]); if ((gpads[ctr].state & GPAD_SNES_LEFT) == GPAD_SNES_LEFT) { uinput_gpad_write(&uinp_gpads[ctr], ABS_X, 0, EV_ABS); } else if ((gpads[ctr].state & GPAD_SNES_RIGHT) == GPAD_SNES_RIGHT) { uinput_gpad_write(&uinp_gpads[ctr], ABS_X, 4, EV_ABS); } else { uinput_gpad_write(&uinp_gpads[ctr], ABS_X, 2, EV_ABS); } if ((gpads[ctr].state & GPAD_SNES_UP) == GPAD_SNES_UP) { uinput_gpad_write(&uinp_gpads[ctr], ABS_Y, 0, EV_ABS); } else if ((gpads[ctr].state & GPAD_SNES_DOWN) == GPAD_SNES_DOWN) { uinput_gpad_write(&uinp_gpads[ctr], ABS_Y, 4, EV_ABS); } else { uinput_gpad_write(&uinp_gpads[ctr], ABS_Y, 2, EV_ABS); } } } if (confres.button_enabled) { btn_read(&button); switch (button.state) { case BTN_STATE_IDLE: break; case BTN_STATE_PRESSED: if (button.pressedCtr == 1 && button.duration >= 1) { uinput_kbd_write(&uinp_kbd, KEY_R, 1, EV_KEY); } break; case BTN_STATE_RELEASED: if (button.pressedCtr == 1 && button.duration >= 1) { uinput_kbd_write(&uinp_kbd, KEY_R, 0, EV_KEY); } else if (button.pressedCtr == 3 && button.duration >= 1) { // Sending ESC uinput_kbd_write(&uinp_kbd, KEY_ESC, 1, EV_KEY); usleep(50000); uinput_kbd_write(&uinp_kbd, KEY_ESC, 0, EV_KEY); } else if (button.pressedCtr == 5 && button.duration >= 1) { uinput_kbd_write(&uinp_kbd, KEY_F4, 1, EV_KEY); usleep(50000); uinput_kbd_write(&uinp_kbd, KEY_F4, 0, EV_KEY); // shutting down system("shutdown -t 3 -h now"); } break; } } /* wait for some time to keep the CPU load low */ if (confres.button_enabled && !(confres.gamepad1_enabled || confres.gamepad2_enabled)) { bcm2835_delay(FRAMEWAITLONG); } else { bcm2835_delay(FRAMEWAIT); } } return 0; }
int main(int argc, char* argv[]) { int result = 0; int rd, ctr; int detach = 0; int opt; while ((opt = getopt(argc, argv, "+d")) != -1) { switch (opt) { case 'd': detach = 1; break; default: fprintf(stderr, "Usage: %s [-d]\n", argv[0]); exit(1); break; } } printf("[MadCatz] Getting exclusive access: "); result = input_madcatz_open(&madcatzdev, INPUT_MADCATZ_TYPE); printf("%s\n", (result == 0) ? "SUCCESS" : "FAILURE"); if (result != 0) { exit(-1); } uinput_gpad_open(&uinp_gpads[0], UINPUT_GPAD_TYPE_MADCATZ); uinput_kbd_open(&uinp_kbd); if (detach) { if (daemon(0, 1)) { perror("daemon"); return 1; } } while (1) { rd = input_madcatz_read(&madcatzdev); if (rd < 0) { break; } for (ctr = 0; ctr < rd; ctr++) { if (madcatzdev.ev[ctr].type == 0) continue; if (madcatzdev.ev[ctr].type == EV_MSC) continue; if (EV_ABS == madcatzdev.ev[ctr].type) { const __s32 value = madcatzdev.ev[ctr].value; switch (madcatzdev.ev[ctr].code) { case 0: /* LS x */ uinput_gpad_write(&uinp_gpads[0], ABS_X, value < 127 ? 0 : (value > 128 ? 4 : 2), EV_ABS); break; case 1: /* LS y */ uinput_gpad_write(&uinp_gpads[0], ABS_Y, value < 127 ? 0 : (value > 128 ? 4 : 2), EV_ABS); break; case 16: /* DP x */ uinput_gpad_write(&uinp_gpads[0], ABS_X, value < 0 ? 0 : (value > 0 ? 4 : 2), EV_ABS); break; case 17: /* DP y */ uinput_gpad_write(&uinp_gpads[0], ABS_Y, value < 0 ? 0 : (value > 0 ? 4 : 2), EV_ABS); break; case 2: /* RS x */ uinput_gpad_write(&uinp_gpads[0], ABS_X, value < 127 ? 0 : (value > 128 ? 4 : 2), EV_ABS); break; case 5: /* RS y */ uinput_gpad_write(&uinp_gpads[0], ABS_Y, value < 127 ? 0 : (value > 128 ? 4 : 2), EV_ABS); break; } } else if (EV_KEY == madcatzdev.ev[ctr].type) { switch (madcatzdev.ev[ctr].code) { case BTN_TL2: uinput_gpad_write(&uinp_gpads[0], BTN_SELECT, madcatzdev.ev[ctr].value, EV_KEY); break; case BTN_TR2: uinput_gpad_write(&uinp_gpads[0], BTN_START, madcatzdev.ev[ctr].value, EV_KEY); break; default: uinput_gpad_write(&uinp_gpads[0], madcatzdev.ev[ctr].code, madcatzdev.ev[ctr].value, EV_KEY); break; } } } } printf("Exiting.\n"); input_madcatz_close(&madcatzdev); uinput_gpad_close(&uinp_gpads[0]); uinput_gpad_close(&uinp_gpads[1]); uinput_kbd_close(&uinp_kbd); return 0; }