📄 tpdrv.c
字号:
//=============================================================================
//
// TeamPOS 2000 Touchpanel driver
//
//
//
//-----------------------------------------------------------------------------
//================================================
// include
//================================================
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/times.h>
#include <sys/resource.h>
#include <sys/ioctl.h>
#include <sys/kd.h>
#include <syslog.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <limits.h>
#define D_TPDRV_DEBUG 0
//================================================
// define
//================================================
#define MAXFD 64
#define D_LOCK_FILE_NAME "/usr/tmp/TPDrv.lock"
#define D_TP_PROFILE_NAME "/usr/etc/TPDrv.conf"#define D_RAWSTAT_MAX 5
#define D_STATUS 0
#define D_XL 1
#define D_XH 2
#define D_YL 3
#define D_YH 4
#define D_MAKE 0x00
#define D_BODY 0x01
#define D_BREAK 0x02
#define D_STREAMMODE 1
#define D_POINTMODE 2
//================================================
// struct
//================================================
typedef struct T_MouseStat
{
int rawstat;
unsigned char CurrentRaw[5]; //僞僢僠僷僱儖偐傜偺嵗昗僨乕僞僷働僢僩
int LastX;
int LastY;
int BtnStat;
}t_MouseStat;
typedef struct T_TPProf
{
int mode;
int SamplingRate;
char Port[16];
int Scalling;
int Threashold;
int X_Resolution;
int Y_Resolution;
int MAX_X_VAL;
int MAX_Y_VAL;
char DevName[256];
}t_TPProf;
typedef struct T_ps2Packet
{
unsigned char Botton;
unsigned char X;
unsigned char Y; unsigned char rsv;
}t_ps2Packet;
//================================================
// global
//================================================
static int g_FIFOSH = -1;
t_MouseStat g_MouseStat;
t_ps2Packet g_ps2Packet[32];
t_TPProf g_TPProf; //default : STREAMMODE - SamplingRate 40ms
static int g_SERISH;
char g_OutData[256];
int g_MAXMOVE;//===============================================
// prototype
//================================================
static int k_HandlerTP(unsigned char val);
static int k_ConvertPS2XYData(int X, int Y);
static void k_MainLoop(void);
static int k_SendDmy(void);
static int k_SetRate(void);
static int k_Report(void);
static int k_RS_Open(void);
static int k_RS_Write(char* Buf, int Size);
static int k_RS_Read(char* Buf, int Size);
static void k_RS_Close(void);
static int k_Write_PS2Packet(int Num);
static int k_AccelCalc(int X, int Y, char XSign, char YSign);
static void k_DPrint(const char *fmt, ...);
static void k_Dump(const char *Tag, void *msg, int len);
static int k_GetProfileInt(const char *Section, const char *key, int Default);
static int k_GetProfileString(const char *Section, const char *key, char *string, int stringsize,const char* Default);
static void k_ValueInit(void);static void k_Sig_Chld(int SigID);
static int k_mkfifo(char *FIFOName);
//================================================
// main
//================================================
int main(void)
{
int PipeFd[2];
struct flock Lock;
char Buf[16];
int Fd;
int ii;
int FncRet;
pid_t Pid;
// start log
openlog("TPDrv ", 0, LOG_DAEMON); syslog(LOG_CRIT, "start\n");
syslog(LOG_CRIT, "priority = %d\n", getpriority(PRIO_PROCESS, 0));
FncRet = pipe(PipeFd);
#if D_TPDRV_DEBUG
#else
// be daemon process
Pid = fork();
if(Pid < 0)
goto l_ErrorFork;
if(Pid != 0)
{
// wait... until child process be session leader
read(PipeFd[0], Buf, 1);
exit(0);
}
setsid();
write(PipeFd[1], Buf, 1);
#endif
chdir("/");
umask(0);
#if D_TPDRV_DEBUG
// set signal handler
signal(SIGCHLD, k_Sig_Chld);
#else
// close file
for (ii=0;ii<MAXFD;ii++)
close(ii);
#endif
// lock file
Fd = open(D_LOCK_FILE_NAME, O_RDWR | O_CREAT);
if(Fd < 0)
goto l_ELockFileOpen;
Lock.l_type = F_WRLCK;
Lock.l_whence = SEEK_SET;
Lock.l_start = 0;
Lock.l_len = 1;
FncRet = fcntl(Fd, F_SETLK, &Lock);
if(FncRet != 0)
goto l_ErrorLock;
k_ValueInit();
FncRet = k_mkfifo(g_TPProf.DevName);
if(FncRet != 0)
goto l_EMKFifo;
g_FIFOSH = open(g_TPProf.DevName, O_WRONLY);
if(g_FIFOSH < 0)
goto l_EFIFOOpen;
g_MouseStat.LastX = g_TPProf.X_Resolution/2;
g_MouseStat.LastY = g_TPProf.Y_Resolution/2;
k_MainLoop();
l_Exit:
if(g_FIFOSH != -1) close(g_FIFOSH);
syslog(LOG_CRIT, "stop\n");
return 0;
l_ELockFileOpen:
k_DPrint("SystemError[ID=0001](open errno=%d)\n", errno);
goto l_Exit;
l_ErrorFork:
k_DPrint("SystemError[ID=0002](fork errno=%d)\n", errno);
goto l_Exit;
l_ErrorLock:
k_DPrint("SystemError[ID=0003](lock errno=%d\n)\n", errno);
goto l_Exit;
l_EFIFOOpen:
k_DPrint("SystemError[ID=0004](open errno=%d)\n", errno);
goto l_Exit;
l_EMKFifo:
k_DPrint("SystemError[ID=0013]\n");
goto l_Exit;
}
//================================================
// MainLoop
//================================================
static void k_MainLoop(void)
{
int FuncRet;
int RecvLen;
fd_set SReadFs;
char TempBuf[256];
int ii;
int Status;
FuncRet = k_RS_Open();
if(FuncRet < 0)
goto l_EOpen;
FuncRet = k_SendDmy();
if(FuncRet != 0)
goto l_SendDmy;
FuncRet = k_SetRate();
if(FuncRet != 0)
goto l_SetRate;
FuncRet = k_Report(); if(FuncRet != 0)
goto l_Report;
while(1)
{
FD_ZERO(&SReadFs);
FD_SET(g_SERISH, &SReadFs);
select(g_SERISH + 1, &SReadFs, NULL, NULL, NULL);
if(FD_ISSET(g_SERISH, &SReadFs))
{
while(1)
{
RecvLen = k_RS_Read(TempBuf, sizeof(TempBuf));
if(RecvLen <= 0)
{
Status = 0;
break;
}
for(ii = 0; ii < RecvLen; ii++)
{
if(Status == 0)
{
if(!(TempBuf[ii] & 0x80))
continue;
else
{
k_HandlerTP(TempBuf[ii]); /* 僷働僢僩僨乕僞偑婣傞偙偲偼偁傝偊側偄 */
Status++;
}
}
else
{
FuncRet = k_HandlerTP(TempBuf[ii]);
if(0 < FuncRet)
{
k_Write_PS2Packet(FuncRet);
Status = 0;
}
}
}
}
}
}
l_Exit:
k_RS_Close();
close(g_FIFOSH);
return;
l_EOpen:
l_SendDmy:
l_SetRate:
l_Report: goto l_Exit;
}
//================================================
// k_SendDmy
//================================================
static int k_SendDmy(void)
{
char Val = 0xFF;
int FuncRet;
FuncRet = k_RS_Write(&Val, sizeof(Val));
if(FuncRet < 0)
goto l_WErr;
usleep(1000*10); //sleep 10ms
l_Exit:
return 0;
l_WErr:
FuncRet = -1;
goto l_Exit;
}
//================================================
// k_SetRate
//================================================
static int k_SetRate(void)
{
unsigned char Val[2];
int FuncRet;
int RecvLen = 0;
Val[0] = 0x8B;
Val[1] = g_TPProf.SamplingRate;
FuncRet = k_RS_Write(Val, sizeof(Val));
if(FuncRet < 0)
goto l_WErr;
while(RecvLen != 2)
{
FuncRet = k_RS_Read(Val + RecvLen, sizeof(Val) - RecvLen);
if(0 <= FuncRet)
RecvLen += FuncRet;
else
goto l_ESetRate;
if(RecvLen == 2)
{
if(((Val[0] == 0x90) ||( Val[0] == 0xD0)) && (Val[1] == 0x00))
FuncRet = 0;
else
goto l_ESetRate;
}
}
l_Exit:
return FuncRet;
l_WErr:
FuncRet = -1;
goto l_Exit;
l_ESetRate:
k_DPrint("SystemError[ID=0005]\n");
k_Dump("Recv", Val, FuncRet);
FuncRet = -1;
goto l_Exit;
}
//================================================
// k_Report
//================================================
static int k_Report(void)
{
unsigned char Val[16];
int FuncRet;
int RecvLen = 0;
Val[0] = 0x88;
FuncRet = k_RS_Write(Val, 1);
if(FuncRet < 0)
goto l_WErr;
while(RecvLen != 9)
{
FuncRet = k_RS_Read(Val + RecvLen, 9 - RecvLen);
if(0 <= FuncRet)
RecvLen += FuncRet;
else
goto l_EReport;
if(RecvLen == 9)
{
if(((Val[0] == 0x90) ||( Val[0] == 0xD0)) && (Val[1] == 0x00))
{
g_TPProf.MAX_X_VAL = Val[5] + ((Val[6]&0x3F) << 7);
g_TPProf.MAX_Y_VAL = Val[7] + ((Val[8]&0x3F) << 7);
FuncRet = 0;
}
else
goto l_EReport;
}
}
l_Exit:
return FuncRet;
l_WErr:
FuncRet = -1;
goto l_Exit;
l_EReport:
k_DPrint("SystemError[ID=0006]\n");
k_Dump("Recv", Val, FuncRet);
FuncRet = -1;
goto l_Exit;
}
/*============================================================================
* PS/2 Mouse Movement Packet
* +-----+-----+-----+-----+-----+-----+-----+-----+
* BYTE1 |YOver|XOver|YSign|XSign| 1 |M Btn|R Btn|L Btn|
* +-----+-----+-----+-----+-----+-----+-----+-----+
* +-----+-----+-----+-----+-----+-----+-----+-----+
* BYTE2 | X Movement |
* +-----+-----+-----+-----+-----+-----+-----+-----+
* +-----+-----+-----+-----+-----+-----+-----+-----+
* BYTE3 | Y Movement |
* +-----+-----+-----+-----+-----+-----+-----+-----+
*-----------------------------------------------------------------------------*/
/*===================================================================
* k_HandlerTP
*
* 堷悢
* val 僞僢僠僷僱儖偐傜偺嵗昗僨乕僞
* 栠傝抣
* PS2僷働僢僩姰惉悢
*--------------------------------------------------------------------*/
static int k_HandlerTP(unsigned char val)
{
int RetValue = 0;
int TempX;
int TempY;
int FuncRet;
int ii;
int LastRecFlg = 0;
if(val & 0x80) //recv data header
{
g_MouseStat.rawstat = D_STATUS; //reset rawstat
g_MouseStat.CurrentRaw[g_MouseStat.rawstat] = val;
g_MouseStat.rawstat++; //goto next rawstat
}
else //coordinate data
{
g_MouseStat.CurrentRaw[g_MouseStat.rawstat] = val;
g_MouseStat.rawstat++;
if(g_MouseStat.rawstat == D_RAWSTAT_MAX)
{
memset(g_ps2Packet, 0x00, sizeof(t_ps2Packet)*32);
TempX = g_MouseStat.CurrentRaw[D_XL];
TempX += g_MouseStat.CurrentRaw[D_XH] << 7;
TempY = g_MouseStat.CurrentRaw[D_YL];
TempY += g_MouseStat.CurrentRaw[D_YH] << 7;
TempX = (TempX*g_TPProf.X_Resolution)/g_TPProf.MAX_X_VAL;
TempY = (TempY*g_TPProf.Y_Resolution)/g_TPProf.MAX_Y_VAL;
FuncRet = k_ConvertPS2XYData(TempX, TempY);
switch(g_MouseStat.BtnStat)
{
case 0: //墴壓懸偪
switch(g_MouseStat.CurrentRaw[D_STATUS] & 0x03)
{
case D_MAKE:
if(0 < FuncRet)
{
g_ps2Packet[FuncRet-1].Botton |= 0x01; //嵍儃僞儞ON
RetValue = FuncRet;
}
else
{
g_ps2Packet[0].Botton |= 0x01; //嵍儃僞儞ON
RetValue = 1;
}
if(g_TPProf.mode == D_STREAMMODE)
{ //僗僩儕乕儉儌乕僪夝曻懸偪傊
g_MouseStat.BtnStat = 1;
}
else
{ //億僀儞僩儌乕僪夝曻懸偪傊
g_MouseStat.BtnStat = 2;
}
LastRecFlg = 1;
break;
default:
k_DPrint("BtnStat %d \n", g_MouseStat.BtnStat);
k_Dump("Recv", g_MouseStat.CurrentRaw, 5);
break;
}
break;
case 1: //僗僩儕乕儉儌乕僪夝曻懸偪
switch(g_MouseStat.CurrentRaw[D_STATUS] & 0x03)
{
case D_MAKE:
case D_BODY:
for(ii = 0; ii < FuncRet; ii++)
g_ps2Packet[ii].Botton |= 0x01; //嵍儃僞儞ON
RetValue = FuncRet;
LastRecFlg = 1;
break;
case D_BREAK:
if(0 < FuncRet)
{
for(ii = 0; ii < FuncRet; ii++)
g_ps2Packet[ii].Botton |= 0x01; //嵍儃僞儞ON
g_ps2Packet[FuncRet-1].Botton &= 0xFE; //嵟屻偺僷働僢僩偱儃僞儞夝曻
// 墴壓懸偪傊
g_MouseStat.BtnStat = 0;
RetValue = FuncRet;
}
else
{
g_ps2Packet[0].Botton &= 0xFE; //嵟屻偺僷働僢僩偱儃僞儞夝曻
g_MouseStat.BtnStat = 0;
RetValue = 1; //儃僞儞夝曻捠抦偺1僷働僢僩傪憲傞
}
LastRecFlg = 1;
break;
default:
k_DPrint("BtnStat %d \n", g_MouseStat.BtnStat);
k_Dump("Recv", g_MouseStat.CurrentRaw, 5);
break;
}
break;
case 2: //億僀儞僩儌乕僪夝曻懸偪
switch(g_MouseStat.CurrentRaw[D_STATUS] & 0x03)
{
case D_MAKE:
case D_BODY:
//墴壓帪偺嵗昗偱捠抦偡傞(堏摦搙侽)
g_ps2Packet[0].X = 0;
g_ps2Packet[0].Y = 0;
g_ps2Packet[0].Botton = 0x04;
//埲屻柍帇偡傞偨傔偵夝曻傑偪傊
g_MouseStat.BtnStat = 3;
RetValue = 1;
break;
case D_BREAK:
//墴壓帪偺嵗昗偱捠抦偡傞(堏摦搙侽)
g_ps2Packet[0].X = 0;
g_ps2Packet[0].Y = 0;
g_ps2Packet[0].Botton = 0x04;
//墴壓傑偪傊
g_MouseStat.BtnStat = 0;
RetValue = 1;
break;
default:
k_DPrint("BtnStat %d \n", g_MouseStat.BtnStat);
k_Dump("Recv", g_MouseStat.CurrentRaw, 5);
break;
}
break;
case 3: //億僀儞僩儌乕僪夝曻捠抦屻BREAK懸偪
RetValue = 0;//偡偱偵夝曻捠抦偟偨偺偱杮摉偺夝曻偑棃傞傑偱柍帇偡傞
switch(g_MouseStat.CurrentRaw[D_STATUS] & 0x03)
{
case D_BREAK:
g_MouseStat.BtnStat = 0;
break;
case D_MAKE:
case D_BODY:
break;
default:
k_DPrint("BtnStat %d \n", g_MouseStat.BtnStat);
k_Dump("Recv", g_MouseStat.CurrentRaw, 5);
break;
}
break;
default:
k_DPrint("BtnStat %d \n", g_MouseStat.BtnStat);
k_Dump("Recv", g_MouseStat.CurrentRaw, 5);
break;
}
g_MouseStat.rawstat = D_STATUS;
if(LastRecFlg == 1)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -