feat: implement cyborg joystick bulk write, global timings, and enhanced CLI mapping feedback
This commit is contained in:
@@ -26,6 +26,7 @@ int cmd_export_config(int argc, char *argv[]);
|
||||
int cmd_import_config(int argc, char *argv[]);
|
||||
int cmd_set_stick(int argc, char *argv[]);
|
||||
int cmd_read_raw(int argc, char *argv[]);
|
||||
int cmd_set_delays(int argc, char *argv[]);
|
||||
|
||||
/* Command structure */
|
||||
struct command {
|
||||
@@ -45,6 +46,7 @@ static struct command commands[] = {
|
||||
{"export-config", "Export configuration to file", cmd_export_config},
|
||||
{"import-config", "Import configuration from file", cmd_import_config},
|
||||
{"set-stick", "Configure analog stick settings", cmd_set_stick},
|
||||
{"set-delays", "Set global timing delays", cmd_set_delays},
|
||||
{"read-raw", "Read raw memory from device", cmd_read_raw},
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
@@ -189,6 +191,7 @@ int cmd_info(int argc, char *argv[])
|
||||
printf("\nStick Configuration:\n");
|
||||
printf("--------------------\n");
|
||||
printf("Mode: %s\n", azeron_stick_mode_string(stick.mode));
|
||||
printf("Angle: %d\n", stick.angle);
|
||||
printf("Deadzone: %d%%\n", stick.deadzone);
|
||||
printf("Sensitivity: %d\n", stick.sensitivity);
|
||||
printf("Response Curve: %d\n", stick.response_curve);
|
||||
@@ -251,23 +254,41 @@ int cmd_show_mappings(int argc, char *argv[])
|
||||
|
||||
printf("Button Mappings:\n");
|
||||
printf("================\n\n");
|
||||
printf("%-10s %-15s %s\n", "Button", "Type", "Mapping");
|
||||
printf("%-10s %-15s %s\n", "------", "----", "-------");
|
||||
printf("%-8s %-15s %-15s %-15s\n", "Button", "Single", "Long", "Double");
|
||||
printf("%-8s %-15s %-15s %-15s\n", "------", "------", "----", "------");
|
||||
|
||||
for (i = 0; i < 30; i++) {
|
||||
struct azeron_button_mapping mapping;
|
||||
ret = azeron_device_get_button_mapping(device, i, &mapping);
|
||||
struct azeron_button_mapping s_mapping, l_mapping, d_mapping;
|
||||
char s_str[32], l_str[32], d_str[32];
|
||||
|
||||
/* Single */
|
||||
s_mapping.action = AZERON_ACTION_SINGLE;
|
||||
ret = azeron_device_get_button_mapping(device, i, &s_mapping);
|
||||
if (ret == AZERON_SUCCESS) {
|
||||
printf("%-10d %-15s 0x%02x\n",
|
||||
i + 1,
|
||||
azeron_button_type_string(mapping.type),
|
||||
mapping.key_code);
|
||||
} else {
|
||||
printf("%-10d %-15s <error: %s>\n",
|
||||
i + 1,
|
||||
"unknown",
|
||||
azeron_error_string(ret));
|
||||
}
|
||||
const char *key = azeron_keycode_to_string(s_mapping.key_code);
|
||||
if (key) snprintf(s_str, sizeof(s_str), "%s", key);
|
||||
else snprintf(s_str, sizeof(s_str), "0x%02x", s_mapping.key_code);
|
||||
} else snprintf(s_str, sizeof(s_str), "err");
|
||||
|
||||
/* Long */
|
||||
l_mapping.action = AZERON_ACTION_LONG;
|
||||
ret = azeron_device_get_button_mapping(device, i, &l_mapping);
|
||||
if (ret == AZERON_SUCCESS) {
|
||||
const char *key = azeron_keycode_to_string(l_mapping.key_code);
|
||||
if (key) snprintf(l_str, sizeof(l_str), "%s", key);
|
||||
else snprintf(l_str, sizeof(l_str), "0x%02x", l_mapping.key_code);
|
||||
} else snprintf(l_str, sizeof(l_str), "err");
|
||||
|
||||
/* Double */
|
||||
d_mapping.action = AZERON_ACTION_DOUBLE;
|
||||
ret = azeron_device_get_button_mapping(device, i, &d_mapping);
|
||||
if (ret == AZERON_SUCCESS) {
|
||||
const char *key = azeron_keycode_to_string(d_mapping.key_code);
|
||||
if (key) snprintf(d_str, sizeof(d_str), "%s", key);
|
||||
else snprintf(d_str, sizeof(d_str), "0x%02x", d_mapping.key_code);
|
||||
} else snprintf(d_str, sizeof(d_str), "err");
|
||||
|
||||
printf("%-8d %-15s %-15s %-15s\n", i + 1, s_str, l_str, d_str);
|
||||
}
|
||||
|
||||
azeron_device_close(device);
|
||||
@@ -602,6 +623,8 @@ int cmd_set_stick(int argc, char *argv[])
|
||||
{"deadzone", required_argument, 0, 'z'},
|
||||
{"sensitivity", required_argument, 0, 's'},
|
||||
{"curve", required_argument, 0, 'c'},
|
||||
{"mode", required_argument, 0, 'm'},
|
||||
{"angle", required_argument, 0, 'a'},
|
||||
{"invert-x", no_argument, 0, 'x'},
|
||||
{"invert-y", no_argument, 0, 'y'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
@@ -613,16 +636,29 @@ int cmd_set_stick(int argc, char *argv[])
|
||||
|
||||
/* Initialize defaults from current config if possible, or zeros */
|
||||
memset(&stick, 0, sizeof(stick));
|
||||
bool dz_set = false, sens_set = false, curve_set = false;
|
||||
bool dz_set = false, sens_set = false, curve_set = false, mode_set = false, angle_set = false;
|
||||
bool x_set = false, y_set = false;
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "d:z:s:c:xyh", long_options, &option_index)) != -1) {
|
||||
while ((opt = getopt_long(argc, argv, "d:z:s:c:m:a:xyh", long_options, &option_index)) != -1) {
|
||||
switch (opt) {
|
||||
case 'd': device_index = atoi(optarg); break;
|
||||
case 'z': stick.deadzone = atoi(optarg); dz_set = true; break;
|
||||
case 's': stick.sensitivity = atoi(optarg); sens_set = true; break;
|
||||
case 'c': stick.response_curve = atoi(optarg); curve_set = true; break;
|
||||
case 'x': stick.invert_x = true; break;
|
||||
case 'y': stick.invert_y = true; break;
|
||||
case 'm':
|
||||
if (strcmp(optarg, "analog") == 0) stick.mode = AZERON_STICK_ANALOG;
|
||||
else if (strcmp(optarg, "digital_4") == 0) stick.mode = AZERON_STICK_DIGITAL_4;
|
||||
else if (strcmp(optarg, "digital_8") == 0) stick.mode = AZERON_STICK_DIGITAL_8;
|
||||
else if (strcmp(optarg, "mouse") == 0) stick.mode = AZERON_STICK_MOUSE;
|
||||
else {
|
||||
fprintf(stderr, "Error: Invalid mode '%s'. Use: analog, digital_4, digital_8, mouse\n", optarg);
|
||||
return 1;
|
||||
}
|
||||
mode_set = true;
|
||||
break;
|
||||
case 'a': stick.angle = atoi(optarg); angle_set = true; break;
|
||||
case 'x': stick.invert_x = true; x_set = true; break;
|
||||
case 'y': stick.invert_y = true; y_set = true; break;
|
||||
case 'h':
|
||||
printf("Usage: %s set-stick [options]\n", argv[0]);
|
||||
printf("Options:\n");
|
||||
@@ -630,6 +666,8 @@ int cmd_set_stick(int argc, char *argv[])
|
||||
printf(" -z, --deadzone <0-100> Set deadzone percentage\n");
|
||||
printf(" -s, --sensitivity <0-255> Set sensitivity\n");
|
||||
printf(" -c, --curve <0-255> Set response curve\n");
|
||||
printf(" -m, --mode <mode> Set mode (analog, digital_4, digital_8, mouse)\n");
|
||||
printf(" -a, --angle <0-255> Set stick angle\n");
|
||||
printf(" -x, --invert-x Invert X axis\n");
|
||||
printf(" -y, --invert-y Invert Y axis\n");
|
||||
return 0;
|
||||
@@ -659,6 +697,10 @@ int cmd_set_stick(int argc, char *argv[])
|
||||
if (!dz_set) stick.deadzone = current.deadzone;
|
||||
if (!sens_set) stick.sensitivity = current.sensitivity;
|
||||
if (!curve_set) stick.response_curve = current.response_curve;
|
||||
if (!mode_set) stick.mode = current.mode;
|
||||
if (!angle_set) stick.angle = current.angle;
|
||||
if (!x_set) stick.invert_x = current.invert_x;
|
||||
if (!y_set) stick.invert_y = current.invert_y;
|
||||
}
|
||||
|
||||
printf("Updating stick configuration...\n");
|
||||
@@ -752,6 +794,74 @@ int cmd_read_raw(int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set global timing delays */
|
||||
int cmd_set_delays(int argc, char *argv[])
|
||||
{
|
||||
struct azeron_device *device;
|
||||
int ret;
|
||||
int device_index = 0;
|
||||
uint16_t long_press = 500;
|
||||
uint16_t double_click = 200;
|
||||
|
||||
/* Parse options */
|
||||
static struct option long_options[] = {
|
||||
{"device", required_argument, 0, 'd'},
|
||||
{"long", required_argument, 0, 'l'},
|
||||
{"double", required_argument, 0, 'b'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
int opt;
|
||||
int option_index = 0;
|
||||
while ((opt = getopt_long(argc, argv, "d:l:b:h", long_options, &option_index)) != -1) {
|
||||
switch (opt) {
|
||||
case 'd': device_index = atoi(optarg); break;
|
||||
case 'l': long_press = (uint16_t)atoi(optarg); break;
|
||||
case 'b': double_click = (uint16_t)atoi(optarg); break;
|
||||
case 'h':
|
||||
printf("Usage: %s set-delays [options]\n", argv[0]);
|
||||
printf("Options:\n");
|
||||
printf(" -d, --device <index> Select device (default: 0)\n");
|
||||
printf(" -l, --long <ms> Set long press delay in ms (default: 500)\n");
|
||||
printf(" -b, --double <ms> Set double click delay in ms (default: 200)\n");
|
||||
return 0;
|
||||
default:
|
||||
fprintf(stderr, "Unknown option. Use --help for usage.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
ret = azeron_init();
|
||||
if (ret != AZERON_SUCCESS) {
|
||||
fprintf(stderr, "Failed to initialize library: %s\n", azeron_error_string(ret));
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = azeron_device_open_index(&device, device_index);
|
||||
if (ret != AZERON_SUCCESS) {
|
||||
fprintf(stderr, "Failed to open device %d: %s\n", device_index, azeron_error_string(ret));
|
||||
azeron_exit();
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Setting global delays: Long Press = %dms, Double Click = %dms...\n", long_press, double_click);
|
||||
ret = azeron_device_set_global_timings(device, long_press, double_click);
|
||||
if (ret != AZERON_SUCCESS) {
|
||||
fprintf(stderr, "Failed to set global timings: %s\n", azeron_error_string(ret));
|
||||
azeron_device_close(device);
|
||||
azeron_exit();
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Delays updated successfully.\n");
|
||||
|
||||
azeron_device_close(device);
|
||||
azeron_exit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Main function */
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user