/* $XConsortium: xf86SpOrb.c blah blah RCS codes go here */ /* * Copyright 1997 by Louis Kruger. * based on the Wacom Tablet driver: xf86Wacom.c * * Information and code on the SpaceOrb's protocol courtesy of Brett Viren, * author of the SpaceOrb Programming Secrets page: * http://bock.physics.sunysb.edu/~bviren/orb/ * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Louis Kruger not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Louis Kruger makes no * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * * LOUIS KRUGER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL LOUIS KRUGER BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * */ /* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86SpOrb.c,v 3.25.2.1 1997/05/12 12:52:28 hohndel Exp $ */ #include "Xos.h" #include #define NEED_EVENTS #include "X.h" #include "Xproto.h" #include "misc.h" #include "inputstr.h" #include "scrnintstr.h" #include "XI.h" #include "XIproto.h" #include "keysym.h" #if defined(sun) && !defined(i386) #define POSIX_TTY #include #include #include #include #include #include "extio.h" #else #include "compiler.h" #include "xf86.h" #include "xf86Procs.h" #include "xf86_OSlib.h" #include "xf86_Config.h" #include "xf86Xinput.h" #include "atKeynames.h" #include "xf86Version.h" #endif #if !defined(sun) || defined(i386) #include "osdep.h" #include "exevents.h" #include "extnsionst.h" #include "extinit.h" #endif /****************************************************************************** * debugging macro *****************************************************************************/ #ifdef DBG #undef DBG #endif #ifdef DEBUG #undef DEBUG #endif static int debug_level = 0; #define DEBUG 1 #if DEBUG #define DBG(lvl, f) {if ((lvl) <= debug_level) f;} #else #define DBG(lvl, f) #endif /****************************************************************************** * SpOrbDeviceRec flags *****************************************************************************/ #define DEVICE_ID(flags) ((flags) & 0x07) #define SPORB_ID 1 #define ABSOLUTE_FLAG 8 #define SORB_BUTTON_SIZE 5 /* The packet size for no motion */ #define SORB_BUTTON_NUMBER 75 /* The flag for a no-motion-packet */ #define SORB_MOTION_SIZE 12 /* The packet size for motion */ #define SORB_MOTION_NUMBER 68 /* The flag for a motion-packet */ #define SORB_GREETING_SIZE 53 /* The packet size for motion */ #define SORB_GREETING_NUMBER 'R' /* The flag for a motion-packet */ /****************************************************************************** * SpOrbCommonRec flags *****************************************************************************/ typedef struct { /* configuration fields */ unsigned char flags; double factorX; double factorY; int offsetX; int offsetY; struct _SpOrbCommonRec *common; /* common info pointer */ /* state fields */ int x; int y; int z; int u; int v; int r; int oldx; int oldy; int oldz; int oldu; int oldv; int oldr; int oldButtons; } SpOrbDeviceRec, *SpOrbDevicePtr; typedef struct _SpOrbCommonRec { char *srbDevice; /* device file name */ LocalDevicePtr *srbDevices; /* array of all devices sharing the same port */ char srbFlags; /* unused */ int srbNumDevices; /* number of devices */ int srbIndex; /* number of bytes read */ int srbPktLength[3]; /* length of a packet */ unsigned char srbData[64]; /* data read on the device */ } SpOrbCommonRec, *SpOrbCommonPtr; /****************************************************************************** * configuration stuff *****************************************************************************/ #define SPORB_SECTION_NAME "SpaceOrb" #define PORT 1 #define DEVICENAME 2 #define THE_MODE 3 #define SUPPRESS 4 #define DEBUG_LEVEL 5 #define HISTORY_SIZE 7 #define ALWAYS_CORE 8 #define AXIS_MAP 9 #define BUTTON_MAP 10 #define XSENSITIVITY 11 #define YSENSITIVITY 12 #define XOFFSET 13 #define YOFFSET 14 #if !defined(sun) || defined(i386) static SymTabRec srbTab[] = { { ENDSUBSECTION, "endsubsection" }, { PORT, "port" }, { DEVICENAME, "devicename" }, { THE_MODE, "mode" }, { SUPPRESS, "suppress" }, { DEBUG_LEVEL, "debuglevel" }, { HISTORY_SIZE, "historysize" }, { ALWAYS_CORE, "alwayscore" }, { AXIS_MAP, "axismap" }, /* { BUTTON_MAP, "buttonmap" }, */ { XSENSITIVITY, "xsensitivity" }, { YSENSITIVITY, "ysensitivity" }, { XOFFSET, "xoffset" }, { YOFFSET, "yoffset" }, { -1, "" } }; #define RELATIVE 1 #define ABSOLUTE 2 static SymTabRec ModeTabRec[] = { { RELATIVE, "relative" }, { ABSOLUTE, "absolute" }, { -1, "" } }; #endif /****************************************************************************** * constant and macros declarations *****************************************************************************/ #define BUFFER_SIZE 256 /* size of reception buffer */ #define XI_SPORB "SpaceOrb" /* X device name for the stylus */ #define MAX_VALUE 1024 /* number of positions */ #define MAXTRY 50 /* max number of try to receive magic number */ #define SYSCALL(call) while(((call) == -1) && (errno == EINTR)) #define COMMAND_SET_MASK 0xc0 #define BAUD_RATE_MASK 0x0a #define PARITY_MASK 0x30 #define DATA_LENGTH_MASK 0x40 #define STOP_BIT_MASK 0x80 #define HEADER_BIT 0x80 #define ZAXIS_SIGN_BIT 0x40 #define ZAXIS_BIT 0x04 #define ZAXIS_BITS 0x7f #define POINTER_BIT 0x20 #define PROXIMITY_BIT 0x40 #define BUTTON_FLAG 0x08 #define BUTTONS_BITS 0x78 #define TILT_SIGN_BIT 0x40 #define TILT_BITS 0x7f #define HANDLE_TILT(comm) ((comm)->srbPktLength == 9) #define mils(res) (res * 1000 / 2.54) /* resolution */ /****************************************************************************** * Function/Macro keys variables *****************************************************************************/ static KeySym SpOrb_map[] = { NoSymbol, /* 0x00 */ 1, 2, 3, 4, 5, 6, 7, }; static int SpOrb_Axis_map[6] = {0, 1, 2, 3, 4, 5}; static int SpOrb_Axis_rev[6] = {0, 0, 0, 0, 0, 0}; /* minKeyCode = 8 because this is the min legal key code */ static KeySymsRec SpOrb_keysyms = { /* map minKeyCode maxKC width */ SpOrb_map, 8, 0x20, 1 }; /****************************************************************************** * external declarations *****************************************************************************/ #if defined(sun) && !defined(i386) #define ENQUEUE suneqEnqueue #else #define ENQUEUE xf86eqEnqueue extern void xf86eqEnqueue( #if NeedFunctionPrototypes xEventPtr /*e*/ #endif ); #endif extern void miPointerDeltaCursor( #if NeedFunctionPrototypes int /*dx*/, int /*dy*/, unsigned long /*time*/ #endif ); #if NeedFunctionPrototypes static LocalDevicePtr xf86srbAllocateSpball(void); #endif #if !defined(sun) || defined(i386) static void SpOrbInvertMap() { int map[6]; int i; for(i=0; i<6; ++i) { map[i]=SpOrb_Axis_map[i]; } for(i=0; i<6; ++i) { SpOrb_Axis_map[map[i]]=i; } } /* *************************************************************************** * * xf86srbConfig -- * Configure the device. * *************************************************************************** */ static Bool xf86srbConfig(LocalDevicePtr *array, int inx, int max, LexPtr val) { LocalDevicePtr dev = array[inx]; SpOrbDevicePtr priv = (SpOrbDevicePtr)(dev->private); SpOrbCommonPtr common = priv->common; int token; int mtoken; int tmp,i; DBG(1, ErrorF("xf86srbConfig\n")); while ((token = xf86GetToken(srbTab)) != ENDSUBSECTION) { switch(token) { case DEVICENAME: if (xf86GetToken(NULL) != STRING) xf86ConfigError("Option string expected"); dev->name = strdup(val->str); if (xf86Verbose) ErrorF("%s SpOrb X device name is %s\n", XCONFIG_GIVEN, dev->name); break; case PORT: if (xf86GetToken(NULL) != STRING) xf86ConfigError("Option string expected"); else { int loop; /* try to find another SpOrb device which share the same port */ for(loop=0; loopdevice_config == xf86srbConfig) && (strcmp(((SpOrbDevicePtr)array[loop]->private)->common->srbDevice, val->str) == 0)) { DBG(2, ErrorF("xf86srbConfig SpOrb port share between" " %s and %s\n", dev->name, array[loop]->name)); xfree(common->srbDevices); xfree(common); common = priv->common = ((SpOrbDevicePtr) array[loop]->private)->common; common->srbNumDevices++; common->srbDevices = (LocalDevicePtr *) xrealloc(common->srbDevices, sizeof(LocalDevicePtr) * common->srbNumDevices); common->srbDevices[common->srbNumDevices - 1] = dev; break; } } if (loop == max) { common->srbDevice = strdup(val->str); if (xf86Verbose) ErrorF("%s SpOrb port is %s\n", XCONFIG_GIVEN, common->srbDevice); } } break; case THE_MODE: mtoken = xf86GetToken(ModeTabRec); if ((mtoken == EOF) || (mtoken == STRING) || (mtoken == NUMBER)) xf86ConfigError("Mode type token expected"); else { switch (mtoken) { case ABSOLUTE: priv->flags = priv->flags | ABSOLUTE_FLAG; break; case RELATIVE: priv->flags = priv->flags & ~ABSOLUTE_FLAG; break; default: xf86ConfigError("Illegal Mode type"); break; } } break; case DEBUG_LEVEL: if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Option number expected"); debug_level = val->num; if (xf86Verbose) { #if DEBUG ErrorF("%s SpOrb debug level sets to %d\n", XCONFIG_GIVEN, debug_level); #else ErrorF("%s SpOrb debug level not sets to %d because" " debugging is not compiled\n", XCONFIG_GIVEN, debug_level); #endif } break; case HISTORY_SIZE: if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Option number expected"); dev->history_size = val->num; if (xf86Verbose) ErrorF("%s SpOrb Motion history size is %d\n", XCONFIG_GIVEN, dev->history_size); break; case ALWAYS_CORE: xf86AlwaysCore(dev, TRUE); if (xf86Verbose) ErrorF("%s SpOrb device always stays core pointer\n", XCONFIG_GIVEN); break; case XSENSITIVITY: if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Option number expected"); priv->factorX = val->realnum; if(xf86Verbose) ErrorF("%s SpOrb X sensitivity set to %f",XCONFIG_GIVEN,priv->factorX); break; case YSENSITIVITY: if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Option number expected"); priv->factorY = val->realnum; if(xf86Verbose) ErrorF("%s SpOrb Y sensitivity set to %f",XCONFIG_GIVEN,priv->factorY); break; case XOFFSET: if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Option number expected"); priv->offsetX = val->num; if(xf86Verbose) ErrorF("%s SpOrb X offset set to %d",XCONFIG_GIVEN,priv->offsetX); break; case YOFFSET: if (xf86GetToken(NULL) != NUMBER) xf86ConfigError("Option number expected"); priv->offsetY = val->num; if(xf86Verbose) ErrorF("%s SpOrb Y offset set to %d",XCONFIG_GIVEN,priv->offsetY); break; case AXIS_MAP: if (xf86GetToken(NULL) != STRING) xf86ConfigError("Option string expected"); if(strlen(val->str) != 6) xf86ConfigError("AxisMap string should be 6 characters"); tmp = 0; for(i=0; i<6; ++i) { if(val->str[i]>='A' && val->str[i]<='Z') SpOrb_Axis_rev[i] = 1; else SpOrb_Axis_rev[i] = 0; switch(val->str[i]) { default: xf86ConfigError("AxisMap string should permute XYZUVR"); case 'x': case 'X': SpOrb_Axis_map[i] = 0; tmp |= 1; break; case 'y': case 'Y': SpOrb_Axis_map[i] = 1; tmp |= 2; break; case 'z': case 'Z': SpOrb_Axis_map[i] = 2; tmp |= 4; break; case 'u': case 'U': SpOrb_Axis_map[i] = 3; tmp |= 8; break; case 'v': case 'V': SpOrb_Axis_map[i] = 4; tmp |= 16; break; case 'r': case 'R': SpOrb_Axis_map[i] = 5; tmp |= 32; break; } } if (tmp != 63) xf86ConfigError("AxisMap string should permute XYZUVR"); SpOrbInvertMap(); if (xf86Verbose) ErrorF("%s SpOrb Axis Map (%d %d %d %d %d %d)\n", XCONFIG_GIVEN, SpOrb_Axis_map[0], SpOrb_Axis_map[1], SpOrb_Axis_map[2], SpOrb_Axis_map[3], SpOrb_Axis_map[4], SpOrb_Axis_map[5]); break; case EOF: FatalError("Unexpected EOF (missing EndSubSection)"); break; default: xf86ConfigError("SpOrb subsection keyword expected"); break; } } DBG(1, ErrorF("xf86srbConfig name=%s\n", common->srbDevice)); return Success; } #endif /* *************************************************************************** * * wait_for_fd -- * * Wait one second that the file descriptor becomes readable. * *************************************************************************** */ static int wait_for_fd(int fd) { int err; fd_set readfds; struct timeval timeout; FD_ZERO(&readfds); FD_SET(fd, &readfds); timeout.tv_sec = 1; timeout.tv_usec = 0; SYSCALL(err = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout)); return err; } static void xf86srbSendEvents(LocalDevicePtr local, int is_ball, int x, int y, int z, int u, int v, int r, int buttons) { SpOrbDevicePtr priv = (SpOrbDevicePtr) local->private; SpOrbCommonPtr common = priv->common; int i; int rx, ry, rz, ru, rv, rr; int valuator[7]; int is_core_pointer, is_absolute; DBG(6, ErrorF("[%s] \tx=%d\ty=%d\tz=%d\tu=%d\tv=%d\tr=%d\tbuttons=%d\n", is_ball ? "ball" : "buttons", x, y, z, u, v, r, buttons)); /* Translate coordinates according to Top and Bottom points * if we are outside the zone do as a ProximityOut event. */ is_absolute = (priv->flags & ABSOLUTE_FLAG); is_core_pointer = xf86IsCorePointer(local->dev); if(is_ball) { /* sets rx and ry according to the mode */ rx = x; ry = y; rz = z; ru = u; rv = v; rr = r; } else { rx = priv->oldx; ry = priv->oldy; rz = priv->oldz; ru = priv->oldu; rv = priv->oldv; rr = priv->oldr; } /* handle axis_map */ valuator[SpOrb_Axis_map[0]] = rx; valuator[SpOrb_Axis_map[1]] = ry; valuator[SpOrb_Axis_map[2]] = rz; valuator[SpOrb_Axis_map[3]] = ru; valuator[SpOrb_Axis_map[4]] = rv; valuator[SpOrb_Axis_map[5]] = rr; for(i=0; i<6; ++i) if(SpOrb_Axis_rev[i]) valuator[i] = -valuator[i]-1; if (is_core_pointer) { valuator[0] *= priv->factorX; valuator[1] *= priv->factorY; } if (is_absolute) { valuator[0] += priv->offsetX; valuator[1] += priv->offsetY; } /* coordonates are ready we can send events */ if(is_ball) { DBG(6, ErrorF("[move] \tx=%d\ty=%d\tz=%d\tu=%d\tv=%d\tr=%d\tbuttons=%d\n", valuator[0], valuator[1], valuator[2], valuator[3], valuator[4], valuator[5], buttons)); xf86PostMotionEvent(local->dev, is_absolute, 0, 6, valuator[0], valuator[1], valuator[2], valuator[3], valuator[4], valuator[5]); priv->oldx = rx; priv->oldy = ry; priv->oldz = rz; priv->oldu = ru; priv->oldv = rv; priv->oldr = rr; } else { for(i=0; i<7; ++i) { if((priv->oldButtons&(1<dev, is_absolute, SpOrb_map[i+1], buttons&(1<oldButtons = buttons; } } /* *************************************************************************** * * xf86srbReadInput -- * Read the new events from the device, and enqueue them. * *************************************************************************** */ static void xf86srbReadInput(LocalDevicePtr local) { SpOrbDevicePtr priv = (SpOrbDevicePtr) local->private; SpOrbCommonPtr common = priv->common; int len, loop, idx; int x=31, y=32, z=33, u=34, v=35, r=36, buttons=37; int *px, *py, *pz, *pbuttons, *pprox; static int packettype; int i; unsigned char buffer[BUFFER_SIZE]; static char SpaceWare[] = "SpaceWare!"; DBG(7, ErrorF("xf86srbReadInput BEGIN device=%s fd=%d\n", common->srbDevice, local->fd)); SYSCALL(len = read(local->fd, buffer, sizeof(buffer))); if (len <= 0) { ErrorF("Error reading SpOrb device : %s\n", strerror(errno)); return; } else { DBG(10, ErrorF("xf86srbReadInput read %d bytes\n", len)); } for(loop=0; loopsrbIndex == 0) { if(buffer[loop] == SORB_BUTTON_NUMBER) { DBG(9, ErrorF("Got Button Packet\n")) packettype = 0; } else if(buffer[loop] == SORB_MOTION_NUMBER) { DBG(9, ErrorF("Got Motion Packet\n")) packettype = 1; } else if(buffer[loop] == SORB_GREETING_NUMBER) { DBG(9, ErrorF("Got Greeting Packet\n")) packettype = 2; } else if(buffer[loop] == '\r') { continue; /* CRs are normal */ } else { /* first byte is not OK */ DBG(6, ErrorF("xf86srbReadInput bad magic number 0x%x\n", buffer[loop])); continue; } } common->srbData[common->srbIndex++] = buffer[loop] & 0177; if(packettype!=0 && packettype!=1 && packettype!=2) { ErrorF("SpOrb: bad bad bad... Processing bad packet %d\n",packettype); continue; } if (common->srbIndex == common->srbPktLength[packettype]) { /* the packet is OK */ /* reset char count for next read */ common->srbIndex = 0; if(xf86Verbose && packettype==2) { char tmpbuffer[64]; strncpy(tmpbuffer,(char *)common->srbData,SORB_GREETING_SIZE); ErrorF("%s SpaceOrb: %s\n",XCONFIG_PROBED,tmpbuffer); continue; } /* decode data */ /* x=, y,z,u,v,r */ switch(packettype) { case 1: /* ball movement */ /* Strip the MSB, which is a parity bit */ for (i = 0; i < 9; ++i) { common->srbData[i+2] &= 0177; /* Make sure everything is 7bit */ common->srbData[i+2] ^= SpaceWare[i]; /* XOR "encryption key" */ } /* Turn chars into 10 bit integers */ x = ((common->srbData[2] & 0177)<<3)|((common->srbData[3] & 0160)>>4); y = ((common->srbData[3] & 0017)<<6)|((common->srbData[4] & 0176)>>1); z = ((common->srbData[4] & 0001)<<9)|((common->srbData[5] & 0177)<<2)|((common->srbData[6] & 0140)>>5); u = ((common->srbData[6] & 0037)<<5)|((common->srbData[7] & 0174)>>2); v = ((common->srbData[7] & 0003)<<8)|((common->srbData[8] & 0177)<<1)|((common->srbData[9] & 0100)>>6); r = ((common->srbData[9] & 0077)<<4)|((common->srbData[10] & 0170)>>3); /* Get the sign right. */ if (x > 511) x -= 1024; if (y > 511) y -= 1024; if (z > 511) z -= 1024; if (u > 511) u -= 1024; if (v > 511) v -= 1024; if (r > 511) r -= 1024; buttons = common->srbData[1]; break; case 0: /* button packet */ DBG(5,ErrorF("Buttons: %d %d %d %d %d\n", common->srbData[0], common->srbData[1], common->srbData[2], common->srbData[3], common->srbData[4])); buttons = common->srbData[2]; x = priv->oldx; y = priv->oldr; z = priv->oldz; u = priv->oldu; v = priv->oldv; r = priv->oldr; break; } for(idx=0; idxsrbNumDevices; idx++) { DBG(7, ErrorF("xf86srbReadInput trying to send to %s\n", common->srbDevices[idx]->name)); xf86srbSendEvents(common->srbDevices[idx], packettype, x, y, z, u, v, r, buttons); } } } DBG(7, ErrorF("xf86srbReadInput END local=0x%x priv=0x%x\n", local, priv)); } /* *************************************************************************** * * xf86srbControlProc -- * *************************************************************************** */ static void xf86srbControlProc(DeviceIntPtr device, PtrCtrl *ctrl) { DBG(2, ErrorF("xf86srbControlProc\n")); } /* *************************************************************************** * * xf86srbOpen -- * *************************************************************************** */ static Bool xf86srbOpen(LocalDevicePtr local) { struct termios termios_tty; struct timeval timeout; char buffer[256]; int err; SpOrbDevicePtr priv = (SpOrbDevicePtr)local->private; SpOrbCommonPtr common = priv->common; int a, b; int loop, idx; float version = 0.0; DBG(1, ErrorF("opening %s\n", common->srbDevice)); SYSCALL(local->fd = open(common->srbDevice, O_RDWR|O_NDELAY|O_NOCTTY)); if (local->fd == -1) { ErrorF("Error opening %s : %s\n", common->srbDevice, strerror(errno)); return !Success; } #ifdef POSIX_TTY SYSCALL(err = tcgetattr(local->fd, &termios_tty)); if (err == -1) { ErrorF("SpOrb tcgetattr error : %s\n", strerror(errno)); return !Success; } termios_tty.c_iflag = IXOFF; termios_tty.c_oflag = 0; termios_tty.c_cflag = B9600|CS8|CREAD|CLOCAL; termios_tty.c_lflag = 0; termios_tty.c_cc[VINTR] = 0; termios_tty.c_cc[VQUIT] = 0; termios_tty.c_cc[VERASE] = 0; termios_tty.c_cc[VEOF] = 0; #ifdef VWERASE termios_tty.c_cc[VWERASE] = 0; #endif #ifdef VREPRINT termios_tty.c_cc[VREPRINT] = 0; #endif termios_tty.c_cc[VKILL] = 0; termios_tty.c_cc[VEOF] = 0; termios_tty.c_cc[VEOL] = 0; #ifdef VEOL2 termios_tty.c_cc[VEOL2] = 0; #endif termios_tty.c_cc[VSUSP] = 0; #ifdef VDSUSP termios_tty.c_cc[VDSUSP] = 0; #endif #ifdef VDISCARD termios_tty.c_cc[VDISCARD] = 0; #endif #ifdef VLNEXT termios_tty.c_cc[VLNEXT] = 0; #endif /* minimum 1 character in one read call and timeout to 100 ms */ termios_tty.c_cc[VMIN] = 1; termios_tty.c_cc[VTIME] = 10; SYSCALL(err = tcsetattr(local->fd, TCSANOW, &termios_tty)); if (err == -1) { ErrorF("SpOrb tcsetattr TCSANOW error : %s\n", strerror(errno)); return !Success; } #else Code for OSs without POSIX tty functions #endif DBG(1, ErrorF("initializing SpaceOrb\n")); #ifdef POSIX_TTY /* send a START just for the case the tablet would have been stopped */ SYSCALL(err = tcflow(local->fd, TCION)); if (err == -1) { ErrorF("SpOrb tcflow TCION error : %s\n", strerror(errno)); } /* flush input and output */ SYSCALL(err = tcflush(local->fd, TCIOFLUSH)); if (err == -1) { ErrorF("SpOrb tcflush TCIOFLUSH error : %s\n", strerror(errno)); } #else Code for OSs without POSIX tty functions #endif /* maybe read greet packet */ DBG(2,ErrorF("SpOrb init err = %d\n",err)) if (err < 0) { SYSCALL(close(local->fd)); return !Success; } if (xf86Verbose) ErrorF("%s SpaceOrb Initialized\n", XCONFIG_PROBED); return Success; } /* *************************************************************************** * * xf86srbOpenDevice -- * Open the physical device and init information structs. * *************************************************************************** */ static int xf86srbOpenDevice(DeviceIntPtr psrb) { LocalDevicePtr local = (LocalDevicePtr)psrb->public.devicePrivate; SpOrbDevicePtr priv = (SpOrbDevicePtr)PRIVATE(psrb); SpOrbCommonPtr common = priv->common; double screenRatio, tabletRatio; int gap; int loop; if (local->fd < 0) { if (xf86srbOpen(local) != Success) { if (local->fd >= 0) { SYSCALL(close(local->fd)); } local->fd = -1; } else { /* report the file descriptor to all devices */ for(loop=0; loopsrbNumDevices; loop++) { common->srbDevices[loop]->fd = local->fd; } } } /* Set the real values */ InitValuatorAxisStruct(psrb, 0, -512, 511, 9600,0,9600); InitValuatorAxisStruct(psrb, 1, -512, 511, 9600,0,9600); InitValuatorAxisStruct(psrb, 2, -512, 511, 9600,0,9600); InitValuatorAxisStruct(psrb, 3, -512, 511, 9600,0,9600); InitValuatorAxisStruct(psrb, 4, -512, 511, 9600,0,9600); InitValuatorAxisStruct(psrb, 5, -512, 511, 9600,0,9600); return (local->fd != -1); } /* *************************************************************************** * * xf86srbClose -- * *************************************************************************** */ static void xf86srbClose(LocalDevicePtr local) { SpOrbDevicePtr priv = (SpOrbDevicePtr)local->private; SpOrbCommonPtr common = priv->common; int loop; int num = 0; for(loop=0; loopsrbNumDevices; loop++) { if (common->srbDevices[loop]->fd >= 0) { num++; } } DBG(4, ErrorF("SpOrb number of open devices = %d\n", num)); if (num == 1) { SYSCALL(close(local->fd)); } local->fd = -1; } /* *************************************************************************** * * xf86srbProc -- * Handle the initialization, etc. of a SpOrb * *************************************************************************** */ static int xf86srbProc(DeviceIntPtr psrb, int what) { CARD8 map[(32 << 4) + 1]; int nbaxes; int nbbuttons; KeySymsRec keysyms; int loop; LocalDevicePtr local = (LocalDevicePtr)psrb->public.devicePrivate; SpOrbDevicePtr priv = (SpOrbDevicePtr)PRIVATE(psrb); DBG(2, ErrorF("BEGIN xf86srbProc dev=0x%x priv=0x%x flags=%d what=%d\n", psrb, priv, priv->flags, what)); switch (what) { case DEVICE_INIT: DBG(1, ErrorF("xf86srbProc psrb=0x%x what=INIT\n", psrb)); nbaxes = 6; /* X, Y, Z, U, V, R */ nbbuttons = 7; for(loop=1; loop<=nbbuttons; loop++) map[loop] = loop; if (InitButtonClassDeviceStruct(psrb, nbbuttons, map) == FALSE) { ErrorF("unable to allocate Button class device\n"); return !Success; } if (InitFocusClassDeviceStruct(psrb) == FALSE) { ErrorF("unable to init Focus class device\n"); return !Success; } if (InitPtrFeedbackClassDeviceStruct(psrb, xf86srbControlProc) == FALSE) { ErrorF("unable to init ptr feedback\n"); return !Success; } if (InitProximityClassDeviceStruct(psrb) == FALSE) { ErrorF("unable to init proximity class device\n"); return !Success; } if (InitKeyClassDeviceStruct(psrb, &SpOrb_keysyms, NULL) == FALSE) { ErrorF("unable to init key class device\n"); return !Success; } if (InitValuatorClassDeviceStruct(psrb, nbaxes, xf86GetMotionEvents, local->history_size, (priv->flags & ABSOLUTE_FLAG) ? Absolute : Relative) == FALSE) { ErrorF("unable to allocate Valuator class device\n"); return !Success; } else { /* allocate the motion history buffer if needed */ xf86MotionHistoryAllocate(local); AssignTypeAndName(psrb, local->atom, local->name); } /* open the device to gather informations */ xf86srbOpenDevice(psrb); break; case DEVICE_ON: DBG(1, ErrorF("xf86srbProc psrb=0x%x what=ON\n", psrb)); if ((local->fd < 0) && (!xf86srbOpenDevice(psrb))) { return !Success; } AddEnabledDevice(local->fd); psrb->public.on = TRUE; break; case DEVICE_OFF: DBG(1, ErrorF("xf86srbProc psrb=0x%x what=%s\n", psrb, (what == DEVICE_CLOSE) ? "CLOSE" : "OFF")); if (local->fd >= 0) RemoveEnabledDevice(local->fd); psrb->public.on = FALSE; break; case DEVICE_CLOSE: DBG(1, ErrorF("xf86srbProc psrb=0x%x what=%s\n", psrb, (what == DEVICE_CLOSE) ? "CLOSE" : "OFF")); xf86srbClose(local); break; default: ErrorF("unsupported mode=%d\n", what); return !Success; break; } DBG(2, ErrorF("END xf86srbProc Success what=%d dev=0x%x priv=0x%x\n", what, psrb, priv)); return Success; } /* *************************************************************************** * * xf86srbChangeControl -- * *************************************************************************** */ static int xf86srbChangeControl(LocalDevicePtr local, xDeviceCtl *control) { return(Success); } /* *************************************************************************** * * xf86srbSwitchMode -- * *************************************************************************** */ static int xf86srbSwitchMode(ClientPtr client, DeviceIntPtr dev, int mode) { LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate; SpOrbDevicePtr priv = (SpOrbDevicePtr)local->private; DBG(3, ErrorF("xf86srbSwitchMode dev=0x%x mode=%d\n", dev, mode)); if (mode == Absolute) { priv->flags = priv->flags | ABSOLUTE_FLAG; } else { if (mode == Relative) { priv->flags = priv->flags & ~ABSOLUTE_FLAG; } else { DBG(1, ErrorF("xf86srbSwitchMode dev=0x%x invalid mode=%d\n", dev, mode)); return BadMatch; } } return Success; } /* *************************************************************************** * * xf86srbAllocate -- * *************************************************************************** */ static LocalDevicePtr xf86srbAllocate(char * name, int flag) { LocalDevicePtr local = (LocalDevicePtr) xalloc(sizeof(LocalDeviceRec)); SpOrbDevicePtr priv = (SpOrbDevicePtr) xalloc(sizeof(SpOrbDeviceRec)); SpOrbCommonPtr common = (SpOrbCommonPtr) xalloc(sizeof(SpOrbCommonRec)); #if defined(sun) && !defined(i386) char *dev_name = (char *) getenv("SpOrb_DEV"); #endif local->name = name; local->flags = 0; /*XI86_NO_OPEN_ON_INIT;*/ #if !defined(sun) || defined(i386) local->device_config = xf86srbConfig; #endif local->device_control = xf86srbProc; local->read_input = xf86srbReadInput; local->control_proc = xf86srbChangeControl; local->close_proc = xf86srbClose; local->switch_mode = xf86srbSwitchMode; local->fd = -1; local->atom = 0; local->dev = NULL; local->private = priv; local->private_flags = 0; local->history_size = 0; priv->flags = flag; /* various flags (device type, absolute, first touch...) */ priv->oldx = -1; /* previous X position */ priv->oldy = -1; /* previous Y position */ priv->oldz = -1; /* previous Z position */ priv->oldu = -1; /* previous U position */ priv->oldv = -1; /* previous V position */ priv->oldr = -1; /* previous R position */ priv->oldButtons = 0; /* previous buttons state */ priv->factorX = 0.1; /* X factor */ priv->factorY = 0.1; /* Y factor */ priv->offsetX = 0; /* X offset */ priv->offsetY = 0; /* Y offset */ priv->common = common; /* common info pointer */ common->srbDevice = ""; /* device file name */ #if defined(sun) && !defined(i386) if (dev_name) { common->srbDevice = (char*) xalloc(strlen(dev_name)+1); strcpy(common->srbDevice, dev_name); ErrorF("xf86srbOpen port changed to '%s'\n", common->srbDevice); } #endif common->srbFlags = 0; /* various flags */ common->srbDevices = (LocalDevicePtr*) xalloc(sizeof(LocalDevicePtr)); common->srbDevices[0] = local; common->srbNumDevices = 1; /* number of devices */ common->srbIndex = 0; /* number of bytes read */ common->srbPktLength[0] = SORB_BUTTON_SIZE; /* length of a packet */ common->srbPktLength[1] = SORB_MOTION_SIZE; /* length of a packet */ common->srbPktLength[2] = SORB_GREETING_SIZE; /* length of a packet */ return local; } /* *************************************************************************** * * xf86srbAllocateSpBall -- * *************************************************************************** */ static LocalDevicePtr xf86srbAllocateSpBall() { LocalDevicePtr local = xf86srbAllocate(XI_SPORB, SPORB_ID); local->type_name = "SpaceTec SpaceBall"; return local; } /* *************************************************************************** * * SpOrb Stylus device association -- * *************************************************************************** */ DeviceAssocRec SpOrb_assoc = { SPORB_SECTION_NAME, /* config_section_name */ xf86srbAllocateSpBall /* device_allocate */ }; #ifdef DYNAMIC_MODULE /* *************************************************************************** * * entry point of dynamic loading * *************************************************************************** */ int #ifndef DLSYM_BUG init_module(unsigned long server_version) #else init_xf86SpOrb(unsigned long server_version) #endif { xf86AddDeviceAssoc(&SpOrb_assoc); if (server_version != XF86_VERSION_CURRENT) { ErrorF("Warning: SpOrb module compiled for version%s\n", XF86_VERSION); return 0; } else { return 1; } } #endif /* end of xf86SpOrb.c */