Files

copied
Last update 7 years 11 months by Sergey Sharybin
FilesSoftware
..
main.cc
makefile
main.cc
/* Copyright (C) 2015 Sergey Sharybin <sergey.vfx@gmail.com> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #include <errno.h> #include <signal.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <libusb.h> // #define VERSION "0.1.0" #define VENDOR_ID 0x04d8 #define PRODUCT_ID 0x003f #define COMMAND_TEST 0x80 #define COMMAND_SWITCH_PRESS 0x81 #define COMMAND_CFG_SET_AUTOBOOT 0x82 #define COMMAND_CFG_SET_IP 0x83 #define COMMAND_CFG_SET_MAC 0x84 #define COMMAND_CFG_SET_PC_NAME 0x85 #define COMMAND_CFG_GET_AUTOBOOT 0x86 #define COMMAND_CFG_GET_IP 0x87 #define COMMAND_CFG_GET_MAC 0x88 #define COMMAND_GET_STATUS 0x89 #define COMMAND_CFG_GET_PC_NAME 0x90 #define NUM_PCS 2 namespace { const int PACKET_INT_LEN = 64; const int INTERFACE = 0; const int ENDPOINT_INT_IN = 0x81; /* endpoint 0x81 address for IN */ const int ENDPOINT_INT_OUT = 0x01; /* endpoint 1 address for OUT */ const int TIMEOUT = 5000; /* timeout in ms */ static libusb_device_handle *devh = NULL; static libusb_context *ctx = NULL; int find_lvr_hidusb(void) { devh = libusb_open_device_with_vid_pid(ctx, VENDOR_ID, PRODUCT_ID); return devh ? 0 : -EIO; } int send_buffer(unsigned char buffer[PACKET_INT_LEN]) { int transferred; int r = libusb_interrupt_transfer(devh, ENDPOINT_INT_OUT, buffer, PACKET_INT_LEN, &transferred, TIMEOUT); if (r < 0) { fprintf(stderr, "Interrupt write error %s\n", libusb_error_name(r)); return r; } return 0; } int send_command(int command, int arg, const char *data, int len) { unsigned char buffer[PACKET_INT_LEN] = {0}; buffer[0] = command; buffer[1] = arg; memcpy(buffer + 2, data, len); send_buffer(buffer); return 0; } int send_command(int command, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0, int arg5 = 0, int arg6 = 0) { unsigned char buffer[PACKET_INT_LEN] = {0}; buffer[0] = command; buffer[1] = arg1; buffer[2] = arg2; buffer[3] = arg3; buffer[4] = arg4; buffer[5] = arg5; buffer[6] = arg6; return send_buffer(buffer); } int read_answer(unsigned char *buffer) { int r, transferred; r = libusb_interrupt_transfer(devh, ENDPOINT_INT_IN, buffer, PACKET_INT_LEN, &transferred, TIMEOUT); if (r < 0) { fprintf(stderr, "Interrupt read error %s\n", libusb_error_name(r)); return r; } return 0; } void send_test_command(void) { send_command(COMMAND_TEST); } void send_press_command(int pc, bool force) { send_command(COMMAND_SWITCH_PRESS, pc, force ? 1 : 0); } void send_set_ip_command(const unsigned char ip[4]) { send_command(COMMAND_CFG_SET_IP, ip[0], ip[1], ip[2], ip[3]); } void send_set_mac_command(const unsigned char mac[6]) { send_command(COMMAND_CFG_SET_MAC, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } void send_set_autoboot_command(int pc, bool enabled) { send_command(COMMAND_CFG_SET_AUTOBOOT, pc, enabled ? 1 : 0); } void send_set_name_command(int pc, const char *name) { send_command(COMMAND_CFG_SET_PC_NAME, pc, name, strlen(name)); } void send_get_ip_command(void) { send_command(COMMAND_CFG_GET_IP); } void retrieve_ip(unsigned char ip[4]) { unsigned char buffer[64]; read_answer(buffer); memcpy(ip, buffer, 4); } void send_get_mac_command(void) { send_command(COMMAND_CFG_GET_MAC); } void retrieve_mac(unsigned char mac[6]) { unsigned char buffer[64]; read_answer(buffer); memcpy(mac, buffer, 6); } void send_get_status_command(void) { send_command(COMMAND_GET_STATUS); } void retrieve_status(unsigned char buffer[64]) { read_answer(buffer); } void send_get_autoboot_command(int pc) { send_command(COMMAND_CFG_GET_AUTOBOOT, pc); } bool retrieve_autoboot(void) { unsigned char buffer[64]; read_answer(buffer); return buffer[0] != 0; } void send_get_name_command(int pc) { send_command(COMMAND_CFG_GET_PC_NAME, pc); } void retrieve_name(unsigned char name[64]) { read_answer(name); } bool check_pc_valid(int pc) { return pc >= 0 && pc <= NUM_PCS; } bool parse_press_command(int argc, char **argv) { if ((argc != 3 && argc != 4) || (argc == 4 && strcmp(argv[3], "force") != 0)) { printf("Usage: %s press <pc> [force]\n", argv[0]); return false; } int pc = atoi(argv[2]); if (!check_pc_valid(pc)) { fprintf(stderr, "Invalid PC number\n"); return false; } bool force = argc == 4; send_press_command(pc, force); return true; } void parse_ip_addr(const char *value, unsigned char ip[4]) { sscanf(value, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3]); } void parse_mac_addr(const char *value, unsigned char mac[6]) { int tmac[6]; sscanf(value, "%x:%x:%x:%x:%x:%x", &tmac[0], &tmac[1], &tmac[2], &tmac[3], &tmac[4], &tmac[5]); mac[0] = tmac[0]; mac[1] = tmac[1]; mac[2] = tmac[2]; mac[3] = tmac[3]; mac[4] = tmac[4]; mac[5] = tmac[5]; } bool parse_set_global_command(int argc, char **argv) { /* Number of arguments has been already checked by callee. */ const char *variable = argv[2]; const char *value = argv[3]; if (strcmp(variable, "ip") == 0) { unsigned char ip[4]; parse_ip_addr(value, ip); send_set_ip_command(ip); } else if (strcmp(variable, "mac") == 0) { unsigned char mac[6]; parse_mac_addr(value, mac); send_set_mac_command(mac); } else { printf("Unknown variable %s. " "Supported variables are: ip, mac.\n", variable); return false; } return true; } bool parse_set_pc_command(int argc, char **argv) { /* Number of arguments has been already checked by callee. */ int pc = atoi(argv[2]); if (!check_pc_valid(pc)) { fprintf(stderr, "Invalid PC number\n"); return false; } const char *variable = argv[3]; const char *value = argv[4]; if (strcmp(variable, "autoboot") == 0) { if (strcmp(value, "on") != 0 && strcmp(value, "off") != 0) { printf("Unsupported value %s. Supported values: on, off\n", value); return false; } bool autoboot = strcmp(value, "on") == 0; send_set_autoboot_command(pc, autoboot); } else if (strcmp(variable, "name") == 0) { send_set_name_command(pc, value); } else { printf("Unknown variable %s. " "Supported variables are: autoboot, name.\n", variable); return false; } return true; } bool parse_set_command(int argc, char **argv) { if (argc == 4) { return parse_set_global_command(argc, argv); } else if (argc == 5) { return parse_set_pc_command(argc, argv); } printf("Usage: %s set [<pc>] <variable> <value>\n", argv[0]); return false; } void retrieve_and_print_ip(void) { unsigned char ip[4]; send_get_ip_command(); retrieve_ip(ip); printf("IP address: %d:%d:%d:%d\n", ip[0], ip[1], ip[2], ip[3]); } void retrieve_and_print_mac(void) { unsigned char mac[6]; send_get_mac_command(); retrieve_mac(mac); printf("Mac address: %x:%x:%x:%x:%x:%x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } bool parse_get_global_command(int argc, char **argv) { /* Number of arguments has been already checked by callee. */ const char *variable = argv[2]; if (strcmp(variable, "ip") == 0) { retrieve_and_print_ip(); } else if (strcmp(variable, "mac") == 0) { retrieve_and_print_mac(); } else if (strcmp(variable, "status") == 0) { retrieve_and_print_ip(); retrieve_and_print_mac(); unsigned char buffer[64]; send_get_status_command(); retrieve_status(buffer); printf("Number of computers: %d\n", buffer[0]); for (int i = 0; i < buffer[0]; ++i) { unsigned char name[64]; send_get_name_command(i); retrieve_name(name); printf(" Computer %d:\n", i); printf(" Name: %s\n", name); printf(" Status: %d\n", buffer[i + 1]); } } else { printf("Unknown variable %s. " "Supported variables are: ip, mac, status.\n", variable); return false; } return true; } bool parse_get_pc_command(int argc, char **argv) { /* Number of arguments has been already checked by callee. */ int pc = atoi(argv[2]); if (!check_pc_valid(pc)) { fprintf(stderr, "Invalid PC number\n"); return false; } const char *variable = argv[3]; if (strcmp(variable, "autoboot") == 0) { send_get_autoboot_command(pc); bool enabled = retrieve_autoboot(); printf("Computer %d: Autoboot is %s\n", pc, enabled ? "disabled" : "enabled"); } else if (strcmp(variable, "name") == 0) { unsigned char name[64]; send_get_name_command(pc); retrieve_name(name); printf("Computer name: %s\n", name); } else { printf("Unknown variable %s. " "Supported variables are: autoboot, name.\n", variable); return false; } return true; } bool parse_get_command(int argc, char **argv) { if (argc == 3) { return parse_get_global_command(argc, argv); } else if (argc == 4) { return parse_get_pc_command(argc, argv); } printf("Usage: %s set [<pc>] <variable> <value>\n", argv[0]); return false; } void print_usage(const char *argv0) { printf("Usage: %s test|" "press <pc> <force>|" "set <variable> [<pc>] <value>|" "get <variable> [<pc>]\n", argv0); }; } /* namespace */ int main(int argc, char **argv) { if (argc < 2) { print_usage(argv[0]); return EXIT_FAILURE; } int r = libusb_init(&ctx); if (r < 0) { fprintf(stderr, "Failed to initialise libusb\n"); return EXIT_FAILURE; } /* Set verbosity level to 3, as suggested in the documentation. */ libusb_set_debug(ctx, 3); r = find_lvr_hidusb(); if (r < 0) { fprintf(stderr, "Could not find/open LVR Generic HID device\n"); return EXIT_FAILURE; } printf("Successfully find the LVR Generic HID device\n"); libusb_detach_kernel_driver(devh, 0); #if 0 r = libusb_set_configuration(devh, 1); if (r < 0) { fprintf(stderr, "libusb_set_configuration error %d\n", r); goto out; } printf("Successfully set usb configuration 1\n"); #endif r = libusb_claim_interface(devh, 0); if (r < 0) { fprintf(stderr, "libusb_claim_interface error %d\n", r); goto out; } printf("Successfully claimed interface\n"); if (!strcmp(argv[1], "test")) { send_test_command(); } else if (!strcmp(argv[1], "press")) { parse_press_command(argc, argv); } else if (!strcmp(argv[1], "set")) { parse_set_command(argc, argv); } else if (!strcmp(argv[1], "get")) { parse_get_command(argc, argv); } else { print_usage(argv[0]); } libusb_release_interface(devh, 0); out: /* libusb_reset_device(devh); */ libusb_close(devh); libusb_exit(ctx); return r == 0 ? EXIT_SUCCESS : -EXIT_FAILURE; }
Report a bug