#include <stddef.h> // for size_t #include <stdio.h> // for printf, fprintf, puts, NULL, etc #include "vrpn_Configure.h" // for VRPN_USE_HID #include "vrpn_HumanInterface.h" // for vrpn_HidAcceptor (ptr only), etc #include "vrpn_Types.h" // for vrpn_uint8, vrpn_uint16 #ifdef _WIN32 #include <conio.h> #endif #include <sstream> // for istringstream, basic_ios, etc #include <string> // for operator==, string, etc #if defined(VRPN_USE_HID) class HidDebug: public vrpn_HidInterface { public: HidDebug(vrpn_HidAcceptor *a); ~HidDebug() { } protected: void on_data_received(size_t bytes, vrpn_uint8 *buffer); }; HidDebug::HidDebug(vrpn_HidAcceptor *a): vrpn_HidInterface(a) { } void HidDebug::on_data_received(size_t bytes, vrpn_uint8 *buffer) { #ifdef TEST for (size_t i = 0; i < (bytes / 2); i++) { if ((i != 0) && ((i % 20) == 0)) { printf("\n"); } printf("%02X ", buffer[i]); } #else printf("%d bytes: ", static_cast<int>(bytes)); for (size_t i = 0; i < bytes; i++) { printf("%02X ", buffer[i]); } #endif // TEST puts(""); } #endif int usage(char * argv0) { printf("Usage:\n\n" "%s -h|--help\n" " Display this help text.\n\n" "%s [N]\n" " Open HID device number N (default to 0)\n\n" "%s VEND PROD [N]\n" " Open HID device number N (default to 0) that matches\n" " vendor VEND and product PROD, in _decimal_\n\n" #ifdef _WIN32 "During runtime:\n" " Press ESC to exit\n" " Press r to reconnect\n\n" #endif , argv0, argv0, argv0); return 1; } int failedOnArgument(int argNum, const char * expected, char * argv[]) { fprintf(stderr, "Failed to interpret argument %d: expected %s, got '%s' - usage help follows.\n\n", argNum, expected, argv[argNum]); return usage(argv[0]); } int main(int argc, char * argv[]) { #if defined(VRPN_USE_HID) if (argc > 1 && (std::string("-h") == argv[1] || std::string("--help") == argv[1])) { return usage(argv[0]); } vrpn_HidAcceptor * acceptor = NULL; unsigned N = 0; // Which device to open? if (argc >= 3) { vrpn_uint16 vend; std::istringstream vendS(argv[1]); if (!(vendS >> vend)) { return failedOnArgument(1, "a decimal vendor ID", argv); } vrpn_uint16 prod; std::istringstream prodS(argv[2]); if (!(prodS >> prod)) { return failedOnArgument(2, "a decimal product ID", argv); } if (argc >= 4) { std::istringstream nS(argv[3]); if (!(nS >> N)) { return failedOnArgument(3, "a number indicating which matching device to pick, or nothing for the default '0'", argv); } } printf("Will accept HID device number %u that has vendor:product %04x:%04x\n", N, vend, prod); acceptor = new vrpn_HidProductAcceptor(vend, prod); } else { if (argc == 2) { std::istringstream nS(argv[1]); if (!(nS >> N)) { return failedOnArgument(1, "a number indicating which device to pick, or nothing for the default '0'", argv); } } printf("Will accept HID device number %u\n", N); acceptor = new vrpn_HidAlwaysAcceptor; } HidDebug hid(new vrpn_HidNthMatchAcceptor(N, acceptor)); printf("HID initialized.\n"); if (hid.connected()) { printf("Connected: HID device vendor ID %u, product ID %u, aka %04x:%04x\n", static_cast<unsigned>(hid.vendor()), static_cast<unsigned>(hid.product()), static_cast<unsigned>(hid.vendor()), static_cast<unsigned>(hid.product())); } else { printf("Could not connect.\n"); return 1; } bool go = true; printf("Entering update loop.\n"); while (go) { hid.update(); #ifdef _WIN32 if (_kbhit()) switch (_getch()) { case 27: go = false; break; case 'r': case 'R': hid.reconnect(); break; } #endif // _WIN32 } return 0; #else printf("HID support not included.\n"); return 0; #endif // defined(VRPN_USE_HID) }