Merge master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6 into next
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Mon, 21 Jul 2008 04:55:14 +0000 (00:55 -0400)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Mon, 21 Jul 2008 04:55:14 +0000 (00:55 -0400)
100 files changed:
Documentation/input/gameport-programming.txt
Documentation/input/input.txt
Documentation/input/joystick-api.txt
Documentation/input/joystick-parport.txt
Documentation/input/joystick.txt
MAINTAINERS
drivers/char/keyboard.c
drivers/hwmon/hdaps.c
drivers/input/evbug.c
drivers/input/evdev.c
drivers/input/ff-memless.c
drivers/input/gameport/emu10k1-gp.c
drivers/input/gameport/gameport.c
drivers/input/gameport/lightning.c
drivers/input/gameport/ns558.c
drivers/input/input.c
drivers/input/joystick/a3d.c
drivers/input/joystick/amijoy.c
drivers/input/joystick/cobra.c
drivers/input/joystick/db9.c
drivers/input/joystick/gf2k.c
drivers/input/joystick/grip.c
drivers/input/joystick/grip_mp.c
drivers/input/joystick/guillemot.c
drivers/input/joystick/iforce/iforce-ff.c
drivers/input/joystick/iforce/iforce-main.c
drivers/input/joystick/iforce/iforce-packets.c
drivers/input/joystick/iforce/iforce-serio.c
drivers/input/joystick/iforce/iforce-usb.c
drivers/input/joystick/iforce/iforce.h
drivers/input/joystick/interact.c
drivers/input/joystick/joydump.c
drivers/input/joystick/magellan.c
drivers/input/joystick/spaceball.c
drivers/input/joystick/spaceorb.c
drivers/input/joystick/stinger.c
drivers/input/joystick/tmdc.c
drivers/input/joystick/turbografx.c
drivers/input/joystick/twidjoy.c
drivers/input/joystick/warrior.c
drivers/input/joystick/xpad.c
drivers/input/keyboard/amikbd.c
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/gpio_keys.c
drivers/input/keyboard/lkkbd.c
drivers/input/keyboard/pxa27x_keypad.c
drivers/input/keyboard/sunkbd.c
drivers/input/keyboard/xtkbd.c
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/ati_remote.c
drivers/input/misc/ati_remote2.c
drivers/input/misc/keyspan_remote.c
drivers/input/misc/powermate.c
drivers/input/misc/sgi_btns.c [new file with mode: 0644]
drivers/input/misc/wistron_btns.c
drivers/input/misc/yealink.c
drivers/input/mouse/appletouch.c
drivers/input/mouse/atarimouse.c
drivers/input/mouse/hil_ptr.c
drivers/input/mouse/inport.c
drivers/input/mouse/logibm.c
drivers/input/mouse/pc110pad.c
drivers/input/mouse/sermouse.c
drivers/input/serio/Kconfig
drivers/input/serio/Makefile
drivers/input/serio/ct82c710.c
drivers/input/serio/hil_mlc.c
drivers/input/serio/hp_sdc.c
drivers/input/serio/hp_sdc_mlc.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/libps2.c
drivers/input/serio/q40kbd.c
drivers/input/serio/rpckbd.c
drivers/input/serio/serio.c
drivers/input/serio/xilinx_ps2.c [new file with mode: 0644]
drivers/input/tablet/acecad.c
drivers/input/tablet/aiptek.c
drivers/input/tablet/gtco.c
drivers/input/tablet/kbtab.c
drivers/input/tablet/wacom.h
drivers/input/tablet/wacom_sys.c
drivers/input/tablet/wacom_wac.c
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/gunze.c
drivers/input/touchscreen/h3600_ts_input.c
drivers/input/touchscreen/htcpen.c [new file with mode: 0644]
drivers/input/touchscreen/inexio.c [new file with mode: 0644]
drivers/input/touchscreen/migor_ts.c [new file with mode: 0644]
drivers/input/touchscreen/touchit213.c [new file with mode: 0644]
drivers/input/touchscreen/usbtouchscreen.c
drivers/input/touchscreen/wm9712.c
drivers/macintosh/adbhid.c
include/linux/gameport.h
include/linux/gpio_keys.h
include/linux/input.h
include/linux/joystick.h
include/linux/libps2.h
include/linux/serio.h

index 14e0a8b..03a74fc 100644 (file)
@@ -1,5 +1,3 @@
-$Id: gameport-programming.txt,v 1.3 2001/04/24 13:51:37 vojtech Exp $
-
 Programming gameport drivers
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
index ff8cea0..686ee99 100644 (file)
@@ -1,7 +1,6 @@
                          Linux Input drivers v1.0
               (c) 1999-2001 Vojtech Pavlik <vojtech@ucw.cz>
                             Sponsored by SuSE
-           $Id: input.txt,v 1.8 2002/05/29 03:15:01 bradleym Exp $
 ----------------------------------------------------------------------------
 
 0. Disclaimer
index acbd32b..c507330 100644 (file)
@@ -5,8 +5,6 @@
 
                              7 Aug 1998
 
-       $Id: joystick-api.txt,v 1.2 2001/05/08 21:21:23 vojtech Exp $
-
 1. Initialization
 ~~~~~~~~~~~~~~~~~
 
index ede5f33..1c856f3 100644 (file)
@@ -2,7 +2,6 @@
               (c) 1998-2000 Vojtech Pavlik <vojtech@ucw.cz>
               (c) 1998 Andree Borrmann <a.borrmann@tu-bs.de>
                             Sponsored by SuSE
-       $Id: joystick-parport.txt,v 1.6 2001/09/25 09:31:32 vojtech Exp $
 ----------------------------------------------------------------------------
 
 0. Disclaimer
index 389de9b..154d767 100644 (file)
@@ -1,7 +1,6 @@
                       Linux Joystick driver v2.0.0
               (c) 1996-2000 Vojtech Pavlik <vojtech@ucw.cz>
                             Sponsored by SuSE
-          $Id: joystick.txt,v 1.12 2002/03/03 12:13:07 jdeneux Exp $
 ----------------------------------------------------------------------------
 
 0. Disclaimer
index ec0c9c9..df3fa0e 100644 (file)
@@ -1988,6 +1988,12 @@ M:       mikulas@artax.karlin.mff.cuni.cz
 W:     http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
 S:     Maintained
 
+HTCPEN TOUCHSCREEN DRIVER
+P:     Pau Oliva Fora
+M:     pof@eslack.org
+L:     linux-input@vger.kernel.org
+S:     Maintained
+
 HUGETLB FILESYSTEM
 P:     William Irwin
 M:     wli@holomorphy.com
index d9a0a53..7b3a212 100644 (file)
@@ -46,6 +46,8 @@
 
 extern void ctrl_alt_del(void);
 
+#define to_handle_h(n) container_of(n, struct input_handle, h_node)
+
 /*
  * Exported functions/variables
  */
index 50f2269..a4d92d2 100644 (file)
@@ -581,6 +581,8 @@ static int __init hdaps_init(void)
        /* initialize the input class */
        idev = hdaps_idev->input;
        idev->name = "hdaps";
+       idev->phys = "isa1600/input0";
+       idev->id.bustype = BUS_ISA;
        idev->dev.parent = &pdev->dev;
        idev->evbit[0] = BIT_MASK(EV_ABS);
        input_set_abs_params(idev, ABS_X,
index c21f2f1..0353601 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: evbug.c,v 1.10 2001/09/25 10:12:07 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
@@ -41,7 +39,7 @@ MODULE_LICENSE("GPL");
 static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
 {
        printk(KERN_DEBUG "evbug.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n",
-               handle->dev->phys, type, code, value);
+               handle->dev->dev.bus_id, type, code, value);
 }
 
 static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
@@ -66,7 +64,10 @@ static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
        if (error)
                goto err_unregister_handle;
 
-       printk(KERN_DEBUG "evbug.c: Connected device: \"%s\", %s\n", dev->name, dev->phys);
+       printk(KERN_DEBUG "evbug.c: Connected device: %s (%s at %s)\n",
+               dev->dev.bus_id,
+               dev->name ?: "unknown",
+               dev->phys ?: "unknown");
 
        return 0;
 
@@ -79,7 +80,8 @@ static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
 
 static void evbug_disconnect(struct input_handle *handle)
 {
-       printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n", handle->dev->phys);
+       printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n",
+               handle->dev->dev.bus_id);
 
        input_close_device(handle);
        input_unregister_handle(handle);
index b32984b..2d65411 100644 (file)
@@ -300,6 +300,35 @@ struct input_event_compat {
        __s32 value;
 };
 
+struct ff_periodic_effect_compat {
+       __u16 waveform;
+       __u16 period;
+       __s16 magnitude;
+       __s16 offset;
+       __u16 phase;
+
+       struct ff_envelope envelope;
+
+       __u32 custom_len;
+       compat_uptr_t custom_data;
+};
+
+struct ff_effect_compat {
+       __u16 type;
+       __s16 id;
+       __u16 direction;
+       struct ff_trigger trigger;
+       struct ff_replay replay;
+
+       union {
+               struct ff_constant_effect constant;
+               struct ff_ramp_effect ramp;
+               struct ff_periodic_effect_compat periodic;
+               struct ff_condition_effect condition[2]; /* One for each axis */
+               struct ff_rumble_effect rumble;
+       } u;
+};
+
 /* Note to the author of this code: did it ever occur to
    you why the ifdefs are needed? Think about it again. -AK */
 #ifdef CONFIG_X86_64
@@ -368,6 +397,42 @@ static int evdev_event_to_user(char __user *buffer,
        return 0;
 }
 
+static int evdev_ff_effect_from_user(const char __user *buffer, size_t size,
+                                    struct ff_effect *effect)
+{
+       if (COMPAT_TEST) {
+               struct ff_effect_compat *compat_effect;
+
+               if (size != sizeof(struct ff_effect_compat))
+                       return -EINVAL;
+
+               /*
+                * It so happens that the pointer which needs to be changed
+                * is the last field in the structure, so we can copy the
+                * whole thing and replace just the pointer.
+                */
+
+               compat_effect = (struct ff_effect_compat *)effect;
+
+               if (copy_from_user(compat_effect, buffer,
+                                  sizeof(struct ff_effect_compat)))
+                       return -EFAULT;
+
+               if (compat_effect->type == FF_PERIODIC &&
+                   compat_effect->u.periodic.waveform == FF_CUSTOM)
+                       effect->u.periodic.custom_data =
+                               compat_ptr(compat_effect->u.periodic.custom_data);
+       } else {
+               if (size != sizeof(struct ff_effect))
+                       return -EINVAL;
+
+               if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
+                       return -EFAULT;
+       }
+
+       return 0;
+}
+
 #else
 
 static inline size_t evdev_event_size(void)
@@ -393,6 +458,18 @@ static int evdev_event_to_user(char __user *buffer,
        return 0;
 }
 
+static int evdev_ff_effect_from_user(const char __user *buffer, size_t size,
+                                    struct ff_effect *effect)
+{
+       if (size != sizeof(struct ff_effect))
+               return -EINVAL;
+
+       if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
+               return -EFAULT;
+
+       return 0;
+}
+
 #endif /* CONFIG_COMPAT */
 
 static ssize_t evdev_write(struct file *file, const char __user *buffer,
@@ -633,17 +710,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
 
                return input_set_keycode(dev, t, v);
 
-       case EVIOCSFF:
-               if (copy_from_user(&effect, p, sizeof(effect)))
-                       return -EFAULT;
-
-               error = input_ff_upload(dev, &effect, file);
-
-               if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
-                       return -EFAULT;
-
-               return error;
-
        case EVIOCRMFF:
                return input_ff_erase(dev, (int)(unsigned long) p, file);
 
@@ -733,6 +799,19 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
 
                if (_IOC_DIR(cmd) == _IOC_WRITE) {
 
+                       if (_IOC_NR(cmd) == _IOC_NR(EVIOCSFF)) {
+
+                               if (evdev_ff_effect_from_user(p, _IOC_SIZE(cmd), &effect))
+                                       return -EFAULT;
+
+                               error = input_ff_upload(dev, &effect, file);
+
+                               if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
+                                       return -EFAULT;
+
+                               return error;
+                       }
+
                        if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
 
                                t = _IOC_NR(cmd) & ABS_MAX;
index d226d93..6790e97 100644 (file)
@@ -247,9 +247,9 @@ static void ml_combine_effects(struct ff_effect *effect,
                 * in s8, this should be changed to something more generic
                 */
                effect->u.ramp.start_level =
-                       max(min(effect->u.ramp.start_level + x, 0x7f), -0x80);
+                       clamp_val(effect->u.ramp.start_level + x, -0x80, 0x7f);
                effect->u.ramp.end_level =
-                       max(min(effect->u.ramp.end_level + y, 0x7f), -0x80);
+                       clamp_val(effect->u.ramp.end_level + y, -0x80, 0x7f);
                break;
 
        case FF_RUMBLE:
index 9793ac3..b04930f 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: emu10k1-gp.c,v 1.8 2002/01/22 20:40:46 vojtech Exp $
- *
  *  Copyright (c) 2001 Vojtech Pavlik
  */
 
index c5600ac..078e4ee 100644 (file)
@@ -36,7 +36,6 @@ EXPORT_SYMBOL(__gameport_register_driver);
 EXPORT_SYMBOL(gameport_unregister_driver);
 EXPORT_SYMBOL(gameport_open);
 EXPORT_SYMBOL(gameport_close);
-EXPORT_SYMBOL(gameport_rescan);
 EXPORT_SYMBOL(gameport_set_phys);
 EXPORT_SYMBOL(gameport_start_polling);
 EXPORT_SYMBOL(gameport_stop_polling);
@@ -230,8 +229,6 @@ static void gameport_find_driver(struct gameport *gameport)
  */
 
 enum gameport_event_type {
-       GAMEPORT_RESCAN,
-       GAMEPORT_RECONNECT,
        GAMEPORT_REGISTER_PORT,
        GAMEPORT_REGISTER_DRIVER,
 };
@@ -365,15 +362,6 @@ static void gameport_handle_event(void)
                                gameport_add_port(event->object);
                                break;
 
-                       case GAMEPORT_RECONNECT:
-                               gameport_reconnect_port(event->object);
-                               break;
-
-                       case GAMEPORT_RESCAN:
-                               gameport_disconnect_port(event->object);
-                               gameport_find_driver(event->object);
-                               break;
-
                        case GAMEPORT_REGISTER_DRIVER:
                                gameport_add_driver(event->object);
                                break;
@@ -651,16 +639,6 @@ static void gameport_disconnect_port(struct gameport *gameport)
        device_release_driver(&gameport->dev);
 }
 
-void gameport_rescan(struct gameport *gameport)
-{
-       gameport_queue_event(gameport, NULL, GAMEPORT_RESCAN);
-}
-
-void gameport_reconnect(struct gameport *gameport)
-{
-       gameport_queue_event(gameport, NULL, GAMEPORT_RECONNECT);
-}
-
 /*
  * Submits register request to kgameportd for subsequent execution.
  * Note that port registration is always asynchronous.
index 6b4d456..06ad36e 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: lightning.c,v 1.20 2002/01/22 20:41:31 vojtech Exp $
- *
  *  Copyright (c) 1998-2001 Vojtech Pavlik
  */
 
index 7b7a546..2b282cd 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: ns558.c,v 1.43 2002/01/24 19:23:21 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  *  Copyright (c) 1999 Brian Gerst
  */
index 408df0b..c13ced3 100644 (file)
@@ -242,7 +242,7 @@ static void input_handle_event(struct input_dev *dev,
                break;
        }
 
-       if (type != EV_SYN)
+       if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
                dev->sync = 0;
 
        if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
index 52ba16f..92498d4 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: a3d.c,v 1.21 2002/01/22 20:11:50 vojtech Exp $
- *
  *  Copyright (c) 1998-2001 Vojtech Pavlik
  */
 
index deb9f82..05022f0 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: amijoy.c,v 1.13 2002/01/22 20:26:32 vojtech Exp $
- *
  *  Copyright (c) 1998-2001 Vojtech Pavlik
  */
 
index 55646a6..639b975 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: cobra.c,v 1.19 2002/01/22 20:26:52 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
index 960e501..5239594 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: db9.c,v 1.13 2002/04/07 20:13:37 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
  *  Based on the work of:
index 1f6302c..cb6eef1 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: gf2k.c,v 1.19 2002/01/22 20:27:43 vojtech Exp $
- *
  *  Copyright (c) 1998-2001 Vojtech Pavlik
  */
 
index fd3853a..684e07c 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: grip.c,v 1.21 2002/01/22 20:27:57 vojtech Exp $
- *
  *  Copyright (c) 1998-2001 Vojtech Pavlik
  */
 
index c57e21d..8279481 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: grip_mp.c,v 1.9 2002/07/20 19:28:45 bonnland Exp $
- *
  *  Driver for the Gravis Grip Multiport, a gamepad "hub" that
  *  connects up to four 9-pin digital gamepads/joysticks.
  *  Driver tested on SMP and UP kernel versions 2.4.18-4 and 2.4.18-5.
index aa6bfb3..25ec3fa 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: guillemot.c,v 1.10 2002/01/22 20:28:12 vojtech Exp $
- *
  *  Copyright (c) 2001 Vojtech Pavlik
  */
 
index f2a4381..7839b7b 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: iforce-ff.c,v 1.9 2002/02/02 19:28:35 jdeneux Exp $
- *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
  *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
index a2517fa..61ee6e3 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: iforce-main.c,v 1.19 2002/07/07 10:22:50 jdeneux Exp $
- *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
  *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
index 45c4939..015b50a 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: iforce-packets.c,v 1.16 2002/07/07 10:22:50 jdeneux Exp $
- *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
  *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
index 7b4bc19..46d5041 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: iforce-serio.c,v 1.4 2002/01/28 22:45:00 jdeneux Exp $
- *
  *  Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz>
  *  Copyright (c) 2001, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
index 7fb3cf8..851cc40 100644 (file)
@@ -1,6 +1,4 @@
  /*
- * $Id: iforce-usb.c,v 1.16 2002/06/09 11:08:04 jdeneux Exp $
- *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
  *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
@@ -89,10 +87,10 @@ static void iforce_usb_irq(struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d",
-                   __FUNCTION__, urb->status);
+                   __func__, urb->status);
                return;
        default:
-               dbg("%s - urb has status of: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb has status of: %d", __func__, urb->status);
                goto exit;
        }
 
@@ -103,7 +101,7 @@ exit:
        status = usb_submit_urb (urb, GFP_ATOMIC);
        if (status)
                err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, status);
+                    __func__, status);
 }
 
 static void iforce_usb_out(struct urb *urb)
index a964a7c..f2d91f4 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: iforce.h,v 1.13 2002/07/07 10:22:50 jdeneux Exp $
- *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
  *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
index bc8ea95..8c3290b 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: interact.c,v 1.16 2002/01/22 20:28:25 vojtech Exp $
- *
  *  Copyright (c) 2001 Vojtech Pavlik
  *
  *  Based on the work of:
index 88ec5a9..2a1b82c 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: joydump.c,v 1.1 2002/01/23 06:56:16 jsimmons Exp $
- *
  *  Copyright (c) 1996-2001 Vojtech Pavlik
  */
 
index 54e6769..40e4078 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: magellan.c,v 1.16 2002/01/22 20:28:39 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
index d4087fd..0cd9b29 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: spaceball.c,v 1.17 2002/01/22 20:29:03 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
  *  Based on the work of:
index f7ce400..a694bf8 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: spaceorb.c,v 1.15 2002/01/22 20:29:19 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
  *  Based on the work of:
index baa10b2..e0db9f5 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: stinger.c,v 1.10 2002/01/22 20:29:31 vojtech Exp $
- *
  *  Copyright (c) 2000-2001 Vojtech Pavlik
  *  Copyright (c) 2000 Mark Fletcher
  */
index 0feeb8a..60c37bc 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: tmdc.c,v 1.31 2002/01/22 20:29:52 vojtech Exp $
- *
  *  Copyright (c) 1998-2001 Vojtech Pavlik
  *
  *   Based on the work of:
index 989483f..b6f8598 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: turbografx.c,v 1.14 2002/01/22 20:30:39 vojtech Exp $
- *
  *  Copyright (c) 1998-2001 Vojtech Pavlik
  *
  *  Based on the work of:
index 1085c84..3f4ec73 100644 (file)
@@ -1,8 +1,4 @@
 /*
- * $Id: twidjoy.c,v 1.5 2002/01/22 20:31:53 vojtech Exp $
- *
- *  derived from CVS-ID "stinger.c,v 1.5 2001/05/29 12:57:18 vojtech Exp"
- *
  *  Copyright (c) 2001 Arndt Schoenewald
  *  Copyright (c) 2000-2001 Vojtech Pavlik
  *  Copyright (c) 2000 Mark Fletcher
index e928b6e..f72c83e 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: warrior.c,v 1.14 2002/01/22 20:32:10 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
index b29e3af..87d3e7e 100644 (file)
@@ -418,11 +418,11 @@ static void xpad_irq_in(struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d",
-                       __FUNCTION__, status);
+                       __func__, status);
                return;
        default:
                dbg("%s - nonzero urb status received: %d",
-                       __FUNCTION__, status);
+                       __func__, status);
                goto exit;
        }
 
@@ -441,7 +441,7 @@ exit:
        retval = usb_submit_urb (urb, GFP_ATOMIC);
        if (retval)
                err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, retval);
+                    __func__, retval);
 }
 
 static void xpad_bulk_out(struct urb *urb)
@@ -477,11 +477,11 @@ static void xpad_irq_out(struct urb *urb)
                case -ESHUTDOWN:
                        /* this urb is terminated, clean up */
                        dbg("%s - urb shutting down with status: %d",
-                               __FUNCTION__, status);
+                               __func__, status);
                        return;
                default:
                        dbg("%s - nonzero urb status received: %d",
-                               __FUNCTION__, status);
+                               __func__, status);
                        goto exit;
        }
 
@@ -489,7 +489,7 @@ exit:
        retval = usb_submit_urb(urb, GFP_ATOMIC);
        if (retval)
                err("%s - usb_submit_urb failed with result %d",
-                   __FUNCTION__, retval);
+                   __func__, retval);
 }
 
 static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
index 81bf756..35149ec 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: amikbd.c,v 1.13 2002/02/01 16:02:24 vojtech Exp $
- *
  *  Copyright (c) 2000-2001 Vojtech Pavlik
  *
  *  Based on the work of:
index af58a6f..b1ce10f 100644 (file)
@@ -68,7 +68,7 @@ MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and
  * are loadable via an userland utility.
  */
 
-static unsigned char atkbd_set2_keycode[512] = {
+static const unsigned short atkbd_set2_keycode[512] = {
 
 #ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES
 
@@ -99,7 +99,7 @@ static unsigned char atkbd_set2_keycode[512] = {
 #endif
 };
 
-static unsigned char atkbd_set3_keycode[512] = {
+static const unsigned short atkbd_set3_keycode[512] = {
 
          0,  0,  0,  0,  0,  0,  0, 59,  1,138,128,129,130, 15, 41, 60,
        131, 29, 42, 86, 58, 16,  2, 61,133, 56, 44, 31, 30, 17,  3, 62,
@@ -115,7 +115,7 @@ static unsigned char atkbd_set3_keycode[512] = {
        148,149,147,140
 };
 
-static unsigned char atkbd_unxlate_table[128] = {
+static const unsigned short atkbd_unxlate_table[128] = {
           0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
          21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
          35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
@@ -161,7 +161,7 @@ static unsigned char atkbd_unxlate_table[128] = {
 #define ATKBD_SCR_LEFT         249
 #define ATKBD_SCR_RIGHT                248
 
-#define ATKBD_SPECIAL          248
+#define ATKBD_SPECIAL          ATKBD_SCR_RIGHT
 
 #define ATKBD_LED_EVENT_BIT    0
 #define ATKBD_REP_EVENT_BIT    1
@@ -173,7 +173,7 @@ static unsigned char atkbd_unxlate_table[128] = {
 #define ATKBD_XL_HANGEUL       0x10
 #define ATKBD_XL_HANJA         0x20
 
-static struct {
+static const struct {
        unsigned char keycode;
        unsigned char set2;
 } atkbd_scroll_keys[] = {
@@ -200,7 +200,7 @@ struct atkbd {
        char phys[32];
 
        unsigned short id;
-       unsigned char keycode[512];
+       unsigned short keycode[512];
        DECLARE_BITMAP(force_release_mask, 512);
        unsigned char set;
        unsigned char translated;
@@ -357,7 +357,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
        unsigned int code = data;
        int scroll = 0, hscroll = 0, click = -1;
        int value;
-       unsigned char keycode;
+       unsigned short keycode;
 
 #ifdef ATKBD_DEBUG
        printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags);
@@ -850,6 +850,23 @@ static void atkbd_latitude_keymap_fixup(struct atkbd *atkbd)
                                  atkbd->force_release_mask);
 }
 
+/*
+ * Perform fixup for HP system that doesn't generate release
+ * for its video switch
+ */
+static void atkbd_hp_keymap_fixup(struct atkbd *atkbd)
+{
+       const unsigned int forced_release_keys[] = {
+               0x94,
+       };
+       int i;
+
+       if (atkbd->set == 2)
+               for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++)
+                       __set_bit(forced_release_keys[i],
+                                       atkbd->force_release_mask);
+}
+
 /*
  * atkbd_set_keycode_table() initializes keyboard's keycode table
  * according to the selected scancode set
@@ -961,16 +978,16 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd)
                input_dev->evbit[0] |= BIT_MASK(EV_REL);
                input_dev->relbit[0] = BIT_MASK(REL_WHEEL) |
                        BIT_MASK(REL_HWHEEL);
-               set_bit(BTN_MIDDLE, input_dev->keybit);
+               __set_bit(BTN_MIDDLE, input_dev->keybit);
        }
 
        input_dev->keycode = atkbd->keycode;
-       input_dev->keycodesize = sizeof(unsigned char);
+       input_dev->keycodesize = sizeof(unsigned short);
        input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
 
        for (i = 0; i < 512; i++)
                if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL)
-                       set_bit(atkbd->keycode[i], input_dev->keybit);
+                       __set_bit(atkbd->keycode[i], input_dev->keybit);
 }
 
 /*
@@ -1452,6 +1469,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
                .callback = atkbd_setup_fixup,
                .driver_data = atkbd_latitude_keymap_fixup,
        },
+       {
+               .ident = "HP 2133",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP 2133"),
+               },
+               .callback = atkbd_setup_fixup,
+               .driver_data = atkbd_hp_keymap_fixup,
+       },
        { }
 };
 
index bbd00c3..be58730 100644 (file)
 
 #include <asm/gpio.h>
 
+struct gpio_button_data {
+       struct gpio_keys_button *button;
+       struct input_dev *input;
+       struct timer_list timer;
+};
+
+struct gpio_keys_drvdata {
+       struct input_dev *input;
+       struct gpio_button_data data[0];
+};
+
+static void gpio_keys_report_event(struct gpio_keys_button *button,
+                                  struct input_dev *input)
+{
+       unsigned int type = button->type ?: EV_KEY;
+       int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;
+
+       input_event(input, type, button->code, !!state);
+       input_sync(input);
+}
+
+static void gpio_check_button(unsigned long _data)
+{
+       struct gpio_button_data *data = (struct gpio_button_data *)_data;
+
+       gpio_keys_report_event(data->button, data->input);
+}
+
 static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
 {
-       int i;
        struct platform_device *pdev = dev_id;
        struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
-       struct input_dev *input = platform_get_drvdata(pdev);
+       struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
+       int i;
 
        for (i = 0; i < pdata->nbuttons; i++) {
                struct gpio_keys_button *button = &pdata->buttons[i];
-               int gpio = button->gpio;
 
-               if (irq == gpio_to_irq(gpio)) {
-                       unsigned int type = button->type ?: EV_KEY;
-                       int state = (gpio_get_value(gpio) ? 1 : 0) ^ button->active_low;
+               if (irq == gpio_to_irq(button->gpio)) {
+                       struct gpio_button_data *bdata = &ddata->data[i];
+
+                       if (button->debounce_interval)
+                               mod_timer(&bdata->timer,
+                                         jiffies +
+                                         msecs_to_jiffies(button->debounce_interval));
+                       else
+                               gpio_keys_report_event(button, bdata->input);
 
-                       input_event(input, type, button->code, !!state);
-                       input_sync(input);
                        return IRQ_HANDLED;
                }
        }
@@ -53,17 +84,21 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
 static int __devinit gpio_keys_probe(struct platform_device *pdev)
 {
        struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+       struct gpio_keys_drvdata *ddata;
        struct input_dev *input;
        int i, error;
        int wakeup = 0;
 
+       ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
+                       pdata->nbuttons * sizeof(struct gpio_button_data),
+                       GFP_KERNEL);
        input = input_allocate_device();
-       if (!input)
-               return -ENOMEM;
-
-       platform_set_drvdata(pdev, input);
+       if (!ddata || !input) {
+               error = -ENOMEM;
+               goto fail1;
+       }
 
-       input->evbit[0] = BIT_MASK(EV_KEY);
+       platform_set_drvdata(pdev, ddata);
 
        input->name = pdev->name;
        input->phys = "gpio-keys/input0";
@@ -74,16 +109,23 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
        input->id.product = 0x0001;
        input->id.version = 0x0100;
 
+       ddata->input = input;
+
        for (i = 0; i < pdata->nbuttons; i++) {
                struct gpio_keys_button *button = &pdata->buttons[i];
+               struct gpio_button_data *bdata = &ddata->data[i];
                int irq;
                unsigned int type = button->type ?: EV_KEY;
 
+               bdata->input = input;
+               setup_timer(&bdata->timer,
+                           gpio_check_button, (unsigned long)bdata);
+
                error = gpio_request(button->gpio, button->desc ?: "gpio_keys");
                if (error < 0) {
                        pr_err("gpio-keys: failed to request GPIO %d,"
                                " error %d\n", button->gpio, error);
-                       goto fail;
+                       goto fail2;
                }
 
                error = gpio_direction_input(button->gpio);
@@ -92,7 +134,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
                                " direction for GPIO %d, error %d\n",
                                button->gpio, error);
                        gpio_free(button->gpio);
-                       goto fail;
+                       goto fail2;
                }
 
                irq = gpio_to_irq(button->gpio);
@@ -102,7 +144,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
                                " for GPIO %d, error %d\n",
                                button->gpio, error);
                        gpio_free(button->gpio);
-                       goto fail;
+                       goto fail2;
                }
 
                error = request_irq(irq, gpio_keys_isr,
@@ -114,7 +156,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
                        pr_err("gpio-keys: Unable to claim irq %d; error %d\n",
                                irq, error);
                        gpio_free(button->gpio);
-                       goto fail;
+                       goto fail2;
                }
 
                if (button->wakeup)
@@ -127,21 +169,25 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
        if (error) {
                pr_err("gpio-keys: Unable to register input device, "
                        "error: %d\n", error);
-               goto fail;
+               goto fail2;
        }
 
        device_init_wakeup(&pdev->dev, wakeup);
 
        return 0;
 
- fail:
+ fail2:
        while (--i >= 0) {
                free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev);
+               if (pdata->buttons[i].debounce_interval)
+                       del_timer_sync(&ddata->data[i].timer);
                gpio_free(pdata->buttons[i].gpio);
        }
 
        platform_set_drvdata(pdev, NULL);
+ fail1:
        input_free_device(input);
+       kfree(ddata);
 
        return error;
 }
@@ -149,7 +195,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
 static int __devexit gpio_keys_remove(struct platform_device *pdev)
 {
        struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
-       struct input_dev *input = platform_get_drvdata(pdev);
+       struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
+       struct input_dev *input = ddata->input;
        int i;
 
        device_init_wakeup(&pdev->dev, 0);
@@ -157,6 +204,8 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
        for (i = 0; i < pdata->nbuttons; i++) {
                int irq = gpio_to_irq(pdata->buttons[i].gpio);
                free_irq(irq, pdev);
+               if (pdata->buttons[i].debounce_interval)
+                       del_timer_sync(&ddata->data[i].timer);
                gpio_free(pdata->buttons[i].gpio);
        }
 
index 32e2c26..4730ef3 100644 (file)
@@ -538,11 +538,11 @@ lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code,
                        switch (code) {
                                case SND_CLICK:
                                        if (value == 0) {
-                                               DBG ("%s: Deactivating key clicks\n", __FUNCTION__);
+                                               DBG ("%s: Deactivating key clicks\n", __func__);
                                                lk->serio->write (lk->serio, LK_CMD_DISABLE_KEYCLICK);
                                                lk->serio->write (lk->serio, LK_CMD_DISABLE_CTRCLICK);
                                        } else {
-                                               DBG ("%s: Activating key clicks\n", __FUNCTION__);
+                                               DBG ("%s: Activating key clicks\n", __func__);
                                                lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK);
                                                lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume));
                                                lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK);
@@ -560,7 +560,7 @@ lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code,
 
                default:
                        printk (KERN_ERR "%s (): Got unknown type %d, code %d, value %d\n",
-                                       __FUNCTION__, type, code, value);
+                                       __func__, type, code, value);
        }
 
        return -1;
index 45767e7..6f1516f 100644 (file)
@@ -105,6 +105,8 @@ struct pxa27x_keypad {
        struct input_dev *input_dev;
        void __iomem *mmio_base;
 
+       int irq;
+
        /* matrix key code map */
        unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM];
 
@@ -392,6 +394,10 @@ static int pxa27x_keypad_suspend(struct platform_device *pdev, pm_message_t stat
        struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
 
        clk_disable(keypad->clk);
+
+       if (device_may_wakeup(&pdev->dev))
+               enable_irq_wake(keypad->irq);
+
        return 0;
 }
 
@@ -400,6 +406,9 @@ static int pxa27x_keypad_resume(struct platform_device *pdev)
        struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
        struct input_dev *input_dev = keypad->input_dev;
 
+       if (device_may_wakeup(&pdev->dev))
+               disable_irq_wake(keypad->irq);
+
        mutex_lock(&input_dev->mutex);
 
        if (input_dev->users) {
@@ -509,6 +518,8 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev)
                goto failed_free_dev;
        }
 
+       keypad->irq = irq;
+
        /* Register the input device */
        error = input_register_device(input_dev);
        if (error) {
@@ -516,6 +527,8 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev)
                goto failed_free_irq;
        }
 
+       device_init_wakeup(&pdev->dev, 1);
+
        return 0;
 
 failed_free_irq:
@@ -539,7 +552,7 @@ static int __devexit pxa27x_keypad_remove(struct platform_device *pdev)
        struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
        struct resource *res;
 
-       free_irq(platform_get_irq(pdev, 0), pdev);
+       free_irq(keypad->irq, pdev);
 
        clk_disable(keypad->clk);
        clk_put(keypad->clk);
index be0f5d1..9fce6d1 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: sunkbd.c,v 1.14 2001/09/25 10:12:07 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
index 152a2c0..37b01d7 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: xtkbd.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
index 432699d..e99b788 100644 (file)
@@ -189,6 +189,16 @@ config INPUT_UINPUT
          To compile this driver as a module, choose M here: the
          module will be called uinput.
 
+config INPUT_SGI_BTNS
+       tristate "SGI Indy/O2 volume button interface"
+       depends on SGI_IP22 || SGI_IP32
+       select INPUT_POLLDEV
+       help
+         Say Y here if you want to support SGI Indy/O2 volume button interface.
+
+         To compile this driver as a module, choose M here: the
+         module will be called sgi_btns.
+
 config HP_SDC_RTC
        tristate "HP SDC Real Time Clock"
        depends on GSC || HP300
index ebd39f2..f48009b 100644 (file)
@@ -19,3 +19,4 @@ obj-$(CONFIG_INPUT_YEALINK)           += yealink.o
 obj-$(CONFIG_HP_SDC_RTC)               += hp_sdc_rtc.o
 obj-$(CONFIG_INPUT_UINPUT)             += uinput.o
 obj-$(CONFIG_INPUT_APANEL)             += apanel.o
+obj-$(CONFIG_INPUT_SGI_BTNS)           += sgi_btns.o
index f3b86c2..debfc1a 100644 (file)
@@ -330,7 +330,7 @@ static int ati_remote_open(struct input_dev *inputdev)
        ati_remote->irq_urb->dev = ati_remote->udev;
        if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) {
                dev_err(&ati_remote->interface->dev,
-                       "%s: usb_submit_urb failed!\n", __FUNCTION__);
+                       "%s: usb_submit_urb failed!\n", __func__);
                return -EIO;
        }
 
@@ -356,7 +356,7 @@ static void ati_remote_irq_out(struct urb *urb)
 
        if (urb->status) {
                dev_dbg(&ati_remote->interface->dev, "%s: status %d\n",
-                       __FUNCTION__, urb->status);
+                       __func__, urb->status);
                return;
        }
 
@@ -601,17 +601,17 @@ static void ati_remote_irq_in(struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n",
-                       __FUNCTION__);
+                       __func__);
                return;
        default:                /* error */
                dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n",
-                       __FUNCTION__, urb->status);
+                       __func__, urb->status);
        }
 
        retval = usb_submit_urb(urb, GFP_ATOMIC);
        if (retval)
                dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n",
-                       __FUNCTION__, retval);
+                       __func__, retval);
 }
 
 /*
@@ -734,7 +734,7 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de
        int err = -ENOMEM;
 
        if (iface_host->desc.bNumEndpoints != 2) {
-               err("%s: Unexpected desc.bNumEndpoints\n", __FUNCTION__);
+               err("%s: Unexpected desc.bNumEndpoints\n", __func__);
                return -ENODEV;
        }
 
@@ -742,11 +742,11 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de
        endpoint_out = &iface_host->endpoint[1].desc;
 
        if (!usb_endpoint_is_int_in(endpoint_in)) {
-               err("%s: Unexpected endpoint_in\n", __FUNCTION__);
+               err("%s: Unexpected endpoint_in\n", __func__);
                return -ENODEV;
        }
        if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) {
-               err("%s: endpoint_in message size==0? \n", __FUNCTION__);
+               err("%s: endpoint_in message size==0? \n", __func__);
                return -ENODEV;
        }
 
@@ -814,7 +814,7 @@ static void ati_remote_disconnect(struct usb_interface *interface)
        ati_remote = usb_get_intfdata(interface);
        usb_set_intfdata(interface, NULL);
        if (!ati_remote) {
-               warn("%s - null device?\n", __FUNCTION__);
+               warn("%s - null device?\n", __func__);
                return;
        }
 
index f2709b8..a7fabaf 100644 (file)
@@ -137,14 +137,14 @@ static int ati_remote2_open(struct input_dev *idev)
        r = usb_submit_urb(ar2->urb[0], GFP_KERNEL);
        if (r) {
                dev_err(&ar2->intf[0]->dev,
-                       "%s: usb_submit_urb() = %d\n", __FUNCTION__, r);
+                       "%s: usb_submit_urb() = %d\n", __func__, r);
                return r;
        }
        r = usb_submit_urb(ar2->urb[1], GFP_KERNEL);
        if (r) {
                usb_kill_urb(ar2->urb[0]);
                dev_err(&ar2->intf[1]->dev,
-                       "%s: usb_submit_urb() = %d\n", __FUNCTION__, r);
+                       "%s: usb_submit_urb() = %d\n", __func__, r);
                return r;
        }
 
@@ -294,17 +294,17 @@ static void ati_remote2_complete_mouse(struct urb *urb)
        case -ECONNRESET:
        case -ESHUTDOWN:
                dev_dbg(&ar2->intf[0]->dev,
-                       "%s(): urb status = %d\n", __FUNCTION__, urb->status);
+                       "%s(): urb status = %d\n", __func__, urb->status);
                return;
        default:
                dev_err(&ar2->intf[0]->dev,
-                       "%s(): urb status = %d\n", __FUNCTION__, urb->status);
+                       "%s(): urb status = %d\n", __func__, urb->status);
        }
 
        r = usb_submit_urb(urb, GFP_ATOMIC);
        if (r)
                dev_err(&ar2->intf[0]->dev,
-                       "%s(): usb_submit_urb() = %d\n", __FUNCTION__, r);
+                       "%s(): usb_submit_urb() = %d\n", __func__, r);
 }
 
 static void ati_remote2_complete_key(struct urb *urb)
@@ -321,17 +321,17 @@ static void ati_remote2_complete_key(struct urb *urb)
        case -ECONNRESET:
        case -ESHUTDOWN:
                dev_dbg(&ar2->intf[1]->dev,
-                       "%s(): urb status = %d\n", __FUNCTION__, urb->status);
+                       "%s(): urb status = %d\n", __func__, urb->status);
                return;
        default:
                dev_err(&ar2->intf[1]->dev,
-                       "%s(): urb status = %d\n", __FUNCTION__, urb->status);
+                       "%s(): urb status = %d\n", __func__, urb->status);
        }
 
        r = usb_submit_urb(urb, GFP_ATOMIC);
        if (r)
                dev_err(&ar2->intf[1]->dev,
-                       "%s(): usb_submit_urb() = %d\n", __FUNCTION__, r);
+                       "%s(): usb_submit_urb() = %d\n", __func__, r);
 }
 
 static int ati_remote2_input_init(struct ati_remote2 *ar2)
@@ -438,7 +438,7 @@ static int ati_remote2_setup(struct ati_remote2 *ar2)
                            channel, 0x0, NULL, 0, USB_CTRL_SET_TIMEOUT);
        if (r) {
                dev_err(&ar2->udev->dev, "%s - failed to set channel due to error: %d\n",
-                       __FUNCTION__, r);
+                       __func__, r);
                return r;
        }
 
index 952938a..86afdd1 100644 (file)
@@ -159,7 +159,7 @@ static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed)
        if (dev->data.pos >= dev->data.len) {
                dev_dbg(&dev->udev->dev,
                        "%s - Error ran out of data. pos: %d, len: %d\n",
-                       __FUNCTION__, dev->data.pos, dev->data.len);
+                       __func__, dev->data.pos, dev->data.len);
                return -1;
        }
 
@@ -267,7 +267,7 @@ static void keyspan_check_data(struct usb_keyspan *remote)
                                remote->data.tester = remote->data.tester >> 6;
                                remote->data.bits_left -= 6;
                        } else {
-                               err("%s - Unknown sequence found in system data.\n", __FUNCTION__);
+                               err("%s - Unknown sequence found in system data.\n", __func__);
                                remote->stage = 0;
                                return;
                        }
@@ -286,7 +286,7 @@ static void keyspan_check_data(struct usb_keyspan *remote)
                                remote->data.tester = remote->data.tester >> 6;
                                remote->data.bits_left -= 6;
                        } else {
-                               err("%s - Unknown sequence found in button data.\n", __FUNCTION__);
+                               err("%s - Unknown sequence found in button data.\n", __func__);
                                remote->stage = 0;
                                return;
                        }
@@ -302,7 +302,7 @@ static void keyspan_check_data(struct usb_keyspan *remote)
                        remote->data.tester = remote->data.tester >> 6;
                        remote->data.bits_left -= 6;
                } else {
-                       err("%s - Error in message, invalid toggle.\n", __FUNCTION__);
+                       err("%s - Error in message, invalid toggle.\n", __func__);
                        remote->stage = 0;
                        return;
                }
@@ -317,7 +317,7 @@ static void keyspan_check_data(struct usb_keyspan *remote)
 
                dev_dbg(&remote->udev->dev,
                        "%s found valid message: system: %d, button: %d, toggle: %d\n",
-                       __FUNCTION__, message.system, message.button, message.toggle);
+                       __func__, message.system, message.button, message.toggle);
 
                if (message.toggle != remote->toggle) {
                        keyspan_report_button(remote, message.button, 1);
@@ -341,7 +341,7 @@ static int keyspan_setup(struct usb_device* dev)
                                 0x11, 0x40, 0x5601, 0x0, NULL, 0, 0);
        if (retval) {
                dev_dbg(&dev->dev, "%s - failed to set bit rate due to error: %d\n",
-                       __FUNCTION__, retval);
+                       __func__, retval);
                return(retval);
        }
 
@@ -349,7 +349,7 @@ static int keyspan_setup(struct usb_device* dev)
                                 0x44, 0x40, 0x0, 0x0, NULL, 0, 0);
        if (retval) {
                dev_dbg(&dev->dev, "%s - failed to set resume sensitivity due to error: %d\n",
-                       __FUNCTION__, retval);
+                       __func__, retval);
                return(retval);
        }
 
@@ -357,11 +357,11 @@ static int keyspan_setup(struct usb_device* dev)
                                 0x22, 0x40, 0x0, 0x0, NULL, 0, 0);
        if (retval) {
                dev_dbg(&dev->dev, "%s - failed to turn receive on due to error: %d\n",
-                       __FUNCTION__, retval);
+                       __func__, retval);
                return(retval);
        }
 
-       dev_dbg(&dev->dev, "%s - Setup complete.\n", __FUNCTION__);
+       dev_dbg(&dev->dev, "%s - Setup complete.\n", __func__);
        return(retval);
 }
 
@@ -397,7 +397,7 @@ static void keyspan_irq_recv(struct urb *urb)
 resubmit:
        retval = usb_submit_urb(urb, GFP_ATOMIC);
        if (retval)
-               err ("%s - usb_submit_urb failed with result: %d", __FUNCTION__, retval);
+               err ("%s - usb_submit_urb failed with result: %d", __func__, retval);
 }
 
 static int keyspan_open(struct input_dev *dev)
index 7a7b8c7..a53c488 100644 (file)
@@ -96,10 +96,10 @@ static void powermate_irq(struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down with status: %d", __func__, urb->status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+               dbg("%s - nonzero urb status received: %d", __func__, urb->status);
                goto exit;
        }
 
@@ -112,7 +112,7 @@ exit:
        retval = usb_submit_urb (urb, GFP_ATOMIC);
        if (retval)
                err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, retval);
+                    __func__, retval);
 }
 
 /* Decide if we need to issue a control message and do so. Must be called with pm->lock taken */
diff --git a/drivers/input/misc/sgi_btns.c b/drivers/input/misc/sgi_btns.c
new file mode 100644 (file)
index 0000000..ce238f5
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ *  SGI Volume Button interface driver
+ *
+ *  Copyright (C) 2008  Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/init.h>
+#include <linux/input-polldev.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#ifdef CONFIG_SGI_IP22
+#include <asm/sgi/ioc.h>
+
+static inline u8 button_status(void)
+{
+       u8 status;
+
+       status = readb(&sgioc->panel) ^ 0xa0;
+       return ((status & 0x80) >> 6) | ((status & 0x20) >> 5);
+}
+#endif
+
+#ifdef CONFIG_SGI_IP32
+#include <asm/ip32/mace.h>
+
+static inline u8 button_status(void)
+{
+       u64 status;
+
+       status = readq(&mace->perif.audio.control);
+       writeq(status & ~(3U << 23), &mace->perif.audio.control);
+
+       return (status >> 23) & 3;
+}
+#endif
+
+#define BUTTONS_POLL_INTERVAL  30      /* msec */
+#define BUTTONS_COUNT_THRESHOLD        3
+
+static const unsigned short sgi_map[] = {
+       KEY_VOLUMEDOWN,
+       KEY_VOLUMEUP
+};
+
+struct buttons_dev {
+       struct input_polled_dev *poll_dev;
+       unsigned short keymap[ARRAY_SIZE(sgi_map)];
+       int count[ARRAY_SIZE(sgi_map)];
+};
+
+static void handle_buttons(struct input_polled_dev *dev)
+{
+       struct buttons_dev *bdev = dev->private;
+       struct input_dev *input = dev->input;
+       u8 status;
+       int i;
+
+       status = button_status();
+
+       for (i = 0; i < ARRAY_SIZE(bdev->keymap); i++) {
+               if (status & (1U << i)) {
+                       if (++bdev->count[i] == BUTTONS_COUNT_THRESHOLD) {
+                               input_event(input, EV_MSC, MSC_SCAN, i);
+                               input_report_key(input, bdev->keymap[i], 1);
+                               input_sync(input);
+                       }
+               } else {
+                       if (bdev->count[i] >= BUTTONS_COUNT_THRESHOLD) {
+                               input_event(input, EV_MSC, MSC_SCAN, i);
+                               input_report_key(input, bdev->keymap[i], 0);
+                               input_sync(input);
+                       }
+                       bdev->count[i] = 0;
+               }
+       }
+}
+
+static int __devinit sgi_buttons_probe(struct platform_device *pdev)
+{
+       struct buttons_dev *bdev;
+       struct input_polled_dev *poll_dev;
+       struct input_dev *input;
+       int error, i;
+
+       bdev = kzalloc(sizeof(struct buttons_dev), GFP_KERNEL);
+       poll_dev = input_allocate_polled_device();
+       if (!bdev || !poll_dev) {
+               error = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       memcpy(bdev->keymap, sgi_map, sizeof(bdev->keymap));
+
+       poll_dev->private = bdev;
+       poll_dev->poll = handle_buttons;
+       poll_dev->poll_interval = BUTTONS_POLL_INTERVAL;
+
+       input = poll_dev->input;
+       input->name = "SGI buttons";
+       input->phys = "sgi/input0";
+       input->id.bustype = BUS_HOST;
+       input->dev.parent = &pdev->dev;
+
+       input->keycode = bdev->keymap;
+       input->keycodemax = ARRAY_SIZE(bdev->keymap);
+       input->keycodesize = sizeof(unsigned short);
+
+       input_set_capability(input, EV_MSC, MSC_SCAN);
+       __set_bit(EV_KEY, input->evbit);
+       for (i = 0; i < ARRAY_SIZE(sgi_map); i++)
+               __set_bit(bdev->keymap[i], input->keybit);
+       __clear_bit(KEY_RESERVED, input->keybit);
+
+       bdev->poll_dev = poll_dev;
+       dev_set_drvdata(&pdev->dev, bdev);
+
+       error = input_register_polled_device(poll_dev);
+       if (error)
+               goto err_free_mem;
+
+       return 0;
+
+ err_free_mem:
+       input_free_polled_device(poll_dev);
+       kfree(bdev);
+       dev_set_drvdata(&pdev->dev, NULL);
+       return error;
+}
+
+static int __devexit sgi_buttons_remove(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct buttons_dev *bdev = dev_get_drvdata(dev);
+
+       input_unregister_polled_device(bdev->poll_dev);
+       input_free_polled_device(bdev->poll_dev);
+       kfree(bdev);
+       dev_set_drvdata(dev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver sgi_buttons_driver = {
+       .probe  = sgi_buttons_probe,
+       .remove = __devexit_p(sgi_buttons_remove),
+       .driver = {
+               .name   = "sgibtns",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init sgi_buttons_init(void)
+{
+       return platform_driver_register(&sgi_buttons_driver);
+}
+
+static void __exit sgi_buttons_exit(void)
+{
+       platform_driver_unregister(&sgi_buttons_driver);
+}
+
+module_init(sgi_buttons_init);
+module_exit(sgi_buttons_exit);
index 72176f3..fe268be 100644 (file)
@@ -1186,7 +1186,7 @@ static int wistron_setkeycode(struct input_dev *dev, int scancode, int keycode)
 
 static int __devinit setup_input_dev(void)
 {
-       const struct key_entry *key;
+       struct key_entry *key;
        struct input_dev *input_dev;
        int error;
 
@@ -1219,6 +1219,23 @@ static int __devinit setup_input_dev(void)
                                set_bit(key->sw.code, input_dev->swbit);
                                break;
 
+                       /* if wifi or bluetooth are not available, create normal keys */
+                       case KE_WIFI:
+                               if (!have_wifi) {
+                                       key->type = KE_KEY;
+                                       key->keycode = KEY_WLAN;
+                                       key--;
+                               }
+                               break;
+
+                       case KE_BLUETOOTH:
+                               if (!have_bluetooth) {
+                                       key->type = KE_KEY;
+                                       key->keycode = KEY_BLUETOOTH;
+                                       key--;
+                               }
+                               break;
+
                        default:
                                break;
                }
index 46279ef..facefd3 100644 (file)
@@ -119,6 +119,8 @@ struct yealink_dev {
        u8 lcdMap[ARRAY_SIZE(lcdMap)];  /* state of LCD, LED ... */
        int key_code;                   /* last reported key     */
 
+       unsigned int shutdown:1;
+
        int     stat_ix;
        union {
                struct yld_status s;
@@ -424,10 +426,10 @@ send_update:
 static void urb_irq_callback(struct urb *urb)
 {
        struct yealink_dev *yld = urb->context;
-       int ret;
+       int ret, status = urb->status;
 
-       if (urb->status)
-               err("%s - urb status %d", __FUNCTION__, urb->status);
+       if (status)
+               err("%s - urb status %d", __func__, status);
 
        switch (yld->irq_data->cmd) {
        case CMD_KEYPRESS:
@@ -447,33 +449,38 @@ static void urb_irq_callback(struct urb *urb)
 
        yealink_do_idle_tasks(yld);
 
-       ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
-       if (ret)
-               err("%s - usb_submit_urb failed %d", __FUNCTION__, ret);
+       if (!yld->shutdown) {
+               ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
+               if (ret && ret != -EPERM)
+                       err("%s - usb_submit_urb failed %d", __func__, ret);
+       }
 }
 
 static void urb_ctl_callback(struct urb *urb)
 {
        struct yealink_dev *yld = urb->context;
-       int ret;
+       int ret = 0, status = urb->status;
 
-       if (urb->status)
-               err("%s - urb status %d", __FUNCTION__, urb->status);
+       if (status)
+               err("%s - urb status %d", __func__, status);
 
        switch (yld->ctl_data->cmd) {
        case CMD_KEYPRESS:
        case CMD_SCANCODE:
                /* ask for a response */
-               ret = usb_submit_urb(yld->urb_irq, GFP_ATOMIC);
+               if (!yld->shutdown)
+                       ret = usb_submit_urb(yld->urb_irq, GFP_ATOMIC);
                break;
        default:
                /* send new command */
                yealink_do_idle_tasks(yld);
-               ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
+               if (!yld->shutdown)
+                       ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
+               break;
        }
 
-       if (ret)
-               err("%s - usb_submit_urb failed %d", __FUNCTION__, ret);
+       if (ret && ret != -EPERM)
+               err("%s - usb_submit_urb failed %d", __func__, ret);
 }
 
 /*******************************************************************************
@@ -505,7 +512,7 @@ static int input_open(struct input_dev *dev)
        struct yealink_dev *yld = input_get_drvdata(dev);
        int i, ret;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        /* force updates to device */
        for (i = 0; i<sizeof(yld->master); i++)
@@ -521,7 +528,7 @@ static int input_open(struct input_dev *dev)
        yld->ctl_data->sum      = 0x100-CMD_INIT-10;
        if ((ret = usb_submit_urb(yld->urb_ctl, GFP_KERNEL)) != 0) {
                dbg("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, ret);
+                    __func__, ret);
                return ret;
        }
        return 0;
@@ -531,8 +538,18 @@ static void input_close(struct input_dev *dev)
 {
        struct yealink_dev *yld = input_get_drvdata(dev);
 
+       yld->shutdown = 1;
+       /*
+        * Make sure the flag is seen by other CPUs before we start
+        * killing URBs so new URBs won't be submitted
+        */
+       smp_wmb();
+
        usb_kill_urb(yld->urb_ctl);
        usb_kill_urb(yld->urb_irq);
+
+       yld->shutdown = 0;
+       smp_wmb();
 }
 
 /*******************************************************************************
@@ -809,9 +826,6 @@ static int usb_cleanup(struct yealink_dev *yld, int err)
        if (yld == NULL)
                return err;
 
-       usb_kill_urb(yld->urb_irq);     /* parameter validation in core/urb */
-       usb_kill_urb(yld->urb_ctl);     /* parameter validation in core/urb */
-
         if (yld->idev) {
                if (err)
                        input_free_device(yld->idev);
index ce6fdec..1f41ae9 100644 (file)
@@ -2,12 +2,13 @@
  * Apple USB Touchpad (for post-February 2005 PowerBooks and MacBooks) driver
  *
  * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2005      Johannes Berg (johannes@sipsolutions.net)
+ * Copyright (C) 2005-2008 Johannes Berg (johannes@sipsolutions.net)
  * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
  * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
  * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
  * Copyright (C) 2005      Michael Hanselmann (linux-kernel@hansmi.ch)
  * Copyright (C) 2006      Nicolas Boichat (nicolas@boichat.ch)
+ * Copyright (C) 2007-2008 Sven Anders (anders@anduras.de)
  *
  * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
  *
 #include <linux/module.h>
 #include <linux/usb/input.h>
 
-/* Apple has powerbooks which have the keyboard with different Product IDs */
-#define APPLE_VENDOR_ID                0x05AC
-
-/* These names come from Info.plist in AppleUSBTrackpad.kext */
-#define FOUNTAIN_ANSI_PRODUCT_ID       0x020E
-#define FOUNTAIN_ISO_PRODUCT_ID                0x020F
-
-#define FOUNTAIN_TP_ONLY_PRODUCT_ID    0x030A
-
-#define GEYSER1_TP_ONLY_PRODUCT_ID     0x030B
-
-#define GEYSER_ANSI_PRODUCT_ID         0x0214
-#define GEYSER_ISO_PRODUCT_ID          0x0215
-#define GEYSER_JIS_PRODUCT_ID          0x0216
-
-/* MacBook devices */
-#define GEYSER3_ANSI_PRODUCT_ID                0x0217
-#define GEYSER3_ISO_PRODUCT_ID         0x0218
-#define GEYSER3_JIS_PRODUCT_ID         0x0219
-
-/*
- * Geyser IV: same as Geyser III according to Info.plist in AppleUSBTrackpad.kext
- * -> same IOClass (AppleUSBGrIIITrackpad), same acceleration tables
- */
-#define GEYSER4_ANSI_PRODUCT_ID        0x021A
-#define GEYSER4_ISO_PRODUCT_ID 0x021B
-#define GEYSER4_JIS_PRODUCT_ID 0x021C
-
-#define GEYSER4_HF_ANSI_PRODUCT_ID     0x0229
-#define GEYSER4_HF_ISO_PRODUCT_ID      0x022A
-#define GEYSER4_HF_JIS_PRODUCT_ID      0x022B
+/* Type of touchpad */
+enum atp_touchpad_type {
+       ATP_FOUNTAIN,
+       ATP_GEYSER1,
+       ATP_GEYSER2,
+       ATP_GEYSER3,
+       ATP_GEYSER4
+};
 
-#define ATP_DEVICE(prod)                                       \
+#define ATP_DEVICE(prod, type)                                 \
+{                                                              \
        .match_flags = USB_DEVICE_ID_MATCH_DEVICE |             \
                       USB_DEVICE_ID_MATCH_INT_CLASS |          \
                       USB_DEVICE_ID_MATCH_INT_PROTOCOL,        \
-       .idVendor = APPLE_VENDOR_ID,                            \
+       .idVendor = 0x05ac, /* Apple */                         \
        .idProduct = (prod),                                    \
        .bInterfaceClass = 0x03,                                \
-       .bInterfaceProtocol = 0x02
+       .bInterfaceProtocol = 0x02,                             \
+       .driver_info = ATP_ ## type,                            \
+}
+
+/*
+ * Table of devices (Product IDs) that work with this driver.
+ * (The names come from Info.plist in AppleUSBTrackpad.kext,
+ *  According to Info.plist Geyser IV is the same as Geyser III.)
+ */
 
-/* table of devices that work with this driver */
 static struct usb_device_id atp_table [] = {
-       { ATP_DEVICE(FOUNTAIN_ANSI_PRODUCT_ID) },
-       { ATP_DEVICE(FOUNTAIN_ISO_PRODUCT_ID) },
-       { ATP_DEVICE(FOUNTAIN_TP_ONLY_PRODUCT_ID) },
-       { ATP_DEVICE(GEYSER1_TP_ONLY_PRODUCT_ID) },
+       /* PowerBooks Feb 2005, iBooks G4 */
+       ATP_DEVICE(0x020e, FOUNTAIN),   /* FOUNTAIN ANSI */
+       ATP_DEVICE(0x020f, FOUNTAIN),   /* FOUNTAIN ISO */
+       ATP_DEVICE(0x030a, FOUNTAIN),   /* FOUNTAIN TP ONLY */
+       ATP_DEVICE(0x030b, GEYSER1),    /* GEYSER 1 TP ONLY */
 
        /* PowerBooks Oct 2005 */
-       { ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) },
-       { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) },
-       { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) },
+       ATP_DEVICE(0x0214, GEYSER2),    /* GEYSER 2 ANSI */
+       ATP_DEVICE(0x0215, GEYSER2),    /* GEYSER 2 ISO */
+       ATP_DEVICE(0x0216, GEYSER2),    /* GEYSER 2 JIS */
 
        /* Core Duo MacBook & MacBook Pro */
-       { ATP_DEVICE(GEYSER3_ANSI_PRODUCT_ID) },
-       { ATP_DEVICE(GEYSER3_ISO_PRODUCT_ID) },
-       { ATP_DEVICE(GEYSER3_JIS_PRODUCT_ID) },
+       ATP_DEVICE(0x0217, GEYSER3),    /* GEYSER 3 ANSI */
+       ATP_DEVICE(0x0218, GEYSER3),    /* GEYSER 3 ISO */
+       ATP_DEVICE(0x0219, GEYSER3),    /* GEYSER 3 JIS */
 
        /* Core2 Duo MacBook & MacBook Pro */
-       { ATP_DEVICE(GEYSER4_ANSI_PRODUCT_ID) },
-       { ATP_DEVICE(GEYSER4_ISO_PRODUCT_ID) },
-       { ATP_DEVICE(GEYSER4_JIS_PRODUCT_ID) },
+       ATP_DEVICE(0x021a, GEYSER4),    /* GEYSER 4 ANSI */
+       ATP_DEVICE(0x021b, GEYSER4),    /* GEYSER 4 ISO */
+       ATP_DEVICE(0x021c, GEYSER4),    /* GEYSER 4 JIS */
 
-       { ATP_DEVICE(GEYSER4_HF_ANSI_PRODUCT_ID) },
-       { ATP_DEVICE(GEYSER4_HF_ISO_PRODUCT_ID) },
-       { ATP_DEVICE(GEYSER4_HF_JIS_PRODUCT_ID) },
+       /* Core2 Duo MacBook3,1 */
+       ATP_DEVICE(0x0229, GEYSER4),    /* GEYSER 4 HF ANSI */
+       ATP_DEVICE(0x022a, GEYSER4),    /* GEYSER 4 HF ISO */
+       ATP_DEVICE(0x022b, GEYSER4),    /* GEYSER 4 HF JIS */
 
        /* Terminating entry */
        { }
 };
-MODULE_DEVICE_TABLE (usb, atp_table);
+MODULE_DEVICE_TABLE(usb, atp_table);
 
 /*
  * number of sensors. Note that only 16 instead of 26 X (horizontal)
@@ -124,9 +112,13 @@ MODULE_DEVICE_TABLE (usb, atp_table);
  * We try to keep the touchpad aspect ratio while still doing only simple
  * arithmetics.
  * The factors below give coordinates like:
- *     0 <= x <  960 on 12" and 15" Powerbooks
- *     0 <= x < 1600 on 17" Powerbooks
- *     0 <= y <  646
+ *
+ *      0 <= x <  960 on 12" and 15" Powerbooks
+ *      0 <= x < 1600 on 17" Powerbooks and 17" MacBook Pro
+ *      0 <= x < 1216 on MacBooks and 15" MacBook Pro
+ *
+ *      0 <= y <  646 on all Powerbooks
+ *      0 <= y <  774 on all MacBooks
  */
 #define ATP_XFACT      64
 #define ATP_YFACT      43
@@ -147,43 +139,46 @@ MODULE_DEVICE_TABLE (usb, atp_table);
 /* Structure to hold all of our device specific stuff */
 struct atp {
        char                    phys[64];
-       struct usb_device *     udev;           /* usb device */
-       struct urb *            urb;            /* usb request block */
-       signed char *           data;           /* transferred data */
-       struct input_dev *      input;          /* input dev */
-       unsigned char           open;           /* non-zero if opened */
-       unsigned char           valid;          /* are the sensors valid ? */
-       unsigned char           size_detect_done;
-       unsigned char           overflowwarn;   /* overflow warning printed? */
+       struct usb_device       *udev;          /* usb device */
+       struct urb              *urb;           /* usb request block */
+       signed char             *data;          /* transferred data */
+       struct input_dev        *input;         /* input dev */
+       enum atp_touchpad_type  type;           /* type of touchpad */
+       bool                    open;
+       bool                    valid;          /* are the samples valid? */
+       bool                    size_detect_done;
+       bool                    overflow_warned;
        int                     x_old;          /* last reported x/y, */
        int                     y_old;          /* used for smoothing */
-                                               /* current value of the sensors */
        signed char             xy_cur[ATP_XSENSORS + ATP_YSENSORS];
-                                               /* last value of the sensors */
        signed char             xy_old[ATP_XSENSORS + ATP_YSENSORS];
-                                               /* accumulated sensors */
        int                     xy_acc[ATP_XSENSORS + ATP_YSENSORS];
-       int                     datalen;        /* size of an USB urb transfer */
-       int                     idlecount;      /* number of empty packets */
-       struct work_struct      work;
+       int                     datalen;        /* size of USB transfer */
+       int                     idlecount;      /* number of empty packets */
+       struct work_struct      work;
 };
 
 #define dbg_dump(msg, tab) \
        if (debug > 1) {                                                \
-               int i;                                                  \
-               printk("appletouch: %s %lld", msg, (long long)jiffies); \
-               for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++)       \
-                       printk(" %02x", tab[i]);                        \
+               int __i;                                                \
+               printk(KERN_DEBUG "appletouch: %s", msg);               \
+               for (__i = 0; __i < ATP_XSENSORS + ATP_YSENSORS; __i++) \
+                       printk(" %02x", tab[__i]);                      \
                printk("\n");                                           \
        }
 
 #define dprintk(format, a...)                                          \
        do {                                                            \
-               if (debug) printk(KERN_DEBUG format, ##a);              \
+               if (debug)                                              \
+                       printk(KERN_DEBUG format, ##a);                 \
        } while (0)
 
-MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann");
-MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
+MODULE_AUTHOR("Johannes Berg");
+MODULE_AUTHOR("Stelian Pop");
+MODULE_AUTHOR("Frank Arnold");
+MODULE_AUTHOR("Michael Hanselmann");
+MODULE_AUTHOR("Sven Anders");
+MODULE_DESCRIPTION("Apple PowerBook and MacBook USB touchpad driver");
 MODULE_LICENSE("GPL");
 
 /*
@@ -191,46 +186,14 @@ MODULE_LICENSE("GPL");
  */
 static int threshold = ATP_THRESHOLD;
 module_param(threshold, int, 0644);
-MODULE_PARM_DESC(threshold, "Discards any change in data from a sensor (trackpad has hundreds of these sensors) less than this value");
+MODULE_PARM_DESC(threshold, "Discard any change in data from a sensor"
+                           " (the trackpad has many of these sensors)"
+                           " less than this value.");
 
-static int debug = 1;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Activate debugging output");
 
-static inline int atp_is_fountain(struct atp *dev)
-{
-       u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct);
-
-       return productId == FOUNTAIN_ANSI_PRODUCT_ID ||
-              productId == FOUNTAIN_ISO_PRODUCT_ID ||
-              productId == FOUNTAIN_TP_ONLY_PRODUCT_ID;
-}
-
-/* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */
-static inline int atp_is_geyser_2(struct atp *dev)
-{
-       u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct);
-
-       return (productId == GEYSER_ANSI_PRODUCT_ID) ||
-               (productId == GEYSER_ISO_PRODUCT_ID) ||
-               (productId == GEYSER_JIS_PRODUCT_ID);
-}
-
-static inline int atp_is_geyser_3(struct atp *dev)
-{
-       u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct);
-
-       return (productId == GEYSER3_ANSI_PRODUCT_ID) ||
-               (productId == GEYSER3_ISO_PRODUCT_ID) ||
-               (productId == GEYSER3_JIS_PRODUCT_ID) ||
-               (productId == GEYSER4_ANSI_PRODUCT_ID) ||
-               (productId == GEYSER4_ISO_PRODUCT_ID) ||
-               (productId == GEYSER4_JIS_PRODUCT_ID) ||
-               (productId == GEYSER4_HF_ANSI_PRODUCT_ID) ||
-               (productId == GEYSER4_HF_ISO_PRODUCT_ID) ||
-               (productId == GEYSER4_HF_JIS_PRODUCT_ID);
-}
-
 /*
  * By default newer Geyser devices send standard USB HID mouse
  * packets (Report ID 2). This code changes device mode, so it
@@ -240,6 +203,7 @@ static int atp_geyser_init(struct usb_device *udev)
 {
        char data[8];
        int size;
+       int i;
 
        size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
                        ATP_GEYSER_MODE_READ_REQUEST_ID,
@@ -248,8 +212,11 @@ static int atp_geyser_init(struct usb_device *udev)
                        ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000);
 
        if (size != 8) {
-               err("Could not do mode read request from device"
-                   " (Geyser Raw mode)");
+               dprintk("atp_geyser_init: read error\n");
+               for (i = 0; i < 8; i++)
+                       dprintk("appletouch[%d]: %d\n", i, data[i]);
+
+               err("Failed to read mode from device.");
                return -EIO;
        }
 
@@ -263,8 +230,11 @@ static int atp_geyser_init(struct usb_device *udev)
                        ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000);
 
        if (size != 8) {
-               err("Could not do mode write request to device"
-                   " (Geyser Raw mode)");
+               dprintk("atp_geyser_init: write error\n");
+               for (i = 0; i < 8; i++)
+                       dprintk("appletouch[%d]: %d\n", i, data[i]);
+
+               err("Failed to request geyser raw mode");
                return -EIO;
        }
        return 0;
@@ -280,15 +250,15 @@ static void atp_reinit(struct work_struct *work)
        struct usb_device *udev = dev->udev;
        int retval;
 
+       dprintk("appletouch: putting appletouch to sleep (reinit)\n");
        dev->idlecount = 0;
 
        atp_geyser_init(udev);
 
        retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
-       if (retval) {
-               err("%s - usb_submit_urb failed with result %d",
-                   __FUNCTION__, retval);
-       }
+       if (retval)
+               err("atp_reinit: usb_submit_urb failed with error %d",
+                   retval);
 }
 
 static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
@@ -323,7 +293,8 @@ static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
                 *
                 * - Jason Parekh <jasonparekh@gmail.com>
                 */
-               if (i < 1 || (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) {
+               if (i < 1 ||
+                   (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) {
                        (*fingers)++;
                        is_increasing = 1;
                } else if (i > 0 && xy_sensors[i - 1] >= xy_sensors[i]) {
@@ -331,11 +302,11 @@ static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
                }
 
                /*
-                * Subtracts threshold so a high sensor that just passes the threshold
-                * won't skew the calculated absolute coordinate.  Fixes an issue
-                * where slowly moving the mouse would occassionaly jump a number of
-                * pixels (let me restate--slowly moving the mouse makes this issue
-                * most apparent).
+                * Subtracts threshold so a high sensor that just passes the
+                * threshold won't skew the calculated absolute coordinate.
+                * Fixes an issue where slowly moving the mouse would
+                * occasionally jump a number of pixels (slowly moving the
+                * finger makes this issue most apparent.)
                 */
                pcum += (xy_sensors[i] - threshold) * i;
                psum += (xy_sensors[i] - threshold);
@@ -356,7 +327,7 @@ static inline void atp_report_fingers(struct input_dev *input, int fingers)
        input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2);
 }
 
-static void atp_complete(struct urburb)
+static void atp_complete(struct urb *urb)
 {
        int x, y, x_z, y_z, x_f, y_f;
        int retval, i, j;
@@ -368,22 +339,22 @@ static void atp_complete(struct urb* urb)
                /* success */
                break;
        case -EOVERFLOW:
-               if(!dev->overflowwarn) {
+               if (!dev->overflow_warned) {
                        printk(KERN_WARNING "appletouch: OVERFLOW with data "
                                "length %d, actual length is %d\n",
                                dev->datalen, dev->urb->actual_length);
-                       dev->overflowwarn = 1;
+                       dev->overflow_warned = true;
                }
        case -ECONNRESET:
        case -ENOENT:
        case -ESHUTDOWN:
                /* This urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d",
-                   __FUNCTION__, urb->status);
+               dbg("atp_complete: urb shutting down with status: %d",
+                   urb->status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d",
-                   __FUNCTION__, urb->status);
+               dbg("atp_complete: nonzero urb status received: %d",
+                   urb->status);
                goto exit;
        }
 
@@ -396,7 +367,7 @@ static void atp_complete(struct urb* urb)
        }
 
        /* reorder the sensors values */
-       if (atp_is_geyser_3(dev)) {
+       if (dev->type == ATP_GEYSER3 || dev->type == ATP_GEYSER4) {
                memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
 
                /*
@@ -415,7 +386,7 @@ static void atp_complete(struct urb* urb)
                        dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1];
                        dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2];
                }
-       } else if (atp_is_geyser_2(dev)) {
+       } else if (dev->type == ATP_GEYSER2) {
                memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
 
                /*
@@ -438,7 +409,7 @@ static void atp_complete(struct urb* urb)
        } else {
                for (i = 0; i < 8; i++) {
                        /* X values */
-                       dev->xy_cur[i     ] = dev->data[5 * i +  2];
+                       dev->xy_cur[i +  0] = dev->data[5 * i +  2];
                        dev->xy_cur[i +  8] = dev->data[5 * i +  4];
                        dev->xy_cur[i + 16] = dev->data[5 * i + 42];
                        if (i < 2)
@@ -454,21 +425,22 @@ static void atp_complete(struct urb* urb)
 
        if (!dev->valid) {
                /* first sample */
-               dev->valid = 1;
+               dev->valid = true;
                dev->x_old = dev->y_old = -1;
                memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
 
                if (dev->size_detect_done ||
-                   atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */
+                   dev->type == ATP_GEYSER3) /* No 17" Macbooks (yet) */
                        goto exit;
 
                /* 17" Powerbooks have extra X sensors */
-               for (i = (atp_is_geyser_2(dev) ? 15 : 16); i < ATP_XSENSORS; i++) {
+               for (i = (dev->type == ATP_GEYSER2 ? 15 : 16);
+                    i < ATP_XSENSORS; i++) {
                        if (!dev->xy_cur[i])
                                continue;
 
                        printk(KERN_INFO "appletouch: 17\" model detected.\n");
-                       if (atp_is_geyser_2(dev))
+                       if (dev->type == ATP_GEYSER2)
                                input_set_abs_params(dev->input, ABS_X, 0,
                                                     (20 - 1) *
                                                     ATP_XFACT - 1,
@@ -548,11 +520,15 @@ static void atp_complete(struct urb* urb)
         * several hundred times a second. Re-initialization does not
         * work on Fountain touchpads.
         */
-       if (!atp_is_fountain(dev)) {
+       if (dev->type != ATP_FOUNTAIN) {
+               /*
+                * Button must not be pressed when entering suspend,
+                * otherwise we will never release the button.
+                */
                if (!x && !y && !key) {
                        dev->idlecount++;
                        if (dev->idlecount == 10) {
-                               dev->valid = 0;
+                               dev->valid = false;
                                schedule_work(&dev->work);
                                /* Don't resubmit urb here, wait for reinit */
                                return;
@@ -561,12 +537,11 @@ static void atp_complete(struct urb* urb)
                        dev->idlecount = 0;
        }
 
-exit:
+ exit:
        retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
-       if (retval) {
-               err("%s - usb_submit_urb failed with result %d",
-                   __FUNCTION__, retval);
-       }
+       if (retval)
+               err("atp_complete: usb_submit_urb failed with result %d",
+                   retval);
 }
 
 static int atp_open(struct input_dev *input)
@@ -593,7 +568,7 @@ static int atp_handle_geyser(struct atp *dev)
 {
        struct usb_device *udev = dev->udev;
 
-       if (!atp_is_fountain(dev)) {
+       if (dev->type != ATP_FOUNTAIN) {
                /* switch to raw sensor mode */
                if (atp_geyser_init(udev))
                        return -EIO;
@@ -604,7 +579,8 @@ static int atp_handle_geyser(struct atp *dev)
        return 0;
 }
 
-static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id)
+static int atp_probe(struct usb_interface *iface,
+                    const struct usb_device_id *id)
 {
        struct atp *dev;
        struct input_dev *input_dev;
@@ -640,13 +616,12 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
 
        dev->udev = udev;
        dev->input = input_dev;
-       dev->overflowwarn = 0;
-       if (atp_is_geyser_3(dev))
-               dev->datalen = 64;
-       else if (atp_is_geyser_2(dev))
-               dev->datalen = 64;
-       else
+       dev->type = id->driver_info;
+       dev->overflow_warned = false;
+       if (dev->type == ATP_FOUNTAIN || dev->type == ATP_GEYSER1)
                dev->datalen = 81;
+       else
+               dev->datalen = 64;
 
        dev->urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!dev->urb)
@@ -680,7 +655,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
 
        set_bit(EV_ABS, input_dev->evbit);
 
-       if (atp_is_geyser_3(dev)) {
+       if (dev->type == ATP_GEYSER3 || dev->type == ATP_GEYSER4) {
                /*
                 * MacBook have 20 X sensors, 10 Y sensors
                 */
@@ -688,7 +663,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
                                     ((20 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
                input_set_abs_params(input_dev, ABS_Y, 0,
                                     ((10 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
-       } else if (atp_is_geyser_2(dev)) {
+       } else if (dev->type == ATP_GEYSER2) {
                /*
                 * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected
                 * later.
@@ -703,9 +678,11 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
                 * 17" models are detected later.
                 */
                input_set_abs_params(input_dev, ABS_X, 0,
-                                    (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
+                                    (16 - 1) * ATP_XFACT - 1,
+                                    ATP_FUZZ, 0);
                input_set_abs_params(input_dev, ABS_Y, 0,
-                                    (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+                                    (ATP_YSENSORS - 1) * ATP_YFACT - 1,
+                                    ATP_FUZZ, 0);
        }
        input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
 
@@ -774,7 +751,7 @@ static int atp_suspend(struct usb_interface *iface, pm_message_t message)
        struct atp *dev = usb_get_intfdata(iface);
 
        usb_kill_urb(dev->urb);
-       dev->valid = 0;
+       dev->valid = false;
 
        return 0;
 }
index 98a3561..adf45b3 100644 (file)
@@ -57,15 +57,12 @@ MODULE_AUTHOR("Michael Schmitz <schmitz@biophys.uni-duesseldorf.de>");
 MODULE_DESCRIPTION("Atari mouse driver");
 MODULE_LICENSE("GPL");
 
-static int mouse_threshold[2] = {2,2};
+static int mouse_threshold[2] = {2, 2};
+module_param_array(mouse_threshold, int, NULL, 0);
 
-#ifdef __MODULE__
-MODULE_PARM(mouse_threshold, "2i");
-#endif
 #ifdef FIXED_ATARI_JOYSTICK
 extern int atari_mouse_buttons;
 #endif
-static int atamouse_used = 0;
 
 static struct input_dev *atamouse_dev;
 
@@ -97,9 +94,6 @@ static void atamouse_interrupt(char *buf)
 
 static int atamouse_open(struct input_dev *dev)
 {
-       if (atamouse_used++)
-               return 0;
-
 #ifdef FIXED_ATARI_JOYSTICK
        atari_mouse_buttons = 0;
 #endif
@@ -107,23 +101,24 @@ static int atamouse_open(struct input_dev *dev)
        ikbd_mouse_thresh(mouse_threshold[0], mouse_threshold[1]);
        ikbd_mouse_rel_pos();
        atari_input_mouse_interrupt_hook = atamouse_interrupt;
+
        return 0;
 }
 
 static void atamouse_close(struct input_dev *dev)
 {
-       if (!--atamouse_used) {
-               ikbd_mouse_disable();
-               atari_mouse_interrupt_hook = NULL;
-       }
+       ikbd_mouse_disable();
+       atari_mouse_interrupt_hook = NULL;
 }
 
 static int __init atamouse_init(void)
 {
+       int error;
+
        if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP))
                return -ENODEV;
 
-       if (!(atari_keyb_init()))
+       if (!atari_keyb_init())
                return -ENODEV;
 
        atamouse_dev = input_allocate_device();
@@ -141,12 +136,14 @@ static int __init atamouse_init(void)
        atamouse_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
        atamouse_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
                BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
+
        atamouse_dev->open = atamouse_open;
        atamouse_dev->close = atamouse_close;
 
-       if (input_register_device(atamouse_dev)) {
+       error = input_register_device(atamouse_dev);
+       if (error) {
                input_free_device(atamouse_dev);
-               return -ENOMEM;
+               return error;
        }
 
        return 0;
index 27f88fb..e532c48 100644 (file)
@@ -247,19 +247,24 @@ static void hil_ptr_disconnect(struct serio *serio)
 
 static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
 {
-       struct hil_ptr   *ptr;
-       const char       *txt;
-       unsigned int     i, naxsets, btntype;
-       uint8_t          did, *idd;
-
-       if (!(ptr = kzalloc(sizeof(struct hil_ptr), GFP_KERNEL)))
+       struct hil_ptr  *ptr;
+       const char      *txt;
+       unsigned int    i, naxsets, btntype;
+       uint8_t         did, *idd;
+       int             error;
+
+       ptr = kzalloc(sizeof(struct hil_ptr), GFP_KERNEL);
+       if (!ptr)
                return -ENOMEM;
 
        ptr->dev = input_allocate_device();
-       if (!ptr->dev)
+       if (!ptr->dev) {
+               error = -ENOMEM;
                goto bail0;
+       }
 
-       if (serio_open(serio, driver))
+       error = serio_open(serio, driver);
+       if (error)
                goto bail1;
 
        serio_set_drvdata(serio, ptr);
@@ -297,6 +302,7 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
        did = ptr->idd[0];
        idd = ptr->idd + 1;
        txt = "unknown";
+
        if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
                ptr->dev->evbit[0] = BIT_MASK(EV_REL);
                txt = "relative";
@@ -306,8 +312,11 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
                ptr->dev->evbit[0] = BIT_MASK(EV_ABS);
                txt = "absolute";
        }
-       if (!ptr->dev->evbit[0])
+
+       if (!ptr->dev->evbit[0]) {
+               error = -ENODEV;
                goto bail2;
+       }
 
        ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd);
        if (ptr->nbtn)
@@ -380,13 +389,19 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
        ptr->dev->id.version    = 0x0100; /* TODO: get from ptr->rsc */
        ptr->dev->dev.parent    = &serio->dev;
 
-       input_register_device(ptr->dev);
+       error = input_register_device(ptr->dev);
+       if (error) {
+               printk(KERN_INFO PREFIX "Unable to register input device\n");
+               goto bail2;
+       }
+
        printk(KERN_INFO "input: %s (%s), ID: %d\n",
                ptr->dev->name,
                (btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad",
                did);
 
        return 0;
+
  bail2:
        serio_close(serio);
  bail1:
@@ -394,7 +409,7 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
  bail0:
        kfree(ptr);
        serio_set_drvdata(serio, NULL);
-       return -ENODEV;
+       return error;
 }
 
 static struct serio_device_id hil_ptr_ids[] = {
index 06c35fc..3827a22 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: inport.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
  *  Based on the work of:
index 9ea8955..e241311 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: logibm.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
  *  Based on the work of:
index 61cff83..fd09c8d 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: pc110pad.c,v 1.12 2001/09/25 10:12:07 vojtech Exp $
- *
  *  Copyright (c) 2000-2001 Vojtech Pavlik
  *
  *  Based on the work of:
index ed917bf..17ff137 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: sermouse.c,v 1.17 2002/03/13 10:03:43 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
index ec4b661..27d70d3 100644 (file)
@@ -190,4 +190,14 @@ config SERIO_RAW
          To compile this driver as a module, choose M here: the
          module will be called serio_raw.
 
+config SERIO_XILINX_XPS_PS2
+       tristate "Xilinx XPS PS/2 Controller Support"
+       depends on PPC
+       help
+         This driver supports XPS PS/2 IP from the Xilinx EDK on
+         PowerPC platform.
+
+         To compile this driver as a module, choose M here: the
+         module will be called xilinx_ps2.
+
 endif
index 38b8868..9b6c813 100644 (file)
@@ -21,3 +21,4 @@ obj-$(CONFIG_SERIO_PCIPS2)    += pcips2.o
 obj-$(CONFIG_SERIO_MACEPS2)    += maceps2.o
 obj-$(CONFIG_SERIO_LIBPS2)     += libps2.o
 obj-$(CONFIG_SERIO_RAW)                += serio_raw.o
+obj-$(CONFIG_SERIO_XILINX_XPS_PS2)     += xilinx_ps2.o
index 0d35018..d1380fc 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: ct82c710.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
index 93a1a6b..37586a6 100644 (file)
@@ -76,7 +76,7 @@ static struct timer_list      hil_mlcs_kicker;
 static int                     hil_mlcs_probe;
 
 static void hil_mlcs_process(unsigned long unused);
-DECLARE_TASKLET_DISABLED(hil_mlcs_tasklet, hil_mlcs_process, 0);
+static DECLARE_TASKLET_DISABLED(hil_mlcs_tasklet, hil_mlcs_process, 0);
 
 
 /* #define HIL_MLC_DEBUG */
@@ -459,7 +459,7 @@ static int hilse_operate(hil_mlc *mlc, int repoll)
 #define OUT_LAST(pack) \
 { HILSE_OUT_LAST,      { .packet = pack }, 0, 0, 0, 0 },
 
-const struct hilse_node hil_mlc_se[HILSEN_END] = {
+static const struct hilse_node hil_mlc_se[HILSEN_END] = {
 
        /* 0  HILSEN_START */
        FUNC(hilse_init_lcv, 0, HILSEN_NEXT,    HILSEN_SLEEP,   0)
@@ -784,7 +784,7 @@ static void hil_mlcs_process(unsigned long unused)
 
 /************************* Keepalive timer task *********************/
 
-void hil_mlcs_timer(unsigned long data)
+static void hil_mlcs_timer(unsigned long data)
 {
        hil_mlcs_probe = 1;
        tasklet_schedule(&hil_mlcs_tasklet);
index edfedd9..7b233a4 100644 (file)
@@ -105,6 +105,10 @@ EXPORT_SYMBOL(__hp_sdc_enqueue_transaction);
 EXPORT_SYMBOL(hp_sdc_enqueue_transaction);
 EXPORT_SYMBOL(hp_sdc_dequeue_transaction);
 
+static unsigned int hp_sdc_disabled;
+module_param_named(no_hpsdc, hp_sdc_disabled, bool, 0);
+MODULE_PARM_DESC(no_hpsdc, "Do not enable HP SDC driver.");
+
 static hp_i8042_sdc    hp_sdc; /* All driver state is kept in here. */
 
 /*************** primitives for use in any context *********************/
@@ -980,6 +984,11 @@ static int __init hp_sdc_register(void)
        unsigned char i;
 #endif
 
+       if (hp_sdc_disabled) {
+               printk(KERN_WARNING PREFIX "HP SDC driver disabled by no_hpsdc=1.\n");
+               return -ENODEV;
+       }
+
        hp_sdc.dev = NULL;
        hp_sdc.dev_err = 0;
 #if defined(__hppa__)
index 587398f..b587e2d 100644 (file)
@@ -50,7 +50,7 @@ MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
 MODULE_DESCRIPTION("Glue for onboard HIL MLC in HP-PARISC machines");
 MODULE_LICENSE("Dual BSD/GPL");
 
-struct hp_sdc_mlc_priv_s {
+static struct hp_sdc_mlc_priv_s {
        int emtestmode;
        hp_sdc_transaction trans;
        u8 tseq[16];
index 78eb784..fe732a5 100644 (file)
@@ -63,11 +63,20 @@ static inline void i8042_write_command(int val)
        outb(val, I8042_COMMAND_REG);
 }
 
-#if defined(__i386__) || defined(__x86_64__)
+#ifdef CONFIG_X86
 
 #include <linux/dmi.h>
 
 static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
+       {
+               /* AUX LOOP command does not raise AUX IRQ */
+               .ident = "Arima-Rioworks HDAMB",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "RIOWORKS"),
+                       DMI_MATCH(DMI_BOARD_NAME, "HDAMB"),
+                       DMI_MATCH(DMI_BOARD_VERSION, "Rev E"),
+               },
+       },
        {
                /* AUX LOOP command does not raise AUX IRQ */
                .ident = "ASUS P65UP5",
@@ -118,6 +127,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
                        DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"),
                },
        },
+       {
+               .ident = "Medion MAM 2070",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MAM 2070"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "5a"),
+               },
+       },
        { }
 };
 
@@ -291,17 +308,36 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
                        DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"),
                },
        },
+       {
+               .ident = "Acer Aspire 1360",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"),
+               },
+       },
+       {
+               .ident = "Gericom Bellagio",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Gericom"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"),
+               },
+       },
        { }
 };
 
-
-
+#ifdef CONFIG_PNP
+static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = {
+       {
+               .ident = "Intel MBO Desktop D845PESV",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_NAME, "D845PESV"),
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
+               },
+       },
+       { }
+};
 #endif
 
-#ifdef CONFIG_X86
-
-#include <linux/dmi.h>
-
 /*
  * Some Wistron based laptops need us to explicitly enable the 'Dritek
  * keyboard extension' to make their extra keys start generating scancodes.
@@ -330,6 +366,13 @@ static struct dmi_system_id __initdata i8042_dmi_dritek_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5680"),
                },
        },
+       {
+               .ident = "Acer Aspire 5720",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"),
+               },
+       },
        {
                .ident = "Acer Aspire 9110",
                .matches = {
@@ -356,7 +399,6 @@ static struct dmi_system_id __initdata i8042_dmi_dritek_table[] = {
 
 #endif /* CONFIG_X86 */
 
-
 #ifdef CONFIG_PNP
 #include <linux/pnp.h>
 
@@ -466,6 +508,11 @@ static int __init i8042_pnp_init(void)
        int pnp_data_busted = 0;
        int err;
 
+#ifdef CONFIG_X86
+       if (dmi_check_system(i8042_dmi_nopnp_table))
+               i8042_nopnp = 1;
+#endif
+
        if (i8042_nopnp) {
                printk(KERN_INFO "i8042: PNP detection disabled\n");
                return 0;
@@ -591,15 +638,13 @@ static int __init i8042_platform_init(void)
         i8042_reset = 1;
 #endif
 
-#if defined(__i386__) || defined(__x86_64__)
+#ifdef CONFIG_X86
        if (dmi_check_system(i8042_dmi_noloop_table))
                i8042_noloop = 1;
 
        if (dmi_check_system(i8042_dmi_nomux_table))
                i8042_nomux = 1;
-#endif
 
-#ifdef CONFIG_X86
        if (dmi_check_system(i8042_dmi_dritek_table))
                i8042_dritek = 1;
 #endif /* CONFIG_X86 */
index b819239..2b304c2 100644 (file)
@@ -26,15 +26,6 @@ MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
 MODULE_DESCRIPTION("PS/2 driver library");
 MODULE_LICENSE("GPL");
 
-/* Work structure to schedule execution of a command */
-struct ps2work {
-       struct work_struct work;
-       struct ps2dev *ps2dev;
-       int command;
-       unsigned char param[0];
-};
-
-
 /*
  * ps2_sendbyte() sends a byte to the device and waits for acknowledge.
  * It doesn't handle retransmission, though it could - because if there
@@ -245,49 +236,6 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
 }
 EXPORT_SYMBOL(ps2_command);
 
-/*
- * ps2_execute_scheduled_command() sends a command, previously scheduled by
- * ps2_schedule_command(), to a PS/2 device (keyboard, mouse, etc.)
- */
-
-static void ps2_execute_scheduled_command(struct work_struct *work)
-{
-       struct ps2work *ps2work = container_of(work, struct ps2work, work);
-
-       ps2_command(ps2work->ps2dev, ps2work->param, ps2work->command);
-       kfree(ps2work);
-}
-
-/*
- * ps2_schedule_command() allows to schedule delayed execution of a PS/2
- * command and can be used to issue a command from an interrupt or softirq
- * context.
- */
-
-int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int command)
-{
-       struct ps2work *ps2work;
-       int send = (command >> 12) & 0xf;
-       int receive = (command >> 8) & 0xf;
-
-       if (!(ps2work = kmalloc(sizeof(struct ps2work) + max(send, receive), GFP_ATOMIC)))
-               return -1;
-
-       memset(ps2work, 0, sizeof(struct ps2work));
-       ps2work->ps2dev = ps2dev;
-       ps2work->command = command;
-       memcpy(ps2work->param, param, send);
-       INIT_WORK(&ps2work->work, ps2_execute_scheduled_command);
-
-       if (!schedule_work(&ps2work->work)) {
-               kfree(ps2work);
-               return -1;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(ps2_schedule_command);
-
 /*
  * ps2_init() initializes ps2dev structure
  */
index d962a8d..e36a090 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: q40kbd.c,v 1.12 2002/02/02 22:26:44 vojtech Exp $
- *
  *  Copyright (c) 2000-2001 Vojtech Pavlik
  *
  *  Based on the work of:
@@ -49,7 +47,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Q40 PS/2 keyboard controller driver");
 MODULE_LICENSE("GPL");
 
-DEFINE_SPINLOCK(q40kbd_lock);
+static DEFINE_SPINLOCK(q40kbd_lock);
 static struct serio *q40kbd_port;
 static struct platform_device *q40kbd_device;
 
index 34c59d9..1567b77 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: rpckbd.c,v 1.7 2001/09/25 10:12:07 vojtech Exp $
- *
  *  Copyright (c) 2000-2001 Vojtech Pavlik
  *  Copyright (c) 2002 Russell King
  */
index 7f52938..78f2abb 100644 (file)
@@ -331,9 +331,10 @@ static void serio_handle_event(void)
 }
 
 /*
- * Remove all events that have been submitted for a given serio port.
+ * Remove all events that have been submitted for a given
+ * object, be it serio port or driver.
  */
-static void serio_remove_pending_events(struct serio *serio)
+static void serio_remove_pending_events(void *object)
 {
        struct list_head *node, *next;
        struct serio_event *event;
@@ -343,7 +344,7 @@ static void serio_remove_pending_events(struct serio *serio)
 
        list_for_each_safe(node, next, &serio_event_list) {
                event = list_entry(node, struct serio_event, node);
-               if (event->object == serio) {
+               if (event->object == object) {
                        list_del_init(node);
                        serio_free_event(event);
                }
@@ -837,7 +838,9 @@ void serio_unregister_driver(struct serio_driver *drv)
        struct serio *serio;
 
        mutex_lock(&serio_mutex);
+
        drv->manual_bind = 1;   /* so serio_find_driver ignores it */
+       serio_remove_pending_events(drv);
 
 start_over:
        list_for_each_entry(serio, &serio_list, node) {
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
new file mode 100644 (file)
index 0000000..0ed044d
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ * Xilinx XPS PS/2 device driver
+ *
+ * (c) 2005 MontaVista Software, Inc.
+ * (c) 2008 Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <linux/module.h>
+#include <linux/serio.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/io.h>
+
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+#define DRIVER_NAME            "xilinx_ps2"
+
+/* Register offsets for the xps2 device */
+#define XPS2_SRST_OFFSET       0x00000000 /* Software Reset register */
+#define XPS2_STATUS_OFFSET     0x00000004 /* Status register */
+#define XPS2_RX_DATA_OFFSET    0x00000008 /* Receive Data register */
+#define XPS2_TX_DATA_OFFSET    0x0000000C /* Transmit Data register */
+#define XPS2_GIER_OFFSET       0x0000002C /* Global Interrupt Enable reg */
+#define XPS2_IPISR_OFFSET      0x00000030 /* Interrupt Status register */
+#define XPS2_IPIER_OFFSET      0x00000038 /* Interrupt Enable register */
+
+/* Reset Register Bit Definitions */
+#define XPS2_SRST_RESET                0x0000000A /* Software Reset  */
+
+/* Status Register Bit Positions */
+#define XPS2_STATUS_RX_FULL    0x00000001 /* Receive Full  */
+#define XPS2_STATUS_TX_FULL    0x00000002 /* Transmit Full  */
+
+/* Bit definitions for ISR/IER registers. Both the registers have the same bit
+ * definitions and are only defined once. */
+#define XPS2_IPIXR_WDT_TOUT    0x00000001 /* Watchdog Timeout Interrupt */
+#define XPS2_IPIXR_TX_NOACK    0x00000002 /* Transmit No ACK Interrupt */
+#define XPS2_IPIXR_TX_ACK      0x00000004 /* Transmit ACK (Data) Interrupt */
+#define XPS2_IPIXR_RX_OVF      0x00000008 /* Receive Overflow Interrupt */
+#define XPS2_IPIXR_RX_ERR      0x00000010 /* Receive Error Interrupt */
+#define XPS2_IPIXR_RX_FULL     0x00000020 /* Receive Data Interrupt */
+
+/* Mask for all the Transmit Interrupts */
+#define XPS2_IPIXR_TX_ALL      (XPS2_IPIXR_TX_NOACK | XPS2_IPIXR_TX_ACK)
+
+/* Mask for all the Receive Interrupts */
+#define XPS2_IPIXR_RX_ALL      (XPS2_IPIXR_RX_OVF | XPS2_IPIXR_RX_ERR |  \
+                                       XPS2_IPIXR_RX_FULL)
+
+/* Mask for all the Interrupts */
+#define XPS2_IPIXR_ALL         (XPS2_IPIXR_TX_ALL | XPS2_IPIXR_RX_ALL |  \
+                                       XPS2_IPIXR_WDT_TOUT)
+
+/* Global Interrupt Enable mask */
+#define XPS2_GIER_GIE_MASK     0x80000000
+
+struct xps2data {
+       int irq;
+       u32 phys_addr;
+       u32 remap_size;
+       spinlock_t lock;
+       u8 rxb;                         /* Rx buffer */
+       void __iomem *base_address;     /* virt. address of control registers */
+       unsigned int dfl;
+       struct serio serio;             /* serio */
+};
+
+/************************************/
+/* XPS PS/2 data transmission calls */
+/************************************/
+
+/*
+ * xps2_recv() will attempt to receive a byte of data from the PS/2 port.
+ */
+static int xps2_recv(struct xps2data *drvdata, u8 *byte)
+{
+       u32 sr;
+       int status = -1;
+
+       /* If there is data available in the PS/2 receiver, read it */
+       sr = in_be32(drvdata->base_address + XPS2_STATUS_OFFSET);
+       if (sr & XPS2_STATUS_RX_FULL) {
+               *byte = in_be32(drvdata->base_address + XPS2_RX_DATA_OFFSET);
+               status = 0;
+       }
+
+       return status;
+}
+
+/*********************/
+/* Interrupt handler */
+/*********************/
+static irqreturn_t xps2_interrupt(int irq, void *dev_id)
+{
+       struct xps2data *drvdata = dev_id;
+       u32 intr_sr;
+       u8 c;
+       int status;
+
+       /* Get the PS/2 interrupts and clear them */
+       intr_sr = in_be32(drvdata->base_address + XPS2_IPISR_OFFSET);
+       out_be32(drvdata->base_address + XPS2_IPISR_OFFSET, intr_sr);
+
+       /* Check which interrupt is active */
+       if (intr_sr & XPS2_IPIXR_RX_OVF)
+               printk(KERN_WARNING "%s: receive overrun error\n",
+                       drvdata->serio.name);
+
+       if (intr_sr & XPS2_IPIXR_RX_ERR)
+               drvdata->dfl |= SERIO_PARITY;
+
+       if (intr_sr & (XPS2_IPIXR_TX_NOACK | XPS2_IPIXR_WDT_TOUT))
+               drvdata->dfl |= SERIO_TIMEOUT;
+
+       if (intr_sr & XPS2_IPIXR_RX_FULL) {
+               status = xps2_recv(drvdata, &drvdata->rxb);
+
+               /* Error, if a byte is not received */
+               if (status) {
+                       printk(KERN_ERR
+                               "%s: wrong rcvd byte count (%d)\n",
+                               drvdata->serio.name, status);
+               } else {
+                       c = drvdata->rxb;
+                       serio_interrupt(&drvdata->serio, c, drvdata->dfl);
+                       drvdata->dfl = 0;
+               }
+       }
+
+       if (intr_sr & XPS2_IPIXR_TX_ACK)
+               drvdata->dfl = 0;
+
+       return IRQ_HANDLED;
+}
+
+/*******************/
+/* serio callbacks */
+/*******************/
+
+/*
+ * sxps2_write() sends a byte out through the PS/2 interface.
+ */
+static int sxps2_write(struct serio *pserio, unsigned char c)
+{
+       struct xps2data *drvdata = pserio->port_data;
+       unsigned long flags;
+       u32 sr;
+       int status = -1;
+
+       spin_lock_irqsave(&drvdata->lock, flags);
+
+       /* If the PS/2 transmitter is empty send a byte of data */
+       sr = in_be32(drvdata->base_address + XPS2_STATUS_OFFSET);
+       if (!(sr & XPS2_STATUS_TX_FULL)) {
+               out_be32(drvdata->base_address + XPS2_TX_DATA_OFFSET, c);
+               status = 0;
+       }
+
+       spin_unlock_irqrestore(&drvdata->lock, flags);
+
+       return status;
+}
+
+/*
+ * sxps2_open() is called when a port is open by the higher layer.
+ */
+static int sxps2_open(struct serio *pserio)
+{
+       struct xps2data *drvdata = pserio->port_data;
+       int retval;
+
+       retval = request_irq(drvdata->irq, &xps2_interrupt, 0,
+                               DRIVER_NAME, drvdata);
+       if (retval) {
+               printk(KERN_ERR
+                       "%s: Couldn't allocate interrupt %d\n",
+                       drvdata->serio.name, drvdata->irq);
+               return retval;
+       }
+
+       /* start reception by enabling the interrupts */
+       out_be32(drvdata->base_address + XPS2_GIER_OFFSET, XPS2_GIER_GIE_MASK);
+       out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, XPS2_IPIXR_RX_ALL);
+       (void)xps2_recv(drvdata, &drvdata->rxb);
+
+       return 0;               /* success */
+}
+
+/*
+ * sxps2_close() frees the interrupt.
+ */
+static void sxps2_close(struct serio *pserio)
+{
+       struct xps2data *drvdata = pserio->port_data;
+
+       /* Disable the PS2 interrupts */
+       out_be32(drvdata->base_address + XPS2_GIER_OFFSET, 0x00);
+       out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0x00);
+       free_irq(drvdata->irq, drvdata);
+}
+
+/*********************/
+/* Device setup code */
+/*********************/
+
+static int xps2_setup(struct device *dev, struct resource *regs_res,
+                     struct resource *irq_res)
+{
+       struct xps2data *drvdata;
+       struct serio *serio;
+       unsigned long remap_size;
+       int retval;
+
+       if (!dev)
+               return -EINVAL;
+
+       if (!regs_res || !irq_res) {
+               dev_err(dev, "IO resource(s) not found\n");
+               return -EINVAL;
+       }
+
+       drvdata = kzalloc(sizeof(struct xps2data), GFP_KERNEL);
+       if (!drvdata) {
+               dev_err(dev, "Couldn't allocate device private record\n");
+               return -ENOMEM;
+       }
+
+       dev_set_drvdata(dev, drvdata);
+
+       spin_lock_init(&drvdata->lock);
+       drvdata->irq = irq_res->start;
+
+       remap_size = regs_res->end - regs_res->start + 1;
+       if (!request_mem_region(regs_res->start, remap_size, DRIVER_NAME)) {
+               dev_err(dev, "Couldn't lock memory region at 0x%08X\n",
+                       (unsigned int)regs_res->start);
+               retval = -EBUSY;
+               goto failed1;
+       }
+
+       /* Fill in configuration data and add them to the list */
+       drvdata->phys_addr = regs_res->start;
+       drvdata->remap_size = remap_size;
+       drvdata->base_address = ioremap(regs_res->start, remap_size);
+       if (drvdata->base_address == NULL) {
+               dev_err(dev, "Couldn't ioremap memory at 0x%08X\n",
+                       (unsigned int)regs_res->start);
+               retval = -EFAULT;
+               goto failed2;
+       }
+
+       /* Disable all the interrupts, just in case */
+       out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0);
+
+       /* Reset the PS2 device and abort any current transaction, to make sure
+        * we have the PS2 in a good state */
+       out_be32(drvdata->base_address + XPS2_SRST_OFFSET, XPS2_SRST_RESET);
+
+       dev_info(dev, "Xilinx PS2 at 0x%08X mapped to 0x%08X, irq=%d\n",
+               drvdata->phys_addr, (u32)drvdata->base_address, drvdata->irq);
+
+       serio = &drvdata->serio;
+       serio->id.type = SERIO_8042;
+       serio->write = sxps2_write;
+       serio->open = sxps2_open;
+       serio->close = sxps2_close;
+       serio->port_data = drvdata;
+       serio->dev.parent = dev;
+       snprintf(serio->name, sizeof(serio->name),
+                "Xilinx XPS PS/2 at %08X", drvdata->phys_addr);
+       snprintf(serio->phys, sizeof(serio->phys),
+                "xilinxps2/serio at %08X", drvdata->phys_addr);
+       serio_register_port(serio);
+
+       return 0;               /* success */
+
+failed2:
+       release_mem_region(regs_res->start, remap_size);
+failed1:
+       kfree(drvdata);
+       dev_set_drvdata(dev, NULL);
+
+       return retval;
+}
+
+/***************************/
+/* OF Platform Bus Support */
+/***************************/
+
+static int __devinit xps2_of_probe(struct of_device *ofdev, const struct
+                                  of_device_id * match)
+{
+       struct resource r_irq; /* Interrupt resources */
+       struct resource r_mem; /* IO mem resources */
+       int rc = 0;
+
+       printk(KERN_INFO "Device Tree Probing \'%s\'\n",
+                       ofdev->node->name);
+
+       /* Get iospace for the device */
+       rc = of_address_to_resource(ofdev->node, 0, &r_mem);
+       if (rc) {
+               dev_err(&ofdev->dev, "invalid address\n");
+               return rc;
+       }
+
+       /* Get IRQ for the device */
+       rc = of_irq_to_resource(ofdev->node, 0, &r_irq);
+       if (rc == NO_IRQ) {
+               dev_err(&ofdev->dev, "no IRQ found\n");
+               return rc;
+       }
+
+       return xps2_setup(&ofdev->dev, &r_mem, &r_irq);
+}
+
+static int __devexit xps2_of_remove(struct of_device *of_dev)
+{
+       struct device *dev = &of_dev->dev;
+       struct xps2data *drvdata;
+
+       if (!dev)
+               return -EINVAL;
+
+       drvdata = dev_get_drvdata(dev);
+
+       serio_unregister_port(&drvdata->serio);
+       iounmap(drvdata->base_address);
+       release_mem_region(drvdata->phys_addr, drvdata->remap_size);
+       kfree(drvdata);
+
+       dev_set_drvdata(dev, NULL);
+
+       return 0;               /* success */
+}
+
+/* Match table for of_platform binding */
+static struct of_device_id xps2_of_match[] __devinitdata = {
+       { .compatible = "xlnx,xps-ps2-1.00.a", },
+       { /* end of list */ },
+};
+MODULE_DEVICE_TABLE(of, xps2_of_match);
+
+static struct of_platform_driver xps2_of_driver = {
+       .name           = DRIVER_NAME,
+       .match_table    = xps2_of_match,
+       .probe          = xps2_of_probe,
+       .remove         = __devexit_p(xps2_of_remove),
+};
+
+static int __init xps2_init(void)
+{
+       return of_register_platform_driver(&xps2_of_driver);
+}
+
+static void __exit xps2_cleanup(void)
+{
+       of_unregister_platform_driver(&xps2_of_driver);
+}
+
+module_init(xps2_init);
+module_exit(xps2_cleanup);
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_DESCRIPTION("Xilinx XPS PS/2 driver");
+MODULE_LICENSE("GPL");
+
index b973d0e..570e0e8 100644 (file)
@@ -73,10 +73,10 @@ static void usb_acecad_irq(struct urb *urb)
                case -ENOENT:
                case -ESHUTDOWN:
                        /* this urb is terminated, clean up */
-                       dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+                       dbg("%s - urb shutting down with status: %d", __func__, urb->status);
                        return;
                default:
-                       dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+                       dbg("%s - nonzero urb status received: %d", __func__, urb->status);
                        goto resubmit;
        }
 
index 55c1134..8f037a1 100644 (file)
@@ -449,12 +449,12 @@ static void aiptek_irq(struct urb *urb)
        case -ESHUTDOWN:
                /* This urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d",
-                   __FUNCTION__, urb->status);
+                   __func__, urb->status);
                return;
 
        default:
                dbg("%s - nonzero urb status received: %d",
-                   __FUNCTION__, urb->status);
+                   __func__, urb->status);
                goto exit;
        }
 
@@ -813,7 +813,7 @@ exit:
        retval = usb_submit_urb(urb, GFP_ATOMIC);
        if (retval != 0) {
                err("%s - usb_submit_urb failed with result %d",
-                   __FUNCTION__, retval);
+                   __func__, retval);
        }
 }
 
index 1e748e4..b9b7a98 100644 (file)
@@ -863,7 +863,7 @@ static int gtco_probe(struct usb_interface *usbinterface,
        gtco->urbinfo = usb_alloc_urb(0, GFP_KERNEL);
        if (!gtco->urbinfo) {
                err("Failed to allocate URB");
-               return -ENOMEM;
+               error = -ENOMEM;
                goto err_free_buf;
        }
 
index f23f5a9..d89112f 100644 (file)
@@ -56,10 +56,10 @@ static void kbtab_irq(struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down with status: %d", __func__, urb->status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+               dbg("%s - nonzero urb status received: %d", __func__, urb->status);
                goto exit;
        }
 
@@ -88,7 +88,7 @@ static void kbtab_irq(struct urb *urb)
        retval = usb_submit_urb (urb, GFP_ATOMIC);
        if (retval)
                err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, retval);
+                    __func__, retval);
 }
 
 static struct usb_device_id kbtab_ids[] = {
index 706619d..ca62ec6 100644 (file)
@@ -105,7 +105,7 @@ struct wacom {
        struct urb *irq;
        struct wacom_wac * wacom_wac;
        struct mutex lock;
-       int open:1;
+       unsigned int open:1;
        char phys[32];
 };
 
index 71cc0c1..5fbc463 100644 (file)
@@ -56,10 +56,10 @@ static void wacom_sys_irq(struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down with status: %d", __func__, urb->status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+               dbg("%s - nonzero urb status received: %d", __func__, urb->status);
                goto exit;
        }
 
@@ -74,7 +74,7 @@ static void wacom_sys_irq(struct urb *urb)
        retval = usb_submit_urb (urb, GFP_ATOMIC);
        if (retval)
                err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, retval);
+                    __func__, retval);
 }
 
 void wacom_report_key(void *wcombo, unsigned int key_type, int key_data)
index 192513e..bf3d9a8 100644 (file)
@@ -56,7 +56,7 @@ static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo)
 static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo)
 {
        unsigned char *data = wacom->data;
-       int prox, id, pressure;
+       int prox, pressure;
 
        if (data[0] != 2) {
                dbg("wacom_pl_irq: received unknown report #%d", data[0]);
@@ -65,7 +65,7 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo)
 
        prox = data[1] & 0x40;
 
-       id = ERASER_DEVICE_ID;
+       wacom->id[0] = ERASER_DEVICE_ID;
        if (prox) {
 
                pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
@@ -99,10 +99,10 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo)
                if (wacom->tool[1] != BTN_TOOL_RUBBER) {
                        /* Unknown tool selected default to pen tool */
                        wacom->tool[1] = BTN_TOOL_PEN;
-                       id = STYLUS_DEVICE_ID;
+                       wacom->id[0] = STYLUS_DEVICE_ID;
                }
                wacom_report_key(wcombo, wacom->tool[1], prox); /* report in proximity for tool */
-               wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
+               wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */
                wacom_report_abs(wcombo, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
                wacom_report_abs(wcombo, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
                wacom_report_abs(wcombo, ABS_PRESSURE, pressure);
@@ -127,7 +127,6 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo)
 static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo)
 {
        unsigned char *data = wacom->data;
-       int id;
 
        if (data[0] != 2) {
                printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]);
@@ -137,13 +136,13 @@ static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo)
        if (data[1] & 0x04) {
                wacom_report_key(wcombo, BTN_TOOL_RUBBER, data[1] & 0x20);
                wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x08);
-               id = ERASER_DEVICE_ID;
+               wacom->id[0] = ERASER_DEVICE_ID;
        } else {
                wacom_report_key(wcombo, BTN_TOOL_PEN, data[1] & 0x20);
                wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01);
-               id = STYLUS_DEVICE_ID;
+               wacom->id[0] = STYLUS_DEVICE_ID;
        }
-       wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
+       wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */
        wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
        wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
        wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6]));
@@ -155,27 +154,26 @@ static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo)
 static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
 {
        unsigned char *data = wacom->data;
-       int x, y, id, rw;
+       int x, y, rw;
 
        if (data[0] != 2) {
                dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
                return 0;
        }
 
-       id = STYLUS_DEVICE_ID;
-       if ((data[1] & 0x80) && ((data[1] & 0x07) || data[2] || data[3] || data[4]
-                       || data[5] || data[6] || (data[7] & 0x07))) {
+       if (data[1] & 0x80) {
                /* in prox and not a pad data */
 
                switch ((data[1] >> 5) & 3) {
 
                        case 0: /* Pen */
                                wacom->tool[0] = BTN_TOOL_PEN;
+                               wacom->id[0] = STYLUS_DEVICE_ID;
                                break;
 
                        case 1: /* Rubber */
                                wacom->tool[0] = BTN_TOOL_RUBBER;
-                               id = ERASER_DEVICE_ID;
+                               wacom->id[0] = ERASER_DEVICE_ID;
                                break;
 
                        case 2: /* Mouse with wheel */
@@ -190,7 +188,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
 
                        case 3: /* Mouse without wheel */
                                wacom->tool[0] = BTN_TOOL_MOUSE;
-                               id = CURSOR_DEVICE_ID;
+                               wacom->id[0] = CURSOR_DEVICE_ID;
                                wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01);
                                wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02);
                                if (wacom->features->type == WACOM_G4 ||
@@ -210,9 +208,9 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
                        wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
                        wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04);
                }
-               wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
+               wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */
                wacom_report_key(wcombo, wacom->tool[0], 1);
-       } else if (!(data[1] & 0x90)) {
+       } else if (wacom->id[0]) {
                wacom_report_abs(wcombo, ABS_X, 0);
                wacom_report_abs(wcombo, ABS_Y, 0);
                if (wacom->tool[0] == BTN_TOOL_MOUSE) {
@@ -225,6 +223,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
                        wacom_report_key(wcombo, BTN_STYLUS, 0);
                        wacom_report_key(wcombo, BTN_STYLUS2, 0);
                }
+               wacom->id[0] = 0;
                wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
                wacom_report_key(wcombo, wacom->tool[0], 0);
        }
@@ -234,13 +233,13 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
            case WACOM_G4:
                if (data[7] & 0xf8) {
                        wacom_input_sync(wcombo); /* sync last event */
-                       wacom->id[1] = 1;
+                       wacom->id[1] = PAD_DEVICE_ID;
                        wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
                        wacom_report_key(wcombo, BTN_4, (data[7] & 0x80));
                        rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
                        wacom_report_rel(wcombo, REL_WHEEL, rw);
                        wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
-                       wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
+                       wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]);
                        wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
                } else if (wacom->id[1]) {
                        wacom_input_sync(wcombo); /* sync last event */
@@ -255,14 +254,14 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
            case WACOM_MO:
                if ((data[7] & 0xf8) || (data[8] & 0xff)) {
                        wacom_input_sync(wcombo); /* sync last event */
-                       wacom->id[1] = 1;
+                       wacom->id[1] = PAD_DEVICE_ID;
                        wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
                        wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
                        wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));
                        wacom_report_key(wcombo, BTN_5, (data[7] & 0x40));
                        wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f));
                        wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
-                       wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
+                       wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]);
                        wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
                } else if (wacom->id[1]) {
                        wacom_input_sync(wcombo); /* sync last event */
index 565ec71..e573665 100644 (file)
@@ -103,6 +103,18 @@ config TOUCHSCREEN_MTOUCH
          To compile this driver as a module, choose M here: the
          module will be called mtouch.
 
+config TOUCHSCREEN_INEXIO
+       tristate "iNexio serial touchscreens"
+       select SERIO
+       help
+         Say Y here if you have an iNexio serial touchscreen connected to
+         your system.
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called inexio.
+
 config TOUCHSCREEN_MK712
        tristate "ICS MicroClock MK712 touchscreen"
        help
@@ -134,6 +146,18 @@ config TOUCHSCREEN_HP7XX
          To compile this driver as a module, choose M here: the
          module will be called jornada720_ts.
 
+config TOUCHSCREEN_HTCPEN
+       tristate "HTC Shift X9500 touchscreen"
+       depends on ISA
+       help
+         Say Y here if you have an HTC Shift UMPC also known as HTC X9500
+         Clio / Shangrila and want to support the built-in touchscreen.
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called htcpen.
+
 config TOUCHSCREEN_PENMOUNT
        tristate "Penmount serial touchscreen"
        select SERIO
@@ -146,6 +170,17 @@ config TOUCHSCREEN_PENMOUNT
          To compile this driver as a module, choose M here: the
          module will be called penmount.
 
+config TOUCHSCREEN_MIGOR
+       tristate "Renesas MIGO-R touchscreen"
+       depends on SH_MIGOR && I2C
+       help
+         Say Y here to enable MIGO-R touchscreen support.
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called migor_ts.
+
 config TOUCHSCREEN_TOUCHRIGHT
        tristate "Touchright serial touchscreen"
        select SERIO
@@ -316,4 +351,15 @@ config TOUCHSCREEN_USB_GOTOP
        bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EMBEDDED
        depends on TOUCHSCREEN_USB_COMPOSITE
 
+config TOUCHSCREEN_TOUCHIT213
+       tristate "Sahara TouchIT-213 touchscreen"
+       select SERIO
+       help
+         Say Y here if you have a Sahara TouchIT-213 Tablet PC.
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called touchit213.
+
 endif
index 3c096d7..39a804c 100644 (file)
@@ -12,12 +12,16 @@ obj-$(CONFIG_TOUCHSCREEN_CORGI)             += corgi_ts.o
 obj-$(CONFIG_TOUCHSCREEN_GUNZE)                += gunze.o
 obj-$(CONFIG_TOUCHSCREEN_ELO)          += elo.o
 obj-$(CONFIG_TOUCHSCREEN_FUJITSU)      += fujitsu_ts.o
+obj-$(CONFIG_TOUCHSCREEN_INEXIO)       += inexio.o
+obj-$(CONFIG_TOUCHSCREEN_MIGOR)                += migor_ts.o
 obj-$(CONFIG_TOUCHSCREEN_MTOUCH)       += mtouch.o
 obj-$(CONFIG_TOUCHSCREEN_MK712)                += mk712.o
 obj-$(CONFIG_TOUCHSCREEN_HP600)                += hp680_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_HP7XX)                += jornada720_ts.o
+obj-$(CONFIG_TOUCHSCREEN_HTCPEN)       += htcpen.o
 obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)        += usbtouchscreen.o
 obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)     += penmount.o
+obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)   += touchit213.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)   += touchright.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)     += touchwin.o
 obj-$(CONFIG_TOUCHSCREEN_UCB1400)      += ucb1400_ts.o
index a48a158..a54f90e 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: gunze.c,v 1.12 2001/09/25 10:12:07 vojtech Exp $
- *
  *  Copyright (c) 2000-2001 Vojtech Pavlik
  */
 
index 28ae15e..4f86081 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: h3600_ts_input.c,v 1.4 2002/01/23 06:39:37 jsimmons Exp $
- *
  *  Copyright (c) 2001 "Crazy" James Simmons jsimmons@transvirtual.com
  *
  *  Sponsored by Transvirtual Technology.
diff --git a/drivers/input/touchscreen/htcpen.c b/drivers/input/touchscreen/htcpen.c
new file mode 100644 (file)
index 0000000..62811de
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * HTC Shift touchscreen driver
+ *
+ * Copyright (C) 2008 Pau Oliva Fora <pof@eslack.org>
+ *
+ * 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.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/isa.h>
+#include <linux/ioport.h>
+#include <linux/dmi.h>
+
+MODULE_AUTHOR("Pau Oliva Fora <pau@eslack.org>");
+MODULE_DESCRIPTION("HTC Shift touchscreen driver");
+MODULE_LICENSE("GPL");
+
+#define HTCPEN_PORT_IRQ_CLEAR  0x068
+#define HTCPEN_PORT_INIT       0x06c
+#define HTCPEN_PORT_INDEX      0x0250
+#define HTCPEN_PORT_DATA       0x0251
+#define HTCPEN_IRQ             3
+
+#define DEVICE_ENABLE          0xa2
+#define DEVICE_DISABLE         0xa3
+
+#define X_INDEX                        3
+#define Y_INDEX                        5
+#define TOUCH_INDEX            0xb
+#define LSB_XY_INDEX           0xc
+#define X_AXIS_MAX             2040
+#define Y_AXIS_MAX             2040
+
+static int invert_x;
+module_param(invert_x, bool, 0644);
+MODULE_PARM_DESC(invert_x, "If set, X axis is inverted");
+static int invert_y;
+module_param(invert_y, bool, 0644);
+MODULE_PARM_DESC(invert_y, "If set, Y axis is inverted");
+
+static struct pnp_device_id pnp_ids[] = {
+       { .id = "PNP0cc0" },
+       { .id = "" }
+};
+MODULE_DEVICE_TABLE(pnp, pnp_ids);
+
+static irqreturn_t htcpen_interrupt(int irq, void *handle)
+{
+       struct input_dev *htcpen_dev = handle;
+       unsigned short x, y, xy;
+
+       /* 0 = press; 1 = release */
+       outb_p(TOUCH_INDEX, HTCPEN_PORT_INDEX);
+
+       if (inb_p(HTCPEN_PORT_DATA)) {
+               input_report_key(htcpen_dev, BTN_TOUCH, 0);
+       } else {
+               outb_p(X_INDEX, HTCPEN_PORT_INDEX);
+               x = inb_p(HTCPEN_PORT_DATA);
+
+               outb_p(Y_INDEX, HTCPEN_PORT_INDEX);
+               y = inb_p(HTCPEN_PORT_DATA);
+
+               outb_p(LSB_XY_INDEX, HTCPEN_PORT_INDEX);
+               xy = inb_p(HTCPEN_PORT_DATA);
+
+               /* get high resolution value of X and Y using LSB */
+               x = X_AXIS_MAX - ((x * 8) + ((xy >> 4) & 0xf));
+               y = (y * 8) + (xy & 0xf);
+               if (invert_x)
+                       x = X_AXIS_MAX - x;
+               if (invert_y)
+                       y = Y_AXIS_MAX - y;
+
+               if (x != X_AXIS_MAX && x != 0) {
+                       input_report_key(htcpen_dev, BTN_TOUCH, 1);
+                       input_report_abs(htcpen_dev, ABS_X, x);
+                       input_report_abs(htcpen_dev, ABS_Y, y);
+               }
+       }
+
+       input_sync(htcpen_dev);
+
+       inb_p(HTCPEN_PORT_IRQ_CLEAR);
+
+       return IRQ_HANDLED;
+}
+
+static int htcpen_open(struct input_dev *dev)
+{
+       outb_p(DEVICE_ENABLE, HTCPEN_PORT_INIT);
+
+       return 0;
+}
+
+static void htcpen_close(struct input_dev *dev)
+{
+       outb_p(DEVICE_DISABLE, HTCPEN_PORT_INIT);
+       synchronize_irq(HTCPEN_IRQ);
+}
+
+static int __devinit htcpen_isa_probe(struct device *dev, unsigned int id)
+{
+       struct input_dev *htcpen_dev;
+       int err = -EBUSY;
+
+       if (!request_region(HTCPEN_PORT_IRQ_CLEAR, 1, "htcpen")) {
+               printk(KERN_ERR "htcpen: unable to get IO region 0x%x\n",
+                       HTCPEN_PORT_IRQ_CLEAR);
+               goto request_region1_failed;
+       }
+
+       if (!request_region(HTCPEN_PORT_INIT, 1, "htcpen")) {
+               printk(KERN_ERR "htcpen: unable to get IO region 0x%x\n",
+                       HTCPEN_PORT_INIT);
+               goto request_region2_failed;
+       }
+
+       if (!request_region(HTCPEN_PORT_INDEX, 2, "htcpen")) {
+               printk(KERN_ERR "htcpen: unable to get IO region 0x%x\n",
+                       HTCPEN_PORT_INDEX);
+               goto request_region3_failed;
+       }
+
+       htcpen_dev = input_allocate_device();
+       if (!htcpen_dev) {
+               printk(KERN_ERR "htcpen: can't allocate device\n");
+               err = -ENOMEM;
+               goto input_alloc_failed;
+       }
+
+       htcpen_dev->name = "HTC Shift EC TouchScreen";
+       htcpen_dev->id.bustype = BUS_ISA;
+
+       htcpen_dev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
+       htcpen_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+       input_set_abs_params(htcpen_dev, ABS_X, 0, X_AXIS_MAX, 0, 0);
+       input_set_abs_params(htcpen_dev, ABS_Y, 0, Y_AXIS_MAX, 0, 0);
+
+       htcpen_dev->open = htcpen_open;
+       htcpen_dev->close = htcpen_close;
+
+       err = request_irq(HTCPEN_IRQ, htcpen_interrupt, 0, "htcpen",
+                       htcpen_dev);
+       if (err) {
+               printk(KERN_ERR "htcpen: irq busy\n");
+               goto request_irq_failed;
+       }
+
+       inb_p(HTCPEN_PORT_IRQ_CLEAR);
+
+       err = input_register_device(htcpen_dev);
+       if (err)
+               goto input_register_failed;
+
+       dev_set_drvdata(dev, htcpen_dev);
+
+       return 0;
+
+ input_register_failed:
+       free_irq(HTCPEN_IRQ, htcpen_dev);
+ request_irq_failed:
+       input_free_device(htcpen_dev);
+ input_alloc_failed:
+       release_region(HTCPEN_PORT_INDEX, 2);
+ request_region3_failed:
+       release_region(HTCPEN_PORT_INIT, 1);
+ request_region2_failed:
+       release_region(HTCPEN_PORT_IRQ_CLEAR, 1);
+ request_region1_failed:
+       return err;
+}
+
+static int __devexit htcpen_isa_remove(struct device *dev, unsigned int id)
+{
+       struct input_dev *htcpen_dev = dev_get_drvdata(dev);
+
+       input_unregister_device(htcpen_dev);
+
+       free_irq(HTCPEN_IRQ, htcpen_dev);
+
+       release_region(HTCPEN_PORT_INDEX, 2);
+       release_region(HTCPEN_PORT_INIT, 1);
+       release_region(HTCPEN_PORT_IRQ_CLEAR, 1);
+
+       dev_set_drvdata(dev, NULL);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int htcpen_isa_suspend(struct device *dev, unsigned int n,
+                               pm_message_t state)
+{
+       outb_p(DEVICE_DISABLE, HTCPEN_PORT_INIT);
+
+       return 0;
+}
+
+static int htcpen_isa_resume(struct device *dev, unsigned int n)
+{
+       outb_p(DEVICE_ENABLE, HTCPEN_PORT_INIT);
+
+       return 0;
+}
+#endif
+
+static struct isa_driver htcpen_isa_driver = {
+       .probe          = htcpen_isa_probe,
+       .remove         = __devexit_p(htcpen_isa_remove),
+#ifdef CONFIG_PM
+       .suspend        = htcpen_isa_suspend,
+       .resume         = htcpen_isa_resume,
+#endif
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = "htcpen",
+       }
+};
+
+static struct dmi_system_id __initdata htcshift_dmi_table[] = {
+       {
+               .ident = "Shift",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "High Tech Computer Corp"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Shift"),
+               },
+       },
+       { }
+};
+
+static int __init htcpen_isa_init(void)
+{
+       if (!dmi_check_system(htcshift_dmi_table))
+               return -ENODEV;
+
+       return isa_register_driver(&htcpen_isa_driver, 1);
+}
+
+static void __exit htcpen_isa_exit(void)
+{
+       isa_unregister_driver(&htcpen_isa_driver);
+}
+
+module_init(htcpen_isa_init);
+module_exit(htcpen_isa_exit);
diff --git a/drivers/input/touchscreen/inexio.c b/drivers/input/touchscreen/inexio.c
new file mode 100644 (file)
index 0000000..192ade0
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * iNexio serial touchscreen driver
+ *
+ * Copyright (c) 2008 Richard Lemon
+ * Based on the mtouch driver (c) Vojtech Pavlik and Dan Streetman
+ *
+ */
+
+/*
+ * 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.
+ */
+
+/*
+ * 2008/06/19 Richard Lemon <richard@codelemon.com>
+ *   Copied mtouch.c and edited for iNexio protocol
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+
+#define DRIVER_DESC    "iNexio serial touchscreen driver"
+
+MODULE_AUTHOR("Richard Lemon <richard@codelemon.com>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/*
+ * Definitions & global arrays.
+ */
+
+#define INEXIO_FORMAT_TOUCH_BIT 0x01
+#define INEXIO_FORMAT_LENGTH 5
+#define INEXIO_RESPONSE_BEGIN_BYTE 0x80
+
+/* todo: check specs for max length of all responses */
+#define INEXIO_MAX_LENGTH 16
+
+#define INEXIO_MIN_XC 0
+#define INEXIO_MAX_XC 0x3fff
+#define INEXIO_MIN_YC 0
+#define INEXIO_MAX_YC 0x3fff
+
+#define INEXIO_GET_XC(data) (((data[1])<<7) | data[2])
+#define INEXIO_GET_YC(data) (((data[3])<<7) | data[4])
+#define INEXIO_GET_TOUCHED(data) (INEXIO_FORMAT_TOUCH_BIT & data[0])
+
+/*
+ * Per-touchscreen data.
+ */
+
+struct inexio {
+       struct input_dev *dev;
+       struct serio *serio;
+       int idx;
+       unsigned char data[INEXIO_MAX_LENGTH];
+       char phys[32];
+};
+
+static void inexio_process_data(struct inexio *pinexio)
+{
+       struct input_dev *dev = pinexio->dev;
+
+       if (INEXIO_FORMAT_LENGTH == ++pinexio->idx) {
+               input_report_abs(dev, ABS_X, INEXIO_GET_XC(pinexio->data));
+               input_report_abs(dev, ABS_Y, INEXIO_GET_YC(pinexio->data));
+               input_report_key(dev, BTN_TOUCH, INEXIO_GET_TOUCHED(pinexio->data));
+               input_sync(dev);
+
+               pinexio->idx = 0;
+       }
+}
+
+static irqreturn_t inexio_interrupt(struct serio *serio,
+               unsigned char data, unsigned int flags)
+{
+       struct inexio* pinexio = serio_get_drvdata(serio);
+
+       pinexio->data[pinexio->idx] = data;
+
+       if (INEXIO_RESPONSE_BEGIN_BYTE&pinexio->data[0])
+               inexio_process_data(pinexio);
+       else
+               printk(KERN_DEBUG "inexio.c: unknown/unsynchronized data from device, byte %x\n",pinexio->data[0]);
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * inexio_disconnect() is the opposite of inexio_connect()
+ */
+
+static void inexio_disconnect(struct serio *serio)
+{
+       struct inexio* pinexio = serio_get_drvdata(serio);
+
+       input_get_device(pinexio->dev);
+       input_unregister_device(pinexio->dev);
+       serio_close(serio);
+       serio_set_drvdata(serio, NULL);
+       input_put_device(pinexio->dev);
+       kfree(pinexio);
+}
+
+/*
+ * inexio_connect() is the routine that is called when someone adds a
+ * new serio device that supports iNexio protocol and registers it as
+ * an input device. This is usually accomplished using inputattach.
+ */
+
+static int inexio_connect(struct serio *serio, struct serio_driver *drv)
+{
+       struct inexio *pinexio;
+       struct input_dev *input_dev;
+       int err;
+
+       pinexio = kzalloc(sizeof(struct inexio), GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!pinexio || !input_dev) {
+               err = -ENOMEM;
+               goto fail1;
+       }
+
+       pinexio->serio = serio;
+       pinexio->dev = input_dev;
+       snprintf(pinexio->phys, sizeof(pinexio->phys), "%s/input0", serio->phys);
+
+       input_dev->name = "iNexio Serial TouchScreen";
+       input_dev->phys = pinexio->phys;
+       input_dev->id.bustype = BUS_RS232;
+       input_dev->id.vendor = SERIO_INEXIO;
+       input_dev->id.product = 0;
+       input_dev->id.version = 0x0001;
+       input_dev->dev.parent = &serio->dev;
+       input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+       input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+       input_set_abs_params(pinexio->dev, ABS_X, INEXIO_MIN_XC, INEXIO_MAX_XC, 0, 0);
+       input_set_abs_params(pinexio->dev, ABS_Y, INEXIO_MIN_YC, INEXIO_MAX_YC, 0, 0);
+
+       serio_set_drvdata(serio, pinexio);
+
+       err = serio_open(serio, drv);
+       if (err)
+               goto fail2;
+
+       err = input_register_device(pinexio->dev);
+       if (err)
+               goto fail3;
+
+       return 0;
+
+ fail3:        serio_close(serio);
+ fail2:        serio_set_drvdata(serio, NULL);
+ fail1:        input_free_device(input_dev);
+       kfree(pinexio);
+       return err;
+}
+
+/*
+ * The serio driver structure.
+ */
+
+static struct serio_device_id inexio_serio_ids[] = {
+       {
+               .type   = SERIO_RS232,
+               .proto  = SERIO_INEXIO,
+               .id     = SERIO_ANY,
+               .extra  = SERIO_ANY,
+       },
+       { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, inexio_serio_ids);
+
+static struct serio_driver inexio_drv = {
+       .driver         = {
+               .name   = "inexio",
+       },
+       .description    = DRIVER_DESC,
+       .id_table       = inexio_serio_ids,
+       .interrupt      = inexio_interrupt,
+       .connect        = inexio_connect,
+       .disconnect     = inexio_disconnect,
+};
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+static int __init inexio_init(void)
+{
+       return serio_register_driver(&inexio_drv);
+}
+
+static void __exit inexio_exit(void)
+{
+       serio_unregister_driver(&inexio_drv);
+}
+
+module_init(inexio_init);
+module_exit(inexio_exit);
diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c
new file mode 100644 (file)
index 0000000..c1cd99d
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * Touch Screen driver for Renesas MIGO-R Platform
+ *
+ * Copyright (c) 2008 Magnus Damm
+ * Copyright (c) 2007 Ujjwal Pande <ujjwal@kenati.com>,
+ *  Kenati Technologies Pvt Ltd.
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU  General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <linux/i2c.h>
+#include <linux/timer.h>
+
+#define EVENT_PENDOWN 1
+#define EVENT_REPEAT  2
+#define EVENT_PENUP   3
+
+struct migor_ts_priv {
+       struct i2c_client *client;
+       struct input_dev *input;
+       struct delayed_work work;
+       int irq;
+};
+
+static const u_int8_t migor_ts_ena_seq[17] = { 0x33, 0x22, 0x11,
+                                              0x01, 0x06, 0x07, };
+static const u_int8_t migor_ts_dis_seq[17] = { };
+
+static void migor_ts_poscheck(struct work_struct *work)
+{
+       struct migor_ts_priv *priv = container_of(work,
+                                                 struct migor_ts_priv,
+                                                 work.work);
+       unsigned short xpos, ypos;
+       unsigned char event;
+       u_int8_t buf[16];
+
+       memset(buf, 0, sizeof(buf));
+
+       /* Set Index 0 */
+       buf[0] = 0;
+       if (i2c_master_send(priv->client, buf, 1) != 1) {
+               dev_err(&priv->client->dev, "Unable to write i2c index\n");
+               goto out;
+       }
+
+       /* Now do Page Read */
+       if (i2c_master_recv(priv->client, buf, sizeof(buf)) != sizeof(buf)) {
+               dev_err(&priv->client->dev, "Unable to read i2c page\n");
+               goto out;
+       }
+
+       ypos = ((buf[9] & 0x03) << 8 | buf[8]);
+       xpos = ((buf[11] & 0x03) << 8 | buf[10]);
+       event = buf[12];
+
+       if (event == EVENT_PENDOWN || event == EVENT_REPEAT) {
+               input_report_key(priv->input, BTN_TOUCH, 1);
+               input_report_abs(priv->input, ABS_X, ypos); /*X-Y swap*/
+               input_report_abs(priv->input, ABS_Y, xpos);
+               input_sync(priv->input);
+       } else if (event == EVENT_PENUP) {
+               input_report_key(priv->input, BTN_TOUCH, 0);
+               input_sync(priv->input);
+       }
+ out:
+       enable_irq(priv->irq);
+}
+
+static irqreturn_t migor_ts_isr(int irq, void *dev_id)
+{
+       struct migor_ts_priv *priv = dev_id;
+
+       /* the touch screen controller chip is hooked up to the cpu
+        * using i2c and a single interrupt line. the interrupt line
+        * is pulled low whenever someone taps the screen. to deassert
+        * the interrupt line we need to acknowledge the interrupt by
+        * communicating with the controller over the slow i2c bus.
+        *
+        * we can't acknowledge from interrupt context since the i2c
+        * bus controller may sleep, so we just disable the interrupt
+        * here and handle the acknowledge using delayed work.
+        */
+
+       disable_irq_nosync(irq);
+       schedule_delayed_work(&priv->work, HZ / 20);
+
+       return IRQ_HANDLED;
+}
+
+
+static int migor_ts_open(struct input_dev *dev)
+{
+       struct migor_ts_priv *priv = input_get_drvdata(dev);
+       struct i2c_client *client = priv->client;
+       int count;
+
+       /* enable controller */
+       count = i2c_master_send(client, migor_ts_ena_seq,
+                               sizeof(migor_ts_ena_seq));
+       if (count != sizeof(migor_ts_ena_seq)) {
+               dev_err(&client->dev, "Unable to enable touchscreen.\n");
+               return -ENXIO;
+       }
+
+       return 0;
+}
+
+static void migor_ts_close(struct input_dev *dev)
+{
+       struct migor_ts_priv *priv = input_get_drvdata(dev);
+       struct i2c_client *client = priv->client;
+
+       disable_irq(priv->irq);
+
+       /* cancel pending work and wait for migor_ts_poscheck() to finish */
+       if (cancel_delayed_work_sync(&priv->work)) {
+               /*
+                * if migor_ts_poscheck was canceled we need to enable IRQ
+                * here to balance disable done in migor_ts_isr.
+                */
+               enable_irq(priv->irq);
+       }
+
+       /* disable controller */
+       i2c_master_send(client, migor_ts_dis_seq, sizeof(migor_ts_dis_seq));
+
+       enable_irq(priv->irq);
+}
+
+static int migor_ts_probe(struct i2c_client *client,
+                         const struct i2c_device_id *idp)
+{
+       struct migor_ts_priv *priv;
+       struct input_dev *input;
+       int error;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv) {
+               dev_err(&client->dev, "failed to allocate driver data\n");
+               error = -ENOMEM;
+               goto err0;
+       }
+
+       dev_set_drvdata(&client->dev, priv);
+
+       input = input_allocate_device();
+       if (!input) {
+               dev_err(&client->dev, "Failed to allocate input device.\n");
+               error = -ENOMEM;
+               goto err1;
+       }
+
+       input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+       input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+       input_set_abs_params(input, ABS_X, 95, 955, 0, 0);
+       input_set_abs_params(input, ABS_Y, 85, 935, 0, 0);
+
+       input->name = client->driver_name;
+       input->id.bustype = BUS_I2C;
+       input->dev.parent = &client->dev;
+
+       input->open = migor_ts_open;
+       input->close = migor_ts_close;
+
+       input_set_drvdata(input, priv);
+
+       priv->client = client;
+       priv->input = input;
+       INIT_DELAYED_WORK(&priv->work, migor_ts_poscheck);
+       priv->irq = client->irq;
+
+       error = input_register_device(input);
+       if (error)
+               goto err1;
+
+       error = request_irq(priv->irq, migor_ts_isr, IRQF_TRIGGER_LOW,
+                           client->driver_name, priv);
+       if (error) {
+               dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
+               goto err2;
+       }
+
+       return 0;
+
+ err2:
+       input_unregister_device(input);
+       input = NULL; /* so we dont try to free it below */
+ err1:
+       input_free_device(input);
+       kfree(priv);
+ err0:
+       dev_set_drvdata(&client->dev, NULL);
+       return error;
+}
+
+static int migor_ts_remove(struct i2c_client *client)
+{
+       struct migor_ts_priv *priv = dev_get_drvdata(&client->dev);
+
+       free_irq(priv->irq, priv);
+       input_unregister_device(priv->input);
+       kfree(priv);
+
+       dev_set_drvdata(&client->dev, NULL);
+
+       return 0;
+}
+
+static struct i2c_driver migor_ts_driver = {
+       .driver = {
+               .name = "migor_ts",
+       },
+       .probe = migor_ts_probe,
+       .remove = migor_ts_remove,
+};
+
+static int __init migor_ts_init(void)
+{
+       return i2c_add_driver(&migor_ts_driver);
+}
+
+static void __exit migor_ts_exit(void)
+{
+       i2c_del_driver(&migor_ts_driver);
+}
+
+MODULE_DESCRIPTION("MigoR Touchscreen driver");
+MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
+MODULE_LICENSE("GPL");
+
+module_init(migor_ts_init);
+module_exit(migor_ts_exit);
diff --git a/drivers/input/touchscreen/touchit213.c b/drivers/input/touchscreen/touchit213.c
new file mode 100644 (file)
index 0000000..d1297ba
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * Sahara TouchIT-213 serial touchscreen driver
+ *
+ * Copyright (c) 2007-2008 Claudio Nieder <private@claudio.ch>
+ *
+ * Based on Touchright driver (drivers/input/touchscreen/touchright.c)
+ * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com>
+ * Copyright (c) 2004 Vojtech Pavlik
+ * and Dan Streetman <ddstreet@ieee.org>
+ */
+
+/*
+ * 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.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+
+#define DRIVER_DESC    "Sahara TouchIT-213 serial touchscreen driver"
+
+MODULE_AUTHOR("Claudio Nieder <private@claudio.ch>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/*
+ * Definitions & global arrays.
+ */
+
+/*
+ * Data is received through COM1 at 9600bit/s,8bit,no parity in packets
+ * of 5 byte each.
+ *
+ *   +--------+   +--------+   +--------+   +--------+   +--------+
+ *   |1000000p|   |0xxxxxxx|   |0xxxxxxx|   |0yyyyyyy|   |0yyyyyyy|
+ *   +--------+   +--------+   +--------+   +--------+   +--------+
+ *                    MSB          LSB          MSB          LSB
+ *
+ * The value of p is 1 as long as the screen is touched and 0 when
+ * reporting the location where touching stopped, e.g. where the pen was
+ * lifted from the screen.
+ *
+ * When holding the screen in landscape mode as the BIOS text output is
+ * presented, x is the horizontal axis with values growing from left to
+ * right and y is the vertical axis with values growing from top to
+ * bottom.
+ *
+ * When holding the screen in portrait mode with the Sahara logo in its
+ * correct position, x ist the vertical axis with values growing from
+ * top to bottom and y is the horizontal axis with values growing from
+ * right to left.
+ */
+
+#define T213_FORMAT_TOUCH_BIT  0x01
+#define T213_FORMAT_STATUS_BYTE        0x80
+#define T213_FORMAT_STATUS_MASK        ~T213_FORMAT_TOUCH_BIT
+
+/*
+ * On my Sahara Touch-IT 213 I have observed x values from 0 to 0x7f0
+ * and y values from 0x1d to 0x7e9, so the actual measurement is
+ * probably done with an 11 bit precision.
+ */
+#define T213_MIN_XC 0
+#define T213_MAX_XC 0x07ff
+#define T213_MIN_YC 0
+#define T213_MAX_YC 0x07ff
+
+/*
+ * Per-touchscreen data.
+ */
+
+struct touchit213 {
+       struct input_dev *dev;
+       struct serio *serio;
+       int idx;
+       unsigned char csum;
+       unsigned char data[5];
+       char phys[32];
+};
+
+static irqreturn_t touchit213_interrupt(struct serio *serio,
+               unsigned char data, unsigned int flags)
+{
+       struct touchit213 *touchit213 = serio_get_drvdata(serio);
+       struct input_dev *dev = touchit213->dev;
+
+       touchit213->data[touchit213->idx] = data;
+
+       switch (touchit213->idx++) {
+       case 0:
+               if ((touchit213->data[0] & T213_FORMAT_STATUS_MASK) !=
+                               T213_FORMAT_STATUS_BYTE) {
+                       pr_debug("unsynchronized data: 0x%02x\n", data);
+                       touchit213->idx = 0;
+               }
+               break;
+
+       case 4:
+               touchit213->idx = 0;
+               input_report_abs(dev, ABS_X,
+                       (touchit213->data[1] << 7) | touchit213->data[2]);
+               input_report_abs(dev, ABS_Y,
+                       (touchit213->data[3] << 7) | touchit213->data[4]);
+               input_report_key(dev, BTN_TOUCH,
+                       touchit213->data[0] & T213_FORMAT_TOUCH_BIT);
+               input_sync(dev);
+               break;
+       }
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * touchit213_disconnect() is the opposite of touchit213_connect()
+ */
+
+static void touchit213_disconnect(struct serio *serio)
+{
+       struct touchit213 *touchit213 = serio_get_drvdata(serio);
+
+       input_get_device(touchit213->dev);
+       input_unregister_device(touchit213->dev);
+       serio_close(serio);
+       serio_set_drvdata(serio, NULL);
+       input_put_device(touchit213->dev);
+       kfree(touchit213);
+}
+
+/*
+ * touchit213_connect() is the routine that is called when someone adds a
+ * new serio device that supports the Touchright protocol and registers it as
+ * an input device.
+ */
+
+static int touchit213_connect(struct serio *serio, struct serio_driver *drv)
+{
+       struct touchit213 *touchit213;
+       struct input_dev *input_dev;
+       int err;
+
+       touchit213 = kzalloc(sizeof(struct touchit213), GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!touchit213 || !input_dev) {
+               err = -ENOMEM;
+               goto fail1;
+       }
+
+       touchit213->serio = serio;
+       touchit213->dev = input_dev;
+       snprintf(touchit213->phys, sizeof(touchit213->phys),
+                "%s/input0", serio->phys);
+
+       input_dev->name = "Sahara Touch-iT213 Serial TouchScreen";
+       input_dev->phys = touchit213->phys;
+       input_dev->id.bustype = BUS_RS232;
+       input_dev->id.vendor = SERIO_TOUCHIT213;
+       input_dev->id.product = 0;
+       input_dev->id.version = 0x0100;
+       input_dev->dev.parent = &serio->dev;
+       input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+       input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+       input_set_abs_params(touchit213->dev, ABS_X,
+                            T213_MIN_XC, T213_MAX_XC, 0, 0);
+       input_set_abs_params(touchit213->dev, ABS_Y,
+                            T213_MIN_YC, T213_MAX_YC, 0, 0);
+
+       serio_set_drvdata(serio, touchit213);
+
+       err = serio_open(serio, drv);
+       if (err)
+               goto fail2;
+
+       err = input_register_device(touchit213->dev);
+       if (err)
+               goto fail3;
+
+       return 0;
+
+ fail3:        serio_close(serio);
+ fail2:        serio_set_drvdata(serio, NULL);
+ fail1:        input_free_device(input_dev);
+       kfree(touchit213);
+       return err;
+}
+
+/*
+ * The serio driver structure.
+ */
+
+static struct serio_device_id touchit213_serio_ids[] = {
+       {
+               .type   = SERIO_RS232,
+               .proto  = SERIO_TOUCHIT213,
+               .id     = SERIO_ANY,
+               .extra  = SERIO_ANY,
+       },
+       { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, touchit213_serio_ids);
+
+static struct serio_driver touchit213_drv = {
+       .driver         = {
+               .name   = "touchit213",
+       },
+       .description    = DRIVER_DESC,
+       .id_table       = touchit213_serio_ids,
+       .interrupt      = touchit213_interrupt,
+       .connect        = touchit213_connect,
+       .disconnect     = touchit213_disconnect,
+};
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+static int __init touchit213_init(void)
+{
+       return serio_register_driver(&touchit213_drv);
+}
+
+static void __exit touchit213_exit(void)
+{
+       serio_unregister_driver(&touchit213_drv);
+}
+
+module_init(touchit213_init);
+module_exit(touchit213_exit);
index 3a0a8ca..fdd645c 100644 (file)
@@ -49,6 +49,7 @@
 #include <linux/init.h>
 #include <linux/usb.h>
 #include <linux/usb/input.h>
+#include <linux/hid.h>
 
 
 #define DRIVER_VERSION         "v0.6"
@@ -101,7 +102,7 @@ struct usbtouch_usb {
 
 /* device types */
 enum {
-       DEVTPYE_DUMMY = -1,
+       DEVTYPE_IGNORE = -1,
        DEVTYPE_EGALAX,
        DEVTYPE_PANJIT,
        DEVTYPE_3M,
@@ -115,8 +116,21 @@ enum {
        DEVTYPE_GOTOP,
 };
 
+#define USB_DEVICE_HID_CLASS(vend, prod) \
+       .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \
+               | USB_DEVICE_ID_MATCH_DEVICE, \
+       .idVendor = (vend), \
+       .idProduct = (prod), \
+       .bInterfaceClass = USB_INTERFACE_CLASS_HID, \
+       .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE
+
 static struct usb_device_id usbtouch_devices[] = {
 #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
+       /* ignore the HID capable devices, handled by usbhid */
+       {USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE},
+       {USB_DEVICE_HID_CLASS(0x0eef, 0x0002), .driver_info = DEVTYPE_IGNORE},
+
+       /* normal device IDs */
        {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX},
        {USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX},
        {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX},
@@ -262,7 +276,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                              1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
        dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d",
-           __FUNCTION__, ret);
+           __func__, ret);
        if (ret < 0)
                return ret;
        msleep(150);
@@ -273,7 +287,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
                                      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                                      1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
                dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
-                   __FUNCTION__, ret);
+                   __func__, ret);
                if (ret >= 0)
                        break;
                if (ret != -EPIPE)
@@ -793,18 +807,18 @@ static void usbtouch_irq(struct urb *urb)
        case -ETIME:
                /* this urb is timing out */
                dbg("%s - urb timed out - was the device unplugged?",
-                   __FUNCTION__);
+                   __func__);
                return;
        case -ECONNRESET:
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d",
-                   __FUNCTION__, urb->status);
+                   __func__, urb->status);
                return;
        default:
                dbg("%s - nonzero urb status received: %d",
-                   __FUNCTION__, urb->status);
+                   __func__, urb->status);
                goto exit;
        }
 
@@ -814,7 +828,7 @@ exit:
        retval = usb_submit_urb(urb, GFP_ATOMIC);
        if (retval)
                err("%s - usb_submit_urb failed with result: %d",
-                   __FUNCTION__, retval);
+                   __func__, retval);
 }
 
 static int usbtouch_open(struct input_dev *input)
@@ -857,6 +871,10 @@ static int usbtouch_probe(struct usb_interface *intf,
        struct usbtouch_device_info *type;
        int err = -ENOMEM;
 
+       /* some devices are ignored */
+       if (id->driver_info == DEVTYPE_IGNORE)
+               return -ENODEV;
+
        interface = intf->cur_altsetting;
        endpoint = &interface->endpoint[0].desc;
 
@@ -883,7 +901,7 @@ static int usbtouch_probe(struct usb_interface *intf,
 
        usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL);
        if (!usbtouch->irq) {
-               dbg("%s - usb_alloc_urb failed: usbtouch->irq", __FUNCTION__);
+               dbg("%s - usb_alloc_urb failed: usbtouch->irq", __func__);
                goto out_free_buffers;
        }
 
@@ -939,14 +957,14 @@ static int usbtouch_probe(struct usb_interface *intf,
        if (type->init) {
                err = type->init(usbtouch);
                if (err) {
-                       dbg("%s - type->init() failed, err: %d", __FUNCTION__, err);
+                       dbg("%s - type->init() failed, err: %d", __func__, err);
                        goto out_free_buffers;
                }
        }
 
        err = input_register_device(usbtouch->input);
        if (err) {
-               dbg("%s - input_register_device failed, err: %d", __FUNCTION__, err);
+               dbg("%s - input_register_device failed, err: %d", __func__, err);
                goto out_free_buffers;
        }
 
@@ -966,12 +984,12 @@ static void usbtouch_disconnect(struct usb_interface *intf)
 {
        struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
 
-       dbg("%s - called", __FUNCTION__);
+       dbg("%s - called", __func__);
 
        if (!usbtouch)
                return;
 
-       dbg("%s - usbtouch is initialized, cleaning up", __FUNCTION__);
+       dbg("%s - usbtouch is initialized, cleaning up", __func__);
        usb_set_intfdata(intf, NULL);
        usb_kill_urb(usbtouch->irq);
        input_unregister_device(usbtouch->input);
index 0b6e4cf..4c5d85a 100644 (file)
@@ -168,6 +168,18 @@ static void wm9712_phy_init(struct wm97xx *wm)
                        64000 / rpu);
        }
 
+       /* WM9712 five wire */
+       if (five_wire) {
+               dig2 |= WM9712_45W;
+               dev_dbg(wm->dev, "setting 5-wire touchscreen mode.");
+
+               if (pil) {
+                       dev_warn(wm->dev, "pressure measurement is not "
+                                "supported in 5-wire mode\n");
+                       pil = 0;
+               }
+       }
+
        /* touchpanel pressure current*/
        if (pil == 2) {
                dig2 |= WM9712_PIL;
@@ -179,12 +191,6 @@ static void wm9712_phy_init(struct wm97xx *wm)
        if (!pil)
                pressure = 0;
 
-       /* WM9712 five wire */
-       if (five_wire) {
-               dig2 |= WM9712_45W;
-               dev_dbg(wm->dev, "setting 5-wire touchscreen mode.");
-       }
-
        /* polling mode sample settling delay */
        if (delay < 0 || delay > 15) {
                dev_dbg(wm->dev, "supplied delay out of range.");
index 59ea520..5396c67 100644 (file)
@@ -219,11 +219,13 @@ struct adbhid {
        int flags;
 };
 
-#define FLAG_FN_KEY_PRESSED    0x00000001
-#define FLAG_POWER_FROM_FN     0x00000002
-#define FLAG_EMU_FWDEL_DOWN    0x00000004
-#define FLAG_CAPSLOCK_TRANSLATE        0x00000008
-#define FLAG_CAPSLOCK_DOWN     0x00000010
+#define FLAG_FN_KEY_PRESSED            0x00000001
+#define FLAG_POWER_FROM_FN             0x00000002
+#define FLAG_EMU_FWDEL_DOWN            0x00000004
+#define FLAG_CAPSLOCK_TRANSLATE                0x00000008
+#define FLAG_CAPSLOCK_DOWN             0x00000010
+#define FLAG_CAPSLOCK_IGNORE_NEXT      0x00000020
+#define FLAG_POWER_KEY_PRESSED         0x00000040
 
 static struct adbhid *adbhid[16];
 
@@ -291,11 +293,20 @@ adbhid_input_keycode(int id, int scancode, int repeat)
                if (keycode == ADB_KEY_CAPSLOCK && !up_flag) {
                        /* Key pressed, turning on the CapsLock LED.
                         * The next 0xff will be interpreted as a release. */
-                       ahid->flags |= FLAG_CAPSLOCK_TRANSLATE
+                       if (ahid->flags & FLAG_CAPSLOCK_IGNORE_NEXT) {
+                               /* Throw away this key event if it happens
+                                * just after resume. */
+                               ahid->flags &= ~FLAG_CAPSLOCK_IGNORE_NEXT;
+                               return;
+                       } else {
+                               ahid->flags |= FLAG_CAPSLOCK_TRANSLATE
                                        | FLAG_CAPSLOCK_DOWN;
-               } else if (scancode == 0xff) {
+                       }
+               } else if (scancode == 0xff &&
+                          !(ahid->flags & FLAG_POWER_KEY_PRESSED)) {
                        /* Scancode 0xff usually signifies that the capslock
-                        * key was either pressed or released. */
+                        * key was either pressed or released, or that the
+                        * power button was released. */
                        if (ahid->flags & FLAG_CAPSLOCK_TRANSLATE) {
                                keycode = ADB_KEY_CAPSLOCK;
                                if (ahid->flags & FLAG_CAPSLOCK_DOWN) {
@@ -309,7 +320,7 @@ adbhid_input_keycode(int id, int scancode, int repeat)
                                }
                        } else {
                                printk(KERN_INFO "Spurious caps lock event "
-                                               "(scancode 0xff).");
+                                                "(scancode 0xff).\n");
                        }
                }
        }
@@ -336,6 +347,12 @@ adbhid_input_keycode(int id, int scancode, int repeat)
                }
                break;
        case ADB_KEY_POWER:
+               /* Keep track of the power key state */
+               if (up_flag)
+                       ahid->flags &= ~FLAG_POWER_KEY_PRESSED;
+               else
+                       ahid->flags |= FLAG_POWER_KEY_PRESSED;
+
                /* Fn + Command will produce a bogus "power" keycode */
                if (ahid->flags & FLAG_FN_KEY_PRESSED) {
                        keycode = ADB_KEY_CMD;
@@ -681,6 +698,21 @@ static int adbhid_kbd_event(struct input_dev *dev, unsigned int type, unsigned i
        return -1;
 }
 
+static void
+adbhid_kbd_capslock_remember(void)
+{
+       struct adbhid *ahid;
+       int i;
+
+       for (i = 1; i < 16; i++) {
+               ahid = adbhid[i];
+
+               if (ahid && ahid->id == ADB_KEYBOARD)
+                       if (ahid->flags & FLAG_CAPSLOCK_TRANSLATE)
+                               ahid->flags |= FLAG_CAPSLOCK_IGNORE_NEXT;
+       }
+}
+
 static int
 adb_message_handler(struct notifier_block *this, unsigned long code, void *x)
 {
@@ -697,8 +729,17 @@ adb_message_handler(struct notifier_block *this, unsigned long code, void *x)
                }
 
                /* Stop pending led requests */
-               while(leds_req_pending)
+               while (leds_req_pending)
                        adb_poll();
+
+               /* After resume, and if the capslock LED is on, the PMU will
+                * send a "capslock down" key event. This confuses the
+                * restore_capslock_events logic. Remember if the capslock
+                * LED was on before suspend so the unwanted key event can
+                * be ignored after resume. */
+               if (restore_capslock_events)
+                       adbhid_kbd_capslock_remember();
+
                break;
 
        case ADB_MSG_POST_RESET:
index afad952..f64e29c 100644 (file)
@@ -68,7 +68,6 @@ struct gameport_driver {
 
 int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode);
 void gameport_close(struct gameport *gameport);
-void gameport_rescan(struct gameport *gameport);
 
 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
 
index c6d3a9d..ec6ecd7 100644 (file)
@@ -9,6 +9,7 @@ struct gpio_keys_button {
        char *desc;
        int type;               /* input event type (EV_KEY, EV_SW) */
        int wakeup;             /* configure the button as a wake-up source */
+       int debounce_interval;  /* debounce ticks interval in msecs */
 };
 
 struct gpio_keys_platform_data {
index d150c57..a5802c9 100644 (file)
@@ -373,6 +373,8 @@ struct input_absinfo {
 
 #define KEY_WIMAX              246
 
+/* Range 248 - 255 is reserved for special needs of AT keyboard driver */
+
 #define BTN_MISC               0x100
 #define BTN_0                  0x100
 #define BTN_1                  0x101
@@ -640,6 +642,8 @@ struct input_absinfo {
 #define SW_RFKILL_ALL          0x03  /* rfkill master switch, type "any"
                                         set = radio enabled */
 #define SW_RADIO               SW_RFKILL_ALL   /* deprecated */
+#define SW_MICROPHONE_INSERT   0x04  /* set = inserted */
+#define SW_DOCK                        0x05  /* set = plugged into dock */
 #define SW_MAX                 0x0f
 #define SW_CNT                 (SW_MAX+1)
 
@@ -1215,11 +1219,6 @@ struct input_handle {
        struct list_head        h_node;
 };
 
-#define to_dev(n) container_of(n, struct input_dev, node)
-#define to_handler(n) container_of(n, struct input_handler, node)
-#define to_handle(n) container_of(n, struct input_handle, d_node)
-#define to_handle_h(n) container_of(n, struct input_handle, h_node)
-
 struct input_dev *input_allocate_device(void);
 void input_free_device(struct input_dev *dev);
 
index e2d3a18..b5e0512 100644 (file)
@@ -2,8 +2,6 @@
 #define _LINUX_JOYSTICK_H
 
 /*
- * $Id: joystick.h,v 1.3 2000/11/30 11:07:05 vojtech Exp $
- *
  *  Copyright (C) 1996-2000 Vojtech Pavlik
  *
  *  Sponsored by SuSE
index f6f301e..afc4133 100644 (file)
@@ -43,7 +43,6 @@ void ps2_init(struct ps2dev *ps2dev, struct serio *serio);
 int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout);
 void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout);
 int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command);
-int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int command);
 int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data);
 int ps2_handle_response(struct ps2dev *ps2dev, unsigned char data);
 void ps2_cmd_aborted(struct ps2dev *ps2dev);
index 95674d9..e72716c 100644 (file)
@@ -175,7 +175,7 @@ static inline void serio_unpin_driver(struct serio *serio)
 #define SERIO_8042_XL  0x06
 
 /*
- * Serio types
+ * Serio protocols
  */
 #define SERIO_UNKNOWN  0x00
 #define SERIO_MSC      0x01
@@ -212,5 +212,7 @@ static inline void serio_unpin_driver(struct serio *serio)
 #define SERIO_TAOSEVM  0x34
 #define SERIO_FUJITSU  0x35
 #define SERIO_ZHENHUA  0x36
+#define SERIO_INEXIO   0x37
+#define SERIO_TOUCHIT213       0x37
 
 #endif