#define _citron_C_
#define PK 0
#define INITT 0
#define CITOUCH_VERSION 0x211
char version[]="Touch Driver V2.1.1 (c) 1999-2003 Citron GmbH";
#define CITOUCH_VERSION_MAJOR ((CITOUCH_VERSION >> 8) & 0xf)
#define CITOUCH_VERSION_MINOR ((CITOUCH_VERSION >> 4) & 0xf)
#define CITOUCH_VERSION_PATCH ((CITOUCH_VERSION >> 0) & 0xf)
#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"
#define CIT_BEEP
#include "citron.h"
#define CIT_DEF_MIN_X 0
#define CIT_DEF_MAX_X 0xFFFF
#define CIT_DEF_MIN_Y 0
#define CIT_DEF_MAX_Y 0xFFFF
#define CIT_BUFFER_SIZE 1024
#ifdef DBG
#undef DBG
#endif
#ifdef DEBUG
#undef DEBUG
#endif
static int debug_level = 0;
#define DEBUG
#ifdef DEBUG
#define DBG(lvl, f) {if ((lvl) <= debug_level) f;}
#else
#define DBG(lvl, f)
#endif
#define PP 5
#define RI 6
#define GP 6
#define DDS 5
#define DC 5
#define XFREE86_V4
#ifdef XFREE86_V4
#define WAIT(t) \
err = xf86WaitForInput(-1, ((t) * 1000)); \
if (err == -1) { \
ErrorF("Citron select error\n"); \
return !Success; \
}
#else
#define WAIT(t) \
timeout.tv_sec = 0; \
timeout.tv_usec = (t) * 1000; \
SYSCALL(err = select(0, NULL, NULL, NULL, &timeout)); \
if (err == -1) { \
ErrorF("Citron select error : %s\n", strerror(errno)); \
return !Success; \
}
#endif
static InputInfoPtr CitronPreInit(InputDriverPtr drv, IDevPtr dev, int flags);
InputDriverRec CITRON = {
1,
"citron",
NULL,
CitronPreInit,
NULL,
NULL,
0
};
static char *UserStrNames[] =
{
"NAME",
"REV",
"RECEIVERBOARD",
"TOUCH",
"DISPLAY",
"INVERTER",
"MECHANICS",
"PAR1",
"PAR2",
NULL
};
#ifdef XFree86LOADER
static XF86ModuleVersionInfo VersionRec =
{
"citron",
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
XF86_VERSION_CURRENT,
CITOUCH_VERSION_MAJOR,
CITOUCH_VERSION_MINOR,
CITOUCH_VERSION_PATCH,
ABI_CLASS_XINPUT,
ABI_XINPUT_VERSION,
MOD_CLASS_XINPUT,
{0, 0, 0, 0}
};
static pointer
SetupProc( pointer module,
pointer options,
int *errmaj,
int *errmin )
{
xf86AddInputDriver(&CITRON, module, 0);
DBG(5, ErrorF ("%sSetupProc called\n", CI_INFO));
return (pointer) 1;
}
static void
TearDownProc (pointer p)
{
DBG(5, ErrorF ("%sTearDownProc Called\n", CI_INFO));
}
XF86ModuleData citronModuleData = { &VersionRec, SetupProc, TearDownProc};
#endif
static const char *default_options[] =
{
"BaudRate", "19200",
"StopBits", "1",
"DataBits", "8",
"Parity", "None",
"Vmin", "1",
"Vtime", "1",
"FlowControl", "None",
"ClearDTR", ""
};
static void cit_SendLockZ(cit_PrivatePtr priv);
static int cit_SendString(XISBuffer *b, unsigned char cmd, int cnt, char *ustr);
static Bool cit_GetUserString(cit_PrivatePtr priv, char *ustr_name, char *ustr_cont, Bool scan_flg);
static void
cit_SendtoTouch(DeviceIntPtr dev)
{
LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
cit_PrivatePtr priv = (cit_PrivatePtr)(local->private);
int i,j;
unsigned char buf[MAX_BYTES_TO_TRANSFER*2+2];
DBG(DDS, ErrorF("%scit_SendtoTouch(numbytes=0x%02X, ", CI_INFO, priv->dds.numbytes));
for(i=0; i<priv->dds.numbytes; i++)
{
DBG(DDS, ErrorF("%02x ", priv->dds.data[i]));
}
DBG(DDS, ErrorF(")\n"));
j=0;
buf[j++] = CTS_STX;
for(i=0; i<priv->dds.numbytes; i++)
{
if (priv->dds.data[i] >= CTS_CTRLMIN && priv->dds.data[i] <= CTS_CTRLMAX)
{
buf[j++] = CTS_ESC;
buf[j++] = priv->dds.data[i] | CTS_ENCODE;
}
else buf[j++] = priv->dds.data[i];
}
buf[j++] = CTS_ETX;
XisbWrite(priv->buffer, buf, j);
for(i=0; i<j; i++)
{
if(i == 0)
{
DBG(DDS, ErrorF("%s sent=", CI_INFO));
}
else if(i%16 == 0)
{
DBG(DDS, ErrorF("\n"));
}
DBG(DDS, ErrorF("%02x ",buf[i]));
}
DBG(DDS, ErrorF("\n"));
}
static void
cit_ParseCommand(DeviceIntPtr dev)
{
LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
cit_PrivatePtr priv = (cit_PrivatePtr)(local->private);
int i;
DBG(DDS, ErrorF("%scit_ParseCommand: numbytes=0x%02X, data= ", CI_INFO, priv->dds.numbytes));
for(i=0; i<priv->dds.numbytes; i++)
DBG(DDS, ErrorF("%02x ", priv->dds.data[i]));
DBG(DDS,ErrorF("\n"));
switch(priv->dds.data[0]&0xff)
{
case C_SETPWM:
priv->pwm_active = priv->dds.data[1];
priv->pwm_sleep = priv->dds.data[2];
priv->dds.data[1] = cit_AdjustBright(priv, priv->dds.data[1]);
priv->dds.data[2] = cit_AdjustBright(priv, priv->dds.data[2]);
DBG(DDS, ErrorF("%scit_ParseCommand: PWM Active:%d PWM Sleep:%d \n", CI_INFO, priv->dds.data[1], priv->dds.data[2]));
break;
case C_SETPWMFREQ:
priv->pwm_freq = (int)priv->dds.data[1] | (int)(priv->dds.data[2] << 8);
DBG(DDS, ErrorF("%scit_ParseCommand: PWM Freq:%d\n", CI_INFO, priv->pwm_freq));
break;
case C_SETSLEEPMODE:
if(priv->dds.data[1] == 0)
{
priv->sleep_time_act = priv->dds.data[2] | (priv->dds.data[3] << 8);
}
DBG(DDS, ErrorF("%scit_ParseCommand: Sleep Time act:%d \n", CI_INFO, priv->sleep_time_act));
break;
case C_SETDOZEMODE:
if(priv->dds.data[1] == 0)
{
priv->doze_time_act = priv->dds.data[2] | (priv->dds.data[3] << 8);
}
DBG(DDS, ErrorF("%scit_ParseCommand: Doze Time act:%d \n", CI_INFO, priv->doze_time_act));
break;
case C_SETAREAPRESSURE:
priv->button_threshold = priv->dds.data[1];
DBG(DDS, ErrorF("%scit_ParseCommand: Button Threshold:%d \n", CI_INFO, priv->button_threshold));
break;
case C_SETLOCKZ:
priv->lockz_enter_time = priv->dds.data[1];
priv->lockz_exit_time = priv->dds.data[2];
priv->lockz_lock_time = priv->dds.data[3];
DBG(DDS, ErrorF("%scit_ParseCommand: LockZ: enter %d, exit %d, lock %d \n", CI_INFO,
priv->lockz_enter_time, priv->lockz_exit_time, priv->lockz_lock_time));
break;
default:
DBG(DDS, ErrorF("%scit_ParseCommand: Command %d [0x%02x] not found\n", CI_INFO, priv->dds.data[0], priv->dds.data[0]));
break;
}
}
static void
cit_DriverComm(DeviceIntPtr dev)
{
LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
cit_PrivatePtr priv = (cit_PrivatePtr)(local->private);
int i;
unsigned short tmp;
DBG(DC, ErrorF("%scit_DriverComm(numbytes=0x%02X, data[1]=%02x, ...)\n", CI_INFO, priv->dds.numbytes, priv->dds.data[1]));
i=1;
switch(priv->dds.data[i++])
{
case D_SETCLICKMODE:
priv->click_mode = priv->dds.data[i++];
ErrorF("%sClick Mode: %d\n", CI_INFO, priv->click_mode);
cit_SetEnterCount(priv);
break;
case D_BEEP:
priv->beep = priv->dds.data[i++];
ErrorF("%sBeep: %s\n", CI_INFO, (priv->beep > 0) ? "activated":"not activated");
break;
case D_SETBEEP:
priv->press_vol = priv->dds.data[i++];
ErrorF("%sBeep Pressure Volume: %d\n", CI_INFO, priv->press_vol);
tmp = priv->dds.data[i++];
tmp += priv->dds.data[i++] << 8;
priv->press_pitch = tmp;
ErrorF("%sBeep Pressure Pitch: %d\n", CI_INFO, priv->press_pitch);
priv->press_dur = priv->dds.data[i++];
ErrorF("%sBeep Pressure Duration: %d\n", CI_INFO, priv->press_dur);
priv->rel_vol = priv->dds.data[i++];
ErrorF("%sBeep Release Volume: %d\n", CI_INFO, priv->rel_vol);
tmp = priv->dds.data[i++];
tmp += priv->dds.data[i++] << 8;
priv->rel_pitch = tmp;
ErrorF("%sBeep Release Pitch: %d\n", CI_INFO, priv->rel_pitch);
priv->rel_dur = priv->dds.data[i++];
ErrorF("%sBeep Release Duration: %d\n", CI_INFO, priv->rel_dur);
break;
case D_DEBUG:
debug_level = priv->dds.data[i++];
ErrorF("%sDebug level set to %d \n", CI_INFO, debug_level);
break;
case D_ENTERCOUNT:
priv->enter_count_no_Z = priv->dds.data[i++];
cit_SetEnterCount(priv);
ErrorF("%sEnterCount set to %d \n", CI_INFO, priv->enter_count_no_Z);
break;
case D_ZENTERCOUNT:
priv->enter_count_Z = priv->dds.data[i++];
cit_SetEnterCount(priv);
ErrorF("%sZEnterCount set to %d \n", CI_INFO, priv->enter_count_Z);
break;
case D_PWMADJ:
priv->pwm_src = priv->dds.data[i++];
priv->pwm_dst = priv->dds.data[i++];
cit_SendPWM(priv);
ErrorF("%spwm_src=%d, pwm_dst=%d \n", CI_INFO, priv->pwm_src, priv->pwm_dst);
break;
default:
ErrorF("%sNot known command: %d [0x%02x] - Get a recent driver\n", CI_WARNING, priv->dds.data[1], priv->dds.data[1]);
break;
}
}
static void
xf86CitronPrint (int nr, LedCtrl *ctrl)
{
DBG(8, ErrorF("%s------------------------------------------\n", CI_INFO));
DBG(8, ErrorF("%sxf86CitronFeedback%d(dev, ctrl)\n", CI_INFO, nr));
DBG(8, ErrorF("%s ctrl->led_values.......:%ld [0x%08lX]\n", CI_INFO,
ctrl->led_values, ctrl->led_values));
DBG(8, ErrorF("%s ctrl->led_mask.........:%ld [0x%08lX]\n", CI_INFO,
(unsigned long)ctrl->led_mask, (unsigned long)ctrl->led_mask));
DBG(8, ErrorF("%s ctrl->id...............:%d\n", CI_INFO, ctrl->id));
}
static void
xf86CitronFeedback0 (DeviceIntPtr dev, LedCtrl *ctrl)
{
LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
cit_PrivatePtr priv = (cit_PrivatePtr)(local->private);
COMMAND *cmd;
DBG(DDS, ErrorF("%sEntering xf86CitronFeedback0()...\n",CI_INFO));
cmd = (COMMAND *)&ctrl->led_values;
DBG(DDS, ErrorF("%scmd->packet = %d\n", CI_INFO, cmd->packet));
if(cmd->packet == 0)
{
if(cmd->par[0] == 0)
return;
priv->dds.curbyte = 2;
priv->dds.numbytes = cmd->par[0];
priv->dds.data[0] = cmd->par[1];
priv->dds.data[1] = cmd->par[2];
priv->dds.packet = 1;
}
else
{
if(priv->dds.packet == cmd->packet)
{
priv->dds.data[priv->dds.packet*3-1] = cmd->par[0];
priv->dds.data[priv->dds.packet*3] = cmd->par[1];
priv->dds.data[priv->dds.packet*3+1] = cmd->par[2];
priv->dds.packet++;
priv->dds.curbyte += 3;
}
else
DBG(DDS, ErrorF("%sPacket error: should be %d is %d\n", CI_WARNING, priv->dds.packet, cmd->packet));
}
DBG(DDS, ErrorF("%snumbytes = %d curbyte=%d\n", CI_INFO, priv->dds.numbytes, priv->dds.curbyte));
if(priv->dds.curbyte >= priv->dds.numbytes)
{
if(priv->dds.data[0] == DRIVCOMM)
cit_DriverComm(dev);
else
{
cit_ParseCommand(dev);
cit_SendtoTouch(dev);
}
}
DBG(DDS, ErrorF("%s 1 led_values = %08lx\n", CI_INFO, ctrl->led_values));
ctrl->led_values = (unsigned long)GetTimeInMillis();
DBG(DDS, ErrorF("%s 2 led_values = %08lx\n", CI_INFO, ctrl->led_values));
}
static void
xf86CitronFeedback1 (DeviceIntPtr dev, LedCtrl *ctrl)
{
static int test = 0;
xf86CitronPrint (1, ctrl);
ctrl->led_values = 0x8765432;
ctrl->led_mask = test++;
}
static void
xf86CitronFeedback2 (DeviceIntPtr dev, LedCtrl *ctrl)
{
xf86CitronPrint (2, ctrl);
ctrl->led_values = (unsigned long)GetTimeInMillis();
ctrl->led_mask = (unsigned long)GetTimeInMillis()&0xff;
}
#if(PK)
static void hexdump (void *ioaddr, int len)
{
int i;
unsigned long *ptr = (unsigned long *)ioaddr;
ErrorF(" ADDR 0-3 4-7 8-B C-F\n");
ErrorF("---------+-----+----+----+----+----+----+----+----\n");
while (len > 0)
{
ErrorF ("%08X: ", (unsigned long)ptr);
for (i=0;i < ( (len>4)?4:len);i++)
ErrorF (" %08x", *ptr++);
ErrorF ("\n");
len -= 8;
}
ErrorF("---------+-----+----+----+----+----+----+----+----\n");
}
#endif
static void
cit_StartTimer(cit_PrivatePtr priv, int nr)
{
priv->timer_ptr[nr] = TimerSet(priv->timer_ptr[nr], 0, priv->timer_val1[nr],
priv->timer_callback[nr], (pointer)priv);
DBG(5, ErrorF ("%scit_StartTimer[%d] called PTR=%p\n", CI_INFO, nr, (void *)priv->timer_ptr));
}
static void
cit_CloseTimer(cit_PrivatePtr priv, int nr)
{
DBG(5, ErrorF ("%scit_CloseTimer[%d] called PTR=%p\n", CI_INFO, nr, (void *)priv->timer_ptr));
if(priv->timer_ptr[nr])
{
TimerFree(priv->timer_ptr[nr]);
priv->timer_ptr[nr] = NULL;
}
else
DBG(5, ErrorF ("%scit_CloseTimer[%d]: Nothing to close\n", CI_WARNING, nr));
}
static CARD32
cit_SuperVisionTimer(OsTimerPtr timer, CARD32 now, pointer arg)
{
cit_PrivatePtr priv = (cit_PrivatePtr) arg;
int sigstate;
DBG(5, ErrorF ("%scit_SuperVisionTimer called %ld\n", CI_INFO,
(unsigned long)GetTimeInMillis()));
sigstate = xf86BlockSIGIO ();
cit_ReinitSerial(priv);
xf86UnblockSIGIO (sigstate);
return (0);
}
#ifdef CIT_TIM
static CARD32
cit_DualTouchTimer(OsTimerPtr timer, CARD32 now, pointer arg)
{
cit_PrivatePtr priv = (cit_PrivatePtr) arg;
int sigstate;
DBG(5, ErrorF ("%scit_DualTouchTimer called %d\n", CI_INFO, GetTimeInMillis()));
priv->packet[0] = R_EXIT;
priv->packet[1] = LOBYTE(priv->raw_x);
priv->packet[2] = HIBYTE(priv->raw_x);
priv->packet[3] = LOBYTE(priv->raw_y);
priv->packet[4] = HIBYTE(priv->raw_y);
priv->packeti = 5;
priv->fake_exit = TRUE;
sigstate = xf86BlockSIGIO ();
priv->local->read_input(priv->local);
xf86UnblockSIGIO (sigstate);
DBG(3, ErrorF ("%scit_DualTouchTimer: Faking Exit Message Sent\n", CI_INFO));
return (0);
}
#endif
static InputInfoPtr
CitronPreInit (InputDriverPtr drv, IDevPtr dev, int flags)
{
LocalDevicePtr local = xf86AllocateInput(drv, 0);
cit_PrivatePtr priv = (cit_PrivatePtr) xcalloc (1, sizeof (cit_PrivateRec));
char *s;
#if(INITT)
int errmaj, errmin;
#endif
ErrorF ("%sCitronPreInit called - xcalloc=%d\n", CI_INFO,
(int)sizeof(cit_PrivateRec));
if ((!local) || (!priv))
{
ErrorF("%s\t- unable to allocate structures!\n", CI_ERROR);
goto SetupProc_fail;
}
priv->local = local;
local->name = xf86SetStrOption(local->options, "DeviceName", "CiTouch");
ErrorF("%sDevice name: %s\n", CI_INFO, local->name);
local->type_name = XI_TOUCHSCREEN;
local->device_control = DeviceControl;
local->read_input = ReadInput;
local->control_proc = ControlProc;
local->close_proc = CloseProc;
local->switch_mode = SwitchMode;
local->conversion_proc = ConvertProc;
local->dev = NULL;
local->private = priv;
local->private_flags = 0;
local->history_size = xf86SetIntOption(local->options, "HistorySize", 0);
local->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
local->conf_idev = dev;
xf86CollectInputOptions(local, default_options, NULL);
debug_level = xf86SetIntOption(local->options, "DebugLevel", 0);
if(debug_level)
{
#ifdef DEBUG
ErrorF("%sDebug level set to %d\n", CI_CONFIG, debug_level);
#else
ErrorF("%sDebug not available\n", CI_INFO);
#endif
}
#if(INITT)
DBG(5, ErrorF ("%sOpenSerial will be called\n", CI_INFO));
local->fd = xf86OpenSerial (local->options);
if (local->fd == -1)
{
ErrorF ("%s\t- unable to open device %s\n", CI_ERROR, xf86FindOptionValue (local->options, "Device"));
goto SetupProc_fail;
}
DBG(6, ErrorF("%s\t+ %s opened successfully.\n", CI_INFO, xf86FindOptionValue (local->options, "Device")));
#endif
priv->screen_num = xf86SetIntOption(local->options, "ScreenNumber", 0);
ErrorF("%sAssociated screen: %d\n", CI_CONFIG, priv->screen_num);
priv->min_x = xf86SetIntOption(local->options, "MinX", CIT_DEF_MIN_X);
ErrorF("%sMinimum x position: %d\n", CI_CONFIG, priv->min_x);
priv->max_x = xf86SetIntOption(local->options, "MaxX", CIT_DEF_MAX_X);
ErrorF("%sMaximum x position: %d\n", CI_CONFIG, priv->max_x);
priv->min_y = xf86SetIntOption(local->options, "MinY", CIT_DEF_MIN_Y);
ErrorF("%sMinimum y position: %d\n", CI_CONFIG, priv->min_y);
priv->max_y = xf86SetIntOption(local->options, "MaxY", CIT_DEF_MAX_Y);
ErrorF("%sMaximum y position: %d\n", CI_CONFIG, priv->max_y);
priv->button_number = xf86SetIntOption(local->options, "ButtonNumber", 1);
ErrorF("%sButton Number: %d\n", CI_CONFIG, priv->button_number);
priv->button_threshold = xf86SetIntOption(local->options, "ButtonThreshold", 10);
ErrorF("%sButton Threshold: %d\n", CI_CONFIG, priv->button_threshold);
priv->sleep_mode = xf86SetIntOption(local->options, "SleepMode", 0);
ErrorF("%sSleep Mode: %d\n", CI_CONFIG, priv->sleep_mode);
priv->sleep_time_act = xf86SetIntOption(local->options, "SleepTime", 65535);
ErrorF("%sSleep Time: %d\n", CI_CONFIG, priv->sleep_time_act);
priv->sleep_time_scan = xf86SetIntOption(local->options, "SleepScan", 65535);
ErrorF("%sSleep Scan: %d\n", CI_CONFIG, priv->sleep_time_scan);
priv->pwm_src = xf86SetIntOption(local->options, "PWMAdjSrc", -1);
ErrorF("%sPWMAdjSrc: %d\n", CI_CONFIG, priv->pwm_src);
priv->pwm_dst = xf86SetIntOption(local->options, "PWMAdjDst", -1);
ErrorF("%sPWMAdjDst: %d\n", CI_CONFIG, priv->pwm_dst);
priv->pwm_active = xf86SetIntOption(local->options, "PWMActive", 255);
ErrorF("%sPWM Active: %d\n", CI_CONFIG, priv->pwm_active);
priv->pwm_sleep = xf86SetIntOption(local->options, "PWMSleep", 255);
ErrorF("%sPWM Sleep: %d\n", CI_CONFIG, priv->pwm_sleep);
priv->click_mode = xf86SetIntOption(local->options, "ClickMode", NO_CLICK_MODE);
ErrorF("%sClick Mode: %d\n", CI_CONFIG, priv->click_mode);
priv->origin = xf86SetIntOption(local->options, "Origin", 0);
ErrorF("%sOrigin: %d\n", CI_CONFIG, priv->origin);
priv->doze_mode = xf86SetIntOption(local->options, "DozeMode", 0);
ErrorF("%sDoze Mode: %d\n", CI_CONFIG, priv->doze_mode);
priv->doze_time_act = xf86SetIntOption(local->options, "DozeTime", 10);
ErrorF("%sDoze Time: %d\n", CI_CONFIG, priv->doze_time_act);
priv->doze_time_scan = xf86SetIntOption(local->options, "DozeScan", 25);
ErrorF("%sDoze Scan: %d\n", CI_CONFIG, priv->doze_time_scan);
priv->delta_x = xf86SetIntOption(local->options, "DeltaX", 0) & 0xff;
ErrorF("%sDelta X: %d\n", CI_CONFIG, priv->delta_x);
priv->delta_y = xf86SetIntOption(local->options, "DeltaY", 0) & 0xff;
ErrorF("%sDelta Y: %d\n", CI_CONFIG, priv->delta_y);
priv->beep = xf86SetIntOption(local->options, "Beep", 0);
ErrorF("%sBeep: %s\n", CI_CONFIG, (priv->beep > 0) ? "activated":"not activated");
priv->press_vol = xf86SetIntOption(local->options, "PressVol", 100);
ErrorF("%sBeep Pressure Volume: %d\n", CI_CONFIG, priv->press_vol);
priv->press_pitch = xf86SetIntOption(local->options, "PressPitch", 880);
ErrorF("%sBeep Pressure Pitch: %d\n", CI_CONFIG, priv->press_pitch);
priv->press_dur = xf86SetIntOption(local->options, "PressDur", 15) & 0xff;
ErrorF("%sBeep Pressure Duration: %d\n", CI_CONFIG, priv->press_dur);
priv->rel_vol = xf86SetIntOption(local->options, "ReleaseVol", 100);
ErrorF("%sBeep Release Volume: %d\n", CI_CONFIG, priv->rel_vol);
priv->rel_pitch = xf86SetIntOption(local->options, "ReleasePitch", 1200);
ErrorF("%sBeep Release Pitch: %d\n", CI_CONFIG, priv->rel_pitch);
priv->rel_dur = xf86SetIntOption(local->options, "ReleaseDur", 10) & 0xff;
ErrorF("%sBeep Release Duration: %d\n", CI_CONFIG, priv->rel_dur);
priv->beam_timeout = xf86SetIntOption(local->options, "BeamTimeout", 30) & 0xffff;
ErrorF("%sBeam Timeout: %d\n", CI_CONFIG, priv->beam_timeout);
priv->touch_time = xf86SetIntOption(local->options, "TouchTime", 0) & 0xff;
ErrorF("%sTouch Time: %d\n", CI_CONFIG, priv->touch_time);
priv->max_dual_count = xf86SetIntOption(local->options, "DualCount", MAX_DUAL_TOUCH_COUNT);
ErrorF("%sDual Count: %d\n", CI_CONFIG, priv->max_dual_count);
priv->enter_count_no_Z = xf86SetIntOption(priv->local->options, "EnterCount", 3);
ErrorF("%sEnterCount: %d\n", CI_CONFIG, priv->enter_count_no_Z);
priv->enter_count_Z = xf86SetIntOption(priv->local->options, "ZEnterCount", 2);
ErrorF("%sZEnterCount: %d\n", CI_CONFIG, priv->enter_count_Z);
priv->pwm_freq = xf86SetIntOption(priv->local->options, "PWMFreq", -1);
ErrorF("%sPWMFreq: %d\n", CI_CONFIG, priv->pwm_freq);
priv->lockz_enter_time = xf86SetIntOption(priv->local->options, "LockZEnterTime", 1);
ErrorF("%sLockZEnterTime: %d\n", CI_CONFIG, priv->lockz_enter_time);
priv->lockz_exit_time = xf86SetIntOption(priv->local->options, "LockZExitTime", 1);
ErrorF("%sLockZExitTime: %d\n", CI_CONFIG, priv->lockz_exit_time);
priv->lockz_lock_time = xf86SetIntOption(priv->local->options, "LockZLockTime", 10);
ErrorF("%sLockLockTime: %d\n", CI_CONFIG, priv->lockz_lock_time);
cit_SetEnterCount(priv);
priv->raw_min_x = CIT_DEF_MAX_X;
priv->raw_max_x = 0;
priv->raw_min_y = CIT_DEF_MAX_Y;
priv->raw_max_y = 0;
#ifdef CIT_TIM
priv->timer_ptr[FAKE_TIMER] = NULL;
priv->timer_val1[FAKE_TIMER] = 0;
priv->timer_val2[FAKE_TIMER] = 0;
priv->timer_callback[FAKE_TIMER] = NULL;
#endif
priv->timer_ptr[SV_TIMER] = NULL;
priv->timer_val1[SV_TIMER] = 0;
priv->timer_val2[SV_TIMER] = 0;
priv->timer_callback[SV_TIMER] = NULL;
priv->fake_exit = FALSE;
priv->enter_touched = 0;
DBG(6, ErrorF("%s\t+ options read\n", CI_INFO));
s = xf86FindOptionValue (local->options, "ReportingMode");
if ((s) && (xf86NameCmp (s, "raw") == 0))
priv->reporting_mode = TS_Raw;
else
priv->reporting_mode = TS_Scaled;
#if(INITT)
priv->buffer = XisbNew (local->fd, CIT_BUFFER_SIZE);
#endif
priv->proximity = FALSE;
priv->button_down = FALSE;
priv->dual_touch_count = 0;
priv->dual_flg = 0;
priv->state = 0;
priv->lex_mode = cit_idle;
priv->last_x = 0;
priv->last_y = 0;
priv->query_state = 0;
#if(INITT)
DBG (8, XisbTrace (priv->buffer, 1));
if (QueryHardware (local, &errmaj, &errmin) != Success)
{
ErrorF ("%s\t- Unable to query/initialize Citron hardware.\n", CI_INFO);
goto SetupProc_fail;
}
#endif
xf86ProcessCommonOptions(local, local->options);
local->flags |= XI86_CONFIGURED;
#if(PK)
if (xf86FindOption (local->options, "DemandLoaded"))
{
DBG (5, ErrorF ("%s\tCitron module was demand loaded\n", CI_INFO));
xf86AddLocalDevice (local, TRUE);
}
else
xf86AddLocalDevice (local, FALSE);
#endif
if (local->fd >= 0)
{
RemoveEnabledDevice (local->fd);
#if(INITT)
if (priv->buffer)
{
XisbFree(priv->buffer);
priv->buffer = NULL;
}
xf86CloseSerial(local->fd);
local->fd = 0;
#endif
}
DBG(5, ErrorF ("%sCitronPreInit success\n", CI_INFO));
return (local);
SetupProc_fail:
#if(INITT)
if ((local) && (local->fd))
{
xf86CloseSerial (local->fd);
local->fd = 0;
}
#endif
if ((local) && (local->name))
xfree (local->name);
if (local)
xfree (local);
#if(INITT)
if ((priv) && (priv->buffer))
XisbFree (priv->buffer);
#endif
if (priv)
xfree (priv);
ErrorF ("%sCitronPreInit returning NULL\n", CI_ERROR);
return (NULL);
}
static Bool
DeviceControl (DeviceIntPtr dev, int mode)
{
Bool RetVal;
DBG(5, ErrorF ("%sDeviceControl called; mode = %d\n", CI_INFO, mode));
switch (mode)
{
case DEVICE_INIT:
DBG(6, ErrorF ("%s\tINIT\n", CI_INFO));
DeviceInit (dev);
RetVal = Success;
break;
case DEVICE_ON:
DBG(6, ErrorF ("%s\tON\n", CI_INFO));
RetVal = DeviceOn (dev);
break;
case DEVICE_OFF:
DBG(6, ErrorF ("%s\tOFF\n", CI_INFO));
RetVal = DeviceOff (dev);
break;
case DEVICE_CLOSE:
DBG(6, ErrorF ("%s\tCLOSE\n", CI_INFO));
RetVal = DeviceClose (dev);
break;
default:
ErrorF ("%sDeviceControl Mode (%d) not found\n", CI_ERROR, mode);
RetVal = BadValue;
}
DBG(2, ErrorF ("%sDeviceControl: RetVal = %d\n", CI_INFO, RetVal));
return(RetVal);
}
static Bool
DeviceOn (DeviceIntPtr dev)
{
LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
cit_PrivatePtr priv = (cit_PrivatePtr) (local->private);
int errmaj, errmin;
DBG(5, ErrorF ("%sDeviceOn called\n", CI_INFO));
local->fd = xf86OpenSerial(local->options);
if (local->fd == -1)
{
DBG(5, ErrorF("%s%s: cannot open input device\n", CI_ERROR, local->name));
goto DeviceOn_fail;
}
priv->buffer = XisbNew (local->fd, CIT_BUFFER_SIZE);
if (!priv->buffer)
goto DeviceOn_fail;
xf86FlushInput(local->fd);
cit_SendCommand(priv->buffer, C_SOFTRESET, 0);
if (QueryHardware (local, &errmaj, &errmin) != Success)
{
ErrorF ("%s\t- DeviceOn: Unable to query/initialize hardware.\n", CI_ERROR);
goto DeviceOn_fail;
}
AddEnabledDevice(local->fd);
dev->public.on = TRUE;
DBG(5, ErrorF ("%sDeviceOn Success\n", CI_INFO));
return (Success);
DeviceOn_fail:
if ((local) && (local->fd))
{
xf86CloseSerial (local->fd);
local->fd = 0;
}
if ((local) && (local->name))
xfree (local->name);
if (local)
{
xfree (local);
local = NULL;
}
if ((priv) && (priv->buffer))
XisbFree (priv->buffer);
if (priv)
{
xfree (priv);
priv = NULL;
}
ErrorF ("%sDeviceOn failed\n", CI_ERROR);
return (!Success);
}
static Bool
DeviceOff (DeviceIntPtr dev)
{
DBG(5, ErrorF ("%sDeviceOff called\n", CI_INFO));
return DeviceClose(dev);
}
static Bool
DeviceClose (DeviceIntPtr dev)
{
LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
cit_PrivatePtr priv = (cit_PrivatePtr) (local->private);
int c;
DBG(5, ErrorF ("%sDeviceClose called\n",CI_INFO));
cit_Flush(priv);
cit_SendCommand(priv->buffer, C_SOFTRESET, 0);
#ifdef CIT_TIM
cit_CloseTimer(priv, FAKE_TIMER);
#endif
cit_CloseTimer(priv, SV_TIMER);
XisbTrace(priv->buffer, 1);
cit_SetBlockDuration (priv, 500000);
c = XisbRead (priv->buffer);
if(c == CTS_NAK)
{
DBG(6, ErrorF ("%sTouch Reset executed\n",CI_INFO));
}
else
{
DBG(6, ErrorF ("%sTouch Reset not executed\n",CI_ERROR));
}
if (local->fd >= 0)
{
RemoveEnabledDevice (local->fd);
if (priv->buffer)
{
XisbFree(priv->buffer);
priv->buffer = NULL;
}
xf86CloseSerial(local->fd);
local->fd = 0;
}
dev->public.on = FALSE;
ErrorF("%sx-range = [%d..%d]\n", CI_INFO, priv->raw_min_x, priv->raw_max_x);
ErrorF("%sy-range = [%d..%d]\n", CI_INFO, priv->raw_min_y, priv->raw_max_y);
return (Success);
}
static Bool
DeviceInit (DeviceIntPtr dev)
{
LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
cit_PrivatePtr priv = (cit_PrivatePtr) (local->private);
unsigned char map[] =
{0, 1};
DBG (5, ErrorF("%sDeviceInit called\n", CI_INFO));
priv->screen_width = screenInfo.screens[priv->screen_num]->width;
priv->screen_height = screenInfo.screens[priv->screen_num]->height;
DBG (5, ErrorF("%sScreen Number: %d Screen Width: %d Screen Height: %d\n", CI_INFO,
priv->screen_num, priv->screen_width, priv->screen_height));
if (InitButtonClassDeviceStruct (dev, 1, map) == FALSE)
{
ErrorF ("%sUnable to allocate Citron touchscreen ButtonClassDeviceStruct\n", CI_ERROR);
return !Success;
}
if (InitValuatorClassDeviceStruct (dev, 2, xf86GetMotionEvents,
local->history_size, Absolute) == FALSE)
{
ErrorF ("%sUnable to allocate Citron touchscreen ValuatorClassDeviceStruct\n", CI_ERROR);
return !Success;
}
else
{
InitValuatorAxisStruct (dev, 0, priv->min_x, priv->max_x,
CIT_DEF_MAX_X,
CIT_DEF_MIN_X ,
CIT_DEF_MAX_X );
InitValuatorAxisStruct (dev, 1, priv->min_y, priv->max_y,
CIT_DEF_MAX_Y,
CIT_DEF_MIN_Y ,
CIT_DEF_MAX_Y );
}
if (InitProximityClassDeviceStruct (dev) == FALSE)
{
ErrorF ("%sUnable to allocate Citron touchscreen ProximityClassDeviceStruct\n", CI_ERROR);
return !Success;
}
if (InitLedFeedbackClassDeviceStruct(dev, xf86CitronFeedback0) == FALSE)
{
ErrorF("Unable to allocate CITRON touchscreen LedFeedbackClassDeviceStruct, id=0\n");
return !Success;
}
if (InitLedFeedbackClassDeviceStruct(dev, xf86CitronFeedback1) == FALSE)
{
ErrorF("Unable to allocate CITRON touchscreen LedFeedbackClassDeviceStruct, id=1\n");
return !Success;
}
if (InitLedFeedbackClassDeviceStruct(dev, xf86CitronFeedback2) == FALSE)
{
ErrorF("Unable to allocate CITRON touchscreen LedFeedbackClassDeviceStruct, id=2\n");
return !Success;
}
xf86MotionHistoryAllocate (local);
return (Success);
}
static void
ReadInput (LocalDevicePtr local)
{
int x, y;
cit_PrivatePtr priv = (cit_PrivatePtr) (local->private);
DBG(RI, ErrorF("%sReadInput called\n", CI_INFO));
if(!priv->fake_exit)
{
cit_SetBlockDuration (priv, -1);
}
while (
#ifdef CIT_TIM
priv->fake_exit ||
#endif
(cit_GetPacket (priv) == Success))
{
cit_ProcessPacket(priv);
if (priv->reporting_mode == TS_Scaled)
{
x = xf86ScaleAxis (priv->raw_x, 0, priv->screen_width, priv->min_x,
priv->max_x);
y = xf86ScaleAxis (priv->raw_y, 0, priv->screen_height, priv->min_y,
priv->max_y);
DBG(RI, ErrorF("%s\tscaled coordinates: (%d, %d)\n", CI_INFO, x, y));
}
else
{
x = priv->raw_x;
y = priv->raw_y;
}
xf86XInputSetScreen (local, priv->screen_num, x, y);
if ((priv->proximity == FALSE) && (priv->state & CIT_TOUCHED))
{
priv->proximity = TRUE;
xf86PostProximityEvent (local->dev, 1, 0, 2, x, y);
DBG(RI, ErrorF("%s\tproximity(TRUE, x=%d, y=%d)\n", CI_INFO, x, y));
}
if ( ((x >= (priv->last_x + priv->delta_x)) ||
(x <= (priv->last_x - priv->delta_x)) ||
(y >= (priv->last_y + priv->delta_y)) ||
(y <= (priv->last_y - priv->delta_y))) ||
( ((x < priv->delta_x) ||
(x > (priv->screen_width - priv->delta_x))) ||
((y < priv->delta_x) ||
(y > (priv->screen_height - priv->delta_y)))) )
{
xf86PostMotionEvent (local->dev, TRUE, 0, 2, x, y);
DBG(RI, ErrorF("%s\tPostMotionEvent(x=%d, y=%d, last_x=%d, last_y=%d)\n", CI_INFO,
x, y, priv->last_x, priv->last_y));
priv->last_x = x;
priv->last_y = y;
}
if ((priv->button_down == FALSE) && (priv->state & CIT_BUTTON))
{
if(priv->enter_touched < priv->enter_count)
priv->enter_touched++;
if(priv->enter_touched == priv->enter_count)
{
priv->enter_touched++;
xf86PostButtonEvent (local->dev, TRUE,
priv->button_number, 1, 0, 2, x, y);
cit_Beep(priv, 1);
DBG(RI, ErrorF("%s\tPostButtonEvent(DOWN, x=%d, y=%d)\n", CI_INFO, x, y));
priv->button_down = TRUE;
}
}
if ((priv->button_down == TRUE) && !(priv->state & CIT_BUTTON))
{
xf86PostButtonEvent (local->dev, TRUE,
priv->button_number, 0, 0, 2, x, y);
cit_Beep(priv, 0);
DBG(RI, ErrorF("%s\tPostButtonEvent(UP, x=%d, y=%d)\n", CI_INFO, x, y));
priv->button_down = FALSE;
}
if ((priv->proximity == TRUE) && !(priv->state & CIT_TOUCHED))
{
priv->proximity = FALSE;
xf86PostProximityEvent (local->dev, 0, 0, 2, x, y);
DBG(RI, ErrorF("%s\tproximity(FALSE, x=%d, y=%d)\n", CI_INFO, x, y));
}
DBG (RI, ErrorF ("%sTouchScreen: x(%d), y(%d), %s\n",
CI_INFO, x, y,
(priv->state == CIT_TOUCHED) ? "Touched" : "Released"));
#ifdef CIT_TIM
if(priv->fake_exit)
{
priv->fake_exit = FALSE;
return;
}
#endif
}
DBG(RI, ErrorF("%sExit ReadInput\n", CI_INFO));
}
static int
ControlProc (LocalDevicePtr local, xDeviceCtl * control)
{
xDeviceTSCalibrationCtl *c = (xDeviceTSCalibrationCtl *) control;
cit_PrivatePtr priv = (cit_PrivatePtr) (local->private);
DBG(5, ErrorF("%sControlProc called\n", CI_INFO));
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 (LocalDevicePtr local)
{
DBG(5, ErrorF("%sCloseProc called\n", CI_INFO));
}
static int
SwitchMode (ClientPtr client, DeviceIntPtr dev, int mode)
{
LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
cit_PrivatePtr priv = (cit_PrivatePtr) (local->private);
DBG(5, ErrorF("%sSwitchMode called; mode = %d\n", CI_INFO, mode));
if ((mode == TS_Raw) || (mode == TS_Scaled))
{
priv->reporting_mode = mode;
DBG(6, ErrorF("%s\treporting mode = %s\n", CI_INFO, mode==TS_Raw?"raw":"scaled"));
return (Success);
}
else if ((mode == SendCoreEvents) || (mode == DontSendCoreEvents))
{
xf86XInputSetSendCoreEvents (local, (mode == SendCoreEvents));
DBG(6, ErrorF("%s\tmode = %sSend Core Events\n", CI_INFO, mode==DontSendCoreEvents?"Don\'t ":""));
return (Success);
}
#ifdef CIT_MODE_EXT
else if (mode == ClickMode_Enter)
{
priv->click_mode = CM_ENTER;
DBG(6, ErrorF("%s\tset click mode to ENTER\n", CI_INFO));
return (Success);
}
else if (mode == ClickMode_Dual)
{
priv->click_mode = CM_DUAL;
DBG(6, ErrorF("%s\tset click mode to DUAL TOUCH\n", CI_INFO));
return (Success);
}
else if (mode == ClickMode_ZPress)
{
priv->click_mode = CM_ZPRESS;
DBG(6, ErrorF("%s\tset click mode to Z-Press\n", CI_INFO));
return (Success);
}
#endif
else
{
ErrorF("%sUnknown mode for Citron Touchscreen Switchmode Function: 0x%02x!\n", CI_ERROR, mode);
return (!Success);
}
}
static Bool
ConvertProc (LocalDevicePtr local,
int first,
int num,
int v0,
int v1,
int v2,
int v3,
int v4,
int v5,
int *x,
int *y)
{
cit_PrivatePtr priv = (cit_PrivatePtr) (local->private);
DBG(5, ErrorF("%sConvertProc called(first=%d, num=%d, v0=%d, v1=%d, v2=%d, v3=%d\n",
CI_INFO, first, num, v0, v1, v2, v3));
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;
}
DBG(6, ErrorF("%s\t+ x=%d, y=%d\n",CI_INFO, *x, *y));
return (TRUE);
}
static Bool
QueryHardware (LocalDevicePtr local, int *errmaj, int *errmin)
{
cit_PrivatePtr priv = (cit_PrivatePtr) (local->private);
unsigned char x;
int i, cnt;
int err;
char UsrStr[CTS_USERSTRING_LEN+1];
DBG(5, ErrorF("%sQueryHardware called\n", CI_INFO));
cit_Flush(priv);
cit_Flush(priv);
DBG(6, ErrorF("%s\t* waiting for BREAKS...\n", CI_INFO));
cit_SetBlockDuration (priv, 1);
for (i=0, cnt=0; (i<20) && (cnt<3); i++)
{
cit_Flush(priv);
WAIT(150);
DBG(7, ErrorF("%s\t (loop %d)\n", CI_INFO, i));
if (XisbRead(priv->buffer) == 0)
{
cnt++;
DBG(6, ErrorF("%s\t+ BREAK %d detected\n", CI_INFO, cnt));
}
else
{
cnt = 0;
}
if ( i == 12)
{
cit_SendCommand(priv->buffer, C_SOFTRESET, 0);
DBG(6, ErrorF("%s\t+ SOFTRESET sent\n", CI_INFO));
}
#if(0)
if(i == 15)
{
XisbWrite(priv->buffer, (unsigned char *)"r2", 2);
x = 0x0d;
XisbWrite(priv->buffer, &x, 1);
DBG(6, ErrorF("%s\t+ DEBUG-MODE SOFTRESET sent\n", CI_INFO));
}
#endif
}
if (cnt < 2)
{
ErrorF("%sCannot reset Citron Infrared Touch!\n", CI_ERROR);
cit_ReinitSerial(priv);
return (!Success);
}
DBG(6, ErrorF("%s\t* initializing to CTS mode\n", CI_INFO));
x = 0x0d;
for (i=0; i<2; i++)
{
XisbWrite(priv->buffer, &x, 1);
WAIT(50);
}
x = MODE_D;
XisbWrite(priv->buffer, &x, 1);
DBG(6, ErrorF("%s\t* waiting for acknowledge\n", CI_INFO));
cit_SetBlockDuration (priv, 500000);
cnt = 0;
while ((i=XisbRead(priv->buffer)) != -1)
{
DBG(7, ErrorF("%s\t* 0x%02X received - waiting for CTS_XON\n",CI_INFO, i));
if ((unsigned char)i == CTS_XON)
break;
if(cnt++ > 50) return (Success);
}
if ((unsigned char)i != CTS_XON)
{
ErrorF("%sNo acknowledge from Citron Infrared Touch!\n", CI_ERROR);
cit_ReinitSerial(priv);
return (!Success);
}
DBG(6, ErrorF("%s\t+ Touch connected!\n",CI_INFO));
cit_Flush(priv);
DBG(6, ErrorF("%s\t+ requesting pressure sensors report\n",CI_INFO));
if (cit_GetPressureSensors(priv)!=Success)
{
ErrorF("%sNo pressure sensors report received from Citron Touchscreen!\n",CI_ERROR);
}
DBG(5, ErrorF("%s ClickMode is %d\n",CI_INFO, priv->click_mode));
if(priv->click_mode == NO_CLICK_MODE)
{
priv->click_mode = (priv->pressure_sensors > 0) ? CM_ZPRESS : CM_ENTER;
DBG(5, ErrorF("%sClickMode set to %d\n",CI_INFO, priv->click_mode));
cit_SetEnterCount(priv);
}
cit_SendCommand(priv->buffer, C_SETAREAFLAGS, 1, AOF_ADDEXIT
| AOF_ADDCOORD
| AOF_ACTIVE
| AOF_ADDPRESS);
cit_SendCommand(priv->buffer, C_SETAREAMODE, 1, AOM_CONT);
cit_SendCommand(priv->buffer, C_SETCONTTIME, 1, 20);
cit_SendCommand(priv->buffer, C_SETDUALTOUCHING, 1, DT_ERROR);
cit_SendCommand(priv->buffer, C_SETAREAPRESSURE, 1, LOBYTE(priv->button_threshold));
cit_SendCommand(priv->buffer, C_SETRESOLUTION, 4,
LOBYTE(CIT_DEF_MAX_X),
HIBYTE(CIT_DEF_MAX_X),
LOBYTE(CIT_DEF_MAX_Y),
HIBYTE(CIT_DEF_MAX_Y));
cit_SendCommand(priv->buffer, C_SETBEAMTIMEOUT, 2,
LOBYTE(priv->beam_timeout),
HIBYTE(priv->beam_timeout));
cit_SendCommand(priv->buffer, C_SETORIGIN, 1, LOBYTE(priv->origin));
cit_SendCommand(priv->buffer, C_SETTOUCHTIME, 1, LOBYTE(priv->touch_time));
cit_SendCommand(priv->buffer, C_SETSLEEPMODE, 5,
LOBYTE(priv->sleep_mode),
LOBYTE(priv->sleep_time_act),
HIBYTE(priv->sleep_time_act),
LOBYTE(priv->sleep_time_scan),
HIBYTE(priv->sleep_time_scan));
cit_SendCommand(priv->buffer, C_SETDOZEMODE, 5,
LOBYTE(priv->doze_mode),
LOBYTE(priv->doze_time_act),
HIBYTE(priv->doze_time_act),
LOBYTE(priv->doze_time_scan),
HIBYTE(priv->doze_time_scan));
cit_SendCommand(priv->buffer, C_SETTRANSMISSION, 1, TM_TRANSMIT);
cit_SendPWM(priv);
cit_SendPWMFreq(priv);
cit_SendLockZ(priv);
if(priv->query_state == 0)
{
priv->query_state++;
DBG(6, ErrorF("%s\t+ requesting initial errors report\n",CI_INFO));
if (cit_GetInitialErrors(priv)!=Success)
{
ErrorF("%sNo initial error report received from Citron Touchscreen!\n",CI_ERROR);
*errmaj = LDR_NOHARDWARE;
return (!Success);
}
DBG(6, ErrorF("\t+ requesting defective beams report\n"));
if (cit_GetDefectiveBeams(priv)!=Success)
{
ErrorF("%sNo defective beams report received from Citron Touchscreen!\n",CI_ERROR);
*errmaj = LDR_NOHARDWARE;
return (!Success);
}
DBG(6, ErrorF("\t+ requesting touch revisions\n"));
if (cit_GetDesignator(priv)!=Success)
{
ErrorF("%sNo designator received from Citron Touchscreen!\n",CI_ERROR);
*errmaj = LDR_NOHARDWARE;
return (!Success);
}
if (cit_GetRevision(priv, GR_SYSMGR)!=Success)
{
ErrorF("%sNo system manager module revision received from Citron Touchscreen!\n",CI_ERROR);
*errmaj = LDR_NOHARDWARE;
return (!Success);
}
if (cit_GetRevision(priv, GR_HARDWARE)!=Success)
{
ErrorF("%sNo hardware module revision received from Citron Touchscreen!\n",CI_ERROR);
*errmaj = LDR_NOHARDWARE;
return (!Success);
}
if (cit_GetRevision(priv, GR_PROCESS)!=Success)
{
ErrorF("%sNo process module revision received from Citron Touchscreen!\n",CI_ERROR);
*errmaj = LDR_NOHARDWARE;
return (!Success);
}
if (cit_GetRevision(priv, GR_PROTOCOL)!=Success)
{
ErrorF("%sNo protocol module revision received from Citron Touchscreen!\n",CI_ERROR);
*errmaj = LDR_NOHARDWARE;
return (!Success);
}
if (cit_GetRevision(priv, GR_HWPARAM)!=Success)
{
ErrorF("%sNo hardware parameter module revision received from Citron Touchscreen!\n",CI_ERROR);
*errmaj = LDR_NOHARDWARE;
return (!Success);
}
i=0;
while(UserStrNames[i] != NULL)
{
if (cit_GetUserString(priv, UserStrNames[i], UsrStr, FALSE) != Success)
{
ErrorF("%sNo UserString read from Touch.\n",CI_NOTICE);
break;
}
else
ErrorF("%sUserString: %s=%s\n",CI_INFO, UserStrNames[i], UsrStr);
i++;
}
}
cit_SendCommand(priv->buffer, C_SETSCANNING, 1, SC_ENABLE);
DBG(6, ErrorF("%s\t+ Touch initialized - %d\n",CI_INFO, priv->query_state));
return (Success);
}
static Bool
cit_GetPacket (cit_PrivatePtr priv)
{
int c;
int errmaj, errmin;
int loop = 0;
DBG(GP, ErrorF("%scit_GetPacket called\n", CI_INFO));
DBG(GP, ErrorF("%s\t* initial lex_mode =%d (%s)\n", CI_INFO, priv->lex_mode,
priv->lex_mode==cit_idle ?"idle":
priv->lex_mode==cit_getID ?"getID":
priv->lex_mode==cit_collect ?"collect":
priv->lex_mode==cit_escape ?"escape":
"???"));
while ((c = XisbRead (priv->buffer)) >= 0)
{
#if(0)
DBG(GP, ErrorF("%s c=%d\n",CI_INFO, c));
#endif
loop++;
if (c == CTS_STX)
{
DBG(GP, ErrorF("%s\t+ STX detected\n", CI_INFO));
if (priv->lex_mode != cit_idle)
DBG(7, ErrorF("%s\t- no ETX received before this STX!\n", CI_WARNING));
priv->lex_mode = cit_getID;
DBG(GP, ErrorF("%s\t+ new lex_mode == getID\n", CI_INFO));
priv->timer_val1[SV_TIMER] = 2000;
priv->timer_callback[SV_TIMER] = (OsTimerCallback)cit_SuperVisionTimer;
cit_StartTimer(priv, SV_TIMER);
}
else if (c == CTS_ETX)
{
DBG(GP, ErrorF("%s\t+ ETX detected\n", CI_INFO));
DBG(GP, ErrorF("%s\t+ new lex_mode == idle\n", CI_INFO));
if (priv->lex_mode == cit_collect)
{
DBG(GP, ErrorF("%s\t+ Good report received\n", CI_INFO));
priv->lex_mode = cit_idle;
cit_CloseTimer(priv, SV_TIMER);
return (Success);
}
DBG(GP, ErrorF("%s\t- unexpected ETX received!\n", CI_WARNING));
priv->lex_mode = cit_idle;
}
else if (c == CTS_ESC)
{
DBG(GP, ErrorF("%s\t+ escape detected\n", CI_INFO));
if (priv->lex_mode != cit_collect)
{
DBG(GP, ErrorF("%s\t- unexpected control character received\n", CI_WARNING));
}
else
{
priv->lex_mode = cit_escape;
DBG(GP, ErrorF("%s\t+ new lex_mode == escape\n", CI_INFO));
}
}
else if ((c < CTS_CTRLMIN) || (c > CTS_CTRLMAX))
{
if (priv->lex_mode == cit_getID)
{
priv->packeti = 0;
priv->packet[priv->packeti++] = (unsigned char)c;
priv->lex_mode = cit_collect;
DBG(GP, ErrorF("%s\t+ identifier captured, new lex_mode == collect\n", CI_INFO));
}
else if ((priv->lex_mode == cit_collect) || (priv->lex_mode == cit_escape))
{
if (priv->lex_mode == cit_escape)
{
c &= CTS_DECODE;
priv->lex_mode = cit_collect;
DBG(GP, ErrorF("%s\t+ decoded character = 0x%02X\n", CI_INFO, c));
DBG(GP, ErrorF("%s\t+ new lex_mode = collect\n", CI_INFO));
}
if (priv->packeti < CTS_PACKET_SIZE)
{
priv->packet[priv->packeti++] = (unsigned char)c;
}
else
{
DBG(GP, ErrorF("%s\t- command buffer overrun, loop[%d]\n", CI_ERROR, loop));
priv->lex_mode = cit_idle;
cit_ReinitSerial(priv);
}
}
else
{
DBG(GP, ErrorF("%s\t- unexpected non control received! [%d, 0x%02x, loop[%d]]\n", CI_WARNING, c, c, loop));
DBG(GP, ErrorF("%s\t- Device not connected - trying to reconnect ...\n", CI_WARNING));
if (QueryHardware (priv->local, &errmaj, &errmin) != Success)
ErrorF ("%s\t- Unable to query/initialize Citron Touch hardware.\n", CI_ERROR);
else
ErrorF ("%s\t- Citron Touch reconnected\n", CI_INFO);
return(!Success);
}
}
else if (c != CTS_XON && c != CTS_XOFF)
{
DBG(GP, ErrorF("%s\t- unhandled control character received! loop[%d]\n", CI_WARNING, loop));
}
}
DBG(GP, ErrorF("%scit_GetPacket exit !Success - loop[%d]\n", CI_INFO, loop));
return (!Success);
}
static void
cit_ReinitSerial(cit_PrivatePtr priv)
{
if(priv->local->fd)
{
xf86CloseSerial(priv->local->fd);
priv->local->fd = 0;
priv->local->fd = xf86OpenSerial (priv->local->options);
DBG(6, ErrorF("%s\t* cit_ReinitSerial: Serial connection reinitialized\n", CI_INFO));
}
else
DBG(6, ErrorF("%s\t* cit_ReinitSerial: Serial connection not opened\n", CI_ERROR));
}
static void
cit_Flush (cit_PrivatePtr priv)
{
int old_block_duration;
DBG(7, ErrorF("%scit_Flush called\n", CI_INFO));
old_block_duration = priv->buffer->block_duration;
XisbBlockDuration(priv->buffer, 1000);
while (XisbRead(priv->buffer) >= 0);
cit_SetBlockDuration(priv, old_block_duration);
}
static void
cit_SetBlockDuration (cit_PrivatePtr priv, int block_duration)
{
DBG(7, ErrorF("%scit_SetBlockDuration called [%d]\n", CI_INFO, block_duration));
XisbBlockDuration(priv->buffer, block_duration);
}
static void
cit_Beep(cit_PrivatePtr priv, int press)
{
#ifdef CIT_BEEP
if(priv->beep == 0)
return;
if(press == 0)
xf86SoundKbdBell(priv->rel_vol, priv->rel_pitch, priv->rel_dur);
else
xf86SoundKbdBell(priv->press_vol,priv->press_pitch, priv->press_dur);
DBG(7, ErrorF("%scit_Beep called - %s\n", CI_INFO, (press == 0) ? "release" : "press"));
#endif
}
static void
cit_SendCommand (XISBuffer *b, unsigned char cmd, int cnt, ...)
{
va_list ap;
unsigned char data, x;
va_start(ap, cnt);
DBG(7, ErrorF("%scit_SendCommand(cmd=0x%02X, cnt=%d, ...)\n", CI_INFO, cmd, cnt));
x = CTS_STX;
XisbWrite(b, &x, 1);
XisbWrite(b, &cmd, 1);
x = CTS_ESC;
while (cnt-- > 0)
{
data = va_arg(ap, int);
if (data >= CTS_CTRLMIN && data <= CTS_CTRLMAX)
{
data |= CTS_ENCODE;
XisbWrite(b, &x, 1);
}
XisbWrite(b, &data, 1);
}
x = CTS_ETX;
XisbWrite(b, &x, 1);
va_end(ap);
}
static int
cit_SendString(XISBuffer *b, unsigned char cmd, int cnt, char *ustr)
{
int i,j;
unsigned char buf[CTS_OEMSTRING_LEN];
if(((strlen((char *)ustr)+1) > cnt) || (cnt > sizeof(buf)))
{
DBG(5, ErrorF("%scit_SendString: String too long\n", CI_ERROR));
return(!Success);
}
DBG(9, ErrorF("%scit_SendString(cmd=0x%02x numbytes=0x%02X, %s\n", CI_INFO, cmd, cnt, ustr));
j=0;
buf[j++] = CTS_STX;
buf[j++] = cmd;
for(i=0; i<cnt; i++)
{
if ((ustr[i] >= CTS_CTRLMIN) && (ustr[i] <= CTS_CTRLMAX))
{
buf[j++] = CTS_ESC;
buf[j++] = ustr[i] | CTS_ENCODE;
}
else buf[j++] = ustr[i];
}
buf[j++] = CTS_ETX;
XisbWrite(b, buf, j);
for(i=0; i<j; i++)
{
if(i == 0)
{
DBG(9, ErrorF("%s sent=", CI_INFO));
}
else if(i%16 == 0)
{
DBG(9, ErrorF("\n"));
}
DBG(9, ErrorF("%02x ",buf[i]));
}
DBG(9, ErrorF("\n"));
return(Success);
}
static Bool cit_GetInitialErrors(cit_PrivatePtr priv)
{
unsigned long errors;
int i;
Bool res;
cit_Flush(priv);
cit_SendCommand(priv->buffer, C_GETERRORS, 1, GE_INITIAL);
for (i=0; i<5; i++)
{
cit_SetBlockDuration(priv, 500000);
res = cit_GetPacket(priv);
if ((res == Success) || (priv->lex_mode == cit_idle));
break;
}
if (res != Success)
{
DBG(5, ErrorF("%sNo packet received!\n", CI_NOTICE));
return (!Success);
}
if (priv->packeti != 6)
{
DBG(5, ErrorF("%sWrong packet length (expected 6, received %d bytes)\n", CI_NOTICE, priv->packeti));
return (!Success);
}
if (priv->packet[0] != (C_GETERRORS & CMD_REP_CONV))
{
DBG(5, ErrorF("%sWrong packet identifier (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
(C_GETERRORS & CMD_REP_CONV), priv->packet[0]));
return (!Success);
}
if (priv->packet[1] != GE_INITIAL)
{
DBG(5, ErrorF("%sWrong packet selector (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
GE_INITIAL, priv->packet[1]));
return (!Success);
}
errors = 0x00000001UL * (unsigned long)priv->packet[2]
+ 0x00000100UL * (unsigned long)priv->packet[3]
+ 0x00010000UL * (unsigned long)priv->packet[4]
+ 0x10000000UL * (unsigned long)priv->packet[5];
DBG(6, ErrorF("%sinitial errors = 0x%08lX\n", CI_NOTICE, errors));
if (errors == 0x00000000UL)
{
ErrorF("%sNo initialization errors detected.\n", CI_INFO);
}
if (errors & IE_SMCHKSUM)
{
ErrorF("%sSystem Manager Module checksum error!\n", CI_ERROR);
}
if (errors & IE_SMINIT)
{
ErrorF("%sSystem Manager Module initialization error!\n", CI_ERROR);
}
if (errors & IE_HWCHKSUM)
{
ErrorF("%sHardware Module checksum error!\n", CI_ERROR);
}
if (errors & IE_HWINIT)
{
ErrorF("%sHardware Module initialization error!\n", CI_ERROR);
}
if (errors & IE_HW_BEAMS)
{
ErrorF("%s broken beams during initialization detected!\n", CI_ERROR);
}
if (errors & IE_HW_PSU)
{
ErrorF("%s force sensors not operating!\n", CI_ERROR);
}
if (errors & IE_HW_CPU)
{
ErrorF("%s CPU integrity test failed!\n", CI_ERROR);
}
if (errors & IE_HW_IRAM)
{
ErrorF("%s internal RAM error!\n", CI_ERROR);
}
if (errors & IE_HW_XRAM)
{
ErrorF("%s external SRAM error!\n", CI_ERROR);
}
if (errors & IE_PCCHKSUM)
{
ErrorF("%sProcess Module checksum error!\n", CI_ERROR);
}
if (errors & IE_PCINIT)
{
ErrorF("%sProcess Module initialization error!\n", CI_ERROR);
}
if (errors & IE_PTCHKSUM)
{
ErrorF("%sProtocol Module checksum error!\n", CI_ERROR);
}
if (errors & IE_PTINIT)
{
ErrorF("%sProtocol Module initialization error!\n", CI_ERROR);
}
if (errors & IE_BICHK)
{
ErrorF("%sBurnIn Module checksum error!\n", CI_ERROR);
}
if (errors & IE_BIINIT)
{
ErrorF("%sBurnIn Module initialization error!\n", CI_ERROR);
}
if (errors & IE_FPGACHK)
{
ErrorF("%sFPGA configuration checksum error!\n", CI_ERROR);
}
if (errors & IE_HWPCHK)
{
ErrorF("%sHardware Parameter checksum error!\n", CI_ERROR);
}
return (Success);
}
static Bool cit_GetDefectiveBeams(cit_PrivatePtr priv)
{
unsigned nx, ny;
int i;
Bool res;
cit_Flush(priv);
cit_SendCommand(priv->buffer, C_GETERRORS, 1, GE_DEFECTBEAMS);
for (i=0; i<5; i++)
{
cit_SetBlockDuration(priv, 500000);
res = cit_GetPacket(priv);
if ((res == Success) || (priv->lex_mode == cit_idle));
break;
}
if (res != Success)
{
DBG(5, ErrorF("%sNo packet received!\n", CI_NOTICE));
return (!Success);
}
if (priv->packeti < 6)
{
DBG(5, ErrorF("%sWrong packet length (expected >= 6, received %d bytes)\n", CI_NOTICE, priv->packeti));
return (!Success);
}
if (priv->packet[0] != (C_GETERRORS & CMD_REP_CONV))
{
DBG(5, ErrorF("%sWrong packet identifier (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
(C_GETERRORS & CMD_REP_CONV), priv->packet[0]));
return (!Success);
}
if (priv->packet[1] != GE_DEFECTBEAMS)
{
DBG(5, ErrorF("%sWrong packet selector (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
GE_DEFECTBEAMS, priv->packet[1]));
return (!Success);
}
nx = 0x0001U * (unsigned)priv->packet[2]
+ 0x0100U * (unsigned)priv->packet[3];
ny = 0x0001U * (unsigned)priv->packet[4]
+ 0x0100U * (unsigned)priv->packet[5];
if (nx > 0)
{
ErrorF("%s%u defective X-Beams detected:\n", CI_ERROR, nx);
for (i=0; i<nx; i++)
{
ErrorF("%s\tX%02u\n", CI_ERROR, (unsigned)priv->packet[6+i]);
}
}
else
{
ErrorF("%sNo defective X-beams detected.\n", CI_INFO);
}
if (ny > 0)
{
ErrorF("%s%u defective Y-Beams detected:\n", CI_ERROR, ny);
for (i=0; i<ny; i++)
{
ErrorF("%s\tY%02u\n", CI_ERROR, (unsigned)priv->packet[6+nx+i]);
}
}
else
{
ErrorF("%sNo defective Y-beams detected.\n", CI_INFO);
}
return (Success);
}
static Bool cit_GetDesignator(cit_PrivatePtr priv)
{
int i,n;
Bool res;
cit_Flush(priv);
cit_SendCommand(priv->buffer, C_GETREVISIONS, 1, GR_DESIGNATOR);
for (i=0; i<5; i++)
{
cit_SetBlockDuration(priv, 500000);
res = cit_GetPacket(priv);
if ((res == Success) || (priv->lex_mode == cit_idle));
break;
}
if (res != Success)
{
DBG(5, ErrorF("%sNo packet received!\n", CI_NOTICE));
return (!Success);
}
if (priv->packeti < 2+CTS_DESIGNATOR_LEN+CTS_ASSY_LEN)
{
DBG(5, ErrorF("%sWrong packet length (expected >= %d, received %d bytes)\n", CI_NOTICE,
2+CTS_DESIGNATOR_LEN+CTS_ASSY_LEN,
priv->packeti));
return (!Success);
}
if (priv->packet[0] != (C_GETREVISIONS & CMD_REP_CONV))
{
DBG(5, ErrorF("%sWrong packet identifier (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
(C_GETREVISIONS & CMD_REP_CONV), priv->packet[0]));
return (!Success);
}
if (priv->packet[1] != GR_DESIGNATOR)
{
DBG(5, ErrorF("%sWrong packet selector (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
GR_DESIGNATOR, priv->packet[1]));
return (!Success);
}
ErrorF("%sDesignator \"", CI_INFO);
i = 2;
n = 0;
while (n++ < CTS_DESIGNATOR_LEN && priv->packet[i]!=0)
{
ErrorF("%c", priv->packet[i++]);
}
ErrorF("\"\n%sAssembly \"", CI_INFO);
i = 2 + CTS_DESIGNATOR_LEN;
n = 0;
while (n++ < CTS_ASSY_LEN && priv->packet[i]!=0)
{
ErrorF("%c", priv->packet[i++]);
}
ErrorF("\"\n");
return (Success);
}
static Bool cit_GetRevision(cit_PrivatePtr priv, int selection)
{
int i,n;
Bool res;
cit_Flush(priv);
cit_SendCommand(priv->buffer, C_GETREVISIONS, 1, (unsigned char)selection);
cit_SetBlockDuration(priv, 500000);
while (((res = cit_GetPacket(priv)) != Success) && (priv->lex_mode != cit_idle));
if (res != Success)
{
DBG(5, ErrorF("%sNo packet received!\n", CI_NOTICE));
return (!Success);
}
if (priv->packeti < 2)
{
DBG(5, ErrorF("%sWrong packet length (expected >= %d, received %d bytes)\n", CI_NOTICE,
2, priv->packeti));
return (!Success);
}
if (priv->packet[0] != (C_GETREVISIONS & CMD_REP_CONV))
{
DBG(5, ErrorF("%sWrong packet identifier (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
(C_GETREVISIONS & CMD_REP_CONV), priv->packet[0]));
return (!Success);
}
if (priv->packet[1] != selection)
{
DBG(5, ErrorF("%sWrong packet selector (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
selection, priv->packet[1]));
return (!Success);
}
DBG(5, ErrorF("%s%s module revision ", CI_INFO,
selection == GR_SYSMGR ? "SysMgr " :
selection == GR_HARDWARE ? "Hardware" :
selection == GR_PROCESS ? "Process " :
selection == GR_PROTOCOL ? "Protocol" :
selection == GR_HWPARAM ? "HWParam " :
"???"));
i = 2;
n = 0;
DBG(5, ErrorF("\""));
while (n < priv->packeti && priv->packet[i]!=0)
{
DBG(5, ErrorF("%c", priv->packet[i]));
i++;
}
DBG(5, ErrorF("\"\n"));
return (Success);
}
static Bool cit_GetUserString(cit_PrivatePtr priv, char *ustr_name, char *ustr_cont, Bool scan_flg)
{
int ustrlen;
int err;
Bool res;
DBG(8, ErrorF("%scit_GetUserString called\n", CI_INFO));
ustrlen = strlen((char *)ustr_name);
if((ustrlen <= 0) || (ustrlen > CTS_USERNAME_LEN))
{
DBG(5, ErrorF("%scit_GetUserString: No strname specified or string too long\n", CI_ERROR));
return (!Success);
}
if(scan_flg)
{
cit_SendCommand(priv->buffer, C_SETSCANNING, 1, SC_DISABLE);
WAIT(150);
}
cit_Flush(priv);
cit_SendString(priv->buffer, C_GETUSERSTRING, ustrlen+1, ustr_name);
cit_SetBlockDuration(priv, 1000000);
while (((res = cit_GetPacket(priv)) != Success) && (priv->lex_mode != cit_idle));
if(scan_flg)
cit_SendCommand(priv->buffer, C_SETSCANNING, 1, SC_ENABLE);
if (res != Success)
{
DBG(5, ErrorF("%sNo packet received!\n", CI_NOTICE));
return (!Success);
}
if (priv->packeti < 2)
{
DBG(5, ErrorF("%sWrong packet length (expected >= %d, received %d bytes)\n", CI_NOTICE,
2, priv->packeti));
return (!Success);
}
if (priv->packet[0] != (C_GETUSERSTRING & CMD_REP_CONV))
{
DBG(5, ErrorF("%sWrong packet identifier (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
(C_GETUSERSTRING & CMD_REP_CONV), priv->packet[0]));
return (!Success);
}
if(strncmp(ustr_name, (char *)&priv->packet[1], CTS_USERNAME_LEN) == 0)
{
strncpy(ustr_cont, (char *)&priv->packet[strlen((char *)&priv->packet[1])+2], CTS_USERSTRING_LEN);
DBG(5, ErrorF("%s cit_GetUserString: %s=%s \n", CI_INFO, ustr_name, ustr_cont));
}
else
{
DBG(5, ErrorF("%s cit_GetUserString: %s != %s\n", CI_ERROR,
ustr_name, &priv->packet[1]));
return (!Success);
}
return (Success);
}
static void cit_ProcessPacket(cit_PrivatePtr priv)
{
int i;
DBG(PP, ErrorF("%scit_ProcessPacket called\n", CI_INFO));
DBG(PP, ErrorF("%s\t+ enter state = 0x%04X, dual touch count=%d\n", CI_INFO, priv->state, priv->dual_touch_count));
priv->dual_flg = TRUE;
#ifdef CIT_TIM
priv->timer_val1[FAKE_TIMER] = 1000;
priv->timer_callback[FAKE_TIMER] = (OsTimerCallback)cit_DualTouchTimer;
cit_StartTimer(priv, FAKE_TIMER);
#endif
switch (priv->packet[0])
{
case R_COORD:
if (priv->packeti < 5)
{
DBG(PP, ErrorF("%s\t- coordinate message packet too short (%d bytes)\n", CI_ERROR, priv->packeti));
break;
}
if (priv->dual_touch_count > 0)
priv->dual_touch_count--;
priv->raw_x = 0x0001U * priv->packet[1]
+ 0x0100U * priv->packet[2];
priv->raw_y = 0x0001U * priv->packet[3]
+ 0x0100U * priv->packet[4];
priv->raw_min_x = min(priv->raw_min_x, priv->raw_x);
priv->raw_max_x = max(priv->raw_max_x, priv->raw_x);
priv->raw_min_y = min(priv->raw_min_y, priv->raw_y);
priv->raw_max_y = max(priv->raw_max_y, priv->raw_y);
priv->state |= CIT_TOUCHED;
DBG(PP, ErrorF("%s\t+ COORD message raw (%d,%d)\n", CI_INFO, priv->raw_x, priv->raw_y));
break;
case R_EXIT:
if (priv->packeti < 5)
{
DBG(PP, ErrorF("%s\t- exit message packet too short (%d bytes)\n", CI_ERROR, priv->packeti));
break;
}
priv->state &= ~(CIT_TOUCHED | CIT_PRESSED);
priv->dual_touch_count = 0;
priv->enter_touched = 0;
priv->raw_x = 0x0001U * priv->packet[1]
+ 0x0100U * priv->packet[2];
priv->raw_y = 0x0001U * priv->packet[3]
+ 0x0100U * priv->packet[4];
#ifdef CIT_TIM
cit_CloseTimer(priv, FAKE_TIMER);
#endif
DBG(PP, ErrorF("%s\t+ EXIT message (%d,%d)\n", CI_INFO, priv->raw_x, priv->raw_y));
break;
case R_DUALTOUCHERROR:
if (priv->dual_touch_count < priv->max_dual_count)
priv->dual_touch_count++;
DBG(PP, ErrorF("%s\t+ DUAL TOUCH ERROR message received\n", CI_INFO));
break;
case R_PRESSURE:
if (priv->packeti < 2)
{
DBG(PP, ErrorF("%s\t- pressure message packet too short (%d bytes)\n", CI_ERROR, priv->packeti));
break;
}
priv->state |= CIT_TOUCHED;
if (priv->packet[1] == PRESS_EXCEED)
priv->state |= CIT_PRESSED;
else if(priv->packet[1] == PRESS_BELOW)
{
priv->enter_touched = 0;
priv->state &= ~CIT_PRESSED;
}
else
DBG(PP, ErrorF("%sPressure Message Error\n", CI_ERROR));
DBG(PP, ErrorF("%s\t+ pressure %s message\n", CI_INFO, priv->packet[1] ? "enter":"exit"));
break;
default:
DBG(PP, ErrorF("%s\t* unhandled message:", CI_ERROR));
for (i=0; i<priv->packeti; i++)
{
DBG(PP, ErrorF(" 0x%02X", priv->packet[i]));
}
DBG(PP, ErrorF("\n"));
}
switch (priv->click_mode)
{
case CM_ZPRESS:
DBG(PP, ErrorF("%s\t+ ZPress, button ", CI_INFO));
if (priv->state & CIT_PRESSED)
{
priv->state |= CIT_BUTTON;
DBG(PP, ErrorF("down"));
}
else
{
priv->state &= ~CIT_BUTTON;
DBG(PP, ErrorF("up"));
}
break;
case CM_ZPRESSEXIT:
DBG(PP, ErrorF("%s\t+ ZPressExit, button ", CI_INFO));
if (priv->state & CIT_PRESSED)
{
priv->state |= CIT_BUTTON;
DBG(PP, ErrorF("down"));
}
else if (!(priv->state & CIT_TOUCHED))
{
priv->state &= ~CIT_BUTTON;
DBG(PP, ErrorF("up"));
}
break;
case CM_DUAL:
DBG(PP, ErrorF("%s\t+ Dual Touch, button ", CI_INFO));
if ((priv->dual_touch_count == priv->max_dual_count) && (priv->state & CIT_TOUCHED))
{
priv->state |= CIT_BUTTON;
DBG(PP, ErrorF("down"));
}
else if (priv->dual_touch_count == 0)
{
priv->state &= ~CIT_BUTTON;
DBG(PP, ErrorF("up"));
}
break;
case CM_DUALEXIT:
DBG(PP, ErrorF("%s\t+ Dual Exit, button ", CI_INFO));
if ((priv->dual_touch_count == priv->max_dual_count) && (priv->state & CIT_TOUCHED))
{
priv->dual_flg = TRUE;
priv->state |= CIT_BUTTON;
DBG(PP, ErrorF("down"));
}
else if (!(priv->state & CIT_TOUCHED))
{
priv->state &= ~CIT_BUTTON;
DBG(PP, ErrorF("up"));
}
break;
default:
DBG(PP, ErrorF("%s\t+ Enter Mode, button ", CI_INFO));
if (priv->state & CIT_TOUCHED)
{
priv->state |= CIT_BUTTON;
DBG(PP, ErrorF("down"));
}
else
{
priv->state &= ~CIT_BUTTON;
DBG(PP, ErrorF("up"));
}
break;
}
DBG(PP, ErrorF("\n"));
DBG(PP, ErrorF("%s\t+ Click Mode=%d\n", CI_INFO, priv->click_mode));
DBG(PP+1, ErrorF("%s\t+ exit state = 0x%04X, dual touch count=%d\n", CI_INFO, priv->state, priv->dual_touch_count));
DBG(PP+1, ErrorF("%s\t raw_x=%d, raw_y=%d\n", CI_INFO, priv->raw_x, priv->raw_y));
}
static Bool cit_GetPressureSensors(cit_PrivatePtr priv)
{
int i;
Bool res;
cit_Flush(priv);
cit_SendCommand(priv->buffer, C_GETHARDWARE, 1, GH_SENSORCOUNT);
for (i=0; i<5; i++)
{
cit_SetBlockDuration(priv, 500000);
res = cit_GetPacket(priv);
if ((res == Success) || (priv->lex_mode == cit_idle));
break;
}
if (res != Success)
{
DBG(5, ErrorF("%sNo packet received!\n", CI_NOTICE));
return (!Success);
}
if (priv->packeti < 2+CTS_SENSORCOUNT_LEN)
{
DBG(5, ErrorF("%sWrong packet length (expected >= %d, received %d bytes)\n", CI_NOTICE,
2+CTS_SENSORCOUNT_LEN,
priv->packeti));
return (!Success);
}
if (priv->packet[0] != (C_GETHARDWARE & CMD_REP_CONV))
{
DBG(5, ErrorF("%sWrong packet identifier (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
(C_GETHARDWARE & CMD_REP_CONV), priv->packet[0]));
return (!Success);
}
if (priv->packet[1] != GH_SENSORCOUNT)
{
DBG(5, ErrorF("%sWrong packet selector (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
GH_SENSORCOUNT, priv->packet[1]));
return (!Success);
}
ErrorF("%sPressureSensors: \"%d\"\n", CI_INFO, priv->packet[2]);
priv->pressure_sensors = priv->packet[2];
return (Success);
}
static int cit_ZPress(cit_PrivatePtr priv)
{
if((priv->click_mode == CM_ZPRESS) || (priv->click_mode == CM_ZPRESSEXIT))
return (TRUE);
else
return (FALSE);
}
static void cit_SetEnterCount(cit_PrivatePtr priv)
{
if(cit_ZPress(priv))
priv->enter_count = priv->enter_count_Z;
else priv->enter_count = priv->enter_count_no_Z;
ErrorF("%scit_SetEnterCount: Count=%d\n", CI_CONFIG, priv->enter_count);
}
static void cit_SendPWM(cit_PrivatePtr priv)
{
int pwm_active, pwm_sleep;
pwm_active = cit_AdjustBright(priv, priv->pwm_active);
pwm_sleep = cit_AdjustBright(priv, priv->pwm_sleep);
cit_SendCommand(priv->buffer, C_SETPWM, 2, LOBYTE(pwm_active),
LOBYTE(pwm_sleep));
DBG(3,ErrorF("%scit_SendPWM: active=%d, sleep=%d\n", CI_CONFIG, pwm_active, pwm_sleep));
}
static void cit_SendPWMFreq(cit_PrivatePtr priv)
{
if(priv->pwm_freq >= 0)
{
cit_SendCommand(priv->buffer, C_SETPWMFREQ, 2,
LOBYTE(priv->pwm_freq),
HIBYTE(priv->pwm_freq));
DBG(3,ErrorF("%scit_SendPWMFreq: Freq=%d\n", CI_CONFIG, priv->pwm_freq));
}
else
DBG(3,ErrorF("%scit_SendPWMFreq: Frequency not set\n", CI_CONFIG));
}
static void cit_SendLockZ(cit_PrivatePtr priv)
{
cit_SendCommand(priv->buffer, C_SETLOCKZ, 3, LOBYTE(priv->lockz_enter_time),
LOBYTE(priv->lockz_exit_time),
LOBYTE(priv->lockz_lock_time));
DBG(3,ErrorF("%scit_SendLockZ: enter=%d, exit=%d, lock=%d\n", CI_CONFIG,
priv->lockz_enter_time,priv->lockz_exit_time, priv->lockz_lock_time));
}
static int cit_AdjustBright(cit_PrivatePtr priv, int val)
{
int i;
int src_val;
DBG(9,ErrorF("%scit_AdjustBright entered val=%d, src=%d, dst=%d\n", CI_CONFIG, val, priv->pwm_src, priv->pwm_dst));
if((priv->pwm_src < 0) || (priv->pwm_dst < 0))
return(val);
if((priv->pwm_src <= BL_AC) && (priv->pwm_dst <= BL_MAX) && (val < 256))
src_val = cit_bright_adjust[priv->pwm_src][val];
else
{
DBG(3,ErrorF("%scit_AdjustBright: Wrong value src=%d dst=%d\n", CI_CONFIG, priv->pwm_src, priv->pwm_dst));
return(-1);
}
for(i=0; i<256; i++)
{
if(cit_bright_adjust[priv->pwm_dst][i] >= src_val)
return (i);
}
return (255);
}