diff options
author | Peter Osterlund <petero2@telia.com> | 2002-07-04 00:40:37 +0200 |
---|---|---|
committer | Peter Osterlund <petero2@telia.com> | 2006-04-09 04:00:49 +0200 |
commit | 0d8042d8b68e259457de14a0c4365459b1de7d30 (patch) | |
tree | a9a0e8a6fcaa138d8cb6e1e77b7f9b7036b6f4e8 |
Added source code for the synaptics touchpad XFree86
driver.
-rw-r--r-- | FEATURES | 13 | ||||
-rw-r--r-- | FILES | 7 | ||||
-rw-r--r-- | INSTALL | 58 | ||||
-rw-r--r-- | INSTALL.DE | 58 | ||||
-rw-r--r-- | LICENSE | 280 | ||||
-rw-r--r-- | Makefile | 63 | ||||
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | PARAMETER | 15 | ||||
-rw-r--r-- | TODO | 10 | ||||
-rw-r--r-- | VERSION | 1 | ||||
-rw-r--r-- | pc_keyb.c.diff.2.4.3 | 57 | ||||
-rw-r--r-- | ps2comm.c | 346 | ||||
-rw-r--r-- | ps2comm.h | 67 | ||||
-rw-r--r-- | synaptics.c | 903 | ||||
-rw-r--r-- | synaptics.h | 97 | ||||
-rw-r--r-- | synclient.c | 26 |
16 files changed, 2003 insertions, 0 deletions
diff --git a/FEATURES b/FEATURES new file mode 100644 index 0000000..e731e1f --- /dev/null +++ b/FEATURES @@ -0,0 +1,13 @@ +The touchpad driver has the following functions (some function requires features from the touchpad that must be present, multifinger taps for example): +- Movement with adjustable, non-linear acceleration and speed (Options: MinSpeed, MaxSpeed, AccelFactor) +- Button events through short touching of the touchpad (Options: MaxTapTime, MaxTapMove) +- Double-Button events through double short touching of the touchpad +- Dragging through short touching and holding down the finger on the touchpad +- Middle and right button events on the upper and lower corner of the touchpad (Option: Edges) +- Scrolling (button four and five events) through moving the finger on the right side of the touchpad (Options: Edges, VertScrollDelta) +- The up/down button sends button four/five events +- Adjustable finger detection (Option: Finger) +- Ext Mouse repeater support - Alpha! (Option: Repeater) +- Multifinger taps: two finger for middle button and three finger for right button events +- Online configuration through short-memory (in development) (Option: SHMConfig) + @@ -0,0 +1,7 @@ +pc_keyb.c.diff.2.4.3 Patch for the reconnect message handling +ps2comm.c Synaptics communication routines +ps2comm.h see above +synaptics.c Synaptics driver-module for xfree +synaptics.h see above +synclient.c Program for testing the shared-memory + shows the x, y-coordinates of the finger @@ -0,0 +1,58 @@ +Installation of the Synaptics-Touchpad-Driver for XFree 4.x +=========================================================== + +Author: Stefan Gmeiner <riddlebox@freesurf.ch> +Date: 17.02.02 + +needs: - XFree 4.x + - Using with Kernel 2.4.x for x < 10 needs a kernel-patch (see + source-code) + +1. If you installing the driver by binary (recommended) you can go to +step 3. + +2. Change in the "Makefile" the path to the xfree-sourcecode tree by +changig the Variable TOP. Then type "make" to build the driver +"synaptics_drv.o". + +3. Copy the driver-modul "snyaptics_drv.o" into the XFree-module path +"ex. /usr/X11R6/lib/modules/input/". + +4. Load the driver by changig the XFree configuration file through +adding the line 'Load "synaptics"' in the modul-section. + +5. Add/Replace in the InputDevice-section for the touchpad the +following lines: + +Section "InputDevice" + Driver "synaptics" + Identifier "Mouse[1]" + Option "Device" "/dev/psaux" + Option "Edges" "1900 5400 1800 3900" + Option "Finger" "25 30" + Option "MaxTapTime" "20" + Option "MaxTapMove" "220" + Option "VertScrollDelta" "100" + Option "MinSpeed" "0.02" + Option "MaxSpeed" "0.18" + Option "AccelFactor" "0.0010" +# Option "Repeater" "/dev/ps2mouse" +# Option "SHMConfig" "on" +EndSection + +Change the Identifier to the same name as in the ServerLayout-section. +The Option "Repeater" und "SHMConfig" are at the moment for testing. + +6. Start/Restart the X-Server. If the touchpad doesn't work go to +step 7. + +7. a) Check the XFree-Logfiles + b) Try to start the XServer with 'startx -- -logverbose 8' for more + Output +If you can't get the driver working, mail the logfiles and the +configuration file to me. + + + + + diff --git a/INSTALL.DE b/INSTALL.DE new file mode 100644 index 0000000..ff5131c --- /dev/null +++ b/INSTALL.DE @@ -0,0 +1,58 @@ +Installation des Synaptics-Touchpad-Treibers für XFree 4.x +========================================================== + +Autor: Stefan Gmeiner <riddlebox@freesurf.ch> +Datum: 17.02.02 + +Vorraussetzungen für die Installation: +- XFree 4.x +- Bei Kernel 2.4.x für x < 10 muss ein Kernel-Patch installiert + werden (siehe Source-Tree des Treibers) + +1. Wenn du den Treiber als Binary installierst (empfohlen), kannst du direkt +zum Schritt 2 übergehen. + +2. Nach dem im "Makefile" der Pfad zum XFree Sourcetree angepasst +wurde (TOP=<Pfad zum XFree-Quellcode , kann der Treiber mit +"make" übersetzt werden. + +3. Der Treiber "synaptics_drv.o" muss in das Modul-Verzeichnis +der XFree Installation kopiert werden. + +4. In der Konfigurationsdatei ist der Treiber über "Load +"synaptics"" in der Modul-Section zu laden. + +5. In der InputDevice-Section für das Touchpad sind folgende +Optionen einzufügen/ersetzen: + +Section "InputDevice" + Driver "synaptics" + Identifier "Mouse[1]" + Option "Device" "/dev/psaux" + Option "Edges" "1900 5400 1800 3900" + Option "Finger" "25 30" + Option "MaxTapTime" "20" + Option "MaxTapMove" "220" + Option "VertScrollDelta" "100" + Option "MinSpeed" "0.02" + Option "MaxSpeed" "0.18" + Option "AccelFactor" "0.0010" +# Option "Repeater" "/dev/ps2mouse" +# Option "SHMConfig" "on" +EndSection + +Als Identifier muss der gleiche Name wie in der +ServerLayout-Section verwendet werden. +Die Optionen "Repeater" und "SHMConfig" sind noch in der +Testphase. Über die "Repeater"-Option kann eine ext. Maus auf ein +Repeater-FiFo umgeleitet werden. Über die Option "SHMConfig" soll +der Treiber später einaml online konfigurierbar werden. + +6. Der X-Server ist neu zu starten. Sollte das Touchpad nicht +funktionieren, siehe Schritt 7. + +7. a) Die Ausgaben des XFree-Logfiles anschauen. + b) Den XServer mit "startx -- -logverbose 8" starten um mehr + Ausgaben zu erzeugen. + + @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..33cab24 --- /dev/null +++ b/Makefile @@ -0,0 +1,63 @@ +TOP = /usr/src/packages/BUILD/xc +XTOP = $(TOP) +BUILDINCROOT = $(TOP)/exports +EXTINCSRC = $(XTOP)/include/extensions +INCLUDESRC = $(BUILDINCROOT)/include +XINCLUDESRC = $(INCLUDESRC)/X11 +SERVERSRC = $(XTOP)/programs/Xserver +TOP_X_INCLUDES = -I$(TOP)/exports/include +TOP_INCLUDES = -I$(TOP) $(TOP_X_INCLUDES) + + +XF86SRC = $(SERVERSRC)/hw/xfree86 +XF86COMSRC = $(XF86SRC)/common +XF86OSSRC = $(XF86SRC)/os-support + + +INCLUDES = -I. -I$(XF86COMSRC) -I$(SERVERSRC)/hw/xfree86/loader -I$(XF86OSSRC) -I$(SERVERSRC)/mi -I$(SERVERSRC)/include -I$(XINCLUDESRC) -I$(EXTINCSRC) + +ALLINCLUDES = $(INCLUDES) $(TOP_INCLUDES) + +MODULE_DEFINES = -DIN_MODULE -DXFree86Module +PROTO_DEFINES = -DFUNCPROTO=15 -DNARROWPROTO + +STD_DEFINES = -Dlinux -D__i386__ -D_POSIX_C_SOURCE=199309L -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE -D_GNU_SOURCE -DSHAPE -DXINPUT -DXKB -DLBX -DXAPPGROUP -DXCSECURITY -DTOGCUP -DDPMSExtension -DPIXPRIV -DPANORAMIX -DRENDER -DGCCUSESGAS -DAVOID_GLYPHBLT -DPIXPRIV -DSINGLEDEPTH -DXFreeXDGA -DXvExtension -DXFree86LOADER -DXFree86Server -DXF86VIDMODE -DSMART_SCHEDULE -DBUILDDEBUG -DX_BYTE_ORDER=X_LITTLE_ENDIAN -DNDEBUG +ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(PROTO_DEFINES) $(MODULE_DEFINES) + +CCOPTIONS = -ansi -pedantic -Wall -Wpointer-arith +CDEBUGFLAGS = -O2 +CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES) + +CC = gcc +CCOPTIONS = -ansi -pedantic -Wall -Wpointer-arith + +LDCOMBINEFLAGS = -r + +SRCS = synaptics.c ps2comm.c +OBJS = synaptics.o ps2comm.o + +DRIVER = synaptics + +.c.o: + $(RM) $@ + $(CC) -c $(CFLAGS) $(_NOOP_) $*.c + +all:: $(DRIVER)_drv.o + +$(DRIVER)_drv.o: $(OBJS) $(EXTRALIBRARYDEPS) + $(RM) $@ + $(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $@ + +test: + $(CC) $(CFLAGS) -o synclient synclient.c + +clean:: + $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut synclient "#"* + +tags:: + $(TAGS) -w *.[ch] + $(TAGS) -xw *.[ch] > TAGS + + + + @@ -0,0 +1,2 @@ +13.10.01 - Version 0.10 +- multifinger taps diff --git a/PARAMETER b/PARAMETER new file mode 100644 index 0000000..39cd31d --- /dev/null +++ b/PARAMETER @@ -0,0 +1,15 @@ +Device String Synaptics device +SHMConfig Bool switch on/off shared-memory for configuration +LeftEdge Int coordinates for left edge +RightEdge Int coordinates for right edge +TopEdge Int coordinates for top edge +BottomEdge Int coordinates for bottom edge +FingerLow Int min. finger pressure after ending with movement +FingerHigh Int max. finger pressure before beginning with movement +MaxTapTime Int max. time (time of 1/80s) for detecting a tap +MaxTapMove Int max. movement of the finger for detecting a tap +VertScrollDelta Int move-distance of the finger for a scroll event +Repeater String repeater device +MinSpeed Float min. Speed-factor +MaxSpeed Float max. Speed-factor +AccelFactor Float acceleration-factor @@ -0,0 +1,10 @@ +* horz. Scrolling möglich (Button 6,7 mit imwheel?) +* edge draging - bewegung geht am Rand bei dragging weiter +* Resetsequenz für repeater treiber +* feartures über optionen abschalten +* schnelleres scrolling (buttonrelease events) +* shared-memory für online konfiguration +* ftok benutzen um Shared-Memory ID zu erzeugen + + + @@ -0,0 +1 @@ +0.10 diff --git a/pc_keyb.c.diff.2.4.3 b/pc_keyb.c.diff.2.4.3 new file mode 100644 index 0000000..0d211a3 --- /dev/null +++ b/pc_keyb.c.diff.2.4.3 @@ -0,0 +1,57 @@ +*** pc_keyb.c.orig Thu Oct 4 21:48:24 2001 +--- pc_keyb.c Thu Oct 4 21:52:41 2001 +*************** +*** 63,68 **** +--- 63,69 ---- + #ifdef CONFIG_PSMOUSE + static void aux_write_ack(int val); + static void __aux_write_ack(int val); ++ static int aux_reconnect = 0; + #endif + + static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED; +*************** +*** 403,409 **** + } + mouse_reply_expected = 0; + } +! else if(scancode == AUX_RECONNECT){ + queue->head = queue->tail = 0; /* Flush input queue */ + __aux_write_ack(AUX_ENABLE_DEV); /* ping the mouse :) */ + return; +--- 404,411 ---- + } + mouse_reply_expected = 0; + } +! else if(scancode == AUX_RECONNECT && aux_reconnect){ +! printk(KERN_DEBUG "AUX_RECONNECT scancode read\n"); + queue->head = queue->tail = 0; /* Flush input queue */ + __aux_write_ack(AUX_ENABLE_DEV); /* ping the mouse :) */ + return; +*************** +*** 751,756 **** +--- 753,776 ---- + } + + #if defined CONFIG_PSMOUSE ++ ++ /* ++ AUX_RECONNECT support becomes a boot option, default off ++ ++ WARNING: aux-reconnect breaks synaptics ps2 touchpad support ++ (synaptics generates spurious AUX_RECONNECT scancodes ?) ++ ++ ported from 2.2.18 by MAtteo HCE Valsasna (hce@uninsubria.it) ++ */ ++ ++ static int __init aux_reconnect_setup(char *str, int *ints) ++ { ++ aux_reconnect=1; ++ printk(KERN_INFO "AUX_RECONNECT support enabled, forget your synaptics\n"); ++ return 1; ++ } ++ ++ __setup("aux-reconnect", aux_reconnect_setup); + + /* + * Check if this is a dual port controller. diff --git a/ps2comm.c b/ps2comm.c new file mode 100644 index 0000000..cc43724 --- /dev/null +++ b/ps2comm.c @@ -0,0 +1,346 @@ +/* Copyright (C) 2001 Stefan Gmeiner <riddlebox@freesurf.ch> + * + * Copyright (c) 1997 C. Scott Ananian <cananian@alumni.priceton.edu> + * Copyright (c) 1998-2000 Bruce Kalk <kall@compass.com> + * code für the special synaptics commands (from the tpconfig-source) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "xf86_OSproc.h" + +#include "ps2comm.h" + +/* acknowledge for commands and parameter */ +#define PS2_ACK 0xFA +#define PS2_ERROR 0xFC + +/* standard PS/2 commands */ +#define PS2_CMD_RESET 0xFF +#define PS2_CMD_RESEND 0xFE +#define PS2_CMD_SET_DEFAULT 0xF6 +#define PS2_CMD_DISABLE 0xF5 +#define PS2_CMD_ENABLE 0xF4 +#define PS2_CMD_SET_SAMPLE_RATE 0xF3 +#define PS2_CMD_READ_DEVICE_TYPE 0xF2 +#define PS2_CMD_SET_REMOTE_MODE 0xF0 +#define PS2_CMD_SET_WRAP_MODE 0xEE +#define PS2_CMD_RESET_WRAP_MODE 0xEC +#define PS2_CMD_READ_DATA 0xEB +#define PS2_CMD_SET_STREAM_MODE 0xEA +#define PS2_CMD_STATUS_REQUEST 0xE9 +#define PS2_CMD_SET_RESOLUTION 0xE8 +#define PS2_CMD_SET_SCALING_2_1 0xE7 +#define PS2_CMD_SET_SCALING_1_1 0xE6 + +/* synaptics queries */ +#define SYN_QUE_IDENTIFY 0x00 +#define SYN_QUE_MODES 0x01 +#define SYN_QUE_CAPABILITIES 0x02 +#define SYN_QUE_MODEL 0x03 +#define SYN_QUE_SERIAL_NUMBER_PREFIX 0x06 +#define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07 +#define SYN_QUE_RESOLUTION 0x08 + +/* status request response bits (PS2_CMD_STATUS_REQUEST) */ +#define PS2_RES_REMOTE(r) (r&(1<<22)) +#define PS2_RES_ENABLE(r) (r&(1<<21)) +#define PS2_RES_SCALING(r) (r&(1<<20)) +#define PS2_RES_LEFT(r) (r&(1<<18)) +#define PS2_RES_MIDDLE(r) (r&(1<<17)) +#define PS2_RES_RIGHT(r) (r&(1<<16)) +#define PS2_RES_RESOLUTION(r) ((r>>8)&0x03) +#define PS2_RES_SAMPLE_RATE(r) (r&0xff) + + + +/***************************************************************************** + * PS/2 Utility functions. + * Many parts adapted from tpconfig.c by C. Scott Ananian + ****************************************************************************/ + +/* + * Read a byte from the ps/2 port + */ +static Bool +ps2_getbyte(int fd, byte *b) +{ + if(xf86WaitForInput(fd, 50000) > 0) { + if(xf86ReadSerial(fd, b, 1) != 1) { +#ifdef DEBUG + ErrorF("ps2_getbyte: No byte read\n"); +#endif + return !Success; + } +#ifdef DEBUG + ErrorF("ps2_getbyte: byte %02X read\n", *b); +#endif + return Success; + } +#ifdef DEBUG + ErrorF("ps2_getbyte: timeout xf86WaitForInput\n"); +#endif + return !Success; +} + +/* + * Write a byte to the ps/2 port, wair for ACK + */ +static Bool +ps2_putbyte(int fd, byte b) +{ + byte ack; + + if(xf86WriteSerial(fd, &b, 1) != 1) { +#ifdef DEBUG + ErrorF("ps2_putbyte: error xf86WriteSerial\n"); +#endif + return !Success; + } +#ifdef DEBUG + ErrorF("ps2_putbyte: byte %02X send\n", b); +#endif + /* wait for an ACK */ + if(ps2_getbyte(fd, &ack) != Success) { + return !Success; + } + if(ack != PS2_ACK) { +#ifdef DEBUG + ErrorF("ps2_putbyte: wrong acknowledge 0x%02x\n", ack); +#endif + return !Success; + } + return Success; +} + +/* + * Use the Synaptics extended ps/2 syntax to write a special command byte. Needed by + * ps2_send_cmd and ps2_set_mode. + * special command: 0xE8 rr 0xE8 ss 0xE8 tt 0xE8 uu where (rr*64)+(ss*16)+(tt*4)+uu + * is the command. A 0xF3 or 0xE9 must follow (see ps2_send_cmd, ps2_set_mode) + */ +static Bool +ps2_special_cmd(int fd, byte cmd) +{ + int i; + + /* initialize with 'inert' command */ + if(ps2_putbyte(fd, PS2_CMD_SET_SCALING_1_1) == Success) + /* send 4x 2-bits with set resolution command */ + for (i=0; i<4; i++) { + if(((ps2_putbyte(fd, PS2_CMD_SET_RESOLUTION)) != Success) || + ((ps2_putbyte(fd, (cmd>>6)&0x3) != Success))) + return !Success; + cmd<<=2; + } + else + return !Success; + return Success; +} + +/* + * Send a command to the synpatics touchpad by special commands + */ +static Bool +ps2_send_cmd(int fd, byte c) +{ +#ifdef DEBUG + ErrorF("send command: 0x%02X\n", c); +#endif + return(ps2_special_cmd(fd, c) || ps2_putbyte(fd, PS2_CMD_STATUS_REQUEST)); +} + +/***************************************************************************** + * Synaptics communications functions + ****************************************************************************/ + +/* + * Set the synaptics touchpad mode byte by special commands + */ +Bool +synaptics_set_mode(int fd, byte mode) +{ +#ifdef DEBUG + ErrorF("set mode byte to: 0x%02X\n", mode); +#endif + return(ps2_special_cmd(fd, mode) || + ps2_putbyte(fd, PS2_CMD_SET_SAMPLE_RATE) || + ps2_putbyte(fd, 0x14)); +} + +/* + * reset the touchpad + */ +Bool +synaptics_reset(int fd) +{ + byte r[2]; + + xf86FlushInput(fd); +#ifdef DEBUG + ErrorF("Reset the Touchpad...\n"); +#endif + if(ps2_putbyte(fd, PS2_CMD_RESET) != Success) { +#ifdef DEBUG + ErrorF("...failed\n"); +#endif + return !Success; + } + xf86WaitForInput(fd, 1500000); + if((ps2_getbyte(fd, &r[0]) == Success) && + (ps2_getbyte(fd, &r[1]) == Success)) { + if(r[0] == 0xAA && r[1] == 0x00) { +#ifdef DEBUG + ErrorF("...done\n"); +#endif + return Success; + } else { +#ifdef DEBUG + ErrorF("...failed. Wrong reset ack 0x%02x, 0x%02x\n", r[0], r[1]); +#endif + return !Success; + } + } +#ifdef DEBUG + ErrorF("...failed\n"); +#endif + return !Success; +} + +/* + * Read the model-id bytes from the touchpad + * see also SYN_MODEL_* macros + */ +Bool +synaptics_model_id(int fd, unsigned long int *model_id) +{ + byte mi[3]; + +#ifdef DEBUG + ErrorF("Read mode id...\n"); +#endif + + if((ps2_send_cmd(fd, SYN_QUE_MODEL) == Success) && + (ps2_getbyte(fd, &mi[0]) == Success) && + (ps2_getbyte(fd, &mi[1]) == Success) && + (ps2_getbyte(fd, &mi[2]) == Success)) { + *model_id = (mi[0]<<16) | (mi[1]<<8) | mi[2]; +#ifdef DEBUG + ErrorF("mode-id %06X\n", *model_id); +#endif +#ifdef DEBUG + ErrorF("...done.\n"); +#endif + return Success; + } +#ifdef DEBUG + ErrorF("...failed.\n"); +#endif + return !Success; +} + +/* + * Read the capability-bits from the touchpad + * see also the SYN_CAP_* macros + */ +Bool +synaptics_capability(int fd, unsigned long int *capability) +{ + byte cap[3]; + +#ifdef DEBUG + ErrorF("Read capabilites...\n"); +#endif + + if((ps2_send_cmd(fd, SYN_QUE_CAPABILITIES) == Success) && + (ps2_getbyte(fd, &cap[0]) == Success) && + (ps2_getbyte(fd, &cap[1]) == Success) && + (ps2_getbyte(fd, &cap[2]) == Success)) { + *capability = (cap[0]<<16) | (cap[1]<<8) | cap[2]; +#ifdef DEBUG + ErrorF("capability %06X\n", *capability); +#endif + if(SYN_CAP_VALID(*capability)) { +#ifdef DEBUG + ErrorF("...done.\n"); +#endif + return Success; + } + } +#ifdef DEBUG + ErrorF("...failed.\n"); +#endif + return !Success; +} + +/* + * Identify Touchpad + * See also the SYN_ID_* macros + */ +Bool +synaptics_identify(int fd, unsigned long int *ident) +{ + byte id[3]; + +#ifdef DEBUG + ErrorF("Identify Touchpad...\n"); +#endif + + if((ps2_send_cmd(fd, SYN_QUE_IDENTIFY) == Success) && + (ps2_getbyte(fd, &id[0]) == Success) && + (ps2_getbyte(fd, &id[1]) == Success) && + (ps2_getbyte(fd, &id[2]) == Success)) { + *ident = (id[0]<<16) | (id[1]<<8) | id[2]; +#ifdef DEBUG + ErrorF("ident %06X\n", *ident); +#endif + if(SYN_ID_IS_SYNAPTICS(*ident)) { +#ifdef DEBUG + ErrorF("...done.\n"); +#endif + return Success; + } + } +#ifdef DEBUG + ErrorF("...failed.\n"); +#endif + return !Success; +} + +Bool +SynapticsEnableDevice(int fd) +{ + return(ps2_putbyte(fd, PS2_CMD_ENABLE)); +} + +Bool +QueryIsSynaptics(int fd) +{ + unsigned long id; + + xf86FlushInput(fd); + if(synaptics_identify(fd, &id) == Success) { + return TRUE; + } else { + ErrorF("Query no Synaptics: %06X\n", id); + return FALSE; + } +} + +/* + * vim: ts=4 sw=4 cindent + */ + diff --git a/ps2comm.h b/ps2comm.h new file mode 100644 index 0000000..e509238 --- /dev/null +++ b/ps2comm.h @@ -0,0 +1,67 @@ +#ifndef _PS2COMM_H_ +#define _PS2COMM_H_ + +/* synatics modes */ +#define SYN_BIT_ABSOLUTE_MODE (1<<7) +#define SYN_BIT_HIGH_RATE (1<<6) +#define SYN_BIT_SLEEP_MODE (1<<3) +#define SYN_BIT_DISABLE_GESTURE (1<<2) +#define SYN_BIT_W_MODE (1<<0) + +/* synaptics model ID bits */ +#define SYN_MODEL_ROT180(m) (m&(1<<23)) +#define SYN_MODEL_PORTRAIT(m) (m&(1<<22)) +#define SYN_MODEL_SENSOR(m) ((m>>16)&0x3f) +#define SYN_MODEL_HARDWARE(m) ((m>>9)0x7f) +#define SYN_MODEL_NEWABS(m) (m&(1<<7)) +#define SYN_MODEL_PEN(m) (m&(1<<6)) +#define SYN_MODEL_SIMPLIC(m) (m&(1<<5)) +#define SYN_MODEL_GEOMETRY(m) (m&0x0f) + +/* synaptics capability bits */ +#define SYN_CAP_EXTENDED(c) (c&(1<<23)) +#define SYN_CAP_SLEEP(c) (c&(1<<4)) +#define SYN_CAP_FOUR_BUTTON(c) (c&(1<<3)) +#define SYN_CAP_MULTIFINGER(c) (c&(1<<1)) +#define SYN_CAP_PALMDETECT(c) (c&(1<<0)) +#define SYN_CAP_VALID(c) (((c&0x00ff00)>>8)==0x47) + +/* synaptics modes query bits */ +#define SYN_MODE_ABSOLUTE(m) (m&(1<<7)) +#define SYN_MODE_RATE(m) (m&(1<<6)) +#define SYN_MODE_BAUD_SLEEP(m) (m&(1<<3)) +#define SYN_MODE_DISABLE_GESTURE(m) (m&(1<<2)) +#define SYN_MODE_PACKSIZE(m) (m&(1<<1)) +#define SYN_MODE_WMODE(m) (m&(1<<0)) +#define SYN_MODE_VALID(m) ((m&0xffff00)==0x3B47) + +/* synaptics identify query bits */ +#define SYN_ID_MODEL(i) ((i>>4)&0x0f) +#define SYN_ID_MAJOR(i) (i&0x0f) +#define SYN_ID_MINOR(i) ((i>>16)&0xff) +#define SYN_ID_IS_SYNAPTICS(i) (((i>>8)&0xff)==0x47) + +typedef unsigned char byte; + +Bool +synaptics_reset(int fd); + +Bool +synaptics_model_id(int fd, unsigned long int *model_id); + +Bool +synaptics_capability(int fd, unsigned long int *capability); + +Bool +synaptics_identify(int fd, unsigned long int *ident); + +Bool +synaptics_set_mode(int fd, byte cmd); + +Bool +SynapticsEnableDevice(int fd); + +Bool +QueryIsSynaptics(int fd); + +#endif /* _PS2COMM_H_ */ diff --git a/synaptics.c b/synaptics.c new file mode 100644 index 0000000..0396fdb --- /dev/null +++ b/synaptics.c @@ -0,0 +1,903 @@ +/* Copyright (C) 2001 Stefan Gmeiner <riddlebox@freesurf.ch> + * + * Copyright (c) 1999 Henry Davies <hdavies@ameritech.net> for the + * absolut to relative translation code (from the gpm-source) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + +/***************************************************************************** + * Standard Headers + ****************************************************************************/ + +#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> /* Needed for InitValuator/Proximity stuff */ +#include "mipointer.h" +#include <xf86Optrec.h> /* needed for Options */ + +/***************************************************************************** + * Local Headers + ****************************************************************************/ +#include "synaptics.h" +#include "ps2comm.h" + +/***************************************************************************** + * Variables without includable headers + ****************************************************************************/ + +/***************************************************************************** + * Local Variables + ****************************************************************************/ + +typedef enum { + BOTTOM_EDGE = 1, + TOP_EDGE = 2, + LEFT_EDGE = 4, + RIGHT_EDGE = 8, + LEFT_BOTTOM_EDGE = BOTTOM_EDGE | LEFT_EDGE, + RIGHT_BOTTOM_EDGE = BOTTOM_EDGE | RIGHT_EDGE, + RIGHT_TOP_EDGE = TOP_EDGE | RIGHT_EDGE, + LEFT_TOP_EDGE = TOP_EDGE | LEFT_EDGE +} edge_type; + +#define DIFF_TIME(a, b) (((a)>(b))?(a)-(b):(b)-(a)) +#define VERSION "0.10" + +static InputInfoPtr +SynapticsPreInit(InputDriverPtr drv, IDevPtr dev, int flags); + + +InputDriverRec SYNAPTICS = { + 1, + "synaptics", + NULL, + SynapticsPreInit, + /*SynapticsUnInit*/ NULL, + NULL, + 0 +}; + +#ifdef XFree86LOADER + +static XF86ModuleVersionInfo VersionRec = +{ + "synaptics", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_XINPUT, + ABI_XINPUT_VERSION, + MOD_CLASS_XINPUT, + {0, 0, 0, 0} /* signature, to be patched into the file by + * a tool */ +}; + + +static pointer +SetupProc(pointer module, pointer options, int *errmaj, int *errmin ) +{ + xf86AddInputDriver(&SYNAPTICS, module, 0); + return module; +} + +XF86ModuleData synapticsModuleData = {&VersionRec, &SetupProc, NULL }; + +#endif /* XFree86LOADER */ + + +/***************************************************************************** + * Function Definitions + ****************************************************************************/ + +static InputInfoPtr +SynapticsPreInit(InputDriverPtr drv, IDevPtr dev, int flags) +{ + LocalDevicePtr local; + SynapticsPrivatePtr priv; + XF86OptionPtr optList; + char *s; + int shmid; + + /* allocate memory for SynaticsPrivateRec */ + priv = xcalloc (1, sizeof (SynapticsPrivateRec)); + if (!priv) + return NULL; + + /* Allocate a new InputInfoRec and add it to the head xf86InputDevs. */ + local = xf86AllocateInput(drv, 0); + if (!local) { + xfree(priv); + return NULL; + } + + /* initialize the InputInfoRec */ + local->name = dev->identifier; + local->type_name = XI_MOUSE; /* XI_TOUCHPAD and KDE killed the X-Server at startup ? */ + 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->reverse_conversion_proc = NULL; + local->dev = NULL; + local->private = priv; + local->private_flags = 0; + local->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS; + local->conf_idev = dev; + local->motion_history_proc = xf86GetMotionEvents; + local->history_size = 0; + local->always_core_feedback = 0; + + xf86CollectInputOptions(local, NULL, NULL); + + xf86OptionListReport(local->options); + + /* open the touchpad device */ + local->fd = xf86OpenSerial (local->options); + if (local->fd == -1) + { + ErrorF ("Synaptics driver unable to open device\n"); + goto SetupProc_fail; + } + xf86ErrorFVerb( 6, "port opened successfully\n" ); + + /* initialize variables */ + priv->repeat_timer = NULL; + priv->repeatButtons = 0; + + /* install shared memory or normal memory for parameter */ + if(xf86SetBoolOption(local->options, "SHMConfig", FALSE)) { + xf86shmctl(SHM_SYNAPTICS, XF86IPC_RMID, NULL); + if((shmid = xf86shmget(SHM_SYNAPTICS, sizeof(SynapticsSHM), 0777 | XF86IPC_CREAT)) == -1) { + xf86Msg(X_ERROR, "%s error shmget\n", local->name); + goto SetupProc_fail; + } else if((priv->synpara = (SynapticsSHM*) xf86shmat(shmid, NULL, 0)) == NULL) { + xf86Msg(X_ERROR, "%s error shmat\n", local->name); + goto SetupProc_fail; + } + } else { + priv->synpara = xcalloc (1, sizeof (SynapticsSHM)); + if(!priv->synpara) + goto SetupProc_fail; + } + + /* read the parameter */ + priv->synpara->left_edge = xf86SetIntOption(local->options, "LeftEdge", 1900); + priv->synpara->right_edge = xf86SetIntOption(local->options, "RightEdge", 5400); + priv->synpara->top_edge = xf86SetIntOption(local->options, "TopEdge", 3900); + priv->synpara->bottom_edge = xf86SetIntOption(local->options, "BottomEdge", 1800); + priv->synpara->finger_low = xf86SetIntOption(local->options, "FingerLow", 25); + priv->synpara->finger_high = xf86SetIntOption(local->options, "FingerHigh", 30); + priv->synpara->tap_time = xf86SetIntOption(local->options, "MaxTapTime", 20); + priv->synpara->tap_move = xf86SetIntOption(local->options, "MaxTapMove", 220); + priv->synpara->scroll_dist_vert = xf86SetIntOption(local->options, "VertScrollDelta", 100); + priv->synpara->repeater = xf86SetStrOption(local->options, "Repeater", NULL); + s = xf86FindOptionValue(local->options, "MinSpeed"); + if((!s) || (xf86sscanf(s, "%lf", &priv->synpara->min_speed) != 1)) + priv->synpara->min_speed=0.02; + s = xf86FindOptionValue(local->options, "MaxSpeed"); + if((!s) || (xf86sscanf(s, "%lf", &priv->synpara->max_speed) != 1)) + priv->synpara->max_speed=0.18; + s = xf86FindOptionValue(local->options, "AccelFactor"); + if((!s) || (xf86sscanf(s, "%lf", &priv->synpara->accl) != 1)) + priv->synpara->accl=0.0015; + + priv->buffer = XisbNew(local->fd, 200); + DBG(9, XisbTrace (priv->buffer, 1)); + + if(priv->synpara->repeater) { + /* create repeater fifo */ + if((xf86mknod(priv->synpara->repeater, 666, XF86_S_IFIFO) != 0) && + (xf86errno != xf86_EEXIST)) { + xf86Msg(X_ERROR, "%s can't create repeater fifo\n", local->name); + xf86free(priv->synpara->repeater); + priv->synpara->repeater = NULL; + priv->fifofd = -1; + } else { + /* open the repeater fifo */ + optList = xf86NewOption("Device", priv->synpara->repeater); + if((priv->fifofd = xf86OpenSerial(optList)) == -1) { + xf86Msg(X_ERROR, "%s repeater device open failed\n", local->name); + xf86free(priv->synpara->repeater); + priv->synpara->repeater = NULL; + priv->fifofd = -1; + } + } + } + + if(QueryHardware(local) != Success) { + xf86Msg(X_ERROR, "%s Unable to query/initialize Synaptics hardware.\n", local->name); + goto SetupProc_fail; + } + + local->history_size = xf86SetIntOption( local->options, "HistorySize", 0 ); + + /* this results in an xstrdup that must be freed later */ + /*local->name = xf86SetStrOption( local->options, "DeviceName", "Synaptics-Touchpad" );*/ + xf86ProcessCommonOptions(local, local->options); + local->flags |= XI86_CONFIGURED; + + if (local->fd != -1) { + RemoveEnabledDevice (local->fd); + if (priv->buffer) { + XisbFree(priv->buffer); + priv->buffer = NULL; + } + xf86CloseSerial(local->fd); + } + RemoveEnabledDevice (local->fd); + local->fd = -1; + return (local); + + SetupProc_fail: + if ((local) && (local->fd)) + xf86CloseSerial (local->fd); + + /* If it fails, the name will be printed + if ((local) && (local->name)) + xfree (local->name); + */ + + if ((priv) && (priv->buffer)) + XisbFree (priv->buffer); + if ((priv) && (priv->synpara)) + xfree (priv->synpara); + if (priv) + xfree (priv); + return (local); +} + +/* + * SynapticsCtrl -- + * Alter the control parameters for the mouse. Note that all special + * protocol values are handled by dix. + */ +static void +SynapticsCtrl(DeviceIntPtr device, PtrCtrl *ctrl) +{ + ErrorF("SynapticsCtrl called.\n"); +/* + pInfo = device->public.devicePrivate; + pMse = pInfo->private; + + pMse->num = ctrl->num; + pMse->den = ctrl->den; + pMse->threshold = ctrl->threshold; +*/ +} + +static Bool +DeviceControl (DeviceIntPtr dev, int mode) +{ + Bool RetValue; + + switch (mode) + { + case DEVICE_INIT: + DeviceInit(dev); + RetValue = Success; + break; + case DEVICE_ON: + RetValue = DeviceOn( dev ); + break; + case DEVICE_OFF: + case DEVICE_CLOSE: + RetValue = DeviceOff( dev ); + break; + default: + RetValue = BadValue; + } + + return( RetValue ); +} + +static Bool +DeviceOn (DeviceIntPtr dev) +{ + LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate; + SynapticsPrivatePtr priv = (SynapticsPrivatePtr) (local->private); + + ErrorF("Synaptics DeviceOn called\n"); + + local->fd = xf86OpenSerial(local->options); + if (local->fd == -1) { + xf86Msg(X_WARNING, "%s: cannot open input device\n", local->name); + return (!Success); + } + + priv->buffer = XisbNew(local->fd, 64); + if (!priv->buffer) { + xf86CloseSerial(local->fd); + local->fd = -1; + return (!Success); + } + + xf86FlushInput(local->fd); + xf86AddEnabledDevice (local); + dev->public.on = TRUE; + return (Success); +} + +static Bool +DeviceOff(DeviceIntPtr dev) +{ + LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate; + SynapticsPrivatePtr priv = (SynapticsPrivatePtr) (local->private); + + ErrorF("Synaptics DeviceOff called\n"); + + if (local->fd != -1) { + xf86RemoveEnabledDevice (local); + if (priv->buffer) { + XisbFree(priv->buffer); + priv->buffer = NULL; + } + xf86CloseSerial(local->fd); + } + + RemoveEnabledDevice (local->fd); + dev->public.on = FALSE; + return (Success); +} + +static Bool +DeviceInit(DeviceIntPtr dev) +{ + LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate; + unsigned char map[] = {0, 1, 2, 3, 4, 5}; + + ErrorF("Synaptics DeviceInit called\n"); + + dev->public.on = FALSE; + + InitPointerDeviceStruct((DevicePtr)dev, map, + 5, + miPointerGetMotionEvents, SynapticsCtrl, + miPointerGetMotionBufferSize()); + + /* X valuator */ + xf86InitValuatorAxisStruct(dev, 0, 0, -1, 1, 0, 1); + xf86InitValuatorDefaults(dev, 0); + /* Y valuator */ + xf86InitValuatorAxisStruct(dev, 1, 0, -1, 1, 0, 1); + xf86InitValuatorDefaults(dev, 1); + + xf86MotionHistoryAllocate(local); + + return Success; +} + +static int +move_distance(int dx, int dy) { + return(xf86sqrt((dx * dx) + (dy * dy))); +} + +static edge_type +edge_detection( SynapticsPrivatePtr priv, int x, int y ) { + + edge_type edge = 0; + + if(x > priv->synpara->right_edge) + edge |= RIGHT_EDGE; + else if(x < priv->synpara->left_edge) + edge |= LEFT_EDGE; + + if(y > priv->synpara->top_edge) + edge |= TOP_EDGE; + else if(y < priv->synpara->bottom_edge) + edge |= BOTTOM_EDGE; + + return( edge ); +} + +static CARD32 +updownTimer(OsTimerPtr timer, CARD32 now, pointer arg) +{ + LocalDevicePtr local = (LocalDevicePtr) (arg); + SynapticsPrivatePtr priv = (SynapticsPrivatePtr) (local->private); + int sigstate, change, id; + + sigstate = xf86BlockSIGIO (); + + change = priv->repeatButtons; + while(change) { + id = ffs(change); + change &= ~(1 << (id - 1)); + xf86PostButtonEvent(local->dev, FALSE, id, FALSE, 0, 0); + xf86PostButtonEvent(local->dev, FALSE, id, TRUE, 0, 0); + } + + xf86UnblockSIGIO (sigstate); + + priv->repeat_timer = TimerSet(priv->repeat_timer, 0, 100, updownTimer, local); + + return 0; +} + + +#define MOVE_HIST(a) ((priv->count_packet_finger-(a))%SYNAPTICS_MOVE_HISTORY) + +static void +ReadInput(LocalDevicePtr local) +{ + SynapticsPrivatePtr priv = (SynapticsPrivatePtr) (local->private); + SynapticsSHMPtr para = priv->synpara; + Bool finger; + int x, y, z, w, dist, dx, dy, buttons, id; + edge_type edge; + Bool left, mid, right, up, down; + double speed, integral; + int change; + + /* + * set blocking to -1 on the first call because we know there is data to + * read. Xisb automatically clears it after one successful read so that + * succeeding reads are preceeded buy a select with a 0 timeout to prevent + * read from blocking indefinately. + */ + XisbBlockDuration(priv->buffer, -1); + while(SynapticsGetPacket(local, priv) == Success) + { + /* process input data */ + x = ((priv->protoBuf[3] & 0x10) << 8) | + ((priv->protoBuf[1] & 0x0f) << 8) | + priv->protoBuf[4]; + y = ((priv->protoBuf[3] & 0x20) << 7) | + ((priv->protoBuf[1] & 0xf0) << 4) | + priv->protoBuf[5]; + /* pressure */ + z = priv->protoBuf[2]; + w = ((priv->protoBuf[0] & 0x30) >> 2) | + ((priv->protoBuf[0] & 0x04) >> 1) | + ((priv->protoBuf[3] & 0x04) >> 2); + + left = (priv->protoBuf[0] & 0x01) ? TRUE : FALSE; + mid = FALSE; + right = (priv->protoBuf[0] & 0x2) ? TRUE : FALSE; + up = ((priv->protoBuf[3] & 0x01) && !left) ? TRUE : FALSE; + down = ((priv->protoBuf[3] & 0x02) && !right) ? TRUE : FALSE; + + edge = edge_detection(priv, x, y); + + dx = dy = 0; + + /* shared memory */ + para->x = x; + para->y = y; + + /* 3rd button emulation */ + if(!left && !right) { + priv->count_button_delay = priv->count_packet; + priv->third_button = FALSE; + } else if(DIFF_TIME(priv->count_packet, priv->count_button_delay) < 6) { + left = right = FALSE; + } else if(DIFF_TIME(priv->count_packet, priv->count_button_delay) == 6) { + priv->third_button = left && right; + } + if(priv->third_button) { + mid = TRUE; + left = right = FALSE; + } + + /* finger detection thru pressure an threshold */ + finger = (((z > para->finger_high) && !priv->finger_flag) || + ((z > para->finger_low) && priv->finger_flag)); + + /* tap and drag detection */ + if(finger && !priv->finger_flag) { /* touched */ + DBG(7, ErrorF("touched - x:%d, y:%d packet:%lu\n", x, y, priv->count_packet)); + if(priv->tap) { + DBG(7, ErrorF("drag detected - tap time:%lu\n", priv->count_packet_tapping)); + priv->drag = TRUE; /* drag gesture */ + } + priv->touch_on.x = x; + priv->touch_on.y = y; + priv->touch_on.packet = priv->count_packet; + } else if(!finger && priv->finger_flag) { /* untouched */ + DBG(7, ErrorF("untouched - x:%d, y:%d packet:%lu finger:%d\n", + x, y, priv->count_packet, priv->finger_count)); + /* check if + 1. the tap is in tap_time + 2. the max movement is in tap_move or more than one finger are tapped */ + if((DIFF_TIME(priv->count_packet, priv->touch_on.packet) < para->tap_time) && + (((abs(x - priv->touch_on.x) < para->tap_move) && + (abs(y - priv->touch_on.y) < para->tap_move)) || + priv->finger_count)) { + if(priv->drag) { + DBG(7, ErrorF("double tapping detected\n")); + priv->doubletap = TRUE; + priv->tap = FALSE; + } else { + DBG(7, ErrorF("tapping detected @ ")); + priv->count_packet_tapping = priv->count_packet; + priv->tap = TRUE; + if(priv->finger_count == 0) { + switch(edge) { + case RIGHT_TOP_EDGE: + DBG(7, ErrorF("right top edge\n")); + priv->tap_mid = TRUE; + break; + case RIGHT_BOTTOM_EDGE: + DBG(7, ErrorF("right bottom edge\n")); + priv->tap_right = TRUE; + break; + case LEFT_TOP_EDGE: + DBG(7, ErrorF("left top edge\n")); + break; + case LEFT_BOTTOM_EDGE: + DBG(7, ErrorF("left bottom edge\n")); + break; + default: + DBG(7, ErrorF("no edge\n")); + priv->tap_left = TRUE; + } + } else { + switch(priv->finger_count) { + case 2: + DBG(7, ErrorF("two finger tap\n")); + priv->tap_mid = TRUE; + break; + case 3: + DBG(7, ErrorF("three finger tap\n")); + priv->tap_right = TRUE; + break; + default: + DBG(7, ErrorF("one finger\n")); + priv->tap_left = TRUE; + } + } + } + } /* tap detection */ + priv->drag = FALSE; + } /* finger lost */ + + /* detecting 2 and 3 fingers */ + if(finger && (DIFF_TIME(priv->count_packet, priv->touch_on.packet) < para->tap_time)) { + if((w == 0) && (priv->finger_count == 0)) + priv->finger_count = 2; + if(w == 1) + priv->finger_count = 3; + } else + priv->finger_count = 0; + + /* reset tapping button flags */ + if(!priv->tap && !priv->drag && !priv->doubletap) { + priv->tap_left = priv->tap_mid = priv->tap_right = FALSE; + } + + /* tap processing */ + if(priv->tap && + (DIFF_TIME(priv->count_packet, priv->count_packet_tapping) < para->tap_time)) { + left = priv->tap_left; + mid = priv->tap_mid; + right = priv->tap_right; + } else { + priv->tap = FALSE; + } + + /* drag processing */ + if(priv->drag) { + left = priv->tap_left; + mid = priv->tap_mid; + right = priv->tap_right; + } + + /* double tap processing */ + if(priv->doubletap && !priv->finger_flag) { + left = priv->tap_left; + mid = priv->tap_mid; + right = priv->tap_right; + priv->doubletap = FALSE; + } + + /* scroll detection */ + if(finger && !priv->finger_flag) { + if(edge & RIGHT_EDGE) { + priv->vert_scroll_on = TRUE; + priv->scroll_y = y; + DBG(7, ErrorF("edge scroll detected on right edge\n")); + } + } + if(priv->vert_scroll_on && (!(edge & RIGHT_EDGE) || !finger)) { + DBG(7, ErrorF("edge scroll off\n")); + priv->vert_scroll_on = FALSE; + } + + /* scroll processing */ + if(priv->vert_scroll_on) { + dist = y - priv->scroll_y; /* + = up, - = down */ + if(dist > para->scroll_dist_vert) { + up = TRUE; + priv->scroll_y += para->scroll_dist_vert; + } + else if(dist < (-1 * para->scroll_dist_vert)) { + down = TRUE; + priv->scroll_y -= para->scroll_dist_vert; + } + } + + /* movement */ + if(finger && !priv->vert_scroll_on && !priv->finger_count) { + if(priv->count_packet_finger > 3) { /* min. 3 packets */ + dy = (1 * + (((priv->move_hist[MOVE_HIST(1)].y + priv->move_hist[MOVE_HIST(2)].y) / 2) - + ((y + priv->move_hist[MOVE_HIST(1)].y) / 2))); + dx = (-1 * + (((priv->move_hist[MOVE_HIST(1)].x + priv->move_hist[MOVE_HIST(2)].x) / 2) - + ((x + priv->move_hist[MOVE_HIST(1)].x) / 2))); + + /* speed in depence of distance/packet */ + dist = move_distance( dx, dy ); + speed = dist * para->accl; + if(speed > para->max_speed) + speed = para->max_speed; + else if(speed < para->min_speed) + speed = para->min_speed; + + /* save the fraction for adding to the next priv->count_packet */ + priv->frac_x = xf86modf((dx * speed) + priv->frac_x, &integral); + dx = integral; + priv->frac_y = xf86modf((dy * speed) + priv->frac_y, &integral); + dy = integral; + } + + priv->count_packet_finger++; + } else { + priv->count_packet_finger = 0; + } + + + buttons = ((left ? 0x01 : 0) | + (mid ? 0x02 : 0) | + (right ? 0x04 : 0) | + (up ? 0x08 : 0) | + (down ? 0x10 : 0)); + + priv->count_packet++; + + /* Flags */ + priv->finger_flag = finger; + priv->move_hist[MOVE_HIST(0)].y = y; + priv->move_hist[MOVE_HIST(0)].x = x; + + /* repeat timer for up/down buttons */ + /* when you press a button the packets will only send for a second, so + we have to use a timer for repeating */ + if((up || down) && !priv->vert_scroll_on) { + if(!priv->repeat_timer) { + priv->repeatButtons = buttons & 0x18; + priv->repeat_timer = TimerSet(priv->repeat_timer, + 0, 200, updownTimer, local); + } + } else if(priv->repeat_timer) { + TimerFree(priv->repeat_timer); + priv->repeat_timer = NULL; + priv->repeatButtons = 0; + } + + /* Post events */ + if(dx || dy) + xf86PostMotionEvent(local->dev, 0, 0, 2, dx, dy); + + change = buttons ^ priv->lastButtons; + while(change) { + id = ffs(change); + change &= ~(1 << (id - 1)); + xf86PostButtonEvent(local->dev, FALSE, id, (buttons & (1 << (id - 1))), 0, 0); + } + priv->lastButtons = buttons; + } +} + +static int +ControlProc(LocalDevicePtr local, xDeviceCtl * control) +{ + ErrorF("Control Proc called\n"); + return (Success); +} + +static void +CloseProc (LocalDevicePtr local) +{ + ErrorF("Close Proc called\n"); +} + +static int +SwitchMode (ClientPtr client, DeviceIntPtr dev, int mode) +{ + ErrorF("SwitchMode called\n"); + 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) +{ + if(first != 0 || num != 2) + return FALSE; + + *x = v0; + *y = v1; + + return TRUE; +} + + +static Bool +QueryHardware (LocalDevicePtr local) +{ + SynapticsPrivatePtr priv = (SynapticsPrivatePtr) local->private; + SynapticsSHMPtr para = priv->synpara; + int retries; + + xf86Msg(X_INFO, "synaptics touchpad driver %s\n", VERSION); + + /* is the synaptics touchpad active? */ + priv->isSynaptics = QueryIsSynaptics(local->fd); + + if((!priv->isSynaptics) && (!para->repeater || (priv->fifofd == -1))) { + xf86Msg(X_ERROR, "%s no synaptics touchpad detected and no repeater device\n", + local->name); + priv->isSynaptics = TRUE; + return(!Success); + } + + if(!priv->isSynaptics) { + xf86Msg(X_PROBED, "%s no synaptics touchpad, data piped to repeater fifo\n", local->name); + synaptics_reset(local->fd); + SynapticsEnableDevice(local->fd); + return(Success); + } + + xf86Msg(X_PROBED, "%s synaptics touchpad found\n", local->name); + + retries = 3; + while((retries++ <= 3) && (synaptics_reset(local->fd) != Success)) + xf86Msg(X_ERROR, "%s reset failed\n", local->name); + + if(synaptics_identify(local->fd, &priv->identity) != Success) + return !Success; + + if(synaptics_model_id(local->fd, &priv->model_id) != Success) + return !Success; + + if(synaptics_capability(local->fd, &priv->capabilities) != Success) + return !Success; + + if(synaptics_set_mode(local->fd, SYN_BIT_ABSOLUTE_MODE | + SYN_BIT_HIGH_RATE | + SYN_BIT_DISABLE_GESTURE | + SYN_BIT_W_MODE) != Success) + return !Success; + + PrintIdent(priv); + return Success; +} + +static Bool +SynapticsGetPacket(LocalDevicePtr local, SynapticsPrivatePtr priv) +{ + int count = 0; + int c; + unsigned char *pBuf, u; + + pBuf = priv->protoBuf; + + while((c = XisbRead(priv->buffer)) >= 0) { + u = (unsigned char)c; + + /* test if there is a reset sequence received */ + if((c == 0x00) && (priv->lastByte == 0xAA)) { + if(xf86WaitForInput(local->fd, 50000) == 0 ) { + DBG(7, ErrorF("Reset received\n")); + QueryHardware(local); + } else + ErrorF("faked reset received\n"); + } + priv->lastByte = u; + + /* when there is no synaptics touchpad pipe the data to the repeater fifo */ + if(!priv->isSynaptics) { + xf86write(priv->fifofd, &u, 1); + if(++count >= 3) + return(!Success); + continue; + } + + /* to avoid endless loops */ + if(count++ > 100) { + return (!Success); + } + + pBuf[priv->protoBufTail++] = u; + + /* check first byte */ + if((priv->protoBufTail == 1) && ((u & 0xC8) != 0x80)) { + priv->inSync = FALSE; + priv->protoBufTail = 0; + DBG(4, ErrorF("Synaptics driver lost sync at 1st byte\n")); + continue; + } + + /* check 4th byte */ + if((priv->protoBufTail == 4) && ((u & 0xc8) != 0xc0)) { + priv->inSync = FALSE; + priv->protoBufTail = 0; + DBG(4, ErrorF("Synaptics driver lost sync at 4th byte\n")); + continue; + } + + if(priv->protoBufTail >= 6) { /* Full packet received */ + if(!priv->inSync) { + priv->inSync = TRUE; + DBG(4, ErrorF("Synaptics driver resynced.\n")); + } + priv->protoBufTail = 0; + return Success; + } + } + + return !Success; +} + +static void +PrintIdent(SynapticsPrivatePtr priv) { + + xf86Msg(X_PROBED, " Synaptics Touchpad, model: %d\n", SYN_ID_MODEL(priv->identity)); + xf86Msg(X_PROBED, " Firware: %d.%d\n", SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity)); + + if(SYN_MODEL_ROT180(priv->model_id)) + xf86Msg(X_PROBED, " 180 degree mounted touchpad\n"); + if(SYN_MODEL_PORTRAIT(priv->model_id)) + xf86Msg(X_PROBED, " portrait touchpad\n"); + xf86Msg(X_PROBED, " Sensor: %d\n", SYN_MODEL_SENSOR(priv->model_id)); + if(SYN_MODEL_NEWABS(priv->model_id)) + xf86Msg(X_PROBED, " new absolute packet format\n"); + if(SYN_MODEL_PEN(priv->model_id)) + xf86Msg(X_PROBED, " pen detection\n"); + + if(SYN_CAP_EXTENDED(priv->capabilities)) { + xf86Msg(X_PROBED, " Touchpad has extended capabiliety bits\n"); + if(SYN_CAP_FOUR_BUTTON(priv->capabilities)) + xf86Msg(X_PROBED, " -> four buttons\n"); + if(SYN_CAP_MULTIFINGER(priv->capabilities)) + xf86Msg(X_PROBED, " -> multifinger detection\n"); + if(SYN_CAP_PALMDETECT(priv->capabilities)) + xf86Msg(X_PROBED, " -> palm detection\n"); + } +} + +/* vim:ts=2:sw=2:cindent: +*/ diff --git a/synaptics.h b/synaptics.h new file mode 100644 index 0000000..9a18ef0 --- /dev/null +++ b/synaptics.h @@ -0,0 +1,97 @@ +#ifndef _SAMPLE_H_ +#define _SAMPLE_H_ + +/****************************************************************************** + * Definitions + * structs, typedefs, #defines, enums + *****************************************************************************/ +#define SYNAPTICS_MOVE_HISTORY 5 +#define SHM_SYNAPTICS 23947 + +typedef struct _SynapticsTapRec { + int x, y; + unsigned int packet; +} SynapticsTapRec; + +typedef struct _SynapticsMoveHist { + int x, y; +} SynapticsMoveHistRec; + +typedef struct _SynapticsSHM { + int x, y; /* actual x, y Coordinates */ + + unsigned long int model_id; /* Model-ID */ + unsigned long int capabilities; /* Capabilities */ + unsigned long int identity; /* Identification */ + Bool isSynaptics; /* Synaptics touchpad aktiv */ + + /* Parameter data */ + int left_edge, right_edge, top_edge, bottom_edge; + /* edge coordinates absolute */ + int finger_low, finger_high; /* finger detection values in Z-values */ + int tap_time, tap_move; /* max. tapping-time and movement in packets and coord. */ + int scroll_dist_vert; /* Scrolling distance in absolute coordinates */ + double min_speed, max_speed, accl; /* movement parameters */ + char* repeater; /* Repeater on or off */ +} SynapticsSHM, *SynapticsSHMPtr; + +typedef struct _SynapticsPrivateRec +{ + /* shared memory pointer */ + SynapticsSHMPtr synpara; + + /* Data read from the touchpad */ + unsigned long int model_id; /* Model-ID */ + unsigned long int capabilities; /* Capabilities */ + unsigned long int identity; /* Identification */ + Bool isSynaptics; /* Synaptics touchpad aktiv */ + + /* Data for normal processing */ + XISBuffer *buffer; + unsigned char protoBuf[6]; /* Buffer for Packet */ + unsigned char lastByte; /* letztes gelesene byte */ + Bool inSync; /* Packets in sync */ + int protoBufTail; + int fifofd; /* fd for fifo */ + SynapticsTapRec touch_on; /* data when the touchpad is touched */ + SynapticsMoveHistRec move_hist[SYNAPTICS_MOVE_HISTORY]; + /* movement history */ + int scroll_y; /* last y-scroll position */ + unsigned int count_packet_finger; /* packet counter with finger on the touchpad */ + unsigned int count_packet; /* packet counter */ + unsigned int count_packet_tapping; /* packet counter for tapping */ + unsigned int count_button_delay; /* button delay for 3rd button emulation */ + Bool finger_flag; /* previous finger */ + Bool tap, drag, doubletap; /* feature flags */ + Bool tap_left, tap_mid, tap_right; /* tapping buttons */ + Bool vert_scroll_on; /* scrolling flag */ + double frac_x, frac_y; /* absoulte -> relative fraction */ + Bool third_button; /* emulated 3rd button */ + OsTimerPtr repeat_timer; /* for up/down-button repeat */ + int repeatButtons; /* buttons for repeat */ + int lastButtons; /* last State of the buttons */ + int finger_count; /* tap counter for fingers */ +} +SynapticsPrivateRec, *SynapticsPrivatePtr; + + +static Bool DeviceControl(DeviceIntPtr, int); +static void ReadInput(LocalDevicePtr); +static int ControlProc(LocalDevicePtr, xDeviceCtl*); +static void CloseProc(LocalDevicePtr); +static int SwitchMode(ClientPtr, DeviceIntPtr, int); +static Bool ConvertProc(LocalDevicePtr, int, int, int, int, int, int, int, int, int*, int*); +static Bool QueryHardware(LocalDevicePtr); +static Bool DeviceInit(DeviceIntPtr); +static Bool DeviceOn(DeviceIntPtr); +static Bool DeviceOff(DeviceIntPtr); +static Bool DeviceInit(DeviceIntPtr); +static Bool SynapticsGetPacket(LocalDevicePtr, SynapticsPrivatePtr); +static void PrintIdent(SynapticsPrivatePtr); +/* + * DO NOT PUT ANYTHING AFTER THIS ENDIF + */ +#endif +/* vim:ts=4:sw=4:cindent: +*/ + diff --git a/synclient.c b/synclient.c new file mode 100644 index 0000000..89e6def --- /dev/null +++ b/synclient.c @@ -0,0 +1,26 @@ +#include <stdio.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <unistd.h> +#define SHM_SYNAPTICS 23947 +typedef struct _SynapticsSHM { + int x, y; +} SynapticsSHM; + +int main() { + SynapticsSHM *synshm; + int shmid; + + if((shmid = shmget(SHM_SYNAPTICS, 0, 0)) == -1) + printf("shmget Fehler\n"); + if((synshm = (SynapticsSHM*) shmat(shmid, NULL, 0)) == NULL) + printf("shmat Fehler\n"); + + while(1) { + printf("x:%d y:%d\n", synshm->x, synshm->y); + usleep(100000); + } + + exit(0); +} |