Logo Search packages:      
Sourcecode: wacom-tools version File versions

wacdump.c

/*****************************************************************************
** wacdump.c
**
** Copyright (C) 2002, 2003 - John E. Joganic
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
**
** REVISION HISTORY
**   2002-12-17 0.3.3 - split ncurses from main file to avoid namespace
**                      collision in linux/input.h
**   2002-12-21 0.3.4 - changed to FILE* to file descriptors
**   2003-01-01 0.3.5 - moved refresh to start display immediately
**   2003-01-25 0.3.6 - moved usb code to wacusb.c
**   2003-01-26 0.3.7 - applied Dean Townsley's Acer C100 patch
**   2003-01-27 0.3.8 - added logging, better error recovery
**   2003-01-31 0.5.0 - new release
**   2003-02-12 0.5.1 - added version option and fixed usage
**   2003-06-19 0.5.2 - added patch for I2 6x8 id 0x47
**
****************************************************************************/

#include "wactablet.h"
#include "wacscrn.h"

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <time.h>

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#define WACDUMP_VER "0.5.2"

/* from linux/input.h */
#define BITS_PER_LONG (sizeof(long) * 8)
#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
#define BIT(x)  (1UL<<((x)%BITS_PER_LONG))
#define LONG(x) ((x)/BITS_PER_LONG)
#define ISBITSET(x,y) ((x)[LONG(y)] & BIT(y))

static int InitTablet(WACOMTABLET hTablet);
void FetchTablet(WACOMTABLET hTablet);
static void DisplaySerialValue(unsigned int uField);
static void DisplaySerialButton(unsigned int uCode);

struct ABS_STATE
{
      int bValid;
      int nRow, nCol;
      int nValue, nMin, nMax;
};

struct KEY_STATE
{
      int bValid;
      int nRow, nCol;
      int nValue;
};

      struct ABS_STATE gAbsState[WACOMFIELD_MAX];
      struct KEY_STATE gKeyState[WACOMBUTTON_MAX];
      int gnSerialDataRow = 0;
      int gbCursesRunning = 0;
      FILE* gLogFile = NULL;

void Usage(void)
{
      int i, j, nClsSize, nDevSize;
      unsigned int uDeviceCls;
      WACOMCLASSREC* pCls;
      WACOMDEVICEREC* pDev;

      fprintf(stderr,"Usage: wacdump [options] device\n"
            "Options:\n"
            "  -h, --help               - usage\n"
            "  -c, --class device_cls   - use specified class (see below)\n"
            "  -f, --force device_name  - use specified device (see below)\n"
            "  -l, --list               - list all supported devices\n"
            "  -v, --verbose            - increase log output; multiple OK\n"
            "  -V, --version            - display version number\n"
            "  --logfile log_file       - output log to file\n"
            "\n");
      fprintf(stderr,
            "Example devices:\n"
#ifdef WCM_ENABLE_LINUXINPUT
            "  /dev/input/event0        - usb tablet device\n"
#endif
            "  /dev/ttyS0               - serial tablet on com1\n"
            "  /dev/ttyUSB0             - serial tablet on USB adapter\n"
            "\n"
            "Supported device classes:\n");

      if (!WacomGetSupportedClassList(&pCls,&nClsSize))
      {
            fprintf(stderr,"  ");
            for (i=0; i<nClsSize; ++i)
                  fprintf(stderr,"%s%s", i ? ", " : "", pCls[i].pszName);
            fprintf(stderr,"\n");

            fprintf(stderr,"Supported device names:\n");
            for (i=0; i<nClsSize; ++i)
            {
                  fprintf(stderr,"  %s: ",pCls[i].pszName);
                  uDeviceCls = pCls[i].uDeviceClass;
                  if (!WacomGetSupportedDeviceList(uDeviceCls,&pDev,&nDevSize))
                  {
                        for (j=0; j<nDevSize; ++j)
                              fprintf(stderr,"%s%s", j ? ", " : "", pDev[j].pszName);
                        fprintf(stderr,"\n");
                        WacomFreeList(pDev);
                  }
            }
            WacomFreeList(pCls);
      }
}

void Version(void)
{
      fprintf(stdout,"%s\n", WACDUMP_VER);
}

void ListSupportedDevices(void)
{
      int i, nListSize;
      WACOMDEVICEREC* pList;

      if (!WacomGetSupportedDeviceList(0,&pList,&nListSize))
      {
            for (i=0; i<nListSize; ++i)
            {
                  fprintf(stdout,"%s\t%s\t%s\t\"%s\"\n",
                        pList[i].pszName,
                        pList[i].pszVendorName,
                        pList[i].pszClass,
                        pList[i].pszDesc);
            }
            WacomFreeList(pList);
      }
}

static void termscr(void)
{
      wacscrn_term();
}

static int InitTablet(WACOMTABLET hTablet)
{
      int i, nCaps, nItem, nRow=0;
      int nMajor, nMinor, nRelease;
      char chBuf[256];
      WACOMMODEL model;
      WACOMSTATE ranges = WACOMSTATE_INIT;
      const char* pszName;
      const char* pszClass = "UNK_CLS";
      const char* pszVendor = "UNK_VNDR";
      const char* pszDevice = "UNK_DEV";
      const char* pszSub = "UNK_SUB";

      /* Identify program and version */
      wacscrn_standout();
      for (i=0; i<80; ++i) wacscrn_output(nRow,i," ");
      wacscrn_output(nRow,0,"wacdump v" WACDUMP_VER);
      wacscrn_normal();
      nRow += 2;

      /* get model */
      model = WacomGetModel(hTablet);
      pszVendor = WacomGetVendorName(hTablet);
      pszClass = WacomGetClassName(hTablet);
      pszDevice = WacomGetDeviceName(hTablet);
      pszSub = WacomGetSubTypeName(hTablet);
      pszName = WacomGetModelName(hTablet);
      WacomGetROMVersion(hTablet,&nMajor,&nMinor,&nRelease);
      snprintf(chBuf,sizeof(chBuf),"MODEL=%s",pszName);
      wacscrn_output(nRow,0,chBuf);
      snprintf(chBuf,sizeof(chBuf),"ROM=%d.%d-%d",nMajor, nMinor, nRelease);
      wacscrn_output(nRow,40,chBuf);
      ++nRow;
      snprintf(chBuf,sizeof(chBuf),"CLS=%s  VNDR=%s  DEV=%s  SUB=%s",
                  pszClass, pszVendor, pszDevice, pszSub);
      wacscrn_output(nRow,0,chBuf);
      nRow += 2;

      gnSerialDataRow = nRow++; /* data */
      nRow += 2;

      /* get event types supported, ranges, and immediate values */
      nCaps = WacomGetCapabilities(hTablet);
      WacomGetState(hTablet,&ranges);

      nItem = 0;
      for (i=0; i<31; ++i)
      {
            if (nCaps & (1<<i))
            {
                  gAbsState[i].bValid = 1;
                  gAbsState[i].nValue = ranges.values[i].nValue;
                  gAbsState[i].nMin = ranges.values[i].nMin;
                  gAbsState[i].nMax = ranges.values[i].nMax;
                  gAbsState[i].nRow = nRow + nItem / 2;
                  gAbsState[i].nCol = nItem % 2;
                  DisplaySerialValue(i);
                  ++nItem;
            }
      }
      nRow += ((nItem + 1) / 2) + 1;

      /* get key event types */
      nItem = 0;
      for (i=0; i<WACOMBUTTON_MAX; ++i)
      {
            gKeyState[i].bValid = 1;
            gKeyState[i].nRow = nRow + nItem / 4;
            gKeyState[i].nCol = nItem % 4;
            DisplaySerialButton(i);
            ++nItem;
      }
      nRow += ((nItem + 3) / 4) + 1;
      return 0;
}

const char* GetSerialField(unsigned int uField)
{
      static const char* xszField[WACOMFIELD_MAX] =
      {
            "TOOLTYPE", "SERIAL", "IN_PROX", "BUTTON",
            "POS_X", "POS_Y", "ROT_Z", "DISTANCE",
            "PRESSURE", "TILT_X", "TILT_Y", "ABSWHEEL",
            "RELWHEEL", "THROTTLE"
      };

      return (uField >= WACOMFIELD_MAX) ?  "FIELD?" : xszField[uField];
}

static void DisplaySerialValue(unsigned int uField)
{
      static char xchBuf[256];
      static const char* xszTool[WACOMTOOLTYPE_MAX] =
      {
            "NONE", "PEN", "PENCIL", "BRUSH", "ERASER", "AIRBRUSH",
            "MOUSE", "LENS"
      };

      int bBold = 0;
      if ((uField >= WACOMFIELD_MAX) || !gAbsState[uField].bValid)
      {
            snprintf(xchBuf,sizeof(xchBuf),"Bad FIELD Code: 0x%X",uField);
            wacscrn_output(24,0,xchBuf);
            return;
      }

      snprintf(xchBuf,sizeof(xchBuf),"%8s=",GetSerialField(uField));
      wacscrn_output(gAbsState[uField].nRow,gAbsState[uField].nCol*40,xchBuf);

      if (uField == WACOMFIELD_TOOLTYPE)
      {
            int nToolType = gAbsState[uField].nValue;
            if ((nToolType<WACOMTOOLTYPE_NONE) || (nToolType>WACOMTOOLTYPE_MAX))
                  snprintf(xchBuf,sizeof(xchBuf),"UNKNOWN");
            else
                  snprintf(xchBuf,sizeof(xchBuf),"%-10s",
                              xszTool[nToolType]);
            bBold = (nToolType != WACOMTOOLTYPE_NONE);
      }
      else if (uField == WACOMFIELD_SERIAL)
      {
            snprintf(xchBuf,sizeof(xchBuf),"0x%08X",gAbsState[uField].nValue);
      }
      else if (uField == WACOMFIELD_SERIAL)
      {
            snprintf(xchBuf,sizeof(xchBuf),"%-3s",
                        gAbsState[uField].nValue ? "in" : "out");
            bBold = gAbsState[uField].nValue;
      }
      else
      {
            snprintf(xchBuf,sizeof(xchBuf),"%+06d (%+06d .. %+06d)",
                  gAbsState[uField].nValue,
                  gAbsState[uField].nMin,
                  gAbsState[uField].nMax);
      }

      if (bBold) wacscrn_standout();
      wacscrn_output(gAbsState[uField].nRow,gAbsState[uField].nCol*40+9,xchBuf);
      if (bBold) wacscrn_normal();
}

const char* GetSerialButton(unsigned int uButton)
{
      static const char* xszButton[WACOMBUTTON_MAX] =
      {
            "LEFT", "MIDDLE", "RIGHT", "EXTRA", "SIDE",
            "TOUCH", "STYLUS", "STYLUS2"
      };

      return (uButton >= WACOMBUTTON_MAX) ?  "FIELD?" : xszButton[uButton];
}


static void DisplaySerialButton(unsigned int uButton)
{
      int bDown;
      static char xchBuf[256];
      if ((uButton >= WACOMBUTTON_MAX) || !gKeyState[uButton].bValid)
      {
            snprintf(xchBuf,sizeof(xchBuf),"Bad Button Code: 0x%X",uButton);
            wacscrn_output(24,0,xchBuf);
            return;
      }

      bDown = gKeyState[uButton].nValue ? 1 : 0;

      snprintf(xchBuf,sizeof(xchBuf),"%8s=%s",
            GetSerialButton(uButton), bDown ? "DOWN" : "    ");

      if (bDown) wacscrn_standout();
      wacscrn_output(gKeyState[uButton].nRow,gKeyState[uButton].nCol*20,xchBuf);
      wacscrn_normal();
}

void FetchTablet(WACOMTABLET hTablet)
{
      char chOut[128];
      unsigned char uchBuf[16];
      int i, nLength, nRow=gnSerialDataRow, nErrors=0;
      WACOMSTATE state = WACOMSTATE_INIT;

      while (1)
      {
            wacscrn_refresh();

            nLength = WacomReadRaw(hTablet,uchBuf,sizeof(uchBuf));
            if (nLength < 0)
            {
                  snprintf(chOut,sizeof(chOut),"ReadRaw: %10d (%d)",
                              nLength,++nErrors);
                  wacscrn_output(22,0,chOut);
                  wacscrn_refresh();
                  sleep(1);
                  continue;
            }

            for (i=0; i<nLength; ++i)
            {
                  snprintf(chOut,sizeof(chOut),"%02X",uchBuf[i]);
                  wacscrn_output(nRow,i*3,chOut);
            }
            for (i=0; i<nLength; ++i)
            {
                  snprintf(chOut,sizeof(chOut),"%c",isprint(uchBuf[i]) ?
                              uchBuf[i] : '.');
                  wacscrn_output(nRow,60 + i,chOut);
            }

            if (WacomParseData(hTablet,uchBuf,nLength,&state))
            {
                  snprintf(chOut,sizeof(chOut),
                        "ParseData: %10d %-40s (%d)",
                        errno,strerror(errno),++nErrors);
                  wacscrn_output(23,0,chOut);
                  wacscrn_refresh();
                  continue;
            }

            for (i=WACOMFIELD_TOOLTYPE; i<WACOMFIELD_MAX; ++i)
            {
                  if (state.uValid & BIT(i))
                  {
                        if (i == WACOMFIELD_RELWHEEL)
                              gAbsState[i].nValue += state.values[i].nValue;
                        else
                              gAbsState[i].nValue = state.values[i].nValue;
                        DisplaySerialValue(i);
                  }
            }

            for (i=WACOMBUTTON_LEFT; i<WACOMBUTTON_MAX; ++i)
            {
                  gKeyState[i].nValue = state.values[WACOMFIELD_BUTTONS].nValue &
                              (1 << i) ? 1 : 0;
                  DisplaySerialButton(i);
            }
      }
}

void LogCallback(struct timeval tv, WACOMLOGLEVEL level, const char* psz)
{
      int i;
      struct tm* pTM;

      static const char* xszLog[WACOMLOGLEVEL_MAX] =
      {
            "", "CRITICAL", "ERROR", "WARN",
            "INFO", "DEBUG", "TRACE"
      };

      if ((level < WACOMLOGLEVEL_CRITICAL) || (level >= WACOMLOGLEVEL_MAX))
            level = WACOMLOGLEVEL_NONE;

      /* get the time */
      pTM = localtime((time_t*)&tv.tv_sec);

      if (gbCursesRunning)
      {
            static char chBuf[1024];
            snprintf(chBuf,sizeof(chBuf),"%02d:%02d:%02d.%03d %s: %s",
                  pTM->tm_hour,pTM->tm_min,pTM->tm_min,
                  (int)(tv.tv_usec / 1000),xszLog[level],psz);
            for (i=0; i<78; ++i) wacscrn_output(24,i," ");
            wacscrn_output(24,0,chBuf);
            wacscrn_refresh();
      }
      else
      {
            fprintf(stderr,"%02d:%02d:%02d.%03d %s: %s\n",
                  pTM->tm_hour,pTM->tm_min,pTM->tm_min,
                  (int)(tv.tv_usec / 1000), xszLog[level], psz);
      }

      if (gLogFile)
      {
            fprintf(gLogFile,"%02d:%02d:%02d.%03d %s: %s\n",
                  pTM->tm_hour,pTM->tm_min,pTM->tm_min,
                  (int)(tv.tv_usec / 1000), xszLog[level], psz);
            fflush(gLogFile);
      }
}

int main(int argc, char** argv)
{
      const char* pszFile = NULL;
      const char* arg;
      WACOMENGINE hEngine = NULL;
      WACOMTABLET hTablet = NULL;
      int nLevel = (int)WACOMLOGLEVEL_WARN;
      const char* pszDeviceCls = NULL;
      const char* pszDeviceType = NULL;
      const char* pszLogFile = NULL;
      WACOMMODEL model = { 0 };

      /* parse args */
      ++argv;
      while (*argv)
      {
            arg = *(argv++);

            /* handle options */
            if (arg[0] == '-')
            {
                  /* information */
                  if ((strcmp(arg,"-h") == 0) || (strcmp(arg,"--help")==0))
                        { Usage(); exit(0); }
                  if ((strcmp(arg,"-V") == 0) || (strcmp(arg,"--version")==0))
                        { Version(); exit(0); }
                  else if ((strcmp(arg,"-l") == 0) || (strcmp(arg,"--list") == 0))
                        { ListSupportedDevices(); exit(0); }

                  /* force device type */
                  else if ((strcmp(arg,"-f") == 0) || (strcmp(arg,"--force") == 0))
                  {
                        arg = *(argv++);
                        if (arg == NULL)
                              { fprintf(stderr,"Missing device\n"); exit(1); }
                        pszDeviceType = arg;
                  }

                  /* serial and usb class overrides */
                  else if ((strcmp(arg,"-c") == 0) || (strcmp(arg,"--class") == 0))
                  {
                        arg = *(argv++);
                        if (arg == NULL)
                              { fprintf(stderr,"Missing class\n"); exit(1); }
                        pszDeviceCls = arg;
                  }

                  /* log file */
                  else if (strcmp(arg,"--logfile") == 0)
                  {
                        arg = *(argv++);
                        if (arg == NULL)
                              { fprintf(stderr,"Missing log file\n"); exit(1); }
                        pszLogFile = arg;
                  }
                  else if ((strcmp(arg,"-v") == 0) || (strcmp(arg,"--verbose") == 0))
                  {
                        ++nLevel;
                  }

                  /* unknown options */
                  else
                        { fprintf(stderr,"Unknown option %s\n",arg); exit(1); }
            }

            /* device name */
            else
            {
                  if (pszFile)
                        { fprintf(stderr,"Extra argument %s\n",arg); exit(1); }

                  pszFile = arg;
            }
      }

      /* check for device */
      if (!pszFile)
      {
            Usage();
            exit(1);
      }

      /* check for log file */
      if (pszLogFile)
      {
            gLogFile = fopen(pszLogFile,"w");
            if (!gLogFile)
            {
                  perror("failed to open log file for writing");
                  exit(1);
            }
      }

      /* set device class, if provided */
      if (pszDeviceCls)
      {
            model.uClass = WacomGetClassFromName(pszDeviceCls);
            if (!model.uClass)
            {
                  fprintf(stderr, "Unrecognized class: %s\n",pszDeviceCls);
                  exit(1);
            }
      }

      /* set device type, if provided */
      if (pszDeviceType)
      {
            model.uDevice = WacomGetDeviceFromName(pszDeviceType,model.uClass);
            if (!model.uDevice)
            {
                  fprintf(stderr, "Unrecognized device: %s\n",pszDeviceType);
                  exit(1);
            }
      }

      /* open engine */
      hEngine = WacomInitEngine();
      if (!hEngine)
      {
            perror("failed to open tablet engine");
            exit(1);
      }

      WacomSetLogFunc(hEngine,LogCallback);
      WacomSetLogLevel(hEngine,(WACOMLOGLEVEL)nLevel);

      WacomLog(hEngine,WACOMLOGLEVEL_INFO,"Opening log");
   
      /* open tablet */
      hTablet = WacomOpenTablet(hEngine,pszFile,&model);
      if (!hTablet)
      {
            perror("WacomOpenTablet");
            exit(1);
      }

      /* begin curses window mode */
      wacscrn_init();
      atexit(termscr);

      gbCursesRunning = 1;

      /* get device capabilities, build screen */
      if (InitTablet(hTablet))
      {
            perror("InitTablet");
            WacomCloseTablet(hTablet);
            exit(1);
      }

      /* read, parse, and display */
      FetchTablet(hTablet);

      /* close device */
      WacomCloseTablet(hTablet);
      WacomTermEngine(hEngine);

      /* close log file, if open */
      if (gLogFile)
            fclose(gLogFile);

      return 0;
}


Generated by  Doxygen 1.6.0   Back to index