--- xf86Wacom.c_0.5.0 Wed Feb 12 17:14:33 2003
+++ xf86Wacom.c Mon Feb 24 12:31:12 2003
@@ -339,6 +339,8 @@
Bool wcmStylusSide; /* eraser or stylus ? */
Bool wcmStylusProximity; /* the stylus is in proximity ? */
int wcmProtocolLevel; /* 4 for Wacom IV, 5 for Wacom V */
+ int wcmForceDevice; /* force device type (used by ISD V4) */
+ int wcmRotate; /* rotate screen (for TabletPC) */
int wcmThreshold; /* Threshold for counting pressure as a button */
WacomDeviceState wcmDevStat[2]; /* device state for each tool */
int wcmInitNumber; /* magic number for the init phasis */
@@ -351,6 +353,11 @@
#endif
} WacomCommonRec, *WacomCommonPtr;
+#define DEVICE_ISDV4 0x000C
+#define ROTATE_NONE 0
+#define ROTATE_CW 1
+#define ROTATE_CCW 2
+
#ifdef LINUX_INPUT
#define IS_USB(x) ((x)->wcmOpen == xf86WcmUSBOpen)
#else
@@ -578,6 +585,9 @@
static Bool xf86WcmUSBOpen(LocalDevicePtr);
#endif
+static void xf86WcmReadISDV4Input(LocalDevicePtr);
+static Bool xf86WcmISDV4Open(LocalDevicePtr);
+
#ifndef XFREE86_V4
@@ -2447,6 +2457,7 @@
} /* next event */
}
+
/*
***************************************************************************
*
@@ -2565,6 +2576,161 @@
/*
***************************************************************************
*
+ * xf86WcmReadISDV4Input --
+ * Read the new events from the device, and enqueue them.
+ *
+ ***************************************************************************
+ */
+static void
+xf86WcmReadISDV4Input(LocalDevicePtr local)
+{
+ WacomDevicePtr priv = (WacomDevicePtr) local->private;
+ WacomCommonPtr common = priv->common;
+ int len, loop, idx;
+ int is_stylus = 1, is_button, is_proximity, wheel=0;
+ int x, y, z, tmp_coord, buttons, tx = 0, ty = 0;
+ unsigned char buffer[BUFFER_SIZE];
+
+ DBG(7, ErrorF("xf86WcmReadInput BEGIN device=%s fd=%d\n",
+ common->wcmDevice, local->fd));
+
+ SYSCALL(len = read(local->fd, buffer, sizeof(buffer)));
+
+ if (len <= 0) {
+ ErrorF("Error reading wacom device : %s\n", strerror(errno));
+ return;
+ } else {
+ DBG(10, ErrorF("xf86WcmReadInput read %d bytes\n", len));
+ }
+
+ for(loop=0; loopwcmIndex == 0) && !(buffer[loop] & HEADER_BIT)) { /* magic bit is not OK */
+ DBG(6, ErrorF("xf86WcmReadInput bad magic number 0x%x (pktlength=%d) %d\n",
+ buffer[loop], common->wcmPktLength, loop));
+ continue;
+ }
+ else { /* magic bit at wrong place */
+ if ((common->wcmIndex != 0) && (buffer[loop] & HEADER_BIT)) {
+ DBG(6, ErrorF("xf86WcmReadInput magic number 0x%x detetected at index %d loop=%d\n",
+ (unsigned int) buffer[loop], common->wcmIndex, loop));
+ common->wcmIndex = 0;
+ }
+ }
+
+ common->wcmData[common->wcmIndex++] = buffer[loop];
+
+ if (common->wcmIndex == common->wcmPktLength) {
+ /* we have a full packet */
+
+ is_proximity = (common->wcmData[0] & 0x20);
+
+ /* reset char count for next read */
+ common->wcmIndex = 0;
+
+ /* x and y in "normal" orientetion (wide length is X) */
+ x = (((int)common->wcmData[6] & 0x60) >> 5) |
+ ((int)common->wcmData[2] << 2) |
+ ((int)common->wcmData[1] << 9);
+ y = (((int)common->wcmData[6] & 0x18) >> 3) |
+ ((int)common->wcmData[4] << 2) |
+ ((int)common->wcmData[3] << 9);
+
+ /* rotation mixes x and y up a bit */
+ if (common->wcmRotate == ROTATE_CW) {
+ tmp_coord = x;
+ x = y;
+ y = common->wcmMaxY - tmp_coord;
+ } else if (common->wcmRotate == ROTATE_CCW) {
+ tmp_coord = y;
+ y = x;
+ x = common->wcmMaxX - tmp_coord;
+ }
+
+
+ /* check which device we have */
+ is_stylus = (common->wcmData[0] & 0x04) ? 0 : 1;
+
+ /* pressure */
+ z = ((common->wcmData[6] & 0x01) << 7) | (common->wcmData[5] & 0x7F);
+ /* report touch as button 1 */
+ buttons = (common->wcmData[0] & 0x01) ? 1 : 0 ;
+ /* report side switch as button 3 */
+ buttons |= (common->wcmData[0] & 0x02) ? 0x04 : 0 ;
+
+ is_button = (buttons != 0);
+
+ /* save whether we have stylus or eraser for future proximity out */
+ if (is_stylus) {
+ common->wcmStylusSide = 1;
+ } else {
+ common->wcmStylusSide = 0; /* is eraser */
+ }
+ DBG(8, ErrorF("xf86WcmReadInput %s side\n",
+ common->wcmStylusSide ? "stylus" : "eraser"));
+ common->wcmStylusProximity = is_proximity;
+
+ /* figure out which device(s) to impersonate and send */
+ for(idx=0; idxwcmNumDevices; idx++) {
+ LocalDevicePtr local_dev = common->wcmDevices[idx];
+ WacomDevicePtr priv = (WacomDevicePtr) local_dev->private;
+ int curDevice;
+
+ DBG(7, ErrorF("xf86WcmReadInput trying to send to %s\n",
+ local_dev->name));
+
+ if (is_proximity) {
+ /* stylus and eraser are distingushable in proximity */
+ /* report as eraser if we have one
+ * otherwise as stylus */
+ if (!is_stylus && common->wcmHasEraser) {
+ curDevice = ERASER_ID;
+ } else {
+ curDevice = STYLUS_ID;
+ }
+ } else {
+ /* eraser bit not set when out of proximity, check */
+ if (common->wcmHasEraser && (!common->wcmStylusSide)) {
+ curDevice = ERASER_ID;
+ } else {
+ curDevice = STYLUS_ID;
+ }
+ }
+ if (DEVICE_ID(priv->flags) != curDevice) continue;
+
+ DBG(10, ErrorF((DEVICE_ID(priv->flags) == ERASER_ID) ?
+ "Eraser\n" :
+ "Stylus\n"));
+
+ xf86WcmSendEvents(common->wcmDevices[idx],
+ curDevice, 0,
+ is_stylus,
+ is_button,
+ is_proximity,
+ x, y, z, buttons,
+ tx, ty, wheel);
+ ((WacomDevicePtr)(common->wcmDevices[idx])->private)->oldProximity=is_proximity;
+ }
+
+ /* SendEvents looks here for old values for comparison */
+ priv->oldX = x;
+ priv->oldY = y;
+ priv->oldZ = z;
+ priv->oldTiltX = 0;
+ priv->oldTiltY = 0;
+ priv->oldProximity = is_proximity;
+ priv->oldButtons = buttons;
+ priv->oldWheel = wheel;
+ common->wcmLastSerial = 0;
+ } /* full packet */
+ } /* next data */
+ DBG(7, ErrorF("xf86WcmReadInput END local=0x%x priv=0x%x index=%d\n",
+ local, priv, common->wcmIndex));
+}
+
+/*
+ ***************************************************************************
+ *
* xf86WcmControlProc --
*
***************************************************************************
@@ -2646,6 +2812,21 @@
}
#endif
+ if (common->wcmForceDevice == DEVICE_ISDV4) {
+ int loop;
+
+ SYSCALL(close(local->fd));
+
+ for(loop=0; loopwcmNumDevices; loop++) {
+ common->wcmDevices[loop]->read_input=xf86WcmReadISDV4Input;
+ }
+ common->wcmOpen=xf86WcmISDV4Open;
+
+ return xf86WcmISDV4Open(local);
+ }
+
+
+
DBG(1, ErrorF("initializing tablet\n"));
/* Set the speed of the serial link to 38400 */
@@ -3066,6 +3247,157 @@
/*
***************************************************************************
*
+ * xf86WcmISDV4Open --
+ *
+ ***************************************************************************
+ */
+
+static Bool
+xf86WcmISDV4Open(LocalDevicePtr local)
+{
+#ifndef XFREE86_V4
+ struct timeval timeout;
+#endif
+ int err;
+ WacomDevicePtr priv = (WacomDevicePtr)local->private;
+ WacomCommonPtr common = priv->common;
+
+ DBG(1, ErrorF("opening %s\n", common->wcmDevice));
+
+#ifdef XFREE86_V4
+ local->fd = xf86OpenSerial(local->options);
+#else
+ SYSCALL(local->fd = open(common->wcmDevice, O_RDWR|O_NDELAY, 0));
+#endif
+ if (local->fd < 0) {
+ ErrorF("Error opening %s : %s\n", common->wcmDevice, strerror(errno));
+ return !Success;
+ }
+
+
+ DBG(1, ErrorF("continuing opening %s\n", common->wcmDevice));
+
+ DBG(1, ErrorF("resetting tablet\n"));
+
+ /* Set the speed of the serial link to 38400 */
+#ifdef XFREE86_V4
+ if (xf86SetSerialSpeed(local->fd, 38400) < 0) {
+ return !Success;
+ }
+#else
+ if (set_serial_speed(local->fd, B38400) == !Success)
+ return !Success;
+#endif
+
+ /* Send reset to the tablet */
+ SYSCALL(err = write(local->fd, WC_RESET_BAUD, strlen(WC_RESET_BAUD)));
+ if (err == -1) {
+ ErrorF("Wacom write error : %s\n", strerror(errno));
+ return !Success;
+ }
+
+ /* Wait 250 mSecs */
+ WAIT(250);
+
+ /* Send reset to the tablet */
+ SYSCALL(err = write(local->fd, WC_RESET, strlen(WC_RESET)));
+ if (err == -1) {
+ ErrorF("Wacom write error : %s\n", strerror(errno));
+ return !Success;
+ }
+
+ /* Wait 75 mSecs */
+ WAIT(75);
+
+ /* Set the speed of the serial link to 19200 */
+#ifdef XFREE86_V4
+ if (xf86SetSerialSpeed(local->fd, 19200) < 0) {
+ return !Success;
+ }
+#else
+ if (set_serial_speed(local->fd, B19200) == !Success)
+ return !Success;
+#endif
+
+ /* Send reset to the tablet */
+ SYSCALL(err = write(local->fd, WC_RESET_BAUD, strlen(WC_RESET_BAUD)));
+ if (err == -1) {
+ ErrorF("Wacom write error : %s\n", strerror(errno));
+ return !Success;
+ }
+
+ /* Wait 250 mSecs */
+ WAIT(250);
+
+ /* Send reset to the tablet */
+ SYSCALL(err = write(local->fd, WC_RESET, strlen(WC_RESET)));
+ if (err == -1) {
+ ErrorF("Wacom write error : %s\n", strerror(errno));
+ return !Success;
+ }
+
+ /* Wait 75 mSecs */
+ WAIT(75);
+
+#ifdef XFREE86_V4
+ xf86FlushInput(local->fd);
+#else
+ flush_input_fd(local->fd);
+#endif
+
+ DBG(2, ErrorF("not reading model -- Wacom TabletPC ISD V4\n"));
+
+ /* set parameters */
+ common->wcmProtocolLevel = 0;
+ common->wcmMaxZ = 255; /* max Z value (pressure)*/
+ common->wcmResolX = 2570; /* X resolution in points/inch */
+ common->wcmResolY = 2570; /* Y resolution in points/inch */
+ common->wcmResolZ = 1; /* pressure resolution of tablet */
+ common->wcmPktLength = 9; /* length of a packet */
+ if (common->wcmRotate==ROTATE_NONE) {
+ common->wcmMaxX = 21136;
+ common->wcmMaxY = 15900;
+ } else if (common->wcmRotate==ROTATE_CW || common->wcmRotate==ROTATE_CCW) {
+ common->wcmMaxX = 15900;
+ common->wcmMaxY = 21136;
+ }
+
+ DBG(2, ErrorF("setup is max X=%d max Y=%d resol X=%d resol Y=%d\n",
+ common->wcmMaxX, common->wcmMaxY, common->wcmResolX,
+ common->wcmResolY));
+
+ /* suppress is not currently implemented for this device --
+ if (common->wcmSuppress < 0) {
+ int xratio = common->wcmMaxX/screenInfo.screens[0]->width;
+ int yratio = common->wcmMaxY/screenInfo.screens[0]->height;
+
+ common->wcmSuppress = (xratio > yratio) ? yratio : xratio;
+ }
+
+ if (common->wcmSuppress > 100) {
+ common->wcmSuppress = 99;
+ }
+ */
+
+ if (xf86Verbose)
+ ErrorF("%s Wacom %s tablet maximum X=%d maximum Y=%d "
+ "X resolution=%d Y resolution=%d suppress=%d%s\n",
+ XCONFIG_PROBED, "ISDV4",
+ common->wcmMaxX, common->wcmMaxY,
+ common->wcmResolX, common->wcmResolY, common->wcmSuppress,
+ HANDLE_TILT(common) ? " Tilt" : "");
+
+ if (err == -1) {
+ SYSCALL(close(local->fd));
+ return !Success;
+ }
+
+ return Success;
+}
+
+/*
+ ***************************************************************************
+ *
* xf86WcmOpenDevice --
* Open the physical device and init information structs.
*
@@ -3874,6 +4206,27 @@
}
xf86Msg(X_CONFIG, "%s is in %s mode\n", local->name,
(priv->flags & ABSOLUTE_FLAG) ? "absolute" : "relative");
+
+ s = xf86FindOptionValue(local->options, "ForceDevice");
+
+ if (s && (xf86NameCmp(s, "ISDV4") == 0)) {
+ common->wcmForceDevice=DEVICE_ISDV4;
+ local->read_input=xf86WcmReadISDV4Input;
+ common->wcmOpen=xf86WcmISDV4Open;
+ xf86Msg(X_CONFIG, "%s: forcing TabletPC ISD V4 protocol\n", dev->identifier);
+ }
+
+ common->wcmRotate=ROTATE_NONE;
+
+ s = xf86FindOptionValue(local->options, "Rotate");
+
+ if (s) {
+ if (xf86NameCmp(s, "CW") == 0) {
+ common->wcmRotate=ROTATE_CW;
+ } else if (xf86NameCmp(s, "CCW") ==0) {
+ common->wcmRotate=ROTATE_CCW;
+ }
+ }
common->wcmSuppress = xf86SetIntOption(local->options, "Suppress", common->wcmSuppress);
if (common->wcmSuppress != -1) {