#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
#ifdef DBG
#undef DBG
#endif
#ifdef DEBUG
#undef DEBUG
#endif
#ifdef DEBUG
static int debug_level = 0;
#define DBG(lvl, f) {if ((lvl) <= debug_level) f;}
#else
#define DBG(lvl, f)
#endif
#define SYSCALL(call) while(((call) == -1) && (errno == EINTR))
static InputDriverPtr tekDrv;
static const char *default_options[] =
{
"Device", "/dev/ttyS2",
"BaudRate", "9600",
"DataBits", "7",
"StopBits", "1",
"Parity", "Odd",
"FlowControl", "None",
"VTime", "10",
"VMin", "1",
NULL
};
static const int resol[] =
{
2340,
2972,
11700,
11887,
5850,
5944,
4680,
1170,
12,
24
};
typedef struct
{
char *Device;
int LastX;
int LastY;
int LastProximity;
int LastButtons;
int XMax;
int YMax;
int XSize;
int XOffset;
int YSize;
int YOffset;
int Resmode;
int Speed;
int Init;
int Index;
unsigned char Data[9];
} TekDeviceRec, *TekDevicePtr;
static Bool
TekConvert(LocalDevicePtr local,
int first,
int num,
int v0,
int v1,
int v2,
int v3,
int v4,
int v5,
int* x,
int* y)
{
TekDevicePtr priv = (TekDevicePtr) local->private;
int W,H;
ScreenPtr SP;
DBG(6,xf86Msg(X_INFO,"Tek4957:TekConvert (%d,%d)\n",v0,v1));
SP=miPointerCurrentScreen();
W=SP->width;
H=SP->height;
if (first != 0 || num == 1) return (FALSE);
*x = ((long)v0 * (long)W) / (long)priv->XSize;
*y = ((long)v1 * (long)H) / (long)priv->YSize;
DBG(7,xf86Msg(X_INFO,"Tek4957:TekConvert ->(%d,%d)\n",*x,*y));
return (TRUE);
}
static void
TekReadInput(LocalDevicePtr local)
{
TekDevicePtr priv = (TekDevicePtr) local->private;
int len, loop;
int x, y, buttons, prox;
DeviceIntPtr device;
unsigned char buffer[10];
SYSCALL(len = xf86ReadSerial(local->fd, buffer, sizeof(buffer)));
if (len <= 0) {
xf86Msg(X_ERROR,"Tek4957:Error while reading data stream\n");
return;
}
for(loop=0; loop<len; loop++) {
if ((priv->Index == 0) && !(buffer[loop] & 0x40))
continue;
priv->Data[priv->Index++] = buffer[loop];
if (priv->Index == 8) {
priv->Index = 0;
prox = (priv->Data[0] & 1)? 0: 1;
buttons = (priv->Data[1] & 7);
x = (priv->Data[2]&0x3F)|((priv->Data[3]&0x3F)<<6) | ((priv->Data[4]&0x3F)<<12);
y = (priv->Data[5]&0x3F)|((priv->Data[6]&0x3F)<<6) | ((priv->Data[7]&0x3F)<<12);
x -= priv->XOffset;
y -= priv->YOffset;
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x > priv->XSize) x = priv->XSize;
if (y > priv->YSize) y = priv->YSize;
device = local->dev;
if (prox) {
DBG(10,xf86Msg(X_INFO,"Tek4957:TekReadInput Proximity in X=%d Y=%d Buttons=%d\n",x,y,buttons));
if (!(priv->LastProximity))
xf86PostProximityEvent(device, 1, 0, 2, x, y);
if ( (priv->LastX != x) || (priv->LastY != y) )
xf86PostMotionEvent(device,1, 0, 2, x, y);
if (priv->LastButtons != buttons) {
if ((priv->LastButtons&1)!=(buttons&1))
xf86PostButtonEvent(device, 1,1,((buttons&1)>0), 0, 2, x, y);
if ((priv->LastButtons&2)!=(buttons&2))
xf86PostButtonEvent(device, 1,2,((buttons&2)>0), 0, 2, x, y);
if ((priv->LastButtons&4)!=(buttons&4))
xf86PostButtonEvent(device, 1,3,((buttons&4)>0), 0, 2, x, y);
}
priv->LastButtons = buttons;
priv->LastX = x;
priv->LastY = y;
priv->LastProximity = prox;
} else {
DBG(10,xf86Msg(X_INFO,"Tek4957:TekReadInput Proximity out\n"));
if (priv->LastProximity)
xf86PostProximityEvent(device, 0, 0, 2, x, y);
priv->LastProximity = 0;
}
}
}
}
static void
TekControlProc(DeviceIntPtr device, PtrCtrl *ctrl)
{
}
static Bool
TekOpen(LocalDevicePtr local)
{
char Buffer[10];
int err,i;
TekDevicePtr priv = (TekDevicePtr)local->private;
DBG(4,xf86Msg(X_INFO,"Tek4957:TekOpen\n"));
SYSCALL(err = xf86WriteSerial(local->fd,"\x1B" "Z" , 2));
if (err == -1) {
xf86Msg(X_ERROR,"Tek4957:Write error\n");
return !Success;
}
err = xf86WaitForInput(-1, 100000);
xf86FlushInput(local->fd);
SYSCALL(err = xf86WriteSerial(local->fd,"\x1B" "x" , 2));
if (err == -1) {
xf86Msg(X_ERROR,"Tek4957:Write error\n");
return !Success;
}
i=0;
while (i < 6) {
err = xf86WaitForInput(local->fd, 300000);
if (err == -1) {
xf86Msg(X_ERROR,"Tek4957:WaitForInput\n");
return !Success;
}
if (!err) {
xf86Msg(X_ERROR,"Tek4957:Timeout while reading tablet. No tablet connected ???\n");
return !Success;
}
SYSCALL(err = xf86ReadSerial(local->fd,&Buffer[i++], 1));
if (err == -1) {
xf86Msg(X_ERROR,"Tek4957:Read error\n");
return !Success;
}
if (!err) break;
}
Buffer[i]=0;
if ((Buffer[0] != '.') || (Buffer[1] != '#' )) {
xf86Msg(X_ERROR,"Tek4957:Tablet detection error %d [%s]\n",i,Buffer);
return !Success;
}
Buffer[0]='\x1B';
Buffer[1]='C';
Buffer[2]='0'+priv->Resmode;
Buffer[3]='\x1B';
Buffer[4]='R';
Buffer[5]='0'+priv->Speed;
SYSCALL(err = xf86WriteSerial(local->fd,Buffer, 6));
if (err == -1) {
xf86Msg(X_ERROR,"Tek4957:Write error\n");
return !Success;
}
SYSCALL(err = xf86WriteSerial(local->fd,"\x1B""F3""\x1B""I001""\x1B""M0" , 11));
if (err == -1) {
xf86Msg(X_ERROR,"Tek4957:Write error\n");
return !Success;
}
xf86FlushInput(local->fd);
return Success;
}
static Bool
TekOpenDevice(DeviceIntPtr pDev)
{
LocalDevicePtr local = (LocalDevicePtr)pDev->public.devicePrivate;
TekDevicePtr priv = (TekDevicePtr)local->private;
local->fd = xf86OpenSerial(local->options);
if (local->fd == -1) {
return !Success;
}
xf86Msg(X_INFO,"Tek4957:%s opened as fd %d\n", priv->Device, local->fd);
if (TekOpen(local) != Success) {
xf86Msg(X_ERROR,"Tek4957:Initialisation error\n");
if (local->fd >= 0) {
SYSCALL(xf86CloseSerial(local->fd));
}
local->fd = -1;
} else {
InitValuatorAxisStruct(pDev,
0,
0,
priv->XSize,
20000,
0,
20000);
InitValuatorAxisStruct(pDev,
1,
0,
priv->YSize,
20000,
0,
20000);
xf86Msg(X_PROBED,"Tek4957:Initialisation completed\n");
}
return (local->fd != -1);
}
static int
TekProc(DeviceIntPtr pDev, int what)
{
CARD8 map[4];
int loop;
LocalDevicePtr local = (LocalDevicePtr)pDev->public.devicePrivate;
TekDevicePtr priv = (TekDevicePtr)local->private;
DBG(5,xf86Msg(X_INFO,"Tek4957:TekProc pDev=0x%x priv=0x%x what=%d\n", pDev, priv, what));
switch (what) {
case DEVICE_INIT:
DBG(2,xf86Msg(X_INFO,"Tek4957:TekProc pDev=0x%x priv=0x%x what=INIT\n", pDev, priv));
if (priv->Init==1) break;
for(loop=1; loop<=3; loop++) map[loop] = loop;
if (InitButtonClassDeviceStruct(pDev,3,map) == FALSE) {
xf86Msg(X_ERROR,"Tek4957:Unable to allocate Button class device\n");
return !Success;
}
if (InitFocusClassDeviceStruct(pDev) == FALSE) {
xf86Msg(X_ERROR,"Tek4957:Unable to init Focus class device\n");
return !Success;
}
if (InitPtrFeedbackClassDeviceStruct(pDev,TekControlProc) == FALSE) {
xf86Msg(X_ERROR,"Tek4957:Unable to init ptr feedback\n");
return !Success;
}
if (InitProximityClassDeviceStruct(pDev) == FALSE) {
xf86Msg(X_ERROR,"Tek4957:Unable to init proximity class device\n");
return !Success;
}
if (InitValuatorClassDeviceStruct(pDev,2,xf86GetMotionEvents,
local->history_size,Absolute)== FALSE) {
xf86Msg(X_ERROR,"Tek4957:Unable to allocate Valuator class device\n");
return !Success;
}
TekOpenDevice(pDev);
priv->Init=1;
break;
case DEVICE_ON:
DBG(2,xf86Msg(X_INFO,"Tek4957:TekProc pDev=0x%x priv=0x%x what=ON\n", pDev, priv));
if (pDev->public.on) break;
if ((local->fd < 0) && (!TekOpenDevice(pDev))) {
return !Success;
}
pDev->public.on = TRUE;
xf86AddEnabledDevice(local);
break;
case DEVICE_OFF:
DBG(2,xf86Msg(X_INFO,"Tek4957:TekProc pDev=0x%x priv=0x%x what=OFF\n", pDev, priv));
if (! pDev->public.on) break;
xf86RemoveEnabledDevice(local);
if (local->fd >= 0)
pDev->public.on = FALSE;
break;
case DEVICE_CLOSE:
DBG(2,xf86Msg(X_INFO,"Tek4957:TekProc pDev=0x%x priv=0x%x what=CLOSE\n", pDev, priv));
if (local->fd != -1) {
SYSCALL(xf86CloseSerial(local->fd));
local->fd = -1;
}
break;
default:
DBG(2,xf86Msg(X_INFO,"Tek4957:TekProc Unsupported mode=%d\n",what));
return !Success;
break;
}
return Success;
}
static void
TekClose(LocalDevicePtr local)
{
DBG(2,xf86Msg(X_INFO,"Tek4957:TekClose local = %lx, ->fd = %d\n", local, local->fd));
if (local->fd >= 0) {
xf86CloseSerial(local->fd);
}
local->fd = -1;
}
static int
TekChangeControl(LocalDevicePtr local, xDeviceCtl* control)
{
return(Success);
}
static int
TekSwitchMode(ClientPtr client, DeviceIntPtr dev, int mode)
{
return !Success;
}
static void
TekUninit(InputDriverPtr drv,
LocalDevicePtr local,
int flags)
{
TekDevicePtr priv = (TekDevicePtr) local->private;
ErrorF("TekUninit\n");
TekProc(local->dev, DEVICE_OFF);
xfree (priv);
xf86DeleteInput(local, 0);
}
static InputInfoPtr
TekInit(InputDriverPtr drv,
IDevPtr dev,
int flags)
{
LocalDevicePtr local = NULL;
TekDevicePtr priv = NULL;
int min,max;
tekDrv = drv;
xf86Msg(X_INFO,"Tek4957:Allocating device...\n");
priv = xalloc(sizeof(TekDeviceRec));
if (!priv) return NULL;
local = xf86AllocateInput(tekDrv, 0);
if (!local) {
xfree(priv);
return NULL;
}
local->name = "TEK4957";
local->type_name = XI_TABLET;
local->flags = 0;
local->device_control = TekProc;
local->read_input = TekReadInput;
local->control_proc = TekChangeControl;
local->close_proc = TekClose;
local->switch_mode = TekSwitchMode;
local->conversion_proc = TekConvert;
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;
#if defined (sun) && !defined(i386)
char *dev_name;
#endif
#if defined(sun) && !defined(i386)
if ((dev_name = getenv("TEK4957_DEV"))) {
priv->Device = xalloc(strlen(dev_name) + 1);
strcpy(priv->Device, dev_name);
xf86Msg(X_INFO,"Tek4957:Port selected : %s\n", priv->Device);
} else {
priv->Device = "";
}
#else
priv->Device = "";
#endif
local->conf_idev = dev;
xf86CollectInputOptions(local, default_options, NULL);
xf86OptionListReport( local->options );
priv = (TekDevicePtr) local->private;
local->name = dev->identifier;
#ifdef DEBUG
debug_level = xf86SetIntOption(local->options, "DebugLevel", 0);
if (debug_level > 0) {
xf86Msg(X_CONFIG, "Tek4957:Debug level set to %d\n", debug_level);
}
#endif
priv->Device = xf86FindOptionValue(local->options, "Device");
if (!priv->Device) {
xf86Msg (X_ERROR, "Tek4957: %s: No Device specified.\n", dev->identifier);
goto SetupProc_fail;
}
xf86ProcessCommonOptions(local, local->options);
xf86Msg(X_CONFIG, "Tek4957: %s: serial device is %s\n", dev->identifier,
priv->Device);
priv->Resmode = xf86SetIntOption (local->options,"Resolution",5);
priv->XMax=resol[priv->Resmode];
priv->YMax=resol[priv->Resmode];
if ((priv->Resmode<0)||(priv->Resmode>9)) {
xf86Msg(X_ERROR,"Tek4957: Invalid resolution specified. Using default\n");
priv->Resmode=5;
priv->XMax=resol[priv->Resmode];
priv->YMax=resol[priv->Resmode];
} else {
xf86Msg(X_CONFIG,"Tek4957: Resolution [%d] = %d positions\n",priv->Resmode,priv->XMax);
}
priv->Speed = xf86SetIntOption (local->options, "Speed", 6 );
if ((priv->Speed<0)||(priv->Speed>6)) {
xf86Msg(X_ERROR,"Tek4957: Invalid speed specified. Using default\n");
priv->Speed=5;
} else {
xf86Msg(X_CONFIG,"Tek4957: Speed = %d\n",priv->Speed);
}
min = xf86SetIntOption( local->options, "TopX", 0 );
max = xf86SetIntOption( local->options, "BottomX",priv->XMax );
if (((max-min)<=0)||(max>priv->XMax)||(min<0)) {
xf86Msg(X_ERROR,"Tek4957:Invalid X interval specified : TopX=%d, BottomX=%d\n",min,max);
min=0; max=priv->XMax;
} else {
xf86Msg(X_CONFIG,"Tek4957:X interval :TopX=%d, BottomX=%d\n",min,max);
}
priv->XSize=max-min;
priv->XOffset=min;
min = xf86SetIntOption( local->options, "TopY", 0 );
max = xf86SetIntOption( local->options, "BottomY",priv->YMax );
if (((max-min)<=0)||(max>priv->YMax)||(min<0)) {
xf86Msg(X_ERROR,"Tek4957:Invalid Y interval specified : TopY=%d, BottomY=%d\n",min,max);
min=0; max=priv->XMax;
} else {
xf86Msg(X_CONFIG,"Tek4957:Y interval :TopY=%d, BottomY=%d\n",min,max);
}
priv->YSize=max-min;
priv->YOffset=min;
priv->Index = 0;
priv->Init = 0;
priv->LastX = -1;
priv->LastY = -1;
priv->LastProximity = 0;
priv->LastButtons = 0;
local->flags |= XI86_POINTER_CAPABLE | XI86_CONFIGURED;
return local;
SetupProc_fail:
if (priv)
xfree(priv);
return local;
}
#ifdef XFree86LOADER
static
#endif
InputDriverRec TEK4957 = {
1,
"tek4957",
NULL,
TekInit,
TekUninit,
NULL,
0
};
#ifdef XFree86LOADER
static void
TekUnplug(pointer p)
{
}
static pointer
TekPlug(pointer module,
pointer options,
int *errmaj,
int *errmin)
{
xf86AddInputDriver(&TEK4957, module, 0);
return module;
}
static XF86ModuleVersionInfo TekVersionRec =
{
"tek4957",
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
XF86_VERSION_CURRENT,
1, 0, 0,
ABI_CLASS_XINPUT,
ABI_XINPUT_VERSION,
MOD_CLASS_XINPUT,
{0, 0, 0, 0}
};
XF86ModuleData tek4957ModuleData = {&TekVersionRec,
TekPlug,
TekUnplug};
#endif