This commit is contained in:
vx-clutch
2026-04-09 17:29:41 -04:00
parent 85c20db9b2
commit 5c22803d15
6 changed files with 379 additions and 7 deletions

View File

@@ -17,16 +17,20 @@ install: $(BIN)
mkdir -p $(DESTDIR)$(PREFIX)/bin
cp -f $(BIN) $(DESTDIR)$(PREFIX)/bin/$(BIN)
chmod 755 $(DESTDIR)$(PREFIX)/bin/$(BIN)
mkdir -p $(DESTDIR)$(MANPREFIX)/man1
cp -f frcctrlmgr.1 $(DESTDIR)$(MANPREFIX)/man1/
chmod 644 $(DESTDIR)$(MANPREFIX)/man1/frcctrlmgr.1
uninstall:
rm -f $(DESTDIR)$(PREFIX)/bin/$(BIN)
rm -f $(DESTDIR)$(PREFIX)/bin/$(BIN) \
$(DESTDIR)$(MANPREFIX)/man1/frcctrlmgr.1
clean:
rm -f $(OBJ) $(BIN) $(DIST).tar.gz
dist: clean
mkdir -p $(DIST)
cp -R src config.mk Makefile $(DIST)
cp -R src config.mk Makefile frcctrlmgr.1 LICENSE README $(DIST)
tar -czf $(DIST).tar.gz $(DIST)
rm -rf $(DIST)

BIN
frcctrlmgr Executable file

Binary file not shown.

27
frcctrlmgr.1 Normal file
View File

@@ -0,0 +1,27 @@
.TH VXC "1" "April 2026" "frcctrlmgr v0.1" "User Commands"
.SH NAME
frcctrlmgr \- manual page for frcctrlmgr v0.1
.SH SYNOPSIS
.B frcctrlmgr
[\fI\,OPTION\/\fR]... \fI\,<version> <dir>\/\fR
.SH DESCRIPTION
A simple way to display the control schema of your robot.
.SH OPTIONS
.TP
\fB\-h, \-\-help\fR
print this help and exit
.TP
\fB\-v, \-\-version\fR
output version information
.TP
\fB\-D, --display\fR
displays a diagram of the Thrustmaster and the Xbox controller.
.TP
\fB\-j\fR
output the controls in a JSON format.
.TP
.SH COPYRIGHT
Copyright \(co 2025\-2026 fSD.
.br
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

View File

@@ -1,22 +1,301 @@
#include "frcctrlmgr.h"
char *argv0;
bool use_json = false;
void usage(int code) {
printf("usage: %s: [-h help] [-v]\n", argv0);
static void usage(int code)
{
printf("usage: %s: [--help] [--diagram] [-vhD]\n", argv0);
exit(code);
}
static void display_disgrams()
{
puts("|1|2|3| 1234 |1|2|3|");
puts("|4|5|6| |4|5|6|");
exit(0);
}
static void die(const char *fmt, ...)
{
printf("%s: ", argv0);
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
putchar('\n');
exit(1);
}
static char *join_path(const char *a, const char *b) {
if (!a) a = "";
if (!b) b = "";
size_t la = strlen(a), lb = strlen(b);
int a_has = la > 0 && a[la-1] == '/';
int b_has = lb > 0 && b[0] == '/';
size_t need = la + lb + 2;
char *res = malloc(need);
if (!res) return NULL;
if (la == 0) {
snprintf(res, need, "%s", b);
} else if (lb == 0) {
snprintf(res, need, "%s", a);
} else if (a_has && b_has) {
snprintf(res, need, "%s%s", a, b + 1);
} else if (!a_has && !b_has) {
snprintf(res, need, "%s/%s", a, b);
} else {
snprintf(res, need, "%s%s", a, b);
}
return res;
}
static const char *controller_kind_str(ControllerKind k)
{
switch (k) {
case JOYSTICK: return "JOYSTICK";
case XBOX: return "XBOX";
default: return "UNKNOWN";
}
}
static const char *controller_action_str(ControllerAction a)
{
switch (a) {
case JOYSTICK_ONE: return "JOYSTICK_ONE";
case JOYSTICK_TWO: return "JOYSTICK_TWO";
case JOYSTICK_THREE: return "JOYSTICK_THREE";
case JOYSTICK_FOUR: return "JOYSTICK_FOUR";
case JOYSTICK_FIVE: return "JOYSTICK_FIVE";
case JOYSTICK_SIX: return "JOYSTICK_SIX";
case JOYSTICK_SEVEN: return "JOYSTICK_SEVEN";
case JOYSTICK_EIGHT: return "JOYSTICK_EIGHT";
case JOYSTICK_NINE: return "JOYSTICK_NINE";
case JOYSTICK_TEN: return "JOYSTICK_TEN";
case JOYSTICK_ELEVEN: return "JOYSTICK_ELEVEN";
case JOYSTICK_TWELVE: return "JOYSTICK_TWELVE";
case JOYSTICK_THIRTEEN: return "JOYSTICK_THIRTEEN";
case JOYSTICK_FOURTEEN: return "JOYSTICK_FOURTEEN";
case JOYSTICK_FIFTEEN: return "JOYSTICK_FIFTEEN";
case JOYSTICK_SIXTEEN: return "JOYSTICK_SIXTEEN";
case XBOX_BACK: return "XBOX_BACK";
case XBOX_START: return "XBOX_START";
case XBOX_X: return "XBOX_X";
case XBOX_Y: return "XBOX_Y";
case XBOX_B: return "XBOX_B";
case XBOX_A: return "XBOX_A";
case XBOX_LEFTBUMPER: return "XBOX_LEFTBUMPER";
case XBOX_RIGHTBUMPER: return "XBOX_RIGHTBUMPER";
case XBOX_LEFTSTICK: return "XBOX_LEFTSTICK";
case XBOX_RIGHTSTICK: return "XBOX_RIGHTSTICK";
case XBOX_LEFTTRIGGER: return "XBOX_LEFTTRIGGER";
case XBOX_RIGHTTRIGGER: return "XBOX_RIGHTTRIGGER";
case XBOX_UP: return "XBOX_UP";
case XBOX_DOWN: return "XBOX_DOWN";
case XBOX_LEFT: return "XBOX_LEFT";
case XBOX_RIGHT: return "XBOX_RIGHT";
case XBOX_NORTH: return "XBOX_NORTH";
case XBOX_NORTHEAST: return "XBOX_NORTHEAST";
case XBOX_EAST: return "XBOX_EAST";
case XBOX_SOUTHEAST: return "XBOX_SOUTHEAST";
case XBOX_SOUTH: return "XBOX_SOUTH";
case XBOX_SOUTHWEST: return "XBOX_SOUTHWEST";
case XBOX_WEST: return "XBOX_WEST";
case XBOX_NORTHWEST: return "XBOX_NORTHWEST";
default: return "UNKNOWN";
}
}
static ControllerAction controller_str_action(char *a)
{
if (strcmp(a, "JOYSTICK_ONE") == 0)
return JOYSTICK_ONE;
else if (strcmp(a, "JOYSTICK_TWO") == 0)
return JOYSTICK_TWO;
else if (strcmp(a, "JOYSTICK_THREE") == 0)
return JOYSTICK_THREE;
else if (strcmp(a, "JOYSTICK_FOUR") == 0)
return JOYSTICK_FOUR;
else if (strcmp(a, "JOYSTICK_FIVE") == 0)
return JOYSTICK_FIVE;
else if (strcmp(a, "JOYSTICK_SIX") == 0)
return JOYSTICK_SIX;
else if (strcmp(a, "JOYSTICK_SEVEN") == 0)
return JOYSTICK_SEVEN;
else if (strcmp(a, "JOYSTICK_EIGHT") == 0)
return JOYSTICK_EIGHT;
else if (strcmp(a, "JOYSTICK_NINE") == 0)
return JOYSTICK_NINE;
else if (strcmp(a, "JOYSTICK_TEN") == 0)
return JOYSTICK_TEN;
else if (strcmp(a, "JOYSTICK_ELEVEN") == 0)
return JOYSTICK_ELEVEN;
else if (strcmp(a, "JOYSTICK_TWELVE") == 0)
return JOYSTICK_TWELVE;
else if (strcmp(a, "JOYSTICK_THIRTEEN") == 0)
return JOYSTICK_THIRTEEN;
else if (strcmp(a, "JOYSTICK_FOURTEEN") == 0)
return JOYSTICK_FOURTEEN;
else if (strcmp(a, "JOYSTICK_FIFTEEN") == 0)
return JOYSTICK_FIFTEEN;
else if (strcmp(a, "JOYSTICK_SIXTEEN") == 0)
return JOYSTICK_SIXTEEN;
else if (strcmp(a, "XBOX_BACK") == 0)
return XBOX_BACK;
else if (strcmp(a, "XBOX_START") == 0)
return XBOX_START;
else if (strcmp(a, "XBOX_X") == 0)
return XBOX_X;
else if (strcmp(a, "XBOX_Y") == 0)
return XBOX_Y;
else if (strcmp(a, "XBOX_B") == 0)
return XBOX_B;
else if (strcmp(a, "XBOX_A") == 0)
return XBOX_A;
else if (strcmp(a, "XBOX_LEFTBUMPER") == 0)
return XBOX_LEFTBUMPER;
else if (strcmp(a, "XBOX_RIGHTBUMPER") == 0)
return XBOX_RIGHTBUMPER;
else if (strcmp(a, "XBOX_LEFTSTICK") == 0)
return XBOX_LEFTSTICK;
else if (strcmp(a, "XBOX_RIGHTSTICK") == 0)
return XBOX_RIGHTSTICK;
else if (strcmp(a, "XBOX_LEFTTRIGGER") == 0)
return XBOX_LEFTTRIGGER;
else if (strcmp(a, "XBOX_RIGHTTRIGGER") == 0)
return XBOX_RIGHTTRIGGER;
else if (strcmp(a, "XBOX_UP") == 0)
return XBOX_UP;
else if (strcmp(a, "XBOX_DOWN") == 0)
return XBOX_DOWN;
else if (strcmp(a, "XBOX_LEFT") == 0)
return XBOX_LEFT;
else if (strcmp(a, "XBOX_RIGHT") == 0)
return XBOX_RIGHT;
else if (strcmp(a, "XBOX_NORTH") == 0)
return XBOX_NORTH;
else if (strcmp(a, "XBOX_NORTHEAST") == 0)
return XBOX_NORTHEAST;
else if (strcmp(a, "XBOX_EAST") == 0)
return XBOX_EAST;
else if (strcmp(a, "XBOX_SOUTHEAST") == 0)
return XBOX_SOUTHEAST;
else if (strcmp(a, "XBOX_SOUTH") == 0)
return XBOX_SOUTH;
else if (strcmp(a, "XBOX_SOUTHWEST") == 0)
return XBOX_SOUTHWEST;
else if (strcmp(a, "XBOX_WEST") == 0)
return XBOX_WEST;
else if (strcmp(a, "XBOX_NORTHWEST") == 0)
return XBOX_NORTHWEST;
die("%s:%s", __FILE__, __LINE__);
return XBOX_A; // dummy
}
int print_control(Control control, bool fmt_json)
{
if (fmt_json) {
return printf(
"{\"controller\":\"%s\",\"button\":\"%s\",\"action\":\"%s\"}\n",
controller_kind_str(control.controller),
controller_action_str(control.button),
control.action ? control.action : ""
);
}
return printf(
"controller=%s button=%s action=%s\n",
controller_kind_str(control.controller),
controller_action_str(control.button),
control.action ? control.action : ""
);
}
static char *trim_string(char *str) {
if (!str) return NULL;
size_t len = strlen(str);
size_t start = 0;
size_t end = len - 1;
while (isspace(str[start])) start++;
while (end > start && isspace(str[end])) end--;
char *result = malloc(end - start + 2);
if (!result) return NULL;
strncpy(result, str + start, end - start + 1);
result[end - start + 1] = '\0';
return result;
}
int read_wpiproject(Control *output, char *root)
{
FILE *fp = fopen(join_path(root, "src/main/java/com/adambots/RobotContainer.java"), "r");
char buf[BUFSIZ];
bool found_configure_bindings_start = false;
int output_i = 0;
if (!fp)
die("failed to read: %s", root);
while (fgets(buf, sizeof(buf), fp)) {
char *p = buf;
while (*p && isspace((unsigned char)*p))
p++;
if (strncmp(p, "Buttons.", 8) == 0) {
unsigned char c = p[8];
if (c && isupper(c)) {
// Buttons.XboxStartButton.onTrue(
// 17^
ControllerKind controller = XBOX;
ControllerAction button = controller_str_action("XBOX_A");
print_control((Control){
.controller = controller,
.button = button,
.action = ""
}, use_json);
}
}
}
fclose(fp);
return 0;
}
int main(int argc, char *argv[]) {
argv0 = argv[0];
argv0 = basename(argv[0]);
char *project;
if (argc < 2)
usage(1);
for (int i = 0; i < argc; ++i) {
if (STRCMP("--help"))
usage(0);
if (STRCMP("-h"))
else if (STRCMP("-h"))
usage(0);
if (STRCMP("-v"))
else if (STRCMP("-v"))
printf("%s/%s\n", argv0, VERSION);
else if (STRCMP("-j"))
use_json = true;
else if (STRCMP("--diagram") || STRCMP("-D"))
display_disgrams();
else if (argv[i][0] == '-')
die("unknown option: %s", argv[i]);
else
project = argv[i];
}
Control *output = malloc(sizeof(Control) * 40);
read_wpiproject(output, project);
return 0;
}

View File

@@ -3,10 +3,72 @@
#define VERSION "0.1"
#include <ctype.h>
#include <libgen.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STRCMP(x) !strcmp(argv[i], x)
typedef enum {
JOYSTICK,
XBOX,
} ControllerKind;
typedef enum {
JOYSTICK_ONE,
JOYSTICK_TWO,
JOYSTICK_THREE,
JOYSTICK_FOUR,
JOYSTICK_FIVE,
JOYSTICK_SIX,
JOYSTICK_SEVEN,
JOYSTICK_EIGHT,
JOYSTICK_NINE,
JOYSTICK_TEN,
JOYSTICK_ELEVEN,
JOYSTICK_TWELVE,
JOYSTICK_THIRTEEN,
JOYSTICK_FOURTEEN,
JOYSTICK_FIFTEEN,
JOYSTICK_SIXTEEN,
XBOX_BACK,
XBOX_START,
XBOX_X,
XBOX_Y,
XBOX_B,
XBOX_A,
XBOX_LEFTBUMPER,
XBOX_RIGHTBUMPER,
XBOX_LEFTSTICK,
XBOX_RIGHTSTICK,
XBOX_LEFTTRIGGER,
XBOX_RIGHTTRIGGER,
XBOX_UP,
XBOX_DOWN,
XBOX_LEFT,
XBOX_RIGHT,
XBOX_NORTH,
XBOX_NORTHEAST,
XBOX_EAST,
XBOX_SOUTHEAST,
XBOX_SOUTH,
XBOX_SOUTHWEST,
XBOX_WEST,
XBOX_NORTHWEST,
} ControllerAction;
typedef struct {
ControllerKind controller;
ControllerAction button;
char *action;
} Control;
int print_control(Control, bool);
int read_wpiproject(Control*, char *);
#endif // FRCTRLMGR_H_

BIN
src/frcctrlmgr.o Normal file

Binary file not shown.