aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorPaul Fox <pgf@laptop.org>2009-08-05 03:30:31 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-08-05 03:34:32 -0400
commitc46dd1eb9a4f1b8c1bb597a75199e3d34fb7b43b (patch)
tree62f03ed65d4e6cc309535e6cafb20290cce3698e /drivers/input
parentcf5f439b48f82c230dcd81d0061e00664cbb6d39 (diff)
Input: hgpk - forced recalibration for the OLPC touchpad
The OLPC XO laptop incorporates a combination touchpad/tablet device which unfortunately requires frequent recalibration. The driver will force this automatically when various suspicious behaviors are observed, and the user can recalibrate manually (with a special keyboard sequence). There's currently no way, however, for an external program to cause recalibration. We can not use the reconnect capability which is already available in /sys because full reset of the touchpad takes 1.1 - 1.2 secons which is too long. This patch creates a new node in /sys which, when written with '1', will force a touchpad recalibration; no other writes (or reads) of this node are supported. Signed-off-by: Paul Fox <pgf@laptop.org> Acked-by: Andres Salomon <dilinger@collabora.co.uk> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/mouse/hgpk.c55
1 files changed, 52 insertions, 3 deletions
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c
index a1ad2f1a7bb3..f5aa035774d9 100644
--- a/drivers/input/mouse/hgpk.c
+++ b/drivers/input/mouse/hgpk.c
@@ -369,12 +369,46 @@ static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data,
369__PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL, 369__PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL,
370 hgpk_show_powered, hgpk_set_powered, 0); 370 hgpk_show_powered, hgpk_set_powered, 0);
371 371
372static ssize_t hgpk_trigger_recal_show(struct psmouse *psmouse,
373 void *data, char *buf)
374{
375 return -EINVAL;
376}
377
378static ssize_t hgpk_trigger_recal(struct psmouse *psmouse, void *data,
379 const char *buf, size_t count)
380{
381 struct hgpk_data *priv = psmouse->private;
382 unsigned long value;
383 int err;
384
385 err = strict_strtoul(buf, 10, &value);
386 if (err || value != 1)
387 return -EINVAL;
388
389 /*
390 * We queue work instead of doing recalibration right here
391 * to avoid adding locking to to hgpk_force_recalibrate()
392 * since workqueue provides serialization.
393 */
394 psmouse_queue_work(psmouse, &priv->recalib_wq, 0);
395 return count;
396}
397
398__PSMOUSE_DEFINE_ATTR(recalibrate, S_IWUSR | S_IRUGO, NULL,
399 hgpk_trigger_recal_show, hgpk_trigger_recal, 0);
400
372static void hgpk_disconnect(struct psmouse *psmouse) 401static void hgpk_disconnect(struct psmouse *psmouse)
373{ 402{
374 struct hgpk_data *priv = psmouse->private; 403 struct hgpk_data *priv = psmouse->private;
375 404
376 device_remove_file(&psmouse->ps2dev.serio->dev, 405 device_remove_file(&psmouse->ps2dev.serio->dev,
377 &psmouse_attr_powered.dattr); 406 &psmouse_attr_powered.dattr);
407
408 if (psmouse->model >= HGPK_MODEL_C)
409 device_remove_file(&psmouse->ps2dev.serio->dev,
410 &psmouse_attr_recalibrate.dattr);
411
378 psmouse_reset(psmouse); 412 psmouse_reset(psmouse);
379 kfree(priv); 413 kfree(priv);
380} 414}
@@ -423,10 +457,25 @@ static int hgpk_register(struct psmouse *psmouse)
423 457
424 err = device_create_file(&psmouse->ps2dev.serio->dev, 458 err = device_create_file(&psmouse->ps2dev.serio->dev,
425 &psmouse_attr_powered.dattr); 459 &psmouse_attr_powered.dattr);
426 if (err) 460 if (err) {
427 hgpk_err(psmouse, "Failed to create sysfs attribute\n"); 461 hgpk_err(psmouse, "Failed creating 'powered' sysfs node\n");
462 return err;
463 }
428 464
429 return err; 465 /* C-series touchpads added the recalibrate command */
466 if (psmouse->model >= HGPK_MODEL_C) {
467 err = device_create_file(&psmouse->ps2dev.serio->dev,
468 &psmouse_attr_recalibrate.dattr);
469 if (err) {
470 hgpk_err(psmouse,
471 "Failed creating 'recalibrate' sysfs node\n");
472 device_remove_file(&psmouse->ps2dev.serio->dev,
473 &psmouse_attr_powered.dattr);
474 return err;
475 }
476 }
477
478 return 0;
430} 479}
431 480
432int hgpk_init(struct psmouse *psmouse) 481int hgpk_init(struct psmouse *psmouse)