#if 0
static const char identification[] = "$Identification: 18 $";
#endif
#include "xf86Version.h"
#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(3,9,0,0,0)
#define XFREE86_V4 1
#endif
#ifdef XFREE86_V4
#ifndef XFree86LOADER
#include <unistd.h>
#include <errno.h>
#endif
#include "misc.h"
#include "xf86.h"
#define NEED_XF86_TYPES
#if !defined(DGUX)
#include "xf86_ansic.h"
#include "xisb.h"
#endif
#include "xf86_OSproc.h"
#include "xf86Xinput.h"
#include "exevents.h"
#include "keysym.h"
#include "mipointer.h"
#ifdef XFree86LOADER
#include "xf86Module.h"
#endif
#define wait_for_fd(fd) xf86WaitForInput((fd), 1000)
#define tcflush(fd, n) xf86FlushInput((fd))
#undef read
#define read(a,b,c) xf86ReadSerial((a),(b),(c))
#undef write
#define write(a,b,c) xf86WriteSerial((a),(char*)(b),(c))
#undef close
#define close(a) xf86CloseSerial((a))
#define XCONFIG_PROBED "(==)"
#define XCONFIG_GIVEN "(**)"
#define xf86Verbose 1
#undef PRIVATE
#define PRIVATE(x) XI_PRIVATE(x)
static const char *default_options[] =
{
"BaudRate", "9600",
"DataBits", "8",
"StopBits", "1",
"Parity", "Odd",
"FlowControl", "Xoff",
"VTime", "10",
"VMin", "1",
NULL
};
static InputDriverPtr sumDrv;
#else
#define NEED_EVENTS
#include "X.h"
#include "Xproto.h"
#include "misc.h"
#include "inputstr.h"
#include "scrnintstr.h"
#include "XI.h"
#include "XIproto.h"
#if defined(sun) && !defined(i386)
#define POSIX_TTY
#include <errno.h>
#include <termio.h>
#include <fcntl.h>
#include <ctype.h>
#include "extio.h"
#else
#include "compiler.h"
#include "xf86.h"
#include "xf86Priv.h"
#include "xf86_OSproc.h"
#ifdef XFree86LOADER
#include "xf86_ansic.h"
#endif
#include "xf86Config.h"
#include "xf86Xinput.h"
#include "atKeynames.h"
#endif
#if !defined(sun) || defined(i386)
#include "osdep.h"
#include "exevents.h"
#include "extnsionst.h"
#include "extinit.h"
#endif
#endif
#ifdef DBG
#undef DBG
#endif
#ifdef DEBUG
#undef DEBUG
#endif
static int debug_level = 5;
#define DEBUG 1
#if DEBUG
#define DBG(lvl, f) {if ((lvl) <= debug_level) f;}
#else
#define DBG(lvl, f)
#endif
#define ABSOLUTE_FLAG 1
#define STYLUS_FLAG 2
#define COMPATIBLE_FLAG 4
#define H1217D_FLAG 8
#define Z_AXIS_FLAG 16
#define INITIALIZED 32
typedef struct
{
char *sumDevice;
int sumInc;
int sumButTrans;
int sumOldX;
int sumOldY;
int sumOldZ;
int sumOldProximity;
int sumOldButtons;
int sumMaxX;
int sumMaxY;
int sumXSize;
int sumXOffset;
int sumYSize;
int sumYOffset;
int sumRes;
int flags;
int sumIndex;
unsigned char sumData[7];
} SummaDeviceRec, *SummaDevicePtr;
#define SUMMA_SECTION_NAME "SummaSketch"
#ifndef XFREE86_V4
#define PORT 1
#define DEVICENAME 2
#define THE_MODE 3
#define CURSOR 4
#define INCREMENT 5
#define BORDER 6
#define DEBUG_LEVEL 7
#define HISTORY_SIZE 8
#define ALWAYS_CORE 9
#define ACTIVE_AREA 10
#define ACTIVE_OFFSET 11
#define COMPATIBLE 12
#define RESOLUTION 13
#define HITACHI_1217D 14
#if !defined(sun) || defined(i386)
static SymTabRec SumTab[] = {
{ENDSUBSECTION, "endsubsection"},
{PORT, "port"},
{DEVICENAME, "devicename"},
{THE_MODE, "mode"},
{CURSOR, "cursor"},
{INCREMENT, "increment"},
{BORDER, "border"},
{DEBUG_LEVEL, "debuglevel"},
{HISTORY_SIZE, "historysize"},
{ALWAYS_CORE, "alwayscore"},
{ACTIVE_AREA, "activearea"},
{ACTIVE_OFFSET, "activeoffset"},
{COMPATIBLE, "compatible"},
{RESOLUTION, "resolution"},
{HITACHI_1217D, "hitachi_1217d"},
{-1, ""}
};
#define RELATIVE 1
#define ABSOLUTE 2
static SymTabRec SumModeTabRec[] = {
{RELATIVE, "relative"},
{ABSOLUTE, "absolute"},
{-1, ""}
};
#define PUCK 1
#define STYLUS 2
static SymTabRec SumPointTabRec[] = {
{PUCK, "puck"},
{STYLUS, "stylus"},
{-1, ""}
};
#endif
#endif
#define BUFFER_SIZE 256
#define XI_NAME "SUMMA"
#define SYSCALL(call) while(((call) == -1) && (errno == EINTR))
#define SS_TABID0 "0"
#define SS_FIRMID "z?"
#define SS_CONFIG "a"
#define SS_ABSOLUTE 'F'
#define SS_RELATIVE 'E'
#define SS_UPPER_ORIGIN "b"
#define SS_PROMPT_MODE "B"
#define SS_STREAM_MODE "@"
#define SS_INCREMENT 'I'
#define SS_BINARY_FMT "zb"
#define SS_PROMPT "P"
static const char * ss_initstr = SS_TABID0 SS_UPPER_ORIGIN SS_BINARY_FMT SS_STREAM_MODE;
#define PHASING_BIT 0x80
#define PROXIMITY_BIT 0x40
#define TABID_BIT 0x20
#define XSIGN_BIT 0x10
#define YSIGN_BIT 0x08
#define BUTTON_BITS 0x07
#define COORD_BITS 0x7f
#define LPI2CPM(res) (res * 1000 / 25.4)
#ifndef XFREE86_V4
#if defined(sun) && !defined(i386)
#define ENQUEUE suneqEnqueue
#else
#define ENQUEUE xf86eqEnqueue
extern void xf86eqEnqueue(
xEventPtr
);
#endif
extern void miPointerDeltaCursor(
int ,
int ,
unsigned long
);
#endif
#ifndef XFREE86_V4
#if !defined(sun) || defined(i386)
static Bool
xf86SumConfig(LocalDevicePtr *array, int inx, int max, LexPtr val)
{
LocalDevicePtr dev = array[inx];
SummaDevicePtr priv = (SummaDevicePtr)(dev->private);
int token;
int mtoken;
DBG(2, ErrorF("xf86SumConfig\n"));
while ((token = xf86GetToken(SumTab)) != ENDSUBSECTION) {
switch(token) {
case DEVICENAME:
if (xf86GetToken(NULL) != STRING)
xf86ConfigError("Option string expected");
else {
dev->name = strdup(val->str);
if (xf86Verbose)
ErrorF("%s SummaSketch X device name is %s\n", XCONFIG_GIVEN,
dev->name);
}
break;
case PORT:
if (xf86GetToken(NULL) != STRING)
xf86ConfigError("Option string expected");
else {
priv->sumDevice = strdup(val->str);
if (xf86Verbose)
ErrorF("%s SummaSketch port is %s\n", XCONFIG_GIVEN,
priv->sumDevice);
}
break;
case THE_MODE:
mtoken = xf86GetToken(SumModeTabRec);
if ((mtoken == EOF) || (mtoken == STRING) || (mtoken == NUMBER))
xf86ConfigError("Mode type token expected");
else {
switch (mtoken) {
case ABSOLUTE:
priv->flags |= ABSOLUTE_FLAG;
break;
case RELATIVE:
priv->flags &= ~ABSOLUTE_FLAG;
break;
default:
xf86ConfigError("Illegal Mode type");
break;
}
}
break;
case CURSOR:
mtoken = xf86GetToken(SumPointTabRec);
if ((mtoken == EOF) || (mtoken == STRING) || (mtoken == NUMBER))
xf86ConfigError("Cursor token expected");
else {
switch (mtoken) {
case STYLUS:
priv->flags |= STYLUS_FLAG;
break;
case PUCK:
priv->flags &= ~STYLUS_FLAG;
break;
default:
xf86ConfigError("Illegal cursor type");
break;
}
}
break;
case INCREMENT:
if (xf86GetToken(NULL) != NUMBER)
xf86ConfigError("Option number expected");
priv->sumInc = val->num;
if (xf86Verbose)
ErrorF("%s SummaSketch increment value is %d\n", XCONFIG_GIVEN,
priv->sumInc);
break;
case DEBUG_LEVEL:
if (xf86GetToken(NULL) != NUMBER)
xf86ConfigError("Option number expected");
debug_level = val->num;
if (xf86Verbose) {
#if DEBUG
ErrorF("%s SummaSketch debug level sets to %d\n", XCONFIG_GIVEN,
debug_level);
#else
ErrorF("%s SummaSketch debug level not sets to %d because"
" debugging is not compiled\n", XCONFIG_GIVEN,
debug_level);
#endif
}
break;
case HISTORY_SIZE:
if (xf86GetToken(NULL) != NUMBER)
xf86ConfigError("Option number expected");
dev->history_size = val->num;
if (xf86Verbose)
ErrorF("%s SummaSketch Motion history size is %d\n", XCONFIG_GIVEN,
dev->history_size);
break;
case HITACHI_1217D:
priv->flags |= H1217D_FLAG;
priv->sumInc = 0;
if(xf86Verbose)
ErrorF("%s Hitach_1217D, compatible enforced.\n", XCONFIG_GIVEN);
case COMPATIBLE:
priv->flags |= COMPATIBLE_FLAG;
if(xf86Verbose)
ErrorF("%s SummaSketch compatible - will not query firmware ID\n", XCONFIG_GIVEN);
break;
case ALWAYS_CORE:
xf86AlwaysCore(dev, TRUE);
if (xf86Verbose)
ErrorF("%s SummaSketch device always stays core pointer\n",
XCONFIG_GIVEN);
break;
case ACTIVE_AREA:
if (xf86GetToken(NULL) != NUMBER)
xf86ConfigError("Option number expected");
priv->sumXSize = val->realnum * 100;
if (xf86GetToken(NULL) != NUMBER)
xf86ConfigError("Option number expected");
priv->sumYSize = val->realnum * 100;
if (xf86Verbose)
ErrorF("%s SummaSketch active area: %d.%02dx%d.%02d"
" inches\n", XCONFIG_GIVEN, priv->sumXSize / 100,
priv->sumXSize % 100, priv->sumYSize / 100,
priv->sumYSize % 100);
break;
case ACTIVE_OFFSET:
if (xf86GetToken(NULL) != NUMBER)
xf86ConfigError("Option number expected");
priv->sumXOffset = val->realnum * 100;
if (xf86GetToken(NULL) != NUMBER)
xf86ConfigError("Option number expected");
priv->sumYOffset = val->realnum * 100;
if (xf86Verbose)
ErrorF("%s SummaSketch active offsets: %d.%02d %d.%02d"
" inches\n", XCONFIG_GIVEN, priv->sumXOffset / 100,
priv->sumXOffset % 100, priv->sumYOffset / 100,
priv->sumYOffset % 100);
break;
case RESOLUTION:
if (xf86GetToken(NULL) != NUMBER)
xf86ConfigError("Option number expected");
priv->sumRes = val->num;
if (xf86Verbose)
ErrorF("%s SummaSketch resolution set to %d\n", XCONFIG_GIVEN,
priv->sumRes);
break;
case EOF:
FatalError("Unexpected EOF (missing EndSubSection)");
break;
default:
xf86ConfigError("SummaSketch subsection keyword expected");
break;
}
}
DBG(2, ErrorF("xf86SumConfig name=%s\n", priv->sumDevice));
return Success;
}
#endif
#endif
static Bool
xf86SumConvert(LocalDevicePtr local,
int first,
int num,
int v0,
int v1,
int v2,
int v3,
int v4,
int v5,
int* x,
int* y)
{
SummaDevicePtr priv = (SummaDevicePtr) local->private;
if (first != 0 || num == 1)
return FALSE;
*x = (v0 * screenInfo.screens[0]->width) / priv->sumXSize;
*y = (v1 * screenInfo.screens[0]->height) / priv->sumYSize;
if (*x < 0) *x = 0;
if (*y < 0) *y = 0;
if (*x > screenInfo.screens[0]->width)
*x = screenInfo.screens[0]->width;
if (*y > screenInfo.screens[0]->height)
*y = screenInfo.screens[0]->height;
DBG(6, ErrorF("Adjusted coords x=%d y=%d\n", *x, *y));
return TRUE;
}
static void
xf86SumReadInput(LocalDevicePtr local)
{
SummaDevicePtr priv = (SummaDevicePtr) local->private;
int len, loop;
int is_absolute, num_ax;
int x, y, z, buttons, prox;
DeviceIntPtr device;
unsigned char buffer[BUFFER_SIZE];
DBG(7, ErrorF("xf86SumReadInput BEGIN device=%s fd=%d\n",
priv->sumDevice, local->fd));
SYSCALL(len = read(local->fd, buffer, sizeof(buffer)));
if (len <= 0) {
Error("error reading SummaSketch device");
return;
}
for(loop=0; loop<len; loop++) {
if ((priv->sumIndex == 0) && !(buffer[loop] & PHASING_BIT)) {
DBG(6, ErrorF("xf86SumReadInput bad magic number 0x%x\n", buffer[loop]));;
continue;
}
priv->sumData[priv->sumIndex++] = buffer[loop];
if (priv->sumIndex == ( (priv->flags & ABSOLUTE_FLAG) ?
((priv->flags & Z_AXIS_FLAG)?7:5) : 3)) {
priv->sumIndex = 0;
prox = (priv->sumData[0] & PROXIMITY_BIT)? 0: 1;
buttons = (priv->sumData[0] & BUTTON_BITS);
if (priv->flags & ABSOLUTE_FLAG) {
x = (int)priv->sumData[1] + ((int)priv->sumData[2] << 7);
y = (int)priv->sumData[3] + ((int)priv->sumData[4] << 7);
if(priv->flags & Z_AXIS_FLAG){
z = ((int)priv->sumData[5] << 2) |
((int)priv->sumData[6] & 0x01 << 1) |
((int)priv->sumData[6] & 0x10);
buttons |= ((int)priv->sumData[6] & 0x02 << 2);
} else z = 0;
} else {
x = priv->sumData[0] & XSIGN_BIT? priv->sumData[1]: -priv->sumData[1];
y = priv->sumData[0] & YSIGN_BIT? priv->sumData[2]: -priv->sumData[2];
z = 0;
}
x -= priv->sumXOffset;
y -= priv->sumYOffset;
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x > priv->sumXSize) x = priv->sumXSize;
if (y > priv->sumYSize) y = priv->sumYSize;
device = local->dev;
DBG(6, ErrorF("prox=%s\tx=%d\ty=%d\tz=%d\tbuttons=%d\n",
prox ? "true" : "false", x, y, z, buttons));
is_absolute = (priv->flags & ABSOLUTE_FLAG);
num_ax = (priv->flags & Z_AXIS_FLAG)? 3 : 2;
if (prox) {
if (!(priv->sumOldProximity))
xf86PostProximityEvent(device, 1, 0, num_ax, x, y, z);
if ((is_absolute && ((priv->sumOldX != x) || (priv->sumOldY != y) || (priv->sumOldZ != z)))
|| (!is_absolute && (x || y))) {
if (is_absolute || priv->sumOldProximity) {
xf86PostMotionEvent(device, is_absolute, 0, num_ax, x, y, z);
}
}
if (priv->sumOldButtons != buttons) {
int delta;
int button;
delta = buttons - priv->sumOldButtons;
button = (delta > 0)? delta: ((delta == 0)?
priv->sumOldButtons : -delta);
if (priv->sumOldButtons != buttons) {
DBG(6, ErrorF("xf86SumReadInput button=%d delta=%d\n", button,
delta));
xf86PostButtonEvent(device, is_absolute, button,
(delta > 0), 0, num_ax, x, y, z);
}
}
priv->sumOldButtons = buttons;
priv->sumOldX = x;
priv->sumOldY = y;
priv->sumOldZ = z;
priv->sumOldProximity = prox;
} else {
if (priv->sumOldProximity)
xf86PostProximityEvent(device, 0, 0, num_ax, x, y, z);
priv->sumOldProximity = 0;
}
}
}
DBG(7, ErrorF("xf86SumReadInput END device=%p priv=%p\n",
(void *)local->dev, (void *)priv));
}
static void
xf86SumControlProc(DeviceIntPtr device, PtrCtrl *ctrl)
{
DBG(2, ErrorF("xf86SumControlProc\n"));
}
static char *
xf86SumWriteAndRead(int fd, char *data, char *buffer, int len, int cr_term)
{
int err, numread = 0;
#ifndef XFREE86_V4
fd_set readfds;
struct timeval timeout;
#endif
SYSCALL(err = write(fd, data, strlen(data)));
if (err == -1) {
Error("SummaSketch write");
return NULL;
}
#ifndef XFREE86_V4
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
#endif
while (numread < len) {
#ifndef XFREE86_V4
timeout.tv_sec = 0;
timeout.tv_usec = 200000;
SYSCALL(err = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout));
#else
err = xf86WaitForInput(fd, 200000);
#endif
if (err == -1) {
Error("SummaSketch select");
return NULL;
}
if (!err) {
ErrorF("Timeout while reading SummaSketch tablet. No tablet connected ???\n");
return NULL;
}
SYSCALL(err = read(fd, buffer + numread++, 1));
if (err == -1) {
Error("SummaSketch read");
return NULL;
}
if (!err) {
--numread;
break;
}
if (cr_term && buffer[numread - 1] == '\r') {
buffer[numread - 1] = 0;
break;
}
}
buffer[numread] = 0;
return buffer;
}
static void
xf86SumSetResCode (int *res, char *buffer, int index)
{
switch (*res) {
case 1: buffer[index] = 'l'; break;
case 2: buffer[index] = 'n'; break;
case 4: buffer[index] = 'p'; break;
case 100: buffer[index] = 'd'; break;
case 200: buffer[index] = 'e'; break;
case 10:
*res = 254;
case 254:
buffer[index] = 'f'; break;
case 400:
buffer[index] = 'g'; break;
case 20:
*res = 508;
case 508:
buffer[index] = 'i'; break;
case 1000:
buffer[index] = 'j'; break;
case 40:
*res = 1016;
case 1016:
buffer[index] = 'q'; break;
case 2000:
buffer[index] = 's'; break;
case 2032:
buffer[index] = 'u'; break;
case 2540:
buffer[index] = 'v'; break;
default:
*res = 500;
buffer[index] = 'h'; break;
}
buffer[index+1] = 0;
}
static Bool
xf86SumOpen(LocalDevicePtr local)
{
#ifndef XFREE86_V4
struct termios termios_tty;
struct timeval timeout;
#endif
char buffer[256], dbuffer[4];
int err, idx;
int res100;
double sratio, tratio;
SummaDevicePtr priv = (SummaDevicePtr)local->private;
DBG(2, ErrorF("opening %s\n", priv->sumDevice));
#ifdef XFREE86_V4
local->fd = xf86OpenSerial(local->options);
#else
SYSCALL(local->fd = open(priv->sumDevice, O_RDWR|O_NDELAY, 0));
#endif
if (local->fd == -1) {
Error(priv->sumDevice);
return !Success;
}
DBG(2, ErrorF("%s opened as fd %d\n", priv->sumDevice, local->fd));
#ifndef XFREE86_V4
#ifdef POSIX_TTY
err = tcgetattr(local->fd, &termios_tty);
if (err == -1) {
Error("SummaSketch tcgetattr");
return !Success;
}
termios_tty.c_iflag = IXOFF;
termios_tty.c_cflag = B9600|CS8|CREAD|CLOCAL|HUPCL|PARENB|PARODD;
termios_tty.c_lflag = 0;
termios_tty.c_cc[VINTR] = 0;
termios_tty.c_cc[VQUIT] = 0;
termios_tty.c_cc[VERASE] = 0;
#ifdef VWERASE
termios_tty.c_cc[VWERASE] = 0;
#endif
#ifdef VREPRINT
termios_tty.c_cc[VREPRINT] = 0;
#endif
termios_tty.c_cc[VKILL] = 0;
termios_tty.c_cc[VEOF] = 0;
termios_tty.c_cc[VEOL] = 0;
#ifdef VEOL2
termios_tty.c_cc[VEOL2] = 0;
#endif
termios_tty.c_cc[VSUSP] = 0;
#ifdef VDISCARD
termios_tty.c_cc[VDISCARD] = 0;
#endif
#ifdef VLNEXT
termios_tty.c_cc[VLNEXT] = 0;
#endif
termios_tty.c_cc[VMIN] = 1 ;
termios_tty.c_cc[VTIME] = 10 ;
err = tcsetattr(local->fd, TCSANOW, &termios_tty);
if (err == -1) {
Error("SummaSketch tcsetattr TCSANOW");
return !Success;
}
#else
#error Code for someone else to write to handle OSs without POSIX tty functions
#endif
#endif
DBG(2, ErrorF("initializing SummaSketch tablet\n"));
for (idx = 0; idx < 10; idx++) buffer[idx] = ' ';
SYSCALL(err = write(local->fd, buffer, 10));
if (err == -1) {
Error("SummaSketch write");
return !Success;
}
buffer[0] = 0;
SYSCALL(err = write(local->fd, buffer, 1));
#ifndef XFREE86_V4
timeout.tv_sec = 0;
timeout.tv_usec = 400000;
SYSCALL(err = select(0, NULL, NULL, NULL, &timeout));
#else
err = xf86WaitForInput(-1, 400000);
#endif
if (err == -1) {
Error("SummaSketch select");
return !Success;
}
SYSCALL(err = write(local->fd, SS_PROMPT_MODE, strlen(SS_PROMPT_MODE)));
if (err == -1) {
Error("SummaSketch write");
return !Success;
}
#ifndef XFREE86_V4
tcflush(local->fd, TCIFLUSH);
#else
xf86FlushInput(local->fd);
#endif
if ((priv->flags & COMPATIBLE_FLAG) == 0) {
DBG(2, ErrorF("reading firmware ID\n"));
if (!xf86SumWriteAndRead(local->fd, SS_FIRMID, buffer, 255, 1))
return !Success;
DBG(2, ErrorF("%s\n", buffer));
if (xf86Verbose)
ErrorF("%s %s firmware ID : %s\n", XCONFIG_PROBED, local->name, buffer);
}
DBG(2, ErrorF("setting up resolution\n"));
xf86SumSetResCode (&priv->sumRes, dbuffer, 0);
dbuffer[1] = 'a';
dbuffer[2] = 0;
DBG(2, ErrorF("reading max coordinates\n"));
if (!xf86SumWriteAndRead(local->fd, dbuffer, buffer,
(priv->flags&Z_AXIS_FLAG)?7:5, 0))
return !Success;
priv->sumMaxX = (buffer[1] & 0x7f) | (buffer[2] << 7);
priv->sumMaxY = (buffer[3] & 0x7f) | (buffer[4] << 7);
if (priv->flags & H1217D_FLAG) {
priv->sumMaxX = (432.4 / 25.4) * priv->sumRes;
priv->sumMaxY = (297.6 / 25.4) * priv->sumRes;
}
if (xf86Verbose)
ErrorF("%s %s: tablet size is %d.%02din. x %d.%02din., %dx%d "
"lines of resolution\n", XCONFIG_PROBED, local->name,
priv->sumMaxX / priv->sumRes,
(priv->sumMaxX * 100 / priv->sumRes) % 100,
priv->sumMaxY / priv->sumRes,
(priv->sumMaxY * 100 / priv->sumRes) % 100,
priv->sumMaxX, priv->sumMaxY);
res100 = priv->sumRes / 100;
if (priv->sumXOffset >= 0 && priv->sumYOffset >= 0) {
priv->sumXOffset *= res100;
priv->sumYOffset *= res100;
priv->sumMaxX -= priv->sumXOffset;
priv->sumMaxY -= priv->sumYOffset;
}
if (priv->sumXSize > 0 && priv->sumYSize > 0) {
if ((priv->sumXSize * res100) <= priv->sumMaxX &&
(priv->sumYSize * res100) <= priv->sumMaxY) {
priv->sumXSize *= res100;
priv->sumYSize *= res100;
} else {
ErrorF("%s %s: active area bigger than tablet, "
"assuming maximum\n", XCONFIG_PROBED, local->name);
priv->sumXSize = priv->sumMaxX;
priv->sumYSize = priv->sumMaxY;
}
} else {
priv->sumXSize = priv->sumMaxX;
priv->sumYSize = priv->sumMaxY;
}
sratio = (double)screenInfo.screens[0]->height /
(double)screenInfo.screens[0]->width;
tratio = (double)priv->sumMaxY / (double)priv->sumMaxX;
if (tratio <= 1.0) {
priv->sumXSize = (double)priv->sumYSize / sratio;
if (priv->sumXSize > priv->sumMaxX) priv->sumXSize = priv->sumMaxX;
}
else {
priv->sumYSize = (double)priv->sumXSize / sratio;
if (priv->sumYSize > priv->sumMaxY) priv->sumYSize = priv->sumMaxY;
}
ErrorF("%s %s: using tablet area %d by %d, at res %d lpi\n",
XCONFIG_PROBED, local->name, priv->sumXSize, priv->sumYSize,
priv->sumRes);
if (priv->sumInc > 95)
priv->sumInc = 95;
if (priv->sumInc < 0) {
if (priv->sumXSize / screenInfo.screens[0]->width <
priv->sumYSize / screenInfo.screens[0]->height)
priv->sumInc = priv->sumXSize / screenInfo.screens[0]->width;
else
priv->sumInc = priv->sumYSize / screenInfo.screens[0]->height;
if (priv->sumInc < 1)
priv->sumInc = 1;
if (xf86Verbose)
ErrorF("%s %s: Using increment value of %d\n", XCONFIG_PROBED,
local->name, priv->sumInc);
}
for (idx = 0; ss_initstr[idx]; idx++) {
buffer[idx] = ss_initstr[idx];
}
buffer[idx++] = SS_INCREMENT;
buffer[idx++] = 32 + priv->sumInc;
buffer[idx++] = (priv->flags & ABSOLUTE_FLAG)?
SS_ABSOLUTE: SS_RELATIVE;
buffer[idx] = 0;
SYSCALL(err = write(local->fd, buffer, idx));
if (err == -1) {
Error("SummaSketch write");
return !Success;
}
if (err <= 0) {
SYSCALL(close(local->fd));
return !Success;
}
return Success;
}
static int
xf86SumOpenDevice(DeviceIntPtr pSum)
{
LocalDevicePtr local = (LocalDevicePtr)pSum->public.devicePrivate;
SummaDevicePtr priv = (SummaDevicePtr)XI_PRIVATE(pSum);
if (xf86SumOpen(local) != Success) {
if (local->fd >= 0) {
SYSCALL(close(local->fd));
}
local->fd = -1;
}
InitValuatorAxisStruct(pSum,
0,
0,
priv->sumXSize,
LPI2CPM(priv->sumRes),
0,
LPI2CPM(priv->sumRes));
InitValuatorAxisStruct(pSum,
1,
0,
priv->sumYSize,
LPI2CPM(priv->sumRes),
0,
LPI2CPM(priv->sumRes));
if(priv->flags&Z_AXIS_FLAG)
InitValuatorAxisStruct(pSum,
2,
0,
512,
LPI2CPM(priv->sumRes),
0,
LPI2CPM(priv->sumRes));
return (local->fd != -1);
}
static void
xf86SumInitPrivate (SummaDevicePtr priv)
{
#if defined (sun) && !defined(i386)
char *dev_name;
#endif
if (priv == NULL) return;
#if defined(sun) && !defined(i386)
if ((dev_name = getenv("SUMMASKETCH_DEV"))) {
priv->sumDevice = xalloc(strlen(dev_name) + 1);
strcpy(priv->sumDevice, dev_name);
ErrorF("xf86SumOpen port changed to '%s'\n", priv->sumDevice);
} else {
priv->sumDevice = "";
}
#else
priv->sumDevice = "";
#endif
priv->sumRes = 500;
priv->sumInc = -1;
priv->sumOldX = -1;
priv->sumOldY = -1;
priv->sumOldProximity = 0;
priv->sumOldButtons = 0;
priv->sumMaxX = -1;
priv->sumMaxY = -1;
priv->sumXSize = 0;
priv->sumXOffset = 0;
priv->sumYSize = 0;
priv->sumYOffset = 0;
priv->sumIndex = 0;
priv->flags = ABSOLUTE_FLAG;
}
static int
xf86SumProc(DeviceIntPtr pSum, int what)
{
CARD8 map[25];
int nbaxes;
int nbbuttons;
int loop;
LocalDevicePtr local = (LocalDevicePtr)pSum->public.devicePrivate;
SummaDevicePtr priv = (SummaDevicePtr)PRIVATE(pSum);
DBG(2, ErrorF("BEGIN xf86SumProc dev=%p priv=%p what=%d\n", (void *)pSum, (void *)priv, what));
switch (what) {
case DEVICE_INIT:
DBG(2, ErrorF("xf86SumProc pSum=%p fd = %d, what=INIT\n", (void *)pSum,
local->fd));
if (priv->flags & INITIALIZED) break;
nbaxes = (priv->flags & Z_AXIS_FLAG)?3:2;
nbbuttons = (priv->flags & STYLUS_FLAG)? ((priv->flags & Z_AXIS_FLAG)?3:2): 4;
for(loop=1; loop<=nbbuttons; loop++) map[loop] = loop;
if (InitButtonClassDeviceStruct(pSum,
nbbuttons,
map) == FALSE) {
ErrorF("unable to allocate Button class device\n");
return !Success;
}
if (InitFocusClassDeviceStruct(pSum) == FALSE) {
ErrorF("unable to init Focus class device\n");
return !Success;
}
if (InitPtrFeedbackClassDeviceStruct(pSum,
xf86SumControlProc) == FALSE) {
ErrorF("unable to init ptr feedback\n");
return !Success;
}
if (InitProximityClassDeviceStruct(pSum) == FALSE) {
ErrorF("unable to init proximity class device\n");
return !Success;
}
if (InitValuatorClassDeviceStruct(pSum,
nbaxes,
xf86GetMotionEvents,
local->history_size,
(priv->flags & ABSOLUTE_FLAG)? Absolute: Relative)
== FALSE) {
ErrorF("unable to allocate Valuator class device\n");
return !Success;
}
xf86MotionHistoryAllocate(local);
#ifndef XFREE86_V4
AssignTypeAndName(pSum, local->atom, local->name);
#endif
xf86SumOpenDevice(pSum);
priv->flags |= INITIALIZED;
break;
case DEVICE_ON:
DBG(2, ErrorF("xf86SumProc pSum=%p fd = %d, what=ON\n", (void *)pSum,
local->fd));
if (pSum->public.on) break;
if ((local->fd < 0) && (!xf86SumOpenDevice(pSum))) {
return !Success;
}
SYSCALL(write(local->fd, SS_PROMPT, strlen(SS_PROMPT)));
#if 0
# ifdef XFREE86_V4
xf86AddEnabledDevice(local);
# else
AddEnabledDevice(local->fd);
# endif
#else
AddEnabledDevice(local->fd);
#endif
pSum->public.on = TRUE;
break;
case DEVICE_OFF:
DBG(2, ErrorF("xf86SumProc pSum=%p fd = %d, what=OFF\n", (void *)pSum,
local->fd));
if (! pSum->public.on) break;
if (local->fd >= 0)
#if 0
# ifdef XFREE86_V4
xf86RemoveEnabledDevice(local);
# else
RemoveEnabledDevice(local->fd);
# endif
#else
RemoveEnabledDevice(local->fd);
#endif
pSum->public.on = FALSE;
break;
case DEVICE_CLOSE:
DBG(2, ErrorF("xf86SumProc pSum=%p fd = %d, what=CLOSE\n", (void *)pSum,
local->fd));
if (local->fd != -1) {
SYSCALL(close(local->fd));
local->fd = -1;
}
break;
default:
ErrorF("unsupported mode=%d\n", what);
return !Success;
break;
}
DBG(2, ErrorF("END xf86SumProc Success what=%d dev=%p priv=%p\n",
what, (void *)pSum, (void *)priv));
return Success;
}
static void
xf86SumClose(LocalDevicePtr local)
{
DBG(2, ErrorF("xf86SumClose local = %p, ->fd = %d\n", (void *)local, local->fd));
if (local->fd >= 0) {
#ifdef XFREE86_V4
xf86CloseSerial(local->fd);
#else
SYSCALL(close(local->fd));
#endif
}
local->fd = -1;
xf86SumInitPrivate (local->private);
}
static int
xf86SumChangeControl(LocalDevicePtr local, xDeviceCtl* control)
{
xDeviceResolutionCtl *res;
res = (xDeviceResolutionCtl *)control;
if ((res->control != DEVICE_RESOLUTION) ||
(res->num_valuators < 1))
return (BadMatch);
return(Success);
}
static int
xf86SumSwitchMode(ClientPtr client, DeviceIntPtr dev, int mode)
{
LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate;
SummaDevicePtr priv = (SummaDevicePtr)(local->private);
char newmode;
DBG(3, ErrorF("xf86SumSwitchMode dev=%p mode=%d\n", (void *)dev, mode));
switch(mode) {
case Absolute:
priv->flags |= ABSOLUTE_FLAG;
newmode = SS_ABSOLUTE;
break;
case Relative:
priv->flags &= ~ABSOLUTE_FLAG;
newmode = SS_RELATIVE;
break;
default:
DBG(2, ErrorF("xf86SumSwitchMode dev=%p invalid mode=%d\n",
(void *)dev, mode));
return BadMatch;
}
SYSCALL(write(local->fd, &newmode, 1));
return Success;
}
static LocalDevicePtr
xf86SumAllocate(void)
{
LocalDevicePtr local;
SummaDevicePtr priv;
priv = xalloc(sizeof(SummaDeviceRec));
if (!priv)
return NULL;
#ifdef XFREE86_V4
local = xf86AllocateInput(sumDrv, 0);
#else
local = xalloc(sizeof(LocalDeviceRec));
#endif
if (!local) {
xfree(priv);
return NULL;
}
local->name = XI_NAME;
local->type_name = "SummaSketch Tablet";
local->flags = 0;
#ifndef XFREE86_V4
#if !defined(sun) || defined(i386)
local->device_config = xf86SumConfig;
#endif
#endif
local->device_control = xf86SumProc;
local->read_input = xf86SumReadInput;
local->control_proc = xf86SumChangeControl;
local->close_proc = xf86SumClose;
local->switch_mode = xf86SumSwitchMode;
local->conversion_proc = xf86SumConvert;
local->fd = -1;
local->atom = 0;
local->dev = NULL;
local->private = priv;
local->private_flags = 0;
local->history_size = 0;
local->old_x = -1;
local->old_y = -1;
xf86SumInitPrivate (priv);
return local;
}
#ifndef XFREE86_V4
DeviceAssocRec summasketch_assoc =
{
SUMMA_SECTION_NAME,
xf86SumAllocate
};
#ifdef DYNAMIC_MODULE
int
#ifndef DLSYM_BUG
init_module(unsigned long server_version)
#else
init_xf86Summa(unsigned long server_version)
#endif
{
xf86AddDeviceAssoc(&summasketch_assoc);
if (server_version != XF86_VERSION_CURRENT) {
ErrorF("Warning: SummaKetch module compiled for version%s\n",
XF86_VERSION);
return 0;
} else {
return 1;
}
}
#endif
#else
static void
xf86SumUninit(InputDriverPtr drv,
LocalDevicePtr local,
int flags)
{
SummaDevicePtr priv = (SummaDevicePtr) local->private;
DBG(2, ErrorF("xf86SumUninit\n"));
xf86SumProc(local->dev, DEVICE_OFF);
xfree (priv);
xf86DeleteInput(local, 0);
}
static InputInfoPtr
xf86SumInit(InputDriverPtr drv,
IDevPtr dev,
int flags)
{
LocalDevicePtr local = NULL;
SummaDevicePtr priv = NULL;
char *s;
sumDrv = drv;
DBG(2, ErrorF("xf86SumInit allocating...\n"));
local = xf86SumAllocate();
if (!local)
return NULL;
local->conf_idev = dev;
DBG(2, ErrorF("xf86SumInit CollectInputOptions... "));
xf86CollectInputOptions(local, default_options, NULL);
DBG(2, ErrorF("done.\n"));
xf86OptionListReport( local->options );
priv = (SummaDevicePtr) local->private;
local->name = dev->identifier;
priv->sumDevice = xf86FindOptionValue(local->options, "Device");
if (!priv->sumDevice) {
xf86Msg (X_ERROR, "%s: No Device specified.\n", dev->identifier);
goto SetupProc_fail;
}
xf86ProcessCommonOptions(local, local->options);
xf86Msg(X_CONFIG, "%s: serial device is %s\n", dev->identifier,
priv->sumDevice);
debug_level = xf86SetIntOption(local->options, "DebugLevel", 0);
if (debug_level > 0) {
xf86Msg(X_CONFIG, "Summa: debug level set to %d\n", debug_level);
}
priv->sumInc = xf86SetIntOption(local->options, "Increment", -1);
if (priv->sumInc >= 0) {
xf86Msg(X_CONFIG, "%s: increment set to %d\n", local->name, priv->sumInc);
}
s = xf86FindOptionValue(local->options, "Resolution");
if (s) {
priv->sumRes=atoi(s);
xf86Msg(X_CONFIG, "%s: resolution given %d\n", local->name, priv->sumRes);
}
s = xf86FindOptionValue(local->options, "Mode");
if (s && (xf86NameCmp(s, "absolute") == 0)) {
priv->flags = priv->flags | ABSOLUTE_FLAG;
}
else if (s && (xf86NameCmp(s, "relative") == 0)) {
priv->flags = priv->flags & ~ABSOLUTE_FLAG;
}
else if (s) {
xf86Msg(X_ERROR, "%s: invalid Mode (should be absolute or relative). "
"Using default.\n", dev->identifier);
}
xf86Msg(X_CONFIG, "%s: set for %s mode\n", local->name,
(priv->flags & ABSOLUTE_FLAG) ? "absolute" : "relative");
s = xf86FindOption(local->options, "Compatible");
if (s) {
priv->flags|=COMPATIBLE_FLAG;
}
if (xf86FindOption(local->options, "Hitachi_1217D") != NULL) {
priv->flags |= H1217D_FLAG | COMPATIBLE_FLAG;
priv->sumInc = 0;
xf86Msg(X_CONFIG, "%s: Hitachi 1217D, Compatible mode and Increment 0 implied\n",
local->name);
}
if (priv->flags & COMPATIBLE_FLAG) {
xf86Msg(X_CONFIG, "%s: will not query firmware ID.\n", local->name);
}
s = xf86FindOptionValue(local->options, "ZAxis");
if(s){
priv->flags|=Z_AXIS_FLAG;
xf86Msg(X_CONFIG, "Tablet has Z axis (AceCad Flair or compatible)\n");
}
s = xf86FindOptionValue(local->options, "Cursor");
if (s && (xf86NameCmp(s, "stylus") == 0)) {
priv->flags = priv->flags | STYLUS_FLAG;
}
else if (s && (xf86NameCmp(s, "puck") == 0)) {
priv->flags = priv->flags & ~STYLUS_FLAG;
}
else if (s) {
xf86Msg(X_ERROR, "%s: invalid Cursor (should be stylus or puck). "
"Using default.\n", dev->identifier);
}
xf86Msg(X_CONFIG, "%s: cursor mode is %s\n", local->name,
(priv->flags & STYLUS_FLAG) ? "cursor" : "puck");
priv->sumXSize = xf86SetRealOption(local->options, "XSize", 0.0) * 100;
if (priv->sumXSize != 0) {
xf86Msg(X_CONFIG, "%s: XSize = %d.%02din.\n",
dev->identifier, priv->sumXSize/100, priv->sumXSize%100);
}
priv->sumYSize = xf86SetRealOption(local->options, "YSize", 0.0) * 100;
if (priv->sumYSize != 0) {
xf86Msg(X_CONFIG, "%s: YSize = %d.%02din.\n",
dev->identifier, priv->sumYSize/100, priv->sumYSize%100);
}
priv->sumXOffset = xf86SetRealOption(local->options, "XOffset", 0.0) * 100;
if (priv->sumXOffset != 0) {
xf86Msg(X_CONFIG, "%s: XOffset = %d.%02din.\n",
dev->identifier, priv->sumXOffset / 100,
priv->sumXOffset % 100);
}
priv->sumYOffset = xf86SetRealOption(local->options, "YOffset", 0.0) * 100;
if (priv->sumYOffset != 0) {
xf86Msg(X_CONFIG, "%s: YOffset = %d.%02din.\n",
dev->identifier, priv->sumYOffset / 100,
priv->sumYOffset % 100);
}
local->flags |= XI86_POINTER_CAPABLE | XI86_CONFIGURED;
return local;
SetupProc_fail:
if (priv)
xfree(priv);
return local;
}
#ifdef XFree86LOADER
static
#endif
InputDriverRec SUMMA = {
1,
"summa",
NULL,
xf86SumInit,
xf86SumUninit,
NULL,
0
};
#ifdef XFree86LOADER
static void
xf86SumUnplug(pointer p)
{
}
static pointer
xf86SumPlug(pointer module,
pointer options,
int *errmaj,
int *errmin)
{
xf86AddInputDriver(&SUMMA, module, 0);
return module;
}
static XF86ModuleVersionInfo xf86SumVersionRec =
{
"summa",
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
XF86_VERSION_CURRENT,
1, 0, 0,
ABI_CLASS_XINPUT,
ABI_XINPUT_VERSION,
MOD_CLASS_XINPUT,
{0, 0, 0, 0}
};
XF86ModuleData summaModuleData = {&xf86SumVersionRec,
xf86SumPlug,
xf86SumUnplug};
#endif
#endif