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

wcmISDV4.c

/*
 * Copyright 1995-2003 by Frederic Lepied, France. <Lepied@XFree86.org>
 *                                                                            
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is  hereby granted without fee, provided that
 * the  above copyright   notice appear  in   all  copies and  that both  that
 * copyright  notice   and   this  permission   notice  appear  in  supporting
 * documentation, and that   the  name of  Frederic   Lepied not  be  used  in
 * advertising or publicity pertaining to distribution of the software without
 * specific,  written      prior  permission.     Frederic  Lepied   makes  no
 * representations about the suitability of this software for any purpose.  It
 * is provided "as is" without express or implied warranty.                   
 *                                                                            
 * FREDERIC  LEPIED DISCLAIMS ALL   WARRANTIES WITH REGARD  TO  THIS SOFTWARE,
 * INCLUDING ALL IMPLIED   WARRANTIES OF MERCHANTABILITY  AND   FITNESS, IN NO
 * EVENT  SHALL FREDERIC  LEPIED BE   LIABLE   FOR ANY  SPECIAL, INDIRECT   OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA  OR PROFITS, WHETHER  IN  AN ACTION OF  CONTRACT,  NEGLIGENCE OR OTHER
 * TORTIOUS  ACTION, ARISING    OUT OF OR   IN  CONNECTION  WITH THE USE    OR
 * PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "xf86Wacom.h"
#include "wcmSerial.h"
#include "wcmFilter.h"

static Bool isdv4Detect(LocalDevicePtr);
static Bool isdv4Init(LocalDevicePtr);
static void isdv4InitISDV4(WacomCommonPtr common, int fd, const char* id,
      float version);
static int isdv4GetRanges(WacomCommonPtr common, int fd);
static int isdv4StartTablet(WacomCommonPtr common, int fd);
static int isdv4Parse(WacomCommonPtr common, const unsigned char* data);

      WacomDeviceClass gWacomISDV4Device =
      {
            isdv4Detect,
            isdv4Init,
            xf86WcmReadPacket,
      };

      static WacomModel isdv4General =
      {
            "General ISDV4",
            isdv4InitISDV4,
            NULL,                 /* resolution not queried */
            isdv4GetRanges,       /* query ranges */
            NULL,                 /* reset not supported */
            NULL,                 /* tilt automatically enabled */
            NULL,                 /* suppress implemented in software */
            NULL,                 /* link speed unsupported */
            isdv4StartTablet,     /* start tablet */
            isdv4Parse,
            xf86WcmHysteresisFilter,   /* input filtering */
      };

/*****************************************************************************
 * isdv4Detect -- Test if the attached device is ISDV4.
 ****************************************************************************/

static Bool isdv4Detect(LocalDevicePtr local)
{
      WacomDevicePtr priv = (WacomDevicePtr) local->private;
      WacomCommonPtr common = priv->common;
      return (common->wcmForceDevice == DEVICE_ISDV4) ? 1 : 0;
}

/*****************************************************************************
 * isdv4Init --
 ****************************************************************************/

static Bool isdv4Init(LocalDevicePtr local)
{
      int err;
      WacomDevicePtr priv = (WacomDevicePtr)local->private;
      WacomCommonPtr common = priv->common;

      DBG(1, ErrorF("initializing ISDV4 tablet\n"));    

      /* Set the speed of the serial link to 19200 */
      if (xf86WcmSetSerialSpeed(local->fd, 19200) < 0)
            return !Success;
   
      /* Send stop command to the tablet */
      SYSCALL(err = xf86WcmWrite(local->fd, WC_ISDV4_STOP, strlen(WC_ISDV4_STOP)));
      if (err == -1)
      {
            ErrorF("Wacom xf86WcmWrite error : %s\n", strerror(errno));
            return !Success;
      }

      /* Wait 250 mSecs */
      if (xf86WcmWait(250))
            return !Success;

      return xf86WcmInitTablet(common,&isdv4General,local->fd,"ISDV4", common->wcmVersion);
}

/*****************************************************************************
 * isdv4InitISDV4 -- Setup the device
 ****************************************************************************/

static void isdv4InitISDV4(WacomCommonPtr common, int fd,
      const char* id, float version)
{
      int temp;
      DBG(2, ErrorF("initializing as ISDV4 model\n"));
  
      /* set parameters */
      common->wcmProtocolLevel = 4;
      common->wcmPktLength = 9;       /* length of a packet */
      common->wcmResolX = 2540;     /* tablet X resolution in points/inch */
      common->wcmResolY = 2540;     /* tablet Y resolution in points/inch */
      common->wcmTPCButton = 1;     /* Tablet PC buttons on by default */

      if (common->wcmRotate==ROTATE_CW || common->wcmRotate==ROTATE_CCW)
      {
            temp = common->wcmMaxX;
            common->wcmMaxX = common->wcmMaxY;
            common->wcmMaxY = temp;
      }

}
static int isdv4GetRanges(WacomCommonPtr common, int fd)
{
      char data[BUFFER_SIZE];
      int maxtry = MAXTRY, nr;

      DBG(2, ErrorF("getting ISDV4 Ranges\n"));
      /* Send query command to the tablet */
      do
      {
            SYSCALL(nr = xf86WcmWrite(fd, WC_ISDV4_QUERY, strlen(WC_ISDV4_QUERY)));
            if ((nr == -1) && (errno != EAGAIN))
            {
                  ErrorF("Wacom xf86WcmWrite error : %s", strerror(errno));
                  return !Success;
            }
            maxtry--;
      } while ((nr == -1) && maxtry);

      if (maxtry == 0)
      {
            ErrorF("Wacom unable to xf86WcmWrite request query command "
                        "after %d tries\n", MAXTRY);
            return !Success;
      }

      /* Read the control data */
      maxtry = MAXTRY;
      do
      {
            if ((nr = xf86WcmWaitForTablet(fd)) > 0)
            {
                  SYSCALL(nr = xf86WcmRead(fd, data, 11));
                  if ((nr == -1) && (errno != EAGAIN))
                  {
                        ErrorF("Wacom xf86WcmRead error : %s\n", strerror(errno));
                        return !Success;
                  }
            }
            maxtry--;  
      } while ( nr <= 0 && maxtry );

      if (maxtry == 0 && nr <= 0 )
      {
            ErrorF("Wacom unable to read ISDV4 control data "
                        "after %d tries\n", MAXTRY);
            return !Success;
      }

      /* Control data bit check */
      if ( !(data[0] & 0x40) )
      {
            ErrorF("Wacom Query ISDV4 error magic error \n");
            return !Success;
      }
      
      common->wcmMaxZ = ( data[5] | ((data[6] & 0x07) << 7) );
      common->wcmMaxX = ( (data[1] << 9) | (data[2] << 2) 
                        | ( (data[6] & 0x60) >> 5) );      
      common->wcmMaxY = ( (data[3] << 9) | (data[4] << 2 ) 
                        | ( (data[6] & 0x18) >> 3) );
      common->wcmVersion = ( data[10] | (data[9] << 7) );

      return Success;
}

static int isdv4StartTablet(WacomCommonPtr common, int fd)
{
      int err;

      /* Tell the tablet to start sending coordinates */
      SYSCALL(err = xf86WcmWrite(fd, WC_ISDV4_SAMPLING, (strlen(WC_ISDV4_SAMPLING))));

      if (err == -1)
      {
            ErrorF("Wacom xf86WcmWrite error : %s\n", strerror(errno));
            return !Success;
      }

      return Success;
}

static int isdv4Parse(WacomCommonPtr common, const unsigned char* data)
{
      WacomDeviceState* last = &common->wcmChannel[0].valid.state;
      WacomDeviceState* ds;
      int n, cur_type, tmp_coord;

      if ((n = xf86WcmSerialValidate(common,data)) > 0)
      {
            return n;
      }
      else
      {
            /* Coordinate data bit check */
            if (data[0] & 0x40)
                  return common->wcmPktLength;
      }
      /* pick up where we left off, minus relative values */
      ds = &common->wcmChannel[0].work;
      RESET_RELATIVE(*ds);

      ds->proximity = (data[0] & 0x20);

      /* x and y in "normal" orientetion (wide length is X) */
      ds->x = (((int)data[6] & 0x60) >> 5) | ((int)data[2] << 2) |
            ((int)data[1] << 9);
      ds->y = (((int)data[6] & 0x18) >> 3) | ((int)data[4] << 2) |
            ((int)data[3] << 9);

      /* rotation mixes x and y up a bit */
      if (common->wcmRotate == ROTATE_CW)
      {
            tmp_coord = ds->x;
            ds->x = ds->y;
            ds->y = common->wcmMaxY - tmp_coord;
      }
      else if (common->wcmRotate == ROTATE_CCW)
      {
            tmp_coord = ds->y;
            ds->y = ds->x;
            ds->x = common->wcmMaxX - tmp_coord;
      }

      /* pressure */
      ds->pressure = (((data[6] & 0x07) << 7) | data[5] );

      /* buttons */
      ds->buttons = (data[0] & 0x07);

      /* check which device we have */
      cur_type = (ds->buttons & 4) ? ERASER_ID : STYLUS_ID;

      /* first time into prox */
      if (!last->proximity && ds->proximity) 
            ds->device_type = cur_type;

      /* out of prox */
      else if (!ds->proximity)
            memset(ds,0,sizeof(*ds));

      /* check on previous proximity */
      else
      {
            /* we were fooled by tip and second
             * sideswitch when it came into prox */
            if ((ds->device_type != cur_type) &&
                  (ds->device_type == ERASER_ID))
            {
                  /* send a prox-out for old device */
                  WacomDeviceState out = { 0 };
                  xf86WcmEvent(common,0,&out);
                  ds->device_type = cur_type;
            }
      }

      DBG(8, ErrorF("isdv4Parse %s\n",
            ds->device_type == ERASER_ID ? "ERASER " :
            ds->device_type == STYLUS_ID ? "STYLUS" : "NONE"));

      xf86WcmEvent(common,0,ds);

      return common->wcmPktLength;
}


Generated by  Doxygen 1.6.0   Back to index