diff options
Diffstat (limited to 'drivers/input/mouse/psmouse-base.c')
-rw-r--r-- | drivers/input/mouse/psmouse-base.c | 81 |
1 files changed, 53 insertions, 28 deletions
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index f5a6be1d3c46..126e977e199e 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "synaptics.h" | 25 | #include "synaptics.h" |
26 | #include "logips2pp.h" | 26 | #include "logips2pp.h" |
27 | #include "alps.h" | 27 | #include "alps.h" |
28 | #include "hgpk.h" | ||
28 | #include "lifebook.h" | 29 | #include "lifebook.h" |
29 | #include "trackpoint.h" | 30 | #include "trackpoint.h" |
30 | #include "touchkit_ps2.h" | 31 | #include "touchkit_ps2.h" |
@@ -201,6 +202,12 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse) | |||
201 | return PSMOUSE_FULL_PACKET; | 202 | return PSMOUSE_FULL_PACKET; |
202 | } | 203 | } |
203 | 204 | ||
205 | void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work, | ||
206 | unsigned long delay) | ||
207 | { | ||
208 | queue_delayed_work(kpsmoused_wq, work, delay); | ||
209 | } | ||
210 | |||
204 | /* | 211 | /* |
205 | * __psmouse_set_state() sets new psmouse state and resets all flags. | 212 | * __psmouse_set_state() sets new psmouse state and resets all flags. |
206 | */ | 213 | */ |
@@ -220,7 +227,7 @@ static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_sta | |||
220 | * is not a concern. | 227 | * is not a concern. |
221 | */ | 228 | */ |
222 | 229 | ||
223 | static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) | 230 | void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) |
224 | { | 231 | { |
225 | serio_pause_rx(psmouse->ps2dev.serio); | 232 | serio_pause_rx(psmouse->ps2dev.serio); |
226 | __psmouse_set_state(psmouse, new_state); | 233 | __psmouse_set_state(psmouse, new_state); |
@@ -305,7 +312,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, | |||
305 | psmouse->name, psmouse->phys, psmouse->pktcnt); | 312 | psmouse->name, psmouse->phys, psmouse->pktcnt); |
306 | psmouse->badbyte = psmouse->packet[0]; | 313 | psmouse->badbyte = psmouse->packet[0]; |
307 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | 314 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); |
308 | queue_work(kpsmoused_wq, &psmouse->resync_work); | 315 | psmouse_queue_work(psmouse, &psmouse->resync_work, 0); |
309 | goto out; | 316 | goto out; |
310 | } | 317 | } |
311 | 318 | ||
@@ -342,7 +349,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, | |||
342 | time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) { | 349 | time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) { |
343 | psmouse->badbyte = psmouse->packet[0]; | 350 | psmouse->badbyte = psmouse->packet[0]; |
344 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | 351 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); |
345 | queue_work(kpsmoused_wq, &psmouse->resync_work); | 352 | psmouse_queue_work(psmouse, &psmouse->resync_work, 0); |
346 | goto out; | 353 | goto out; |
347 | } | 354 | } |
348 | 355 | ||
@@ -630,8 +637,20 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
630 | } | 637 | } |
631 | } | 638 | } |
632 | 639 | ||
633 | if (max_proto > PSMOUSE_IMEX) { | 640 | /* |
641 | * Try OLPC HGPK touchpad. | ||
642 | */ | ||
643 | if (max_proto > PSMOUSE_IMEX && | ||
644 | hgpk_detect(psmouse, set_properties) == 0) { | ||
645 | if (!set_properties || hgpk_init(psmouse) == 0) | ||
646 | return PSMOUSE_HGPK; | ||
647 | /* | ||
648 | * Init failed, try basic relative protocols | ||
649 | */ | ||
650 | max_proto = PSMOUSE_IMEX; | ||
651 | } | ||
634 | 652 | ||
653 | if (max_proto > PSMOUSE_IMEX) { | ||
635 | if (genius_detect(psmouse, set_properties) == 0) | 654 | if (genius_detect(psmouse, set_properties) == 0) |
636 | return PSMOUSE_GENPS; | 655 | return PSMOUSE_GENPS; |
637 | 656 | ||
@@ -762,6 +781,14 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
762 | .detect = touchkit_ps2_detect, | 781 | .detect = touchkit_ps2_detect, |
763 | }, | 782 | }, |
764 | #endif | 783 | #endif |
784 | #ifdef CONFIG_MOUSE_PS2_OLPC | ||
785 | { | ||
786 | .type = PSMOUSE_HGPK, | ||
787 | .name = "OLPC HGPK", | ||
788 | .alias = "hgpk", | ||
789 | .detect = hgpk_detect, | ||
790 | }, | ||
791 | #endif | ||
765 | { | 792 | { |
766 | .type = PSMOUSE_CORTRON, | 793 | .type = PSMOUSE_CORTRON, |
767 | .name = "CortronPS/2", | 794 | .name = "CortronPS/2", |
@@ -935,7 +962,7 @@ static int psmouse_poll(struct psmouse *psmouse) | |||
935 | static void psmouse_resync(struct work_struct *work) | 962 | static void psmouse_resync(struct work_struct *work) |
936 | { | 963 | { |
937 | struct psmouse *parent = NULL, *psmouse = | 964 | struct psmouse *parent = NULL, *psmouse = |
938 | container_of(work, struct psmouse, resync_work); | 965 | container_of(work, struct psmouse, resync_work.work); |
939 | struct serio *serio = psmouse->ps2dev.serio; | 966 | struct serio *serio = psmouse->ps2dev.serio; |
940 | psmouse_ret_t rc = PSMOUSE_GOOD_DATA; | 967 | psmouse_ret_t rc = PSMOUSE_GOOD_DATA; |
941 | int failed = 0, enabled = 0; | 968 | int failed = 0, enabled = 0; |
@@ -1194,7 +1221,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
1194 | goto err_free; | 1221 | goto err_free; |
1195 | 1222 | ||
1196 | ps2_init(&psmouse->ps2dev, serio); | 1223 | ps2_init(&psmouse->ps2dev, serio); |
1197 | INIT_WORK(&psmouse->resync_work, psmouse_resync); | 1224 | INIT_DELAYED_WORK(&psmouse->resync_work, psmouse_resync); |
1198 | psmouse->dev = input_dev; | 1225 | psmouse->dev = input_dev; |
1199 | snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys); | 1226 | snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys); |
1200 | 1227 | ||
@@ -1395,25 +1422,29 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev | |||
1395 | 1422 | ||
1396 | psmouse = serio_get_drvdata(serio); | 1423 | psmouse = serio_get_drvdata(serio); |
1397 | 1424 | ||
1398 | if (psmouse->state == PSMOUSE_IGNORE) { | 1425 | if (attr->protect) { |
1399 | retval = -ENODEV; | 1426 | if (psmouse->state == PSMOUSE_IGNORE) { |
1400 | goto out_unlock; | 1427 | retval = -ENODEV; |
1401 | } | 1428 | goto out_unlock; |
1429 | } | ||
1402 | 1430 | ||
1403 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | 1431 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { |
1404 | parent = serio_get_drvdata(serio->parent); | 1432 | parent = serio_get_drvdata(serio->parent); |
1405 | psmouse_deactivate(parent); | 1433 | psmouse_deactivate(parent); |
1406 | } | 1434 | } |
1407 | 1435 | ||
1408 | psmouse_deactivate(psmouse); | 1436 | psmouse_deactivate(psmouse); |
1437 | } | ||
1409 | 1438 | ||
1410 | retval = attr->set(psmouse, attr->data, buf, count); | 1439 | retval = attr->set(psmouse, attr->data, buf, count); |
1411 | 1440 | ||
1412 | if (retval != -ENODEV) | 1441 | if (attr->protect) { |
1413 | psmouse_activate(psmouse); | 1442 | if (retval != -ENODEV) |
1443 | psmouse_activate(psmouse); | ||
1414 | 1444 | ||
1415 | if (parent) | 1445 | if (parent) |
1416 | psmouse_activate(parent); | 1446 | psmouse_activate(parent); |
1447 | } | ||
1417 | 1448 | ||
1418 | out_unlock: | 1449 | out_unlock: |
1419 | mutex_unlock(&psmouse_mutex); | 1450 | mutex_unlock(&psmouse_mutex); |
@@ -1433,10 +1464,8 @@ static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const | |||
1433 | { | 1464 | { |
1434 | unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset); | 1465 | unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset); |
1435 | unsigned long value; | 1466 | unsigned long value; |
1436 | char *rest; | ||
1437 | 1467 | ||
1438 | value = simple_strtoul(buf, &rest, 10); | 1468 | if (strict_strtoul(buf, 10, &value)) |
1439 | if (*rest) | ||
1440 | return -EINVAL; | 1469 | return -EINVAL; |
1441 | 1470 | ||
1442 | if ((unsigned int)value != value) | 1471 | if ((unsigned int)value != value) |
@@ -1549,10 +1578,8 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co | |||
1549 | static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const char *buf, size_t count) | 1578 | static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const char *buf, size_t count) |
1550 | { | 1579 | { |
1551 | unsigned long value; | 1580 | unsigned long value; |
1552 | char *rest; | ||
1553 | 1581 | ||
1554 | value = simple_strtoul(buf, &rest, 10); | 1582 | if (strict_strtoul(buf, 10, &value)) |
1555 | if (*rest) | ||
1556 | return -EINVAL; | 1583 | return -EINVAL; |
1557 | 1584 | ||
1558 | psmouse->set_rate(psmouse, value); | 1585 | psmouse->set_rate(psmouse, value); |
@@ -1562,10 +1589,8 @@ static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const | |||
1562 | static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, const char *buf, size_t count) | 1589 | static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, const char *buf, size_t count) |
1563 | { | 1590 | { |
1564 | unsigned long value; | 1591 | unsigned long value; |
1565 | char *rest; | ||
1566 | 1592 | ||
1567 | value = simple_strtoul(buf, &rest, 10); | 1593 | if (strict_strtoul(buf, 10, &value)) |
1568 | if (*rest) | ||
1569 | return -EINVAL; | 1594 | return -EINVAL; |
1570 | 1595 | ||
1571 | psmouse->set_resolution(psmouse, value); | 1596 | psmouse->set_resolution(psmouse, value); |