#define _DMC_C_
#include <misc.h>
#include <xf86.h>
#define NEED_XF86_TYPES
#include <xf86_ansic.h>
#include <xf86_OSproc.h>
#include <xf86Xinput.h>
#include <xisb.h>
#include <exevents.h>
#include "xf86DMC.h"
InputDriverRec DMC = {
1,
"dmc",
NULL,
DMCPreInit,
NULL,
NULL,
0
};
#ifdef XFree86LOADER
static XF86ModuleVersionInfo VersionRec =
{
"dmc",
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
XF86_VERSION_CURRENT,
1, 0, 0,
ABI_CLASS_XINPUT,
ABI_XINPUT_VERSION,
MOD_CLASS_XINPUT,
{0, 0, 0, 0}
};
static const char *reqSymbols[] = {
"AddEnabledDevice",
"ErrorF",
"InitButtonClassDeviceStruct",
"InitProximityClassDeviceStruct",
"InitValuatorAxisStruct",
"InitValuatorClassDeviceStruct",
"InitPtrFeedbackClassDeviceStruct",
"RemoveEnabledDevice",
"Xcalloc",
"Xfree",
"XisbBlockDuration",
"XisbFree",
"XisbNew",
"XisbRead",
"XisbTrace",
"screenInfo",
"xf86AddInputDriver",
"xf86AllocateInput",
"xf86CloseSerial",
"xf86CollectInputOptions",
"xf86ErrorFVerb",
"xf86FindOptionValue",
"xf86GetMotionEvents",
"xf86GetVerbosity",
"xf86MotionHistoryAllocate",
"xf86NameCmp",
"xf86OpenSerial",
"xf86OptionListCreate",
"xf86OptionListMerge",
"xf86OptionListReport",
"xf86PostButtonEvent",
"xf86PostMotionEvent",
"xf86PostProximityEvent",
"xf86ProcessCommonOptions",
"xf86ScaleAxis",
"xf86SetIntOption",
"xf86SetStrOption",
"xf86XInputSetScreen",
"xf86XInputSetSendCoreEvents",
NULL
};
static pointer
DMCSetupProc( pointer module,
pointer options,
int *errmaj,
int *errmin )
{
xf86LoaderReqSymLists(reqSymbols, NULL);
xf86AddInputDriver(&DMC, module, 0);
return (pointer) 1;
}
XF86ModuleData dmcModuleData = { &VersionRec, DMCSetupProc, NULL };
#endif
static const char *default_options[] =
{
"BaudRate", "9600",
"StopBits", "1",
"DataBits", "8",
"Parity", "None",
"Vmin", "3",
"Vtime", "1",
"FlowControl", "None",
NULL,
};
static InputInfoPtr
DMCPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
{
InputInfoPtr pInfo;
DMCPrivatePtr priv = xcalloc (1, sizeof (DMCPrivateRec));
char *s;
if (!priv)
return NULL;
if (!(pInfo = xf86AllocateInput(drv, 0))) {
xfree(priv);
return NULL;
}
priv->min_x = 0;
priv->max_x = 1024;
priv->min_y = 768;
priv->max_y = 0;
priv->screen_num = 0;
priv->screen_width = -1;
priv->screen_height = -1;
priv->lex_mode = DMC_byte0;
priv->swap_xy = 0;
priv->button_down = FALSE;
priv->button_number = 1;
priv->proximity = FALSE;
priv->pen_down = 0;
pInfo->type_name = XI_TOUCHSCREEN;
pInfo->device_control = DeviceControl;
pInfo->read_input = ReadInput;
pInfo->control_proc = ControlProc;
pInfo->close_proc = CloseProc;
pInfo->switch_mode = SwitchMode;
pInfo->conversion_proc = ConvertProc;
pInfo->dev = NULL;
pInfo->private = priv;
pInfo->private_flags = 0;
pInfo->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
pInfo->conf_idev = dev;
xf86CollectInputOptions(pInfo, default_options, NULL);
xf86OptionListReport( pInfo->options );
pInfo->fd = xf86OpenSerial (pInfo->options);
if (pInfo->fd == -1)
{
ErrorF ("DMC driver unable to open device\n");
goto SetupProc_fail;
}
xf86CloseSerial(pInfo->fd);
priv->min_x = xf86SetIntOption( pInfo->options, "MinX", 0 );
priv->max_x = xf86SetIntOption( pInfo->options, "MaxX", 1024 );
priv->min_y = xf86SetIntOption( pInfo->options, "MinY", 768 );
priv->max_y = xf86SetIntOption( pInfo->options, "MaxY", 0 );
priv->screen_num = xf86SetIntOption( pInfo->options, "ScreenNumber", 0 );
priv->button_number = xf86SetIntOption( pInfo->options, "ButtonNumber", 1 );
priv->swap_xy = xf86SetIntOption( pInfo->options, "SwapXY", 0 );
priv->buffer = NULL;
s = xf86FindOptionValue (pInfo->options, "ReportingMode");
if ((s) && (xf86NameCmp (s, "raw") == 0))
priv->reporting_mode = TS_Raw;
else
priv->reporting_mode = TS_Scaled;
priv->proximity = FALSE;
priv->button_down = FALSE;
priv->lex_mode = DMC_byte0;
if (QueryHardware (priv) != Success)
{
ErrorF ("Unable to query/initialize DMC hardware.\n");
goto SetupProc_fail;
}
pInfo->name = xf86SetStrOption( pInfo->options, "DeviceName", "DMC");
xf86ProcessCommonOptions(pInfo, pInfo->options);
pInfo->flags |= XI86_CONFIGURED;
return (pInfo);
SetupProc_fail:
if ((pInfo) && (pInfo->fd))
xf86CloseSerial (pInfo->fd);
if ((pInfo) && (pInfo->name))
xfree (pInfo->name);
if ((priv) && (priv->buffer))
XisbFree (priv->buffer);
if (priv)
xfree (priv);
return (pInfo);
}
static Bool
DeviceControl (DeviceIntPtr dev, int mode)
{
InputInfoPtr pInfo = dev->public.devicePrivate;
DMCPrivatePtr priv = (DMCPrivatePtr) (pInfo->private);
unsigned char map[] =
{0, 1};
switch (mode)
{
case DEVICE_INIT:
priv->screen_width = screenInfo.screens[priv->screen_num]->width;
priv->screen_height = screenInfo.screens[priv->screen_num]->height;
if (InitButtonClassDeviceStruct (dev, 1, map) == FALSE)
{
ErrorF ("Unable to allocate DMC ButtonClassDeviceStruct\n");
return !Success;
}
if (InitValuatorClassDeviceStruct (dev, 2, xf86GetMotionEvents,
pInfo->history_size, Absolute) == FALSE)
{
ErrorF ("Unable to allocate DMC ValuatorClassDeviceStruct\n");
return !Success;
}
else
{
InitValuatorAxisStruct (dev, 0, priv->min_x, priv->max_x,
9500,
0 ,
9500 );
InitValuatorAxisStruct (dev, 1, priv->min_y, priv->max_y,
10500,
0 ,
10500 );
}
if (InitProximityClassDeviceStruct (dev) == FALSE)
{
ErrorF ("unable to allocate DMC ProximityClassDeviceStruct\n");
return !Success;
}
if (InitPtrFeedbackClassDeviceStruct(dev, DMCPtrCtrl) == FALSE)
{
ErrorF ("unable to allocate DMC PtrFeedbackClassDeviceStruct\n");
return !Success;
}
xf86MotionHistoryAllocate (pInfo);
return (Success);
case DEVICE_ON:
pInfo->fd = xf86OpenSerial(pInfo->options);
if (pInfo->fd == -1)
{
xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
return (!Success);
}
else
{
priv->buffer = XisbNew(pInfo->fd, 64);
if (!priv->buffer)
{
xf86CloseSerial(pInfo->fd);
pInfo->fd = -1;
return (!Success);
}
else
{
unsigned char resbuf[1] = { 0x55 };
unsigned char buf[2] = { 0x05, 0x40 };
XisbBlockDuration (priv->buffer, 500000);
sleep(1);
if ( DMCSendPacket(priv, resbuf, 1) != Success )
{
xf86Msg(X_ERROR, "DMC-Touch reset error\n");
return (!Success);
}
sleep(1);
if ( DMCSendPacket(priv, buf, 2) == Success )
{
priv->lex_mode = DMC_Response0;
if (DMCGetPacket (priv) == Success )
{
if ( priv->packet[0] == 0x06 )
{
buf[0] = 0x31;
DMCSendPacket(priv,buf,1);
priv->lex_mode = DMC_Response0;
xf86Msg(X_INFO, "DMC-Touch found\n");
}
else
{
xf86Msg(X_ERROR, "DMC-Touch not found(bad response)\n");
return (!Success);
}
}
else
{
xf86Msg(X_ERROR, "DMC-Touch not found(no response)\n");
return (!Success);
}
}
else
{
xf86Msg(X_ERROR, "DMC-Touch not found(send error)\n");
return (!Success);
}
}
}
XisbBlockDuration (priv->buffer, -1);
priv->lex_mode = DMC_byte0;
xf86FlushInput(pInfo->fd);
AddEnabledDevice (pInfo->fd);
dev->public.on = TRUE;
return (Success);
case DEVICE_OFF:
case DEVICE_CLOSE:
if (pInfo->fd != -1)
{
RemoveEnabledDevice (pInfo->fd);
if (priv->buffer)
{
XisbFree(priv->buffer);
priv->buffer = NULL;
}
xf86CloseSerial(pInfo->fd);
}
dev->public.on = FALSE;
return (Success);
default:
return (BadValue);
}
}
static void
ReadInput (InputInfoPtr pInfo)
{
DMCPrivatePtr priv = (DMCPrivatePtr) (pInfo->private);
int x,y;
unsigned char opck[ DMC_PACKET_SIZE ];
XisbBlockDuration (priv->buffer, -1);
while (1)
{
memcpy(opck,priv->packet,5);
if ( DMCGetPacket (priv) != Success)
break;
if ( priv->packet[0] == 0x11 )
priv->pen_down=1;
else
priv->pen_down=0;
if ( priv->swap_xy)
{
y = priv->packet[1]*256+priv->packet[2];
x = priv->packet[3]*256+priv->packet[4];
}
else
{
x = priv->packet[1]*256+priv->packet[2];
y = priv->packet[3]*256+priv->packet[4];
}
priv->packet[0] = priv->pen_down ? 0x01 : 0x00;
if (priv->reporting_mode == TS_Scaled)
{
x = xf86ScaleAxis (x, 0, priv->screen_width, priv->min_x,
priv->max_x);
y = xf86ScaleAxis (y, 0, priv->screen_height, priv->min_y,
priv->max_y);
}
xf86XInputSetScreen (pInfo, priv->screen_num, x, y);
if ((priv->proximity == FALSE) && (priv->packet[0] & 0x01))
{
priv->proximity = TRUE;
xf86PostProximityEvent (pInfo->dev, 1, 0, 2, x, y);
}
xf86PostMotionEvent (pInfo->dev, TRUE, 0, 2, x, y);
if ((priv->button_down == FALSE) && (priv->packet[0] & 0x01))
{
xf86PostButtonEvent (pInfo->dev, TRUE,
priv->button_number, 1, 0, 2, x, y);
priv->button_down = TRUE;
}
if ((priv->button_down == TRUE) && !(priv->packet[0] & 0x01))
{
xf86PostButtonEvent (pInfo->dev, TRUE,
priv->button_number, 0, 0, 2, x, y);
priv->button_down = FALSE;
}
if ((priv->proximity == TRUE) && !(priv->packet[0] & 0x01))
{
priv->proximity = FALSE;
xf86PostProximityEvent (pInfo->dev, 0, 0, 2, x, y);
}
}
}
static int
ControlProc (InputInfoPtr pInfo, xDeviceCtl * control)
{
xDeviceTSCalibrationCtl *c = (xDeviceTSCalibrationCtl *) control;
DMCPrivatePtr priv = (DMCPrivatePtr) (pInfo->private);
priv->min_x = c->min_x;
priv->max_x = c->max_x;
priv->min_y = c->min_y;
priv->max_y = c->max_y;
return (Success);
}
static void
CloseProc (InputInfoPtr pInfo)
{
}
static int
SwitchMode (ClientPtr client, DeviceIntPtr dev, int mode)
{
InputInfoPtr pInfo = dev->public.devicePrivate;
DMCPrivatePtr priv = (DMCPrivatePtr) (pInfo->private);
if ((mode == TS_Raw) || (mode == TS_Scaled))
{
priv->reporting_mode = mode;
return (Success);
}
else if ((mode == SendCoreEvents) || (mode == DontSendCoreEvents))
{
xf86XInputSetSendCoreEvents (pInfo, (mode == SendCoreEvents));
return (Success);
}
else
return (!Success);
}
static Bool
ConvertProc (InputInfoPtr pInfo,
int first,
int num,
int v0,
int v1,
int v2,
int v3,
int v4,
int v5,
int *x,
int *y)
{
DMCPrivatePtr priv = (DMCPrivatePtr) (pInfo->private);
if (priv->reporting_mode == TS_Raw)
{
*x = xf86ScaleAxis (v0, 0, priv->screen_width, priv->min_x,
priv->max_x);
*y = xf86ScaleAxis (v1, 0, priv->screen_height, priv->min_y,
priv->max_y);
}
else
{
*x = v0;
*y = v1;
}
return (TRUE);
}
static Bool
QueryHardware (DMCPrivatePtr priv)
{
return (Success);
}
static Bool
DMCGetPacket (DMCPrivatePtr priv)
{
int count = 0;
int c;
while ((c = XisbRead (priv->buffer)) >= 0)
{
if (count++ > 500)
return (!Success);
switch (priv->lex_mode)
{
case DMC_byte0:
if ((( c & 0x3f ) != 0x11 ) &&
(( c & 0x3f ) != 0x10 ))
return (!Success);
priv->packet[0] = (unsigned char) c & 0x3f;
if ( ( (unsigned char) c & 0x3f) == 0x10 )
return (Success);
priv->lex_mode = DMC_byte1;
break;
case DMC_byte1:
priv->packet[1] = (unsigned char) c;
priv->lex_mode = DMC_byte2;
break;
case DMC_byte2:
priv->packet[2] = (unsigned char) c;
priv->lex_mode = DMC_byte3;
break;
case DMC_byte3:
priv->packet[3] = (unsigned char) c;
priv->lex_mode = DMC_byte4;
break;
case DMC_byte4:
priv->packet[4] = (unsigned char) c;
priv->lex_mode = DMC_byte0;
return (Success);
break;
case DMC_Response0:
priv->packet[0] = (unsigned char) c;
return (Success);
break;
}
}
return (!Success);
}
static Bool
DMCSendPacket (DMCPrivatePtr priv, unsigned char *buf, int len)
{
int count = 0;
while ( len > 0 )
{
if ( XisbWrite(priv->buffer, buf, 1) == 1 )
{
buf++;
len--;
continue;
}
if ( count++ > 500 )
break;
}
return (len ? !Success : Success);
}
static void
DMCPtrCtrl(DeviceIntPtr device, PtrCtrl *ctrl)
{
}