diff --git a/core/adapter.c b/core/adapter.c index cbd8874e..a1c19f7a 100644 --- a/core/adapter.c +++ b/core/adapter.c @@ -677,9 +677,9 @@ static int adapter_send_reset(int device) return 0; } -int adapter_detect() +e_gimx_status adapter_detect() { - int ret = 0; + e_gimx_status ret = E_GIMX_STATUS_SUCCESS; int i; s_adapter* adapter; @@ -692,7 +692,7 @@ int adapter_detect() if (rtype < 0) { fprintf(stderr, _("No GPP detected.\n")); - ret = -1; + ret = E_GIMX_STATUS_ADAPTER_NOT_DETECTED; } else if(rtype < C_TYPE_MAX) { @@ -702,7 +702,7 @@ int adapter_detect() else { fprintf(stderr, _("Unknown GPP controller type.\n")); - ret = -1; + ret = E_GIMX_STATUS_GENERIC_ERROR; } } else if(adapter->atype == E_ADAPTER_TYPE_DIY_USB) @@ -712,8 +712,7 @@ int adapter_detect() adapter->serialdevice = gserial_open(adapter->portname, BAUDRATE); if(adapter->serialdevice < 0) { - fprintf(stderr, _("Check the wiring (maybe you swapped Rx and Tx?).\n")); - ret = -1; + ret = E_GIMX_STATUS_ADAPTER_NOT_DETECTED; } else { @@ -735,7 +734,7 @@ int adapter_detect() else if(adapter->ctype != (e_controller_type) rtype) { fprintf(stderr, _("Wrong controller type.\n")); - ret = -1; + ret = E_GIMX_STATUS_GENERIC_ERROR; } int status = adapter_send_short_command(i, BYTE_STATUS); @@ -743,7 +742,7 @@ int adapter_detect() if(status < 0) { fprintf(stderr, _("Can't get adapter status.\n")); - ret = -1; + ret = E_GIMX_STATUS_ADAPTER_NOT_DETECTED; } if(ret != -1) @@ -759,7 +758,7 @@ int adapter_detect() if(adapter_send_reset(i) < 0) { fprintf(stderr, _("Can't reset the adapter.\n")); - ret = -1; + ret = E_GIMX_STATUS_GENERIC_ERROR; } else { @@ -780,7 +779,7 @@ int adapter_detect() if(adapter_send_reset(i) < 0) { fprintf(stderr, _("Can't reset the adapter.\n")); - ret = -1; + ret = E_GIMX_STATUS_GENERIC_ERROR; } else { @@ -800,7 +799,7 @@ int adapter_detect() } } - if(ret != -1) + if(ret == E_GIMX_STATUS_SUCCESS) { int usb_res = usb_init(i, adapter->ctype); if(usb_res < 0) @@ -810,12 +809,28 @@ int adapter_detect() || status != BYTE_STATUS_SPOOFED) { fprintf(stderr, _("No controller was found on USB buses.\n")); - ret = -1; + switch(adapter->ctype) + { + case C_TYPE_360_PAD: + ret = E_GIMX_STATUS_AUTH_MISSING_X360; + break; + case C_TYPE_DS4: + case C_TYPE_G29_PS4: + case C_TYPE_T300RS_PS4: + ret = E_GIMX_STATUS_AUTH_MISSING_PS4; + break; + case C_TYPE_XONE_PAD: + ret = E_GIMX_STATUS_AUTH_MISSING_XONE; + break; + default: + ret = E_GIMX_STATUS_GENERIC_ERROR; + break; + } } } } - if(ret != -1) + if(ret == E_GIMX_STATUS_SUCCESS) { controller_init_report(adapter->ctype, &adapter->report[0].value); @@ -825,10 +840,14 @@ int adapter_detect() } } } + else + { + ret = E_GIMX_STATUS_ADAPTER_NOT_DETECTED; + } } - if(adapter->ctype == C_TYPE_NONE) + if(adapter->ctype == C_TYPE_NONE && ret == E_GIMX_STATUS_SUCCESS) { - ret = -1; + ret = E_GIMX_STATUS_GENERIC_ERROR; } } } @@ -841,7 +860,7 @@ int adapter_detect() { struct in_addr addr = { .s_addr = adapter->dst_ip }; fprintf(stderr, _("Can't connect to: %s:%d.\n"), inet_ntoa(addr), adapter->dst_port); - ret = -1; + ret = E_GIMX_STATUS_ADAPTER_NOT_DETECTED; } else { @@ -856,7 +875,7 @@ int adapter_detect() { if(btds4_init(i, adapter->dongle_index, adapter->bdaddr_dst) < 0) { - ret = -1; + ret = E_GIMX_STATUS_GENERIC_ERROR; } controller_init_report(C_TYPE_DS4, &adapter->report[0].value); } @@ -999,10 +1018,10 @@ int adapter_start() fprintf(stderr, _("Can't start the serial asynchronous processing.\n")); ret = -1; } - const char * button = controller_get_activation_button(adapter->ctype); - if (button != NULL) + adapter->activation_button.index = controller_get_activation_button(adapter->ctype); + if (adapter->activation_button.index != 0) { - printf(_("Press the %s button to activate the controller.\n"), button); + printf(_("Press the %s button to activate the controller.\n"), controller_get_axis_name(adapter->ctype, adapter->activation_button.index)); } } } @@ -1098,6 +1117,14 @@ int adapter_send() { if(adapter->serialdevice >= 0) { + if (adapter->activation_button.index != 0) + { + if (adapter->axis[adapter->activation_button.index] != 0) + { + adapter->activation_button.pressed = 1; + } + } + unsigned int index = controller_build_report(adapter->ctype, adapter->axis, adapter->report); s_report_packet* report = adapter->report+index; @@ -1205,8 +1232,9 @@ int adapter_send() return ret; } -void adapter_clean() +e_gimx_status adapter_clean() { + e_gimx_status status = E_GIMX_STATUS_SUCCESS; int i; s_adapter* adapter; for(i=0; iserialdevice >= 0) { + if (adapter->activation_button.index != 0) + { + if (adapter->activation_button.pressed == 0) + { + status = E_GIMX_STATUS_NO_ACTIVATION; + } + } switch(adapter->ctype) { case C_TYPE_360_PAD: @@ -1264,6 +1299,7 @@ void adapter_clean() gpp_disconnect(i); } } + return status; } int adapter_is_usb_auth_required(int adapter) diff --git a/core/gimx.c b/core/gimx.c index 004985a6..22bb89c5 100755 --- a/core/gimx.c +++ b/core/gimx.c @@ -14,6 +14,7 @@ #include //to get the homedir #include //to get the homedir #include //to disable/enable echo +#include // chown #else #define WIN32_LEAN_AND_MEAN #include @@ -155,6 +156,8 @@ void show_devices() int main(int argc, char *argv[]) { + e_gimx_status status = E_GIMX_STATUS_SUCCESS; + GE_Event kgevent = { .key = { .type = GE_KEYDOWN } }; #ifdef WIN32 @@ -196,6 +199,7 @@ int main(int argc, char *argv[]) if(SHGetFolderPath( NULL, CSIDL_APPDATA , NULL, 0, path )) { eprintf("SHGetFolderPath failed\n"); + status = E_GIMX_STATUS_GENERIC_ERROR; goto QUIT; } gimx_params.homedir = path; @@ -211,6 +215,7 @@ int main(int argc, char *argv[]) if(args_read(argc, argv, &gimx_params) < 0) { eprintf(_("wrong argument")); + status = E_GIMX_STATUS_GENERIC_ERROR; goto QUIT; } @@ -221,15 +226,18 @@ int main(int argc, char *argv[]) if (gusb_init() < 0) { + status = E_GIMX_STATUS_GENERIC_ERROR; goto QUIT; } if (gserial_init() < 0) { + status = E_GIMX_STATUS_GENERIC_ERROR; goto QUIT; } - if(adapter_detect() < 0) + status = adapter_detect(); + if(status != E_GIMX_STATUS_SUCCESS) { eprintf(_("no adapter detected")); goto QUIT; @@ -247,6 +255,7 @@ int main(int argc, char *argv[]) else if(gimx_params.refresh_period < controller_get_min_refresh_period(adapter_get(0)->ctype)) { fprintf(stderr, "Refresh period should be at least %.02fms\n", (double)controller_get_min_refresh_period(adapter_get(0)->ctype)/1000); + status = E_GIMX_STATUS_GENERIC_ERROR; goto QUIT; } @@ -275,6 +284,7 @@ int main(int argc, char *argv[]) if(adapter_start() < 0) { eprintf(_("failed to start the adapter")); + status = E_GIMX_STATUS_GENERIC_ERROR; goto QUIT; } adapter_send(); @@ -304,6 +314,7 @@ int main(int argc, char *argv[]) if (ghid_init() < 0) { + status = E_GIMX_STATUS_GENERIC_ERROR; goto QUIT; } @@ -317,6 +328,7 @@ int main(int argc, char *argv[]) }; if (ginput_init(&poll_interace, src, fp) < 0) { + status = E_GIMX_STATUS_GENERIC_ERROR; goto QUIT; } @@ -339,6 +351,7 @@ int main(int argc, char *argv[]) if(read_config_file(gimx_params.config_file) < 0) { + status = E_GIMX_STATUS_GENERIC_ERROR; goto QUIT; } @@ -372,6 +385,7 @@ int main(int argc, char *argv[]) else { fprintf(stderr, _("Unknown key name for argument --keygen: '%s'\n"), gimx_params.keygen); + status = E_GIMX_STATUS_GENERIC_ERROR; goto QUIT; } } @@ -396,6 +410,7 @@ int main(int argc, char *argv[]) if(adapter_start() < 0) { eprintf(_("failed to start the adapter")); + status = E_GIMX_STATUS_GENERIC_ERROR; goto QUIT; } @@ -413,7 +428,11 @@ int main(int argc, char *argv[]) ghid_exit(); - adapter_clean(); + e_gimx_status clean_status = adapter_clean(); + if (clean_status != E_GIMX_STATUS_SUCCESS) + { + status = clean_status; + } gserial_exit(); @@ -421,9 +440,62 @@ int main(int argc, char *argv[]) xmlCleanupParser(); + if (status != E_GIMX_STATUS_SUCCESS) + { + /* + * Write the status in the gimx.status file, in the system temp directory. + * + * In most cases gimx runs in a terminal window (such as xterm) that may not + * provide the return code to the parent process (in most cases gimx-launcher). + * + * The absence of the gimx.status file means the execution was successful, + * or that the program crashed. + */ + +#ifndef WIN32 + char * file = "/tmp/gimx.status"; +#else + char file[MAX_PATH]; + int ret = GetTempPath(sizeof(file), file); + if (ret > 0 && (unsigned int) ret < MAX_PATH - sizeof("/gimx.status")) + { + strcat(file, "/gimx.status"); + } + else + { + file[0] = '\0'; + } +#endif + if (file != NULL && file[0] != '\0') + { + FILE * fp = fopen(file, "w"); + if (fp != NULL) + { + fprintf(fp, "%d\n", status); + fclose(fp); +#ifndef WIN32 + int ret = chown(file, getpwuid(getuid())->pw_uid, getpwuid(getuid())->pw_gid); + if (ret < 0) + { + eprintf("failed to set ownership of the gimx status file"); + } +#endif + } + } + } + if(gimx_params.logfile) { fclose(gimx_params.logfile); + char file_path[PATH_MAX]; + snprintf(file_path, sizeof(file_path), "%s%s%s%s", gimx_params.homedir, GIMX_DIR, LOG_DIR, gimx_params.logfilename); +#ifndef WIN32 + int ret = chown(file_path, getpwuid(getuid())->pw_uid, getpwuid(getuid())->pw_gid); + if (ret < 0) + { + eprintf("failed to set ownership of the gimx log file"); + } +#endif } if(gimx_params.curses) @@ -440,5 +512,5 @@ int main(int argc, char *argv[]) } #endif - return 0; + return status; } diff --git a/core/include/adapter.h b/core/include/adapter.h index d46056dc..ebf4701d 100644 --- a/core/include/adapter.h +++ b/core/include/adapter.h @@ -10,6 +10,7 @@ #include #include #include +#include #ifndef WIN32 #include @@ -43,6 +44,10 @@ typedef struct int src_fd; e_adapter_type atype; e_controller_type ctype; + struct { + e_controller_axis_index index; + int pressed; + } activation_button; int event; int axis[AXIS_MAX]; int change; @@ -72,10 +77,10 @@ typedef struct unsigned char process_ffb; } s_adapter; -int adapter_detect(); +e_gimx_status adapter_detect(); int adapter_start(); int adapter_send(); -void adapter_clean(); +e_gimx_status adapter_clean(); s_adapter* adapter_get(unsigned char index); int adapter_set_port(unsigned char index, char* portname); diff --git a/core/include/gimx.h b/core/include/gimx.h index 9e1804b7..5bdfaaa8 100644 --- a/core/include/gimx.h +++ b/core/include/gimx.h @@ -13,6 +13,19 @@ #include #define _(STRING) gettext(STRING) +typedef enum { + E_GIMX_STATUS_SUCCESS = 0, + + E_GIMX_STATUS_GENERIC_ERROR = -1, + + E_GIMX_STATUS_ADAPTER_NOT_DETECTED = -2, // wiring issue, incorrect firmware, target not powered + E_GIMX_STATUS_NO_ACTIVATION = -3, // user did not activate the controller + + E_GIMX_STATUS_AUTH_MISSING_X360 = 1, // auth source missing + E_GIMX_STATUS_AUTH_MISSING_PS4 = 2, // auth source missing + E_GIMX_STATUS_AUTH_MISSING_XONE = 3, // auth source missing +} e_gimx_status; + #define MAX_CONTROLLERS 7 #define MAX_CONFIGURATIONS 8 #define MAX_DEVICES 256 diff --git a/launcher/gimx-launcher.cpp b/launcher/gimx-launcher.cpp index bfa7f2c9..970ebd24 100644 --- a/launcher/gimx-launcher.cpp +++ b/launcher/gimx-launcher.cpp @@ -81,6 +81,8 @@ using namespace std; #define LOG_FILE "log.txt" +#define STATUS_FILE "gimx.status" + #define GPP_NAME "GPP/Cronus/Titan" #define CONSOLETUNER_VID 0x2508 @@ -1095,7 +1097,7 @@ class MyProcess : public wxProcess m_parent = parent; } - void OnTerminate(int pid, int status); + virtual void OnTerminate(int pid, int status); protected: launcherFrame *m_parent; @@ -1105,6 +1107,8 @@ class MyProcess : public wxProcess void MyProcess::OnTerminate(int pid __attribute__((unused)), int status) { m_parent->OnProcessTerminated(this, status); + + delete this; } void launcherFrame::readDebugStrings(wxArrayString & values) @@ -1370,34 +1374,121 @@ void launcherFrame::OnButtonStartClick(wxCommandEvent& event __attribute__((unus } } +typedef enum { + E_GIMX_STATUS_SUCCESS = 0, + + E_GIMX_STATUS_GENERIC_ERROR = -1, + + E_GIMX_STATUS_ADAPTER_NOT_DETECTED = -2, // wiring issue, incorrect firmware, target not powered + E_GIMX_STATUS_NO_ACTIVATION = -3, // user did not activate the controller + + E_GIMX_STATUS_AUTH_MISSING_X360 = 1, // auth source missing + E_GIMX_STATUS_AUTH_MISSING_PS4 = 2, // auth source missing + E_GIMX_STATUS_AUTH_MISSING_XONE = 3, // auth source missing +} e_gimx_status; + void launcherFrame::OnProcessTerminated(wxProcess *process __attribute__((unused)), int status) { ButtonStart->Enable(true); StatusBar1->SetStatusText(wxEmptyString); - if(status) + status = E_GIMX_STATUS_SUCCESS; + + /* + * Get the execution status from the gimx.status file, in the system temp directory. + * + * The absence of the gimx.status file means the execution was successful, + * or that the program crashed. + */ + + wxString statusFile = wxStandardPaths::Get().GetTempDir() + wxT("/") + wxT(STATUS_FILE); + if (::wxFileExists(statusFile)) { - wxMessageBox( _("gimx error"), _("Error"), wxICON_ERROR); + ifstream infile(statusFile.mb_str(wxConvUTF8)); + if (infile.is_open()) + { + if (infile.good()) + { + string line; + getline(infile, line); + stringstream ss(line); + ss >> status; + } + infile.close(); + } + remove(statusFile.mb_str(wxConvUTF8)); } - else - { - //Save options when gimx successfully terminates. - wxCommandEvent event; - OnMenuSave(event); + switch(status) + { + case E_GIMX_STATUS_SUCCESS: + { + wxCommandEvent event; + OnMenuSave(event); + } + break; + case E_GIMX_STATUS_GENERIC_ERROR: + wxMessageBox( _("GIMX failed with a generic error (please report this)."), _("Error"), wxICON_ERROR); + break; + case E_GIMX_STATUS_ADAPTER_NOT_DETECTED: + if(Output->GetStringSelection() == _(GPP_NAME)) + { + wxMessageBox( _("Failed to detect the GPP/Cronus/Titan device."), _("Error"), wxICON_ERROR); + } + else if(Output->GetStringSelection() == _("DIY USB")) + { + wxMessageBox( _("Failed to detect the USB adapter:\n" + " . make sure to select the right port\n" + " . make sure to power on the target console\n" + "If you built the adapter yourself:\n" + " . make sure the wiring is correct (swapping RX and TX is a common mistake)\n" + " . make sure it runs the right firmware" + ), _("Error"), wxICON_ERROR); + } + else if(Output->GetStringSelection() == _("Remote GIMX")) + { + wxMessageBox( _("Failed to detect the remote GIMX instance:\n" + " . make sure to fill the right IP:port\n" + " . make sure the remote instance is running"), _("Error"), wxICON_ERROR); + } + else + { + wxMessageBox( _("Failed to detect the adapter (fallback error message)."), _("Error"), wxICON_ERROR); + } + break; + case E_GIMX_STATUS_NO_ACTIVATION: + wxMessageBox( _("GIMX exited and the activation button was not pressed."), _("Info"), wxICON_INFORMATION); + break; + case E_GIMX_STATUS_AUTH_MISSING_X360: + wxMessageBox( _("No wired Xbox 360 controller was found on USB ports."), _("Error"), wxICON_ERROR); + break; + case E_GIMX_STATUS_AUTH_MISSING_PS4: + wxMessageBox( _("No Dualshock 4 controller was found on USB ports."), _("Error"), wxICON_ERROR); + break; + case E_GIMX_STATUS_AUTH_MISSING_XONE: + wxMessageBox( _("No Xbox One controller (without 3.5mm jack) was found on USB ports."), _("Error"), wxICON_ERROR); + break; } if(openLog) { + wxString logfile = gimxLogDir + wxT(LOG_FILE); + if (::wxFileExists(logfile)) + { #ifdef WIN32 - gimxLogDir.Replace(wxT("/"), wxT("\\")); - wxExecute(wxT("explorer ") + gimxLogDir + wxT(LOG_FILE), wxEXEC_ASYNC, NULL); + logfile.Replace(wxT("/"), wxT("\\")); + wxExecute(wxT("explorer ") + logfile, wxEXEC_ASYNC, NULL); #else - wxExecute(wxT("xdg-open ") + gimxLogDir + wxT(LOG_FILE), wxEXEC_ASYNC, NULL); + wxExecute(wxT("xdg-open ") + logfile, wxEXEC_ASYNC, NULL); #endif + } + else + { + wxMessageBox( _("Failed to open log file. GIMX may have crashed (please report this)."), _("Error"), wxICON_ERROR); + } openLog = false; } - else + else if (status == E_GIMX_STATUS_GENERIC_ERROR) { long int endTime = wxGetUTCTime(); if(endTime - startTime < 5) @@ -1405,6 +1496,8 @@ void launcherFrame::OnProcessTerminated(wxProcess *process __attribute__((unused int answer = wxMessageBox(_("GIMX ran less than 5 seconds. Would you like to generate a log report?"), _("Confirm"), wxYES_NO); if (answer == wxYES) { + wxString logfile = gimxLogDir + wxT(LOG_FILE); + remove(logfile.mb_str(wxConvUTF8)); ProcessOutputChoice->SetSelection(ProcessOutputChoice->FindString(_("log file"))); wxCommandEvent event; OnButtonStartClick(event); diff --git a/shared/controller/include/controller2.h b/shared/controller/include/controller2.h index ada58b96..e5b3e9d3 100644 --- a/shared/controller/include/controller2.h +++ b/shared/controller/include/controller2.h @@ -59,7 +59,7 @@ typedef struct } axis_name_dirs; unsigned int (*fp_build_report)(int axis[AXIS_MAX], s_report_packet report[MAX_REPORTS]); void (*fp_init_report)(s_report * report); - const char * activation_button; + e_controller_axis_index activation_button; } s_controller; int clamp(int min, int val, int max); @@ -97,7 +97,7 @@ int controller_is_auth_required(e_controller_type type); void controller_get_ids(e_controller_type type, unsigned short * vid, unsigned short * pid); -const char * controller_get_activation_button(e_controller_type type); +e_controller_axis_index controller_get_activation_button(e_controller_type type); #ifdef __cplusplus } diff --git a/shared/controller/src/controller.c b/shared/controller/src/controller.c index 87fc35b8..ff2a80b8 100644 --- a/shared/controller/src/controller.c +++ b/shared/controller/src/controller.c @@ -382,11 +382,11 @@ void controller_get_ids(e_controller_type type, unsigned short * vid, unsigned s } } -const char * controller_get_activation_button(e_controller_type type) +e_controller_axis_index controller_get_activation_button(e_controller_type type) { if(type < C_TYPE_MAX) { return controllers[type]->activation_button; } - return NULL; + return 0; // no activation button } diff --git a/shared/controller/src/ds3.c b/shared/controller/src/ds3.c index 14b371a5..e3b9a487 100644 --- a/shared/controller/src/ds3.c +++ b/shared/controller/src/ds3.c @@ -265,7 +265,7 @@ static s_controller controller = .axis_name_dirs = { .nb = sizeof(axis_name_dirs)/sizeof(*axis_name_dirs), .values = axis_name_dirs }, .fp_build_report = build_report, .fp_init_report = init_report, - .activation_button = "PS", + .activation_button = sa_ps, }; void ds3_init(void) __attribute__((constructor)); diff --git a/shared/controller/src/ds4.c b/shared/controller/src/ds4.c index de227439..1e0cce99 100644 --- a/shared/controller/src/ds4.c +++ b/shared/controller/src/ds4.c @@ -377,7 +377,7 @@ static s_controller controller = .axis_name_dirs = { .nb = sizeof(axis_name_dirs)/sizeof(*axis_name_dirs), .values = axis_name_dirs }, .fp_build_report = build_report, .fp_init_report = init_report, - .activation_button = "PS", + .activation_button = ds4a_ps, }; void ds4_init(void) __attribute__((constructor)); diff --git a/shared/controller/src/g29_ps4.c b/shared/controller/src/g29_ps4.c index 10033eb0..aa047d13 100644 --- a/shared/controller/src/g29_ps4.c +++ b/shared/controller/src/g29_ps4.c @@ -283,7 +283,7 @@ static s_controller controller = .axis_name_dirs = { .nb = sizeof(axis_name_dirs)/sizeof(*axis_name_dirs), .values = axis_name_dirs }, .fp_build_report = build_report, .fp_init_report = init_report, - .activation_button = "PS", + .activation_button = g29Ps4a_ps, }; void g29Ps4_init(void) __attribute__((constructor)); diff --git a/shared/controller/src/t300rs_ps4.c b/shared/controller/src/t300rs_ps4.c index 467f8150..4e246314 100644 --- a/shared/controller/src/t300rs_ps4.c +++ b/shared/controller/src/t300rs_ps4.c @@ -208,7 +208,7 @@ static s_controller controller = .axis_name_dirs = { .nb = sizeof(axis_name_dirs)/sizeof(*axis_name_dirs), .values = axis_name_dirs }, .fp_build_report = build_report, .fp_init_report = init_report, - .activation_button = "PS", + .activation_button = t300rsPs4a_ps, }; void t300rsPs4_init(void) __attribute__((constructor)); diff --git a/shared/controller/src/x360.c b/shared/controller/src/x360.c index dfe28eaf..2d49cda3 100644 --- a/shared/controller/src/x360.c +++ b/shared/controller/src/x360.c @@ -154,7 +154,7 @@ static s_controller controller = .axis_name_dirs = { .nb = sizeof(axis_name_dirs)/sizeof(*axis_name_dirs), .values = axis_name_dirs }, .fp_build_report = build_report, .fp_init_report = init_report, - .activation_button = "guide", + .activation_button = x360a_guide, }; void x360_init(void) __attribute__((constructor)); diff --git a/shared/controller/src/xone.c b/shared/controller/src/xone.c index 439bf63f..21742b4d 100644 --- a/shared/controller/src/xone.c +++ b/shared/controller/src/xone.c @@ -183,7 +183,7 @@ static s_controller controller = .axis_name_dirs = { .nb = sizeof(axis_name_dirs)/sizeof(*axis_name_dirs), .values = axis_name_dirs }, .fp_build_report = build_report, .fp_init_report = init_report, - .activation_button = "guide", + .activation_button = xonea_guide, }; void xone_init(void) __attribute__((constructor));