linux-input/test/raw.cpp

Go to the documentation of this file.
00001 /*
00002  * raw.cpp
00003  *
00004  * Copyright (C) 2009  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  * Performs raw lookups and reads of linux input devices (/dev/input/jsX files)
00008  */
00009 
00010 // includes --------------------------------------------------------------------
00011 #include <linux/joystick.h>
00012 #include <iostream>
00013 #include <time.h>
00014 
00015 #include "common/common.h"
00016 #include "perf/perf.h"
00017 #include "util/file.h"
00018 
00019 
00020 ////////////////////////////////////////////////////////////////////////////////
00021 //
00022 //      static helper methods
00023 //
00024 ////////////////////////////////////////////////////////////////////////////////
00025 
00026 static void
00027 doTest
00028 (
00029 IN const char * path
00030 )
00031 {
00032         THROW(path, "null device path");
00033 
00034         DPRINTF("path: %s", path);
00035         smart_fd fd;
00036         THROW(fd.open(path, O_RDONLY), "Failed to open device path: " << path);
00037 
00038         // get the name of the device
00039         const int bufsize = 1024;
00040         char devname[bufsize];
00041         THROW(ioctl(fd, JSIOCGNAME(bufsize), devname) >= 0,
00042             "Failed to acquire device name");
00043         DPRINTF("Device name: '%s'", devname);
00044 
00045         // get the number of axes
00046         unsigned char nAxes;
00047         THROW(ioctl(fd, JSIOCGAXES, &nAxes) >= 0,
00048             "Failed to determine number of axes");
00049         DPRINTF("Number of axes: %d", nAxes);
00050 
00051         // get the number of buttons
00052         unsigned char nButtons;
00053         THROW(ioctl(fd, JSIOCGBUTTONS, &nButtons) >= 0,
00054             "Failed to determine number of buttons");
00055         DPRINTF("Number of buttons: %d", nButtons);
00056 
00057         // set to non-blocking now
00058         THROW(!fcntl(fd, F_SETFL, O_NONBLOCK),
00059             "Failed to set device path as nonblocking");
00060 
00061         // keep polling
00062         const int desiredHz = 100;
00063         int msSleep = 1000 / desiredHz;
00064         DPRINTF("Want to run at %d Hz", desiredHz);
00065         DPRINTF("  That means polling every %d milliseconds", msSleep);
00066         long nsSleep = 1000 * 1000 * msSleep;
00067         DPRINTF("  Which is %ld nanoseconds", nsSleep);
00068         struct timespec ts;
00069         ts.tv_sec = 0;
00070         ts.tv_nsec = nsSleep;
00071 
00072         // keep state here
00073         const int nMax = 128;
00074         THROW(nAxes <= nMax, "Too many axes!");
00075         THROW(nButtons <= nMax, "Too many buttons!");
00076         short axes[nMax];
00077         byte_t buttons[nMax];
00078 
00079         // loop
00080         printf("\n");
00081         for (;;) {
00082                 nanosleep(&ts, NULL);
00083 
00084                 // poll events
00085                 int nEvents = 0;
00086                 struct js_event events[32];
00087                 int mask = 0x0f;
00088                 while (true) {
00089                         int len = read(fd, events, sizeof(events));
00090                         if (len <= 0)
00091                                 break;          // no more events!
00092 
00093                         nEvents = len / sizeof(events[0]);
00094                         for (int i = 0; i < nEvents; ++i) {
00095                                 switch (events[i].type & mask) {
00096                                 case JS_EVENT_AXIS:
00097                                 //      DPRINTF("Axis event!");
00098                                 //      DPRINTF("  Axis: %d", events[i].number);
00099                                 //      DPRINTF("  value: %d", events[i].value);
00100                                         axes[events[i].number] = events[i].value;
00101                                         break;
00102 
00103                                 case JS_EVENT_BUTTON:
00104                                 //      DPRINTF("Button event!");
00105                                 //      DPRINTF("  Button: %d", events[i].number);
00106                                 //      DPRINTF("  value: %d", events[i].value);
00107                                         if (events[i].value) {
00108                                                 buttons[events[i].number] = 1;
00109                                         }
00110                                         break;
00111 
00112                                 default:
00113                                         DPRINTF("Unknown event type: %d",
00114                                             events[i].type);
00115                                 }
00116                         }
00117                 }
00118 
00119                 // write out state
00120 //              printf("\r");
00121                 printf("%02d", nEvents);
00122                 for (int i = 0; i < nAxes; ++i) {
00123                         printf(" %6d", axes[i]);
00124                 }
00125                 printf(":");
00126                 for (int i = 0; i < nButtons; ++i) {
00127                         if (buttons[i]) {
00128                                 printf(" b%02d", i);
00129                                 buttons[i] = 0;
00130                         }
00131                 }
00132                 printf("            ");
00133                 printf("\n");
00134         }
00135 }
00136 
00137 
00138 
00139 ////////////////////////////////////////////////////////////////////////////////
00140 //
00141 //      entry point
00142 //
00143 ////////////////////////////////////////////////////////////////////////////////
00144 
00145 int
00146 main
00147 (
00148 IN int argc,
00149 IN const char * argv[]
00150 )
00151 {
00152         const char * path = "/dev/input/js0";
00153         if (argc < 2) {
00154                 DPRINTF("No device path specified, using default: %s", path);
00155         } else {
00156                 path = argv[1];
00157         }
00158 
00159         int retval = 0;
00160         try {
00161                 perf::Timer timer("overall timer");
00162 
00163                 doTest(path);
00164 
00165         } catch (std::exception& e) {
00166                 DPRINTF("EXCEPTION: %s", e.what());
00167                 retval = 1;
00168         }
00169 
00170         perf::dumpTimingSummary(std::cerr);
00171 
00172         return retval;
00173 }
00174