version 0.3.1 v0.3.1
authorMats Johannesson <devel@bredband.net>
Thu, 26 Jun 2008 18:49:53 +0000 (14:49 -0400)
committerAristeu Rozanski <arozansk@redhat.com>
Thu, 26 Jun 2008 18:49:53 +0000 (14:49 -0400)
* Graphire4 support. And what a chore it was! The task has revealed
weaknesses in the overall code structuring which _must_ be attended to.
So, a long time will pass on this end doing nothing but code refactoring.
Graphire4 got hacked in by some serious "spaghetti"...

OBSERVE: linuxwacom-0.7.5-2 or greater is _required_ for Graphire4 support!

In that release an option called GetTabletID was introduced (in xsetwacom
version 0.0.7), which gives us a reliable and future proof way of identifying
the tablet model any device belongs to (pad, stylus etc).

The function identify_device can be found in the exec_shell.c file, where
presently only Graphire4 as a family is registered. A finer grained division
is planned so that correct configuration files can be written out for the
Graphire4 BlueTooth, which lacks a Scroll Wheel, and the Intuos3 4x5 with
its single Touch Strip and 4 buttons.

Thanks go to Carsten Schurig for e-mail access to a real Graphire4.
Imagination and deducing can only produce the code, not verify it.

And, as a sidenote to the verifying part, the Scroll Wheel of a Graphire4
triggers button press/release events, (up = button 4, down = button 5) not
axis motion events as has been stated on the linuxwacom web pages.

* The -s switch to get status from a running program was added in the last
24 hours before the 0.3.0 release, without much thought. It turns out not
to be particularly useful in the intended manner. Standard error (stderr)
where it prints the report is private to each shell session. So if the
program already has been launched by one process, the next one who queries
from another shell will see nothing.

Therefore we now save a copy of the status output as a file as well in:
~/.expresskeys/status.log The file gets created automatically at a daemon
launch (updated with each -s query) and is deleted by a normal program exit.

* Inform the user about the different values for a PressCurve, as chosen by
the wacomcpl program, already in the initial _configuration_ file. Nice to
have a copy nearby when doing manual editing.

* Implemented a rudimentary error handler (xerror_handler in on_error.c) for
Xserver error returns. It is mostly a cosmetic thing, but now we can save the
message in error.log as well. The downside is that some of the informative
text from an unhandled X 'crash' is lost, like exactly which function call
that was involved. This can of course be rectified with a more complete handler,
but then the exit_on_error function needs additional parametres, and all the
calls to it need adjustments... Some other day.

* Discover the real mode of a stylus at program start, instead of assuming it
to be Absolute.

* Fixed a bug where -d together with any of -h, -s, -r and -k would delete a
live PID-file.

18 files changed:
ChangeLog
NEWS
README
TODO
USAGE
configure
configure.in
src-expresskeys/config_read.c
src-expresskeys/config_write.c
src-expresskeys/event_loop.c
src-expresskeys/exec_shell.c
src-expresskeys/get_device.c
src-expresskeys/globals.c
src-expresskeys/globals.h
src-expresskeys/main_setup.c
src-expresskeys/on_error.c
src-expresskeys/on_signal.c
src-expresskeys/reg_events.c

index 2cf1019..0a60a9e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,60 @@
 
+_Version 0.3.1 1 Sep 2006_
+
+* Graphire4 support. And what a chore it was! The task has revealed
+weaknesses in the overall code structuring which _must_ be attended to.
+So, a long time will pass on this end doing nothing but code refactoring.
+Graphire4 got hacked in by some serious "spaghetti"...
+
+OBSERVE: linuxwacom-0.7.5 or greater is _required_ for Graphire4 support!
+
+In that release an option called GetTabletID was introduced (in xsetwacom
+version 0.0.7), which gives us a reliable and future proof way of identifying
+the tablet model any device belongs to (pad, stylus etc).
+
+The function identify_device can be found in the exec_shell.c file, where
+presently only Graphire4 as a family is registered. A finer grained division
+is planned so that correct configuration files can be written out for the
+Graphire4 BlueTooth, which lacks a Scroll Wheel, and the Intuos3 4x5 with
+its single Touch Strip and 4 buttons.
+
+Thanks go to Carsten Schurig for e-mail access to a real Graphire4.
+Imagination and deducing can only produce the code, not verify it.
+
+And, as a sidenote to the verifying part, the Scroll Wheel of a Graphire4
+triggers button press/release events, (up = button 4, down = button 5) not
+axis motion events as has been stated on the linuxwacom web pages.
+
+* The -s switch to get status from a running program was added in the last
+24 hours before the 0.3.0 release, without much thought. It turns out not
+to be particularly useful in the intended manner. Standard error (stderr)
+where it prints the report is private to each shell session. So if the
+program already has been launched by one process, the next one who queries
+from another shell will see nothing.
+
+Therefore we now save a copy of the status output as a file as well in:
+~/.expresskeys/status.log The file gets created automatically at a daemon
+launch (updated with each -s query) and is deleted by a normal program exit.
+
+* Inform the user about the different values for a PressCurve, as chosen by
+the wacomcpl program, already in the initial _configuration_ file. Nice to
+have a copy nearby when doing manual editing.
+
+* Implemented a rudimentary error handler (xerror_handler in on_error.c) for
+Xserver error returns. It is mostly a cosmetic thing, but now we can save the
+message in error.log as well. The downside is that some of the informative
+text from an unhandled X 'crash' is lost, like exactly which function call
+that was involved. This can of course be rectified with a more complete handler,
+but then the exit_on_error function needs additional parametres, and all the
+calls to it need adjustments... Some other day.
+
+* Discover the real mode of a stylus at program start, instead of assuming it
+to be Absolute.
+
+* Fixed a bug where -d together with any of -h, -s, -r and -k would delete a
+live PID-file.
+
+
 _Version 0.3.0 27 Jul 2006_
 
 * Finally and totally obliterated the src-expresskeysconf directory.
@@ -23,11 +79,11 @@ a "padless.conf1" or an "intuos3.conf1" file is written out. Apart from
 only containing relevant record fields, the headers of these files are
 tagged with device "Identifier" strings from xorg.conf, like:
 
-_intuos3.conf1_                                                _padless.conf1_
+_intuos3.conf1_                         _padless.conf1_
 
-ConfigVersion 3                                                ConfigVersion 3
-Identifier1Pad 1stIntuos3Pad           Identifier1Pad LACKING
-Identifier1Sty 1stIntuos3Stylus1       Identifier1Sty Stylus1
+ConfigVersion 3                         ConfigVersion 3
+Identifier1Pad 1stIntuos3Pad            Identifier1Pad LACKING
+Identifier1Sty 1stIntuos3Stylus1        Identifier1Sty Stylus1
 
 The TODO file - better known as the "Wish-list" - hints towards why this
 filename change has become desirable...
diff --git a/NEWS b/NEWS
index b745f93..37afbe3 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,7 @@
 
 _Changes since last version. Executive summary_
 
-- New configuration file structure (open-ended). Automatic stylus PressCurve
-  usage. Automatic device detection on program start-up.
+- Graphire4 support (2 buttons and 1 wheel).
+
+OBSERVE: linuxwacom-0.7.5 or greater is _required_ for Graphire4 support!
 
diff --git a/README b/README
index 850028b..60eede3 100644 (file)
--- a/README
+++ b/README
@@ -1,6 +1,7 @@
 
 This program gives linux support for the ExpressKeys and Touch Strips
-of a Wacom Intuos3 tablet or a Cintiq 21UX Interactive Pen Display.
+of a Wacom Intuos3 tablet, a Cintiq 21UX Interactive Pen Display or
+the Scroll Wheel and two ExpressKeys of a Graphire4.
 
 It can also provide an automatic change of stylus pressure sensitivity
 - aka PressCurve - going from one program window to the next, by way
diff --git a/TODO b/TODO
index c6d149f..31ef9e2 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,8 +1,6 @@
 
 _Wish-list_
 
-+ Graphire4 support of their 2 buttons and 1 wheel.
-
 + Multi-device support (more than 1 stylus and 1 pad).
 
 + Replace ASCII with something more international, like UTF-8.
diff --git a/USAGE b/USAGE
index ab03c84..44262bb 100644 (file)
--- a/USAGE
+++ b/USAGE
@@ -22,6 +22,16 @@ in proximity.
 
 ///////////////////////////////////////////////////////////////////////////
 
+Important: linuxwacom-0.7.5 or greater is _required_ for Graphire4 support!
+
+A quick way to find out which release you have installed is to do a
+"xsetwacom -V" in a terminal (it should say 0.0.7 or more for linuxwacom-0.7.5
+and newer releases). Ask your distro maintainers to update the linuxwacom
+packages if they are too old. Or install from source yourself, it is not that
+hard...
+
+///////////////////////////////////////////////////////////////////////////
+
 Important: Gimp doesn't know _anything_ about a "pad" device, so the option
 File --> Preferences --> Input Devices --> Configure Extended Input Devices...
 --> [Device: pad  Mode: Disabled] is how it should be set. If you change it
@@ -50,7 +60,7 @@ Options can be written like -dv or -d -v in any place.
   -r re-reads the configuration file of a running daemon.
   -v prints info to the screen at many execution points.
   -x sets -v and exits after some important info blocks.
-  -s tells a daemon instance to report status (info block).
+  -s tells a daemon instance to report status (file/screen).
   -h unconditionally brings up this help text.
 
 Example1: expresskeys -d (first 'pad' and/or 'stylus' found get used)
@@ -68,7 +78,7 @@ See the BUGS file for further info.
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 * A minimal configuration file is written on first run to the user home
-directory: ~/.expresskeys/intuos3.conf1 (or padless.conf1)
+directory: ~/.expresskeys/intuos3.conf1 (graphire4.conf1 or padless.conf1)
 
 It contains "default", "Gimp", "Blender" and "XTerm" entries and is
 re-created whenever a configuration file is missing on program start.
@@ -87,6 +97,13 @@ close-down on some systems.
 
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
+* The ~/.expresskeys/status.log (created on program daemon launch) is updated
+whenever an "expresskeys -s" is used. It provides the same information as a
+non-daemon run with "expresskeys -x" would do. Just like the pid-file, it is
+deleted on normal program exit.
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
 * The configuration file is re-read when you do an "expresskeys -r" and a
 daemon instance of the program is running.
 
@@ -241,13 +258,13 @@ doesn't matter _where_. Put it last or first or wherever...
 
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
-NEW in expresskeys version 0.3.0:
+NEW in expresskeys version 0.3.0 and above:
 
 Config file version 3 is completely independent of how you organize the
 program fields or records. Only limitation is that all the fields must
 be _present_ somewhere in the record for it to be counted. In version 3
 that means 27 fields for a 'pad' device user ('stylus' field is included),
-and 2 fields for a 'stylus' device only user.
+11 fields for a Graphire4, and 2 fields for a 'stylus' device only user.
 
 This open-ended nature was enforced to facilitate the inclusion of
 future fields - or elimination of already existing ones - without
@@ -353,10 +370,12 @@ either stay with a level 3, or switch to a level 4 while painting.
 
 The "default" entry holds keycodes to make the pad buttons behave just
 as Wacom list them in the Quick Start Guide: Shift, Alt, Ctrl and Space
-mirrored on both sides. Touch Strip support is turned off by default. Use
-the number 1 in the "HandleTouchStrips" field to turn it on. You then get
-Arrow-key Up/Down on the left strip and Arrow-key Right/Left on the right.
-Change direction of the movement by switching the "Up" and "Down" values.
+mirrored on both sides. Touch Strip support is turned on by default. Use
+the number 0 in the "HandleTouchStrips" field to turn it off (a Graphire4
+user changes the "HandleScrollWheel" field). You get "Mouse-scrolling"
+Up/Down on the left strip and Arrow-key Right/Left on the right with the
+values currently written to the minimal config file. Change direction of
+the movement by switching the "Up" and "Down" values.
 
 Both pad buttons and touch strips can send two keys at a time if so
 configured through usage of the "...Plus" keycode fields.
index 2669c31..094481e 100755 (executable)
--- a/configure
+++ b/configure
@@ -1613,7 +1613,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE=expresskeys
- VERSION=0.3.0
+ VERSION=0.3.1
 
 
 cat >>confdefs.h <<_ACEOF
index 9c28dd6..912d13c 100644 (file)
@@ -4,7 +4,7 @@ dnl --- Style and some code below nicked from the linuxwacom package ;-) ---
 
 AC_INIT(src-expresskeys/main_setup.c)
 AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE(expresskeys, 0.3.0)
+AM_INIT_AUTOMAKE(expresskeys, 0.3.1)
 AM_MAINTAINER_MODE
 AC_PROG_CC
 
index 1a952b8..6e422ac 100644 (file)
@@ -27,7 +27,7 @@
  keywords). Returns nothing unless an error occured.
  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
-int read_file_config(int *ip, int *ihp, FILE *fp)
+int read_file_config(int *ip, FILE *fp)
 {
 
        struct program *p;
@@ -35,7 +35,12 @@ int read_file_config(int *ip, int *ihp, FILE *fp)
 
        /* Convert to long for x86_64 systems */
        p = (void *)(long)*ip;
-       hp = (void *)(long)*ihp;
+
+       if (is_graphire4) {
+               hp = gr4_human_readable;
+       } else {
+               hp = human_readable;
+       }
 
        int i;
        int j;
@@ -47,6 +52,7 @@ int read_file_config(int *ip, int *ihp, FILE *fp)
        int sane = 0;
        int programname_alloced = 0;
        int presscurve_alloced = 0;
+       int re_aligned = 0;
 
        int *field_index = 0;
        const char *string_index = 0;
@@ -124,6 +130,9 @@ int read_file_config(int *ip, int *ihp, FILE *fp)
                                                if (pad1_info) {
                                                        configfields = config3fields; /* Full 'pad' and 'stylus' */
                                                }
+                                               if (is_graphire4) {
+                                                       configfields = config3gr4fields; /* Tiny 'pad' and 'stylus' */
+                                               }
                                                configheaderfields = config3headerfields;
                                        } else {
                                                return 3;               /* Add handling when next version exist! */
@@ -176,6 +185,7 @@ int read_file_config(int *ip, int *ihp, FILE *fp)
                                        if ((newline = (strchr(read_buffer, '\n'))) != NULL) {
 
                                                keyword = hp->h_class_name;
+                                               re_aligned = 0;
 
 /* Keyword loop */             for (i = 0; i < configfields; i++) {
 
@@ -253,9 +263,24 @@ int read_file_config(int *ip, int *ihp, FILE *fp)
  structure through string length+1). */
                                                                                        field_index = &p->handle_touch;
                                                                                        string_index = hp->h_handle_touch;
-                                                                                       for (j = 0; j < (configfields - 2); j++) {
+                                                                                       for (j = 0; j <= (configfields - 2); j++) {
                                                                                                slen = strlen(string_index);
                                                                                                if ((strcmp(string_index, keyword)) == 0) {
+/* Time for another ugly hack...*/                                     if (is_graphire4) {
+                                                                                                               if ((strcmp(keyword, "LeftButton")) == 0) {
+                                                                                                                       field_index = &p->key_9;
+                                                                                                               }
+                                                                                                               if ((strcmp(keyword, "LeftButtonPlus")) == 0) {
+                                                                                                                       field_index = &p->key_9_plus;
+                                                                                                               }
+                                                                                                               if ((strcmp(keyword, "RightButton")) == 0) {
+                                                                                                                       field_index = &p->key_13;
+                                                                                                               }
+                                                                                                               if ((strcmp(keyword, "RightButtonPlus")) == 0) {
+                                                                                                                       field_index = &p->key_13_plus;
+                                                                                                               }
+                                                                                                       }
+/* Just until I understand!*/
 /* Write the field to memory structure */                      *field_index = atoi(write_buffer);
                                                                                                        num_field++;
                                                                                                        break;
@@ -269,6 +294,12 @@ int read_file_config(int *ip, int *ihp, FILE *fp)
                                                                }
                                                        }
                                                        keyword = keyword+klen+1; /* Steps to the next string member in the struct */
+/* This is such a HACK*/       if (!re_aligned) {
+/* Because I don't know*/              if ((programname_alloced) && (presscurve_alloced)) {
+/* How to traverse structs*/           keyword = hp->h_handle_touch;
+/* Refactor after graphire4!*/         re_aligned = 1;
+                                                               }
+                                                       }
                                                }
 /* End keyword loop */
                                        } else {
index b822011..a264f5e 100644 (file)
@@ -42,7 +42,7 @@ int write_file_config_header(FILE *fp)
        fprintf(fp, "# Blank lines and everything following a comment \"#\" sign are ignored.\n\n");
        fprintf(fp, "# This file will be re-created whenever missing, but the name and layout depend\n");
        fprintf(fp, "# on which devices that are detected at the very moment of program execution.\n\n");
-       if (pad1_info) {
+       if ((pad1_info) && (!is_graphire4)) {
                fprintf(fp, "# Some ASCII art showing the \"default\" program record:\n");
                fprintf(fp, "#\n");
                fprintf(fp, "# Left ExpressKey Pad\n");
@@ -65,6 +65,8 @@ int write_file_config_header(FILE *fp)
                fprintf(fp, "# | H |  16  |             Button 16 = Space               = keycode 65\n");
                fprintf(fp, "# ------------\n");
                fprintf(fp, "#\n");
+       }
+       if ((pad1_info) || (is_graphire4)) {
                fprintf(fp, "# Use the value 999 as a keycode to enable pen mode toggling. To be able\n");
                fprintf(fp, "# to switch mode anywhere each program block must then contain one 999\n");
                fprintf(fp, "# definition.\n\n");
@@ -72,12 +74,27 @@ int write_file_config_header(FILE *fp)
                fprintf(fp, "# mouse buttons, defined through the driver of the active core pointer, can be\n");
                fprintf(fp, "# simulated.\n\n");
        }
+       fprintf(fp, "# Values for the stylus 'PressCurve' ie 'sensitivity' can be chosen the easy\n");
+       fprintf(fp, "# way - copying from how the wacomcpl program writes them, or the hard way -\n");
+       fprintf(fp, "# by experimenting... The seven curves picked by wacomcpl are (Soft to Firm):\n");
+       fprintf(fp, "# 1               2               3               4 (default)\n");
+       fprintf(fp, "# \"0 75 25 100\" | \"0 50 50 100\" | \"0 25 75 100\" | \"0 0 100 100\"\n");
+       fprintf(fp, "# 5               6               7\n");
+       fprintf(fp, "# \"25 0 100 75\" | \"50 0 100 50\" | \"75 0 100 25\"\n\n");
        fprintf(fp, "# OBSERVE: The \"default\" program record must exist _somewhere_ in the file!\n");
        fprintf(fp, "# Each program record is separated by one set of double percentage signs: %s\n", "%%");
        fprintf(fp, "# Each program field begins after a case sensitive keyword, eg: ProgramName\n");
        fprintf(fp, "# Whitespace (tabs and spaces) are ignored in the keycode fields, but spaces\n");
        fprintf(fp, "# are recorded when in a ProgramName or Stylus1PressCurve field (between the\n");
        fprintf(fp, "# double quotes).\n\n");
+       if (is_graphire4) {
+               fprintf(fp, "# Graphire4 user: Sorry about the automatic keycodes written here. They are\n");
+               fprintf(fp, "# not optimal, to say the least, but picked from a larger set intended for\n");
+               fprintf(fp, "# an Intuos3 (with its different button order). Perhaps we can write out a\n");
+               fprintf(fp, "# more correct initial configuration file in a later version... Also, to you\n");
+               fprintf(fp, "# BlueTooth users, the Scroll Wheel entries will disappear when a finer\n");
+               fprintf(fp, "# grained configuration file can be written.\n\n");
+       }
 
        return 0;
 
@@ -96,39 +113,58 @@ int write_file_config(int *ip, FILE *fp)
 
        struct program *p;
        struct configstrings *hp;
-       hp = human_readable;
-       /* Convert to long for x86_64 systems */
+/* Convert to long for x86_64 systems */
        p = (void *)(long)*ip;
 
+       if (is_graphire4) {
+               hp = gr4_human_readable;
+       } else {
+               hp = human_readable;
+       }
+
        fprintf(fp, "%s                 # <---  ********** BEGIN NEW PROGRAM RECORD **********\n\n", "%%");
-       fprintf(fp, "%s         \"%s\" # Name must be within double quotes \"\"\n\n", hp->h_class_name, p->class_name);
-       fprintf(fp, "%s \"%s\" # PressCurve must be within double quotes \"\"\n\n", hp->h_stylus1_presscurve, p->stylus1_presscurve);
-       if (pad1_info) {
-               fprintf(fp, "%s %d      # Main switch. Use 1 to enable the Touch Strips\n\n", hp->h_handle_touch, p->handle_touch);
+       if (!is_graphire4) {
+               fprintf(fp, "%s         \"%s\" # Name must be within double quotes \"\"\n\n", hp->h_class_name, p->class_name);
+               fprintf(fp, "%s \"%s\" # PressCurve must be within double quotes \"\"\n\n", hp->h_stylus1_presscurve, p->stylus1_presscurve);
+               if (pad1_info) {
+                       fprintf(fp, "%s %d      # Main switch. Use 1 to enable the Touch Strips\n\n", hp->h_handle_touch, p->handle_touch);
+                       fprintf(fp, "%s         %d      # First keycode\n", hp->h_l_touch_up, p->l_touch_up);
+                       fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_l_touch_up_plus, p->l_touch_up_plus);
+                       fprintf(fp, "%s %d      # First keycode\n", hp->h_l_touch_down, p->l_touch_down);
+                       fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_l_touch_down_plus, p->l_touch_down_plus);
+                       fprintf(fp, "%s         %d      # First keycode\n", hp->h_r_touch_up, p->r_touch_up);
+                       fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_r_touch_up_plus, p->r_touch_up_plus);
+                       fprintf(fp, "%s %d      # First keycode\n", hp->h_r_touch_down, p->r_touch_down);
+                       fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_r_touch_down_plus, p->r_touch_down_plus);
+                       fprintf(fp, "%s         %d      # First keycode\n", hp->h_key_9, p->key_9);
+                       fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_key_9_plus, p->key_9_plus);
+                       fprintf(fp, "%s         %d      # First keycode\n", hp->h_key_10, p->key_10);
+                       fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_key_10_plus, p->key_10_plus);
+                       fprintf(fp, "%s         %d      # First keycode\n", hp->h_key_11, p->key_11);
+                       fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_key_11_plus, p->key_11_plus);
+                       fprintf(fp, "%s         %d      # First keycode\n", hp->h_key_12, p->key_12);
+                       fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_key_12_plus, p->key_12_plus);
+                       fprintf(fp, "%s %d      # First keycode\n", hp->h_key_13, p->key_13);
+                       fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_key_13_plus, p->key_13_plus);
+                       fprintf(fp, "%s %d      # First keycode\n", hp->h_key_14, p->key_14);
+                       fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_key_14_plus, p->key_14_plus);
+                       fprintf(fp, "%s %d      # First keycode\n", hp->h_key_15, p->key_15);
+                       fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_key_15_plus, p->key_15_plus);
+                       fprintf(fp, "%s %d      # First keycode\n", hp->h_key_16, p->key_16);
+                       fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_key_16_plus, p->key_16_plus);
+               }
+       } else {
+               fprintf(fp, "%s         \"%s\" # Name must be within double quotes \"\"\n\n", hp->h_class_name, p->class_name);
+               fprintf(fp, "%s \"%s\" # PressCurve must be within double quotes \"\"\n\n", hp->h_stylus1_presscurve, p->stylus1_presscurve);
+               fprintf(fp, "%s %d      # Main switch. Use 1 to enable the Scroll Wheel\n\n", hp->h_handle_touch, p->handle_touch);
                fprintf(fp, "%s         %d      # First keycode\n", hp->h_l_touch_up, p->l_touch_up);
                fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_l_touch_up_plus, p->l_touch_up_plus);
-               fprintf(fp, "%s %d      # First keycode\n", hp->h_l_touch_down, p->l_touch_down);
+               fprintf(fp, "%s         %d      # First keycode\n", hp->h_l_touch_down, p->l_touch_down);
                fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_l_touch_down_plus, p->l_touch_down_plus);
-               fprintf(fp, "%s         %d      # First keycode\n", hp->h_r_touch_up, p->r_touch_up);
-               fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_r_touch_up_plus, p->r_touch_up_plus);
-               fprintf(fp, "%s %d      # First keycode\n", hp->h_r_touch_down, p->r_touch_down);
-               fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_r_touch_down_plus, p->r_touch_down_plus);
                fprintf(fp, "%s         %d      # First keycode\n", hp->h_key_9, p->key_9);
-               fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_key_9_plus, p->key_9_plus);
-               fprintf(fp, "%s         %d      # First keycode\n", hp->h_key_10, p->key_10);
-               fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_key_10_plus, p->key_10_plus);
-               fprintf(fp, "%s         %d      # First keycode\n", hp->h_key_11, p->key_11);
-               fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_key_11_plus, p->key_11_plus);
-               fprintf(fp, "%s         %d      # First keycode\n", hp->h_key_12, p->key_12);
-               fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_key_12_plus, p->key_12_plus);
-               fprintf(fp, "%s %d      # First keycode\n", hp->h_key_13, p->key_13);
-               fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_key_13_plus, p->key_13_plus);
-               fprintf(fp, "%s %d      # First keycode\n", hp->h_key_14, p->key_14);
-               fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_key_14_plus, p->key_14_plus);
-               fprintf(fp, "%s %d      # First keycode\n", hp->h_key_15, p->key_15);
-               fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_key_15_plus, p->key_15_plus);
-               fprintf(fp, "%s %d      # First keycode\n", hp->h_key_16, p->key_16);
-               fprintf(fp, "%s %d      # Extra keycode\n\n", hp->h_key_16_plus, p->key_16_plus);
+               fprintf(fp, "%s         %d      # Extra keycode\n\n", hp->h_key_9_plus, p->key_9_plus);
+               fprintf(fp, "%s         %d      # First keycode\n", hp->h_key_13, p->key_13);
+               fprintf(fp, "%s         %d      # Extra keycode\n\n", hp->h_key_13_plus, p->key_13_plus);
        }
        return 0;
 }
index 3cda2aa..7d9ece8 100644 (file)
@@ -218,7 +218,7 @@ int use_events(Display *display)
 
 /* Next we look for Touch Strip events */
 
-                       if (Event.type == motion_type) {
+                       if ((Event.type == motion_type) && (!is_graphire4)) {
                                if (pad1_info) {
 
                                        if (p->handle_touch) {
@@ -286,8 +286,8 @@ int use_events(Display *display)
                                                                                }
                                                                        }
                                                                }
-                                                       elder_rotation = old_rotation;
-                                                       old_rotation = rotation;
+                                                               elder_rotation = old_rotation;
+                                                               old_rotation = rotation;
                                                        }
 
 /* Right Touch Strip */
@@ -336,8 +336,8 @@ int use_events(Display *display)
                                                                                }
                                                                        }
                                                                }
-                                                       elder_throttle = old_throttle;
-                                                       old_throttle = throttle;
+                                                               elder_throttle = old_throttle;
+                                                               old_throttle = throttle;
                                                        }
                                                }
                                        }
@@ -377,40 +377,73 @@ Right ExpressKey Pad
 
                                        button = (XDeviceButtonEvent *) &Event;
                                        if (button->deviceid == pad1_info->id) {
-                                               button_index = &p->key_9;
 
-                                               for (i = 9; i < button->button; i++) {
-                                                       button_index++;
-                                                       button_index++;
-                                               }
+                                               if (button->button >= 9) {
+                                                       button_index = &p->key_9;
+
+                                                       for (i = 9; i < button->button; i++) {
+                                                               button_index++;
+                                                               button_index++;
+                                                       }
 
-                                               if (*button_index == TOGGLE_STYLUS1) {
-                                                       if (stylus1_info) {
+                                                       if (*button_index == TOGGLE_STYLUS1) {
+                                                               if (stylus1_info) {
+                                                                       if (be_verbose) {
+                                                                               fprintf(stderr, "BTN %d = %d dn\n", button->button, *button_index);
+                                                                       }
+                                                                       toggle_stylus1_mode(display, stylus1_name);
+                                                               }
+                                                       } else if ((*button_index >= STYLUS1_CURVE_DOWNWARD)
+                                                                               && (*button_index <= STYLUS1_CURVE_UPWARD)
+                                                                               && (stylus1_info)) {
                                                                if (be_verbose) {
                                                                        fprintf(stderr, "BTN %d = %d dn\n", button->button, *button_index);
                                                                }
-                                                               toggle_stylus1_mode(display, stylus1_name);
-                                                       }
-                                               } else if ((*button_index >= STYLUS1_CURVE_DOWNWARD)
-                                                                       && (*button_index <= STYLUS1_CURVE_UPWARD)
-                                                                       && (stylus1_info)) {
-                                                       if (be_verbose) {
-                                                               fprintf(stderr, "BTN %d = %d dn\n", button->button, *button_index);
+                                                               call_xsetwacom(*button_index);
+
+                                                       } else {
+                                                               if (*button_index) {
+                                                                       fake_event(display, *button_index, True, CurrentTime );
+                                                                       if (be_verbose) {
+                                                                               fprintf(stderr, "BTN %d = %d dn\n", button->button, *button_index);
+                                                                       }
+                                                               }
+                                                               button_index++;
+                                                               if (*button_index) {
+                                                                       fake_event(display, *button_index, True, CurrentTime );
+                                                                       if (be_verbose) {
+                                                                               fprintf(stderr, "BTN+ %d = %d dn\n", button->button, *button_index);
+                                                                       }
+                                                               }
                                                        }
-                                                       call_xsetwacom(*button_index);
 
-                                               } else {
-                                                       if (*button_index) {
-                                                               fake_event(display, *button_index, True, CurrentTime );
-                                                               if (be_verbose) {
-                                                                       fprintf(stderr, "BTN %d = %d dn\n", button->button, *button_index);
+/*Graphire4 hack*/             } else if (p->handle_touch) {
+                                                       if (button->button == 4) {
+                                                               if (p->l_touch_up) {
+                                                                       fake_event(display, p->l_touch_up, True, CurrentTime);
+                                                                       if (be_verbose) {
+                                                                               fprintf(stderr, "SWHLUP = %d dn\n", p->l_touch_up);
+                                                                       }
+                                                               }
+                                                               if (p->l_touch_up_plus) {
+                                                                       fake_event(display, p->l_touch_up_plus, True, CurrentTime);
+                                                                       if (be_verbose) {
+                                                                               fprintf(stderr, "SWHLUP+ = %d dn\n", p->l_touch_up_plus);
+                                                                       }
                                                                }
                                                        }
-                                                       button_index++;
-                                                       if (*button_index) {
-                                                               fake_event(display, *button_index, True, CurrentTime );
-                                                               if (be_verbose) {
-                                                                       fprintf(stderr, "BTN+ %d = %d dn\n", button->button, *button_index);
+                                                       if (button->button == 5) {
+                                                               if (p->l_touch_down) {
+                                                                       fake_event(display, p->l_touch_down, True, CurrentTime);
+                                                                       if (be_verbose) {
+                                                                               fprintf(stderr, "SWHLDN = %d dn\n", p->l_touch_down);
+                                                                       }
+                                                               }
+                                                               if (p->l_touch_down_plus) {
+                                                                       fake_event(display, p->l_touch_down_plus, True, CurrentTime);
+                                                                       if (be_verbose) {
+                                                                               fprintf(stderr, "SWHLDN+ = %d dn\n", p->l_touch_down_plus);
+                                                                       }
                                                                }
                                                        }
                                                }
@@ -425,38 +458,71 @@ Right ExpressKey Pad
 
                                        button = (XDeviceButtonEvent *) &Event;
                                        if (button->deviceid == pad1_info->id) {
-                                               button_index = &p->key_9;
 
-                                               for (i = 9; i < button->button; i++) {
-                                                       button_index++;
-                                                       button_index++;
-                                               }
+                                               if (button->button >= 9) {
+                                                       button_index = &p->key_9;
+
+                                                       for (i = 9; i < button->button; i++) {
+                                                               button_index++;
+                                                               button_index++;
+                                                       }
 
-                                               if (*button_index == TOGGLE_STYLUS1) {
-                                                       if (stylus1_info) {
+                                                       if (*button_index == TOGGLE_STYLUS1) {
+                                                               if (stylus1_info) {
+                                                                       if (be_verbose) {
+                                                                               fprintf(stderr, "BTN %d = %d up\n", button->button, *button_index);
+                                                                       }
+                                                               }
+                                                       } else if ((*button_index >= STYLUS1_CURVE_DOWNWARD)
+                                                                               && (*button_index <= STYLUS1_CURVE_UPWARD)
+                                                                               && (stylus1_info)) {
                                                                if (be_verbose) {
                                                                        fprintf(stderr, "BTN %d = %d up\n", button->button, *button_index);
                                                                }
+                                                       } else {
+                                                               button_index++;
+                                                               if (*button_index) {
+                                                                       fake_event(display, *button_index, False, CurrentTime );
+                                                                       if (be_verbose) {
+                                                                               fprintf(stderr, "BTN+ %d = %d up\n", button->button, *button_index);
+                                                                       }
+                                                               }
+                                                               button_index--;
+                                                               if (*button_index) {
+                                                                       fake_event(display, *button_index, False, CurrentTime );
+                                                                       if (be_verbose) {
+                                                                               fprintf(stderr, "BTN %d = %d up\n", button->button, *button_index);
+                                                                       }
+                                                               }
                                                        }
-                                               } else if ((*button_index >= STYLUS1_CURVE_DOWNWARD)
-                                                                       && (*button_index <= STYLUS1_CURVE_UPWARD)
-                                                                       && (stylus1_info)) {
-                                                       if (be_verbose) {
-                                                               fprintf(stderr, "BTN %d = %d up\n", button->button, *button_index);
-                                                       }
-                                               } else {
-                                                       button_index++;
-                                                       if (*button_index) {
-                                                               fake_event(display, *button_index, False, CurrentTime );
-                                                               if (be_verbose) {
-                                                                       fprintf(stderr, "BTN+ %d = %d up\n", button->button, *button_index);
+
+/*Graphire4 hack*/             } else if (p->handle_touch) {
+                                                       if (button->button == 4) {
+                                                               if (p->l_touch_up_plus) {
+                                                                       fake_event(display, p->l_touch_up_plus, False, CurrentTime);
+                                                                       if (be_verbose) {
+                                                                               fprintf(stderr, "SWHLUP+ = %d up\n", p->l_touch_up_plus);
+                                                                       }
+                                                               }
+                                                               if (p->l_touch_up) {
+                                                                       fake_event(display, p->l_touch_up, False, CurrentTime);
+                                                                       if (be_verbose) {
+                                                                               fprintf(stderr, "SWHLUP = %d up\n", p->l_touch_up);
+                                                                       }
                                                                }
                                                        }
-                                                       button_index--;
-                                                       if (*button_index) {
-                                                               fake_event(display, *button_index, False, CurrentTime );
-                                                               if (be_verbose) {
-                                                                       fprintf(stderr, "BTN %d = %d up\n", button->button, *button_index);
+                                                       if (button->button == 5) {
+                                                               if (p->l_touch_down_plus) {
+                                                                       fake_event(display, p->l_touch_down_plus, False, CurrentTime);
+                                                                       if (be_verbose) {
+                                                                               fprintf(stderr, "SWHLDN+ = %d up\n", p->l_touch_down_plus);
+                                                                       }
+                                                               }
+                                                               if (p->l_touch_down) {
+                                                                       fake_event(display, p->l_touch_down, False, CurrentTime);
+                                                                       if (be_verbose) {
+                                                                               fprintf(stderr, "SWHLDN = %d up\n", p->l_touch_down);
+                                                                       }
                                                                }
                                                        }
                                                }
index 7c0defc..637849e 100644 (file)
@@ -36,7 +36,6 @@
 
 int call_xsetwacom(int num)
 {
-
        char buffer [MAXBUFFER];
        char curve [12];
 
@@ -106,7 +105,65 @@ int call_xsetwacom(int num)
                }
        }
        return 0;
+}
 
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Function uses the "popen" command which creates a pipe, forks and invokes
+ a shell where xsetwacom can be run. First action is to ensure that version
+ 0.0.7 or greater of xsetwacom is present (ie linuxwacom-0.7.5 where the
+ option GetTabletID was introduced). Thereafter we match the tablet decimal
+ number string against known Graphire4 numbers. A full table can be found in
+ src/xdrv/wcmUSB.c of the linuxwacom sources (Hex numbers).
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+int identify_device(char *name)
+{
+       const char *graphire4_4x5 = "21"; /* 0x15 */
+       const char *graphire4_6x8 = "22"; /* 0x16 */
+       const char *graphire4_6x8_BT = "129"; /* 0x81 */
+       const int min_xsetwacom = 7; /* Minimum xsetwacom version we can use is 0.0.7 */
+
+       char read_buffer [MAXBUFFER];
+       char write_buffer [MAXBUFFER];
+
+       int len = 0;
+       int i, j = 0;
+       int ok_xsetwacom = 0;
+
+       FILE *execfp = NULL;
+
+       if ((execfp = popen("xsetwacom -V", "r")) != NULL) {
+               fgets(read_buffer, MAXBUFFER, execfp);
+               if ((pclose(execfp)) == 0) {
+                       len = strcspn(read_buffer, " \t\n");
+                       for (i = 0; i < len; i++) {
+                               if (isdigit(read_buffer[i])) {
+                                       write_buffer[j] = read_buffer[i];
+                                       j++;
+                               }
+                       }
+                       write_buffer[j] = '\0';
+                       if ((atoi(write_buffer)) >= min_xsetwacom) {
+                               ok_xsetwacom = 1;
+                       }
+               }
+       }
+
+       if (ok_xsetwacom) {
+               snprintf(write_buffer, MAXBUFFER, "xsetwacom get %s GetTabletID", name);
+               if ((execfp = popen(write_buffer, "r")) != NULL) {
+                       fgets(read_buffer, MAXBUFFER, execfp);
+                       if ((pclose(execfp)) == 0) {
+                               len = strcspn(read_buffer, " \t\n");
+                               if (((strncmp(read_buffer, graphire4_4x5, len)) == 0)
+                                       || ((strncmp(read_buffer, graphire4_6x8, len)) == 0)
+                                       || ((strncmp(read_buffer, graphire4_6x8_BT, len)) == 0)) {
+                                       is_graphire4 = 1;
+                               }
+                       }
+               }
+       }
+       return 0;
 }
 
 /* End Code */
index a9abe46..5d1f39f 100644 (file)
 /* get_device_info returns a long to satisfy x86_64 systems */
 long get_device_info(Display *display, XDeviceInfo *info, char *name)
 {
-       int     i, j, c;
+       int     i, j, k, c;
        int     nr_devices;
        int len = 0;
 
        char read_buffer [MAXBUFFER];
        char write_buffer [MAXBUFFER];
 
+       XValuatorInfoPtr valuator;
+       XAnyClassPtr anyclass;
+
        info = XListInputDevices(display, &nr_devices);
 
        if (!pad1_info_block) {
@@ -56,6 +59,16 @@ long get_device_info(Display *display, XDeviceInfo *info, char *name)
                for(i = 0; i < nr_devices; i++) {
                        if ((info[i].use == IsXExtensionDevice) &&
                        (strcmp (info[i].name, name) == 0)) {
+                               anyclass = (XAnyClassPtr)(info[i].inputclassinfo);
+                               for (k = 0; k < info[i].num_classes; k++) {
+                                       if (anyclass->class == ValuatorClass) {
+                                               valuator = (XValuatorInfoPtr) anyclass;
+                                               if (stylus1_info_block == info) {
+                                                       stylus1_mode = valuator->mode;
+                                               }
+                                       }
+                                       anyclass = (XAnyClassPtr)((char *)anyclass + anyclass->length);
+                               }
                                /* Convert to long for x86_64 systems */
                                return (long) &info[i];
                        }
@@ -77,6 +90,16 @@ long get_device_info(Display *display, XDeviceInfo *info, char *name)
                                        }
                                        strncpy(write_buffer + len, "\0", 1);
                                        if ((strstr(write_buffer, name)) !=NULL) {
+                                               anyclass = (XAnyClassPtr)(info[i].inputclassinfo);
+                                               for (k = 0; k < info[i].num_classes; k++) {
+                                                       if (anyclass->class == ValuatorClass) {
+                                                               valuator = (XValuatorInfoPtr) anyclass;
+                                                               if ((strstr(write_buffer, "stylus"))) {
+                                                                       stylus1_mode = valuator->mode;
+                                                               }
+                                                       }
+                                                       anyclass = (XAnyClassPtr)((char *)anyclass + anyclass->length);
+                                               }
                                                /* Convert to long for x86_64 systems */
                                                return (long) &info[i];
                                        }
index d30aba3..0602dcb 100644 (file)
@@ -32,7 +32,7 @@ char *configstring = "ConfigVersion"; /* Searchable string in the config file */
 char *configversion = "3"; /* Our version. Remember to change it if necessary! */
 char *pad1idstring = "Identifier1Pad";         /* Marker to bind tablet and config file */
 char *stylus1idstring = "Identifier1Sty";      /* Marker that can't bind... */
-char *our_prog_version = "0.3.0"; /* Our version. Remember to change it! */
+char *our_prog_version = "0.3.1"; /* Our version. Remember to change it! */
 char *our_prog_name;
 char *pad1_name = 0;
 char *pad1_autoname = "pad";
@@ -42,10 +42,12 @@ char *total_config_dir;
 char *total_config_file;
 char *total_pid_file;
 char *total_error_file;
+char *total_status_file;
 char *config_dir = "/.expresskeys";    /* This is where in the user home */
 char *config_file = 0;                         /* directory we'd like to reside, */
 char *pid_file = "/expresskeys.pid";   /* and what our different status */
 char *error_file = "/error.log";       /* files should be called */
+char *status_file = "/status.log";
 char *config_file_padless = "/padless.conf1";
 char *config_file_intuos3 = "/intuos3.conf1";
 char *config_file_graphire4 = "/graphire4.conf1";
@@ -54,14 +56,15 @@ int userconfigversion = 0; /* Keep track of which format the user has */
 int config3headerfields = 3; /* Number of fields in the header of a configversion 3 file */
 int configheaderfields = 0; /* How many header fields to actually parse in each file */
 int config3fields = 27; /* Number of fields in a configversion 3 record */
+int config3gr4fields = 11; /* Number of fields if tablet is a Graphire4 */
 int configfields = 0; /* How many fields to actually parse in each record */
 int screen;                    /* Active screen. An X thing */
+int is_graphire4 = 0;  /* Only flag if it is so */
 int just_exit = 0;     /* Do not terminate the program immediately */
 int go_daemon = 0;     /* Do not become a daemon without a command */
-int second_instance = 0; /* Prevent a running program's PID file from erasure */
 int be_verbose = 0; /* Run silently per default */
 int reread_config = 0; /* No memory should be freed on the first read */
-int stylus1_mode = 1;  /* Assume pen is in Absolute mode initially */
+int stylus1_mode = 1;  /* Pen initially in Absolute mode. Real value discovered later */
 int padstylus1_presscurve = 4; /* Stylus default Sensitivity. Sample xsetwacom usage */
 
 int motion_type = NON_VALID;
@@ -77,9 +80,9 @@ struct program *default_program; /* Pointer to the "default" program record */
 struct program external_list [MAXRECORDS];
 struct program internal_list[] = {
 /*     Name    stylus1_presscurve      handle_touch */
-{"default",    "0 0 100 100",  0,
+{"default",    "0 0 100 100",  1,
 /*             l_touch_up      l_touch_up_plus l_touch_down    l_touch_down_plus */
-               98,             0,              104,            0,
+               994,            0,              995,            0,
 /*             r_touch_up      r_touch_up_plus r_touch_down    r_touch_down_plus */
                102,            0,              100,            0,
 /*             key_9           key_9_plus      key_10          key_10_plus */
@@ -139,7 +142,7 @@ struct program internal_list[] = {
 /* The number of programs (num_list) must be computed here. After the struct */
 int num_list = (sizeof internal_list / sizeof internal_list[0]);
 
-/* These are the keywords prefacing a value in the config file */
+/* These are the keywords prefacing a value in the Intuos3 config file */
 struct configstrings human_readable[] = {
 {"ProgramName", "Stylus1PressCurve", "HandleTouchStrips",
 "LeftPadTouchUp", "LeftPadTouchUpPlus",
@@ -156,5 +159,15 @@ struct configstrings human_readable[] = {
 "RightPadButton16", "RightPadButton16Plus" }
 };
 
+/* These are the keywords prefacing a value in the Graphire4 config file */
+struct configstrings gr4_human_readable[] = {
+{"ProgramName", "Stylus1PressCurve", "HandleScrollWheel",
+"ScrollWheelUp", "ScrollWheelUpPlus",
+"ScrollWheelDown", "ScrollWheelDownPlus",
+"dummy", "dummy", "dummy", "dummy", "LeftButton", "LeftButtonPlus",
+"dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "RightButton", "RightButtonPlus",
+"dummy", "dummy", "dummy", "dummy", "dummy", "dummy" }
+};
+
 /* End Code */
 
index 95f54a9..1f39302 100644 (file)
@@ -80,26 +80,27 @@ extern char *total_config_dir;      /* The "~/" of the user, plus our config_dir */
 extern char *total_config_file;        /* total_config_dir plus config_file */
 extern char *total_pid_file;   /* total_config_dir plus pid_file */
 extern char *total_error_file; /* total_config_dir plus error_file */
+extern char *total_status_file;        /* total_config_dir plus status_file */
 extern char *config_dir;       /* Set to a dot directory: .expresskeys */
 extern char *config_file;      /* Set to NULL */
 extern char *pid_file;         /* Set to expresskeys.pid */
 extern char *error_file;       /* Set to error.log */
+extern char *status_file;      /* Set to status.log */
 extern char *config_file_padless;
 extern char *config_file_intuos3;
 extern char *config_file_graphire4;
 
-
 extern int userconfigversion; /* Keep track of which format to parse */
 extern int config3headerfields; /* Nr. of fields in the header of a configversion 3 file */
 extern int configheaderfields; /* The decided number of fields to parse in each file */
 extern int config3fields; /* Nr. of fields in a configversion 3 record: globals.c! */
+extern int config3gr4fields; /* Graphire4 fields, see globals.c! */
 extern int configfields; /* The decided number of fields to parse in each record */
 extern int screen;     /* Active screen. An X thing */
 extern int num_list;   /* Number of programs we currently handle */
-
+extern int is_graphire4; /* Flag for writing out the correct configuration file */
 extern int just_exit;  /* Flag to see if we should exit the program immediately */
 extern int go_daemon;  /* Flag to see if this program is in daemon mode */
-extern int second_instance; /* Flag it if a second instance of a daemon run is tried */
 extern int be_verbose; /* Flag to see if we should be spitting out info */
 extern int reread_config; /* Flag for memory release if re-reading the config */
 extern int stylus1_mode;       /* Flag to keep track of the stylus mode we are in */
@@ -113,13 +114,15 @@ extern int proximity_in_type;     /* Event type to keep track of - Stylus In */
 /* Our global (internal) functions */
 extern int write_file_config_header(FILE *fp);
 extern int write_file_config(int *ip, FILE *fp);
-extern int read_file_config(int *ip, int *ihp, FILE *fp);
+extern int read_file_config(int *ip, FILE *fp);
 /* get_device_info returns a long to satisfy x86_64 systems */
 extern long get_device_info(Display *display, XDeviceInfo *info, char *name);
 extern int register_events(Display *display, XDeviceInfo *dev_info, char *name);
 extern int toggle_stylus1_mode(Display *display, char *name);
 extern int use_events(Display *display);
 extern int call_xsetwacom(int num);
+extern int identify_device(char *name);
+extern int xerror_handler(Display *display, XErrorEvent *error_event);
 extern void exit_on_error(FILE *fp, char *string1, char *string2, char *string3);
 extern void re_read_file_config(int signum);
 extern void status_report(int signum);
@@ -198,7 +201,7 @@ extern struct configstrings {
        char *h_key_15_plus;
        char *h_key_16;
        char *h_key_16_plus;
-}human_readable [];
+}human_readable [], gr4_human_readable [];
 
 /* End Code */
 
index e68d32e..d0174b5 100644 (file)
@@ -28,11 +28,10 @@ int main (int argc, char *argv[])
        int len = 0;
 
        struct program *p;
-       struct configstrings *hp;
 
        FILE *fp = NULL;
        FILE *errorfp = NULL;
-
+       
 /* Locate the home directory of the user running this program */
 
        char *user_homedir;
@@ -72,6 +71,16 @@ int main (int argc, char *argv[])
        sprintf(total_error_file_block, "%s%s", total_config_dir, error_file);
        total_error_file = total_error_file_block;
 
+/* Concatenate the full path with the status file name. Store address */
+
+       char *total_status_file_block;
+       len = strlen(total_config_dir) + strlen(status_file) + 1;
+       if ((total_status_file_block = (char *)malloc(len)) == NULL) {
+               exit_on_error(errorfp, "%s ERROR: Memory allocation trouble at stage 4!\n", our_prog_name, "");
+       }
+       sprintf(total_status_file_block, "%s%s", total_config_dir, status_file);
+       total_status_file = total_status_file_block;
+
 /* Try to open the the configuration directory for reading, just as a
    test to see if it exists. A failure here can mean many things, but we
    then try to create it as a means to rule out a true lack of existence */
@@ -116,6 +125,10 @@ int main (int argc, char *argv[])
                exit_on_error(errorfp, "%s ERROR: XInput extension not present on your X server\n", our_prog_name, "");
        }
 
+/* Register our error handler for Xserver error returns */
+
+       XSetErrorHandler(xerror_handler);
+
 /* Automatically discover, open and register events with the first devices
    that contain the string 'pad' and/or 'stylus' in their xorg.conf "Identifier"
    entries (case insensitive). These devices will be invalidated if the user
@@ -124,6 +137,7 @@ int main (int argc, char *argv[])
 
        pad1_info = (void *) get_device_info(display, pad1_info_block, pad1_autoname);
        if (pad1_info) {
+               identify_device(pad1_info->name);
                if (register_events(display, pad1_info, pad1_info->name)) {
                        pad1_autoname = pad1_info->name;
                } else {
@@ -255,7 +269,7 @@ int main (int argc, char *argv[])
                fprintf(stderr, "  -r re-reads the configuration file of a running daemon.\n");
                fprintf(stderr, "  -v prints info to the screen at many execution points.\n");
                fprintf(stderr, "  -x sets -v and exits after some important info blocks.\n");
-               fprintf(stderr, "  -s tells a daemon instance to report status (info block).\n");
+               fprintf(stderr, "  -s tells a daemon instance to report status (file/screen).\n");
                fprintf(stderr, "  -h unconditionally brings up this help text.\n");
                fprintf(stderr, "\n");
                fprintf(stderr, "Example1: %s -d (first 'pad' and/or 'stylus' found get used)\n", our_prog_name);
@@ -264,6 +278,7 @@ int main (int argc, char *argv[])
                fprintf(stderr, "\n");
                fprintf(stderr, "Please direct any bug reports or questions to the top address\n");
                fprintf(stderr, "in the AUTHORS file. This program is _not_ a linuxwacom project.\n");
+               go_daemon = 0; /* Prevent a live PID-file deletion */
                exit_on_error(errorfp, "", "", "");
        }
 
@@ -285,8 +300,9 @@ int main (int argc, char *argv[])
        if ((fp = fopen(total_pid_file, "r")) != NULL) { /* File exists */
                fgets(pid_buffer, MAXBUFFER, fp);
                fclose(fp);
-               if (((kill(atoi(pid_buffer), 0)) != NON_VALID)) { /* Live pid-file */
+               if (((kill(atoi(pid_buffer), 0)) != NON_VALID)) {
                        if ((send_sigusr1) || (send_sigusr2) || (send_sigterm)) {
+                               go_daemon = 0; /* Prevent a live PID-file deletion */
                                if (send_sigusr1) {
                                        if ((kill(atoi(pid_buffer), SIGUSR1)) != NON_VALID) {
                                                if (be_verbose) {
@@ -318,7 +334,7 @@ int main (int argc, char *argv[])
                                        }
                                }
                        } else {
-                               second_instance = 1; /* Flag prevents a PID-file deletion */
+                               go_daemon = 0; /* Prevent a live PID-file deletion */
                                exit_on_error(errorfp, "%s ERROR: Another instance of %s seems to be running!\n", our_prog_name, our_prog_name);
                        }
                } else { /* Dead pid-file */
@@ -351,6 +367,7 @@ int main (int argc, char *argv[])
                        if (!pad1_info) {
                                exit_on_error(errorfp, "%s ERROR: Can not find pad device: %s\n", our_prog_name, pad1_name);
                        }
+                       identify_device(pad1_name);
                        if (!register_events(display, pad1_info, pad1_name)) {
                                exit_on_error(errorfp, "%s ERROR: Could not register any pad events with %s\n", our_prog_name, pad1_name);
                        }
@@ -392,22 +409,26 @@ int main (int argc, char *argv[])
 
 /* Now determine what the config file will be named as */
 
+if (!is_graphire4) {
        if ((pad1_name) && (stylus1_name)) {
                config_file = config_file_intuos3;
        } else {
                if (stylus1_name) {
                        config_file = config_file_padless;
                } else {
-                       config_file = config_file_intuos3; /* User error? 'pad' without 'stylus'! */
+                       config_file = config_file_intuos3; /* User xorg.conf error? 'pad' without 'stylus'! */
                }
        }
+} else {
+       config_file = config_file_graphire4;
+}
 
 /* Concatenate the full path with the config file name. Store address */
 
        char *total_config_file_block;
        len = strlen(total_config_dir) + strlen(config_file) + 1;
        if ((total_config_file_block = (char *)malloc(len)) == NULL) {
-               exit_on_error(errorfp, "%s ERROR: Memory allocation trouble at stage 4!\n", our_prog_name, "");
+               exit_on_error(errorfp, "%s ERROR: Memory allocation trouble at stage 5!\n", our_prog_name, "");
        }
        sprintf(total_config_file_block, "%s%s", total_config_dir, config_file);
        total_config_file = total_config_file_block;
@@ -418,7 +439,8 @@ int main (int argc, char *argv[])
                fprintf(stderr, "OUR CNF-DIR = %s\n", total_config_dir);
                fprintf(stderr, "OUR CNFFILE = %s\n", total_config_file);
                fprintf(stderr, "OUR PIDFILE = %s\n", total_pid_file);
-               fprintf(stderr, "OUR LOGFILE = %s\n", total_error_file);
+               fprintf(stderr, "OUR INFFILE = %s\n", total_status_file);
+               fprintf(stderr, "OUR ERRFILE = %s\n", total_error_file);
                if (pad1_name) {
                        fprintf(stderr, "OUR PD1NAME = %s\n", pad1_name);
                }
@@ -446,15 +468,11 @@ int main (int argc, char *argv[])
        }
        fclose(fp);
 
-/* Read in an existing configuration file */
-
        p = external_list;
-       hp = human_readable;
        if ((fp = fopen(total_config_file, "r")) == NULL) {
                exit_on_error(errorfp, "%s ERROR: Can not open %s in read mode\n", our_prog_name, total_config_file);
        } else {
-               switch (read_file_config((void *)&p, (void *)&hp, fp)){
-
+               switch (read_file_config((void *)&p, fp)){
                        case 0: /* No errors */
                        fclose(fp);
                        break; /* OBS An identical list of error code returns exist in the on_signal.c
@@ -505,6 +523,14 @@ int main (int argc, char *argv[])
                exit_on_error(errorfp, "%s ERROR: Failed to modify signal handling!\n", our_prog_name, "");
        }
 
+/* Store whatever information we have in the status file (silent use of the -s switch */
+
+       if (go_daemon) {
+               go_daemon = 0;
+               status_report(0);
+               go_daemon = 1;
+       }
+
 /* Ready to launch in the foreground or as a daemon.
    In daemon mode we also take care of storing our PID in the config dir
    Observe that with a (0, 0) standard input/output/error goes to /dev/null
index 15c493d..79dd9d6 100644 (file)
@@ -40,5 +40,21 @@ void exit_on_error(FILE *fp, char *string1, char *string2, char *string3)
 
 }
 
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Function is a rudimentary error handler for Xserver error returns
+ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+int xerror_handler(Display *display, XErrorEvent *error_event)
+{
+       FILE *errorfp = NULL;
+       errorfp = fopen(total_error_file, "w");
+
+       char error_buffer [MAXBUFFER];
+       XGetErrorText(display, error_event->error_code, error_buffer, MAXBUFFER);
+       fprintf(stderr, "X error message: %d %s\n", error_event->error_code, error_buffer);
+       exit_on_error(errorfp, "%s ERROR: A fatal error was returned from the X server: %s\n", our_prog_name, error_buffer);
+       return 0;
+}
+
 /* End Code */
 
index ed19229..3f48ee8 100644 (file)
@@ -29,7 +29,6 @@ void re_read_file_config(int signum)
 {
 
        struct program *p;
-       struct configstrings *hp;
 
        FILE *fp;
        FILE *errorfp;
@@ -43,11 +42,10 @@ void re_read_file_config(int signum)
 /* Read in an existing configuration file */
 
        p = external_list;
-       hp = human_readable;
        if ((fp = fopen(total_config_file, "r")) == NULL) {
                exit_on_error(errorfp, "%s ERROR: Reread - Can not open %s in read mode\n", our_prog_name, total_config_file);
        } else {
-               switch (read_file_config((void *)&p, (void *)&hp, fp)){
+               switch (read_file_config((void *)&p, fp)){
 
                        case 0: /* No errors */
                        fclose(fp);
@@ -79,44 +77,89 @@ void re_read_file_config(int signum)
                        exit_on_error(errorfp, "%s ERROR: Reread - Unknown error while parsing %s\n", our_prog_name, total_config_file);
                }
        }
-
+       go_daemon = 0;
+       status_report(0); /* Update our information file */
+       go_daemon = 1;
        fclose(errorfp);
 }
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- Function acts as a signal handler replacement for SIGUSR2
- On this signal we print some choise information to the screen
+ Function acts as a signal handler replacement for SIGUSR2. On this
+ signal we print some choise information to a file and to the screen.
  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
 void status_report(int signum)
 {
 
+       FILE *errorfp = NULL;
+       FILE *statusfp = NULL;
+       
        struct program *p;
        p = external_list;
        int i;
 
-       fprintf(stderr, "PGR VERSION = %s\n", our_prog_version);
-       fprintf(stderr, "USR HOMEDIR = %s\n", getenv("HOME"));
-       fprintf(stderr, "OUR CNF-DIR = %s\n", total_config_dir);
-       fprintf(stderr, "OUR CNFFILE = %s\n", total_config_file);
-       fprintf(stderr, "OUR PIDFILE = %s\n", total_pid_file);
-       fprintf(stderr, "OUR LOGFILE = %s\n", total_error_file);
-       if (pad1_name) {
-               fprintf(stderr, "OUR PD1NAME = %s\n", pad1_name);
-       }
-       if (stylus1_name) {
-               fprintf(stderr, "OUR ST1NAME = %s\n", stylus1_name);
-       }
-       fprintf(stderr, "%s-user = %d\n", configstring, userconfigversion);
-       fprintf(stderr, "%s-ours = %s\n", configstring, configversion);
-       fprintf(stderr, "ConfigHeaderFields = %d\n", configheaderfields);
-       for (i = 0; i < num_list; i++, p++) {
-               fprintf(stderr, "PGR RECNAME = %s\n", p->class_name);
-               fprintf(stderr, "ST1 PRCURVE = \"%s\"\n", p->stylus1_presscurve);
+       errorfp = fopen(total_error_file, "w");
+
+/* Open (and truncate) a status log and fill it with information */
+
+       if ((statusfp = fopen(total_status_file, "w")) == NULL) {
+               exit_on_error(errorfp, "%s ERROR: Can not open %s in write mode\n", our_prog_name, total_status_file);
+       } else {
+               fclose(errorfp);
+               fprintf(statusfp, "PGR VERSION = %s\n", our_prog_version);
+               fprintf(statusfp, "USR HOMEDIR = %s\n", getenv("HOME"));
+               fprintf(statusfp, "OUR CNF-DIR = %s\n", total_config_dir);
+               fprintf(statusfp, "OUR CNFFILE = %s\n", total_config_file);
+               fprintf(statusfp, "OUR PIDFILE = %s\n", total_pid_file);
+               fprintf(statusfp, "OUR INFFILE = %s\n", total_status_file);
+               fprintf(statusfp, "OUR ERRFILE = %s\n", total_error_file);
+               if (pad1_name) {
+                       fprintf(statusfp, "OUR PD1NAME = %s\n", pad1_name);
+               }
+               if (stylus1_name) {
+                       fprintf(statusfp, "OUR ST1NAME = %s\n", stylus1_name);
+               }
+               fprintf(statusfp, "%s-user = %d\n", configstring, userconfigversion);
+               fprintf(statusfp, "%s-ours = %s\n", configstring, configversion);
+               fprintf(statusfp, "ConfigHeaderFields = %d\n", configheaderfields);
+               for (i = 0; i < num_list; i++, p++) {
+                       fprintf(statusfp, "PGR RECNAME = %s\n", p->class_name);
+                       fprintf(statusfp, "ST1 PRCURVE = \"%s\"\n", p->stylus1_presscurve);
+               }
+               fprintf(statusfp, "PGR RECORDS = %d\n", num_list);
+               if (go_daemon) {
+                       fprintf(statusfp, "OUR RUN-PID = %d\n", getpid());
+               }
+               fclose(statusfp);
        }
-       fprintf(stderr, "PGR RECORDS = %d\n", num_list);
-       fprintf(stderr, "OUR RUN-PID = %d\n", getpid());
 
+/* Also print the info to sceen (only if we have been daemonised and act on a -s signal) */
+
+       if (go_daemon) {
+               p = external_list;
+               fprintf(stderr, "PGR VERSION = %s\n", our_prog_version);
+               fprintf(stderr, "USR HOMEDIR = %s\n", getenv("HOME"));
+               fprintf(stderr, "OUR CNF-DIR = %s\n", total_config_dir);
+               fprintf(stderr, "OUR CNFFILE = %s\n", total_config_file);
+               fprintf(stderr, "OUR PIDFILE = %s\n", total_pid_file);
+               fprintf(stderr, "OUR INFFILE = %s\n", total_status_file);
+               fprintf(stderr, "OUR ERRFILE = %s\n", total_error_file);
+               if (pad1_name) {
+                       fprintf(stderr, "OUR PD1NAME = %s\n", pad1_name);
+               }
+               if (stylus1_name) {
+                       fprintf(stderr, "OUR ST1NAME = %s\n", stylus1_name);
+               }
+               fprintf(stderr, "%s-user = %d\n", configstring, userconfigversion);
+               fprintf(stderr, "%s-ours = %s\n", configstring, configversion);
+               fprintf(stderr, "ConfigHeaderFields = %d\n", configheaderfields);
+               for (i = 0; i < num_list; i++, p++) {
+                       fprintf(stderr, "PGR RECNAME = %s\n", p->class_name);
+                       fprintf(stderr, "ST1 PRCURVE = \"%s\"\n", p->stylus1_presscurve);
+               }
+               fprintf(stderr, "PGR RECORDS = %d\n", num_list);
+               fprintf(stderr, "OUR RUN-PID = %d\n", getpid());
+       }
 }
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -140,8 +183,9 @@ void clean_up_exit(int signum)
        }
        clean_up_exit_in_progress = 1;
 
-       if ((go_daemon) && (!second_instance)) { /* Prevent accidental deletion */
+       if (go_daemon) {
                unlink(total_pid_file);
+               unlink(total_status_file);
        }
 
        if (total_config_dir) {
@@ -160,6 +204,10 @@ void clean_up_exit(int signum)
                free(total_error_file);
        }
 
+       if (total_status_file) {
+               free(total_status_file);
+       }
+
        if (num_list) {
                for (i = 0; i < num_list; i++, p++) {
                        free(p->stylus1_presscurve);
@@ -178,7 +226,15 @@ void clean_up_exit(int signum)
 /* pad1_device and stylus1_device should not be explicitly closed by a
    call to XCloseDevice. It leaves a message from X (in the terminal
    where X is started from) saying: "ProcXCloseDevice to close or not ?"
-   Like the program "xsetwacom" does on every device change...*/
+   Instead we just free the XDevice structures created by XOpenDevice */
+
+       if (pad1_device) {
+               XFree(pad1_device);
+       }
+
+       if (stylus1_device) {
+               XFree(stylus1_device);
+       }
 
        if (display) {
                XCloseDisplay(display);
index 57ed878..0032980 100644 (file)
@@ -33,6 +33,7 @@
 
 int register_events(Display *display, XDeviceInfo *dev_info, char *name)
 {
+
        int i;
        int count = 0;