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

wacusb.c

/*****************************************************************************
** wacusb.c
**
** Copyright (C) 2002 - 2004 - 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.
**
****************************************************************************/

#include "wacusb.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <assert.h>

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

/*****************************************************************************
** Begin USB Linux Input Subsystem
*****************************************************************************/

#ifdef WCM_ENABLE_LINUXINPUT
#include <linux/input.h>

#ifndef EV_MSC
#define EV_MSC 0x04
#endif

#ifndef MSC_SERIAL
#define MSC_SERIAL 0x00
#endif

/*****************************************************************************
** Defines
*****************************************************************************/

/* 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))

/*****************************************************************************
** Structures
*****************************************************************************/

typedef struct _USBSUBTYPE USBSUBTYPE;
typedef struct _USBDEVICE USBDEVICE;
typedef struct _USBVENDOR USBVENDOR;

struct _USBSUBTYPE
{
      const char* pszName;
      const char* pszDesc;
      unsigned int uSubType;
      unsigned int uProduct;
};

struct _USBDEVICE
{
      const char* pszName;
      const char* pszDesc;
      unsigned int uDevice;
      USBSUBTYPE* pSubTypes;
};

struct _USBVENDOR
{
      const char* pszName;
      const char* pszDesc;
      unsigned int uVendor;
      USBDEVICE* pDevices;
};

/*****************************************************************************
** USB Tablet object
*****************************************************************************/

typedef struct _USBTABLET USBTABLET;

struct _USBTABLET
{
      WACOMTABLET_PRIV tablet;
      WACOMENGINE hEngine;
      int fd;
      USBVENDOR* pVendor;
      USBDEVICE* pDevice;
      USBSUBTYPE* pSubType;
      int nBus;
      int nVersion;
      WACOMSTATE state;
      int nToolProx;
};

/*****************************************************************************
** Static Prototypes
*****************************************************************************/

static void USBClose(WACOMTABLET_PRIV* pTablet);
static WACOMMODEL USBGetModel(WACOMTABLET_PRIV* pTablet);
static const char* USBGetVendorName(WACOMTABLET_PRIV* pTablet);
static const char* USBGetClassName(WACOMTABLET_PRIV* pTablet);
static const char* USBGetDeviceName(WACOMTABLET_PRIV* pTablet);
static const char* USBGetSubTypeName(WACOMTABLET_PRIV* pTablet);
static const char* USBGetModelName(WACOMTABLET_PRIV* pTablet);
static int USBGetROMVer(WACOMTABLET_PRIV* pTablet, int* pnMajor,
            int* pnMinor, int* pnRelease);
static int USBGetCaps(WACOMTABLET_PRIV* pTablet);
static int USBGetState(WACOMTABLET_PRIV* pTablet, WACOMSTATE* pState);
static int USBGetFD(WACOMTABLET_PRIV* pTablet);
static int USBReadRaw(WACOMTABLET_PRIV* pTablet, unsigned char* puchData,
            unsigned int uSize);
static int USBParseData(WACOMTABLET_PRIV* pTablet,
            const unsigned char* puchData, unsigned int uLength,
            WACOMSTATE* pState);

static int USBFindModel(USBTABLET* pUSB, unsigned int uVendor,
            unsigned int uProduct);
static int USBIdentifyModel(USBTABLET* pUSB);

/*****************************************************************************
** Globals
*****************************************************************************/

      static USBSUBTYPE xPenPartner[] =
      {
            { "MODEL_PP_0405", "Wacom PenPartner", 1, 0x00 },
            { NULL }
      };

      static USBSUBTYPE xGraphire[] =
      {
            { "ET_0405", "Wacom Graphire", 1, 0x10 },
            { NULL }
      };

      static USBSUBTYPE xGraphire2[] =
      {
            { "ET_0405", "Wacom Graphire2 4x5", 1, 0x11 },
            { "ET_0507", "Wacom Graphire2 5x7", 1, 0x12 },
            { NULL }
      };

      static USBSUBTYPE xGraphire3[] =
      {
            { "ET_0405", "Wacom Graphire3 4x5", 1, 0x13 },
            { "ET_0608", "Wacom Graphire3 6x8", 1, 0x14 },
            { NULL }
      };

      static USBSUBTYPE xIntuos[] =
      {
            { "GD_0405-U", "Wacom Intuos 4x5", 1, 0x20 },
            { "GD_0608-U", "Wacom Intuos 6x8", 2, 0x21 },
            { "GD_0912-U", "Wacom Intuos 9x12", 3, 0x22 },
            { "GD_1212-U", "Wacom Intuos 12x12", 4, 0x23 },
            { "GD_1218-U", "Wacom Intuos 12x18", 5, 0x24 },
            { NULL }
      };

      static USBSUBTYPE xCintiq[] =
      {
            { "MODEL_PL400", "Wacom PL400", 1, 0x30 },
            { "MODEL_PL500", "Wacom PL500", 2, 0x31 },
            { "MODEL_PL600", "Wacom PL600", 3, 0x32 },
            { "MODEL_PL600SX", "Wacom PL600SX", 4, 0x33 },
            { "MODEL_PL550", "Wacom PL550", 5, 0x34 },
            { "MODEL_PL800", "Wacom PL800", 6, 0x35 },
            { NULL }
      };

      static USBSUBTYPE xIntuos2[] =
      {
            { "XD-0405-U", "Wacom Intuos2 4x5",   1, 0x41 },
            { "XD-0608-U", "Wacom Intuos2 6x8",   2, 0x42 },
            { "XD-0912-U", "Wacom Intuos2 9x12",  3, 0x43 },
            { "XD-1212-U", "Wacom Intuos2 12x12", 4, 0x44 },
            { "XD-1218-U", "Wacom Intuos2 12x18", 5, 0x45 },

            /* fix for I2 6x8's reporting as 0x47 */
            { "XD-0608-U", "Wacom Intuos2 6x8", 2, 0x47 },

            { NULL }
      };

      static USBSUBTYPE xVolito[] =
      {
            { "MODEL-VOL", "Wacom Volito", 1, 0x60 },
            { NULL }
      };

      static USBSUBTYPE xCintiqPartner[] =
      {
            { "PTU-600", "Wacom Cintiq Partner", 1, 0x03 },
            { NULL }
      };

      static USBSUBTYPE xIntuos3[] =
      {
            { "PTZ-430", "Wacom Intuos3 4x5",  1, 0xB0 },
            { "PTZ-630", "Wacom Intuos3 6x8",  2, 0xB1 },
            { "PTZ-930", "Wacom Intuos3 9x12", 3, 0xB2 },
            { NULL }
      };

      static USBDEVICE xWacomDevices[] =
      {
            { "pp", "PenPartner", WACOMDEVICE_PENPARTNER, xPenPartner },
            { "gr", "Graphire", WACOMDEVICE_GRAPHIRE, xGraphire },
            { "gr2", "Graphire2", WACOMDEVICE_GRAPHIRE2, xGraphire2 },
            { "gr3", "Graphire3", WACOMDEVICE_GRAPHIRE3, xGraphire3 },
            { "int", "Intuos", WACOMDEVICE_INTUOS, xIntuos },
            { "int2", "Intuos2", WACOMDEVICE_INTUOS2, xIntuos2 },
            { "int3", "Intuos3", WACOMDEVICE_INTUOS3, xIntuos3 },
            { "pl", "Cintiq (PL)", WACOMDEVICE_CINTIQ, xCintiq },
            { "ptu", "Cintiq Partner (PTU)", WACOMDEVICE_PTU, xCintiqPartner },
            { "vol", "Volito", WACOMDEVICE_VOLITO, xVolito },
            { NULL }
      };

      static USBVENDOR xVendors[] =
      {
            { "wacom", "Wacom", WACOMVENDOR_WACOM, xWacomDevices },
            { NULL },
      };

/*****************************************************************************
** Public Functions
*****************************************************************************/

typedef struct
{
      void (*pfnFree)(void* pv);
} DEVLIST_INTERNAL;

static void USBFreeDeviceList(void* pv)
{
      DEVLIST_INTERNAL* pInt = ((DEVLIST_INTERNAL*)pv) - 1;
      free(pInt);
}

int WacomGetSupportedUSBDeviceList(WACOMDEVICEREC** ppList, int* pnSize)
{
      int nIndex=0, nCnt=0;
      DEVLIST_INTERNAL* pInt;
      USBDEVICE* pDev;
      USBVENDOR* pVendor;
      WACOMDEVICEREC* pRec;

      if (!ppList || !pnSize) { errno = EINVAL; return 1; }

      /* for each vendor, count up devices */
      for (pVendor=xVendors; pVendor->pszName; ++pVendor)
      {
            /* count up devices */
            for (pDev=pVendor->pDevices; pDev->pszName; ++pDev, ++nCnt) ;
      }
   
      /* allocate enough memory to hold internal structure and all records */
      pInt = (DEVLIST_INTERNAL*)malloc(sizeof(DEVLIST_INTERNAL) +
                              (sizeof(WACOMDEVICEREC) * nCnt));

      pInt->pfnFree = USBFreeDeviceList;
      pRec = (WACOMDEVICEREC*)(pInt + 1);

      /* for each vendor, add devices */
      for (pVendor=xVendors; pVendor->pszName; ++pVendor)
      {
            for (pDev=pVendor->pDevices; pDev->pszName; ++pDev, ++nIndex)
            {
                  pRec[nIndex].pszName = pDev->pszName;
                  pRec[nIndex].pszDesc = pDev->pszDesc;
                  pRec[nIndex].pszVendorName = pVendor->pszName;
                  pRec[nIndex].pszVendorDesc = pVendor->pszDesc;
                  pRec[nIndex].pszClass = "usb";
                  pRec[nIndex].model.uClass = WACOMCLASS_USB;
                  pRec[nIndex].model.uVendor = pVendor->uVendor;
                  pRec[nIndex].model.uDevice = pDev->uDevice;
                  pRec[nIndex].model.uSubType = 0;
            }
      }
      assert(nIndex == nCnt);

      *ppList = pRec;
      *pnSize = nCnt;
      return 0;
}

unsigned int WacomGetUSBDeviceFromName(const char* pszName)
{
      USBDEVICE* pDev;
      USBVENDOR* pVendor;

      if (!pszName) { errno = EINVAL; return 0; }

      /* for each vendor, look for device */
      for (pVendor=xVendors; pVendor->pszName; ++pVendor)
      {
            /* count up devices */
            for (pDev=pVendor->pDevices; pDev->pszName; ++pDev)
            {
                  if (strcasecmp(pszName,pDev->pszName) == 0)
                        return pDev->uDevice;
            }
      }

      errno = ENOENT;
      return 0;
}

WACOMTABLET WacomOpenUSBTablet(WACOMENGINE hEngine, int fd, WACOMMODEL* pModel)
{
      USBTABLET* pUSB = NULL;

      /* Allocate tablet */
      pUSB = (USBTABLET*)malloc(sizeof(USBTABLET));
      memset(pUSB,0,sizeof(*pUSB));
      pUSB->tablet.Close = USBClose;
      pUSB->tablet.GetModel = USBGetModel;
      pUSB->tablet.GetVendorName = USBGetVendorName;
      pUSB->tablet.GetClassName = USBGetClassName;
      pUSB->tablet.GetDeviceName = USBGetDeviceName;
      pUSB->tablet.GetSubTypeName = USBGetSubTypeName;
      pUSB->tablet.GetModelName = USBGetModelName;
      pUSB->tablet.GetROMVer = USBGetROMVer;
      pUSB->tablet.GetCaps = USBGetCaps;
      pUSB->tablet.GetState = USBGetState;
      pUSB->tablet.GetFD = USBGetFD;
      pUSB->tablet.ReadRaw = USBReadRaw;
      pUSB->tablet.ParseData = USBParseData;
      pUSB->hEngine = hEngine;
      pUSB->fd = fd;

      /* Identify and initialize the model */
      if (USBIdentifyModel(pUSB))
      {
            WacomLog(pUSB->hEngine,WACOMLOGLEVEL_ERROR,
                  "Failed to identify model: %s",strerror(errno));
            free(pUSB);
            return NULL;
      }

      return (WACOMTABLET)pUSB;
}

/*****************************************************************************
** Tablet Functions
*****************************************************************************/

static void USBClose(WACOMTABLET_PRIV* pTablet)
{
      USBTABLET* pUSB = (USBTABLET*)pTablet;
      close(pUSB->fd);
      free(pUSB);
}

static WACOMMODEL USBGetModel(WACOMTABLET_PRIV* pTablet)
{
      WACOMMODEL model = { 0 };
      USBTABLET* pUSB = (USBTABLET*)pTablet;
      model.uClass = WACOMCLASS_USB;
      model.uVendor = pUSB->pVendor->uVendor;
      model.uDevice = pUSB->pDevice->uDevice;
      model.uSubType = pUSB->pSubType->uSubType;
      return model;
}

static int USBGetRange(USBTABLET* pUSB, unsigned long* pBits, int nAbsField,
            unsigned int uField)
{
      int nAbs[5];

      if  (!ISBITSET(pBits,nAbsField))
            return 0;
      if (ioctl(pUSB->fd, EVIOCGABS(nAbsField), nAbs) != 0)
            return 1;

      pUSB->state.values[uField].nMin = nAbs[1];
      pUSB->state.values[uField].nMax = nAbs[2];
      pUSB->state.uValid |= BIT(uField);
      return 0;
}

static int USBFindModel(USBTABLET* pUSB, unsigned int uVendor,
            unsigned int uProduct)
{
      USBVENDOR* pVendor = NULL;
      USBDEVICE* pDev = NULL;
      USBSUBTYPE* pSub = NULL;

      static USBSUBTYPE xUnkSub[] =
      {
            { "UNKNOWN", "Unknown", 1, 0x00 },
            { NULL }
      };

      static USBDEVICE xUnkDev[] =
      {
            { "unk", "Unknown", WACOMDEVICE_UNKNOWN, xUnkSub },
            { NULL }
      };

      static USBVENDOR xUnkVendor =
      { "unknown", "Unknown", WACOMVENDOR_UNKNOWN, xUnkDev };

      for (pVendor=xVendors; pVendor->pszName; ++pVendor)
      {
            if (pVendor->uVendor == uVendor)
            {
                  for (pDev=pVendor->pDevices; pDev->pszName; ++pDev)
                  {
                        for (pSub=pDev->pSubTypes; pSub->pszName; ++pSub)
                        {
                              if (pSub->uProduct == uProduct)
                              {
                                    pUSB->pVendor = pVendor;
                                    pUSB->pDevice = pDev;
                                    pUSB->pSubType = pSub;
                                    return 0;
                              }
                        }
                  }

                  /* only one vendor of this type, so we're done */
                  break;
            }
      }

      /* unknown vendor */
      pUSB->pVendor = &xUnkVendor;
      pUSB->pDevice = pUSB->pVendor->pDevices;
      pUSB->pSubType = pUSB->pDevice->pSubTypes;
      return 0;
}



static int USBIdentifyModel(USBTABLET* pUSB)
{
      int nCnt;
      short sID[4];
      unsigned int uVendor, uProduct;
      unsigned long evbits[NBITS(EV_MAX)];
      unsigned long absbits[NBITS(ABS_MAX)];
      unsigned long relbits[NBITS(REL_MAX)];
      unsigned long keybits[NBITS(KEY_MAX)];

      /* Get device name and id */
      if (ioctl(pUSB->fd,EVIOCGID,sID) < 0)
            return 1;

      /* initialize state structure */
      pUSB->state.uValueCnt = WACOMFIELD_MAX;

      /* Get event types supported */
      nCnt = ioctl(pUSB->fd,EVIOCGBIT(0 /*EV*/,sizeof(evbits)),evbits);
      if (nCnt < 0)
      {
            WacomLog(pUSB->hEngine,WACOMLOGLEVEL_ERROR,
                  "Failed to CGBIT ev: %s",strerror(errno));
            return 1;
      }
      assert(nCnt == sizeof(evbits));

      /* absolute events */
      if (ISBITSET(evbits,EV_ABS))
      {
            nCnt = ioctl(pUSB->fd,EVIOCGBIT(EV_ABS,sizeof(absbits)),absbits);
            if (nCnt < 0)
            {
                  WacomLog(pUSB->hEngine,WACOMLOGLEVEL_ERROR,
                        "Failed to CGBIT abs: %s",strerror(errno));
                  return 1;
            }

            /* the following line has problem on Debian systems
            assert(nCnt == sizeof(absbits));
            */

            if (USBGetRange(pUSB,absbits,ABS_X,WACOMFIELD_POSITION_X) ||
                  USBGetRange(pUSB,absbits,ABS_Y,WACOMFIELD_POSITION_Y) ||
                  USBGetRange(pUSB,absbits,ABS_RZ,WACOMFIELD_ROTATION_Z) ||
                  USBGetRange(pUSB,absbits,ABS_DISTANCE,WACOMFIELD_DISTANCE) ||
                  USBGetRange(pUSB,absbits,ABS_PRESSURE,WACOMFIELD_PRESSURE) ||
                  USBGetRange(pUSB,absbits,ABS_TILT_X,WACOMFIELD_TILT_X) ||
                  USBGetRange(pUSB,absbits,ABS_TILT_Y,WACOMFIELD_TILT_Y) ||
                  USBGetRange(pUSB,absbits,ABS_WHEEL,WACOMFIELD_ABSWHEEL) ||
                  USBGetRange(pUSB,absbits,ABS_THROTTLE,WACOMFIELD_THROTTLE))
                  return 1;
      }

      /* relative events */
      if (ISBITSET(evbits,EV_REL))
      {
            nCnt = ioctl(pUSB->fd,EVIOCGBIT(EV_REL,sizeof(relbits)),relbits);
            if (nCnt < 0)
            {
                  WacomLog(pUSB->hEngine,WACOMLOGLEVEL_ERROR,
                        "Failed to CGBIT rel: %s",strerror(errno));
                  return 1;
            }
            assert(nCnt == sizeof(relbits));

            if (ISBITSET(relbits,REL_WHEEL))
            {
                  pUSB->state.uValid |= BIT(WACOMFIELD_RELWHEEL);
                  pUSB->state.values[WACOMFIELD_RELWHEEL].nMin = -1;
                  pUSB->state.values[WACOMFIELD_RELWHEEL].nMax = 1;
            }
      }

      /* key events */
      if (ISBITSET(evbits,EV_KEY))
      {
            nCnt = ioctl(pUSB->fd,EVIOCGBIT(EV_KEY,sizeof(keybits)),keybits);
            if (nCnt < 0)
            {
                  WacomLog(pUSB->hEngine,WACOMLOGLEVEL_ERROR,
                        "Failed to CGBIT key: %s",strerror(errno));
                  return 1;
            }
            assert(nCnt == sizeof(keybits));

            /* button events */
            if (ISBITSET(keybits,BTN_LEFT) ||
                        ISBITSET(keybits,BTN_RIGHT) ||
                        ISBITSET(keybits,BTN_MIDDLE) ||
                        ISBITSET(keybits,BTN_SIDE) ||
                        ISBITSET(keybits,BTN_EXTRA))
                  pUSB->state.uValid |= BIT(WACOMFIELD_BUTTONS);

            /* tool events */
            if (ISBITSET(keybits,BTN_TOOL_PEN) ||
                        ISBITSET(keybits,BTN_TOOL_RUBBER) ||
                        ISBITSET(keybits,BTN_TOOL_BRUSH) ||
                        ISBITSET(keybits,BTN_TOOL_PENCIL) ||
                        ISBITSET(keybits,BTN_TOOL_AIRBRUSH) ||
                        ISBITSET(keybits,BTN_TOOL_FINGER) ||
                        ISBITSET(keybits,BTN_TOOL_MOUSE) ||
                        ISBITSET(keybits,BTN_TOOL_LENS))
                  pUSB->state.uValid |= BIT(WACOMFIELD_PROXIMITY) |
                              BIT(WACOMFIELD_TOOLTYPE);
      }

      /* set identification */
      pUSB->nBus = sID[0];
      uVendor = sID[1];
      uProduct = sID[2];
      pUSB->nVersion = sID[3];

      if (USBFindModel(pUSB,uVendor,uProduct))
            return 1;

      /* add additional capabilities by device type */
      switch (pUSB->pDevice->uDevice)
      {
            case WACOMDEVICE_INTUOS:
            case WACOMDEVICE_INTUOS2:
                  pUSB->state.uValid |= BIT(WACOMFIELD_SERIAL);
            default: ;
      }

      return 0;
}

static const char* USBGetVendorName(WACOMTABLET_PRIV* pTablet)
{
      USBTABLET* pUSB = (USBTABLET*)pTablet;
      return pUSB->pVendor->pszDesc;
}

static const char* USBGetClassName(WACOMTABLET_PRIV* pTablet)
{
      return "USB";
}

static const char* USBGetDeviceName(WACOMTABLET_PRIV* pTablet)
{
      USBTABLET* pUSB = (USBTABLET*)pTablet;
      return pUSB->pDevice->pszDesc;
}

static const char* USBGetSubTypeName(WACOMTABLET_PRIV* pTablet)
{
      USBTABLET* pUSB = (USBTABLET*)pTablet;
      return pUSB->pSubType->pszName;
}

static const char* USBGetModelName(WACOMTABLET_PRIV* pTablet)
{
      USBTABLET* pUSB = (USBTABLET*)pTablet;
      return pUSB->pSubType->pszDesc;
}

static int USBGetROMVer(WACOMTABLET_PRIV* pTablet, int* pnMajor,
            int* pnMinor, int* pnRelease)
{
      USBTABLET* pUSB = (USBTABLET*)pTablet;
      if (!pnMajor) { errno=EINVAL; return 1; }

      /* how is the version number broken down?
       * mine says 0x115.  is that 1.1.5 or 1.15? */
      *pnMajor = pUSB->nVersion >> 8;
      *pnMinor = (pUSB->nVersion >> 4) & 0xF;
      *pnRelease = (pUSB->nVersion & 0xF);
      return 0;
}

static int USBGetCaps(WACOMTABLET_PRIV* pTablet)
{
      USBTABLET* pUSB = (USBTABLET*)pTablet;
      return pUSB->state.uValid;
}

static int USBGetState(WACOMTABLET_PRIV* pTablet, WACOMSTATE* pState)
{
      USBTABLET* pUSB = (USBTABLET*)pTablet;
      return WacomCopyState(pState,&pUSB->state);
}

static int USBGetFD(WACOMTABLET_PRIV* pTablet)
{
      USBTABLET* pUSB = (USBTABLET*)pTablet;
      return pUSB->fd;
}

static int USBReadRaw(WACOMTABLET_PRIV* pTablet, unsigned char* puchData,
            unsigned int uSize)
{
      int nXfer;
      unsigned int uCnt, uPacketLength;
      USBTABLET* pUSB = (USBTABLET*)pTablet;
      uPacketLength = sizeof(struct input_event);

      /* check size of buffer */
      if (uSize < uPacketLength) { errno=EINVAL; return 0; }
      
      for (uCnt=0; uCnt<uPacketLength; uCnt+=nXfer)
      {
            nXfer = read(pUSB->fd,puchData+uCnt,uPacketLength-uCnt);
            if (nXfer <= 0) return nXfer;
      }

      return (signed)uCnt;
}

static int USBParseMSC(USBTABLET* pUSB, struct input_event* pEv)
{
      if (pEv->code == MSC_SERIAL)
            pUSB->state.values[WACOMFIELD_SERIAL].nValue = pEv->value;
      return 0;
}

static int USBParseKEY(USBTABLET* pUSB, struct input_event* pEv)
{
      int i, button=-1, tool=0;
      switch (pEv->code)
      {
            case BTN_LEFT: button = WACOMBUTTON_LEFT; break;
            case BTN_RIGHT: button = WACOMBUTTON_RIGHT; break;
            case BTN_MIDDLE: button = WACOMBUTTON_MIDDLE; break;
            case BTN_SIDE: button = WACOMBUTTON_SIDE; break;
            case BTN_EXTRA: button = WACOMBUTTON_EXTRA; break;
            case BTN_TOUCH: button = WACOMBUTTON_TOUCH; break;
            case BTN_STYLUS: button = WACOMBUTTON_STYLUS; break;
            case BTN_STYLUS2: button = WACOMBUTTON_STYLUS2; break;
            case BTN_TOOL_PEN: tool = WACOMTOOLTYPE_PEN; break;
            case BTN_TOOL_PENCIL: tool = WACOMTOOLTYPE_PENCIL; break;
            case BTN_TOOL_BRUSH: tool = WACOMTOOLTYPE_BRUSH; break;
            case BTN_TOOL_RUBBER: tool = WACOMTOOLTYPE_ERASER; break;
            case BTN_TOOL_AIRBRUSH: tool = WACOMTOOLTYPE_AIRBRUSH; break;
            case BTN_TOOL_MOUSE: tool = WACOMTOOLTYPE_MOUSE; break;
            case BTN_TOOL_FINGER: break;
            case BTN_TOOL_LENS: tool = WACOMTOOLTYPE_LENS; break;
      }

      /* if button was specified */
      if (button != -1)
      {
            /* button state change */
            if (pEv->value)
                  pUSB->state.values[WACOMFIELD_BUTTONS].nValue |= BIT(button);
            else
                  pUSB->state.values[WACOMFIELD_BUTTONS].nValue &= ~BIT(button);
      }

      /* if a tool was specified */
      if (tool)
      {
            /* coming into proximity */
            if (pEv->value)
            {
                  /* no prior tool in proximity */
                  if (!pUSB->nToolProx)
                  {
                        pUSB->state.values[WACOMFIELD_PROXIMITY].nValue = 1;
                        pUSB->state.values[WACOMFIELD_TOOLTYPE].nValue = tool;
                  }

                  /* remember tool in prox */
                  pUSB->nToolProx |= BIT(tool);
            }

            /* otherwise, going out of proximity */
            else
            {
                  /* forget tool in prox */
                  pUSB->nToolProx &= ~BIT(tool);

                  /* nobody left? out of proximity */
                  if (!pUSB->nToolProx)
                        memset(pUSB->state.values, 0,
                                    pUSB->state.uValueCnt * sizeof(WACOMVALUE));

                  /* otherwise, switch to next tool */
                  else
                  {
                        for (i=WACOMTOOLTYPE_PEN; i<WACOMTOOLTYPE_MAX; ++i)
                        {
                              if (pUSB->nToolProx & BIT(i))
                              {
                                    pUSB->state.values[WACOMFIELD_TOOLTYPE].nValue = i;
                              }
                        }
                  }
            } /* out of prox */
      } /* end if tool */

      return 0;
}

static int USBParseABS(USBTABLET* pUSB, struct input_event* pEv)
{
      int field = 0;
      switch (pEv->code)
      {
            case ABS_X: field = WACOMFIELD_POSITION_X; break;
            case ABS_Y: field = WACOMFIELD_POSITION_Y; break;
            case ABS_RZ: field = WACOMFIELD_ROTATION_Z; break;
            case ABS_DISTANCE: field = WACOMFIELD_DISTANCE; break;
            case ABS_PRESSURE: field = WACOMFIELD_PRESSURE; break;
            case ABS_TILT_X: field = WACOMFIELD_TILT_X; break;
            case ABS_TILT_Y: field = WACOMFIELD_TILT_Y; break;
            case ABS_WHEEL: field = WACOMFIELD_ABSWHEEL; break;
            case ABS_THROTTLE: field = WACOMFIELD_THROTTLE; break;
      }

      if (field)
            pUSB->state.values[field].nValue = pEv->value;

      return 0;
}

static int USBParseREL(USBTABLET* pUSB, struct input_event* pEv)
{
      int field = 0;
      switch (pEv->code)
      {
            case REL_WHEEL: field = WACOMFIELD_RELWHEEL; break;
      }

      if (field)
            pUSB->state.values[field].nValue = pEv->value;

      return 0;
}

static int USBParseData(WACOMTABLET_PRIV* pTablet,
            const unsigned char* puchData, unsigned int uLength,
            WACOMSTATE* pState)
{
      USBTABLET* pUSB = (USBTABLET*)pTablet;
      struct input_event* pEv = (struct input_event*)puchData;
      if (uLength != sizeof(struct input_event)) return 1;

      pUSB->state.values[WACOMFIELD_RELWHEEL].nValue = 0;

      /* dispatch event */
      switch (pEv->type)
      {
#ifdef EV_SYN
            case EV_SYN: /* kernel 2.6 */
#endif
            case EV_MSC: /* kernel 2.4 */
                       if (USBParseMSC(pUSB,pEv)) return 1; break;
            case EV_KEY: if (USBParseKEY(pUSB,pEv)) return 1; break;
            case EV_ABS: if (USBParseABS(pUSB,pEv)) return 1; break;
            case EV_REL: if (USBParseREL(pUSB,pEv)) return 1; break;
            default: errno = EINVAL; return 1;
      }

      return pState ? WacomCopyState(pState,&pUSB->state) : 0;
}

/*****************************************************************************
** End USB Linux Input Subsystem
*****************************************************************************/

#else /* WCM_ENABLE_LINUXWACOM */

WACOMTABLET WacomOpenUSBTablet(WACOMENGINE hEngine, int fd, WACOMMODEL* pModel)
{
      errno = EPERM;
      return NULL;
}

unsigned int WacomGetUSBDeviceFromName(const char* pszName)
{
      errno = ENOENT;
      return 0;
}

int WacomGetSupportedUSBDeviceList(WACOMDEVICEREC** ppList, int* pnSize)
{
      if (!ppList || !pnSize) { errno = EINVAL; return 1; }
      *ppList = NULL;
      *pnSize = 0;
      return 0;
}

#endif /* WCM_ENABLE_LINUXWACOM */

Generated by  Doxygen 1.6.0   Back to index