bk://kernel.bkbits.net/vojtech/input vojtech@suse.cz|ChangeSet|20040923110416|52112 vojtech # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/09/23 17:13:04-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/vojtech/input # into bix.(none):/usr/src/bk-input # # drivers/usb/input/hid-core.c # 2004/09/23 17:13:00-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/09/23 13:01:47+02:00 mochel@digitalimplant.org # input: Remove calls to pm_access() and pm_dev_idle() from input.c, as # they're empty functions anyway. # # Signed-off-by: Vojtech Pavlik # Patch-by: Patrick Mochel # # drivers/input/input.c # 2004/09/23 13:01:41+02:00 mochel@digitalimplant.org +0 -7 # input: Remove calls to pm_access() and pm_dev_idle() from input.c, as # they're empty functions anyway. # # Signed-off-by: Vojtech Pavlik # Patch-by: Patrick Mochel # # ChangeSet # 2004/09/23 12:59:31+02:00 vojtech@suse.cz # input: Tidy up & fix the hid-input.c driver. Dual-wheel A4 mice don't report the phantom # button anymore, D-Pads are mapped to Hat-switches, debug can print HID->Input # mappings, more mappings added, devices with reports larger than MaxPacketSize # work again. # # Signed-off-by: Vojtech Pavlik # # include/linux/input.h # 2004/09/23 12:59:24+02:00 vojtech@suse.cz +3 -0 # input: Tidy up & fix the hid-input.c driver. Dual-wheel A4 mice don't report the phantom # button anymore, D-Pads are mapped to Hat-switches, debug can print HID->Input # mappings, more mappings added, devices with reports larger than MaxPacketSize # work again. # # Signed-off-by: Vojtech Pavlik # # drivers/usb/input/hid.h # 2004/09/23 12:59:24+02:00 vojtech@suse.cz +41 -3 # input: Tidy up & fix the hid-input.c driver. Dual-wheel A4 mice don't report the phantom # button anymore, D-Pads are mapped to Hat-switches, debug can print HID->Input # mappings, more mappings added, devices with reports larger than MaxPacketSize # work again. # # Signed-off-by: Vojtech Pavlik # # drivers/usb/input/hid-input.c # 2004/09/23 12:59:24+02:00 vojtech@suse.cz +217 -246 # input: Tidy up & fix the hid-input.c driver. Dual-wheel A4 mice don't report the phantom # button anymore, D-Pads are mapped to Hat-switches, debug can print HID->Input # mappings, more mappings added, devices with reports larger than MaxPacketSize # work again. # # Signed-off-by: Vojtech Pavlik # # drivers/usb/input/hid-debug.h # 2004/09/23 12:59:24+02:00 vojtech@suse.cz +263 -1 # input: Tidy up & fix the hid-input.c driver. Dual-wheel A4 mice don't report the phantom # button anymore, D-Pads are mapped to Hat-switches, debug can print HID->Input # mappings, more mappings added, devices with reports larger than MaxPacketSize # work again. # # Signed-off-by: Vojtech Pavlik # # drivers/usb/input/hid-core.c # 2004/09/23 12:59:24+02:00 vojtech@suse.cz +8 -9 # input: Tidy up & fix the hid-input.c driver. Dual-wheel A4 mice don't report the phantom # button anymore, D-Pads are mapped to Hat-switches, debug can print HID->Input # mappings, more mappings added, devices with reports larger than MaxPacketSize # work again. # # Signed-off-by: Vojtech Pavlik # # ChangeSet # 2004/09/22 23:57:11-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # drivers/Makefile # 2004/09/22 23:57:06-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/09/22 23:57:06-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/09/22 14:08:35-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/vojtech/input # into bix.(none):/usr/src/bk-input # # drivers/usb/input/hid-core.c # 2004/09/22 14:08:31-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/input/serio/Kconfig # 2004/09/22 14:08:31-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/09/22 14:07:34-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # drivers/input/gameport/vortex.c # 2004/09/22 14:07:29-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/09/22 10:46:32+02:00 vojtech@suse.cz # input: More IOWarrior blacklist entries in hid.c, rearranging the # blacklist back to alphabetic order. # # Signed-off-by: Vojtech Pavlik # # drivers/usb/input/hid-core.c # 2004/09/22 10:46:25+02:00 vojtech@suse.cz +9 -7 # input: More IOWarrior blacklist entries in hid.c, rearranging the # blacklist back to alphabetic order. # # Signed-off-by: Vojtech Pavlik # # ChangeSet # 2004/09/22 01:50:38-05:00 dtor_core@ameritech.net # Input: atkbd - export extra, scroll, set, softrepeat and softraw as individual # keyboard attributes (sysfs) and allow them to be set/changed independently # for each keyboard: # # echo -n "2" > /sys/bus/serio/devices/serio1/set # echo -n "1" > /sys/bus/serio/devices/serio1/softrepeat # # Signed-off-by: Dmitry Torokhov # # drivers/input/keyboard/atkbd.c # 2004/09/22 01:50:23-05:00 dtor_core@ameritech.net +365 -76 # Export extra, scroll, set, softrepeat and softraw as individual # sysfs keyboard attributes. # # ChangeSet # 2004/09/22 01:49:31-05:00 dtor_core@ameritech.net # Input: add serio_[un]pin_driver() functions so attribute handlers # can safely access driver bound to a serio port. # # Signed-off-by: Dmitry Torokhov # # include/linux/serio.h # 2004/09/22 01:49:13-05:00 dtor_core@ameritech.net +15 -1 # Add drv_sem to serio structure and serio_[un]pin_driver() so attribute # handlers can safely access driver bound to a serio port # # drivers/input/serio/serio.c # 2004/09/22 01:49:13-05:00 dtor_core@ameritech.net +12 -8 # Take drv_sem when binding/unbinding driver to a serio port # # ChangeSet # 2004/09/22 01:48:40-05:00 dtor_core@ameritech.net # Input: pull common code from psmouse and atkbd into libps2 module # # Signed-off-by: Dmitry Torokhov # # include/linux/libps2.h # 2004/09/22 01:48:17-05:00 dtor_core@ameritech.net +50 -0 # BitKeeper file /misc/arc/dtor/include/linux/libps2.h # # drivers/input/serio/Makefile # 2004/09/22 01:48:17-05:00 dtor_core@ameritech.net +1 -0 # Add libps2 # # drivers/input/serio/Kconfig # 2004/09/22 01:48:17-05:00 dtor_core@ameritech.net +10 -0 # Add libps2 # # drivers/input/mouse/synaptics.c # 2004/09/22 01:48:17-05:00 dtor_core@ameritech.net +15 -13 # Rename psmouse_coommand -> ps2_command # # drivers/input/mouse/psmouse.h # 2004/09/22 01:48:17-05:00 dtor_core@ameritech.net +1 -15 # Embed ps2dev into psmouse structure # # drivers/input/mouse/psmouse-base.c # 2004/09/22 01:48:17-05:00 dtor_core@ameritech.net +52 -187 # Switch to using libps2 to communicate with PS/2 port # # drivers/input/mouse/logips2pp.c # 2004/09/22 01:48:17-05:00 dtor_core@ameritech.net +23 -18 # Rename psmouse_coommand -> ps2_command # # drivers/input/mouse/alps.c # 2004/09/22 01:48:17-05:00 dtor_core@ameritech.net +38 -30 # Rename psmouse_coommand -> ps2_command # # drivers/input/mouse/Kconfig # 2004/09/22 01:48:17-05:00 dtor_core@ameritech.net +1 -0 # Automatically select libps2 when selecting psmouse # # include/linux/libps2.h # 2004/09/22 01:48:17-05:00 dtor_core@ameritech.net +0 -0 # BitKeeper file /usr/src/export/input/include/linux/libps2.h # # drivers/input/serio/libps2.c # 2004/09/22 01:48:17-05:00 dtor_core@ameritech.net +273 -0 # BitKeeper file /misc/arc/dtor/drivers/input/serio/libps2.c # # drivers/input/keyboard/atkbd.c # 2004/09/22 01:48:17-05:00 dtor_core@ameritech.net +52 -238 # Switch to using libps2 to communicate with PS/2 port # # drivers/input/keyboard/Kconfig # 2004/09/22 01:48:17-05:00 dtor_core@ameritech.net +1 -0 # Automatically select libps2 when selecting atkbd # # drivers/input/serio/libps2.c # 2004/09/22 01:48:17-05:00 dtor_core@ameritech.net +0 -0 # BitKeeper file /usr/src/export/input/drivers/input/serio/libps2.c # # ChangeSet # 2004/09/21 21:19:36-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/vojtech/input # into bix.(none):/usr/src/bk-input # # drivers/usb/input/hid-core.c # 2004/09/21 21:19:32-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/char/keyboard.c # 2004/09/21 21:19:32-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/09/21 21:18:33-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # drivers/serial/sunsu.c # 2004/09/21 21:18:28-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/09/21 16:12:18+02:00 vojtech@suse.cz # input: Add AT-compatible rawmode generation for ARM. # # Signed-off-by: Vojtech Pavlik # Patch-by: Woody Suwalski # # drivers/char/keyboard.c # 2004/09/21 16:12:11+02:00 vojtech@suse.cz +4 -1 # input: Add AT-compatible rawmode generation for ARM. # # Signed-off-by: Vojtech Pavlik # Patch-by: Woody Suwalski # # ChangeSet # 2004/09/21 15:48:50+02:00 petero2@telia.com # input: Add ALPS touchpad driver, driver by Neil Brown, Peter Osterlund # and Dmitry Torokhov, some fixes by Vojtech Pavlik. # # Signed-off-by: Vojtech Pavlik # Patch-by: Peter Osterlund # # drivers/input/mouse/alps.h # 2004/09/21 15:48:43+02:00 petero2@telia.com +17 -0 # # drivers/input/mouse/alps.h # 2004/09/21 15:48:43+02:00 petero2@telia.com +0 -0 # BitKeeper file /data2/bk/input/drivers/input/mouse/alps.h # # drivers/input/mouse/alps.c # 2004/09/21 15:48:42+02:00 petero2@telia.com +422 -0 # # drivers/input/mousedev.c # 2004/09/21 15:48:42+02:00 petero2@telia.com +10 -4 # input: Add ALPS touchpad driver, driver by Neil Brown, Peter Osterlund # and Dmitry Torokhov, some fixes by Vojtech Pavlik. # # Signed-off-by: Vojtech Pavlik # Patch-by: Peter Osterlund # # drivers/input/mouse/psmouse.h # 2004/09/21 15:48:42+02:00 petero2@telia.com +3 -0 # input: Add ALPS touchpad driver, driver by Neil Brown, Peter Osterlund # and Dmitry Torokhov, some fixes by Vojtech Pavlik. # # Signed-off-by: Vojtech Pavlik # Patch-by: Peter Osterlund # # drivers/input/mouse/psmouse-base.c # 2004/09/21 15:48:42+02:00 petero2@telia.com +22 -1 # input: Add ALPS touchpad driver, driver by Neil Brown, Peter Osterlund # and Dmitry Torokhov, some fixes by Vojtech Pavlik. # # Signed-off-by: Vojtech Pavlik # Patch-by: Peter Osterlund # # drivers/input/mouse/alps.c # 2004/09/21 15:48:42+02:00 petero2@telia.com +0 -0 # BitKeeper file /data2/bk/input/drivers/input/mouse/alps.c # # drivers/input/mouse/Makefile # 2004/09/21 15:48:42+02:00 petero2@telia.com +1 -1 # input: Add ALPS touchpad driver, driver by Neil Brown, Peter Osterlund # and Dmitry Torokhov, some fixes by Vojtech Pavlik. # # Signed-off-by: Vojtech Pavlik # Patch-by: Peter Osterlund # # ChangeSet # 2004/09/21 15:27:54+02:00 pmaydell@chiark.greenend.org.uk # input: Add support for Kensington ThinkingMouse PS/2 protocol. # # Signed-off-by: Vojtech Pavlik # Patch-by: Peter Maydell # # drivers/input/mouse/psmouse.h # 2004/09/21 15:27:48+02:00 pmaydell@chiark.greenend.org.uk +11 -7 # input: Add support for Kensington ThinkingMouse PS/2 protocol. # # Signed-off-by: Vojtech Pavlik # Patch-by: Peter Maydell # # drivers/input/mouse/psmouse-base.c # 2004/09/21 15:27:48+02:00 pmaydell@chiark.greenend.org.uk +50 -5 # input: Add support for Kensington ThinkingMouse PS/2 protocol. # # Signed-off-by: Vojtech Pavlik # Patch-by: Peter Maydell # # ChangeSet # 2004/09/21 10:04:06+02:00 vojtech@suse.cz # input: Some HID devices have problems returning the HID class descriptor. # Try a few times before giving up. # # Signed-off-by: Vojtech Pavlik # # drivers/usb/input/hid-core.c # 2004/09/21 10:04:00+02:00 vojtech@suse.cz +8 -3 # input: Some HID devices have problems returning the HID class descriptor. # Try a few times before giving up. # # Signed-off-by: Vojtech Pavlik # # ChangeSet # 2004/09/21 09:24:21+02:00 pnelson@suse.cz # input: Fix oops in gamecon # # Signed-off-by: Vojtech Pavlik # Patch-by: Peter Nelson # # drivers/input/joystick/gamecon.c # 2004/09/21 09:24:14+02:00 pnelson@suse.cz +3 -3 # input: Fix oops in gamecon # # Signed-off-by: Vojtech Pavlik # Patch-by: Peter Nelson # # ChangeSet # 2004/09/19 21:58:28-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # drivers/input/serio/Kconfig # 2004/09/19 21:58:24-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/09/19 13:46:50+02:00 olh@suse.de # input: Joydump depends on gameport # # Signed-off-by: Vojtech Pavlik # Patch-by: Olaf Hering # # drivers/input/joystick/Kconfig # 2004/09/19 13:46:33+02:00 olh@suse.de +1 -1 # input: Joydump depends on gameport # # Signed-off-by: Vojtech Pavlik # Patch-by: Olaf Hering # # ChangeSet # 2004/09/17 13:30:06-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # Documentation/kernel-parameters.txt # 2004/09/17 13:30:02-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/09/16 16:27:12-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # include/linux/hiddev.h # 2004/09/16 16:27:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # fs/compat_ioctl.c # 2004/09/16 16:27:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/input/hiddev.c # 2004/09/16 16:27:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/input/serio/Kconfig # 2004/09/16 16:27:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/Makefile # 2004/09/16 16:27:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/09/16 16:27:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # Documentation/kernel-parameters.txt # 2004/09/16 16:27:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/09/08 12:29:01-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # include/linux/hiddev.h # 2004/09/08 12:28:56-07:00 akpm@bix.(none) +0 -7 # Auto merged # # drivers/usb/input/hiddev.c # 2004/09/08 12:28:56-07:00 akpm@bix.(none) +0 -6 # Auto merged # # drivers/Makefile # 2004/09/08 12:28:56-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/09/07 21:06:53-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # fs/compat_ioctl.c # 2004/09/07 21:06:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/09/07 21:06:47-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/09/03 14:23:28-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # MAINTAINERS # 2004/09/03 14:23:24-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/31 14:02:33-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # MAINTAINERS # 2004/08/31 14:02:26-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/28 16:27:11-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # MAINTAINERS # 2004/08/28 16:27:07-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/27 23:57:20-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # drivers/input/serio/Kconfig # 2004/08/27 23:57:14-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/08/27 23:57:14-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/27 13:41:40-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # MAINTAINERS # 2004/08/27 13:41:36-07:00 akpm@bix.(none) +0 -0 # Auto merged # # Documentation/kernel-parameters.txt # 2004/08/27 13:41:36-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/25 19:45:04-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # MAINTAINERS # 2004/08/25 19:44:59-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/25 14:17:06-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/vojtech/input # into bix.(none):/usr/src/bk-input # # include/linux/compat_ioctl.h # 2004/08/25 14:17:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/input/hid-core.c # 2004/08/25 14:17:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/input/serio/gscps2.c # 2004/08/25 14:17:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/input/gameport/vortex.c # 2004/08/25 14:17:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/input/gameport/emu10k1-gp.c # 2004/08/25 14:17:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/Makefile # 2004/08/25 14:17:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/08/25 14:17:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # Documentation/kernel-parameters.txt # 2004/08/25 14:17:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/24 17:54:26-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # drivers/input/serio/gscps2.c # 2004/08/24 17:54:22-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/08/24 17:54:22-07:00 akpm@bix.(none) +0 -0 # Auto merged # # Documentation/kernel-parameters.txt # 2004/08/24 17:54:22-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/23 16:53:47-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # drivers/usb/input/hid-core.c # 2004/08/23 16:53:43-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/input/gameport/vortex.c # 2004/08/23 16:53:43-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/input/gameport/emu10k1-gp.c # 2004/08/23 16:53:43-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/Makefile # 2004/08/23 16:53:43-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/08/23 16:53:42-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/23 14:14:32-07:00 akpm@bix.(none) # Merge # # MAINTAINERS # 2004/08/23 14:14:28-07:00 akpm@bix.(none) +0 -0 # SCCS merged # # fs/compat_ioctl.c # 2004/08/23 14:07:45-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/input/hid-core.c # 2004/08/23 14:07:44-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/Makefile # 2004/08/23 14:07:44-07:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/i386/kernel/dmi_scan.c # 2004/08/23 14:07:44-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/23 14:06:49-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # include/linux/compat_ioctl.h # 2004/08/23 14:06:45-07:00 akpm@bix.(none) +0 -0 # Auto merged # # Documentation/kernel-parameters.txt # 2004/08/23 14:06:45-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/22 21:20:58-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # include/linux/compat_ioctl.h # 2004/08/22 21:20:54-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/15 01:07:14-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # arch/i386/kernel/dmi_scan.c # 2004/08/15 01:07:10-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/04 17:51:18-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/vojtech/input # into bix.(none):/usr/src/bk-input # # fs/compat_ioctl.c # 2004/08/04 17:51:15-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/04 11:19:18-07:00 vojtech@kernel.bkbits.net # Merge kernel.bkbits.net:/home/vojtech/linus # into kernel.bkbits.net:/home/vojtech/input # # fs/compat_ioctl.c # 2004/08/04 11:19:12-07:00 vojtech@kernel.bkbits.net +0 -0 # Auto merged # # ChangeSet # 2004/07/29 23:23:37-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/vojtech/input # into bix.(none):/usr/src/bk-input # # fs/compat_ioctl.c # 2004/07/29 23:23:33-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/input/hiddev.c # 2004/07/29 23:23:33-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/input/hid-core.c # 2004/07/29 23:23:33-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/Makefile # 2004/07/29 23:23:33-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/07/29 23:22:42-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # fs/compat_ioctl.c # 2004/07/29 23:22:38-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/07/27 12:48:04-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/vojtech/input # into bix.(none):/usr/src/bk-input # # drivers/serial/sunsu.c # 2004/07/27 12:48:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/input/keyboard/sunkbd.c # 2004/07/27 12:48:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/input/joystick/analog.c # 2004/07/27 12:48:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/07/26 22:48:28-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # drivers/serial/sunsu.c # 2004/07/26 22:48:25-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/input/keyboard/sunkbd.c # 2004/07/26 22:48:25-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/input/joystick/analog.c # 2004/07/26 22:48:25-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/07/25 16:28:12-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/vojtech/input # into bix.(none):/usr/src/bk-input # # fs/compat_ioctl.c # 2004/07/25 16:28:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/input/hid-core.c # 2004/07/25 16:28:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/Makefile # 2004/07/25 16:28:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/07/16 18:31:00-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # drivers/usb/input/hid-core.c # 2004/07/16 18:30:57-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/Makefile # 2004/07/16 18:30:57-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/07/13 12:40:25-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # fs/compat_ioctl.c # 2004/07/13 12:40:21-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/07/11 23:41:44-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/vojtech/input # into bix.(none):/usr/src/bk-input # # fs/compat_ioctl.c # 2004/07/11 23:41:41-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/input/hiddev.c # 2004/07/11 23:41:41-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/input/hid-tmff.c # 2004/07/11 23:41:41-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/input/serio/i8042-io.h # 2004/07/11 23:41:41-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/char/keyboard.c # 2004/07/11 23:41:41-07:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/i386/kernel/dmi_scan.c # 2004/07/11 23:41:41-07:00 akpm@bix.(none) +0 -0 # Auto merged # # Documentation/kernel-parameters.txt # 2004/07/11 23:41:41-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/07/11 13:33:39-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # arch/i386/kernel/dmi_scan.c # 2004/07/11 13:33:36-07:00 akpm@bix.(none) +0 -0 # Auto merged # # Documentation/kernel-parameters.txt # 2004/07/11 13:33:36-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/07/08 14:24:00-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/vojtech/input # into bix.(none):/usr/src/bk-input # # include/linux/compat_ioctl.h # 2004/07/08 14:23:56-07:00 akpm@bix.(none) +0 -0 # Auto merged # # fs/compat_ioctl.c # 2004/07/08 14:23:56-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/input/hiddev.c # 2004/07/08 14:23:56-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/input/hid-tmff.c # 2004/07/08 14:23:56-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/input/serio/i8042-io.h # 2004/07/08 14:23:56-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/char/keyboard.c # 2004/07/08 14:23:56-07:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/i386/kernel/dmi_scan.c # 2004/07/08 14:23:56-07:00 akpm@bix.(none) +0 -0 # Auto merged # # Documentation/kernel-parameters.txt # 2004/07/08 14:23:56-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/07/06 23:59:45-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # include/linux/compat_ioctl.h # 2004/07/06 23:59:41-07:00 akpm@bix.(none) +0 -0 # Auto merged # # fs/compat_ioctl.c # 2004/07/06 23:59:41-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/07/05 13:01:11-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-input # # drivers/usb/input/hiddev.c # 2004/07/05 13:01:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/i386/kernel/dmi_scan.c # 2004/07/05 13:01:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # Documentation/kernel-parameters.txt # 2004/07/05 13:01:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/30 11:25:44-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/vojtech/input # into bix.(none):/usr/src/bk-input # # fs/compat_ioctl.c # 2004/06/30 11:25:40-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/input/hid-tmff.c # 2004/06/30 11:25:40-07:00 akpm@bix.(none) +0 -1 # Auto merged # # drivers/input/serio/i8042-io.h # 2004/06/30 11:25:40-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/char/keyboard.c # 2004/06/30 11:25:40-07:00 akpm@bix.(none) +0 -0 # Auto merged # diff -Nru a/drivers/char/keyboard.c b/drivers/char/keyboard.c --- a/drivers/char/keyboard.c 2004-09-23 21:12:57 -07:00 +++ b/drivers/char/keyboard.c 2004-09-23 21:12:57 -07:00 @@ -939,7 +939,10 @@ tasklet_enable(&keyboard_tasklet); } -#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64) || defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) +#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\ + defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC32) ||\ + defined(CONFIG_SPARC64) || defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\ + (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_RPC)) #define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\ ((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001)) diff -Nru a/drivers/input/input.c b/drivers/input/input.c --- a/drivers/input/input.c 2004-09-23 21:12:57 -07:00 +++ b/drivers/input/input.c 2004-09-23 21:12:57 -07:00 @@ -67,9 +67,6 @@ { struct input_handle *handle; - if (dev->pm_dev) - pm_access(dev->pm_dev); - if (type > EV_MAX || !test_bit(type, dev->evbit)) return; @@ -230,8 +227,6 @@ int input_open_device(struct input_handle *handle) { - if (handle->dev->pm_dev) - pm_access(handle->dev->pm_dev); handle->open++; if (handle->dev->open) return handle->dev->open(handle->dev); @@ -249,8 +244,6 @@ void input_close_device(struct input_handle *handle) { input_release_device(handle); - if (handle->dev->pm_dev) - pm_dev_idle(handle->dev->pm_dev); if (handle->dev->close) handle->dev->close(handle->dev); handle->open--; diff -Nru a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig --- a/drivers/input/joystick/Kconfig 2004-09-23 21:12:57 -07:00 +++ b/drivers/input/joystick/Kconfig 2004-09-23 21:12:57 -07:00 @@ -249,7 +249,7 @@ config JOYSTICK_JOYDUMP tristate "Gameport data dumper" - depends on INPUT && INPUT_JOYSTICK + depends on INPUT && INPUT_JOYSTICK && GAMEPORT help Say Y here if you want to dump data from your joystick into the system log for debugging purposes. Say N if you are making a production diff -Nru a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c --- a/drivers/input/joystick/gamecon.c 2004-09-23 21:12:57 -07:00 +++ b/drivers/input/joystick/gamecon.c 2004-09-23 21:12:57 -07:00 @@ -89,7 +89,7 @@ static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 }; static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick", - "Multisystem 2-button joystick", "N64 controller", "PSX controller" + "Multisystem 2-button joystick", "N64 controller", "PSX controller", "PSX DDR controller" }; /* * N64 support. @@ -271,7 +271,7 @@ udelay(gc_psx_delay); read = parport_read_status(gc->pd->port) ^ 0x80; for (j = 0; j < 5; j++) - data[j] |= (read & gc_status_bit[j] & gc->pads[GC_PSX]) ? (1 << i) : 0; + data[j] |= (read & gc_status_bit[j] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) ? (1 << i) : 0; parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER); udelay(gc_psx_delay); } @@ -300,7 +300,7 @@ gc_psx_command(gc, 0, data2); /* Dump status */ for (i =0; i < 5; i++) /* Find the longest pad */ - if((gc_status_bit[i] & gc->pads[GC_PSX]) && (GC_PSX_LEN(id[i]) > max_len)) + if((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) && (GC_PSX_LEN(id[i]) > max_len)) max_len = GC_PSX_LEN(id[i]); for (i = 0; i < max_len * 2; i++) { /* Read in all the data */ diff -Nru a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig --- a/drivers/input/keyboard/Kconfig 2004-09-23 21:12:57 -07:00 +++ b/drivers/input/keyboard/Kconfig 2004-09-23 21:12:57 -07:00 @@ -16,6 +16,7 @@ default y depends on INPUT && INPUT_KEYBOARD select SERIO + select SERIO_LIBPS2 select SERIO_I8042 if PC select SERIO_GSCPS2 if GSC help diff -Nru a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c --- a/drivers/input/keyboard/atkbd.c 2004-09-23 21:12:57 -07:00 +++ b/drivers/input/keyboard/atkbd.c 2004-09-23 21:12:57 -07:00 @@ -26,6 +26,7 @@ #include #include #include +#include #define DRIVER_DESC "AT and PS/2 keyboard driver" @@ -170,36 +171,29 @@ { ATKBD_SCR_CLICK, 0x60 }, }; -#define ATKBD_FLAG_ACK 0 /* Waiting for ACK/NAK */ -#define ATKBD_FLAG_CMD 1 /* Waiting for command to finish */ -#define ATKBD_FLAG_CMD1 2 /* First byte of command response */ -#define ATKBD_FLAG_ENABLED 3 /* Waining for init to finish */ - /* * The atkbd control structure */ struct atkbd { + struct ps2dev ps2dev; + /* Written only during init */ char name[64]; char phys[32]; - struct serio *serio; struct input_dev dev; - unsigned char set; unsigned short id; unsigned char keycode[512]; + unsigned char set; unsigned char translated; unsigned char extra; unsigned char write; - - /* Protected by FLAG_ACK */ - unsigned char nak; - - /* Protected by FLAG_CMD */ - unsigned char cmdbuf[4]; - unsigned char cmdcnt; + unsigned char softrepeat; + unsigned char softraw; + unsigned char scroll; + unsigned char enabled; /* Accessed only from interrupt */ unsigned char emul; @@ -208,24 +202,31 @@ unsigned char bat_xl; unsigned int last; unsigned long time; - - /* Ensures that only one command is executing at a time */ - struct semaphore cmd_sem; - - /* Used to signal completion from interrupt handler */ - wait_queue_head_t wait; - - /* Flags */ - unsigned long flags; }; -/* Work structure to schedule execution of a command */ -struct atkbd_work { - struct work_struct work; - struct atkbd *atkbd; - int command; - unsigned char param[0]; -}; +static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, + ssize_t (*handler)(struct atkbd *, char *)); +static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count, + int (*handler)(struct atkbd *, const char *, size_t)); +#define ATKBD_DEFINE_ATTR(_name) \ +static ssize_t atkbd_show_##_name(struct atkbd *, char *); \ +static ssize_t atkbd_set_##_name(struct atkbd *, const char *, size_t); \ +static ssize_t atkbd_do_show_##_name(struct device *d, char *b) \ +{ \ + return atkbd_attr_show_helper(d, b, atkbd_show_##_name); \ +} \ +static ssize_t atkbd_do_set_##_name(struct device *d, const char *b, size_t s) \ +{ \ + return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \ +} \ +static struct device_attribute atkbd_attr_##_name = \ + __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name); + +ATKBD_DEFINE_ATTR(extra); +ATKBD_DEFINE_ATTR(scroll); +ATKBD_DEFINE_ATTR(set); +ATKBD_DEFINE_ATTR(softrepeat); +ATKBD_DEFINE_ATTR(softraw); static void atkbd_report_key(struct input_dev *dev, struct pt_regs *regs, int code, int value) @@ -268,42 +269,15 @@ atkbd->resend = 0; #endif - if (test_bit(ATKBD_FLAG_ACK, &atkbd->flags)) { - switch (code) { - case ATKBD_RET_ACK: - atkbd->nak = 0; - if (atkbd->cmdcnt) { - set_bit(ATKBD_FLAG_CMD, &atkbd->flags); - set_bit(ATKBD_FLAG_CMD1, &atkbd->flags); - } - clear_bit(ATKBD_FLAG_ACK, &atkbd->flags); - wake_up_interruptible(&atkbd->wait); - break; - case ATKBD_RET_NAK: - atkbd->nak = 1; - clear_bit(ATKBD_FLAG_ACK, &atkbd->flags); - wake_up_interruptible(&atkbd->wait); - break; - } - goto out; - } - - if (test_bit(ATKBD_FLAG_CMD, &atkbd->flags)) { - - if (atkbd->cmdcnt) - atkbd->cmdbuf[--atkbd->cmdcnt] = code; - - if (test_and_clear_bit(ATKBD_FLAG_CMD1, &atkbd->flags) && atkbd->cmdcnt) - wake_up_interruptible(&atkbd->wait); + if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_ACK)) + if (ps2_handle_ack(&atkbd->ps2dev, data)) + goto out; - if (!atkbd->cmdcnt) { - clear_bit(ATKBD_FLAG_CMD, &atkbd->flags); - wake_up_interruptible(&atkbd->wait); - } - goto out; - } + if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_CMD)) + if (ps2_handle_response(&atkbd->ps2dev, data)) + goto out; - if (!test_bit(ATKBD_FLAG_ENABLED, &atkbd->flags)) + if (!atkbd->enabled) goto out; input_event(&atkbd->dev, EV_MSC, MSC_RAW, code); @@ -326,8 +300,8 @@ switch (code) { case ATKBD_RET_BAT: - clear_bit(ATKBD_FLAG_ENABLED, &atkbd->flags); - serio_rescan(atkbd->serio); + atkbd->enabled = 0; + serio_rescan(atkbd->ps2dev.serio); goto out; case ATKBD_RET_EMUL0: atkbd->emul = 1; @@ -396,7 +370,7 @@ break; default: value = atkbd->release ? 0 : - (1 + (!atkbd_softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key))); + (1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key))); switch (value) { /* Workaround Toshiba laptop multiple keypress */ case 0: @@ -427,151 +401,6 @@ return IRQ_HANDLED; } -/* - * atkbd_sendbyte() sends a byte to the keyboard, and waits for - * acknowledge. It doesn't handle resends according to the keyboard - * protocol specs, because if these are needed, the keyboard needs - * replacement anyway, and they only make a mess in the protocol. - * - * atkbd_sendbyte() can only be called from a process context - */ - -static int atkbd_sendbyte(struct atkbd *atkbd, unsigned char byte) -{ -#ifdef ATKBD_DEBUG - printk(KERN_DEBUG "atkbd.c: Sent: %02x\n", byte); -#endif - atkbd->nak = 1; - set_bit(ATKBD_FLAG_ACK, &atkbd->flags); - - if (serio_write(atkbd->serio, byte) == 0) - wait_event_interruptible_timeout(atkbd->wait, - !test_bit(ATKBD_FLAG_ACK, &atkbd->flags), - msecs_to_jiffies(200)); - - clear_bit(ATKBD_FLAG_ACK, &atkbd->flags); - return -atkbd->nak; -} - -/* - * atkbd_command() sends a command, and its parameters to the keyboard, - * then waits for the response and puts it in the param array. - * - * atkbd_command() can only be called from a process context - */ - -static int atkbd_command(struct atkbd *atkbd, unsigned char *param, int command) -{ - int timeout; - int send = (command >> 12) & 0xf; - int receive = (command >> 8) & 0xf; - int rc = -1; - int i; - - timeout = msecs_to_jiffies(command == ATKBD_CMD_RESET_BAT ? 4000 : 500); - - down(&atkbd->cmd_sem); - clear_bit(ATKBD_FLAG_CMD, &atkbd->flags); - - if (receive && param) - for (i = 0; i < receive; i++) - atkbd->cmdbuf[(receive - 1) - i] = param[i]; - - atkbd->cmdcnt = receive; - - if (command & 0xff) - if (atkbd_sendbyte(atkbd, command & 0xff)) - goto out; - - for (i = 0; i < send; i++) - if (atkbd_sendbyte(atkbd, param[i])) - goto out; - - timeout = wait_event_interruptible_timeout(atkbd->wait, - !test_bit(ATKBD_FLAG_CMD1, &atkbd->flags), timeout); - - if (atkbd->cmdcnt && timeout > 0) { - if (command == ATKBD_CMD_RESET_BAT && jiffies_to_msecs(timeout) > 100) - timeout = msecs_to_jiffies(100); - - if (command == ATKBD_CMD_GETID && - atkbd->cmdbuf[receive - 1] != 0xab && atkbd->cmdbuf[receive - 1] != 0xac) { - /* - * Device behind the port is not a keyboard - * so we don't need to wait for the 2nd byte - * of ID response. - */ - clear_bit(ATKBD_FLAG_CMD, &atkbd->flags); - atkbd->cmdcnt = 0; - } - - wait_event_interruptible_timeout(atkbd->wait, - !test_bit(ATKBD_FLAG_CMD, &atkbd->flags), timeout); - } - - if (param) - for (i = 0; i < receive; i++) - param[i] = atkbd->cmdbuf[(receive - 1) - i]; - - if (atkbd->cmdcnt && (command != ATKBD_CMD_RESET_BAT || atkbd->cmdcnt != 1)) - goto out; - - rc = 0; - -out: - clear_bit(ATKBD_FLAG_CMD, &atkbd->flags); - clear_bit(ATKBD_FLAG_CMD1, &atkbd->flags); - up(&atkbd->cmd_sem); - - return rc; -} - -/* - * atkbd_execute_scheduled_command() sends a command, previously scheduled by - * atkbd_schedule_command(), to the keyboard. - */ - -static void atkbd_execute_scheduled_command(void *data) -{ - struct atkbd_work *atkbd_work = data; - - atkbd_command(atkbd_work->atkbd, atkbd_work->param, atkbd_work->command); - - kfree(atkbd_work); -} - -/* - * atkbd_schedule_command() allows to schedule delayed execution of a keyboard - * command and can be used to issue a command from an interrupt or softirq - * context. - */ - -static int atkbd_schedule_command(struct atkbd *atkbd, unsigned char *param, int command) -{ - struct atkbd_work *atkbd_work; - int send = (command >> 12) & 0xf; - int receive = (command >> 8) & 0xf; - - if (!test_bit(ATKBD_FLAG_ENABLED, &atkbd->flags)) - return -1; - - if (!(atkbd_work = kmalloc(sizeof(struct atkbd_work) + max(send, receive), GFP_ATOMIC))) - return -1; - - memset(atkbd_work, 0, sizeof(struct atkbd_work)); - atkbd_work->atkbd = atkbd; - atkbd_work->command = command; - memcpy(atkbd_work->param, param, send); - INIT_WORK(&atkbd_work->work, atkbd_execute_scheduled_command, atkbd_work); - - if (!schedule_work(&atkbd_work->work)) { - kfree(atkbd_work); - return -1; - } - - return 0; -} - /* * Event callback from the input module. Events that change the state of @@ -599,7 +428,7 @@ param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0) | (test_bit(LED_NUML, dev->led) ? 2 : 0) | (test_bit(LED_CAPSL, dev->led) ? 4 : 0); - atkbd_schedule_command(atkbd, param, ATKBD_CMD_SETLEDS); + ps2_schedule_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS); if (atkbd->extra) { param[0] = 0; @@ -608,7 +437,7 @@ | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0) | (test_bit(LED_MISC, dev->led) ? 0x10 : 0) | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0); - atkbd_schedule_command(atkbd, param, ATKBD_CMD_EX_SETLEDS); + ps2_schedule_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS); } return 0; @@ -616,7 +445,7 @@ case EV_REP: - if (atkbd_softrepeat) return 0; + if (atkbd->softrepeat) return 0; i = j = 0; while (i < 32 && period[i] < dev->rep[REP_PERIOD]) i++; @@ -624,7 +453,7 @@ dev->rep[REP_PERIOD] = period[i]; dev->rep[REP_DELAY] = delay[j]; param[0] = i | (j << 5); - atkbd_schedule_command(atkbd, param, ATKBD_CMD_SETREP); + ps2_schedule_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP); return 0; } @@ -633,11 +462,36 @@ } /* + * atkbd_enable() signals that interrupt handler is allowed to + * generate input events. + */ + +static inline void atkbd_enable(struct atkbd *atkbd) +{ + serio_pause_rx(atkbd->ps2dev.serio); + atkbd->enabled = 1; + serio_continue_rx(atkbd->ps2dev.serio); +} + +/* + * atkbd_disable() tells input handler that all incoming data except + * for ACKs and command response should be dropped. + */ + +static inline void atkbd_disable(struct atkbd *atkbd) +{ + serio_pause_rx(atkbd->ps2dev.serio); + atkbd->enabled = 0; + serio_continue_rx(atkbd->ps2dev.serio); +} + +/* * atkbd_probe() probes for an AT keyboard on a serio port. */ static int atkbd_probe(struct atkbd *atkbd) { + struct ps2dev *ps2dev = &atkbd->ps2dev; unsigned char param[2]; /* @@ -647,8 +501,8 @@ */ if (atkbd_reset) - if (atkbd_command(atkbd, NULL, ATKBD_CMD_RESET_BAT)) - printk(KERN_WARNING "atkbd.c: keyboard reset failed on %s\n", atkbd->serio->phys); + if (ps2_command(ps2dev, NULL, ATKBD_CMD_RESET_BAT)) + printk(KERN_WARNING "atkbd.c: keyboard reset failed on %s\n", ps2dev->serio->phys); /* * Then we check the keyboard ID. We should get 0xab83 under normal conditions. @@ -658,7 +512,7 @@ */ param[0] = param[1] = 0xa5; /* initialize with invalid values */ - if (atkbd_command(atkbd, param, ATKBD_CMD_GETID)) { + if (ps2_command(ps2dev, param, ATKBD_CMD_GETID)) { /* * If the get ID command failed, we check if we can at least set the LEDs on @@ -666,7 +520,7 @@ * the LEDs off, which we want anyway. */ param[0] = 0; - if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS)) + if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS)) return -1; atkbd->id = 0xabba; return 0; @@ -686,15 +540,17 @@ } /* - * atkbd_set_3 checks if a keyboard has a working Set 3 support, and + * atkbd_select_set checks if a keyboard has a working Set 3 support, and * sets it into that. Unfortunately there are keyboards that can be switched * to Set 3, but don't work well in that (BTC Multimedia ...) */ -static int atkbd_set_3(struct atkbd *atkbd) +static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra) { + struct ps2dev *ps2dev = &atkbd->ps2dev; unsigned char param[2]; + atkbd->extra = 0; /* * For known special keyboards we can go ahead and set the correct set. * We check for NCD PS/2 Sun, NorthGate OmniKey 101 and @@ -706,47 +562,48 @@ if (atkbd->id == 0xaca1) { param[0] = 3; - atkbd_command(atkbd, param, ATKBD_CMD_SSCANSET); + ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET); return 3; } - if (atkbd_extra) { + if (allow_extra) { param[0] = 0x71; - if (!atkbd_command(atkbd, param, ATKBD_CMD_EX_ENABLE)) { + if (!ps2_command(ps2dev, param, ATKBD_CMD_EX_ENABLE)) { atkbd->extra = 1; return 2; } } - if (atkbd_set != 3) + if (target_set != 3) return 2; - if (!atkbd_command(atkbd, param, ATKBD_CMD_OK_GETID)) { + if (!ps2_command(ps2dev, param, ATKBD_CMD_OK_GETID)) { atkbd->id = param[0] << 8 | param[1]; return 2; } param[0] = 3; - if (atkbd_command(atkbd, param, ATKBD_CMD_SSCANSET)) + if (ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET)) return 2; param[0] = 0; - if (atkbd_command(atkbd, param, ATKBD_CMD_GSCANSET)) + if (ps2_command(ps2dev, param, ATKBD_CMD_GSCANSET)) return 2; if (param[0] != 3) { param[0] = 2; - if (atkbd_command(atkbd, param, ATKBD_CMD_SSCANSET)) + if (ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET)) return 2; } - atkbd_command(atkbd, param, ATKBD_CMD_SETALL_MBR); + ps2_command(ps2dev, param, ATKBD_CMD_SETALL_MBR); return 3; } -static int atkbd_enable(struct atkbd *atkbd) +static int atkbd_activate(struct atkbd *atkbd) { + struct ps2dev *ps2dev = &atkbd->ps2dev; unsigned char param[1]; /* @@ -754,7 +611,7 @@ */ param[0] = 0; - if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS)) + if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS)) return -1; /* @@ -762,16 +619,16 @@ */ param[0] = 0; - if (atkbd_command(atkbd, param, ATKBD_CMD_SETREP)) + if (ps2_command(ps2dev, param, ATKBD_CMD_SETREP)) return -1; /* * Enable the keyboard to receive keystrokes. */ - if (atkbd_command(atkbd, NULL, ATKBD_CMD_ENABLE)) { + if (ps2_command(ps2dev, NULL, ATKBD_CMD_ENABLE)) { printk(KERN_ERR "atkbd.c: Failed to enable keyboard on %s\n", - atkbd->serio->phys); + ps2dev->serio->phys); return -1; } @@ -786,9 +643,10 @@ static void atkbd_cleanup(struct serio *serio) { struct atkbd *atkbd = serio->private; - atkbd_command(atkbd, NULL, ATKBD_CMD_RESET_BAT); + ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_BAT); } + /* * atkbd_disconnect() closes and frees. */ @@ -797,15 +655,108 @@ { struct atkbd *atkbd = serio->private; - clear_bit(ATKBD_FLAG_ENABLED, &atkbd->flags); + atkbd_disable(atkbd); + + /* make sure we don't have a command in flight */ synchronize_kernel(); flush_scheduled_work(); + device_remove_file(&serio->dev, &atkbd_attr_extra); + device_remove_file(&serio->dev, &atkbd_attr_scroll); + device_remove_file(&serio->dev, &atkbd_attr_set); + device_remove_file(&serio->dev, &atkbd_attr_softrepeat); + device_remove_file(&serio->dev, &atkbd_attr_softraw); + input_unregister_device(&atkbd->dev); serio_close(serio); kfree(atkbd); } + +/* + * atkbd_set_device_attrs() initializes keyboard's keycode table + * according to the selected scancode set + */ + +static void atkbd_set_keycode_table(struct atkbd *atkbd) +{ + int i, j; + + memset(atkbd->keycode, 0, sizeof(atkbd->keycode)); + + if (atkbd->translated) { + for (i = 0; i < 128; i++) { + atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]]; + atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80]; + if (atkbd->scroll) + for (j = 0; i < 5; i++) { + if (atkbd_unxlate_table[i] == atkbd_scroll_keys[j][1]) + atkbd->keycode[i] = atkbd_scroll_keys[j][0]; + if ((atkbd_unxlate_table[i] | 0x80) == atkbd_scroll_keys[j][1]) + atkbd->keycode[i | 0x80] = atkbd_scroll_keys[j][0]; + } + } + } else if (atkbd->set == 3) { + memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode)); + } else { + memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode)); + + if (atkbd->scroll) + for (i = 0; i < 5; i++) + atkbd->keycode[atkbd_scroll_keys[i][1]] = atkbd_scroll_keys[i][0]; + } +} + +/* + * atkbd_set_device_attrs() sets up keyboard's input device structure + */ + +static void atkbd_set_device_attrs(struct atkbd *atkbd) +{ + int i; + + memset(&atkbd->dev, 0, sizeof(struct input_dev)); + + init_input_dev(&atkbd->dev); + + atkbd->dev.name = atkbd->name; + atkbd->dev.phys = atkbd->phys; + atkbd->dev.id.bustype = BUS_I8042; + atkbd->dev.id.vendor = 0x0001; + atkbd->dev.id.product = atkbd->translated ? 1 : atkbd->set; + atkbd->dev.id.version = atkbd->id; + atkbd->dev.event = atkbd_event; + atkbd->dev.private = atkbd; + + atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC); + + if (atkbd->write) { + atkbd->dev.evbit[0] |= BIT(EV_LED); + atkbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); + } + + if (atkbd->extra) + atkbd->dev.ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) | + BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC); + + if (!atkbd->softrepeat) { + atkbd->dev.rep[REP_DELAY] = 250; + atkbd->dev.rep[REP_PERIOD] = 33; + } + + atkbd->dev.mscbit[0] = atkbd->softraw ? BIT(MSC_SCAN) : BIT(MSC_RAW) | BIT(MSC_SCAN); + + if (atkbd->scroll) { + atkbd->dev.evbit[0] |= BIT(EV_REL); + atkbd->dev.relbit[0] = BIT(REL_WHEEL); + set_bit(BTN_MIDDLE, atkbd->dev.keybit); + } + + for (i = 0; i < 512; i++) + if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL) + set_bit(atkbd->keycode[i], atkbd->dev.keybit); +} + /* * atkbd_connect() is called when the serio module finds and interface * that isn't handled yet by an appropriate device driver. We check if @@ -816,14 +767,12 @@ static void atkbd_connect(struct serio *serio, struct serio_driver *drv) { struct atkbd *atkbd; - int i; if (!(atkbd = kmalloc(sizeof(struct atkbd), GFP_KERNEL))) return; memset(atkbd, 0, sizeof(struct atkbd)); - init_MUTEX(&atkbd->cmd_sem); - init_waitqueue_head(&atkbd->wait); + ps2_init(&atkbd->ps2dev, serio); switch (serio->type & SERIO_TYPE) { @@ -841,31 +790,19 @@ return; } - if (!atkbd->write) - atkbd_softrepeat = 1; - if (atkbd_softrepeat) - atkbd_softraw = 1; - - if (atkbd->write) { - atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP) | BIT(EV_MSC); - atkbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); - } else atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC); - atkbd->dev.mscbit[0] = atkbd_softraw ? BIT(MSC_SCAN) : BIT(MSC_RAW) | BIT(MSC_SCAN); + atkbd->softraw = atkbd_softraw; + atkbd->softrepeat = atkbd_softrepeat; + atkbd->scroll = atkbd_scroll; - if (!atkbd_softrepeat) { - atkbd->dev.rep[REP_DELAY] = 250; - atkbd->dev.rep[REP_PERIOD] = 33; - } else atkbd_softraw = 1; - - atkbd->serio = serio; + if (!atkbd->write) + atkbd->softrepeat = 1; - init_input_dev(&atkbd->dev); + if (atkbd->softrepeat) + atkbd->softraw = 1; atkbd->dev.keycode = atkbd->keycode; atkbd->dev.keycodesize = sizeof(unsigned char); atkbd->dev.keycodemax = ARRAY_SIZE(atkbd_set2_keycode); - atkbd->dev.event = atkbd_event; - atkbd->dev.private = atkbd; serio->private = atkbd; @@ -883,56 +820,34 @@ return; } - atkbd->set = atkbd_set_3(atkbd); - atkbd_enable(atkbd); + atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra); + atkbd_activate(atkbd); } else { atkbd->set = 2; atkbd->id = 0xab00; } - if (atkbd->extra) { - atkbd->dev.ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) | BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC); + if (atkbd->extra) sprintf(atkbd->name, "AT Set 2 Extra keyboard"); - } else + else sprintf(atkbd->name, "AT %s Set %d keyboard", atkbd->translated ? "Translated" : "Raw", atkbd->set); sprintf(atkbd->phys, "%s/input0", serio->phys); - if (atkbd_scroll) { - for (i = 0; i < 5; i++) - atkbd_set2_keycode[atkbd_scroll_keys[i][1]] = atkbd_scroll_keys[i][0]; - atkbd->dev.evbit[0] |= BIT(EV_REL); - atkbd->dev.relbit[0] = BIT(REL_WHEEL); - set_bit(BTN_MIDDLE, atkbd->dev.keybit); - } - - if (atkbd->translated) { - for (i = 0; i < 128; i++) { - atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]]; - atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80]; - } - } else if (atkbd->set == 3) { - memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode)); - } else { - memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode)); - } - - atkbd->dev.name = atkbd->name; - atkbd->dev.phys = atkbd->phys; - atkbd->dev.id.bustype = BUS_I8042; - atkbd->dev.id.vendor = 0x0001; - atkbd->dev.id.product = atkbd->translated ? 1 : atkbd->set; - atkbd->dev.id.version = atkbd->id; - - for (i = 0; i < 512; i++) - if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL) - set_bit(atkbd->keycode[i], atkbd->dev.keybit); + atkbd_set_keycode_table(atkbd); + atkbd_set_device_attrs(atkbd); input_register_device(&atkbd->dev); - set_bit(ATKBD_FLAG_ENABLED, &atkbd->flags); + device_create_file(&serio->dev, &atkbd_attr_extra); + device_create_file(&serio->dev, &atkbd_attr_scroll); + device_create_file(&serio->dev, &atkbd_attr_set); + device_create_file(&serio->dev, &atkbd_attr_softrepeat); + device_create_file(&serio->dev, &atkbd_attr_softraw); + + atkbd_enable(atkbd); printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys); } @@ -948,11 +863,13 @@ struct serio_driver *drv = serio->drv; unsigned char param[1]; - if (!drv) { + if (!atkbd || !drv) { printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n"); return -1; } + atkbd_disable(atkbd); + if (atkbd->write) { param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0) | (test_bit(LED_NUML, atkbd->dev.led) ? 2 : 0) @@ -960,16 +877,16 @@ if (atkbd_probe(atkbd)) return -1; - if (atkbd->set != atkbd_set_3(atkbd)) + if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra)) return -1; - atkbd_enable(atkbd); + atkbd_activate(atkbd); - if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS)) + if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS)) return -1; } - set_bit(ATKBD_FLAG_ENABLED, &atkbd->flags); + atkbd_enable(atkbd); return 0; } @@ -985,6 +902,192 @@ .disconnect = atkbd_disconnect, .cleanup = atkbd_cleanup, }; + +static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, + ssize_t (*handler)(struct atkbd *, char *)) +{ + struct serio *serio = to_serio_port(dev); + int retval; + + retval = serio_pin_driver(serio); + if (retval) + return retval; + + if (serio->drv != &atkbd_drv) { + retval = -ENODEV; + goto out; + } + + retval = handler((struct atkbd *)serio->private, buf); + +out: + serio_unpin_driver(serio); + return retval; +} + +static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count, + int (*handler)(struct atkbd *, const char *, size_t)) +{ + struct serio *serio = to_serio_port(dev); + struct atkbd *atkbd; + int retval; + + retval = serio_pin_driver(serio); + if (retval) + return retval; + + if (serio->drv != &atkbd_drv) { + retval = -ENODEV; + goto out; + } + + atkbd = serio->private; + atkbd_disable(atkbd); + retval = handler(atkbd, buf, count); + atkbd_enable(atkbd); + +out: + serio_unpin_driver(serio); + return retval; +} + +static ssize_t atkbd_show_extra(struct atkbd *atkbd, char *buf) +{ + return sprintf(buf, "%d\n", atkbd->extra ? 1 : 0); +} + +static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count) +{ + unsigned long value; + char *rest; + + if (!atkbd->write) + return -EIO; + + value = simple_strtoul(buf, &rest, 10); + if (*rest || value > 1) + return -EINVAL; + + if (atkbd->extra != value) { + /* unregister device as it's properties will change */ + input_unregister_device(&atkbd->dev); + atkbd->set = atkbd_select_set(atkbd, atkbd->set, value); + atkbd_activate(atkbd); + atkbd_set_device_attrs(atkbd); + input_register_device(&atkbd->dev); + } + return count; +} + +static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf) +{ + return sprintf(buf, "%d\n", atkbd->scroll ? 1 : 0); +} + +static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count) +{ + unsigned long value; + char *rest; + + value = simple_strtoul(buf, &rest, 10); + if (*rest || value > 1) + return -EINVAL; + + if (atkbd->scroll != value) { + /* unregister device as it's properties will change */ + input_unregister_device(&atkbd->dev); + atkbd->scroll = value; + atkbd_set_keycode_table(atkbd); + atkbd_set_device_attrs(atkbd); + input_register_device(&atkbd->dev); + } + return count; +} + +static ssize_t atkbd_show_set(struct atkbd *atkbd, char *buf) +{ + return sprintf(buf, "%d\n", atkbd->set); +} + +static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count) +{ + unsigned long value; + char *rest; + + if (!atkbd->write) + return -EIO; + + value = simple_strtoul(buf, &rest, 10); + if (*rest || (value != 2 && value != 3)) + return -EINVAL; + + if (atkbd->set != value) { + /* unregister device as it's properties will change */ + input_unregister_device(&atkbd->dev); + atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra); + atkbd_activate(atkbd); + atkbd_set_keycode_table(atkbd); + atkbd_set_device_attrs(atkbd); + input_register_device(&atkbd->dev); + } + return count; +} + +static ssize_t atkbd_show_softrepeat(struct atkbd *atkbd, char *buf) +{ + return sprintf(buf, "%d\n", atkbd->softrepeat ? 1 : 0); +} + +static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count) +{ + unsigned long value; + char *rest; + + if (!atkbd->write) + return -EIO; + + value = simple_strtoul(buf, &rest, 10); + if (*rest || value > 1) + return -EINVAL; + + if (atkbd->softrepeat != value) { + /* unregister device as it's properties will change */ + input_unregister_device(&atkbd->dev); + atkbd->softrepeat = value; + if (atkbd->softrepeat) + atkbd->softraw = 1; + atkbd_set_device_attrs(atkbd); + input_register_device(&atkbd->dev); + } + + return count; +} + + +static ssize_t atkbd_show_softraw(struct atkbd *atkbd, char *buf) +{ + return sprintf(buf, "%d\n", atkbd->softraw ? 1 : 0); +} + +static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count) +{ + unsigned long value; + char *rest; + + value = simple_strtoul(buf, &rest, 10); + if (*rest || value > 1) + return -EINVAL; + + if (atkbd->softraw != value) { + /* unregister device as it's properties will change */ + input_unregister_device(&atkbd->dev); + atkbd->softraw = value; + atkbd_set_device_attrs(atkbd); + input_register_device(&atkbd->dev); + } + return count; +} + int __init atkbd_init(void) { diff -Nru a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig --- a/drivers/input/mouse/Kconfig 2004-09-23 21:12:57 -07:00 +++ b/drivers/input/mouse/Kconfig 2004-09-23 21:12:57 -07:00 @@ -16,6 +16,7 @@ default y depends on INPUT && INPUT_MOUSE select SERIO + select SERIO_LIBPS2 select SERIO_I8042 if PC select SERIO_GSCPS2 if GSC ---help--- diff -Nru a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile --- a/drivers/input/mouse/Makefile 2004-09-23 21:12:57 -07:00 +++ b/drivers/input/mouse/Makefile 2004-09-23 21:12:57 -07:00 @@ -14,4 +14,4 @@ obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o -psmouse-objs := psmouse-base.o logips2pp.o synaptics.o +psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o diff -Nru a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/input/mouse/alps.c 2004-09-23 21:12:57 -07:00 @@ -0,0 +1,430 @@ +/* + * ALPS touchpad PS/2 mouse driver + * + * Copyright (c) 2003 Neil Brown + * Copyright (c) 2003 Peter Osterlund + * Copyright (c) 2004 Dmitry Torokhov + * + * ALPS detection, tap switching and status querying info is taken from + * tpconfig utility (by C. Scott Ananian and Bruce Kall). + * + * 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 +#include +#include + +#include "psmouse.h" +#include "alps.h" + +#undef DEBUG +#ifdef DEBUG +#define dbg(format, arg...) printk(KERN_INFO "alps.c: " format "\n", ## arg) +#else +#define dbg(format, arg...) do {} while (0) +#endif + +#define ALPS_MODEL_GLIDEPOINT 1 +#define ALPS_MODEL_DUALPOINT 2 + +struct alps_model_info { + unsigned char signature[3]; + unsigned char model; +} alps_model_data[] = { + { { 0x33, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT }, + { { 0x53, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT }, + { { 0x53, 0x02, 0x14 }, ALPS_MODEL_GLIDEPOINT }, + { { 0x63, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT }, + { { 0x63, 0x02, 0x14 }, ALPS_MODEL_GLIDEPOINT }, + { { 0x73, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT }, + { { 0x73, 0x02, 0x14 }, ALPS_MODEL_GLIDEPOINT }, + { { 0x63, 0x02, 0x28 }, ALPS_MODEL_GLIDEPOINT }, + { { 0x63, 0x02, 0x3c }, ALPS_MODEL_GLIDEPOINT }, + { { 0x63, 0x02, 0x50 }, ALPS_MODEL_GLIDEPOINT }, + { { 0x63, 0x02, 0x64 }, ALPS_MODEL_GLIDEPOINT }, + { { 0x20, 0x02, 0x0e }, ALPS_MODEL_DUALPOINT }, + { { 0x22, 0x02, 0x0a }, ALPS_MODEL_DUALPOINT }, + { { 0x22, 0x02, 0x14 }, ALPS_MODEL_DUALPOINT }, +}; + +/* + * ALPS abolute Mode + * byte 0: 1 1 1 1 1 mid0 rig0 lef0 + * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 + * byte 2: 0 x10 x9 x8 x7 up1 fin ges + * byte 3: 0 y9 y8 y7 1 mid1 rig1 lef1 + * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 + * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 + * + * On a dualpoint, {mid,rig,lef}0 are the stick, 1 are the pad. + * We just 'or' them together for now. + * + * We used to send 'ges'tures as BTN_TOUCH but this made it impossible + * to disable tap events in the synaptics driver since the driver + * was unable to distinguish a gesture tap from an actual button click. + * A tap gesture now creates an emulated touch that the synaptics + * driver can interpret as a tap event, if MaxTapTime=0 and + * MaxTapMove=0 then the driver will ignore taps. + * + * The touchpad on an 'Acer Aspire' has 4 buttons: + * left,right,up,down. + * This device always sets {mid,rig,lef}0 to 1 and + * reflects left,right,down,up in lef1,rig1,mid1,up1. + */ + +static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs) +{ + unsigned char *packet = psmouse->packet; + struct input_dev *dev = &psmouse->dev; + int x, y, z; + int left = 0, right = 0, middle = 0; + + input_regs(dev, regs); + + if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */ + x = packet[1]; + if (packet[0] & 0x10) + x = x - 256; + y = packet[2]; + if (packet[0] & 0x20) + y = y - 256; + left = (packet[0] ) & 1; + right = (packet[0] >> 1) & 1; + + input_report_rel(dev, REL_X, x); + input_report_rel(dev, REL_Y, -y); + input_report_key(dev, BTN_A, left); + input_report_key(dev, BTN_B, right); + input_sync(dev); + return; + } + + x = (packet[1] & 0x7f) | ((packet[2] & 0x78)<<(7-3)); + y = (packet[4] & 0x7f) | ((packet[3] & 0x70)<<(7-4)); + z = packet[5]; + + if (z == 127) { /* DualPoint stick is relative, not absolute */ + if (x > 383) + x = x - 768; + if (y > 255) + y = y - 512; + left = packet[3] & 1; + right = (packet[3] >> 1) & 1; + + input_report_rel(dev, REL_X, x); + input_report_rel(dev, REL_Y, -y); + input_report_key(dev, BTN_LEFT, left); + input_report_key(dev, BTN_RIGHT, right); + input_sync(dev); + return; + } + + if (z > 30) input_report_key(dev, BTN_TOUCH, 1); + if (z < 25) input_report_key(dev, BTN_TOUCH, 0); + + if (z > 0) { + input_report_abs(dev, ABS_X, x); + input_report_abs(dev, ABS_Y, y); + } + input_report_abs(dev, ABS_PRESSURE, z); + input_report_key(dev, BTN_TOOL_FINGER, z > 0); + + left |= (packet[2] ) & 1; + left |= (packet[3] ) & 1; + right |= (packet[3] >> 1) & 1; + if (packet[0] == 0xff) { + int back = (packet[3] >> 2) & 1; + int forward = (packet[2] >> 2) & 1; + if (back && forward) { + middle = 1; + back = 0; + forward = 0; + } + input_report_key(dev, BTN_BACK, back); + input_report_key(dev, BTN_FORWARD, forward); + } else { + left |= (packet[0] ) & 1; + right |= (packet[0] >> 1) & 1; + middle |= (packet[0] >> 2) & 1; + middle |= (packet[3] >> 2) & 1; + } + + input_report_key(dev, BTN_LEFT, left); + input_report_key(dev, BTN_RIGHT, right); + input_report_key(dev, BTN_MIDDLE, middle); + + input_sync(dev); +} + +static psmouse_ret_t alps_process_byte(struct psmouse *psmouse, struct pt_regs *regs) +{ + if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ + if (psmouse->pktcnt == 3) { + alps_process_packet(psmouse, regs); + return PSMOUSE_FULL_PACKET; + } + return PSMOUSE_GOOD_DATA; + } + + /* ALPS absolute mode packets start with 0b11111mrl */ + if ((psmouse->packet[0] & 0xf8) != 0xf8) + return PSMOUSE_BAD_DATA; + + /* Bytes 2 - 6 should have 0 in the highest bit */ + if (psmouse->pktcnt > 1 && psmouse->pktcnt <= 6 && + (psmouse->packet[psmouse->pktcnt] & 0x80)) + return PSMOUSE_BAD_DATA; + + if (psmouse->pktcnt == 6) { + alps_process_packet(psmouse, regs); + return PSMOUSE_FULL_PACKET; + } + + return PSMOUSE_GOOD_DATA; +} + +int alps_get_model(struct psmouse *psmouse) +{ + struct ps2dev *ps2dev = &psmouse->ps2dev; + unsigned char param[4]; + int i; + + /* + * First try "E6 report". + * ALPS should return 0x00,0x00,0x0a or 0x00,0x00,0x64 + */ + param[0] = 0; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) + return -1; + + param[0] = param[1] = param[2] = 0xff; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) + return -1; + + dbg("E6 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]); + + if (param[0] != 0x00 || param[1] != 0x00 || (param[2] != 0x0a && param[2] != 0x64)) + return -1; + + /* Now try "E7 report". ALPS should return 0x33 in byte 1 */ + param[0] = 0; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21)) + return -1; + + param[0] = param[1] = param[2] = 0xff; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) + return -1; + + dbg("E7 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]); + + for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) + if (!memcmp(param, alps_model_data[i].signature, sizeof(alps_model_data[i].signature))) + return alps_model_data[i].model; + + return -1; +} + +/* + * For DualPoint devices select the device that should respond to + * subsequent commands. It looks like glidepad is behind stickpointer, + * I'd thought it would be other way around... + */ +static int alps_passthrough_mode(struct psmouse *psmouse, int enable) +{ + struct ps2dev *ps2dev = &psmouse->ps2dev; + unsigned char param[3]; + int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; + + if (ps2_command(ps2dev, NULL, cmd) || + ps2_command(ps2dev, NULL, cmd) || + ps2_command(ps2dev, NULL, cmd) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE)) + return -1; + + /* we may get 3 more bytes, just ignore them */ + ps2_command(ps2dev, param, 0x0300); + + return 0; +} + +static int alps_magic_knock(struct psmouse *psmouse) +{ + struct ps2dev *ps2dev = &psmouse->ps2dev; + + /* Try ALPS magic knock - 4 disable before enable */ + if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) + return -1; + return 0; +} + +static int alps_absolute_mode(struct psmouse *psmouse) +{ + if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS)) + return -1; + + if (alps_passthrough_mode(psmouse, 1)) + return -1; + + if (alps_magic_knock(psmouse)) + return -1; + + if (alps_passthrough_mode(psmouse, 0)) + return -1; + + if (alps_magic_knock(psmouse)) + return -1; + + /* + * Switch mouse to poll (remote) mode so motion data will not + * get in our way + */ + return ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETPOLL); +} + +static int alps_get_status(struct psmouse *psmouse, char *param) +{ + struct ps2dev *ps2dev = &psmouse->ps2dev; + + /* Get status: 0xF5 0xF5 0xF5 0xE9 */ + if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || + ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) + return -1; + + dbg("Status: %2.2x %2.2x %2.2x", param[0], param[1], param[2]); + + return 0; +} + +/* + * Turn touchpad tapping on or off. The sequences are: + * 0xE9 0xF5 0xF5 0xF3 0x0A to enable, + * 0xE9 0xF5 0xF5 0xE8 0x00 to disable. + * My guess that 0xE9 (GetInfo) is here as a sync point. + * For models that also have stickpointer (DualPoints) its tapping + * is controlled separately (0xE6 0xE6 0xE6 0xF3 0x14|0x0A) but + * we don't fiddle with it. + */ +static int alps_tap_mode(struct psmouse *psmouse, int model, int enable) +{ + int rc = 0; + struct ps2dev *ps2dev = &psmouse->ps2dev; + int cmd = enable ? PSMOUSE_CMD_SETRATE : PSMOUSE_CMD_SETRES; + unsigned char tap_arg = enable ? 0x0A : 0x00; + unsigned char param[4]; + + if (model == ALPS_MODEL_DUALPOINT && alps_passthrough_mode(psmouse, 1)) + return -1; + + if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || + ps2_command(ps2dev, &tap_arg, cmd)) + rc = -1; + + if (model == ALPS_MODEL_DUALPOINT && alps_passthrough_mode(psmouse, 0)) + return -1; + + if (alps_get_status(psmouse, param)) + return -1; + + + return rc; +} + +static int alps_reconnect(struct psmouse *psmouse) +{ + int model; + unsigned char param[4]; + + if ((model = alps_get_model(psmouse)) < 0) + return -1; + + if (alps_get_status(psmouse, param)) + return -1; + + if ((model == ALPS_MODEL_DUALPOINT ? param[2] : param[0]) & 0x04) + alps_tap_mode(psmouse, model, 0); + + if (alps_absolute_mode(psmouse)) { + printk(KERN_ERR "alps.c: Failed to enable absolute mode\n"); + return -1; + } + + return 0; +} + +static void alps_disconnect(struct psmouse *psmouse) +{ + psmouse_reset(psmouse); +} + +int alps_init(struct psmouse *psmouse) +{ + unsigned char param[4]; + int model; + + if ((model = alps_get_model(psmouse)) < 0) + return -1; + + if (alps_get_status(psmouse, param)) { + printk(KERN_ERR "alps.c: touchpad status report request failed\n"); + return -1; + } + + printk(KERN_INFO "ALPS Touchpad (%s) detected\n", + model == ALPS_MODEL_GLIDEPOINT ? "Glidepoint" : "Dualpoint"); + + if ((model == ALPS_MODEL_DUALPOINT ? param[2] : param[0]) & 0x04) { + printk(KERN_INFO " Disabling hardware tapping\n"); + if (alps_tap_mode(psmouse, model, 0)) + printk(KERN_WARNING "alps.c: Failed to disable hardware tapping\n"); + } + + if (alps_absolute_mode(psmouse)) { + printk(KERN_ERR "alps.c: Failed to enable absolute mode\n"); + return -1; + } + + psmouse->dev.evbit[LONG(EV_REL)] |= BIT(EV_REL); + psmouse->dev.relbit[LONG(REL_X)] |= BIT(REL_X); + psmouse->dev.relbit[LONG(REL_Y)] |= BIT(REL_Y); + psmouse->dev.keybit[LONG(BTN_A)] |= BIT(BTN_A); + psmouse->dev.keybit[LONG(BTN_B)] |= BIT(BTN_B); + + psmouse->dev.evbit[LONG(EV_ABS)] |= BIT(EV_ABS); + input_set_abs_params(&psmouse->dev, ABS_X, 0, 1023, 0, 0); + input_set_abs_params(&psmouse->dev, ABS_Y, 0, 1023, 0, 0); + input_set_abs_params(&psmouse->dev, ABS_PRESSURE, 0, 127, 0, 0); + + psmouse->dev.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH); + psmouse->dev.keybit[LONG(BTN_TOOL_FINGER)] |= BIT(BTN_TOOL_FINGER); + psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD); + psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK); + + psmouse->protocol_handler = alps_process_byte; + psmouse->disconnect = alps_disconnect; + psmouse->reconnect = alps_reconnect; + + return 0; +} + +int alps_detect(struct psmouse *psmouse) +{ + return alps_get_model(psmouse) < 0 ? 0 : 1; +} + diff -Nru a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/input/mouse/alps.h 2004-09-23 21:12:57 -07:00 @@ -0,0 +1,17 @@ +/* + * ALPS touchpad PS/2 mouse driver + * + * Copyright (c) 2003 Peter Osterlund + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#ifndef _ALPS_H +#define _ALPS_H + +int alps_detect(struct psmouse *psmouse); +int alps_init(struct psmouse *psmouse); + +#endif diff -Nru a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c --- a/drivers/input/mouse/logips2pp.c 2004-09-23 21:12:57 -07:00 +++ b/drivers/input/mouse/logips2pp.c 2004-09-23 21:12:57 -07:00 @@ -11,6 +11,7 @@ #include #include +#include #include "psmouse.h" #include "logips2pp.h" @@ -97,7 +98,7 @@ if (psmouse_sliced_command(psmouse, command)) return -1; - if (psmouse_command(psmouse, param, PSMOUSE_CMD_POLL)) + if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL)) return -1; return 0; @@ -113,19 +114,20 @@ static void ps2pp_set_smartscroll(struct psmouse *psmouse) { + struct ps2dev *ps2dev = &psmouse->ps2dev; unsigned char param[4]; ps2pp_cmd(psmouse, param, 0x32); param[0] = 0; - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); if (psmouse_smartscroll < 2) { /* 0 - disabled, 1 - enabled */ param[0] = psmouse_smartscroll; - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); } } @@ -137,11 +139,13 @@ void ps2pp_set_800dpi(struct psmouse *psmouse) { + struct ps2dev *ps2dev = &psmouse->ps2dev; unsigned char param = 3; - psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11); - psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11); - psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11); - psmouse_command(psmouse, ¶m, PSMOUSE_CMD_SETRES); + + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); + ps2_command(ps2dev, ¶m, PSMOUSE_CMD_SETRES); } static struct ps2pp_info *get_model_info(unsigned char model) @@ -238,18 +242,19 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) { + struct ps2dev *ps2dev = &psmouse->ps2dev; unsigned char param[4]; unsigned char protocol = PSMOUSE_PS2; unsigned char model, buttons; struct ps2pp_info *model_info; param[0] = 0; - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); - psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11); - psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11); - psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11); + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); param[1] = 0; - psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO); + ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO); if (param[1] != 0) { model = ((param[0] >> 4) & 0x07) | ((param[0] << 3) & 0x78); @@ -263,16 +268,16 @@ /* Unprotect RAM */ param[0] = 0x11; param[1] = 0x04; param[2] = 0x68; - psmouse_command(psmouse, param, 0x30d1); + ps2_command(ps2dev, param, 0x30d1); /* Enable features */ param[0] = 0x11; param[1] = 0x05; param[2] = 0x0b; - psmouse_command(psmouse, param, 0x30d1); + ps2_command(ps2dev, param, 0x30d1); /* Enable PS2++ */ param[0] = 0x11; param[1] = 0x09; param[2] = 0xc3; - psmouse_command(psmouse, param, 0x30d1); + ps2_command(ps2dev, param, 0x30d1); param[0] = 0; - if (!psmouse_command(psmouse, param, 0x13d1) && + if (!ps2_command(ps2dev, param, 0x13d1) && param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14) { protocol = PSMOUSE_PS2TPP; } diff -Nru a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c --- a/drivers/input/mouse/psmouse-base.c 2004-09-23 21:12:57 -07:00 +++ b/drivers/input/mouse/psmouse-base.c 2004-09-23 21:12:57 -07:00 @@ -2,6 +2,7 @@ * PS/2 mouse driver * * Copyright (c) 1999-2002 Vojtech Pavlik + * Copyright (c) 2003-2004 Dmitry Torokhov */ /* @@ -18,9 +19,11 @@ #include #include #include +#include #include "psmouse.h" #include "synaptics.h" #include "logips2pp.h" +#include "alps.h" #define DRIVER_DESC "PS/2 mouse driver" @@ -55,7 +58,7 @@ __obsolete_setup("psmouse_resetafter="); __obsolete_setup("psmouse_rate="); -static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2"}; +static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "ThinkPS/2", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2", "AlpsPS/2" }; /* * psmouse_process_byte() analyzes the PS/2 data stream and reports @@ -110,6 +113,15 @@ } /* + * Extra button on ThinkingMouse + */ + if (psmouse->type == PSMOUSE_THINKPS) { + input_report_key(dev, BTN_EXTRA, (packet[0] >> 3) & 1); + /* Without this bit of weirdness moving up gives wildly high Y changes. */ + packet[1] |= (packet[0] & 0x40) << 1; + } + +/* * Generic PS/2 Mouse */ @@ -144,63 +156,17 @@ printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n", flags & SERIO_TIMEOUT ? " timeout" : "", flags & SERIO_PARITY ? " bad parity" : ""); - psmouse->nak = 1; - clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags); - clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags); - wake_up_interruptible(&psmouse->wait); + ps2_cmd_aborted(&psmouse->ps2dev); goto out; } - if (test_bit(PSMOUSE_FLAG_ACK, &psmouse->flags)) { - switch (data) { - case PSMOUSE_RET_ACK: - psmouse->nak = 0; - break; - - case PSMOUSE_RET_NAK: - psmouse->nak = 1; - break; - - /* - * Workaround for mice which don't ACK the Get ID command. - * These are valid mouse IDs that we recognize. - */ - case 0x00: - case 0x03: - case 0x04: - if (test_bit(PSMOUSE_FLAG_WAITID, &psmouse->flags)) { - psmouse->nak = 0; - break; - } - /* Fall through */ - default: - goto out; - } - - if (!psmouse->nak && psmouse->cmdcnt) { - set_bit(PSMOUSE_FLAG_CMD, &psmouse->flags); - set_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags); - } - clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags); - wake_up_interruptible(&psmouse->wait); - - if (data == PSMOUSE_RET_ACK || data == PSMOUSE_RET_NAK) + if (unlikely(psmouse->ps2dev.flags & PS2_FLAG_ACK)) + if (ps2_handle_ack(&psmouse->ps2dev, data)) goto out; - } - if (test_bit(PSMOUSE_FLAG_CMD, &psmouse->flags)) { - if (psmouse->cmdcnt) - psmouse->cmdbuf[--psmouse->cmdcnt] = data; - - if (test_and_clear_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags) && psmouse->cmdcnt) - wake_up_interruptible(&psmouse->wait); - - if (!psmouse->cmdcnt) { - clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags); - wake_up_interruptible(&psmouse->wait); - } - goto out; - } + if (unlikely(psmouse->ps2dev.flags & PS2_FLAG_CMD)) + if (ps2_handle_response(&psmouse->ps2dev, data)) + goto out; if (psmouse->state == PSMOUSE_INITIALIZING) goto out; @@ -246,7 +212,7 @@ if (++psmouse->out_of_sync == psmouse_resetafter) { psmouse->state = PSMOUSE_IGNORE; printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); - serio_reconnect(psmouse->serio); + serio_reconnect(psmouse->ps2dev.serio); } break; @@ -266,100 +232,6 @@ return IRQ_HANDLED; } -/* - * psmouse_sendbyte() sends a byte to the mouse, and waits for acknowledge. - * It doesn't handle retransmission, though it could - because when there would - * be need for retransmissions, the mouse has to be replaced anyway. - * - * psmouse_sendbyte() can only be called from a process context - */ - -static int psmouse_sendbyte(struct psmouse *psmouse, unsigned char byte) -{ - psmouse->nak = 1; - set_bit(PSMOUSE_FLAG_ACK, &psmouse->flags); - - if (serio_write(psmouse->serio, byte) == 0) - wait_event_interruptible_timeout(psmouse->wait, - !test_bit(PSMOUSE_FLAG_ACK, &psmouse->flags), - msecs_to_jiffies(200)); - - clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags); - return -psmouse->nak; -} - -/* - * psmouse_command() sends a command and its parameters to the mouse, - * then waits for the response and puts it in the param array. - * - * psmouse_command() can only be called from a process context - */ - -int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command) -{ - int timeout; - int send = (command >> 12) & 0xf; - int receive = (command >> 8) & 0xf; - int rc = -1; - int i; - - timeout = msecs_to_jiffies(command == PSMOUSE_CMD_RESET_BAT ? 4000 : 500); - - clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags); - if (command == PSMOUSE_CMD_GETID) - set_bit(PSMOUSE_FLAG_WAITID, &psmouse->flags); - - if (receive && param) - for (i = 0; i < receive; i++) - psmouse->cmdbuf[(receive - 1) - i] = param[i]; - - psmouse->cmdcnt = receive; - - if (command & 0xff) - if (psmouse_sendbyte(psmouse, command & 0xff)) - goto out; - - for (i = 0; i < send; i++) - if (psmouse_sendbyte(psmouse, param[i])) - goto out; - - timeout = wait_event_interruptible_timeout(psmouse->wait, - !test_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags), timeout); - - if (psmouse->cmdcnt && timeout > 0) { - if (command == PSMOUSE_CMD_RESET_BAT && jiffies_to_msecs(timeout) > 100) - timeout = msecs_to_jiffies(100); - - if (command == PSMOUSE_CMD_GETID && - psmouse->cmdbuf[receive - 1] != 0xab && psmouse->cmdbuf[receive - 1] != 0xac) { - /* - * Device behind the port is not a keyboard - * so we don't need to wait for the 2nd byte - * of ID response. - */ - clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags); - psmouse->cmdcnt = 0; - } - - wait_event_interruptible_timeout(psmouse->wait, - !test_bit(PSMOUSE_FLAG_CMD, &psmouse->flags), timeout); - } - - if (param) - for (i = 0; i < receive; i++) - param[i] = psmouse->cmdbuf[(receive - 1) - i]; - - if (psmouse->cmdcnt && (command != PSMOUSE_CMD_RESET_BAT || psmouse->cmdcnt != 1)) - goto out; - - rc = 0; - -out: - clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags); - clear_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags); - clear_bit(PSMOUSE_FLAG_WAITID, &psmouse->flags); - return rc; -} /* * psmouse_sliced_command() sends an extended PS/2 command to the mouse @@ -372,12 +244,12 @@ { int i; - if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) + if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) return -1; for (i = 6; i >= 0; i -= 2) { unsigned char d = (command >> i) & 3; - if (psmouse_command(psmouse, &d, PSMOUSE_CMD_SETRES)) + if (ps2_command(&psmouse->ps2dev, &d, PSMOUSE_CMD_SETRES)) return -1; } @@ -392,7 +264,7 @@ { unsigned char param[2]; - if (psmouse_command(psmouse, param, PSMOUSE_CMD_RESET_BAT)) + if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_RESET_BAT)) return -1; if (param[0] != PSMOUSE_RET_BAT && param[1] != PSMOUSE_RET_ID) @@ -407,14 +279,15 @@ */ static int genius_detect(struct psmouse *psmouse) { + struct ps2dev *ps2dev = &psmouse->ps2dev; unsigned char param[4]; param[0] = 3; - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); - psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11); - psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11); - psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11); - psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO); + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); + ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO); return param[0] == 0x00 && param[1] == 0x33 && param[2] == 0x55; } @@ -424,15 +297,16 @@ */ static int intellimouse_detect(struct psmouse *psmouse) { + struct ps2dev *ps2dev = &psmouse->ps2dev; unsigned char param[2]; param[0] = 200; - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE); + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); param[0] = 100; - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE); + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); param[0] = 80; - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE); - psmouse_command(psmouse, param, PSMOUSE_CMD_GETID); + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); + ps2_command(ps2dev, param, PSMOUSE_CMD_GETID); return param[0] == 3; } @@ -442,22 +316,44 @@ */ static int im_explorer_detect(struct psmouse *psmouse) { + struct ps2dev *ps2dev = &psmouse->ps2dev; unsigned char param[2]; intellimouse_detect(psmouse); param[0] = 200; - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE); + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); param[0] = 200; - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE); + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); param[0] = 80; - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE); - psmouse_command(psmouse, param, PSMOUSE_CMD_GETID); + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); + ps2_command(ps2dev, param, PSMOUSE_CMD_GETID); return param[0] == 4; } /* + * Kensington ThinkingMouse / ExpertMouse magic init. + */ +static int thinking_detect(struct psmouse *psmouse) +{ + struct ps2dev *ps2dev = &psmouse->ps2dev; + unsigned char param[2]; + unsigned char seq[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20, 0 }; + int i; + + param[0] = 10; + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); + param[0] = 0; + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); + for (i = 0; seq[i]; i++) + ps2_command(ps2dev, seq + i, PSMOUSE_CMD_SETRATE); + ps2_command(ps2dev, param, PSMOUSE_CMD_GETID); + + return param[0] == 2; +} + +/* * psmouse_extensions() probes for any extensions to the basic PS/2 protocol * the mouse may have. */ @@ -468,6 +364,22 @@ int synaptics_hardware = 0; /* + * Try Kensington ThinkingMouse (we try first, because synaptics probe + * upsets the thinkingmouse). + */ + + if (max_proto > PSMOUSE_PS2 && thinking_detect(psmouse)) { + + if (set_properties) { + set_bit(BTN_EXTRA, psmouse->dev.keybit); + psmouse->vendor = "Kensington"; + psmouse->name = "ThinkingMouse"; + } + + return PSMOUSE_THINKPS; + } + +/* * Try Synaptics TouchPad */ if (max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse)) { @@ -494,6 +406,25 @@ synaptics_reset(psmouse); } +/* + * Try ALPS TouchPad + */ + if (max_proto > PSMOUSE_IMEX && alps_detect(psmouse)) { + + if (set_properties) { + psmouse->vendor = "ALPS"; + psmouse->name = "TouchPad"; + } + + if (!set_properties || alps_init(psmouse) == 0) + return PSMOUSE_ALPS; + +/* + * Init failed, try basic relative protocols + */ + max_proto = PSMOUSE_IMEX; + } + if (max_proto > PSMOUSE_IMEX && genius_detect(psmouse)) { if (set_properties) { @@ -549,7 +480,7 @@ * extensions. */ psmouse_reset(psmouse); - psmouse_command(psmouse, NULL, PSMOUSE_CMD_RESET_DIS); + ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); } return PSMOUSE_PS2; @@ -561,6 +492,7 @@ static int psmouse_probe(struct psmouse *psmouse) { + struct ps2dev *ps2dev = &psmouse->ps2dev; unsigned char param[2]; /* @@ -569,8 +501,7 @@ */ param[0] = 0xa5; - - if (psmouse_command(psmouse, param, PSMOUSE_CMD_GETID)) + if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETID)) return -1; if (param[0] != 0x00 && param[0] != 0x03 && param[0] != 0x04) @@ -580,8 +511,8 @@ * Then we reset and disable the mouse so that it doesn't generate events. */ - if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_RESET_DIS)) - printk(KERN_WARNING "psmouse.c: Failed to reset mouse on %s\n", psmouse->serio->phys); + if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_DIS)) + printk(KERN_WARNING "psmouse.c: Failed to reset mouse on %s\n", ps2dev->serio->phys); return 0; } @@ -608,7 +539,7 @@ else if (psmouse_resolution) param[0] = 0; - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); + ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_SETRES); } /* @@ -621,7 +552,7 @@ int i = 0; while (rates[i] > psmouse_rate) i++; - psmouse_command(psmouse, rates + i, PSMOUSE_CMD_SETRATE); + ps2_command(&psmouse->ps2dev, rates + i, PSMOUSE_CMD_SETRATE); } /* @@ -639,14 +570,14 @@ if (psmouse_max_proto != PSMOUSE_PS2) { psmouse_set_rate(psmouse); psmouse_set_resolution(psmouse); - psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11); + ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); } /* * We set the mouse into streaming mode. */ - psmouse_command(psmouse, param, PSMOUSE_CMD_SETSTREAM); + ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_SETSTREAM); } /* @@ -657,11 +588,11 @@ static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) { - serio_pause_rx(psmouse->serio); + serio_pause_rx(psmouse->ps2dev.serio); psmouse->state = new_state; - psmouse->pktcnt = psmouse->cmdcnt = psmouse->out_of_sync = 0; - psmouse->flags = 0; - serio_continue_rx(psmouse->serio); + psmouse->pktcnt = psmouse->out_of_sync = 0; + psmouse->ps2dev.flags = 0; + serio_continue_rx(psmouse->ps2dev.serio); } /* @@ -670,8 +601,9 @@ static void psmouse_activate(struct psmouse *psmouse) { - if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_ENABLE)) - printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n", psmouse->serio->phys); + if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) + printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n", + psmouse->ps2dev.serio->phys); psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); } @@ -684,8 +616,9 @@ static void psmouse_deactivate(struct psmouse *psmouse) { - if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_DISABLE)) - printk(KERN_WARNING "psmouse.c: Failed to deactivate mouse on %s\n", psmouse->serio->phys); + if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE)) + printk(KERN_WARNING "psmouse.c: Failed to deactivate mouse on %s\n", + psmouse->ps2dev.serio->phys); psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); } @@ -755,12 +688,10 @@ memset(psmouse, 0, sizeof(struct psmouse)); - init_waitqueue_head(&psmouse->wait); - init_input_dev(&psmouse->dev); + ps2_init(&psmouse->ps2dev, serio); psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); - psmouse->serio = serio; psmouse->dev.private = psmouse; psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); @@ -846,7 +777,7 @@ psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); if (psmouse->reconnect) { - if (psmouse->reconnect(psmouse)) + if (psmouse->reconnect(psmouse)) goto out; } else if (psmouse_probe(psmouse) < 0 || psmouse->type != psmouse_extensions(psmouse, psmouse_max_proto, 0)) diff -Nru a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h --- a/drivers/input/mouse/psmouse.h 2004-09-23 21:12:57 -07:00 +++ b/drivers/input/mouse/psmouse.h 2004-09-23 21:12:57 -07:00 @@ -2,9 +2,11 @@ #define _PSMOUSE_H #define PSMOUSE_CMD_SETSCALE11 0x00e6 +#define PSMOUSE_CMD_SETSCALE21 0x00e7 #define PSMOUSE_CMD_SETRES 0x10e8 #define PSMOUSE_CMD_GETINFO 0x03e9 #define PSMOUSE_CMD_SETSTREAM 0x00ea +#define PSMOUSE_CMD_SETPOLL 0x00f0 #define PSMOUSE_CMD_POLL 0x03eb #define PSMOUSE_CMD_GETID 0x02f2 #define PSMOUSE_CMD_SETRATE 0x10f3 @@ -18,11 +20,6 @@ #define PSMOUSE_RET_ACK 0xfa #define PSMOUSE_RET_NAK 0xfe -#define PSMOUSE_FLAG_ACK 0 /* Waiting for ACK/NAK */ -#define PSMOUSE_FLAG_CMD 1 /* Waiting for command to finish */ -#define PSMOUSE_FLAG_CMD1 2 /* Waiting for the first byte of command response */ -#define PSMOUSE_FLAG_WAITID 3 /* Command execiting is GET ID */ - enum psmouse_state { PSMOUSE_IGNORE, PSMOUSE_INITIALIZING, @@ -40,26 +37,18 @@ struct psmouse { void *private; struct input_dev dev; - struct serio *serio; + struct ps2dev ps2dev; char *vendor; char *name; - unsigned char cmdbuf[8]; unsigned char packet[8]; - unsigned char cmdcnt; unsigned char pktcnt; unsigned char type; unsigned char model; unsigned long last; unsigned long out_of_sync; enum psmouse_state state; - unsigned char nak; - char error; char devname[64]; char phys[32]; - unsigned long flags; - - /* Used to signal completion from interrupt handler */ - wait_queue_head_t wait; psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); int (*reconnect)(struct psmouse *psmouse); @@ -69,15 +58,19 @@ void (*pt_deactivate)(struct psmouse *psmouse); }; -#define PSMOUSE_PS2 1 -#define PSMOUSE_PS2PP 2 -#define PSMOUSE_PS2TPP 3 -#define PSMOUSE_GENPS 4 -#define PSMOUSE_IMPS 5 -#define PSMOUSE_IMEX 6 -#define PSMOUSE_SYNAPTICS 7 +enum psmouse_type { + PSMOUSE_NONE, + PSMOUSE_PS2, + PSMOUSE_PS2PP, + PSMOUSE_PS2TPP, + PSMOUSE_THINKPS, + PSMOUSE_GENPS, + PSMOUSE_IMPS, + PSMOUSE_IMEX, + PSMOUSE_SYNAPTICS, + PSMOUSE_ALPS, +}; -int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command); int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command); int psmouse_reset(struct psmouse *psmouse); diff -Nru a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c --- a/drivers/input/mouse/synaptics.c 2004-09-23 21:12:57 -07:00 +++ b/drivers/input/mouse/synaptics.c 2004-09-23 21:12:57 -07:00 @@ -26,6 +26,7 @@ #include #include #include +#include #include "psmouse.h" #include "synaptics.h" @@ -50,7 +51,7 @@ { if (psmouse_sliced_command(psmouse, c)) return -1; - if (psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO)) + if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) return -1; return 0; } @@ -65,7 +66,7 @@ if (psmouse_sliced_command(psmouse, mode)) return -1; param[0] = SYN_PS_SET_MODE2; - if (psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE)) + if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_SETRATE)) return -1; return 0; } @@ -219,7 +220,7 @@ if (psmouse_sliced_command(parent, c)) return -1; - if (psmouse_command(parent, &rate_param, PSMOUSE_CMD_SETRATE)) + if (ps2_command(&parent->ps2dev, &rate_param, PSMOUSE_CMD_SETRATE)) return -1; return 0; } @@ -245,7 +246,7 @@ static void synaptics_pt_activate(struct psmouse *psmouse) { - struct psmouse *child = psmouse->serio->child->private; + struct psmouse *child = psmouse->ps2dev.serio->child->private; /* adjust the touchpad to child's choice of protocol */ if (child && child->type >= PSMOUSE_GENPS) { @@ -270,11 +271,11 @@ strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name)); strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name)); serio->write = synaptics_pt_write; - serio->parent = psmouse->serio; + serio->parent = psmouse->ps2dev.serio; psmouse->pt_activate = synaptics_pt_activate; - psmouse->serio->child = serio; + psmouse->ps2dev.serio->child = serio; } /***************************************************************************** @@ -470,8 +471,8 @@ priv->pkt_type = synaptics_detect_pkt_type(psmouse); if (SYN_CAP_PASS_THROUGH(priv->capabilities) && synaptics_is_pt_packet(psmouse->packet)) { - if (psmouse->serio->child) - synaptics_pass_pt_packet(psmouse->serio->child, psmouse->packet); + if (psmouse->ps2dev.serio->child) + synaptics_pass_pt_packet(psmouse->ps2dev.serio->child, psmouse->packet); } else synaptics_process_packet(psmouse); @@ -561,15 +562,16 @@ int synaptics_detect(struct psmouse *psmouse) { + struct ps2dev *ps2dev = &psmouse->ps2dev; unsigned char param[4]; param[0] = 0; - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); - psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO); + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); + ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO); return param[1] == 0x47; } diff -Nru a/drivers/input/mousedev.c b/drivers/input/mousedev.c --- a/drivers/input/mousedev.c 2004-09-23 21:12:57 -07:00 +++ b/drivers/input/mousedev.c 2004-09-23 21:12:57 -07:00 @@ -115,20 +115,26 @@ #define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03]) #define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03]) -static void mousedev_touchpad_event(struct mousedev *mousedev, unsigned int code, int value) +static void mousedev_touchpad_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value) { + int size; + if (mousedev->touch) { switch (code) { case ABS_X: + size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; + if (size == 0) size = xres; fx(0) = value; if (mousedev->pkt_count >= 2) - mousedev->packet.dx = ((fx(0) - fx(1)) / 2 + (fx(1) - fx(2)) / 2) / 8; + mousedev->packet.dx = ((fx(0) - fx(1)) / 2 + (fx(1) - fx(2)) / 2) * xres / (size * 2); break; case ABS_Y: + size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y]; + if (size == 0) size = yres; fy(0) = value; if (mousedev->pkt_count >= 2) - mousedev->packet.dy = -((fy(0) - fy(1)) / 2 + (fy(1) - fy(2)) / 2) / 8; + mousedev->packet.dy = -((fy(0) - fy(1)) / 2 + (fy(1) - fy(2)) / 2) * yres / (size * 2); break; } } @@ -279,7 +285,7 @@ return; if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) - mousedev_touchpad_event(mousedev, code, value); + mousedev_touchpad_event(handle->dev, mousedev, code, value); else mousedev_abs_event(handle->dev, mousedev, code, value); diff -Nru a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig --- a/drivers/input/serio/Kconfig 2004-09-23 21:12:57 -07:00 +++ b/drivers/input/serio/Kconfig 2004-09-23 21:12:57 -07:00 @@ -131,6 +131,16 @@ To compile this driver as a module, choose M here: the module will be called maceps2. +config SERIO_LIBPS2 + tristate "PS/2 driver library" + depends on SERIO + help + Say Y here if you are using a driver for device connected + to a PS/2 port, such as PS/2 mouse or standard AT keyboard. + + To compile this driver as a module, choose M here: the + module will be called libps2. + config SERIO_RAW tristate "Raw access to serio ports" depends on SERIO diff -Nru a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile --- a/drivers/input/serio/Makefile 2004-09-23 21:12:57 -07:00 +++ b/drivers/input/serio/Makefile 2004-09-23 21:12:57 -07:00 @@ -17,4 +17,5 @@ obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o 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 diff -Nru a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/input/serio/libps2.c 2004-09-23 21:12:57 -07:00 @@ -0,0 +1,273 @@ +/* + * PS/2 driver library + * + * Copyright (c) 1999-2002 Vojtech Pavlik + * Copyright (c) 2004 Dmitry Torokhov + */ + +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_DESC "PS/2 driver library" + +MODULE_AUTHOR("Dmitry Torokhov "); +MODULE_DESCRIPTION("PS/2 driver library"); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(ps2_init); +EXPORT_SYMBOL(ps2_sendbyte); +EXPORT_SYMBOL(ps2_command); +EXPORT_SYMBOL(ps2_schedule_command); +EXPORT_SYMBOL(ps2_handle_ack); +EXPORT_SYMBOL(ps2_handle_response); +EXPORT_SYMBOL(ps2_cmd_aborted); + +/* 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 mouse, and waits for acknowledge. + * It doesn't handle retransmission, though it could - because when there would + * be need for retransmissions, the mouse has to be replaced anyway. + * + * ps2_sendbyte() can only be called from a process context + */ + +int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte) +{ + serio_pause_rx(ps2dev->serio); + ps2dev->nak = 1; + ps2dev->flags |= PS2_FLAG_ACK; + serio_continue_rx(ps2dev->serio); + + if (serio_write(ps2dev->serio, byte) == 0) + wait_event_interruptible_timeout(ps2dev->wait, + !(ps2dev->flags & PS2_FLAG_ACK), + msecs_to_jiffies(200)); + + serio_pause_rx(ps2dev->serio); + ps2dev->flags &= ~PS2_FLAG_ACK; + serio_continue_rx(ps2dev->serio); + + return -ps2dev->nak; +} + +/* + * ps2_command() sends a command and its parameters to the mouse, + * then waits for the response and puts it in the param array. + * + * ps2_command() can only be called from a process context + */ + +int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) +{ + int timeout; + int send = (command >> 12) & 0xf; + int receive = (command >> 8) & 0xf; + int rc = -1; + int i; + + down(&ps2dev->cmd_sem); + + timeout = msecs_to_jiffies(command == PS2_CMD_RESET_BAT ? 4000 : 500); + + serio_pause_rx(ps2dev->serio); + ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0; + ps2dev->cmdcnt = receive; + if (receive && param) + for (i = 0; i < receive; i++) + ps2dev->cmdbuf[(receive - 1) - i] = param[i]; + serio_continue_rx(ps2dev->serio); + + if (command & 0xff) + if (ps2_sendbyte(ps2dev, command & 0xff)) + goto out; + + for (i = 0; i < send; i++) + if (ps2_sendbyte(ps2dev, param[i])) + goto out; + + timeout = wait_event_interruptible_timeout(ps2dev->wait, + !(ps2dev->flags & PS2_FLAG_CMD1), timeout); + + if (ps2dev->cmdcnt && timeout > 0) { + if (command == PS2_CMD_RESET_BAT && jiffies_to_msecs(timeout) > 100) + timeout = msecs_to_jiffies(100); + + if (command == PS2_CMD_GETID && + ps2dev->cmdbuf[receive - 1] != 0xab && ps2dev->cmdbuf[receive - 1] != 0xac) { + /* + * Device behind the port is not a keyboard + * so we don't need to wait for the 2nd byte + * of ID response. + */ + serio_pause_rx(ps2dev->serio); + ps2dev->flags = ps2dev->cmdcnt = 0; + serio_continue_rx(ps2dev->serio); + } + + wait_event_interruptible_timeout(ps2dev->wait, + !(ps2dev->flags & PS2_FLAG_CMD), timeout); + } + + if (param) + for (i = 0; i < receive; i++) + param[i] = ps2dev->cmdbuf[(receive - 1) - i]; + + if (ps2dev->cmdcnt && (command != PS2_CMD_RESET_BAT || ps2dev->cmdcnt != 1)) + goto out; + + rc = 0; + +out: + serio_pause_rx(ps2dev->serio); + ps2dev->flags = 0; + serio_continue_rx(ps2dev->serio); + + up(&ps2dev->cmd_sem); + return rc; +} + +/* + * 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(void *data) +{ + struct ps2work *ps2work = data; + + 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, ps2work); + + if (!schedule_work(&ps2work->work)) { + kfree(ps2work); + return -1; + } + + return 0; +} + +/* + * ps2_init() initializes ps2dev structure + */ + +void ps2_init(struct ps2dev *ps2dev, struct serio *serio) +{ + init_MUTEX(&ps2dev->cmd_sem); + init_waitqueue_head(&ps2dev->wait); + ps2dev->serio = serio; +} + +/* + * ps2_handle_ack() + */ + +int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data) +{ + switch (data) { + case PS2_RET_ACK: + ps2dev->nak = 0; + break; + + case PS2_RET_NAK: + ps2dev->nak = 1; + break; + + /* + * Workaround for mice which don't ACK the Get ID command. + * These are valid mouse IDs that we recognize. + */ + case 0x00: + case 0x03: + case 0x04: + if (ps2dev->flags & PS2_FLAG_WAITID) { + ps2dev->nak = 0; + break; + } + /* Fall through */ + default: + return 1; + } + + if (!ps2dev->nak && ps2dev->cmdcnt) + ps2dev->flags |= PS2_FLAG_CMD | PS2_FLAG_CMD1; + + ps2dev->flags &= ~PS2_FLAG_ACK; + wake_up_interruptible(&ps2dev->wait); + + return data == PS2_RET_ACK || data == PS2_RET_NAK; +} + + +int ps2_handle_response(struct ps2dev *ps2dev, unsigned char data) +{ + if (ps2dev->cmdcnt) + ps2dev->cmdbuf[--ps2dev->cmdcnt] = data; + + if (ps2dev->flags & PS2_FLAG_CMD1) { + ps2dev->flags &= ~PS2_FLAG_CMD1; + if (ps2dev->cmdcnt) + wake_up_interruptible(&ps2dev->wait); + } + + if (!ps2dev->cmdcnt) { + ps2dev->flags &= ~PS2_FLAG_CMD; + wake_up_interruptible(&ps2dev->wait); + } + + return 1; +} + +void ps2_cmd_aborted(struct ps2dev *ps2dev) +{ + if (ps2dev->flags & PS2_FLAG_ACK) + ps2dev->nak = 1; + + if (ps2dev->flags & (PS2_FLAG_ACK | PS2_FLAG_CMD)) + wake_up_interruptible(&ps2dev->wait); + + ps2dev->flags = 0; +} + diff -Nru a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c --- a/drivers/input/serio/serio.c 2004-09-23 21:12:57 -07:00 +++ b/drivers/input/serio/serio.c 2004-09-23 21:12:57 -07:00 @@ -326,6 +326,7 @@ try_module_get(THIS_MODULE); spin_lock_init(&serio->lock); + init_MUTEX(&serio->drv_sem); list_add_tail(&serio->node, &serio_list); snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id), "serio%d", serio_no++); serio->dev.bus = &serio_bus; @@ -595,17 +596,22 @@ up(&serio_sem); } -/* called from serio_driver->connect/disconnect methods under serio_sem */ -int serio_open(struct serio *serio, struct serio_driver *drv) +static void serio_set_drv(struct serio *serio, struct serio_driver *drv) { + down(&serio->drv_sem); serio_pause_rx(serio); serio->drv = drv; serio_continue_rx(serio); + up(&serio->drv_sem); +} + +/* called from serio_driver->connect/disconnect methods under serio_sem */ +int serio_open(struct serio *serio, struct serio_driver *drv) +{ + serio_set_drv(serio, drv); if (serio->open && serio->open(serio)) { - serio_pause_rx(serio); - serio->drv = NULL; - serio_continue_rx(serio); + serio_set_drv(serio, NULL); return -1; } return 0; @@ -617,9 +623,7 @@ if (serio->close) serio->close(serio); - serio_pause_rx(serio); - serio->drv = NULL; - serio_continue_rx(serio); + serio_set_drv(serio, NULL); } irqreturn_t serio_interrupt(struct serio *serio, diff -Nru a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c --- a/drivers/usb/input/hid-core.c 2004-09-23 21:12:57 -07:00 +++ b/drivers/usb/input/hid-core.c 2004-09-23 21:12:57 -07:00 @@ -1275,9 +1275,14 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, unsigned char type, void *buf, int size) { - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, - (type << 8), ifnum, buf, size, HZ * USB_CTRL_GET_TIMEOUT); + int result, retries = 4; + do { + result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, + (type << 8), ifnum, buf, size, HZ * USB_CTRL_GET_TIMEOUT); + retries--; + } while (result < 0 && retries); + return result; } int hid_open(struct hid_device *hid) @@ -1308,7 +1313,7 @@ struct hid_report_enum *report_enum; struct hid_report *report; struct list_head *list; - int err, ret; + int err, ret, size; /* * The Set_Idle request is supposed to affect only the @@ -1331,6 +1336,10 @@ list = report_enum->report_list.next; while (list != &report_enum->report_list) { report = (struct hid_report *) list; + size = ((report->size - 1) >> 3) + 1 + report_enum->numbered; + if (size > HID_BUFFER_SIZE) size = HID_BUFFER_SIZE; + if (size > hid->urbin->transfer_buffer_length) + hid->urbin->transfer_buffer_length = size; hid_submit_report(hid, report, USB_DIR_IN); list = list->next; } @@ -1456,6 +1465,8 @@ #define USB_VENDOR_ID_CODEMERCS 0x07c0 #define USB_DEVICE_ID_CODEMERCS_IOW40 0x1500 #define USB_DEVICE_ID_CODEMERCS_IOW24 0x1501 +#define USB_DEVICE_ID_CODEMERCS_IOW48 0x1502 +#define USB_DEVICE_ID_CODEMERCS_IOW28 0x1503 static struct hid_blacklist { @@ -1474,8 +1485,15 @@ { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW48, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE }, @@ -1511,13 +1529,6 @@ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 7, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PTU, HID_QUIRK_IGNORE }, - - { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, @@ -1528,8 +1539,8 @@ { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, { USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_BACK }, - { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_EXTRA }, + { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 }, + { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 }, { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, @@ -1650,17 +1661,12 @@ interval = 1 << (interval - 1); if (endpoint->bEndpointAddress & USB_DIR_IN) { - int len; - if (hid->urbin) continue; if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL))) goto fail; pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - len = usb_maxpacket(dev, pipe, 0); - if (len > HID_BUFFER_SIZE) - len = HID_BUFFER_SIZE; - usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, len, + usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, 0, hid_irq_in, hid, interval); hid->urbin->transfer_dma = hid->inbuf_dma; hid->urbin->transfer_flags |=(URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK); diff -Nru a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h --- a/drivers/usb/input/hid-debug.h 2004-09-23 21:12:57 -07:00 +++ b/drivers/usb/input/hid-debug.h 2004-09-23 21:12:57 -07:00 @@ -27,6 +27,8 @@ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ +#include + struct hid_usage_entry { unsigned page; unsigned usage; @@ -323,7 +325,7 @@ printk("."); for (p = hid_usage_table; p->description; p++) if (p->page == (usage >> 16)) { - for(++p; p->description && p->page != 0; p++) + for(++p; p->description && p->usage != 0; p++) if (p->usage == (usage & 0xffff)) { printk("%s", p->description); return; @@ -461,4 +463,264 @@ printk("hid-debug: input "); resolv_usage(usage->hid); printk(" = %d\n", value); +} + + +static char *events[EV_MAX + 1] = { + [0 ... EV_MAX] = NULL, + [EV_SYN] = "Sync", [EV_KEY] = "Key", + [EV_REL] = "Relative", [EV_ABS] = "Absolute", + [EV_MSC] = "Misc", [EV_LED] = "LED", + [EV_SND] = "Sound", [EV_REP] = "Repeat", + [EV_FF] = "ForceFeedback", [EV_PWR] = "Power", + [EV_FF_STATUS] = "ForceFeedbackStatus", +}; + +static char *syncs[2] = { + [0 ... 1] = NULL, + [SYN_REPORT] = "Report", [SYN_CONFIG] = "Config", +}; +static char *keys[KEY_MAX + 1] = { + [0 ... KEY_MAX] = NULL, + [KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc", + [KEY_1] = "1", [KEY_2] = "2", + [KEY_3] = "3", [KEY_4] = "4", + [KEY_5] = "5", [KEY_6] = "6", + [KEY_7] = "7", [KEY_8] = "8", + [KEY_9] = "9", [KEY_0] = "0", + [KEY_MINUS] = "Minus", [KEY_EQUAL] = "Equal", + [KEY_BACKSPACE] = "Backspace", [KEY_TAB] = "Tab", + [KEY_Q] = "Q", [KEY_W] = "W", + [KEY_E] = "E", [KEY_R] = "R", + [KEY_T] = "T", [KEY_Y] = "Y", + [KEY_U] = "U", [KEY_I] = "I", + [KEY_O] = "O", [KEY_P] = "P", + [KEY_LEFTBRACE] = "LeftBrace", [KEY_RIGHTBRACE] = "RightBrace", + [KEY_ENTER] = "Enter", [KEY_LEFTCTRL] = "LeftControl", + [KEY_A] = "A", [KEY_S] = "S", + [KEY_D] = "D", [KEY_F] = "F", + [KEY_G] = "G", [KEY_H] = "H", + [KEY_J] = "J", [KEY_K] = "K", + [KEY_L] = "L", [KEY_SEMICOLON] = "Semicolon", + [KEY_APOSTROPHE] = "Apostrophe", [KEY_GRAVE] = "Grave", + [KEY_LEFTSHIFT] = "LeftShift", [KEY_BACKSLASH] = "BackSlash", + [KEY_Z] = "Z", [KEY_X] = "X", + [KEY_C] = "C", [KEY_V] = "V", + [KEY_B] = "B", [KEY_N] = "N", + [KEY_M] = "M", [KEY_COMMA] = "Comma", + [KEY_DOT] = "Dot", [KEY_SLASH] = "Slash", + [KEY_RIGHTSHIFT] = "RightShift", [KEY_KPASTERISK] = "KPAsterisk", + [KEY_LEFTALT] = "LeftAlt", [KEY_SPACE] = "Space", + [KEY_CAPSLOCK] = "CapsLock", [KEY_F1] = "F1", + [KEY_F2] = "F2", [KEY_F3] = "F3", + [KEY_F4] = "F4", [KEY_F5] = "F5", + [KEY_F6] = "F6", [KEY_F7] = "F7", + [KEY_F8] = "F8", [KEY_F9] = "F9", + [KEY_F10] = "F10", [KEY_NUMLOCK] = "NumLock", + [KEY_SCROLLLOCK] = "ScrollLock", [KEY_KP7] = "KP7", + [KEY_KP8] = "KP8", [KEY_KP9] = "KP9", + [KEY_KPMINUS] = "KPMinus", [KEY_KP4] = "KP4", + [KEY_KP5] = "KP5", [KEY_KP6] = "KP6", + [KEY_KPPLUS] = "KPPlus", [KEY_KP1] = "KP1", + [KEY_KP2] = "KP2", [KEY_KP3] = "KP3", + [KEY_KP0] = "KP0", [KEY_KPDOT] = "KPDot", + [KEY_ZENKAKUHANKAKU] = "Zenkaku/Hankaku", [KEY_102ND] = "102nd", + [KEY_F11] = "F11", [KEY_F12] = "F12", + [KEY_RO] = "RO", [KEY_KATAKANA] = "Katakana", + [KEY_HIRAGANA] = "HIRAGANA", [KEY_HENKAN] = "Henkan", + [KEY_KATAKANAHIRAGANA] = "Katakana/Hiragana", [KEY_MUHENKAN] = "Muhenkan", + [KEY_KPJPCOMMA] = "KPJpComma", [KEY_KPENTER] = "KPEnter", + [KEY_RIGHTCTRL] = "RightCtrl", [KEY_KPSLASH] = "KPSlash", + [KEY_SYSRQ] = "SysRq", [KEY_RIGHTALT] = "RightAlt", + [KEY_LINEFEED] = "LineFeed", [KEY_HOME] = "Home", + [KEY_UP] = "Up", [KEY_PAGEUP] = "PageUp", + [KEY_LEFT] = "Left", [KEY_RIGHT] = "Right", + [KEY_END] = "End", [KEY_DOWN] = "Down", + [KEY_PAGEDOWN] = "PageDown", [KEY_INSERT] = "Insert", + [KEY_DELETE] = "Delete", [KEY_MACRO] = "Macro", + [KEY_MUTE] = "Mute", [KEY_VOLUMEDOWN] = "VolumeDown", + [KEY_VOLUMEUP] = "VolumeUp", [KEY_POWER] = "Power", + [KEY_KPEQUAL] = "KPEqual", [KEY_KPPLUSMINUS] = "KPPlusMinus", + [KEY_PAUSE] = "Pause", [KEY_KPCOMMA] = "KPComma", + [KEY_HANGUEL] = "Hanguel", [KEY_HANJA] = "Hanja", + [KEY_YEN] = "Yen", [KEY_LEFTMETA] = "LeftMeta", + [KEY_RIGHTMETA] = "RightMeta", [KEY_COMPOSE] = "Compose", + [KEY_STOP] = "Stop", [KEY_AGAIN] = "Again", + [KEY_PROPS] = "Props", [KEY_UNDO] = "Undo", + [KEY_FRONT] = "Front", [KEY_COPY] = "Copy", + [KEY_OPEN] = "Open", [KEY_PASTE] = "Paste", + [KEY_FIND] = "Find", [KEY_CUT] = "Cut", + [KEY_HELP] = "Help", [KEY_MENU] = "Menu", + [KEY_CALC] = "Calc", [KEY_SETUP] = "Setup", + [KEY_SLEEP] = "Sleep", [KEY_WAKEUP] = "WakeUp", + [KEY_FILE] = "File", [KEY_SENDFILE] = "SendFile", + [KEY_DELETEFILE] = "DeleteFile", [KEY_XFER] = "X-fer", + [KEY_PROG1] = "Prog1", [KEY_PROG2] = "Prog2", + [KEY_WWW] = "WWW", [KEY_MSDOS] = "MSDOS", + [KEY_COFFEE] = "Coffee", [KEY_DIRECTION] = "Direction", + [KEY_CYCLEWINDOWS] = "CycleWindows", [KEY_MAIL] = "Mail", + [KEY_BOOKMARKS] = "Bookmarks", [KEY_COMPUTER] = "Computer", + [KEY_BACK] = "Back", [KEY_FORWARD] = "Forward", + [KEY_CLOSECD] = "CloseCD", [KEY_EJECTCD] = "EjectCD", + [KEY_EJECTCLOSECD] = "EjectCloseCD", [KEY_NEXTSONG] = "NextSong", + [KEY_PLAYPAUSE] = "PlayPause", [KEY_PREVIOUSSONG] = "PreviousSong", + [KEY_STOPCD] = "StopCD", [KEY_RECORD] = "Record", + [KEY_REWIND] = "Rewind", [KEY_PHONE] = "Phone", + [KEY_ISO] = "ISOKey", [KEY_CONFIG] = "Config", + [KEY_HOMEPAGE] = "HomePage", [KEY_REFRESH] = "Refresh", + [KEY_EXIT] = "Exit", [KEY_MOVE] = "Move", + [KEY_EDIT] = "Edit", [KEY_SCROLLUP] = "ScrollUp", + [KEY_SCROLLDOWN] = "ScrollDown", [KEY_KPLEFTPAREN] = "KPLeftParenthesis", + [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_F13] = "F13", + [KEY_F14] = "F14", [KEY_F15] = "F15", + [KEY_F16] = "F16", [KEY_F17] = "F17", + [KEY_F18] = "F18", [KEY_F19] = "F19", + [KEY_F20] = "F20", [KEY_F21] = "F21", + [KEY_F22] = "F22", [KEY_F23] = "F23", + [KEY_F24] = "F24", [KEY_PLAYCD] = "PlayCD", + [KEY_PAUSECD] = "PauseCD", [KEY_PROG3] = "Prog3", + [KEY_PROG4] = "Prog4", [KEY_SUSPEND] = "Suspend", + [KEY_CLOSE] = "Close", [KEY_PLAY] = "Play", + [KEY_FASTFORWARD] = "Fast Forward", [KEY_BASSBOOST] = "Bass Boost", + [KEY_PRINT] = "Print", [KEY_HP] = "HP", + [KEY_CAMERA] = "Camera", [KEY_SOUND] = "Sound", + [KEY_QUESTION] = "Question", [KEY_EMAIL] = "Email", + [KEY_CHAT] = "Chat", [KEY_SEARCH] = "Search", + [KEY_CONNECT] = "Connect", [KEY_FINANCE] = "Finance", + [KEY_SPORT] = "Sport", [KEY_SHOP] = "Shop", + [KEY_ALTERASE] = "Alternate Erase", [KEY_CANCEL] = "Cancel", + [KEY_BRIGHTNESSDOWN] = "Brightness down", [KEY_BRIGHTNESSUP] = "Brightness up", + [KEY_MEDIA] = "Media", [KEY_UNKNOWN] = "Unknown", + [BTN_0] = "Btn0", [BTN_1] = "Btn1", + [BTN_2] = "Btn2", [BTN_3] = "Btn3", + [BTN_4] = "Btn4", [BTN_5] = "Btn5", + [BTN_6] = "Btn6", [BTN_7] = "Btn7", + [BTN_8] = "Btn8", [BTN_9] = "Btn9", + [BTN_LEFT] = "LeftBtn", [BTN_RIGHT] = "RightBtn", + [BTN_MIDDLE] = "MiddleBtn", [BTN_SIDE] = "SideBtn", + [BTN_EXTRA] = "ExtraBtn", [BTN_FORWARD] = "ForwardBtn", + [BTN_BACK] = "BackBtn", [BTN_TASK] = "TaskBtn", + [BTN_TRIGGER] = "Trigger", [BTN_THUMB] = "ThumbBtn", + [BTN_THUMB2] = "ThumbBtn2", [BTN_TOP] = "TopBtn", + [BTN_TOP2] = "TopBtn2", [BTN_PINKIE] = "PinkieBtn", + [BTN_BASE] = "BaseBtn", [BTN_BASE2] = "BaseBtn2", + [BTN_BASE3] = "BaseBtn3", [BTN_BASE4] = "BaseBtn4", + [BTN_BASE5] = "BaseBtn5", [BTN_BASE6] = "BaseBtn6", + [BTN_DEAD] = "BtnDead", [BTN_A] = "BtnA", + [BTN_B] = "BtnB", [BTN_C] = "BtnC", + [BTN_X] = "BtnX", [BTN_Y] = "BtnY", + [BTN_Z] = "BtnZ", [BTN_TL] = "BtnTL", + [BTN_TR] = "BtnTR", [BTN_TL2] = "BtnTL2", + [BTN_TR2] = "BtnTR2", [BTN_SELECT] = "BtnSelect", + [BTN_START] = "BtnStart", [BTN_MODE] = "BtnMode", + [BTN_THUMBL] = "BtnThumbL", [BTN_THUMBR] = "BtnThumbR", + [BTN_TOOL_PEN] = "ToolPen", [BTN_TOOL_RUBBER] = "ToolRubber", + [BTN_TOOL_BRUSH] = "ToolBrush", [BTN_TOOL_PENCIL] = "ToolPencil", + [BTN_TOOL_AIRBRUSH] = "ToolAirbrush", [BTN_TOOL_FINGER] = "ToolFinger", + [BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens", + [BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus", + [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "Tool Doubletap", + [BTN_TOOL_TRIPLETAP] = "Tool Tripletap", [BTN_GEAR_DOWN] = "WheelBtn", + [BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok", + [KEY_SELECT] = "Select", [KEY_GOTO] = "Goto", + [KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2", + [KEY_OPTION] = "Option", [KEY_INFO] = "Info", + [KEY_TIME] = "Time", [KEY_VENDOR] = "Vendor", + [KEY_ARCHIVE] = "Archive", [KEY_PROGRAM] = "Program", + [KEY_CHANNEL] = "Channel", [KEY_FAVORITES] = "Favorites", + [KEY_EPG] = "EPG", [KEY_PVR] = "PVR", + [KEY_MHP] = "MHP", [KEY_LANGUAGE] = "Language", + [KEY_TITLE] = "Title", [KEY_SUBTITLE] = "Subtitle", + [KEY_ANGLE] = "Angle", [KEY_ZOOM] = "Zoom", + [KEY_MODE] = "Mode", [KEY_KEYBOARD] = "Keyboard", + [KEY_SCREEN] = "Screen", [KEY_PC] = "PC", + [KEY_TV] = "TV", [KEY_TV2] = "TV2", + [KEY_VCR] = "VCR", [KEY_VCR2] = "VCR2", + [KEY_SAT] = "Sat", [KEY_SAT2] = "Sat2", + [KEY_CD] = "CD", [KEY_TAPE] = "Tape", + [KEY_RADIO] = "Radio", [KEY_TUNER] = "Tuner", + [KEY_PLAYER] = "Player", [KEY_TEXT] = "Text", + [KEY_DVD] = "DVD", [KEY_AUX] = "Aux", + [KEY_MP3] = "MP3", [KEY_AUDIO] = "Audio", + [KEY_VIDEO] = "Video", [KEY_DIRECTORY] = "Directory", + [KEY_LIST] = "List", [KEY_MEMO] = "Memo", + [KEY_CALENDAR] = "Calendar", [KEY_RED] = "Red", + [KEY_GREEN] = "Green", [KEY_YELLOW] = "Yellow", + [KEY_BLUE] = "Blue", [KEY_CHANNELUP] = "ChannelUp", + [KEY_CHANNELDOWN] = "ChannelDown", [KEY_FIRST] = "First", + [KEY_LAST] = "Last", [KEY_AB] = "AB", + [KEY_NEXT] = "Next", [KEY_RESTART] = "Restart", + [KEY_SLOW] = "Slow", [KEY_SHUFFLE] = "Shuffle", + [KEY_BREAK] = "Break", [KEY_PREVIOUS] = "Previous", + [KEY_DIGITS] = "Digits", [KEY_TEEN] = "TEEN", + [KEY_TWEN] = "TWEN", [KEY_DEL_EOL] = "Delete EOL", + [KEY_DEL_EOS] = "Delete EOS", [KEY_INS_LINE] = "Insert line", + [KEY_DEL_LINE] = "Delete line", +}; + +static char *absval[5] = { "Value", "Min ", "Max ", "Fuzz ", "Flat " }; + +static char *relatives[REL_MAX + 1] = { + [0 ... REL_MAX] = NULL, + [REL_X] = "X", [REL_Y] = "Y", + [REL_Z] = "Z", [REL_HWHEEL] = "HWheel", + [REL_DIAL] = "Dial", [REL_WHEEL] = "Wheel", + [REL_MISC] = "Misc", +}; + +static char *absolutes[ABS_MAX + 1] = { + [0 ... ABS_MAX] = NULL, + [ABS_X] = "X", [ABS_Y] = "Y", + [ABS_Z] = "Z", [ABS_RX] = "Rx", + [ABS_RY] = "Ry", [ABS_RZ] = "Rz", + [ABS_THROTTLE] = "Throttle", [ABS_RUDDER] = "Rudder", + [ABS_WHEEL] = "Wheel", [ABS_GAS] = "Gas", + [ABS_BRAKE] = "Brake", [ABS_HAT0X] = "Hat0X", + [ABS_HAT0Y] = "Hat0Y", [ABS_HAT1X] = "Hat1X", + [ABS_HAT1Y] = "Hat1Y", [ABS_HAT2X] = "Hat2X", + [ABS_HAT2Y] = "Hat2Y", [ABS_HAT3X] = "Hat3X", + [ABS_HAT3Y] = "Hat 3Y", [ABS_PRESSURE] = "Pressure", + [ABS_DISTANCE] = "Distance", [ABS_TILT_X] = "XTilt", + [ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "Tool Width", + [ABS_VOLUME] = "Volume", [ABS_MISC] = "Misc", +}; + +static char *misc[MSC_MAX + 1] = { + [ 0 ... MSC_MAX] = NULL, + [MSC_SERIAL] = "Serial", [MSC_PULSELED] = "Pulseled", + [MSC_GESTURE] = "Gesture", [MSC_RAW] = "RawData" +}; + +static char *leds[LED_MAX + 1] = { + [0 ... LED_MAX] = NULL, + [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock", + [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose", + [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep", + [LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute", + [LED_MISC] = "Misc", +}; + +static char *repeats[REP_MAX + 1] = { + [0 ... REP_MAX] = NULL, + [REP_DELAY] = "Delay", [REP_PERIOD] = "Period" +}; + +static char *sounds[SND_MAX + 1] = { + [0 ... SND_MAX] = NULL, + [SND_CLICK] = "Click", [SND_BELL] = "Bell", + [SND_TONE] = "Tone" +}; + +static char **names[EV_MAX + 1] = { + [0 ... EV_MAX] = NULL, + [EV_SYN] = syncs, [EV_KEY] = keys, + [EV_REL] = relatives, [EV_ABS] = absolutes, + [EV_MSC] = misc, [EV_LED] = leds, + [EV_SND] = sounds, [EV_REP] = repeats, +}; + +static void resolv_event(__u8 type, __u16 code) { + + printk("%s.%s", events[type] ? events[type] : "?", + names[type] ? (names[type][code] ? names[type][code] : "?") : "?"); } diff -Nru a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c --- a/drivers/usb/input/hid-input.c 2004-09-23 21:12:57 -07:00 +++ b/drivers/usb/input/hid-input.c 2004-09-23 21:12:57 -07:00 @@ -32,6 +32,8 @@ #include #include +#undef DEBUG + #include "hid.h" #define unk KEY_UNKNOWN @@ -60,114 +62,130 @@ __s32 y; } hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}}; -static struct input_dev *find_input(struct hid_device *hid, struct hid_field *field) -{ - struct list_head *lh; - struct hid_input *hidinput; - - list_for_each (lh, &hid->inputs) { - int i; - - hidinput = list_entry(lh, struct hid_input, list); - - if (! hidinput->report) - continue; - - for (i = 0; i < hidinput->report->maxfield; i++) - if (hidinput->report->field[i] == field) - return &hidinput->input; - } - - /* Assume we only have one input and use it */ - if (!list_empty(&hid->inputs)) { - hidinput = list_entry(hid->inputs.next, struct hid_input, list); - return &hidinput->input; - } - - /* This is really a bug */ - return NULL; -} +#define map_abs(c) do { usage->code = c; usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; } while (0) +#define map_rel(c) do { usage->code = c; usage->type = EV_REL; bit = input->relbit; max = REL_MAX; } while (0) +#define map_key(c) do { usage->code = c; usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; } while (0) +#define map_led(c) do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0) +#define map_ff(c) do { usage->code = c; usage->type = EV_FF; bit = input->ffbit; max = FF_MAX; } while (0) + +#define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0) +#define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) +#define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0) static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, struct hid_usage *usage) { struct input_dev *input = &hidinput->input; struct hid_device *device = hidinput->input.private; - int max; - int is_abs = 0; + int max, code; unsigned long *bit; + field->hidinput = hidinput; + +#ifdef DEBUG + printk(KERN_DEBUG "Mapping: "); + resolv_usage(usage->hid); + printk(" ---> "); +#endif + + if (field->flags & HID_MAIN_ITEM_CONSTANT) + goto ignore; + switch (usage->hid & HID_USAGE_PAGE) { + case HID_UP_UNDEFINED: + goto ignore; + case HID_UP_KEYBOARD: set_bit(EV_REP, input->evbit); - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; if ((usage->hid & HID_USAGE) < 256) { - if (!(usage->code = hid_keyboard[usage->hid & HID_USAGE])) - return; - clear_bit(usage->code, bit); + if (!hid_keyboard[usage->hid & HID_USAGE]) goto ignore; + map_key_clear(hid_keyboard[usage->hid & HID_USAGE]); } else - usage->code = KEY_UNKNOWN; + map_key(KEY_UNKNOWN); break; case HID_UP_BUTTON: - usage->code = ((usage->hid - 1) & 0xf) + 0x100; - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; + code = ((usage->hid - 1) & 0xf); switch (field->application) { - case HID_GD_GAMEPAD: usage->code += 0x10; - case HID_GD_JOYSTICK: usage->code += 0x10; - case HID_GD_MOUSE: usage->code += 0x10; break; + case HID_GD_MOUSE: + case HID_GD_POINTER: code += 0x110; break; + case HID_GD_JOYSTICK: code += 0x120; break; + case HID_GD_GAMEPAD: code += 0x130; break; default: - if (field->physical == HID_GD_POINTER) - usage->code += 0x10; - break; + switch (field->physical) { + case HID_GD_MOUSE: + case HID_GD_POINTER: code += 0x110; break; + case HID_GD_JOYSTICK: code += 0x120; break; + case HID_GD_GAMEPAD: code += 0x130; break; + default: code += 0x100; + } } + + map_key(code); break; case HID_UP_GENDESK: if ((usage->hid & 0xf0) == 0x80) { /* SystemControl */ switch (usage->hid & 0xf) { - case 0x1: usage->code = KEY_POWER; break; - case 0x2: usage->code = KEY_SLEEP; break; - case 0x3: usage->code = KEY_WAKEUP; break; - default: usage->code = KEY_UNKNOWN; break; + case 0x1: map_key_clear(KEY_POWER); break; + case 0x2: map_key_clear(KEY_SLEEP); break; + case 0x3: map_key_clear(KEY_WAKEUP); break; + default: goto unknown; } - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; break; } - usage->code = usage->hid & 0xf; - - if (field->report_size == 1) { - usage->code = BTN_MISC; - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; + if ((usage->hid & 0xf0) == 0x90) { /* D-pad */ + switch (usage->hid) { + case HID_GD_UP: usage->hat_dir = 1; break; + case HID_GD_DOWN: usage->hat_dir = 5; break; + case HID_GD_RIGHT: usage->hat_dir = 3; break; + case HID_GD_LEFT: usage->hat_dir = 7; break; + default: goto unknown; + } + if (field->dpad) { + map_abs(field->dpad); + goto ignore; + } + map_abs(ABS_HAT0X); break; } - if (field->flags & HID_MAIN_ITEM_RELATIVE) { - usage->type = EV_REL; bit = input->relbit; max = REL_MAX; - break; - } + switch (usage->hid) { - usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; + /* These usage IDs map directly to the usage codes. */ + case HID_GD_X: case HID_GD_Y: case HID_GD_Z: + case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ: + case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL: + if (field->flags & HID_MAIN_ITEM_RELATIVE) + map_rel(usage->hid & 0xf); + else + map_abs(usage->hid & 0xf); + break; - if (usage->hid == HID_GD_HATSWITCH) { - usage->code = ABS_HAT0X; - usage->hat_min = field->logical_minimum; - usage->hat_max = field->logical_maximum; + case HID_GD_HATSWITCH: + usage->hat_min = field->logical_minimum; + usage->hat_max = field->logical_maximum; + map_abs(ABS_HAT0X); + break; + + case HID_GD_START: map_key_clear(BTN_START); break; + case HID_GD_SELECT: map_key_clear(BTN_SELECT); break; + + default: goto unknown; } + break; case HID_UP_LED: - - usage->code = (usage->hid - 1) & 0xf; - usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; + map_led((usage->hid - 1) & 0xf); break; case HID_UP_DIGITIZER: @@ -175,49 +193,36 @@ switch (usage->hid & 0xff) { case 0x30: /* TipPressure */ - if (!test_bit(BTN_TOUCH, input->keybit)) { device->quirks |= HID_QUIRK_NOTOUCH; set_bit(EV_KEY, input->evbit); set_bit(BTN_TOUCH, input->keybit); } - usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; - usage->code = ABS_PRESSURE; - clear_bit(usage->code, bit); + + map_abs_clear(ABS_PRESSURE); break; case 0x32: /* InRange */ - - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; switch (field->physical & 0xff) { - case 0x21: usage->code = BTN_TOOL_MOUSE; break; - case 0x22: usage->code = BTN_TOOL_FINGER; break; - default: usage->code = BTN_TOOL_PEN; break; + case 0x21: map_key(BTN_TOOL_MOUSE); break; + case 0x22: map_key(BTN_TOOL_FINGER); break; + default: map_key(BTN_TOOL_PEN); break; } break; case 0x3c: /* Invert */ - - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; - usage->code = BTN_TOOL_RUBBER; - clear_bit(usage->code, bit); + map_key_clear(BTN_TOOL_RUBBER); break; case 0x33: /* Touch */ case 0x42: /* TipSwitch */ case 0x43: /* TipSwitch2 */ - device->quirks &= ~HID_QUIRK_NOTOUCH; - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; - usage->code = BTN_TOUCH; - clear_bit(usage->code, bit); + map_key_clear(BTN_TOUCH); break; case 0x44: /* BarrelSwitch */ - - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; - usage->code = BTN_STYLUS; - clear_bit(usage->code, bit); + map_key_clear(BTN_STYLUS); break; default: goto unknown; @@ -228,54 +233,42 @@ set_bit(EV_REP, input->evbit); switch (usage->hid & HID_USAGE) { - case 0x000: usage->code = 0; break; - case 0x034: usage->code = KEY_SLEEP; break; - case 0x036: usage->code = BTN_MISC; break; - case 0x08a: usage->code = KEY_WWW; break; - case 0x095: usage->code = KEY_HELP; break; - - case 0x0b0: usage->code = KEY_PLAY; break; - case 0x0b1: usage->code = KEY_PAUSE; break; - case 0x0b2: usage->code = KEY_RECORD; break; - case 0x0b3: usage->code = KEY_FASTFORWARD; break; - case 0x0b4: usage->code = KEY_REWIND; break; - case 0x0b5: usage->code = KEY_NEXTSONG; break; - case 0x0b6: usage->code = KEY_PREVIOUSSONG; break; - case 0x0b7: usage->code = KEY_STOPCD; break; - case 0x0b8: usage->code = KEY_EJECTCD; break; - case 0x0cd: usage->code = KEY_PLAYPAUSE; break; - case 0x0e0: is_abs = 1; - usage->code = ABS_VOLUME; - break; - case 0x0e2: usage->code = KEY_MUTE; break; - case 0x0e5: usage->code = KEY_BASSBOOST; break; - case 0x0e9: usage->code = KEY_VOLUMEUP; break; - case 0x0ea: usage->code = KEY_VOLUMEDOWN; break; - - case 0x183: usage->code = KEY_CONFIG; break; - case 0x18a: usage->code = KEY_MAIL; break; - case 0x192: usage->code = KEY_CALC; break; - case 0x194: usage->code = KEY_FILE; break; - case 0x21a: usage->code = KEY_UNDO; break; - case 0x21b: usage->code = KEY_COPY; break; - case 0x21c: usage->code = KEY_CUT; break; - case 0x21d: usage->code = KEY_PASTE; break; - - case 0x221: usage->code = KEY_FIND; break; - case 0x223: usage->code = KEY_HOMEPAGE; break; - case 0x224: usage->code = KEY_BACK; break; - case 0x225: usage->code = KEY_FORWARD; break; - case 0x226: usage->code = KEY_STOP; break; - case 0x227: usage->code = KEY_REFRESH; break; - case 0x22a: usage->code = KEY_BOOKMARKS; break; - - default: usage->code = KEY_UNKNOWN; break; - } - - if (is_abs) { - usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; - } else { - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; + case 0x000: goto ignore; + case 0x034: map_key_clear(KEY_SLEEP); break; + case 0x036: map_key_clear(BTN_MISC); break; + case 0x08a: map_key_clear(KEY_WWW); break; + case 0x095: map_key_clear(KEY_HELP); break; + case 0x0b0: map_key_clear(KEY_PLAY); break; + case 0x0b1: map_key_clear(KEY_PAUSE); break; + case 0x0b2: map_key_clear(KEY_RECORD); break; + case 0x0b3: map_key_clear(KEY_FASTFORWARD); break; + case 0x0b4: map_key_clear(KEY_REWIND); break; + case 0x0b5: map_key_clear(KEY_NEXTSONG); break; + case 0x0b6: map_key_clear(KEY_PREVIOUSSONG); break; + case 0x0b7: map_key_clear(KEY_STOPCD); break; + case 0x0b8: map_key_clear(KEY_EJECTCD); break; + case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break; + case 0x0e0: map_abs_clear(ABS_VOLUME); break; + case 0x0e2: map_key_clear(KEY_MUTE); break; + case 0x0e5: map_key_clear(KEY_BASSBOOST); break; + case 0x0e9: map_key_clear(KEY_VOLUMEUP); break; + case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break; + case 0x183: map_key_clear(KEY_CONFIG); break; + case 0x18a: map_key_clear(KEY_MAIL); break; + case 0x192: map_key_clear(KEY_CALC); break; + case 0x194: map_key_clear(KEY_FILE); break; + case 0x21a: map_key_clear(KEY_UNDO); break; + case 0x21b: map_key_clear(KEY_COPY); break; + case 0x21c: map_key_clear(KEY_CUT); break; + case 0x21d: map_key_clear(KEY_PASTE); break; + case 0x221: map_key_clear(KEY_FIND); break; + case 0x223: map_key_clear(KEY_HOMEPAGE); break; + case 0x224: map_key_clear(KEY_BACK); break; + case 0x225: map_key_clear(KEY_FORWARD); break; + case 0x226: map_key_clear(KEY_STOP); break; + case 0x227: map_key_clear(KEY_REFRESH); break; + case 0x22a: map_key_clear(KEY_BOOKMARKS); break; + default: goto unknown; } break; @@ -283,114 +276,82 @@ set_bit(EV_REP, input->evbit); switch (usage->hid & HID_USAGE) { - case 0x021: usage->code = KEY_PRINT; break; - case 0x070: usage->code = KEY_HP; break; - case 0x071: usage->code = KEY_CAMERA; break; - case 0x072: usage->code = KEY_SOUND; break; - case 0x073: usage->code = KEY_QUESTION; break; - - case 0x080: usage->code = KEY_EMAIL; break; - case 0x081: usage->code = KEY_CHAT; break; - case 0x082: usage->code = KEY_SEARCH; break; - case 0x083: usage->code = KEY_CONNECT; break; - case 0x084: usage->code = KEY_FINANCE; break; - case 0x085: usage->code = KEY_SPORT; break; - case 0x086: usage->code = KEY_SHOP; break; - - default: usage->code = KEY_UNKNOWN; break; - + case 0x021: map_key_clear(KEY_PRINT); break; + case 0x070: map_key_clear(KEY_HP); break; + case 0x071: map_key_clear(KEY_CAMERA); break; + case 0x072: map_key_clear(KEY_SOUND); break; + case 0x073: map_key_clear(KEY_QUESTION); break; + case 0x080: map_key_clear(KEY_EMAIL); break; + case 0x081: map_key_clear(KEY_CHAT); break; + case 0x082: map_key_clear(KEY_SEARCH); break; + case 0x083: map_key_clear(KEY_CONNECT); break; + case 0x084: map_key_clear(KEY_FINANCE); break; + case 0x085: map_key_clear(KEY_SPORT); break; + case 0x086: map_key_clear(KEY_SHOP); break; + default: goto unknown; } - - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; break; case HID_UP_PID: - usage->type = EV_FF; bit = input->ffbit; max = FF_MAX; - + set_bit(EV_FF, input->evbit); switch(usage->hid & HID_USAGE) { - case 0x26: set_bit(FF_CONSTANT, input->ffbit); break; - case 0x27: set_bit(FF_RAMP, input->ffbit); break; - case 0x28: set_bit(FF_CUSTOM, input->ffbit); break; - case 0x30: set_bit(FF_SQUARE, input->ffbit); - set_bit(FF_PERIODIC, input->ffbit); break; - case 0x31: set_bit(FF_SINE, input->ffbit); - set_bit(FF_PERIODIC, input->ffbit); break; - case 0x32: set_bit(FF_TRIANGLE, input->ffbit); - set_bit(FF_PERIODIC, input->ffbit); break; - case 0x33: set_bit(FF_SAW_UP, input->ffbit); - set_bit(FF_PERIODIC, input->ffbit); break; - case 0x34: set_bit(FF_SAW_DOWN, input->ffbit); - set_bit(FF_PERIODIC, input->ffbit); break; - case 0x40: set_bit(FF_SPRING, input->ffbit); break; - case 0x41: set_bit(FF_DAMPER, input->ffbit); break; - case 0x42: set_bit(FF_INERTIA , input->ffbit); break; - case 0x43: set_bit(FF_FRICTION, input->ffbit); break; - case 0x7e: usage->code = FF_GAIN; break; - case 0x83: /* Simultaneous Effects Max */ - input->ff_effects_max = (field->value[0]); - dbg("Maximum Effects - %d",input->ff_effects_max); - break; - case 0x98: /* Device Control */ - usage->code = FF_AUTOCENTER; break; - case 0xa4: /* Safety Switch */ - usage->code = BTN_DEAD; - bit = input->keybit; - usage->type = EV_KEY; - max = KEY_MAX; - dbg("Safety Switch Report\n"); - break; - case 0x9f: /* Device Paused */ - case 0xa0: /* Actuators Enabled */ - dbg("Not telling the input API about "); - resolv_usage(usage->hid); - return; + case 0x26: map_ff_effect(FF_CONSTANT); goto ignore; + case 0x27: map_ff_effect(FF_RAMP); goto ignore; + case 0x28: map_ff_effect(FF_CUSTOM); goto ignore; + case 0x30: map_ff_effect(FF_SQUARE); map_ff_effect(FF_PERIODIC); goto ignore; + case 0x31: map_ff_effect(FF_SINE); map_ff_effect(FF_PERIODIC); goto ignore; + case 0x32: map_ff_effect(FF_TRIANGLE); map_ff_effect(FF_PERIODIC); goto ignore; + case 0x33: map_ff_effect(FF_SAW_UP); map_ff_effect(FF_PERIODIC); goto ignore; + case 0x34: map_ff_effect(FF_SAW_DOWN); map_ff_effect(FF_PERIODIC); goto ignore; + case 0x40: map_ff_effect(FF_SPRING); goto ignore; + case 0x41: map_ff_effect(FF_DAMPER); goto ignore; + case 0x42: map_ff_effect(FF_INERTIA); goto ignore; + case 0x43: map_ff_effect(FF_FRICTION); goto ignore; + case 0x7e: map_ff(FF_GAIN); break; + case 0x83: input->ff_effects_max = field->value[0]; goto ignore; + case 0x98: map_ff(FF_AUTOCENTER); break; + case 0xa4: map_key_clear(BTN_DEAD); break; + default: goto ignore; } break; + default: unknown: - resolv_usage(usage->hid); - if (field->report_size == 1) { - if (field->report->type == HID_OUTPUT_REPORT) { - usage->code = LED_MISC; - usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; + map_led(LED_MISC); break; } - - usage->code = BTN_MISC; - usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; + map_key(BTN_MISC); break; } - if (field->flags & HID_MAIN_ITEM_RELATIVE) { - usage->code = REL_MISC; - usage->type = EV_REL; bit = input->relbit; max = REL_MAX; + map_rel(REL_MISC); break; } - - usage->code = ABS_MISC; - usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; + map_abs(ABS_MISC); break; } set_bit(usage->type, input->evbit); - if ((usage->type == EV_REL) - && (device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_BACK - | HID_QUIRK_2WHEEL_MOUSE_HACK_EXTRA)) - && (usage->code == REL_WHEEL)) { - set_bit(REL_HWHEEL, bit); - } - while (usage->code <= max && test_and_set_bit(usage->code, bit)) { + while (usage->code <= max && test_and_set_bit(usage->code, bit)) usage->code = find_next_zero_bit(bit, max + 1, usage->code); - } if (usage->code > max) - return; + goto ignore; + + if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) && + (usage->type == EV_REL) && (usage->code == REL_WHEEL)) + set_bit(REL_HWHEEL, bit); + + if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005)) + || ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) + goto ignore; if (usage->type == EV_ABS) { + int a = field->logical_minimum; int b = field->logical_maximum; @@ -399,61 +360,69 @@ b = field->logical_maximum = 255; } - input->absmin[usage->code] = a; - input->absmax[usage->code] = b; - input->absfuzz[usage->code] = 0; - input->absflat[usage->code] = 0; - - if (field->application == HID_GD_GAMEPAD || field->application == HID_GD_JOYSTICK) { - input->absfuzz[usage->code] = (b - a) >> 8; - input->absflat[usage->code] = (b - a) >> 4; - } + if (field->application == HID_GD_GAMEPAD || field->application == HID_GD_JOYSTICK) + input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4); + else input_set_abs_params(input, usage->code, a, b, 0, 0); + } - if (usage->hat_min != usage->hat_max) { + if (usage->hat_min < usage->hat_max || usage->hat_dir) { int i; for (i = usage->code; i < usage->code + 2 && i <= max; i++) { - input->absmax[i] = 1; - input->absmin[i] = -1; - input->absfuzz[i] = 0; - input->absflat[i] = 0; + input_set_abs_params(input, i, -1, 1, 0, 0); + set_bit(i, input->absbit); } - set_bit(usage->code + 1, input->absbit); + if (usage->hat_dir && !field->dpad) + field->dpad = usage->code; } + +#ifdef DEBUG + resolv_event(usage->type, usage->code); + printk("\n"); +#endif + return; + +ignore: +#ifdef DEBUG + printk("IGNORED\n"); +#endif + return; } void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, struct pt_regs *regs) { - struct input_dev *input = find_input(hid, field); + struct input_dev *input = &field->hidinput->input; int *quirks = &hid->quirks; if (!input) return; + if (!usage->type) + return; + input_regs(input, regs); - if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_EXTRA) && (usage->code == BTN_EXTRA)) - || ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_BACK) && (usage->code == BTN_BACK))) { - if (value) - hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON; - else - hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON; + if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005)) + || ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) { + if (value) hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON; + else hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON; return; } - if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) - && (usage->code == REL_WHEEL)) { + if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) { input_event(input, usage->type, REL_HWHEEL, value); return; } - if (usage->hat_min != usage->hat_max ) { /* FIXME: hat_max can be 0 and hat_min 1 */ - value = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; - if (value < 0 || value > 8) value = 0; - input_event(input, usage->type, usage->code , hid_hat_to_axis[value].x); - input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[value].y); - return; - } + if (usage->hat_min < usage->hat_max || usage->hat_dir) { + int hat_dir = usage->hat_dir; + if (!hat_dir) + hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; + if (hat_dir < 0 || hat_dir > 8) hat_dir = 0; + input_event(input, usage->type, usage->code , hid_hat_to_axis[hat_dir].x); + input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[hat_dir].y); + return; + } if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */ *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT); @@ -481,6 +450,7 @@ dbg("Maximum Effects - %d",input->ff_effects_max); return; } + if (usage->hid == (HID_UP_PID | 0x7fUL)) { dbg("PID Pool Report\n"); return; @@ -556,9 +526,10 @@ INIT_LIST_HEAD(&hid->inputs); for (i = 0; i < hid->maxcollection; i++) - if (hid->collection[i].type == HID_COLLECTION_APPLICATION && - IS_INPUT_APPLICATION(hid->collection[i].usage)) - break; + if (hid->collection[i].type == HID_COLLECTION_APPLICATION || + hid->collection[i].type == HID_COLLECTION_PHYSICAL) + if (IS_INPUT_APPLICATION(hid->collection[i].usage)) + break; if (i == hid->maxcollection) return -1; diff -Nru a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h --- a/drivers/usb/input/hid.h 2004-09-23 21:12:57 -07:00 +++ b/drivers/usb/input/hid.h 2004-09-23 21:12:57 -07:00 @@ -171,6 +171,7 @@ #define HID_USAGE_PAGE 0xffff0000 +#define HID_UP_UNDEFINED 0x00000000 #define HID_UP_GENDESK 0x00010000 #define HID_UP_KEYBOARD 0x00070000 #define HID_UP_LED 0x00080000 @@ -187,7 +188,36 @@ #define HID_GD_MOUSE 0x00010002 #define HID_GD_JOYSTICK 0x00010004 #define HID_GD_GAMEPAD 0x00010005 +#define HID_GD_KEYBOARD 0x00010006 +#define HID_GD_KEYPAD 0x00010007 +#define HID_GD_MULTIAXIS 0x00010008 +#define HID_GD_X 0x00010030 +#define HID_GD_Y 0x00010031 +#define HID_GD_Z 0x00010032 +#define HID_GD_RX 0x00010033 +#define HID_GD_RY 0x00010034 +#define HID_GD_RZ 0x00010035 +#define HID_GD_SLIDER 0x00010036 +#define HID_GD_DIAL 0x00010037 +#define HID_GD_WHEEL 0x00010038 #define HID_GD_HATSWITCH 0x00010039 +#define HID_GD_BUFFER 0x0001003a +#define HID_GD_BYTECOUNT 0x0001003b +#define HID_GD_MOTION 0x0001003c +#define HID_GD_START 0x0001003d +#define HID_GD_SELECT 0x0001003e +#define HID_GD_VX 0x00010040 +#define HID_GD_VY 0x00010041 +#define HID_GD_VZ 0x00010042 +#define HID_GD_VBRX 0x00010043 +#define HID_GD_VBRY 0x00010044 +#define HID_GD_VBRZ 0x00010045 +#define HID_GD_VNO 0x00010046 +#define HID_GD_FEATURE 0x00010047 +#define HID_GD_UP 0x00010090 +#define HID_GD_DOWN 0x00010091 +#define HID_GD_RIGHT 0x00010092 +#define HID_GD_LEFT 0x00010093 /* * HID report types --- Ouch! HID spec says 1 2 3! @@ -208,8 +238,8 @@ #define HID_QUIRK_HIDDEV 0x010 #define HID_QUIRK_BADPAD 0x020 #define HID_QUIRK_MULTI_INPUT 0x040 -#define HID_QUIRK_2WHEEL_MOUSE_HACK_BACK 0x080 -#define HID_QUIRK_2WHEEL_MOUSE_HACK_EXTRA 0x100 +#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x080 +#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x100 #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x200 /* @@ -262,12 +292,16 @@ struct hid_usage { unsigned hid; /* hid usage code */ unsigned collection_index; /* index into collection array */ + /* hidinput data */ __u16 code; /* input driver code */ __u8 type; /* input driver type */ __s8 hat_min; /* hat switch fun */ __s8 hat_max; /* ditto */ + __s8 hat_dir; /* ditto */ }; +struct hid_input; + struct hid_field { unsigned physical; /* physical usage for this field */ unsigned logical; /* logical usage for this field */ @@ -288,6 +322,9 @@ unsigned unit; struct hid_report *report; /* associated report */ unsigned index; /* index into report->field[] */ + /* hidinput data */ + struct hid_input *hidinput; /* associated input structure */ + __u16 dpad; /* dpad input code */ }; #define HID_MAX_FIELDS 64 @@ -423,6 +460,7 @@ #define hid_dump_device(c) do { } while (0) #define hid_dump_field(a,b) do { } while (0) #define resolv_usage(a) do { } while (0) +#define resolv_event(a,b) do { } while (0) #endif #endif @@ -430,7 +468,7 @@ #ifdef CONFIG_USB_HIDINPUT /* Applications from HID Usage Tables 4/8/99 Version 1.1 */ /* We ignore a few input applications that are not widely used */ -#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || ( a == 0x00010080) || ( a == 0x000c0001)) +#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001)) extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32, struct pt_regs *regs); extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report); extern int hidinput_connect(struct hid_device *); diff -Nru a/include/linux/input.h b/include/linux/input.h --- a/include/linux/input.h 2004-09-23 21:12:57 -07:00 +++ b/include/linux/input.h 2004-09-23 21:12:57 -07:00 @@ -482,6 +482,9 @@ #define REL_X 0x00 #define REL_Y 0x01 #define REL_Z 0x02 +#define REL_RX 0x03 +#define REL_RY 0x04 +#define REL_RZ 0x05 #define REL_HWHEEL 0x06 #define REL_DIAL 0x07 #define REL_WHEEL 0x08 diff -Nru a/include/linux/libps2.h b/include/linux/libps2.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/include/linux/libps2.h 2004-09-23 21:12:57 -07:00 @@ -0,0 +1,50 @@ +#ifndef _LIBPS2_H +#define _LIBPS2_H + +/* + * Copyright (C) 1999-2002 Vojtech Pavlik + * Copyright (C) 2004 Dmitry Torokhov + * + * 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. + */ + + +#define PS2_CMD_GETID 0x02f2 +#define PS2_CMD_RESET_BAT 0x02ff + +#define PS2_RET_BAT 0xaa +#define PS2_RET_ID 0x00 +#define PS2_RET_ACK 0xfa +#define PS2_RET_NAK 0xfe + +#define PS2_FLAG_ACK 1 /* Waiting for ACK/NAK */ +#define PS2_FLAG_CMD 2 /* Waiting for command to finish */ +#define PS2_FLAG_CMD1 4 /* Waiting for the first byte of command response */ +#define PS2_FLAG_WAITID 8 /* Command execiting is GET ID */ + +struct ps2dev { + struct serio *serio; + + /* Ensures that only one command is executing at a time */ + struct semaphore cmd_sem; + + /* Used to signal completion from interrupt handler */ + wait_queue_head_t wait; + + unsigned long flags; + unsigned char cmdbuf[6]; + unsigned char cmdcnt; + unsigned char nak; +}; + +void ps2_init(struct ps2dev *ps2dev, struct serio *serio); +int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte); +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); + +#endif /* _LIBPS2_H */ diff -Nru a/include/linux/serio.h b/include/linux/serio.h --- a/include/linux/serio.h 2004-09-23 21:12:57 -07:00 +++ b/include/linux/serio.h 2004-09-23 21:12:57 -07:00 @@ -45,7 +45,8 @@ struct serio *parent, *child; - struct serio_driver *drv; /* accessed from interrupt, must be protected by serio->lock */ + struct serio_driver *drv; /* accessed from interrupt, must be protected by serio->lock and serio->sem */ + struct semaphore drv_sem; /* protects serio->drv so attributes can pin driver */ struct device dev; @@ -120,6 +121,19 @@ static __inline__ void serio_continue_rx(struct serio *serio) { spin_unlock_irq(&serio->lock); +} + +/* + * Use the following fucntions to pin serio's driver in process context + */ +static __inline__ int serio_pin_driver(struct serio *serio) +{ + return down_interruptible(&serio->drv_sem); +} + +static __inline__ void serio_unpin_driver(struct serio *serio) +{ + up(&serio->drv_sem); }