/*  serial port interface for Palm Portable Keyboard
 *  Copyright (C) 2003 
 *  Trap <CXL00145@nifty.com> (linux zaurus SL-C7x0 version)
 *
 *  Based on ser_code.c created by ...
 *    Dan Morris <dmorris@cs.brown.edu> (initial and windows version)
 *    Ralf Ackermann <rac@KOM.tu-darmstadt.de>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 *  2003.12.14 v1.1.0 : Performance Up.
 *    The weight of the value of the parameter (keyrep_first, keyrep_next)
 *    was changed. When using -d option, a default config file changed into
 *    ser_code_direct.ini automatically.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <libgen.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <termio.h>
#include <error.h>

// mouse
#include <linux/fb.h>
#include <asm/page.h>	
#include <sys/mman.h>
// mouse

#ifndef errno
extern int errno;
#endif

#include <asm/sharp_char.h>
#include <asm/sharp_keycode.h>
#include <linux/kbd_ll.h>

/*
keyboard protocol is:
   key press   => key scan code
   key release => (key scan code | (1 << 7)) (most significant bit set)

   When all key was released, last release code once again arrived.
*/


// Constants

#define	MYFLG_SHIFT	0x01
#define	MYFLG_CTRL	0x02
#define	MYFLG_FN	0x04
#define	MYFLG_CMD	0x08

#define RETOUR_OK	0
#define RETOUR_ERROR	-1

#define	RTS_TIMEOUT	600

#define VERSION		"1.1.0"

#define	VNCKBDDRV	"/dev/kbdsim"
#define	SHARPKBDDRV	"/dev/sharp_kbdctl"

// user structure

typedef struct key_mapping {
    char	*keyname;
    long	keycode;
} key_mappings;

// global variables

static int		fdd = -1;		// IOCTL を行うデバイス用のファイルハンドル
static int		fds = -1;		// キーボードからの受信用ファイルハンドル
static int		directflag = 0;		// ダイレクトモードのフラグ
static int		infoflag = 0;		// debug メッセージ表示フラグ
static int		vncflag = 0;		// VNCドライバ利用モードのフラグ
static int		keyrepeat = 0;		// キーリピートのためのカウンタ
static int		keyrep_first = 3;	// 初回キーリピート待ち時間(0.3s)
static int		keyrep_next = 1;	// 2回目以降キーリピート待ち時間(0.1s)
static long		lastkeycode = -1;	// 最後に押されたキーに対する送信コード
static char *		program_name = "";	// このプログラムの名前

static char *		serialdevice = "/dev/ttyS0";
static char *		keymapfile   = NULL;
static char *		keymapfile_n = "/opt/QtPalmtop/etc/ser_code_ksim.ini";
static char *		keymapfile_d = "/opt/QtPalmtop/etc/ser_code_direct.ini";
static char *		metas_str[8] = { "lshift", "lctrl", "lfn", "lcmd", "rshift", "rctrl", "rfn", "rcmd" };

// キー情報格納領域
static int		metaflags;		// meta-key の押し下げ状態を記憶する変数
static char		keys[128];		// 各キーの ON/OFF 状態を保持する配列
static unsigned char	metas[128];		// そのキーがどの meta-key であるかを示す配列
static key_mappings	keymap[16][128];	// cmd, fn, ctrl, shift の組合せ16通りの 128 個のキー

// mouse
static FILE *fp;

static int console_fd;
static struct fb_var_screeninfo vinfo;
static struct fb_fix_screeninfo finfo;
static int mapped_memlen;
static int mapped_offset;
static short *mapped_mem;
static short *mapped_mem_start;
static short *mapped_mem_end;

    int fb_offset;
//mouse


// prototypes

void		infoarea_init( void );
int		check_meta( const char *str );
int		read_key_mapping( char *map_file );

void		rts_down_up( int fd );
int		init_ser( char *ser_device );
int		set_ser_param( int fd );
void		flush_ser( int fd );

unsigned char	get_1_char( void );

void		sig_handler( int status );

void		close_all( void );
void		usage( int status );
void		printversion( void );
void		printinfo( void );

void		onekey_v( int c, int fd, int pressflag );
void		onekey_s( long c, int fd );
int		onekey( long c, int fdd );


//  mouse

#define POINTERCAL "/etc/pointercal"

static struct qt_cal {
    int ok;
    int a, b, c, d, e, f, s;
} cal;

static struct q_cal {
    int ok;
    double a, b, c, d, e, f, s;
} qcal;

static int pointer[16][16] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
                               0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
                               0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
                               0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
                               0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
                               0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
                               0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
                               0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
                               0x0000, 0x0000, 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001,
                               0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0001, 0x0001, 0x0001,
                               0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0001, 0x0001,
                               0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0001,
                               0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0001,
                               0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0001, 0x0001,
                               0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0xFFFF, 0xFFFF, 0x0000, 0x0001, 0x0001, 0x0001,
                               0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001 };


void paint(int x,int y)
{
    static short prev_image[16][16];
    static short prev_x,prev_y;
    static int st=0;
    int i,j;


    x -= 16;

    if(st != 0){
    for (i=0 ; i<16; i++){
        for (j=0 ; j<16; j++){
          if((mapped_mem+i+prev_x+(j+prev_y)*finfo.line_length/2) > mapped_mem_start &&
             (mapped_mem+i+prev_x+(j+prev_y)*finfo.line_length/2) < mapped_mem_end ){
            *(mapped_mem+i+prev_x+(j+prev_y)*finfo.line_length/2 ) = prev_image[i][j];
          }
        }
    }
    }

    st=1;
    prev_x=x;
    prev_y=y;

    for (i=0 ; i<16; i++){
        for (j=0 ; j<16; j++){
          if((mapped_mem+i+prev_x+(j+prev_y)*finfo.line_length/2) > mapped_mem_start &&
             (mapped_mem+i+prev_x+(j+prev_y)*finfo.line_length/2) < mapped_mem_end ){
              prev_image[i][j]=*(mapped_mem+i+x+(j+y)*finfo.line_length/2 );
          }
        }
    }


    for (i=0 ; i<16; i++){
        for (j=0 ; j<16; j++){
          if((mapped_mem+i+prev_x+(j+prev_y)*finfo.line_length/2) > mapped_mem_start &&
             (mapped_mem+i+prev_x+(j+prev_y)*finfo.line_length/2) < mapped_mem_end ){
            if (pointer[15-i][j] != 1) {
              *(mapped_mem+i+x+(j+y)*finfo.line_length/2 ) = pointer[15-i][j];
            }
          }
        }
    }

return;
}

void loadConfig()
{
    FILE *pcal;
    cal.ok = 0;
    pcal = fopen(POINTERCAL, "r");
    if(pcal == NULL){
	fprintf(stderr, "Warning: cannot open " POINTERCAL ".\n");
    }else{
	int n;
	n = fscanf(pcal, "%d %d %d %d %d %d %d",
		   &cal.a, &cal.b, &cal.c, &cal.d, &cal.e, &cal.f, &cal.s);
        qcal.a = cal.a /1000;
        qcal.b = cal.b /1000;
        qcal.c = cal.c /1000;
        qcal.d = cal.d /1000;
        qcal.e = cal.e /1000;
        qcal.f = cal.f /1000;
        qcal.s = cal.s /1000;
	if(n != 7){
	    fprintf(stderr, "Warning: " POINTERCAL " is unknown format.\n");
	}else{
	    cal.ok = 1;
	}
	fclose(pcal);
    }


    console_fd = open("/dev/fb0", O_RDWR, 0);
    if ( console_fd < 0 ) {
    	return;
    }

    if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) {
        printf("error");
	return;
    }

    if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) {
        printf("error");
        return;
    }

    mapped_offset = (((long)finfo.smem_start) -
	             (((long)finfo.smem_start)&~(PAGE_SIZE-1)));
    mapped_memlen = finfo.smem_len+mapped_offset;
    mapped_mem = (short*)mmap(NULL, mapped_memlen,PROT_READ|PROT_WRITE, MAP_SHARED, console_fd, 0);
    mapped_mem_start = mapped_mem;
    mapped_mem_end = mapped_mem + finfo.smem_len;


}

// mouse


/*
	キー情報格納用領域をヌルクリア
*/
void	infoarea_init( void )
{
	metaflags = 0;
	memset( keys, 0, sizeof(keys) );
	memset( metas, 0, sizeof(metas) );
	memset( keymap, 0, sizeof(keymap) );
}


/*
	与えられた文字列が、どの meta-key に一致するかを調べ、
	metaflags 設定値を得る(bit単位のフラグ)

	ret	== 0 : meta-key ではない
		!= 0 : meta-key である。値は bit単位のフラグ値。
*/
int	check_meta( const char *str )
{
	int	i;
	int	flags = 0;

	for( i = 0; i < sizeof(metas_str)/sizeof(metas_str[0]); i++ ) {
		if ( strcasecmp( str, metas_str[i] ) == 0 ) {
			flags = 1 << i;
		}
	}

	return( flags );
}


/*
	設定ファイルから、キーマッピングを読み込む処理

	ret	RETOUR_OK	正常終了(キーマップファイルの中身はともかく)
		RETOUR_ERROR	異常終了(キーマップファイルが開けない)
*/
int	read_key_mapping( char *map_file )
{
	int		flags;
	int		rcnt;
	unsigned int	id;
	long		keycode;
	FILE		*in_file;
	char		line[80];
	char		keyname[80];
	char		flagstr[80];


	// 変数クリア
	infoarea_init();
	memset( line, 0, sizeof(line) );

	// 定義ファイルを開く
	if ( NULL == (in_file = fopen( map_file, "r" )) ) {
		return( RETOUR_ERROR );
	}

	// 定義ファイルを1行ずつ読みながら設定
	while ( ! feof(in_file) ) {

		// 1行読み込む (line byte以上は不許可)
		if ( NULL != fgets(line, sizeof(line)-1, in_file) ) {

			// 行頭が # の行はコメント行として無視する。
			if ( line[0] == '#' ) continue;

			// meta-key 定義行のつもりで読み込んでみる
			rcnt = sscanf(line, "%s %lx", keyname, &id );

			// 先頭の項目がよめない場合は無視して次の行へ(空行など)
			if ( rcnt < 1 ) continue;

			// この行が meta-key 定義行であれば、読み取って metas に設定する。
			if ( (flags = check_meta( keyname )) != 0 ) {
				if ( (rcnt == 2) && (id < 128) ) metas[ id ] = flags;
				continue;
			}

			// その他のパラメータ指定
			if ( strcasecmp( keyname, "keyrep_first" ) == 0 ) {
				keyrep_first = id & 0x7f;
				continue;
			}

			if ( strcasecmp( keyname, "keyrep_next" ) == 0 ) {
				keyrep_next = id & 0x7f;
				continue;
			}

			// 先頭項目が２文字で 16進数文字列でなければ抜ける。
			if ( (strlen(keyname) != 2) || (! isxdigit(keyname[0])) || (! isxdigit(keyname[1])) ) {
				continue; 
			}

			// キー設定行として下記フォーマットで読み取る、
			rcnt = sscanf( line, "%x %s %s %lx", &id, keyname, flagstr, &keycode );

			// 4項目読めなければだめ
			if ( rcnt < 4 ) continue;

			// 範囲チェック
			if ( id > 127 ) continue;

			// フラグは S, C, F, M, N の５文字の組合せから成る。 ex. SCF
			flags = 0;
			if ( strchr( flagstr, 'S' ) != NULL ) flags |= MYFLG_SHIFT;
			if ( strchr( flagstr, 'C' ) != NULL ) flags |= MYFLG_CTRL;
			if ( strchr( flagstr, 'F' ) != NULL ) flags |= MYFLG_FN;
			if ( strchr( flagstr, 'M' ) != NULL ) flags |= MYFLG_CMD;

			keymap[flags][id].keyname	= strdup(keyname);
			keymap[flags][id].keycode	= keycode;
		}
        }

	fclose( in_file );

	return( RETOUR_OK );
}


/*
	RTS ラインを下げて、上げる。
	(palm用 stowaway keyboard のスリープを解除するための処理)
*/
void	rts_down_up( int fd )
{
	int line;

	ioctl (fd, TIOCMGET, &line);
	line &= ~TIOCM_RTS;
	ioctl (fd, TIOCMSET, &line);

	if ( infoflag ) printf( "RTS set to LOW\n" );

	usleep(1000);

	ioctl (fd, TIOCMGET, &line);
	line |= TIOCM_RTS;
	ioctl (fd, TIOCMSET, &line);

	if ( infoflag ) printf( "RTS set to HIGH\n" );
}


/*
	指定されたシリアルポートの排他オープン処理

	in	char	*ser_device	シリアルデバイス指定

	ret	RETOUR_OK	正常
		RETOUR_ERROR	オープン失敗 or 排他ロック失敗 or パラメータ設定失敗

	※グローバル変数 fdd が -1 以外であればオープンされている。
	※ directflag を参照してモードを変えている。
*/
int	init_ser( char *ser_device )
{
	// ser_device のオープン
	if ( (fds = open(ser_device, O_RDWR | O_NOCTTY, 0)) == -1 ) {
		printf( "Error opening serial device !\n" );
		return( RETOUR_ERROR );
	}

	// 他につかまれないよう排他ロックする
	if ( flock( fds, LOCK_EX | LOCK_NB ) == -1 ) {
		return( RETOUR_ERROR );
	}

	// パラメータの設定
	if ( set_ser_param(fds) == RETOUR_ERROR ) {
		printf( "Couldn't set serial parameters !\n" );
		return( RETOUR_ERROR );
	}else{
		return( RETOUR_OK );
	}
}


/*
	シリアルポートのスピードその他の設定 (9600bps 固定)
	※ directflag を参照してモードを変えている。
*/
int	set_ser_param( int fd )
{
	int		line;
	struct termio	sgtty;

	if (ioctl(fd, TCGETA, &sgtty) < 0) {
		printf( "can't TCGETA\n" );
		return( RETOUR_ERROR );
	}

	sgtty.c_iflag		=  (IMAXBEL | IGNBRK);
	sgtty.c_oflag		=  0;
	sgtty.c_lflag		=  0;
	sgtty.c_cflag		=  (CLOCAL | HUPCL | B9600 | CS8 | CREAD);
	sgtty.c_cflag		&= ~(PARENB | PARODD);
	sgtty.c_cc[VTIME]	=  1;		/* タイムアウトは 0.1 s	*/
	sgtty.c_cc[VMIN]	=  0;		/* １文字受けるまでブロックする */

	if ( ioctl(fd, TCSETA, &sgtty) < 0 ) {
		printf( "can't TCSETA\n" );
		return( RETOUR_ERROR );
	}

	ioctl( fd, TIOCMGET, &line );
	line |= TIOCM_DTR;
	ioctl( fd, TIOCMSET, &line );

	if ( infoflag ) printf( "DTR set to HIGH\n" );

	sleep( 1 );
	rts_down_up( fd );	// stowaway keyboard enable
	flush_ser( fd );

	return( RETOUR_OK );
}


/*
	指定ハンドルのフラッシュ操作
*/
void	flush_ser( int fd )
{
	ioctl( fd, TCFLSH, 0 );
}


/*
	1文字入力関数

	この中でオートリピート処理も行っている。
*/
unsigned char	get_1_char( void )
{
	unsigned char	recv_char;
	int		r_code;
	static int	timeout = RTS_TIMEOUT;

	for(;;) {
		/* wait for a char to arrive */
		r_code = read( fds, &recv_char, 1 );

		if ( r_code > 0 ) break;		// キーが押された/離された場合はループを抜ける

		// 受信せずに抜けてきた場合、0.1 s 経過している。

		// キーリピート処理 (通常モード時のみ有効)
		if ( lastkeycode > 0 ) {	// 最後に押されたキーが有効で、
			keyrepeat --;			// キーリピート待ちを越えたらキーコードを送信

			if ( keyrepeat <= 0 ) {
				onekey( lastkeycode, fdd );
				keyrepeat = keyrep_next;
			}
		}

		// 何の操作もされない場合の、RTS 下げ上げ処理 (1分程度放置されたら)
		timeout --;
		if ( timeout <= 0 ) {
			rts_down_up( fds );	// stowaway keyboard enable
			timeout = RTS_TIMEOUT;
		}
	}

	return( recv_char );
}


// Control-C シグナルハンドラ
void	sig_handler( int status )
{
	printf( "SIGNAL(%d) を受けたのでポートを閉じて終了します。\n", status );
	exit( 1 );
}


/*
	プロセス終了時の後始末
*/
void	close_all( void )
{
	int	i;
	long	keycode;

	// open 済のハンドルを閉じて終了。

	// シリアルポート
	if ( fds != -1 ) {
		close( fds );
		fds = -1;
	}

	// デバイスドライバ
	if ( fdd != -1 ) {
		// 念のために、全てのキーを離す

		for( i = 0; i < 127; i++ ) {
			if ( keys[i] != 0 ) {
				keycode = keymap[0][i].keycode & 0x2a000000;
				if ( keycode != 0 ) onekey( keycode, fdd );
			}
		}

		close( fdd );
		fdd = -1;
	}
}


/*
	使用方法説明表示
*/
void	usage( int status )
{
	if ( status != 0 ) {
		printf( "-h for more information.\n" );
	}else{
		printf( "Usage: %s [OPTION]\n", program_name );

		printf(
			"-p : serial port device name (defalt: /dev/ttyS0)\n"
			"-k : vnc kbdsim module use\n"
			"-i : debug info print\n"
			"-d : direct mode\n"
			"-b : background daemon\n"
			"-v : print version\n"
			"-h : display this message\n"
			"-m : key mapping file name\n"
			"     default: /opt/QtPalmtop/etc/ser_code_ksim.ini (or ser_code_direct.ini)\n"
		);
	}

	exit( status );
}


/*
	プログラム・バージョン表示
*/
void	printversion( void )
{
	printf( "%s version %s\n", program_name, VERSION );
	exit( 0 );
}


/*
	キーマップ・テーブルを表示
*/
void	printinfo( void )
{
	int	i,j;

	for ( j = 0; j < 127; j++ ) {
		for ( i = 0; i < 15; i++ ) {
			if ( keymap[i][j].keycode != 0 ) {
				printf( "%02x: %02x : [%s], (%08lx)\n",
					i, 
					j, 
					keymap[i][j].keyname, 
					keymap[i][j].keycode
				 );
			}
		}
	}

	for ( i = 0; i < 128; i++ ) {
		if ( metas[i] != 0 ) {
			printf( "metas[%02x] = %02x\n", i, metas[i] );
		}
	}
}


/*
	設定ファイルに基づいて、キー入力処理を行うメイン
*/
int	main( int argc, char **argv )
{
	unsigned char	rawcode;
	unsigned char	lastrawcode = 0;	// 最後にキーボードから送られてきたコード

	int		daemonflag = 0;
	int		mousemode = 0;
	int		xmode = 0;
	int		pressflag;
	int		meta;
	int		scancode;
	long		keycode;
	char		*keyname;
        int		mousecode = 0;
        int		mouse_x = 0;
        int		mouse_y = 0;
        int		mouse_x_dif = 0;
        int		mouse_y_dif = 0;
        int		mouse_x_sgn = 0;
        int		mouse_y_sgn = 0;
        int		mouse_x_of = 0;
        int		mouse_y_of = 0;
        int		mouse_mb = 0;
        int		mouse_lb = 0;
        int		mouse_rb = 0;
        int		raw_x; 
        int		raw_y; 

	// 終了時に、正しくオープン済ハンドルを閉じるため
	if ( atexit( close_all ) != 0 ) {
		usage( 2 );
	}

	// 起動された自分自身の名前を保存する
	program_name = basename( argv[0] );


	// 引数を解析して、各種変数を設定する
	{
		int	i;
		int	j;
		int	k;

		for( i = 1; i < argc; i++ ) {
			if ( argv[i][0] != '-' ) {
				usage( 1 );
			}else{
				k = i;
				for( j = 1; j < strlen(argv[k]); j++ ) {
					switch( argv[k][j] ) {
					case 'p':
						if ( ++i < argc ) serialdevice = argv[i]; else usage(1);
						break;
					case 'm':
						if ( ++i < argc ) keymapfile = argv[i]; else usage(1);
						break;
					case 'k': vncflag = 1; break;
					case 'i': infoflag = 1;	break;
					case 'd': directflag = 1; break;
					case 'b': daemonflag = 1; break;
					case 'M': mousemode = 1; break;
					case 'x': xmode = 1; break;
					case 'v': printversion();
					case 'h': usage( 0 );
					default:  usage( 1 );
					}
				}
			}
		}
	}

	// directモードか通常モードかでデフォルトの設定ファイルを変更する
	if ( keymapfile == NULL ) {
		keymapfile = (directflag) ? keymapfile_d : keymapfile_n;
	}

	// -i フラグがセットされている場合、情報を表示する。
	if ( infoflag ) {
		printf( "port = [%s]\nmap  = [%s]\n", serialdevice, keymapfile );
	}

	// キー定義ファイルを読み込む。
	if ( read_key_mapping( keymapfile ) !=  RETOUR_OK ) {
		printf( "Key map file is not found\n" );
//		exit( 1 );
	}

	// -i フラグがセットされている場合、情報を表示。
	if ( infoflag ) {
		printinfo();
	}

	// kill 時にオープン済ポートを閉じるためシグナルハンドラを設定
	signal( SIGINT,  &sig_handler );
	signal( SIGTERM, &sig_handler );
	signal( SIGHUP,  &sig_handler );

	// vncflag の状態により、/dev/kbdsim か、/dev/sharp_kbdctl を使うかを決める
	{
		char * kbddrv = (vncflag ? VNCKBDDRV : SHARPKBDDRV);
		if ( (fdd = open( kbddrv, O_RDWR)) < 0 ) {
			printf( "Error opening %s device !\n", kbddrv );
			exit( 1 );
		}
	}

//mouse
loadConfig();
//


	// シリアルポートのオープン
	if ( init_ser( serialdevice ) != RETOUR_OK ) {
		exit( 1 );
	}

	if ( infoflag ) {
		printf( "fds = %d, fdd = %d\n", fds, fdd );
	}

	// daemon化
	if ( daemonflag ) {
		infoflag = 0;
		daemon( 0, 0 );
	}

	for(;;) {

		// 1文字 キー入力処理
		rawcode = get_1_char();

  if (mousemode ==0 ){
		if ( infoflag ) {
			printf( "raw data = %02x\n", (int)rawcode );
		}

		// スキャンコード部のみ取り出す。
		scancode = rawcode & 0x7f;

		// 最上位ビットが 1 ならキーが離された, 0 ならキーが押された
		keys[ scancode ] = pressflag = (rawcode & (1 << 7)) ? 0 : 1;

		// 全てのキーが離された場合の処置
		// (本当は keys[] を見て、すべての解放処理が必要だが実害少ないので割愛)
		if ( (! pressflag) && (rawcode == lastrawcode) ) {
			metaflags   = 0;		// 全てのメタキーを離す
			lastkeycode = -1;		// キーリピートの停止
		}
		lastrawcode = rawcode;

		if ( directflag ) {
			// ダイレクトモードでは、normal key のコード下位1byteをそのまま用いる。
			keycode = keymap[0][scancode].keycode;
			keyname = keymap[0][scancode].keyname;
		}else{
			// Shift, Ctrl, Fn, Cmd などの metaキーについて内部フラグを設定する。

			// meta-key ならば、フラグを立てるだけ
			meta = metas[ scancode ];

			if ( meta != 0 ) {
				if ( pressflag ) {
					metaflags |= meta;
				}else{
					metaflags &= ~meta;
				}
				continue;
			}

			// ここより下は、通常キーの処理

			// 現在の Shift, Ctrl, Fn, Cmd に対応した 値を作成。
			meta = (metaflags & 0x0f) | (metaflags >> 4);

			keycode = keymap[meta][scancode].keycode;
			keyname = keymap[meta][scancode].keyname;
		}

		// keycode が 0 の場合は、対応するキーが無いので何もしない。

		if ( keycode == 0 ) {
			continue;
		}

		if ( directflag ) {
			if ( pressflag ) {
				keycode &= 0x010000ff;
			}else{
				keycode &= 0x020000ff;
			}
			onekey( keycode, fdd );
		}else{
			if ( pressflag ) {
				onekey( keycode, fdd );

				lastkeycode = keycode;		// キーリピートのため
				keyrepeat   = keyrep_first;
			}else{
				lastkeycode = -1;		// キーリピートの停止のため
			}
		}
  }else {
    switch (mousecode){
    case 0:
      mouse_y_of = (rawcode >> 7) & 0x01;
      mouse_x_of = (rawcode >> 6) & 0x01;
      mouse_y_sgn = (rawcode >> 5) & 0x01;
      mouse_x_sgn = (rawcode >> 4) & 0x01;
      mouse_mb = (rawcode >> 2) & 0x01;
      mouse_rb = (rawcode >> 1) & 0x01;
      mouse_lb = (rawcode >> 0) & 0x01;
      mousecode = 1;
      break;
    case 1:
      mouse_x_dif = rawcode;
      mousecode = 2;
      break;
    case 2:
      mouse_y_dif = rawcode;

      mouse_x = mouse_x + mouse_x_dif;
      mouse_y = mouse_y + mouse_y_dif;
      if (mouse_x_sgn)
        mouse_x -= 256;
      if (mouse_y_sgn)
        mouse_y -= 256;
      if(mouse_x > 639)
        mouse_x = 640;
      if(mouse_y > 479)
        mouse_y = 479;
      if(mouse_x < 0)
        mouse_x = 0;
      if(mouse_y < 0)
        mouse_y = 0;


    printf(" %03d %03d %03d ",mouse_x,mouse_y,mouse_lb);
    fflush(stdout);
            raw_y = (mouse_y * qcal.s * qcal.e - qcal.c * qcal.e) /(qcal.e * qcal.a);
            raw_x = (mouse_x * qcal.s * qcal.a - qcal.a * qcal.f) /(qcal.e * qcal.a);
    fp=fopen("/dev/ts", "w");
    if(xmode ==0){
      fprintf(fp, "%d %d %d 0\n",mouse_lb*500,raw_y,raw_x);
      printf("%03d %03d %03d 0\r",mouse_lb*500,raw_y,raw_x);
    }else{
      fprintf(fp, "%d %d %d 0\n",(mouse_lb+1)*500,raw_x,480-raw_y);
      printf("%03d %03d %03d 0\r",(mouse_lb+1)*500,raw_x,480-raw_y);
    }
    fclose(fp);
    if(xmode ==0)
      paint(mouse_y,mouse_x);
      mousecode = 0;
      break;
    default:
    }
  }
	}

	exit( 0 );		// 必要なポートのクローズは、atexit ルーチンで行う。
}


/*
	VNCドライバ用のキー入力処理
*/
void	onekey_v( int c, int fd, int pressflag )
{
	unsigned char buf[2];

	buf[0] = c; buf[1] = pressflag;
	write( fd, buf, 2 );
}


/*
	Sharp KeyCtrlドライバ用のキー入力処理
*/
void	onekey_s( long c, int fd )
{
	ioctl( fd, SHARP_KBDCTL_SENDKEY, c );
}

/*
	キー入力処理(共通)
*/
int	onekey( long c, int fdd )
{
	if ( vncflag ) {
		if ( c & 0x10000000 ) onekey_v( (c >> 16) & 0xff, fdd, 1 );
		if ( c & 0x04000000 ) onekey_v( (c >> 8)  & 0xff, fdd, 1 );
		if ( c & 0x01000000 ) onekey_v( (c)       & 0xff, fdd, 1 );

		if ( c & 0x02000000 ) onekey_v( (c)       & 0xff, fdd, 0 );
		if ( c & 0x08000000 ) onekey_v( (c >> 8)  & 0xff, fdd, 0 );
		if ( c & 0x20000000 ) onekey_v( (c >> 16) & 0xff, fdd, 0 );
	}else{
		onekey_s( c, fdd );
	}
}


