#include <xf86Version.h>
# ifndef XFree86LOADER
# include <unistd.h>
# include <errno.h>
# endif
# include <misc.h>
# include <xf86.h>
# if !defined(DGUX)
# include <xf86_ansic.h>
# endif
# include <xf86_OSproc.h>
# include <xf86Xinput.h>
# include <exevents.h>
# ifdef XFree86LOADER
# include <xf86Module.h>
# endif
#define FPIT_LINK_SPEED B19200
#define FPIT_PORT "/dev/ttyS3"
#define FPIT_MAX_X 4100
#define FPIT_MIN_X 0
#define FPIT_MAX_Y 4100
#define FPIT_MIN_Y 0
#define PHASING_BIT 0x80
#define PROXIMITY_BIT 0x40
#define XSIGN_BIT 0x10
#define YSIGN_BIT 0x08
#define BUTTON_BITS 0x07
#define COORD_BITS 0x7f
#define FPIT_PACKET_SIZE 5
#define BUFFER_SIZE (FPIT_PACKET_SIZE*20)
typedef struct {
char *fpitDev;
int screen_width;
int screen_height;
int screen_no;
int fpitInc;
int fpitButTrans;
int fpitOldX;
int fpitOldY;
int fpitOldProximity;
int fpitOldButtons;
int fpitMinX;
int fpitMinY;
int fpitMaxX;
int fpitMaxY;
int fpitInvX;
int fpitInvY;
int fpitRes;
int flags;
int fpitIndex;
int fpitBaud;
unsigned char fpitData[BUFFER_SIZE];
int fpitSwapXY;
} FpitPrivateRec, *FpitPrivatePtr;
static Bool xf86FpitConvert(LocalDevicePtr local, int first, int num, int v0, int v1, int v2, int v3, int v4, int v5, int *x, int *y)
{
FpitPrivatePtr priv = (FpitPrivatePtr) local->private;
if (first != 0 || num != 2) {
return FALSE;
}
if (priv->fpitSwapXY != 0) {
*x = xf86ScaleAxis(v1, 0, priv->screen_width, priv->fpitMinY, priv->fpitMaxY);
*y = xf86ScaleAxis(v0, 0, priv->screen_height, priv->fpitMinX, priv->fpitMaxX);
} else {
*x = xf86ScaleAxis(v0, 0, priv->screen_width, priv->fpitMinX, priv->fpitMaxX);
*y = xf86ScaleAxis(v1, 0, priv->screen_height, priv->fpitMinY, priv->fpitMaxY);
}
xf86XInputSetScreen(local, priv->screen_no, *x, *y);
return TRUE;
}
static void xf86FpitReadInput(LocalDevicePtr local)
{
FpitPrivatePtr priv = (FpitPrivatePtr) local->private;
int len, loop, found;
int is_core_pointer;
int x, y, buttons, prox;
DeviceIntPtr device;
len = xf86ReadSerial(local->fd, priv->fpitData, BUFFER_SIZE);
if (len <= 0) {
Error("error reading FPIT device");
priv->fpitIndex = 0;
return;
}
priv->fpitIndex += len;
found = 0;
for (loop = priv->fpitIndex - 5; loop >= 0; loop--) {
if (priv->fpitData[loop] & 0x80) {
found = 1;
break;
}
}
if (!found) {
return;
}
x = (int) (priv->fpitData[loop + 1] & 0x7f) + ((int) (priv->fpitData[loop + 2] & 0x7f) << 7);
y = (int) (priv->fpitData[loop + 3] & 0x7f) + ((int) (priv->fpitData[loop + 4] & 0x7f) << 7);
if (priv->fpitInvX)
x = priv->fpitMaxX - x + priv->fpitMinX;
if (priv->fpitInvY)
y = priv->fpitMaxY - y + priv->fpitMinY;
prox = (priv->fpitData[loop] & PROXIMITY_BIT) ? 0 : 1;
buttons = (priv->fpitData[loop] & BUTTON_BITS);
priv->fpitIndex = 0;
device = local->dev;
is_core_pointer = xf86IsCorePointer(device);
if (prox) {
if (!(priv->fpitOldProximity))
if (!is_core_pointer)
xf86PostProximityEvent(device, 1, 0, 2, x, y);
if ((priv->fpitOldX != x) || (priv->fpitOldY != y)) {
if (priv->fpitOldProximity) {
xf86PostMotionEvent(device, 1, 0, 2, x, y);
}
}
if (priv->fpitOldButtons != buttons) {
int delta;
delta = buttons - priv->fpitOldButtons;
while (delta) {
int id;
id = ffs(delta);
delta &= ~(1 << (id - 1));
xf86PostButtonEvent(device, 1, id, (buttons & (1 << (id - 1))), 0, 2, x, y);
}
}
priv->fpitOldButtons = buttons;
priv->fpitOldX = x;
priv->fpitOldY = y;
priv->fpitOldProximity = prox;
} else {
if (!is_core_pointer)
if (priv->fpitOldProximity)
xf86PostProximityEvent(device, 0, 0, 2, x, y);
priv->fpitOldProximity = 0;
}
}
static void xf86FpitPtrCtrl(DeviceIntPtr device, PtrCtrl *ctrl)
{
}
static Bool xf86FpitControl(DeviceIntPtr dev, int mode)
{
LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
FpitPrivatePtr priv = (FpitPrivatePtr) (local->private);
unsigned char map[] = {
0, 1, 2
};
switch (mode) {
case DEVICE_INIT:
{
if (priv->screen_no >= screenInfo.numScreens || priv->screen_no < 0) {
priv->screen_no = 0;
}
priv->screen_width = screenInfo.screens[priv->screen_no]->width;
priv->screen_height = screenInfo.screens[priv->screen_no]->height;
if (InitButtonClassDeviceStruct(dev, 3, map) == FALSE) {
ErrorF("Unable to allocate Fpit touchscreen ButtonClassDeviceStruct\n");
return !Success;
}
if (InitFocusClassDeviceStruct(dev) == FALSE) {
ErrorF("Unable to allocate Fpit touchscreen FocusClassDeviceStruct\n");
return !Success;
}
if(InitPtrFeedbackClassDeviceStruct(dev, xf86FpitPtrCtrl) == FALSE) {
ErrorF("Unable to allocate PtrFeedBackClassDeviceStruct\n");
}
if (InitValuatorClassDeviceStruct(dev, 2, xf86GetMotionEvents, local->history_size, Absolute) == FALSE) {
ErrorF("Unable to allocate Elographics touchscreen ValuatorClassDeviceStruct\n");
return !Success;
} else {
InitValuatorAxisStruct(dev, 0, priv->fpitMinX, priv->fpitMaxX, 9500, 0 ,
9500 );
InitValuatorAxisStruct(dev, 1, priv->fpitMinY, priv->fpitMaxY, 10500, 0 ,
10500 );
}
if (InitFocusClassDeviceStruct(dev) == FALSE) {
ErrorF("Unable to allocate Fpit touchscreen FocusClassDeviceStruct\n");
}
xf86MotionHistoryAllocate(local);
return Success;
}
case DEVICE_ON:
if (local->fd < 0) {
local->fd = xf86OpenSerial(local->options);
if (local->fd < 0) {
Error("Unable to open Fpit touchscreen device");
return !Success;
}
xf86AddEnabledDevice(local);
dev->public.on = TRUE;
}
return Success;
case DEVICE_OFF:
dev->public.on = FALSE;
if (local->fd >= 0) {
xf86RemoveEnabledDevice(local);
}
xf86CloseSerial(local->fd);
local->fd = -1;
return Success;
case DEVICE_CLOSE:
dev->public.on = FALSE;
if (local->fd >= 0) {
RemoveEnabledDevice(local->fd);
}
xf86CloseSerial(local->fd);
local->fd = -1;
return Success;
default:
ErrorF("unsupported mode=%d\n", mode);
return !Success;
}
}
static LocalDevicePtr xf86FpitAllocate(InputDriverPtr drv)
{
LocalDevicePtr local;
FpitPrivatePtr priv;
priv = xalloc(sizeof(FpitPrivateRec));
if (!priv)
return NULL;
local = xf86AllocateInput(drv, 0);
if (!local) {
xfree(priv);
return NULL;
}
priv->fpitDev = strdup(FPIT_PORT);
priv->screen_no = 0;
priv->screen_width = -1;
priv->screen_height = -1;
priv->fpitMinX = FPIT_MIN_X;
priv->fpitMaxX = FPIT_MAX_X;
priv->fpitMinY = FPIT_MIN_Y;
priv->fpitMaxY = FPIT_MAX_Y;
priv->fpitOldX = priv->fpitOldY = -1;
priv->fpitOldButtons = 0;
priv->fpitOldProximity = 0;
priv->fpitIndex = 0;
priv->fpitSwapXY = 0;
local->name = XI_TOUCHSCREEN;
local->flags = 0 ;
local->device_control = xf86FpitControl;
local->read_input = xf86FpitReadInput;
local->control_proc = NULL;
local->close_proc = NULL;
local->switch_mode = NULL;
local->conversion_proc = xf86FpitConvert;
local->reverse_conversion_proc = NULL;
local->fd = -1;
local->atom = 0;
local->dev = NULL;
local->private = priv;
local->type_name = "Fujitsu Stylistic";
local->history_size = 0;
return local;
}
static void xf86FpitUninit(InputDriverPtr drv, LocalDevicePtr local, int flags)
{
FpitPrivatePtr priv = (FpitPrivatePtr) local->private;
xf86FpitControl(local->dev, DEVICE_OFF);
xfree(priv->fpitDev);
xfree(priv);
xfree(local->name);
xfree(local);
xf86DeleteInput(local, 0);
}
static const char *default_options[] = {
"BaudRate", "19200", "StopBits", "0", "DataBits", "8", "Parity", "None", "Vmin", "10", "Vtime", "1", "FlowControl", "None", NULL
};
static InputInfoPtr xf86FpitInit(InputDriverPtr drv, IDevPtr dev, int flags)
{
LocalDevicePtr local = NULL;
FpitPrivatePtr priv = NULL;
char *str;
local = xf86FpitAllocate(drv);
if (!local)
return NULL;
priv = local->private;
local->conf_idev = dev;
xf86CollectInputOptions(local, default_options, NULL);
xf86ProcessCommonOptions(local, local->options);
str = xf86FindOptionValue(local->options, "Device");
if (!str) {
xf86Msg(X_ERROR, "%s: No Device specified in FPIT module config.\n", dev->identifier);
if (priv) {
if (priv->fpitDev) {
xfree(priv->fpitDev);
}
xfree(priv);
}
return local;
}
priv->fpitDev = strdup(str);
local->name = xf86SetStrOption(local->options, "DeviceName", XI_TOUCHSCREEN);
xf86Msg(X_CONFIG, "FPIT device name: %s\n", local->name);
priv->screen_no = xf86SetIntOption(local->options, "ScreenNo", 0);
xf86Msg(X_CONFIG, "Fpit associated screen: %d\n", priv->screen_no);
priv->fpitMaxX = xf86SetIntOption(local->options, "MaximumXPosition", 4100);
xf86Msg(X_CONFIG, "FPIT maximum x position: %d\n", priv->fpitMaxX);
priv->fpitMinX = xf86SetIntOption(local->options, "MinimumXPosition", 0);
xf86Msg(X_CONFIG, "FPIT minimum x position: %d\n", priv->fpitMinX);
priv->fpitMaxY = xf86SetIntOption(local->options, "MaximumYPosition", 4100);
xf86Msg(X_CONFIG, "FPIT maximum y position: %d\n", priv->fpitMaxY);
priv->fpitMinY = xf86SetIntOption(local->options, "MinimumYPosition", 0);
xf86Msg(X_CONFIG, "FPIT minimum y position: %d\n", priv->fpitMinY);
priv->fpitInvX = xf86SetBoolOption(local->options, "InvertX", 0);
priv->fpitInvY = xf86SetBoolOption(local->options, "InvertY", 0);
priv->fpitSwapXY = xf86SetBoolOption(local->options, "SwapXY", 0);
str = xf86SetStrOption(local->options, "Rotate", 0);
if (!xf86NameCmp(str, "CW")) {
priv->fpitInvX = 1;
priv->fpitInvY = 1;
priv->fpitSwapXY = 1;
} else if (!xf86NameCmp(str, "CCW")) {
priv->fpitInvX = 0;
priv->fpitInvY = 0;
priv->fpitSwapXY = 1;
}
xf86Msg(X_CONFIG, "FPIT invert X axis: %s\n", priv->fpitInvX ? "Yes" : "No");
xf86Msg(X_CONFIG, "FPIT invert Y axis: %s\n", priv->fpitInvY ? "Yes" : "No");
xf86Msg(X_CONFIG, "FPIT swap X and Y axis: %s\n", priv->fpitSwapXY ? "Yes" : "No");
local->flags |= XI86_CONFIGURED;
return local;
}
#ifdef XFree86LOADER
static
#endif
InputDriverRec FPIT = {
1,
"fpit",
NULL,
xf86FpitInit,
xf86FpitUninit,
NULL,
0
};
#ifdef XFree86LOADER
static pointer Plug(pointer module, pointer options, int *errmaj, int *errmin)
{
xf86AddInputDriver(&FPIT, module, 0);
return module;
}
static void Unplug(pointer p)
{
}
static XF86ModuleVersionInfo version_rec = {
"fpit", MODULEVENDORSTRING, MODINFOSTRING1, MODINFOSTRING2, XF86_VERSION_CURRENT, 1, 0, 0, ABI_CLASS_XINPUT, ABI_XINPUT_VERSION, MOD_CLASS_XINPUT,
{0, 0, 0, 0}
};
XF86ModuleData fpitModuleData = {
&version_rec, Plug, Unplug
};
#endif