/* * Azeron CLI - Command-line tool for Azeron device configuration * Copyright (C) 2024 Azeron Linux Project * * SPDX-License-Identifier: MIT */ #include #include #include #include #include "azeron.h" #define AZERON_CLI_VERSION "1.0.0" /* Command function prototypes */ int cmd_list(int argc, char *argv[]); int cmd_info(int argc, char *argv[]); int cmd_map_button(int argc, char *argv[]); int cmd_show_mappings(int argc, char *argv[]); int cmd_set_profile(int argc, char *argv[]); int cmd_save_profile(int argc, char *argv[]); int cmd_load_profile(int argc, char *argv[]); int cmd_export_config(int argc, char *argv[]); int cmd_import_config(int argc, char *argv[]); /* Command structure */ struct command { const char *name; const char *description; int (*func)(int argc, char *argv[]); }; static struct command commands[] = { {"list", "List connected Azeron devices", cmd_list}, {"info", "Show device information", cmd_info}, {"map-button", "Map a button to a key or action", cmd_map_button}, {"show-mappings", "Show current button mappings", cmd_show_mappings}, {"set-profile", "Set active profile", cmd_set_profile}, {"save-profile", "Save current configuration to profile", cmd_save_profile}, {"load-profile", "Load configuration from profile", cmd_load_profile}, {"export-config", "Export configuration to file", cmd_export_config}, {"import-config", "Import configuration from file", cmd_import_config}, {NULL, NULL, NULL} }; /* Print usage information */ static void print_usage(const char *program_name) { printf("Azeron CLI - Configuration tool for Azeron devices\n"); printf("Version: %s\n\n", AZERON_CLI_VERSION); printf("Usage: %s [options]\n\n", program_name); printf("Commands:\n"); for (int i = 0; commands[i].name != NULL; i++) { printf(" %-15s %s\n", commands[i].name, commands[i].description); } printf("\nExamples:\n"); printf(" %s list\n", program_name); printf(" %s info\n", program_name); printf(" %s map-button 5 KEY_W\n", program_name); printf(" %s set-profile 1\n", program_name); printf("\nFor help with a specific command:\n"); printf(" %s --help\n", program_name); } /* List connected devices */ int cmd_list(int argc, char *argv[]) { struct azeron_device_info *devices; size_t count; int ret; int i; (void)argc; (void)argv; ret = azeron_init(); if (ret != AZERON_SUCCESS) { fprintf(stderr, "Failed to initialize library: %s\n", azeron_error_string(ret)); return 1; } ret = azeron_device_list(&devices, &count); if (ret != AZERON_SUCCESS) { fprintf(stderr, "Failed to list devices: %s\n", azeron_error_string(ret)); azeron_exit(); return 1; } if (count == 0) { printf("No Azeron devices found.\n"); printf("Make sure your device is connected and you have proper permissions.\n"); } else { printf("Found %zu Azeron device(s):\n\n", count); for (i = 0; i < count; i++) { printf("Device %d:\n", i); printf(" Product: %s\n", devices[i].product); printf(" Manufacturer: %s\n", devices[i].manufacturer); printf(" Serial: %s\n", devices[i].serial_number); printf(" USB ID: %04x:%04x\n", devices[i].vendor_id, devices[i].product_id); printf(" Firmware: %d.%d\n", devices[i].firmware_version >> 8, devices[i].firmware_version & 0xFF); printf("\n"); } } azeron_device_list_free(devices, count); azeron_exit(); return 0; } /* Show device information */ int cmd_info(int argc, char *argv[]) { struct azeron_device *device; struct azeron_device_info info; int ret; int device_index = 0; /* Parse options */ static struct option long_options[] = { {"device", required_argument, 0, 'd'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; int opt; int option_index = 0; while ((opt = getopt_long(argc, argv, "d:h", long_options, &option_index)) != -1) { switch (opt) { case 'd': device_index = atoi(optarg); break; case 'h': printf("Usage: %s info [options]\n", argv[0]); printf("Options:\n"); printf(" -d, --device Select device by index (default: 0)\n"); printf(" -h, --help Show this help message\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; } ret = azeron_device_get_info(device, &info); if (ret != AZERON_SUCCESS) { fprintf(stderr, "Failed to get device info: %s\n", azeron_error_string(ret)); azeron_device_close(device); azeron_exit(); return 1; } printf("Device Information:\n"); printf("===================\n\n"); printf("Product: %s\n", info.product); printf("Manufacturer: %s\n", info.manufacturer); printf("Serial Number: %s\n", info.serial_number); printf("USB ID: %04x:%04x\n", info.vendor_id, info.product_id); printf("Firmware: %d.%d\n", info.firmware_version >> 8, info.firmware_version & 0xFF); printf("Profiles: %d\n", info.num_profiles); printf("Active Profile: %d\n", info.active_profile); azeron_device_close(device); azeron_exit(); return 0; } /* Show current button mappings */ int cmd_show_mappings(int argc, char *argv[]) { struct azeron_device *device; int ret; int device_index = 0; int i; /* Parse options */ static struct option long_options[] = { {"device", required_argument, 0, 'd'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; int opt; int option_index = 0; while ((opt = getopt_long(argc, argv, "d:h", long_options, &option_index)) != -1) { switch (opt) { case 'd': device_index = atoi(optarg); break; case 'h': printf("Usage: %s show-mappings [options]\n", argv[0]); printf("Options:\n"); printf(" -d, --device Select device by index (default: 0)\n"); printf(" -h, --help Show this help message\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("Button Mappings:\n"); printf("================\n\n"); printf("%-10s %-15s %s\n", "Button", "Type", "Mapping"); printf("%-10s %-15s %s\n", "------", "----", "-------"); /* For now, show placeholder since protocol isn't implemented yet */ for (i = 1; i <= 24; i++) { printf("%-10d %-15s %s\n", i, "keyboard", ""); } printf("\nNote: Button mapping functionality requires protocol reverse engineering.\n"); printf("This is a placeholder implementation.\n"); azeron_device_close(device); azeron_exit(); return 0; } /* Map button (placeholder) */ int cmd_map_button(int argc, char *argv[]) { if (argc < 3) { fprintf(stderr, "Usage: %s map-button \n", argv[0]); fprintf(stderr, "Example: %s map-button 5 KEY_W\n", argv[0]); return 1; } fprintf(stderr, "Button mapping is not yet implemented.\n"); fprintf(stderr, "Protocol reverse engineering is required for this feature.\n"); return 1; } /* Set active profile (placeholder) */ int cmd_set_profile(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "Usage: %s set-profile \n", argv[0]); fprintf(stderr, "Example: %s set-profile 1\n", argv[0]); return 1; } fprintf(stderr, "Profile switching is not yet implemented.\n"); fprintf(stderr, "Protocol reverse engineering is required for this feature.\n"); return 1; } /* Save profile (placeholder) */ int cmd_save_profile(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "Usage: %s save-profile \n", argv[0]); return 1; } fprintf(stderr, "Profile saving is not yet implemented.\n"); fprintf(stderr, "Protocol reverse engineering is required for this feature.\n"); return 1; } /* Load profile (placeholder) */ int cmd_load_profile(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "Usage: %s load-profile \n", argv[0]); return 1; } fprintf(stderr, "Profile loading is not yet implemented.\n"); fprintf(stderr, "Protocol reverse engineering is required for this feature.\n"); return 1; } /* Export config (placeholder) */ int cmd_export_config(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "Usage: %s export-config \n", argv[0]); return 1; } fprintf(stderr, "Config export is not yet implemented.\n"); fprintf(stderr, "Protocol reverse engineering is required for this feature.\n"); return 1; } /* Import config (placeholder) */ int cmd_import_config(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "Usage: %s import-config \n", argv[0]); return 1; } fprintf(stderr, "Config import is not yet implemented.\n"); fprintf(stderr, "Protocol reverse engineering is required for this feature.\n"); return 1; } /* Main function */ int main(int argc, char *argv[]) { const char *command; int i; if (argc < 2) { print_usage(argv[0]); return 1; } command = argv[1]; /* Help command */ if (strcmp(command, "help") == 0 || strcmp(command, "--help") == 0 || strcmp(command, "-h") == 0) { print_usage(argv[0]); return 0; } /* Version command */ if (strcmp(command, "version") == 0 || strcmp(command, "--version") == 0 || strcmp(command, "-v") == 0) { printf("azeron-cli version %s\n", AZERON_CLI_VERSION); return 0; } /* Find and execute command */ for (i = 0; commands[i].name != NULL; i++) { if (strcmp(command, commands[i].name) == 0) { return commands[i].func(argc - 1, argv + 1); } } fprintf(stderr, "Unknown command: %s\n", command); fprintf(stderr, "Use '%s help' for usage information.\n", argv[0]); return 1; }