diff options
author | ryd <ryd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-02-19 04:03:49 +0000 |
---|---|---|
committer | ryd <ryd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-02-19 04:03:49 +0000 |
commit | e4a3634c00818e77664da2c3592a95e8c8fad5d6 (patch) | |
tree | 5aec8287ecd3034c53cbbeb5a6408389b1d34507 /target/linux/olpc/files/drivers/input | |
parent | ac24192a897d17c7416cfc1a58ad5432404662de (diff) |
Adding .24 support for olpc
kernel compiles fine, but graphic support is broken
to test new kernel version, change
target/linux/olpc/Makefile
from .23.16 to .24
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@10493 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/olpc/files/drivers/input')
-rw-r--r-- | target/linux/olpc/files/drivers/input/mouse/olpc.c | 554 | ||||
-rw-r--r-- | target/linux/olpc/files/drivers/input/mouse/olpc.h | 49 |
2 files changed, 0 insertions, 603 deletions
diff --git a/target/linux/olpc/files/drivers/input/mouse/olpc.c b/target/linux/olpc/files/drivers/input/mouse/olpc.c deleted file mode 100644 index dc575ac06..000000000 --- a/target/linux/olpc/files/drivers/input/mouse/olpc.c +++ /dev/null @@ -1,554 +0,0 @@ -/* - * OLPC touchpad PS/2 mouse driver - * - * Copyright (c) 2006 One Laptop Per Child, inc. - * Authors Zephaniah E. Hull and Andres Salomon <dilinger@laptop.org> - * - * This driver is partly based on the ALPS driver, which is: - * - * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au> - * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com> - * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru> - * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> - * - * 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 touchpad on the OLPC is fairly wide, with the entire area usable - * as a tablet ("PT mode"), and the center 1/3rd also usable as a touchpad - * ("GS mode"). - * - * Earlier version of the device had simultaneous reporting; however, that - * was removed. Instead, the device now reports packets in one mode, and - * tells the driver when a mode switch needs to happen. - */ - -#include <linux/input.h> -#include <linux/serio.h> -#include <linux/libps2.h> -#include <linux/delay.h> -#include <asm/olpc.h> - -#include "psmouse.h" -#include "olpc.h" - -static int tpdebug; -module_param(tpdebug, int, 0644); - -#define OLPC_GS 1 /* The GS sensor. */ -#define OLPC_PT 2 /* The PT sensor. */ - -static struct olpc_model_info olpc_model_data[] = { - { { 0x67, 0x00, 0x00 }, OLPC_GS | OLPC_PT }, /* unknown ID */ - { { 0x67, 0x00, 0x0a }, OLPC_GS | OLPC_PT }, /* pre-B1 */ - { { 0x67, 0x00, 0x14 }, OLPC_GS }, /* B1.*/ - { { 0x67, 0x00, 0x28 }, OLPC_GS | OLPC_PT }, /* B2 */ - { { 0x67, 0x00, 0x3c }, OLPC_GS | OLPC_PT }, /* B2-2 */ - { { 0x67, 0x00, 0x50 }, OLPC_GS | OLPC_PT }, /* C1 */ -}; - -#define OLPC_PKT_PT 0xcf -#define OLPC_PKT_GS 0xff - -static int olpc_absolute_mode(struct psmouse *psmouse, int mode); - -/* - * OLPC absolute Mode - single-mode format - * - * byte 0: 1 1 0 0 1 1 1 1 - * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 - * byte 2(PT): 0 0 x9 x8 x7 ? pt-dsw gs-dsw - * byte 2(GS): 0 x10 x9 x8 x7 ? gs-dsw pt-dsw - * byte 3: 0 y9 y8 y7 1 0 swr swl - * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 - * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 - * - * ?'s are not defined in the protocol spec, may vary between models. - * - * swr/swl are the left/right buttons. - * - * pt-dsw/gs-dsw indicate that the pt/gs sensor is detecting a - * pen/finger - */ - -static void olpc_process_packet_gspt(struct psmouse *psmouse) -{ - struct olpc_data *priv = psmouse->private; - unsigned char *packet = psmouse->packet; - struct input_dev *dev = psmouse->dev; - struct input_dev *dev2 = priv->dev2; - int x, y, z, gs_down = 0, pt_down = 0, left, right; - struct timeval now_tv; - s64 now_ns; - - left = packet[3] & 1; - right = packet[3] & 2; - x = packet[1] | ((packet[2] & 0x78) << 4); - y = packet[4] | ((packet[3] & 0x70) << 3); - z = packet[5]; - - if (psmouse->packet[0] == OLPC_PKT_GS) { - pt_down = !!(packet[2] & 1); - gs_down = !!(packet[2] & 2); - } else if (psmouse->packet[0] == OLPC_PKT_PT) { - gs_down = !!(packet[2] & 1); - pt_down = !!(packet[2] & 2); - } - - /* - * XXX: Kludge. - * If it's been more than 30ms since the last packet, - * assume that there was a lift we were never told about. - */ - do_gettimeofday(&now_tv); - now_ns = timeval_to_ns (&now_tv); - if (now_ns >= priv->late) { - input_report_key(dev, BTN_TOUCH, 0); - input_report_key(dev, BTN_TOOL_PEN, 0); - input_report_key(dev2, BTN_TOUCH, 0); - input_report_key(dev2, BTN_TOOL_FINGER, 0); - - input_sync(dev); - input_sync(dev2); - } - - priv->late = now_ns + (30 * NSEC_PER_MSEC); - - - if (tpdebug) { - printk(KERN_DEBUG "%s %02x %02x %02x %02x %02x %02x\n", - __FUNCTION__, psmouse->packet[0], psmouse->packet[1], - psmouse->packet[2], psmouse->packet[3], psmouse->packet[4], - psmouse->packet[5]); - printk(KERN_DEBUG "l=%d r=%d p=%d g=%d x=%d y=%d z=%d\n", - left, right, pt_down, gs_down, x, y, z); - } - - if (psmouse->packet[0] == OLPC_PKT_PT) { - input_report_key(dev, BTN_LEFT, left); - input_report_key(dev, BTN_RIGHT, right); - } else if (psmouse->packet[0] == OLPC_PKT_GS) { - input_report_key(dev, BTN_LEFT, left); - input_report_key(dev, BTN_RIGHT, right); - input_report_key(dev2, BTN_LEFT, left); - input_report_key(dev2, BTN_RIGHT, right); - } - - input_report_key(dev, BTN_TOUCH, pt_down); - input_report_key(dev, BTN_TOOL_PEN, pt_down); - input_report_key(dev2, BTN_TOUCH, gs_down); - input_report_key(dev2, BTN_TOOL_FINGER, gs_down); - - input_report_abs(dev2, ABS_PRESSURE, z); - - if (psmouse->packet[0] == OLPC_PKT_PT && pt_down) { - input_report_abs(dev, ABS_X, x); - input_report_abs(dev, ABS_Y, y); - } else if (psmouse->packet[0] == OLPC_PKT_GS && gs_down) { - input_report_abs(dev2, ABS_X, x); - input_report_abs(dev2, ABS_Y, y); - } - - input_sync(dev); - input_sync(dev2); - - if (priv->pending_mode == OLPC_GS && - psmouse->packet[0] == OLPC_PKT_PT && pt_down) { - priv->pending_mode = 0; - cancel_delayed_work(&priv->mode_switch); - } - - if (priv->i->flags & (OLPC_PT|OLPC_GS)) { - int pending = 0; - if (psmouse->packet[0] == OLPC_PKT_PT && !pt_down) - pending = OLPC_GS; - else if (psmouse->packet[0] == OLPC_PKT_GS && pt_down) - pending = OLPC_PT; - - if (priv->current_mode == pending) { - priv->pending_mode = 0; - pending = priv->current_mode; - } - else if (priv->pending_mode != pending) { - priv->pending_mode = pending; - if (tpdebug) - printk(KERN_WARNING "Scheduling mode switch to %s.\n", - pending == OLPC_GS ? "GS" : "PT"); - - /* - * Apply a de-bounce when switching from PT to GS, to allow for - * spurious PT-up packets. - */ - if (priv->pending_mode == OLPC_GS) - queue_delayed_work(kpsmoused_wq, &priv->mode_switch, msecs_to_jiffies(50)); - else - queue_delayed_work(kpsmoused_wq, &priv->mode_switch, 0); - } - } -} - -static psmouse_ret_t olpc_process_byte(struct psmouse *psmouse) -{ - psmouse_ret_t ret = PSMOUSE_BAD_DATA; - - if (psmouse->packet[0] != OLPC_PKT_PT && - psmouse->packet[0] != OLPC_PKT_GS) - goto out; - - /* Bytes 2 - 6 should have 0 in the highest bit */ - if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && - (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) - goto out; - - if (psmouse->pktcnt == 6) { - olpc_process_packet_gspt(psmouse); - ret = PSMOUSE_FULL_PACKET; - goto out; - } - - ret = PSMOUSE_GOOD_DATA; -out: - if (ret != PSMOUSE_GOOD_DATA && ret != PSMOUSE_FULL_PACKET) - printk(KERN_DEBUG "%s: (%d) %02x %02x %02x %02x %02x %02x\n", - __FUNCTION__, psmouse->pktcnt, psmouse->packet[0], - psmouse->packet[1], psmouse->packet[2], - psmouse->packet[3], psmouse->packet[4], - psmouse->packet[5]); - return ret; -} - -static struct olpc_model_info *olpc_get_model(struct psmouse *psmouse) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - unsigned char param[4]; - int i; - - /* - * Now try "E7 report". Allowed responses are in - * olpc_model_data[].signature - */ - if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21)) - return NULL; - - param[0] = param[1] = param[2] = 0xff; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) - return NULL; - - pr_debug("olpc.c(%d): E7 report: %2.2x %2.2x %2.2x", - __LINE__, param[0], param[1], param[2]); - - for (i = 0; i < ARRAY_SIZE(olpc_model_data); i++) { - if (!memcmp(param, olpc_model_data[i].signature, - sizeof(olpc_model_data[i].signature))) { - printk(KERN_INFO __FILE__ ": OLPC touchpad revision 0x%x.\n", param[2]); - return olpc_model_data + i; - } - } - - /* - * ALPS creates new IDs pretty frequently; rather than listing them - * all, just assume they support the defaults. We've set aside the - * first entry of olpc_model_data as the catch-all. - */ - if (!memcmp(param, olpc_model_data[0].signature, 2)) { - printk(KERN_INFO __FILE__ ": unknown ALPS revision %x, assuming default flags.\n", param[2]); - return &olpc_model_data[0]; - } - - return NULL; -} - -static int olpc_find_mode(struct psmouse *psmouse) -{ - struct olpc_data *priv = psmouse->private; - int mode = priv->i->flags; - - if (mode & OLPC_GS) - mode = OLPC_GS; - else if (mode & OLPC_PT) - mode = OLPC_PT; - else - mode = -1; - - return mode; -} - -/* - * Touchpad should be disabled before calling this! - */ -static int olpc_new_mode(struct psmouse *psmouse, int mode) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - struct olpc_data *priv = psmouse->private; - unsigned char param; - int ret; - - if (tpdebug) - printk(KERN_WARNING __FILE__ ": Switching to %d. [%lu]\n", mode, jiffies); - - if ((ret = ps2_command(ps2dev, ¶m, 0x01F2))) - goto failed; - if ((ret = ps2_command(ps2dev, ¶m, 0x01F2))) - goto failed; - if ((ret = ps2_command(ps2dev, ¶m, 0x01F2))) - goto failed; - - switch (mode) { - default: - printk(KERN_WARNING __FILE__ ": Invalid mode %d. Defaulting to OLPC_GS.\n", mode); - case OLPC_GS: - ret = ps2_command(ps2dev, NULL, 0xE6); - break; - case OLPC_PT: - ret = ps2_command(ps2dev, NULL, 0xE7); - break; - } - if (ret) - goto failed; - - /* XXX: This is a bit hacky, make sure this isn't screwing stuff up. */ - psmouse->pktcnt = psmouse->out_of_sync = 0; - psmouse->last = jiffies; - psmouse->state = PSMOUSE_ACTIVATED; - - if ((ret = ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE))) - goto failed; - - priv->current_mode = mode; - priv->pending_mode = 0; - if (tpdebug) - printk(KERN_WARNING __FILE__ ": Switched to mode %d successful.\n", mode); - -failed: - if (ret) - printk(KERN_WARNING __FILE__ ": Mode switch to %d failed! (%d) [%lu]\n", mode, ret, jiffies); - return ret; -} - -static int olpc_absolute_mode(struct psmouse *psmouse, int mode) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - - /* Switch to 'Advanced mode.', four disables in a row. */ - if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE)) - return -1; - - return olpc_new_mode(psmouse, mode); -} - -/* - * olpc_poll() - poll the touchpad for current motion packet. - * Used in resync. - * Note: We can't poll, so always return failure. - */ -static int olpc_poll(struct psmouse *psmouse) -{ - return -1; -} - -static int olpc_reconnect(struct psmouse *psmouse) -{ - struct olpc_data *priv = psmouse->private; - int mode; - - if (olpc_rev_after(OLPC_REV_B2)) - if (psmouse->ps2dev.serio->dev.power.power_state.event != PM_EVENT_ON) - return 0; - - psmouse_reset(psmouse); - - if (!(priv->i = olpc_get_model(psmouse))) - return -1; - - mode = olpc_find_mode(psmouse); - if (mode < 0) - return -1; - - if (olpc_absolute_mode(psmouse, mode)) { - printk(KERN_ERR __FILE__ ": Failed to reenable absolute mode.\n"); - return -1; - } - - return 0; -} - -static void olpc_disconnect(struct psmouse *psmouse) -{ - struct olpc_data *priv = psmouse->private; - - psmouse_reset(psmouse); - input_unregister_device(priv->dev2); - kfree(priv); -} - -static void olpc_mode_switch(struct work_struct *w) -{ - struct delayed_work *work = container_of(w, struct delayed_work, work); - struct olpc_data *priv = container_of(work, struct olpc_data, mode_switch); - struct psmouse *psmouse = priv->psmouse; - struct ps2dev *ps2dev = &psmouse->ps2dev; - int pending_mode, ret; - - if (priv->pending_mode == priv->current_mode) { - priv->pending_mode = 0; - printk (KERN_DEBUG __FILE__ ": In switch_mode, no target mode.\n"); - return; - } - - if (tpdebug) - printk(KERN_WARNING __FILE__ ": Disable for switch to %d. [%lu]\n", priv->pending_mode, jiffies); - - /* XXX: This is a bit hacky, make sure this isn't screwing stuff up. */ - psmouse->state = PSMOUSE_INITIALIZING; - - ret = ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); - if (ret) { - /* XXX: if this ever fails, we need to do a full reset! */ - printk(KERN_WARNING __FILE__ ": Disable failed for switch to %d. (%d) [%lu]\n", priv->pending_mode, ret, jiffies); - return; - } - - /* - * ALPS tells us that it may take up to 20msec for the disable to - * take effect; however, ps2_command() will wait up to 200msec for - * the ACK to come back (and I'm assuming that by the time the - * hardware sends back its ACK, it has stopped sending bytes). - */ - pending_mode = priv->pending_mode; - - if (olpc_new_mode(psmouse, priv->pending_mode)) - goto bad; - - /* - * Deal with a potential race condition. - * - * If there is a brief tap of a stylus or a fingernail that - * triggers a mode switch to PT mode, and the stylus/fingernail is - * lifted after the DISABLE above, but before we reenable in the new mode, - * then we can get stuck in PT mode. - */ - if (pending_mode == OLPC_PT) { - priv->pending_mode = OLPC_GS; - queue_delayed_work(kpsmoused_wq, &priv->mode_switch, msecs_to_jiffies(50)); - } - - return; - -bad: - printk(KERN_WARNING __FILE__ ": Failure to switch modes, resetting device...\n"); - olpc_reconnect(psmouse); -} - -int olpc_init(struct psmouse *psmouse) -{ - struct olpc_data *priv; - struct input_dev *dev = psmouse->dev; - struct input_dev *dev2; - int mode; - - priv = kzalloc(sizeof(struct olpc_data), GFP_KERNEL); - dev2 = input_allocate_device(); - if (!priv || !dev2) - goto init_fail; - - psmouse->private = priv; - priv->dev2 = dev2; - priv->psmouse = psmouse; - - psmouse_reset(psmouse); - if (!(priv->i = olpc_get_model(psmouse))) - goto init_fail; - - mode = olpc_find_mode(psmouse); - if (mode < 0) { - printk(KERN_ERR __FILE__ ": Failed to identify proper mode\n"); - goto init_fail; - } - - if (olpc_absolute_mode(psmouse, mode)) { - printk(KERN_ERR __FILE__ ": Failed to enable absolute mode\n"); - goto init_fail; - } - - /* - * Unset some of the default bits for things we don't have. - */ - dev->evbit[LONG(EV_REL)] &= ~BIT(EV_REL); - dev->relbit[LONG(REL_X)] &= ~(BIT(REL_X) | BIT(REL_Y)); - dev->keybit[LONG(BTN_MIDDLE)] &= ~BIT(BTN_MIDDLE); - - dev->evbit[LONG(EV_KEY)] |= BIT(EV_KEY); - dev->keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH); - dev->keybit[LONG(BTN_TOOL_PEN)] |= BIT(BTN_TOOL_PEN); - dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT); - - dev->evbit[LONG(EV_ABS)] |= BIT(EV_ABS); - input_set_abs_params(dev, ABS_X, 2, 1000, 0, 0); - input_set_abs_params(dev, ABS_Y, 0, 717, 0, 0); - - snprintf(priv->phys, sizeof(priv->phys), - "%s/input1", psmouse->ps2dev.serio->phys); - dev2->phys = priv->phys; - dev2->name = "OLPC ALPS GlideSensor"; - dev2->id.bustype = BUS_I8042; - dev2->id.vendor = 0x0002; - dev2->id.product = PSMOUSE_OLPC; - dev2->id.version = 0x0000; - - dev2->evbit[LONG(EV_KEY)] |= BIT(EV_KEY); - dev2->keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH); - dev2->keybit[LONG(BTN_TOOL_FINGER)] |= BIT(BTN_TOOL_FINGER); - dev2->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT); - - dev2->evbit[LONG(EV_ABS)] |= BIT(EV_ABS); - input_set_abs_params(dev2, ABS_X, 350, 512, 0, 0); - input_set_abs_params(dev2, ABS_Y, 70, 325, 0, 0); - input_set_abs_params(dev2, ABS_PRESSURE, 0, 63, 0, 0); - - if (input_register_device(dev2)) { - printk(KERN_ERR __FILE__ ": Failed to register GlideSensor\n"); - goto init_fail; - } - - psmouse->protocol_handler = olpc_process_byte; - psmouse->poll = olpc_poll; - psmouse->disconnect = olpc_disconnect; - psmouse->reconnect = olpc_reconnect; - psmouse->pktsize = 6; - - /* Disable the idle resync. */ - psmouse->resync_time = 0; - /* Reset after a lot of bad bytes. */ - psmouse->resetafter = 1024; - - INIT_DELAYED_WORK(&priv->mode_switch, olpc_mode_switch); - - return 0; - -init_fail: - input_free_device(dev2); - kfree(priv); - return -1; -} - -int olpc_detect(struct psmouse *psmouse, int set_properties) -{ - if (!olpc_get_model(psmouse)) - return -1; - - if (set_properties) { - psmouse->vendor = "ALPS"; - psmouse->name = "PenTablet"; - psmouse->model = 0; - } - return 0; -} - diff --git a/target/linux/olpc/files/drivers/input/mouse/olpc.h b/target/linux/olpc/files/drivers/input/mouse/olpc.h deleted file mode 100644 index 426f8b4ea..000000000 --- a/target/linux/olpc/files/drivers/input/mouse/olpc.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * OLPC touchpad PS/2 mouse driver - * - * Copyright (c) 2006 One Laptop Per Child, inc. - * - * This driver is partly based on the ALPS driver. - * Copyright (c) 2003 Peter Osterlund <petero2@telia.com> - * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> - * - * 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. - */ - -#ifndef _OLPC_H -#define _OLPC_H - -struct olpc_model_info { - unsigned char signature[3]; - unsigned char flags; -}; - -struct olpc_data { - struct input_dev *dev2; /* Relative device */ - struct psmouse *psmouse; - char name[32]; /* Name */ - char phys[32]; /* Phys */ - struct olpc_model_info *i; /* Info */ - int pending_mode; - int current_mode; - s64 late; - struct delayed_work mode_switch; -}; - -#ifdef CONFIG_MOUSE_PS2_OLPC -int olpc_detect(struct psmouse *psmouse, int set_properties); -int olpc_init(struct psmouse *psmouse); -#else -inline int olpc_detect(struct psmouse *psmouse, int set_properties) -{ - return -ENOSYS; -} -inline int olpc_init(struct psmouse *psmouse) -{ - return -ENOSYS; -} -#endif - -#endif |