/*
* OLPC HGPK (XO-1) touchpad PS/2 mouse driver
*
* Copyright (c) 2006-2008 One Laptop Per Child
* Authors:
* Zephaniah E. Hull
* Andres Salomon <[email protected]>
*
* This driver is partly based on the ALPS driver, which is:
*
* Copyright (c) 2003 Neil Brown <[email protected]>
* Copyright (c) 2003-2005 Peter Osterlund <[email protected]>
* Copyright (c) 2004 Dmitry Torokhov <[email protected]>
* Copyright (c) 2005 Vojtech Pavlik <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/*
* The spec from ALPS is available from
* <http://wiki.laptop.org/go/Touch_Pad/Tablet>. It refers to this
* device as HGPK (Hybrid GS, PT, and Keymatrix).
*
* The earliest versions of the device had simultaneous reporting; that
* was removed. After that, the device used the Advanced Mode GS/PT streaming
* stuff. That turned out to be too buggy to support, so we've finally
* switched to Mouse Mode (which utilizes only the center 1/3 of the touchpad).
*/
#define DEBUG
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/serio.h>
#include <linux/libps2.h>
#include <linux/delay.h>
#include <asm/olpc.h>
#include "psmouse.h"
#include "hgpk.h"
#define ILLEGAL_XY 999999
static bool tpdebug;
module_param(tpdebug, bool, 0644);
MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG.");
static int recalib_delta = 100;
module_param(recalib_delta, int, 0644);
MODULE_PARM_DESC(recalib_delta,
"packets containing a delta this large will be discarded, and a "
"recalibration may be scheduled.");
static int jumpy_delay = 20;
module_param(jumpy_delay, int, 0644);
MODULE_PARM_DESC(jumpy_delay,
"delay (ms) before recal after jumpiness detected");
static int spew_delay = 1;
module_param(spew_delay, int, 0644);
MODULE_PARM_DESC(spew_delay,
"delay (ms) before recal after packet spew detected");
static int recal_guard_time;
module_param(recal_guard_time, int, 0644);
MODULE_PARM_DESC(recal_guard_time,
"interval (ms) during which recal will be restarted if packet received");
static int post_interrupt_delay = 40;
module_param(post_interrupt_delay, int, 0644);
MODULE_PARM_DESC(post_interrupt_delay,
"delay (ms) before recal after recal interrupt detected");
static bool autorecal = true;
module_param(autorecal, bool, 0644);
MODULE_PARM_DESC(autorecal, "enable recalibration in the driver");
static char hgpk_mode_name[16];
module_param_string(hgpk_mode, hgpk_mode_name, sizeof(hgpk_mode_name), 0644);
MODULE_PARM_DESC(hgpk_mode,
"default hgpk mode: mouse, glidesensor or pentablet");
static int hgpk_default_mode = HGPK_MODE_MOUSE;
static const char * const hgpk_mode_names[] = {
[HGPK_MODE_MOUSE] = "Mouse",
[HGPK_MODE_GLIDESENSOR] = "GlideSensor",
[HGPK_MODE_PENTABLET] = "PenTablet",
};
static int hgpk_mode_from_name(const char *buf, int len)
{
int i;
for (i = 0; i < ARRAY_SIZE(hgpk_mode_names); i++) {
const char *name = hgpk_mode_names[i];
if (strlen(name) == len && !strncasecmp(name, buf, len))
return i;
}
return HGPK_MODE_INVALID;
}
/*
* see if new value is within 20% of half of old value
*/
static int approx_half(int curr, int prev)
{
int belowhalf, abovehalf;
if (curr < 5 || prev < 5)
return 0;
belowhalf = (prev * 8) / 20;
abovehalf = (prev * 12) / 20;
return belowhalf < curr && curr <= abovehalf;
}
/*
* Throw out oddly large delta packets, and any that immediately follow whose
* values are each approximately half of the previous. It seems that the ALPS
* firmware emits errant packets, and they get averaged out slowly.
*/
static int hgpk_discard_decay_hack(struct psmouse *psmouse, int x, int y)
{
struct hgpk_data *priv = psmouse->private;
int avx, avy;
bool do_recal = false;
avx = abs(x);
avy = abs(y);
/* discard if too big, or half that but > 4 times the prev delta */
if (avx > recalib_delta ||
(avx > recalib_delta / 2 && ((avx / 4) > priv->xlast))) {
psmouse_warn(psmouse, "detected %dpx jump in x\n", x);
priv->xbigj = avx;
} else if (approx_half(avx, priv->xbigj)) {
psmouse_warn(psmouse, "detected secondary %dpx jump in x\n", x);
priv->xbigj = avx;
priv->xsaw_secondary++;
} else {
if (priv->xbigj && priv->xsaw_secondary > 1)
do_recal = true;
priv->xbigj = 0;
priv->xsaw_secondary = 0;
}
if (avy > recalib_delta ||
(avy > recalib_delta / 2 && ((avy / 4) > priv->ylast))) {
psmouse_warn(psmouse, "detected %dpx jump in y\n", y);
priv->ybigj = avy;
} else if (approx_half(avy, priv->ybigj)) {
psmouse_warn(psmouse, "detected secondary %dpx jump in y\n", y);
priv->ybigj = avy;
priv->ysaw_secondary++;
} else {
if (priv->ybigj && priv->ysaw_secondary > 1)
do_recal = true;
priv->ybigj = 0;
priv->ysaw_secondary = 0;
}
priv->xlast = avx;
priv->ylast = avy;
if (do_recal && jumpy_delay) {
psmouse_warn(psmouse, "scheduling recalibration\n");
psmouse_queue_work(psmouse, &priv->recalib_wq,
msecs_to_jiffies(jumpy_delay));
}
return priv->xbigj || priv->ybigj;
}
static void hgpk_reset_spew_detection(struct hgpk_data *priv)
{
priv->spew_count = 0;
priv->dupe_count = 0;
priv->x_tally = 0;
priv->y_tally = 0;
priv->spew_flag = NO_SPEW;
}
static void hgpk_reset_hack_state(struct psmouse *psmouse)
{
struct hgpk_data *priv = psmouse->private;
priv->abs_x = priv->abs_y = -1;
priv->xlast = priv->ylast = ILLEGAL_XY;
priv->xbigj = priv->ybigj = 0;
priv->xsaw_secondary = priv->ysaw_secondary = 0;
hgpk_reset_spew_detection(priv);
}
/*
* We have no idea why this particular hardware bug occurs. The touchpad
* will randomly start spewing packets without anything touching the
* pad. This wouldn't necessarily be bad, but it's indicative of a
* severely miscalibrated pad; attempting to use the touchpad while it's
* spewing means the cursor will jump all over the place, and act "drunk".
*
* The packets that are spewed tend to all have deltas between -2 and 2, and
* the cursor will move around without really going very far. It will
* tend to end up in the same location; if we tally up the changes over
* 100 packets, we end up w/ a final delta of close to 0. This happens
* pretty regularly when the touchpad is spewing, and is pretty hard to
* manually trigger (at least for *my* fingers). So, it makes a perfect
* scheme for detecting spews.
*/
static void hgpk_spewing_hack(struct psmouse *psmouse,
int l, int r, int x, int y)
{
struct hgpk_data *priv = psmouse->private;
/* ignore button press packets; many in a row could trigger
* a false-positive! */
if (l || r)
return;
/* don't track spew if the workaround feature has been turned off */
if (!spew_delay)
return;
if (abs(x) > 3 || abs(y) > 3) {
/* no spew, or spew ended */
hgpk_reset_spew_detection(priv);
return;
}
/* Keep a tally of the overall delta to the cursor position caused by
* the spew */
priv->x_tally += x;
priv->y_tally += y;
switch (priv->spew_flag) {
case NO_SPEW:
/* we're not spewing, but this packet might be the start */
priv->spew_flag = MAYBE_SPEWING;
/* fall-through */
case MAYBE_SPEWING:
priv->spew_count++;
if (priv->spew_count < SPEW_WATCH_COUNT)
break;
/* excessive spew detected, request recalibration */
priv->spew_flag = SPEW_DETECTED;
/* fall-through */
case SPEW_DETECTED:
/* only recalibrate when the overall delta to the cursor
* is really small. if the spew is causing significant cursor
* movement, it is probably a case of the user moving the
* cursor very slowly across the screen. */
if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) {
psmouse_warn(psmouse, "packet spew detected (%d,%d)\n",
priv->x_tally, priv->y_tally);
priv->spew_flag = RECALIBRATING;
psmouse_queue_work(psmouse, &priv->recalib_wq,
msecs_to_jiffies(spew_delay));
}
break;
case RECALIB
hgpk.rar_mouse
版权申诉
160 浏览量
2022-09-20
22:06:02
上传
评论
收藏 9KB RAR 举报
朱moyimi
- 粉丝: 64
- 资源: 1万+
最新资源
- 简单的Python示例,演示了如何使用TCP/IP协议进行基本的客户端和服务器通信
- 考试.sql
- keil2 + proteus + 8051.exe
- 1961ee27df03bd4595d28e24b00dde4e_744c805f7e4fb4d40fa3f695bfbab035_8(1).c
- mediapipe-0.9.0.1-cp37-cp37m-win-amd64.whl.zip
- windows注册表编辑工具
- mediapipe-0.9.0.1-cp37-cp37m-win-amd64.whl.zip
- 校园通行码预约管理系统20240522075502
- 车类型数据集6250张VOC+YOLO格式.zip
- The PyTorch implementation of STGCN.STGCN-main.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈