On Tue, 2006-03-07 at 10:05 +0800, zhang zhaowei wrote:
> my touch screen is sumsung, but I use the drive for ipaq touch screen,
> this touch screen use usb interface and device
> name /dev/input/event0 . If you code can't work with it, I think I can
> get your code to work with it!

I used a totally different touch screen, it was 1024x768 pixels for a
15" LCD. I doubt that they use the same code. I will however pass along
the calibration code I created for it.

> and do you know the calibate data format of directfb,  can you give me
> some useful infomation?

DirecFB does not do any calibration and doesn't store anything. You need
to have an input driver or a directFB driver. I "wrote" the gunze driver
for DirectFB by taking the X Driver they supplied and transfering the
information over to how DirectFB does things. Some stuff stayed, some
changed. The touch screen I had stored its calibration data in a file,
didn't matter which one. The MuTouch however stores calibration data on
the controller... They are all different.


I haven't read the document you sent, however thank-you for sending it.

-- 
Nathanael D. Noblet
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <errno.h>
#include <fcntl.h>
#include <termios.h>

#include <math.h>
#include <directfb.h>

static IDirectFB *dfb = NULL;
static IDirectFBSurface *primary = NULL;
static IDirectFBEventBuffer *buffer = NULL;
static IDirectFBInputDevice *mouse = NULL;
static IDirectFBFont *gara_reg_12 = NULL;

static int screen_width  = 0;
static int screen_height = 0;

#define DFBCHECK(x...)                                       \
{                                                            \
   DFBResult err = x;                                        \
                                                             \
   if (err != DFB_OK)                                        \
   {                                                         \
      fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \
      DirectFBErrorFatal( #x, err );                         \
   }                                                         \
}


#define BUFFER_SIZE         64          /* size of reception buffer */
#define GUNZE_MAXPHYSCOORD  1023
#define GUNZE_MAXCOORD      (64*1024-1) /* oversampled, synthetic value */
#define FLAG_TAPPING        1
#define FLAG_WAS_UP         2
#define BAUDRATE            B9600
static const char *default_options[] =
{
	"BaudRate", "9600",
	"StopBits", "1",
	"DataBits", "8",
	"Parity", "None",
	"Vmin", "1",
	"Vtime", "10",
	"FlowControl", "None",
	NULL
};

typedef struct 
{
    char	*gunDevice;	/* device file name */
    int		flags;		/* various flags */
    int		gunType;        /* TYPE_SERIAL, etc */
    int		gunBaud;	/* 9600 or 19200 */
    int		gunDlen;	/* data length (3 or 11) */
    int		gunAvgX;	/* previous X position */
    int		gunAvgY;	/* previous Y position */
    int		gunSmooth;	/* how smooth the motion is */
    int		gunTapping;	/* move-and-tap (or press-only) */
    int		gunPrevButton;	/* previous button state */
    int		gunBytes;	/* number of bytes read */
    unsigned char gunData[16];	/* data read on the device */
    struct timeval *gunTv;      /* release time */
    char	*gunConfig;     /* filename for configuration */
    int     fd;
} GunzeDevice, *GunzeDevicePtr;

enum devicetypeitems {
    TYPE_UNKNOWN = 0,
    TYPE_SERIAL = 1,
    TYPE_PS2,
    TYPE_USB
};

#define GUNZE_SERIAL_DLEN 11
#define GUNZE_PS2_DLEN     3

#define GUNZE_SECTION_NAME    "GunzeTS"
#define GUNZE_DEFAULT_CFGFILE "/etc/gunzets.calib"


#define SYSCALL(call) while(((call) == -1) && (errno == EINTR))
struct axis_coord {
    int x;
    int y;
} coords;

static void GetCalibData(GunzeDevicePtr priv)
{
    unsigned char *pkt = priv->gunData;
    int len, loop;
    int x, y;
    coords.x = 0;
    coords.y = 0;
    unsigned char buffer[BUFFER_SIZE];

    while ((len = read( priv->fd, buffer, BUFFER_SIZE)) >= 0 || errno == EINTR)
    {
        if (len <= 0) 
        {
            fprintf(stderr,"error reading Gunze touch screen device %d %d\n",errno,priv->fd);
            perror(NULL);
            return;
        }

        for(loop=0; loop<len; loop++) 
        {
            // if first byte, ensure that the packet is syncronized
            if (priv->gunBytes == 0) 
            {
                int error  = 0;
                if (priv->gunDlen == GUNZE_SERIAL_DLEN) 
                {
                    // First byte is 'R' (0x52) or 'T' (0x54)
                    if ((buffer[loop] != 'R') && (buffer[loop] != 'T'))
                        error = 1;
                }
                else // PS/2 
                {
                    if ( !(buffer[loop] & 0x80) || (len > loop+1 && !(buffer[loop+1] & 0x80)) || (len > loop+2 && (buffer[loop+2]  & 0x80)))
                        error = 1;
                }
                if (error) 
                {
                    fprintf(stderr,"GunzeReadInput: bad first byte 0x%x %c\n",buffer[loop],buffer[loop]);
                    continue;
                }
            }

            pkt[priv->gunBytes++] = buffer[loop];

            // Hack: sometimes a serial packet gets corrupted. If so, drop it
            if (buffer[loop] == 0x0d && priv->gunBytes != priv->gunDlen && priv->gunDlen == GUNZE_SERIAL_DLEN) 
            {
                pkt[priv->gunBytes-1] = '\0';
                fprintf(stderr,"Bad packet \"%s\", dropping it\n", pkt);
                priv->gunBytes = 0; // for next time
                continue;
            }

            // if whole packet collected, decode it
            if (priv->gunBytes == priv->gunDlen)
            {
                priv->gunBytes = 0; // for next time
                if (priv->gunDlen == GUNZE_SERIAL_DLEN) 
                {
                    x = atoi((char *)pkt+1);
                    y = atoi((char *)pkt+6);
                }

                if (x>1023 || x<0 || y>1023 || y<0) 
                {
                    fprintf(stderr,"Bad packet \"%s\" -> %i,%i\n", pkt, x, y);
                    priv->gunBytes = 0; // for next time 
                    continue;
                }

                if (pkt[0] == 'R')
                {
                    printf ("Returning %c %d %d\n",pkt[0],x,y);
                    coords.x = x;
                    coords.y = y;
                    return;
                }
                printf ("Continuing %c %d %d\n",pkt[0],x,y);

                priv->gunAvgX = x;
                priv->gunAvgY = y;
            }
        }
    }
}


static int GunzeOpen(GunzeDevicePtr priv)
{
    struct termios  newtio,termios_tty;
    int err;

    // Is it a serial port or something else? 
    priv->gunType = TYPE_SERIAL;
    priv->gunDlen = GUNZE_SERIAL_DLEN;

    SYSCALL(priv->fd = open(priv->gunDevice, O_RDWR | O_NOCTTY));
    if (priv->fd == -1) 
    {
        fprintf(stderr,"Error opening device %s\n",priv->gunDevice);
        return -1;
    }

    SYSCALL(err = tcgetattr(priv->fd, &newtio));

    if (err == -1) {
        fprintf(stderr,"Gunze touch screen tcgetattr\n");
        return -1;
    }

    memset(&newtio,0, sizeof(newtio)); /* clear struct for new port settings */

/*
    BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
    CRTSCTS : output hardware flow control (only used if the cable has
            all necessary lines. See sect. 7 of Serial-HOWTO)
    CS8     : 8n1 (8bit,no parity,1 stopbit)
    CLOCAL  : local connection, no modem contol
    CREAD   : enable receiving characters
*/
    newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
/*
    IGNPAR  : ignore bytes with parity errors
    ICRNL   : map CR to NL (otherwise a CR input on the other computer will not terminate input)
    otherwise make device raw (no other input processing)
*/
    newtio.c_iflag = IGNPAR | ICRNL;
//  Raw output
    newtio.c_oflag = 0;
/*
    ICANON  : enable canonical input
    disable all echo functionality, and don't send signals to calling program
*/
    newtio.c_lflag = ICANON;

/*
    initialize all control characters 
    default values can be found in /usr/include/termios.h, and are given
    in the comments, but we don't need them here
*/
    newtio.c_cc[VINTR]    = 0;     /* Ctrl-c */ 
    newtio.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
    newtio.c_cc[VERASE]   = 0;     /* del */
    newtio.c_cc[VKILL]    = 0;     /* @ */
    newtio.c_cc[VEOF]     = 4;     /* Ctrl-d */
    newtio.c_cc[VTIME]    = 0;     /* inter-character timer unused */
    newtio.c_cc[VMIN]     = 1;     /* blocking read until 1 character arrives */
    newtio.c_cc[VSWTC]    = 0;     /* '\0' */
    newtio.c_cc[VSTART]   = 0;     /* Ctrl-q */ 
    newtio.c_cc[VSTOP]    = 0;     /* Ctrl-s */
    newtio.c_cc[VSUSP]    = 0;     /* Ctrl-z */
    newtio.c_cc[VEOL]     = 0;     /* '\0' */
    newtio.c_cc[VREPRINT] = 0;     /* Ctrl-r */
    newtio.c_cc[VDISCARD] = 0;     /* Ctrl-u */
    newtio.c_cc[VWERASE]  = 0;     /* Ctrl-w */
    newtio.c_cc[VLNEXT]   = 0;     /* Ctrl-v */
    newtio.c_cc[VEOL2]    = 0;     /* '\0' */

    //now clean the modem line and activate the settings for the port

    tcflush(priv->fd, TCIFLUSH);
    err = tcsetattr(priv->fd, TCSANOW, &newtio);
    if (err == -1) {
        fprintf(stderr,"Gunze touch screen tcsetattr TCSANOW\n");
        return -1;
    }

/*
    DBG(2, fprintf(stderr,"%s opened as fd %d\n", priv->gunDevice, priv->fd));
    DBG(1, fprintf(stderr,"initializing Gunze touch screen\n"));
*/
    // Hmm... close it, so it doens't say anything before we're ready
    // FIX ME

    // Clear any pending input
    tcflush(priv->fd, TCIFLUSH);
    // FIX ME: is there something to write-and-read here?

    return 0;
}

static GunzeDevicePtr GunzeAllocate()
{
    GunzeDevicePtr priv = (GunzeDevicePtr)malloc(sizeof(GunzeDevice));

    priv->gunDevice = "/dev/ttyS0";         /* device file name */
    priv->gunConfig = GUNZE_DEFAULT_CFGFILE;
    priv->gunDlen = 0;            /* unknown */
    priv->gunType = TYPE_SERIAL;
    priv->gunBaud = 9600;
    priv->gunTapping = 0;         /* default */
    priv->gunSmooth = 9;          /* quite smooth */
    priv->gunAvgX = -1;           /* previous (avg) X position */
    priv->gunAvgY = -1;           /* previous (avg) Y position */
    priv->gunPrevButton = 0;      /* previous buttons state */
    priv->flags = FLAG_WAS_UP;    /* first event is button-down */
    priv->gunBytes = 0;           /* number of bytes read */
    priv->fd = -1;

    return priv;
}

//-----------------------------------------------------------------------------------------------
void SetupFonts()
{
    DFBFontDescription font_dsc;
    font_dsc.flags = DFDESC_HEIGHT;
    font_dsc.height=25;
    DFBCHECK(dfb->CreateFont(dfb,"/usr/local/gnatfb/GARA.TTF",&font_dsc,&gara_reg_12));
}

//-----------------------------------------------------------------------------------------------
void ReleaseFonts()
{
    DFBCHECK(gara_reg_12->Release(gara_reg_12));
}

void DrawRects(char *input)
{
    int wid = screen_width; //[winfo screenwidth .]
    int hei = screen_height; //[winfo screenheight .]

    int x = screen_width/8;//[expr $wid/8]
    int y = screen_height/8;//[expr $hei/8]
    int LX = wid-x;//[expr $wid - $x]
    int LY = hei-y;//[expr $hei - $y]
    int hx = screen_width/2;//[expr $wid/2]
    int hy = screen_height/2;//[expr $hei/2]
    int cwid = 2*x;//[expr 2*$x]
    int chei = 2*y;//[expr 2*$y]

    DFBCHECK(primary->Clear(primary,55,18,5,0));
    DFBCHECK(primary->Flip(primary,NULL,DSFLIP_NONE));
    DFBCHECK(primary->Clear(primary,55,18,5,0));
    DFBCHECK(primary->SetFont(primary,gara_reg_12));

    DFBCHECK(primary->SetColor(primary,0xFF,0xEF,0xB5,0));
    //Bottom Rectangle
    DFBCHECK(primary->DrawRectangle(primary,50,hei-chei,cwid,chei));
    // Top Rectangle
    DFBCHECK(primary->DrawRectangle(primary,wid-cwid-50,0,cwid,chei));

    // Draw Two Cross Hairs
    DFBCHECK(primary->DrawLine(primary,50,hei-chei+50,150,hei-chei+50));
    DFBCHECK(primary->DrawLine(primary,100,hei-chei,100,hei-chei+100));

    DFBCHECK(primary->DrawLine(primary,wid-(cwid/2), 0 ,wid-(cwid/2), 100));
    DFBCHECK(primary->DrawLine(primary,wid-(cwid/2)-50, 50 ,wid-(cwid/2)+50, 50));
    DFBCHECK(primary->DrawString(primary,input,-1,screen_width/2,screen_height/2,DSTF_CENTER));
    DFBCHECK(primary->Flip(primary,NULL,DSFLIP_NONE));
    sleep(1);
}

//-----------------------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
    int quit = 0;

    DFBSurfaceDescription dsc;
    DFBCHECK (DirectFBInit (&argc, &argv));
    DFBCHECK (DirectFBCreate (&dfb));

    DFBCHECK (dfb->SetCooperativeLevel (dfb,DFSCL_EXCLUSIVE));// DFSCL_FULLSCREEN));
    DFBCHECK (dfb->SetVideoMode(dfb,1024,768,16));
    dsc.flags = DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT;
    dsc.caps = DSCAPS_PRIMARY | DSCAPS_FLIPPING;
    dsc.width = 1024;
    dsc.height = 768;

    // Surface Creation
    DFBCHECK (dfb->CreateSurface(dfb, &dsc, &primary));
    DFBCHECK (primary->GetSize(primary, &screen_width, &screen_height));
    DFBCHECK (primary->SetBlittingFlags(primary,DSBLIT_BLEND_ALPHACHANNEL));

    // Event Handlers
    DFBCHECK(dfb->CreateInputEventBuffer(dfb,DICAPS_ALL,DFB_FALSE,&buffer));
    //Cursor

    SetupFonts();

    GunzeDevice *priv = GunzeAllocate();
    if(GunzeOpen(priv) != 0){
        fprintf(stderr,"Error Opening device!\n");
        return -1;
    }

    //The offset variables account for window manager borders etc

    //DFBCHECK(primary->DrawLine(primary,wid-cwid-50, 0 ,wid-cwid+50, 50));
    DrawRects("Touch Left Cross");

    GetCalibData(priv);
    int x1 = coords.x;
    int y1 = coords.y;
    DrawRects("Touch Right Cross");

    GetCalibData(priv);
    int x2 = coords.x;
    int y2 = coords.y;

    DrawRects("Done");
    char tmp[100];
    memset(tmp,0,100);
    sprintf(tmp,"X1:%d Y1:%d X2:%d Y2:%d",x1,y1,x2,y2);
    DFBCHECK(primary->DrawString(primary,tmp,-1,screen_width/2,(screen_height/2)-150,DSTF_CENTER));
    DFBCHECK(primary->Flip(primary,NULL,DSFLIP_NONE));
    memset(tmp,0,100);
    sprintf(tmp,"# Calibration coordinates for Gunze Device\n%d %d %d %d",x1,y1,x2,y2);
    int fd = 0;
    SYSCALL(fd = open(priv->gunConfig, O_RDWR | O_TRUNC | O_CREAT));
    SYSCALL(write(fd,tmp,strlen(tmp)));
    close(fd);

    DFBInputEvent event;

    while(!quit)
    {
        buffer->WaitForEvent(buffer);
        while ( buffer->GetEvent(buffer, DFB_EVENT(&event)) == DFB_OK)
        {
            if(event.type == DIET_KEYPRESS)
            {
                if(event.key_id == DIKI_ESCAPE || event.key_id == DIKI_Q)
                {
                    printf("Q||ESC KEY pressed event\n");
                    fflush(NULL);

                    quit = 1;
                }
            }
        }
    }

    close(priv->fd);
    free(priv);

    ReleaseFonts();
    if(mouse != NULL)
        mouse->Release(mouse);

    buffer->Release(buffer);
    primary->Release(primary);
    dfb->Release(dfb);
    return 0;
}
_______________________________________________
directfb-users mailing list
[email protected]
http://mail.directfb.org/cgi-bin/mailman/listinfo/directfb-users

Reply via email to