| From: |
| "Rene van Paassen" <rene.vanpaassen@gmail.com> |
| To: |
| linux-usb-devel@lists.sourceforge.net |
| Subject: |
| [PATCH 2.6.20 1/1] usb/input updated aiptek
tablet driver |
| Date: |
| Thu, 8 Mar 2007 00:02:48 +0100 |
| Cc: |
| aiptektablet-users@lists.sourceforge.net |
| Archive-link: |
| Article,
Thread
|
Hello all,
This is a patch for the aiptek tablet input driver. It is the result
of development work done
on this driver at aiptektablet.sourceforce.net
A summary of the important changes:
- corrected proximity (p) and data valid (dv) flags.
- corrected mouse button defines
- corrected problems with relative mode
- function keys of the tablet now are functional
- corrected specification of tablet capabilities; using set_bit()
old code was wrong for bits > 32
- code now includes a proximity timeout, for tablets that do not
send p=0 (out of proximity) and dv=1 (valid report). Only enable
for buggy tablets or people who really quickly jerk the stylus from
the tablet.
Signed-off-by: René van Paassen <Rene.vanPaassen@gmail.com>
--- linux-2.6.20/drivers/usb/input/aiptek.c.orig 2007-02-04
19:44:54.000000000 +0100
+++ linux-2.6.20/drivers/usb/input/aiptek.c 2007-03-05
22:52:51.000000000 +0100
@@ -4,6 +4,7 @@
*
* Copyright (c) 2001 Chris Atenasio <chris@crud.net>
* Copyright (c) 2002-2004 Bryan W. Headley <bwheadley@earthlink.net>
+ * Extra bits 2004 René van Paassen <M.M.vanPaassen@tudelft.nl>
*
* based on wacom.c by
* Vojtech Pavlik <vojtech@suse.cz>
@@ -45,6 +46,38 @@
* Feb 20, 2004, Bryan W. Headley.
* v1.5 - Added previousJitterable, so we don't do jitter delay when the
* user is holding a button down for periods of time.
+ * v1.6 - Corrected mouse button detection, defines were off (RvP)
+ * Corrected macro button detection. On my tablet (Medion, is
+ * reported as Aiptek 12000U, data[3] = 1 is just left of F1,
+ * 2 = F1, 3 = between F1 and F2, etc.
+ * added a lastMacro variable, so macro key is reset if you drag
+ * mouse/stylus from macro into the drawing area.
+ * v1.7 - switched to strncmp for string comparison, to accept trailing
+ * returns (RvP)
+ * v1.8 - Putting a new timer (add_timer, del_timer) in the system.
+ * The problem is now that the tablet never reports
+ * "out of proximity" events (at least mine doesn't). So my
+ * answer is sending those events after a time of inactivity.
+ * is what the timer is for.
+ * got bitten by the fact that the ABS_MISC event moved up
+ * by a long in the bit array. To celebrate the detection of
+ * this bug, started to neatly use set_bit(), instead of crossing
+ * fingers and mucking with the bitmaps directly (RvP)
+ * v1.9 - Moved the inactivity timer removal to correct place, removed
+ * timeout debugging message, added removal proximity timeout file
+ * (bugfixes). Added fix by the masc (ms - at - sbox.tugraz.at)
+ * This fix also fixes the problem of lacking out-of-proximity
+ * reports (at least with my tablet). So I made the proximity
+ * timeout conditional. Apparently, for my tablet is it not needed
+ * (with the fixed detection of proximity and data valid). Kept
+ * the code in, for now. (nov 19, 2004 RvP)
+ * v1.9.1 Merged in extant patches, did some constant elimination. BwH.
+ * v1.9.2 Merged in patches in signatures to show_# and store_# routines.
+ * v2.0 - Switched to using input_allocate_device and usb_kill_urb.
+ * Ran the code through "indent -kr -i8", to get Linux kernel
+ * indenting style + removed superfluous brakets in case
+ * statements. Apr 19, 2006, RvP
+ * v2.1 Preparing for merge with kernel RvP
*
* NOTE:
* This kernel driver is augmented by the "Aiptek" XFree86 input
@@ -77,14 +110,15 @@
#include <linux/init.h>
#include <linux/usb/input.h>
#include <linux/sched.h>
+#include <linux/timer.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h>
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.5 (May-15-2004)"
-#define DRIVER_AUTHOR "Bryan W. Headley/Chris Atenasio"
+#define DRIVER_VERSION "v2.1 (Feb-14-2007)"
+#define DRIVER_AUTHOR "Bryan W. Headley/Chris Atenasio/Cédric
Brun/René van Paassen"
#define DRIVER_DESC "Aiptek HyperPen USB Tablet Driver (Linux 2.6.x)"
/*
@@ -265,9 +299,9 @@
/* Mouse button programming
*/
-#define AIPTEK_MOUSE_LEFT_BUTTON 0x01
-#define AIPTEK_MOUSE_RIGHT_BUTTON 0x02
-#define AIPTEK_MOUSE_MIDDLE_BUTTON 0x04
+#define AIPTEK_MOUSE_LEFT_BUTTON 0x04
+#define AIPTEK_MOUSE_RIGHT_BUTTON 0x08
+#define AIPTEK_MOUSE_MIDDLE_BUTTON 0x10
/* Stylus button programming
*/
@@ -287,6 +321,12 @@
#define AIPTEK_REPORT_TOOL_STYLUS 0x20
#define AIPTEK_REPORT_TOOL_MOUSE 0x40
+ /* Debug levels - higher means more output.
+ */
+#define AIPTEK_DEBUG_CONFIG 1
+#define AIPTEK_DEBUG_TRACE 2
+#define AIPTEK_DEBUG_IRQTRACE 5
+
static int programmableDelay = AIPTEK_PROGRAMMABLE_DELAY_DEFAULT;
static int jitterDelay = AIPTEK_JITTER_DELAY_DEFAULT;
@@ -312,9 +352,11 @@
int mouseButtonRight; /* mouse right btn delivers... */
int programmableDelay; /* delay for tablet programming */
int jitterDelay; /* delay for hand jittering */
+ int proximityTimeout; /* reset proximity after this */
};
struct aiptek {
+ int debug; /* Debug level; 0 =no
debug */
struct input_dev *inputdev; /* input device struct
*/
struct usb_device *usbdev; /* usb device struct
*/
struct urb *urb; /* urb for incoming
reports */
@@ -328,7 +370,9 @@
int inDelay; /* jitter: in jitter
delay? */
unsigned long endDelay; /* jitter: time when
delay ends */
int previousJitterable; /* jitterable prev value */
+ int lastMacro; /* last macro key,
might need resetting */
unsigned char *data; /* incoming packet
data */
+ struct timer_list activityCheck; /* timer for
monitoring prox */
};
/*
@@ -346,6 +390,36 @@
};
/***********************************************************************
+ * Constants used in the sysfs files. This affords us a small size
+ * optimization, plus maintains a single point of failure (misspellings.)
+ */
+static char *pStylus = "stylus";
+static char *pMouse = "mouse";
+static char *pEither = "either";
+static char *pUnknown = "unknown";
+static char *pAbsolute = "absolute";
+static char *pRelative = "relative";
+static char *pEraser = "eraser";
+static char *pPen = "pen";
+static char *pPencil = "pencil";
+static char *pBrush = "brush";
+static char *pAirbrush = "airbrush";
+static char *pLens = "lens";
+static char *pDisable = "disable";
+static char *pUpper = "upper";
+static char *pLower = "lower";
+static char *pLeft = "left";
+static char *pRight = "right";
+static char *pMiddle = "middle";
+
+/***********************************************************************
+ * Very common printf format strings for the sysfs files.
+ */
+static char *pString = "%s\n";
+static char *pInt = "%d\n";
+static char *pHex = "0x%04x\n";
+
+/***********************************************************************
* Relative reports deliver values in 2's complement format to
* deal with negative offsets.
*/
@@ -432,10 +506,21 @@
aiptek->inDelay = 0;
aiptek->eventCount++;
+ /* Now remove the inactivity timer, if it is still lurking around. */
+ if (aiptek->curSetting.proximityTimeout) {
+ del_timer(&aiptek->activityCheck);
+ }
+
/* Report 1 delivers relative coordinates with either a stylus
* or the mouse. You do not know, however, which input
* tool generated the event.
+ * Update 070228/RvP My tablet, a Medion / re-branded 12000U,
+ * reports x=-255 for the stylus, and y=-255 for the mouse in
+ * this mode, apparently when x resp y should be zero.
*/
+ if (aiptek->debug == AIPTEK_DEBUG_IRQTRACE) {
+ info("irq(%d): report id = %d\n", __LINE__, data[0]);
+ }
if (data[0] == 1) {
if (aiptek->curSetting.coordinateMode ==
AIPTEK_COORDINATE_ABSOLUTE_MODE) {
@@ -461,9 +546,23 @@
input_report_key(inputdev, BTN_LEFT, left);
input_report_key(inputdev, BTN_MIDDLE, middle);
input_report_key(inputdev, BTN_RIGHT, right);
+
+ /* Stylus or Mouse usage is reported in a peculiar
+ * way. Report tool usage, and correct displacement */
+ if (x == -255) {
+ input_report_abs
+ (inputdev, ABS_MISC,
+ 1 | AIPTEK_REPORT_TOOL_STYLUS);
+ x = 0;
+ }
+ if (y == -255) {
+ input_report_abs
+ (inputdev, ABS_MISC,
+ 1 | AIPTEK_REPORT_TOOL_MOUSE);
+ y = 0;
+ }
input_report_rel(inputdev, REL_X, x);
input_report_rel(inputdev, REL_Y, y);
- input_report_rel(inputdev, REL_MISC, 1 |
AIPTEK_REPORT_TOOL_UNKNOWN);
/* Wheel support is in the form of a single-event
* firing.
@@ -473,6 +572,9 @@
aiptek->curSetting.wheel);
aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE;
}
+ input_report_key(inputdev,
+ macroKeyEvents[aiptek->lastMacro],
+ 0);
input_sync(inputdev);
}
}
@@ -490,8 +592,8 @@
y = le16_to_cpu(get_unaligned((__le16 *) (data + 3)));
z = le16_to_cpu(get_unaligned((__le16 *) (data + 6)));
- p = (data[5] & 0x01) != 0 ? 1 : 0;
- dv = (data[5] & 0x02) != 0 ? 1 : 0;
+ dv = (data[5] & 0x01) != 0 ? 1 : 0;
+ p = (data[5] & 0x02) != 0 ? 1 : 0;
tip = (data[5] & 0x04) != 0 ? 1 : 0;
/* Use jitterable to re-arrange button masks
@@ -501,6 +603,10 @@
bs = (data[5] &
aiptek->curSetting.stylusButtonLower) != 0 ? 1 : 0;
pck = (data[5] &
aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0;
+ /* Proximity bit not set when bs or pck set
+ */
+ p |= bs | pck;
+
/* dv indicates 'data valid' (e.g., the tablet
is in sync
* and has delivered a "correct" report) We will ignore
* all 'bad' reports...
@@ -516,18 +622,22 @@
TOOL_BUTTON(aiptek->curSetting.toolMode),
1);
aiptek->curSetting.toolMode |=
TOOL_BUTTON_FIRED_BIT;
+ } else {
+ input_report_key(inputdev,
+
TOOL_BUTTON(aiptek->curSetting.toolMode),
+ 0);
}
if (p != 0) {
- input_report_abs(inputdev, ABS_X, x);
- input_report_abs(inputdev, ABS_Y, y);
- input_report_abs(inputdev,
ABS_PRESSURE, z);
-
input_report_key(inputdev,
BTN_TOUCH, tip);
input_report_key(inputdev,
BTN_STYLUS, bs);
input_report_key(inputdev,
BTN_STYLUS2, pck);
- if (aiptek->curSetting.xTilt !=
+ input_report_abs(inputdev, ABS_X, x);
+ input_report_abs(inputdev, ABS_Y, y);
+ input_report_abs(inputdev,
ABS_PRESSURE, z);
+
+ if (aiptek->curSetting.xTilt !=
AIPTEK_TILT_DISABLE) {
input_report_abs(inputdev,
ABS_TILT_X,
@@ -551,6 +661,10 @@
}
}
input_report_abs(inputdev, ABS_MISC, p
| AIPTEK_REPORT_TOOL_STYLUS);
+ input_report_key(inputdev,
+ macroKeyEvents[aiptek->
+ lastMacro],
+ 0);
input_sync(inputdev);
}
}
@@ -569,8 +683,8 @@
jitterable = data[5] & 0x1c;
- p = (data[5] & 0x01) != 0 ? 1 : 0;
- dv = (data[5] & 0x02) != 0 ? 1 : 0;
+ dv = (data[5] & 0x01) != 0 ? 1 : 0;
+ p = (data[5] & 0x02) != 0 ? 1 : 0;
left = (data[5] &
aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0;
right = (data[5] &
aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0;
middle = (data[5] &
aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
@@ -586,6 +700,9 @@
TOOL_BUTTON(aiptek->curSetting.toolMode),
1);
aiptek->curSetting.toolMode |=
TOOL_BUTTON_FIRED_BIT;
+ } else {
+ input_report_key(inputdev,
+
TOOL_BUTTON(aiptek->curSetting.toolMode), 0);
}
if (p != 0) {
@@ -606,7 +723,9 @@
aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE;
}
}
- input_report_rel(inputdev, REL_MISC, p
| AIPTEK_REPORT_TOOL_MOUSE);
+ input_report_abs(inputdev, ABS_MISC, p
| AIPTEK_REPORT_TOOL_MOUSE);
+ input_report_key(inputdev,
+
macroKeyEvents[aiptek->lastMacro], 0);
input_sync(inputdev);
}
}
@@ -616,13 +735,12 @@
else if (data[0] == 4) {
jitterable = data[1] & 0x18;
- p = (data[1] & 0x01) != 0 ? 1 : 0;
- dv = (data[1] & 0x02) != 0 ? 1 : 0;
+ dv = (data[1] & 0x01) != 0 ? 1 : 0;
+ p = (data[1] & 0x02) != 0 ? 1 : 0;
tip = (data[1] & 0x04) != 0 ? 1 : 0;
bs = (data[1] & aiptek->curSetting.stylusButtonLower)
!= 0 ? 1 : 0;
pck = (data[1] & aiptek->curSetting.stylusButtonUpper)
!= 0 ? 1 : 0;
-
- macro = data[3];
+ macro = data[3] >> 1;
z = le16_to_cpu(get_unaligned((__le16 *) (data + 4)));
if (dv != 0) {
@@ -635,29 +753,25 @@
TOOL_BUTTON(aiptek->curSetting.toolMode),
1);
aiptek->curSetting.toolMode |=
TOOL_BUTTON_FIRED_BIT;
+ } else {
+ input_report_key(inputdev,
+
TOOL_BUTTON(aiptek->curSetting.toolMode), 0);
}
- if (p != 0) {
- input_report_key(inputdev, BTN_TOUCH, tip);
- input_report_key(inputdev, BTN_STYLUS, bs);
- input_report_key(inputdev, BTN_STYLUS2, pck);
- input_report_abs(inputdev, ABS_PRESSURE, z);
- }
-
- /* For safety, we're sending key 'break' codes for the
- * neighboring macro keys.
+ /* This now expressly resets the key on the
+ * areas (reported as odd by the tablet)
+ * between the macro key areas. Only report
+ * key when tip is pressed.
*/
- if (macro > 0) {
- input_report_key(inputdev,
- macroKeyEvents[macro - 1], 0);
- }
- if (macro < 25) {
- input_report_key(inputdev,
- macroKeyEvents[macro + 1], 0);
- }
- input_report_key(inputdev, macroKeyEvents[macro], p);
+ input_report_key(inputdev, macroKeyEvents[macro],
+ tip & ~data[3]);
input_report_abs(inputdev, ABS_MISC,
p | AIPTEK_REPORT_TOOL_STYLUS);
+
+ /* remember this key. If the user now drags stylus
+ * into the drawing area it needs to be reset.
+ */
+ aiptek->lastMacro = macro;
input_sync(inputdev);
}
}
@@ -666,12 +780,12 @@
else if (data[0] == 5) {
jitterable = data[1] & 0x1c;
- p = (data[1] & 0x01) != 0 ? 1 : 0;
- dv = (data[1] & 0x02) != 0 ? 1 : 0;
- left = (data[1]& aiptek->curSetting.mouseButtonLeft)
!= 0 ? 1 : 0;
+ dv = (data[1] & 0x01) != 0 ? 1 : 0;
+ p = (data[1] & 0x02) != 0 ? 1 : 0;
+ left = (data[1] & aiptek->curSetting.mouseButtonLeft)
!= 0 ? 1 : 0;
right = (data[1] &
aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0;
middle = (data[1] &
aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
- macro = data[3];
+ macro = data[3] >> 1;
if (dv != 0) {
/* If we've not already sent a tool_button_?? code, do
@@ -683,29 +797,18 @@
TOOL_BUTTON(aiptek->curSetting.toolMode),
1);
aiptek->curSetting.toolMode |=
TOOL_BUTTON_FIRED_BIT;
- }
-
- if (p != 0) {
- input_report_key(inputdev, BTN_LEFT, left);
- input_report_key(inputdev, BTN_MIDDLE, middle);
- input_report_key(inputdev, BTN_RIGHT, right);
- }
-
- /* For safety, we're sending key 'break' codes for the
- * neighboring macro keys.
- */
- if (macro > 0) {
- input_report_key(inputdev,
- macroKeyEvents[macro - 1], 0);
- }
- if (macro < 25) {
+ } else {
input_report_key(inputdev,
- macroKeyEvents[macro + 1], 0);
+ TOOL_BUTTON(aiptek->
+ curSetting.
+ toolMode), 0);
}
- input_report_key(inputdev, macroKeyEvents[macro], 1);
- input_report_rel(inputdev, ABS_MISC,
+ input_report_key(inputdev, macroKeyEvents[macro],
+ left & ~data[3]);
+ input_report_abs(inputdev, ABS_MISC,
p | AIPTEK_REPORT_TOOL_MOUSE);
+ aiptek->lastMacro = macro;
input_sync(inputdev);
}
}
@@ -735,6 +838,10 @@
TOOL_BUTTON(aiptek->curSetting.
toolMode), 1);
aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+ } else {
+ input_report_key(inputdev,
+ TOOL_BUTTON(aiptek->curSetting.
+ toolMode), 0);
}
input_report_key(inputdev, macroKeyEvents[macro], 1);
@@ -745,10 +852,10 @@
dbg("Unknown report %d", data[0]);
}
- /* Jitter may occur when the user presses a button on the stlyus
+ /* Jitter may occur when the user presses a button on the stylus
* or the mouse. What we do to prevent that is wait 'x' milliseconds
* following a 'jitterable' event, which should give the hand some time
- * stabilize itself.
+ * to stabilize itself.
*
* We just introduced aiptek->previousJitterable to carry forth the
* notion that jitter occurs when the button state changes
from on to off:
@@ -765,7 +872,15 @@
}
aiptek->previousJitterable = jitterable;
-exit:
+ /* set the inactivity timer. Take due account for the jitter
delay too. */
+ if (aiptek->curSetting.proximityTimeout) {
+ aiptek->activityCheck.expires =
+ (aiptek->inDelay ? aiptek->endDelay : jiffies) +
+ aiptek->curSetting.proximityTimeout;
+ add_timer(&aiptek->activityCheck);
+ }
+
+ exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval != 0) {
err("%s - usb_submit_urb failed with result %d",
@@ -872,6 +987,9 @@
command, data);
}
kfree(buf);
+
+ msleep(aiptek->curSetting.programmableDelay);
+
return ret < 0 ? ret : 0;
}
@@ -972,6 +1090,7 @@
return ret;
}
}
+ msleep(160);
/* Enable the macro keys */
if ((ret = aiptek_command(aiptek, 0x11, 0x02)) < 0)
@@ -1002,6 +1121,38 @@
*/
/***********************************************************************
+ * Add dynamic debugging.
+ */
+static ssize_t show_tabletDebug(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct aiptek *aiptek = dev_get_drvdata(dev);
+
+ if (aiptek == NULL) {
+ return 0;
+ }
+
+ return snprintf(buf, PAGE_SIZE, pInt, aiptek->debug);
+}
+
+static ssize_t
+store_tabletDebug(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct aiptek *aiptek = dev_get_drvdata(dev);
+ if (aiptek == NULL) {
+ return 0;
+ }
+
+ aiptek->debug = (int) simple_strtol(buf, 0, 10);
+ return count;
+}
+
+static DEVICE_ATTR(debug, S_IRUGO | S_IWUGO, show_tabletDebug,
+ store_tabletDebug);
+
+/***********************************************************************
* support the 'size' file -- display support
*/
static ssize_t show_tabletSize(struct device *dev, struct
device_attribute *attr, char *buf)
@@ -1034,8 +1185,7 @@
if (aiptek == NULL)
return 0;
- return snprintf(buf, PAGE_SIZE, "0x%04x\n",
- aiptek->inputdev->id.product);
+ return snprintf(buf, PAGE_SIZE, pHex, aiptek->inputdev->id.product);
}
static DEVICE_ATTR(product_id, S_IRUGO, show_tabletProductId, NULL);
@@ -1050,7 +1200,7 @@
if (aiptek == NULL)
return 0;
- return snprintf(buf, PAGE_SIZE, "0x%04x\n",
aiptek->inputdev->id.vendor);
+ return snprintf(buf, PAGE_SIZE, pHex, aiptek->inputdev->id.vendor);
}
static DEVICE_ATTR(vendor_id, S_IRUGO, show_tabletVendorId, NULL);
@@ -1066,7 +1216,7 @@
if (aiptek == NULL)
return 0;
- retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->manufacturer);
+ retval = snprintf(buf, PAGE_SIZE, pString,
aiptek->usbdev->manufacturer);
return retval;
}
@@ -1083,7 +1233,7 @@
if (aiptek == NULL)
return 0;
- retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->product);
+ retval = snprintf(buf, PAGE_SIZE, pString, aiptek->usbdev->product);
return retval;
}
@@ -1103,22 +1253,22 @@
switch (aiptek->curSetting.pointerMode) {
case AIPTEK_POINTER_ONLY_STYLUS_MODE:
- s = "stylus";
+ s = pStylus;
break;
case AIPTEK_POINTER_ONLY_MOUSE_MODE:
- s = "mouse";
+ s = pMouse;
break;
case AIPTEK_POINTER_EITHER_MODE:
- s = "either";
+ s = pEither;
break;
default:
- s = "unknown";
+ s = pUnknown;
break;
}
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, pString, s);
}
static ssize_t
@@ -1128,12 +1278,12 @@
if (aiptek == NULL)
return 0;
- if (strcmp(buf, "stylus") == 0) {
+ if (strncmp(buf, pStylus, 6) == 0) {
aiptek->newSetting.pointerMode =
AIPTEK_POINTER_ONLY_STYLUS_MODE;
- } else if (strcmp(buf, "mouse") == 0) {
+ } else if (strncmp(buf, pMouse, 5) == 0) {
aiptek->newSetting.pointerMode = AIPTEK_POINTER_ONLY_MOUSE_MODE;
- } else if (strcmp(buf, "either") == 0) {
+ } else if (strncmp(buf, pEither, 6) == 0) {
aiptek->newSetting.pointerMode = AIPTEK_POINTER_EITHER_MODE;
}
return count;
@@ -1157,18 +1307,18 @@
switch (aiptek->curSetting.coordinateMode) {
case AIPTEK_COORDINATE_ABSOLUTE_MODE:
- s = "absolute";
+ s = pAbsolute;
break;
case AIPTEK_COORDINATE_RELATIVE_MODE:
- s = "relative";
+ s = pRelative;
break;
default:
- s = "unknown";
+ s = pUnknown;
break;
}
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, pString, s);
}
static ssize_t
@@ -1178,11 +1328,11 @@
if (aiptek == NULL)
return 0;
- if (strcmp(buf, "absolute") == 0) {
- aiptek->newSetting.pointerMode =
+ if (strncmp(buf, pAbsolute, 8) == 0) {
+ aiptek->newSetting.coordinateMode =
AIPTEK_COORDINATE_ABSOLUTE_MODE;
- } else if (strcmp(buf, "relative") == 0) {
- aiptek->newSetting.pointerMode =
+ } else if (strncmp(buf, pRelative, 8) == 0) {
+ aiptek->newSetting.coordinateMode =
AIPTEK_COORDINATE_RELATIVE_MODE;
}
return count;
@@ -1206,38 +1356,38 @@
switch (TOOL_BUTTON(aiptek->curSetting.toolMode)) {
case AIPTEK_TOOL_BUTTON_MOUSE_MODE:
- s = "mouse";
+ s = pMouse;
break;
case AIPTEK_TOOL_BUTTON_ERASER_MODE:
- s = "eraser";
+ s = pEraser;
break;
case AIPTEK_TOOL_BUTTON_PENCIL_MODE:
- s = "pencil";
+ s = pPencil;
break;
case AIPTEK_TOOL_BUTTON_PEN_MODE:
- s = "pen";
+ s = pPen;
break;
case AIPTEK_TOOL_BUTTON_BRUSH_MODE:
- s = "brush";
+ s = pBrush;
break;
case AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE:
- s = "airbrush";
+ s = pAirbrush;
break;
case AIPTEK_TOOL_BUTTON_LENS_MODE:
- s = "lens";
+ s = pLens;
break;
default:
- s = "unknown";
+ s = pUnknown;
break;
}
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, pString, s);
}
static ssize_t
@@ -1247,19 +1397,19 @@
if (aiptek == NULL)
return 0;
- if (strcmp(buf, "mouse") == 0) {
+ if (strncmp(buf, pMouse, 5) == 0) {
aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_MOUSE_MODE;
- } else if (strcmp(buf, "eraser") == 0) {
+ } else if (strncmp(buf, pEraser, 6) == 0) {
aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_ERASER_MODE;
- } else if (strcmp(buf, "pencil") == 0) {
+ } else if (strncmp(buf, pPencil, 6) == 0) {
aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PENCIL_MODE;
- } else if (strcmp(buf, "pen") == 0) {
+ } else if (strncmp(buf, pPen, 3) == 0) {
aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PEN_MODE;
- } else if (strcmp(buf, "brush") == 0) {
+ } else if (strncmp(buf, pBrush, 5) == 0) {
aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_BRUSH_MODE;
- } else if (strcmp(buf, "airbrush") == 0) {
+ } else if (strncmp(buf, pAirbrush, 8) == 0) {
aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE;
- } else if (strcmp(buf, "lens") == 0) {
+ } else if (strncmp(buf, pLens, 4) == 0) {
aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_LENS_MODE;
}
@@ -1282,9 +1432,9 @@
return 0;
if (aiptek->curSetting.xTilt == AIPTEK_TILT_DISABLE) {
- return snprintf(buf, PAGE_SIZE, "disable\n");
+ return snprintf(buf, PAGE_SIZE, pString, pDisable);
} else {
- return snprintf(buf, PAGE_SIZE, "%d\n",
+ return snprintf(buf, PAGE_SIZE, pInt,
aiptek->curSetting.xTilt);
}
}
@@ -1298,10 +1448,10 @@
if (aiptek == NULL)
return 0;
- if (strcmp(buf, "disable") == 0) {
+ if (strncmp(buf, pDisable, 7) == 0) {
aiptek->newSetting.xTilt = AIPTEK_TILT_DISABLE;
} else {
- x = (int)simple_strtol(buf, NULL, 10);
+ x = (int) simple_strtol(buf, 0, 10);
if (x >= AIPTEK_TILT_MIN && x <= AIPTEK_TILT_MAX) {
aiptek->newSetting.xTilt = x;
}
@@ -1324,9 +1474,9 @@
return 0;
if (aiptek->curSetting.yTilt == AIPTEK_TILT_DISABLE) {
- return snprintf(buf, PAGE_SIZE, "disable\n");
+ return snprintf(buf, PAGE_SIZE, pString, pDisable);
} else {
- return snprintf(buf, PAGE_SIZE, "%d\n",
+ return snprintf(buf, PAGE_SIZE, pInt,
aiptek->curSetting.yTilt);
}
}
@@ -1340,10 +1490,10 @@
if (aiptek == NULL)
return 0;
- if (strcmp(buf, "disable") == 0) {
+ if (strncmp(buf, pDisable, 7) == 0) {
aiptek->newSetting.yTilt = AIPTEK_TILT_DISABLE;
} else {
- y = (int)simple_strtol(buf, NULL, 10);
+ y = (int) simple_strtol(buf, 0, 10);
if (y >= AIPTEK_TILT_MIN && y <= AIPTEK_TILT_MAX) {
aiptek->newSetting.yTilt = y;
}
@@ -1365,7 +1515,8 @@
if (aiptek == NULL)
return 0;
- return snprintf(buf, PAGE_SIZE, "%d\n", aiptek->curSetting.jitterDelay);
+ return snprintf(buf, PAGE_SIZE, pInt,
+ aiptek->curSetting.jitterDelay);
}
static ssize_t
@@ -1385,6 +1536,43 @@
show_tabletJitterDelay, store_tabletJitterDelay);
/***********************************************************************
+ * support routines for the proximity_timeout file. Note that this file
+ * both displays current setting and allows reprogramming.
+ */
+static ssize_t show_tabletProximityTimeout(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct aiptek *aiptek = dev_get_drvdata(dev);
+
+ if (aiptek == NULL)
+ return 0;
+
+ return snprintf(buf, PAGE_SIZE, pInt,
+ (aiptek->curSetting.proximityTimeout * 1000) / HZ);
+}
+
+static ssize_t
+store_tabletProximityTimeout(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct aiptek *aiptek = dev_get_drvdata(dev);
+
+ if (aiptek == NULL)
+ return 0;
+
+ aiptek->newSetting.proximityTimeout =
+ ((int) simple_strtol(buf, 0, 10) * HZ) / 1000;
+ return count;
+}
+
+static DEVICE_ATTR(proximity_timeout,
+ S_IRUGO | S_IWUGO,
+ show_tabletProximityTimeout,
+ store_tabletProximityTimeout);
+
+/***********************************************************************
* support routines for the 'delay' file. Note that this file
* both displays current setting and allows reprogramming.
*/
@@ -1395,7 +1583,7 @@
if (aiptek == NULL)
return 0;
- return snprintf(buf, PAGE_SIZE, "%d\n",
+ return snprintf(buf, PAGE_SIZE, pInt,
aiptek->curSetting.programmableDelay);
}
@@ -1407,7 +1595,7 @@
if (aiptek == NULL)
return 0;
- aiptek->newSetting.programmableDelay = (int)simple_strtol(buf,
NULL, 10);
+ aiptek->newSetting.programmableDelay = (int)simple_strtol(buf, 0, 10);
return count;
}
@@ -1436,12 +1624,15 @@
* support routines for the 'event_count' file. Note that this file
* only displays current setting.
*/
-static ssize_t show_tabletEventsReceived(struct device *dev, struct
device_attribute *attr, char *buf)
+static ssize_t show_tabletEventsReceived(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
+ if (aiptek == NULL) {
return 0;
+ }
return snprintf(buf, PAGE_SIZE, "%ld\n", aiptek->eventCount);
}
@@ -1504,18 +1695,18 @@
switch (aiptek->curSetting.stylusButtonUpper) {
case AIPTEK_STYLUS_UPPER_BUTTON:
- s = "upper";
+ s = pUpper;
break;
case AIPTEK_STYLUS_LOWER_BUTTON:
- s = "lower";
+ s = pLower;
break;
default:
- s = "unknown";
- break;
+ s = pUnknown;
}
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+
+ return snprintf(buf, PAGE_SIZE, pString, s);
}
static ssize_t
@@ -1526,10 +1717,10 @@
if (aiptek == NULL)
return 0;
- if (strcmp(buf, "upper") == 0) {
+ if (strncmp(buf, pUpper, 5) == 0) {
aiptek->newSetting.stylusButtonUpper =
AIPTEK_STYLUS_UPPER_BUTTON;
- } else if (strcmp(buf, "lower") == 0) {
+ } else if (strncmp(buf, pLower, 5) == 0) {
aiptek->newSetting.stylusButtonUpper =
AIPTEK_STYLUS_LOWER_BUTTON;
}
@@ -1554,18 +1745,18 @@
switch (aiptek->curSetting.stylusButtonLower) {
case AIPTEK_STYLUS_UPPER_BUTTON:
- s = "upper";
+ s = pUpper;
break;
case AIPTEK_STYLUS_LOWER_BUTTON:
- s = "lower";
+ s = pLower;
break;
default:
- s = "unknown";
+ s = pUnknown;
break;
}
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, pString, s);
}
static ssize_t
@@ -1576,10 +1767,10 @@
if (aiptek == NULL)
return 0;
- if (strcmp(buf, "upper") == 0) {
+ if (strncmp(buf, pUpper, 5) == 0) {
aiptek->newSetting.stylusButtonLower =
AIPTEK_STYLUS_UPPER_BUTTON;
- } else if (strcmp(buf, "lower") == 0) {
+ } else if (strncmp(buf, pLower, 5) == 0) {
aiptek->newSetting.stylusButtonLower =
AIPTEK_STYLUS_LOWER_BUTTON;
}
@@ -1604,22 +1795,22 @@
switch (aiptek->curSetting.mouseButtonLeft) {
case AIPTEK_MOUSE_LEFT_BUTTON:
- s = "left";
+ s = pLeft;
break;
case AIPTEK_MOUSE_MIDDLE_BUTTON:
- s = "middle";
+ s = pMiddle;
break;
case AIPTEK_MOUSE_RIGHT_BUTTON:
- s = "right";
+ s = pRight;
break;
default:
- s = "unknown";
+ s = pUnknown;
break;
}
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, pString, s);
}
static ssize_t
@@ -1630,11 +1821,11 @@
if (aiptek == NULL)
return 0;
- if (strcmp(buf, "left") == 0) {
+ if (strncmp(buf, pLeft, 4) == 0) {
aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_LEFT_BUTTON;
- } else if (strcmp(buf, "middle") == 0) {
+ } else if (strncmp(buf, pMiddle, 6) == 0) {
aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_MIDDLE_BUTTON;
- } else if (strcmp(buf, "right") == 0) {
+ } else if (strncmp(buf, pRight, 5) == 0) {
aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_RIGHT_BUTTON;
}
return count;
@@ -1658,22 +1849,22 @@
switch (aiptek->curSetting.mouseButtonMiddle) {
case AIPTEK_MOUSE_LEFT_BUTTON:
- s = "left";
+ s = pLeft;
break;
case AIPTEK_MOUSE_MIDDLE_BUTTON:
- s = "middle";
+ s = pMiddle;
break;
case AIPTEK_MOUSE_RIGHT_BUTTON:
- s = "right";
+ s = pRight;
break;
default:
- s = "unknown";
+ s = pUnknown;
break;
}
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, pString, s);
}
static ssize_t
@@ -1684,12 +1875,13 @@
if (aiptek == NULL)
return 0;
- if (strcmp(buf, "left") == 0) {
- aiptek->newSetting.mouseButtonMiddle = AIPTEK_MOUSE_LEFT_BUTTON;
- } else if (strcmp(buf, "middle") == 0) {
+ if (strncmp(buf, pLeft, 4) == 0) {
+ aiptek->newSetting.mouseButtonMiddle =
+ AIPTEK_MOUSE_LEFT_BUTTON;
+ } else if (strncmp(buf, pMiddle, 6) == 0) {
aiptek->newSetting.mouseButtonMiddle =
AIPTEK_MOUSE_MIDDLE_BUTTON;
- } else if (strcmp(buf, "right") == 0) {
+ } else if (strncmp(buf, pRight, 5) == 0) {
aiptek->newSetting.mouseButtonMiddle =
AIPTEK_MOUSE_RIGHT_BUTTON;
}
@@ -1701,7 +1893,7 @@
show_tabletMouseMiddle, store_tabletMouseMiddle);
/***********************************************************************
- * support routines for the 'mouse_right' file. Note that this file
+ * support routines for the 'mouse_right' File. Note that this file
* both displays current setting and allows for setting changing.
*/
static ssize_t show_tabletMouseRight(struct device *dev, struct
device_attribute *attr, char *buf)
@@ -1714,22 +1906,22 @@
switch (aiptek->curSetting.mouseButtonRight) {
case AIPTEK_MOUSE_LEFT_BUTTON:
- s = "left";
+ s = pLeft;
break;
case AIPTEK_MOUSE_MIDDLE_BUTTON:
- s = "middle";
+ s = pMiddle;
break;
case AIPTEK_MOUSE_RIGHT_BUTTON:
- s = "right";
+ s = pRight;
break;
default:
- s = "unknown";
+ s = pUnknown;
break;
}
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, pString, s);
}
static ssize_t
@@ -1740,13 +1932,15 @@
if (aiptek == NULL)
return 0;
- if (strcmp(buf, "left") == 0) {
- aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_LEFT_BUTTON;
- } else if (strcmp(buf, "middle") == 0) {
+ if (strncmp(buf, pLeft, 4) == 0) {
+ aiptek->newSetting.mouseButtonRight =
+ AIPTEK_MOUSE_LEFT_BUTTON;
+ } else if (strncmp(buf, pMiddle, 6) == 0) {
aiptek->newSetting.mouseButtonRight =
AIPTEK_MOUSE_MIDDLE_BUTTON;
- } else if (strcmp(buf, "right") == 0) {
- aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_RIGHT_BUTTON;
+ } else if (strncmp(buf, pRight, 5) == 0) {
+ aiptek->newSetting.mouseButtonRight =
+ AIPTEK_MOUSE_RIGHT_BUTTON;
}
return count;
}
@@ -1767,9 +1961,9 @@
return 0;
if (aiptek->curSetting.wheel == AIPTEK_WHEEL_DISABLE) {
- return snprintf(buf, PAGE_SIZE, "disable\n");
+ return snprintf(buf, PAGE_SIZE, pString, pDisable);
} else {
- return snprintf(buf, PAGE_SIZE, "%d\n",
+ return snprintf(buf, PAGE_SIZE, pInt,
aiptek->curSetting.wheel);
}
}
@@ -1782,7 +1976,7 @@
if (aiptek == NULL)
return 0;
- aiptek->newSetting.wheel = (int)simple_strtol(buf, NULL, 10);
+ aiptek->newSetting.wheel = (int) simple_strtol(buf, 0, 10);
return count;
}
@@ -1821,14 +2015,16 @@
memcpy(&aiptek->curSetting, &aiptek->newSetting,
sizeof(struct aiptek_settings));
- if (aiptek_program_tablet(aiptek) < 0)
+ if (aiptek_program_tablet(aiptek) < 0) {
return -EIO;
+ }
return count;
}
static DEVICE_ATTR(execute,
- S_IRUGO | S_IWUGO, show_tabletExecute, store_tabletExecute);
+ S_IRUGO | S_IWUGO, show_tabletExecute,
+ store_tabletExecute);
/***********************************************************************
* support routines for the 'odm_code' file. Note that this file
@@ -1841,7 +2037,7 @@
if (aiptek == NULL)
return 0;
- return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.odmCode);
+ return snprintf(buf, PAGE_SIZE, pHex, aiptek->features.odmCode);
}
static DEVICE_ATTR(odm_code, S_IRUGO, show_tabletODMCode, NULL);
@@ -1857,7 +2053,7 @@
if (aiptek == NULL)
return 0;
- return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.modelCode);
+ return snprintf(buf, PAGE_SIZE, pHex, aiptek->features.modelCode);
}
static DEVICE_ATTR(model_code, S_IRUGO, show_tabletModelCode, NULL);
@@ -1873,7 +2069,7 @@
if (aiptek == NULL)
return 0;
- return snprintf(buf, PAGE_SIZE, "%04x\n",
+ return snprintf(buf, PAGE_SIZE, pHex,
aiptek->features.firmwareCode);
}
@@ -1885,6 +2081,7 @@
*/
static void aiptek_delete_files(struct device *dev)
{
+ device_remove_file(dev, &dev_attr_debug);
device_remove_file(dev, &dev_attr_size);
device_remove_file(dev, &dev_attr_product_id);
device_remove_file(dev, &dev_attr_vendor_id);
@@ -1896,6 +2093,7 @@
device_remove_file(dev, &dev_attr_xtilt);
device_remove_file(dev, &dev_attr_ytilt);
device_remove_file(dev, &dev_attr_jitter);
+ device_remove_file(dev, &dev_attr_proximity_timeout);
device_remove_file(dev, &dev_attr_delay);
device_remove_file(dev, &dev_attr_input_path);
device_remove_file(dev, &dev_attr_event_count);
@@ -1921,6 +2119,7 @@
int ret;
if ((ret = device_create_file(dev, &dev_attr_size)) ||
+ (ret = device_create_file(dev, &dev_attr_debug)) ||
(ret = device_create_file(dev, &dev_attr_product_id)) ||
(ret = device_create_file(dev, &dev_attr_vendor_id)) ||
(ret = device_create_file(dev, &dev_attr_vendor)) ||
@@ -1931,6 +2130,7 @@
(ret = device_create_file(dev, &dev_attr_xtilt)) ||
(ret = device_create_file(dev, &dev_attr_ytilt)) ||
(ret = device_create_file(dev, &dev_attr_jitter)) ||
+ (ret = device_create_file(dev, &dev_attr_proximity_timeout)) ||
(ret = device_create_file(dev, &dev_attr_delay)) ||
(ret = device_create_file(dev, &dev_attr_input_path)) ||
(ret = device_create_file(dev, &dev_attr_event_count)) ||
@@ -1951,6 +2151,9 @@
return ret;
}
+/* forward declaration */
+static void activity_check(unsigned long data);
+
/***********************************************************************
* This routine is called when a tablet has been identified. It basically
* sets up the tablet and the driver's internal structures.
@@ -1964,6 +2167,7 @@
struct input_dev *inputdev;
struct input_handle *inputhandle;
struct list_head *node, *next;
+ // char path[64 + 1];
int i;
int speeds[] = { 0,
AIPTEK_PROGRAMMABLE_DELAY_50,
@@ -2002,6 +2206,8 @@
aiptek->inDelay = 0;
aiptek->endDelay = 0;
aiptek->previousJitterable = 0;
+ aiptek->lastMacro = 0;
+
/* Set up the curSettings struct. Said struct contains the current
* programmable parameters. The newSetting struct contains changes
@@ -2021,10 +2227,58 @@
aiptek->curSetting.stylusButtonLower = AIPTEK_STYLUS_LOWER_BUTTON;
aiptek->curSetting.jitterDelay = jitterDelay;
aiptek->curSetting.programmableDelay = programmableDelay;
+ aiptek->curSetting.proximityTimeout = 0;
/* Both structs should have equivalent settings
*/
- aiptek->newSetting = aiptek->curSetting;
+ memcpy(&aiptek->newSetting, &aiptek->curSetting,
+ sizeof(struct aiptek_settings));
+
+ /* Now program the capacities of the tablet, in terms of being
+ * an input device.
+ */
+ set_bit(EV_KEY, aiptek->inputdev->evbit);
+ set_bit(EV_ABS, aiptek->inputdev->evbit);
+ set_bit(EV_REL, aiptek->inputdev->evbit);
+ set_bit(EV_MSC, aiptek->inputdev->evbit);
+
+ set_bit(ABS_X, aiptek->inputdev->absbit);
+ set_bit(ABS_Y, aiptek->inputdev->absbit);
+ set_bit(ABS_PRESSURE, aiptek->inputdev->absbit);
+ set_bit(ABS_TILT_X, aiptek->inputdev->absbit);
+ set_bit(ABS_TILT_Y, aiptek->inputdev->absbit);
+ set_bit(ABS_WHEEL, aiptek->inputdev->absbit);
+ set_bit(ABS_MISC, aiptek->inputdev->absbit);
+
+ set_bit(REL_X, aiptek->inputdev->relbit);
+ set_bit(REL_Y, aiptek->inputdev->relbit);
+ set_bit(REL_WHEEL, aiptek->inputdev->relbit);
+ set_bit(REL_MISC, aiptek->inputdev->relbit);
+
+ set_bit(BTN_LEFT, aiptek->inputdev->keybit);
+ set_bit(BTN_RIGHT, aiptek->inputdev->keybit);
+ set_bit(BTN_MIDDLE, aiptek->inputdev->keybit);
+
+ set_bit(BTN_TOOL_PEN, aiptek->inputdev->keybit);
+ set_bit(BTN_TOOL_RUBBER, aiptek->inputdev->keybit);
+ set_bit(BTN_TOOL_PENCIL, aiptek->inputdev->keybit);
+ set_bit(BTN_TOOL_AIRBRUSH, aiptek->inputdev->keybit);
+ set_bit(BTN_TOOL_BRUSH, aiptek->inputdev->keybit);
+ set_bit(BTN_TOOL_MOUSE, aiptek->inputdev->keybit);
+ set_bit(BTN_TOOL_LENS, aiptek->inputdev->keybit);
+ set_bit(BTN_TOUCH, aiptek->inputdev->keybit);
+ set_bit(BTN_STYLUS, aiptek->inputdev->keybit);
+ set_bit(BTN_STYLUS2, aiptek->inputdev->keybit);
+
+ set_bit(MSC_SERIAL, aiptek->inputdev->mscbit);
+
+ /* Programming the tablet macro keys needs to be done with a for loop
+ * as the keycodes are discontiguous.
+ */
+ for (i = 0; i < sizeof(macroKeyEvents) / sizeof(macroKeyEvents[0]);
+ ++i) {
+ set_bit(macroKeyEvents[i], aiptek->inputdev->keybit);
+ }
/* Determine the usb devices' physical path.
* Asketh not why we always pretend we're using "../input0",
@@ -2034,7 +2288,7 @@
* us something...
*/
usb_make_path(usbdev, aiptek->features.usbPath,
- sizeof(aiptek->features.usbPath));
+ sizeof(aiptek->features.usbPath));
strlcat(aiptek->features.usbPath, "/input0",
sizeof(aiptek->features.usbPath));
@@ -2048,43 +2302,10 @@
inputdev->private = aiptek;
inputdev->open = aiptek_open;
inputdev->close = aiptek_close;
+ aiptek->usbdev = usbdev;
+ aiptek->ifnum = intf->altsetting[0].desc.bInterfaceNumber;
- /* Now program the capacities of the tablet, in terms of being
- * an input device.
- */
- inputdev->evbit[0] |= BIT(EV_KEY)
- | BIT(EV_ABS)
- | BIT(EV_REL)
- | BIT(EV_MSC);
-
- inputdev->absbit[0] |= BIT(ABS_MISC);
-
- inputdev->relbit[0] |=
- (BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL) | BIT(REL_MISC));
-
- inputdev->keybit[LONG(BTN_LEFT)] |=
- (BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE));
-
- inputdev->keybit[LONG(BTN_DIGI)] |=
- (BIT(BTN_TOOL_PEN) |
- BIT(BTN_TOOL_RUBBER) |
- BIT(BTN_TOOL_PENCIL) |
- BIT(BTN_TOOL_AIRBRUSH) |
- BIT(BTN_TOOL_BRUSH) |
- BIT(BTN_TOOL_MOUSE) |
- BIT(BTN_TOOL_LENS) |
- BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2));
-
- inputdev->mscbit[0] = BIT(MSC_SERIAL);
-
- /* Programming the tablet macro keys needs to be done with a for loop
- * as the keycodes are discontiguous.
- */
- for (i = 0; i < ARRAY_SIZE(macroKeyEvents); ++i)
- set_bit(macroKeyEvents[i], inputdev->keybit);
-
- /*
- * Program the input device coordinate capacities. We do not yet
+ /* Program the input device coordinate capacities. We do not yet
* know what maximum X, Y, and Z values are, so we're putting fake
* values in. Later, we'll ask the tablet to put in the correct
* values.
@@ -2095,9 +2316,14 @@
input_set_abs_params(inputdev, ABS_TILT_X, AIPTEK_TILT_MIN,
AIPTEK_TILT_MAX, 0, 0);
input_set_abs_params(inputdev, ABS_TILT_Y, AIPTEK_TILT_MIN,
AIPTEK_TILT_MAX, 0, 0);
input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN,
AIPTEK_WHEEL_MAX - 1, 0, 0);
-
+ input_set_abs_params(inputdev, ABS_MISC, 0, 255, 0, 0);
endpoint = &intf->altsetting[0].endpoint[0].desc;
+ /* inactivity timer. */
+ init_timer(&aiptek->activityCheck);
+ aiptek->activityCheck.function = activity_check;
+ aiptek->activityCheck.data = (unsigned long) aiptek;
+
/* Go set up our URB, which is called when the tablet receives
* input.
*/
@@ -2111,6 +2337,29 @@
aiptek->urb->transfer_dma = aiptek->data_dma;
aiptek->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ /* Register the tablet as an Input Device
+ */
+ input_register_device(aiptek->inputdev);
+
+ /* We now will look for the evdev device which is mapped to
+ * the tablet. The partial name is kept in the link list of
+ * input_handles associated with this input device.
+ * What identifies an evdev input_handler is that it begins
+ * with 'event', continues with a digit, and that in turn
+ * is mapped to /{devfs}/input/eventN.
+ */
+ inputdev = aiptek->inputdev;
+ list_for_each_safe(node, next, &inputdev->h_list) {
+ inputhandle = to_handle(node);
+ if (strncmp(inputhandle->name, "event", 5) == 0) {
+ strcpy(aiptek->features.inputPath,
+ inputhandle->name);
+ break;
+ }
+ }
+
+ info("input: Aiptek as %s\n", aiptek->features.inputPath);
+
/* Program the tablet. This sets the tablet up in the mode
* specified in newSetting, and also queries the tablet's
* physical capacities.
@@ -2131,24 +2380,12 @@
break;
}
}
-
- /* Register the tablet as an Input Device
- */
- input_register_device(aiptek->inputdev);
-
- /* We now will look for the evdev device which is mapped to
- * the tablet. The partial name is kept in the link list of
- * input_handles associated with this input device.
- * What identifies an evdev input_handler is that it begins
- * with 'event', continues with a digit, and that in turn
- * is mapped to input/eventN.
- */
- list_for_each_safe(node, next, &inputdev->h_list) {
- inputhandle = to_handle(node);
- if (strncmp(inputhandle->name, "event", 5) == 0) {
- strcpy(aiptek->features.inputPath, inputhandle->name);
- break;
- }
+
+ /* Murphy says that some day someone will have a tablet that fails the
+ above test. That's you, Frederic Rodrigo */
+ if (i == ARRAY_SIZE(speeds)) {
+ info("input: Aiptek tablet insane?");
+ goto fail2;
}
/* Associate this driver's struct with the usb interface.
@@ -2173,6 +2410,23 @@
return -ENOMEM;
}
+/* Activity checking thread. If a sufficient period of inactivity is detected,
+ the tablet's proximity is reset. */
+static void activity_check(unsigned long data)
+{
+ struct aiptek *aiptek = (struct aiptek *) data;
+
+ /* This timer is set *after* handling input for the table, and
+ cleared *before* handling it. Am guessing that we never run
+ concurrently the module code. */
+
+ /* info("aiptek: timeout proximity\n"); */
+
+ /* apparently over-due. Reset the misc key, no tool, no proximity */
+ input_report_abs(aiptek->inputdev, ABS_MISC, 0);
+ input_sync(aiptek->inputdev);
+}
+
/* Forward declaration */
static void aiptek_disconnect(struct usb_interface *intf);
@@ -2190,6 +2444,9 @@
{
struct aiptek *aiptek = usb_get_intfdata(intf);
+ /* First remove any timer. */
+ del_timer(&aiptek->activityCheck);
+
/* Disassociate driver's struct with usb interface
*/
usb_set_intfdata(intf, NULL);
@@ -2204,6 +2461,7 @@
AIPTEK_PACKET_LENGTH,
aiptek->data, aiptek->data_dma);
kfree(aiptek);
+ aiptek = NULL;
}
}
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=so...
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel