Commit 9c8680e2 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/dtor/input

* master.kernel.org:/pub/scm/linux/kernel/git/dtor/input: (26 commits)
  Input: add support for Braille devices
  Input: synaptics - limit rate to 40pps on Toshiba Protege M300
  Input: gamecon - add SNES mouse support
  Input: make modalias code respect allowed buffer size
  Input: convert /proc handling to seq_file
  Input: limit attributes' output to PAGE_SIZE
  Input: gameport - fix memory leak
  Input: serio - fix memory leak
  Input: zaurus keyboard driver updates
  Input: i8042 - fix logic around pnp_register_driver()
  Input: ns558 - fix logic around pnp_register_driver()
  Input: pcspkr - separate device and driver registration
  Input: atkbd - allow disabling on X86_PC (if EMBEDDED)
  Input: atkbd - disable softrepeat for dumb keyboards
  Input: atkbd - fix complaints about 'releasing unknown key 0x7f'
  Input: HID - fix duplicate key mapping for Logitech UltraX remote
  Input: use kzalloc() throughout the code
  Input: fix input_free_device() implementation
  Input: initialize serio and gameport at subsystem level
  Input: uinput - semaphore to mutex conversion
  ...
parents f900e582 b9ec4e10
...@@ -36,12 +36,12 @@ with them. ...@@ -36,12 +36,12 @@ with them.
All NES and SNES use the same synchronous serial protocol, clocked from All NES and SNES use the same synchronous serial protocol, clocked from
the computer's side (and thus timing insensitive). To allow up to 5 NES the computer's side (and thus timing insensitive). To allow up to 5 NES
and/or SNES gamepads connected to the parallel port at once, the output and/or SNES gamepads and/or SNES mice connected to the parallel port at once,
lines of the parallel port are shared, while one of 5 available input lines the output lines of the parallel port are shared, while one of 5 available
is assigned to each gamepad. input lines is assigned to each gamepad.
This protocol is handled by the gamecon.c driver, so that's the one This protocol is handled by the gamecon.c driver, so that's the one
you'll use for NES and SNES gamepads. you'll use for NES, SNES gamepads and SNES mice.
The main problem with PC parallel ports is that they don't have +5V power The main problem with PC parallel ports is that they don't have +5V power
source on any of their pins. So, if you want a reliable source of power source on any of their pins. So, if you want a reliable source of power
...@@ -106,7 +106,7 @@ A, Turbo B, Select and Start, and is connected through 5 wires, then it is ...@@ -106,7 +106,7 @@ A, Turbo B, Select and Start, and is connected through 5 wires, then it is
either a NES or NES clone and will work with this connection. SNES gamepads either a NES or NES clone and will work with this connection. SNES gamepads
also use 5 wires, but have more buttons. They will work as well, of course. also use 5 wires, but have more buttons. They will work as well, of course.
Pinout for NES gamepads Pinout for SNES gamepads Pinout for NES gamepads Pinout for SNES gamepads and mice
+----> Power +-----------------------\ +----> Power +-----------------------\
| 7 | o o o o | x x o | 1 | 7 | o o o o | x x o | 1
...@@ -454,6 +454,7 @@ uses the following kernel/module command line: ...@@ -454,6 +454,7 @@ uses the following kernel/module command line:
6 | N64 pad 6 | N64 pad
7 | Sony PSX controller 7 | Sony PSX controller
8 | Sony PSX DDR controller 8 | Sony PSX DDR controller
9 | SNES mouse
The exact type of the PSX controller type is autoprobed when used so The exact type of the PSX controller type is autoprobed when used so
hot swapping should work (but is not recomended). hot swapping should work (but is not recomended).
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
...@@ -1478,3 +1479,20 @@ alpha_panic_event(struct notifier_block *this, unsigned long event, void *ptr) ...@@ -1478,3 +1479,20 @@ alpha_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
#endif #endif
return NOTIFY_DONE; return NOTIFY_DONE;
} }
static __init int add_pcspkr(void)
{
struct platform_device *pd;
int ret;
pd = platform_device_alloc("pcspkr", -1);
if (!pd)
return -ENOMEM;
ret = platform_device_add(pd);
if (ret)
platform_device_put(pd);
return ret;
}
device_initcall(add_pcspkr);
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <linux/initrd.h> #include <linux/initrd.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/platform_device.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/mca.h> #include <linux/mca.h>
#include <linux/root_dev.h> #include <linux/root_dev.h>
...@@ -1547,6 +1548,23 @@ void __init setup_arch(char **cmdline_p) ...@@ -1547,6 +1548,23 @@ void __init setup_arch(char **cmdline_p)
#endif #endif
} }
static __init int add_pcspkr(void)
{
struct platform_device *pd;
int ret;
pd = platform_device_alloc("pcspkr", -1);
if (!pd)
return -ENOMEM;
ret = platform_device_add(pd);
if (ret)
platform_device_put(pd);
return ret;
}
device_initcall(add_pcspkr);
#include "setup_arch_post.h" #include "setup_arch_post.h"
/* /*
* Local Variables: * Local Variables:
......
...@@ -233,6 +233,7 @@ config MACH_JAZZ ...@@ -233,6 +233,7 @@ config MACH_JAZZ
select ARC32 select ARC32
select ARCH_MAY_HAVE_PC_FDC select ARCH_MAY_HAVE_PC_FDC
select GENERIC_ISA_DMA select GENERIC_ISA_DMA
select I8253
select I8259 select I8259
select ISA select ISA
select SYS_HAS_CPU_R4X00 select SYS_HAS_CPU_R4X00
...@@ -530,6 +531,7 @@ config QEMU ...@@ -530,6 +531,7 @@ config QEMU
select DMA_COHERENT select DMA_COHERENT
select GENERIC_ISA_DMA select GENERIC_ISA_DMA
select HAVE_STD_PC_SERIAL_PORT select HAVE_STD_PC_SERIAL_PORT
select I8253
select I8259 select I8259
select ISA select ISA
select SWAP_IO_SPACE select SWAP_IO_SPACE
...@@ -714,6 +716,7 @@ config SNI_RM200_PCI ...@@ -714,6 +716,7 @@ config SNI_RM200_PCI
select HAVE_STD_PC_SERIAL_PORT select HAVE_STD_PC_SERIAL_PORT
select HW_HAS_EISA select HW_HAS_EISA
select HW_HAS_PCI select HW_HAS_PCI
select I8253
select I8259 select I8259
select ISA select ISA
select SYS_HAS_CPU_R4X00 select SYS_HAS_CPU_R4X00
...@@ -1721,6 +1724,9 @@ config MMU ...@@ -1721,6 +1724,9 @@ config MMU
bool bool
default y default y
config I8253
bool
source "drivers/pcmcia/Kconfig" source "drivers/pcmcia/Kconfig"
source "drivers/pci/hotplug/Kconfig" source "drivers/pci/hotplug/Kconfig"
......
...@@ -59,6 +59,8 @@ obj-$(CONFIG_PROC_FS) += proc.o ...@@ -59,6 +59,8 @@ obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_64BIT) += cpu-bugs64.o obj-$(CONFIG_64BIT) += cpu-bugs64.o
obj-$(CONFIG_I8253) += i8253.o
CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi) CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
EXTRA_AFLAGS := $(CFLAGS) EXTRA_AFLAGS := $(CFLAGS)
/*
* Copyright (C) 2006 IBM Corporation
*
* Implements device information for i8253 timer chip
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation
*/
#include <linux/platform_device.h>
static __init int add_pcspkr(void)
{
struct platform_device *pd;
int ret;
pd = platform_device_alloc("pcspkr", -1);
if (!pd)
return -ENOMEM;
ret = platform_device_add(pd);
if (ret)
platform_device_put(pd);
return ret;
}
device_initcall(add_pcspkr);
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/initrd.h> #include <linux/initrd.h>
#include <linux/platform_device.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/ioport.h> #include <linux/ioport.h>
...@@ -462,6 +463,29 @@ static int __init early_xmon(char *p) ...@@ -462,6 +463,29 @@ static int __init early_xmon(char *p)
early_param("xmon", early_xmon); early_param("xmon", early_xmon);
#endif #endif
static __init int add_pcspkr(void)
{
struct device_node *np;
struct platform_device *pd;
int ret;
np = of_find_compatible_node(NULL, NULL, "pnpPNP,100");
of_node_put(np);
if (!np)
return -ENODEV;
pd = platform_device_alloc("pcspkr", -1);
if (!pd)
return -ENOMEM;
ret = platform_device_add(pd);
if (ret)
platform_device_put(pd);
return ret;
}
device_initcall(add_pcspkr);
void probe_machine(void) void probe_machine(void)
{ {
extern struct machdep_calls __machine_desc_start; extern struct machdep_calls __machine_desc_start;
......
...@@ -25,9 +25,6 @@ obj-$(CONFIG_CONNECTOR) += connector/ ...@@ -25,9 +25,6 @@ obj-$(CONFIG_CONNECTOR) += connector/
obj-$(CONFIG_FB_I810) += video/i810/ obj-$(CONFIG_FB_I810) += video/i810/
obj-$(CONFIG_FB_INTEL) += video/intelfb/ obj-$(CONFIG_FB_INTEL) += video/intelfb/
# we also need input/serio early so serio bus is initialized by the time
# serial drivers start registering their serio ports
obj-$(CONFIG_SERIO) += input/serio/
obj-y += serial/ obj-y += serial/
obj-$(CONFIG_PARPORT) += parport/ obj-$(CONFIG_PARPORT) += parport/
obj-y += base/ block/ misc/ mfd/ net/ media/ obj-y += base/ block/ misc/ mfd/ net/ media/
...@@ -53,6 +50,7 @@ obj-$(CONFIG_TC) += tc/ ...@@ -53,6 +50,7 @@ obj-$(CONFIG_TC) += tc/
obj-$(CONFIG_USB) += usb/ obj-$(CONFIG_USB) += usb/
obj-$(CONFIG_PCI) += usb/ obj-$(CONFIG_PCI) += usb/
obj-$(CONFIG_USB_GADGET) += usb/gadget/ obj-$(CONFIG_USB_GADGET) += usb/gadget/
obj-$(CONFIG_SERIO) += input/serio/
obj-$(CONFIG_GAMEPORT) += input/gameport/ obj-$(CONFIG_GAMEPORT) += input/gameport/
obj-$(CONFIG_INPUT) += input/ obj-$(CONFIG_INPUT) += input/
obj-$(CONFIG_I2O) += message/ obj-$(CONFIG_I2O) += message/
......
...@@ -74,7 +74,7 @@ void compute_shiftstate(void); ...@@ -74,7 +74,7 @@ void compute_shiftstate(void);
k_self, k_fn, k_spec, k_pad,\ k_self, k_fn, k_spec, k_pad,\
k_dead, k_cons, k_cur, k_shift,\ k_dead, k_cons, k_cur, k_shift,\
k_meta, k_ascii, k_lock, k_lowercase,\ k_meta, k_ascii, k_lock, k_lowercase,\
k_slock, k_dead2, k_ignore, k_ignore k_slock, k_dead2, k_brl, k_ignore
typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value, typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
char up_flag, struct pt_regs *regs); char up_flag, struct pt_regs *regs);
...@@ -100,7 +100,7 @@ static fn_handler_fn *fn_handler[] = { FN_HANDLERS }; ...@@ -100,7 +100,7 @@ static fn_handler_fn *fn_handler[] = { FN_HANDLERS };
const int max_vals[] = { const int max_vals[] = {
255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1, 255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1,
NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1, NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1,
255, NR_LOCK - 1, 255 255, NR_LOCK - 1, 255, NR_BRL - 1
}; };
const int NR_TYPES = ARRAY_SIZE(max_vals); const int NR_TYPES = ARRAY_SIZE(max_vals);
...@@ -126,7 +126,7 @@ static unsigned long key_down[NBITS(KEY_MAX)]; /* keyboard key bitmap */ ...@@ -126,7 +126,7 @@ static unsigned long key_down[NBITS(KEY_MAX)]; /* keyboard key bitmap */
static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */ static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
static int dead_key_next; static int dead_key_next;
static int npadch = -1; /* -1 or number assembled on pad */ static int npadch = -1; /* -1 or number assembled on pad */
static unsigned char diacr; static unsigned int diacr;
static char rep; /* flag telling character repeat */ static char rep; /* flag telling character repeat */
static unsigned char ledstate = 0xff; /* undefined */ static unsigned char ledstate = 0xff; /* undefined */
...@@ -394,22 +394,30 @@ void compute_shiftstate(void) ...@@ -394,22 +394,30 @@ void compute_shiftstate(void)
* Otherwise, conclude that DIACR was not combining after all, * Otherwise, conclude that DIACR was not combining after all,
* queue it and return CH. * queue it and return CH.
*/ */
static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch) static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch)
{ {
int d = diacr; unsigned int d = diacr;
unsigned int i; unsigned int i;
diacr = 0; diacr = 0;
for (i = 0; i < accent_table_size; i++) { if ((d & ~0xff) == BRL_UC_ROW) {
if ((ch & ~0xff) == BRL_UC_ROW)
return d | ch;
} else {
for (i = 0; i < accent_table_size; i++)
if (accent_table[i].diacr == d && accent_table[i].base == ch) if (accent_table[i].diacr == d && accent_table[i].base == ch)
return accent_table[i].result; return accent_table[i].result;
} }
if (ch == ' ' || ch == d) if (ch == ' ' || ch == (BRL_UC_ROW|0) || ch == d)
return d; return d;
if (kbd->kbdmode == VC_UNICODE)
to_utf8(vc, d);
else if (d < 0x100)
put_queue(vc, d); put_queue(vc, d);
return ch; return ch;
} }
...@@ -419,6 +427,9 @@ static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch) ...@@ -419,6 +427,9 @@ static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch)
static void fn_enter(struct vc_data *vc, struct pt_regs *regs) static void fn_enter(struct vc_data *vc, struct pt_regs *regs)
{ {
if (diacr) { if (diacr) {
if (kbd->kbdmode == VC_UNICODE)
to_utf8(vc, diacr);
else if (diacr < 0x100)
put_queue(vc, diacr); put_queue(vc, diacr);
diacr = 0; diacr = 0;
} }
...@@ -615,7 +626,7 @@ static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag, s ...@@ -615,7 +626,7 @@ static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag, s
printk(KERN_ERR "keyboard.c: k_lowercase was called - impossible\n"); printk(KERN_ERR "keyboard.c: k_lowercase was called - impossible\n");
} }
static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag, struct pt_regs *regs)
{ {
if (up_flag) if (up_flag)
return; /* no action, if this is a key release */ return; /* no action, if this is a key release */
...@@ -628,6 +639,9 @@ static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct ...@@ -628,6 +639,9 @@ static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct
diacr = value; diacr = value;
return; return;
} }
if (kbd->kbdmode == VC_UNICODE)
to_utf8(vc, value);
else if (value < 0x100)
put_queue(vc, value); put_queue(vc, value);
} }
...@@ -636,13 +650,23 @@ static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct ...@@ -636,13 +650,23 @@ static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct
* dead keys modifying the same character. Very useful * dead keys modifying the same character. Very useful
* for Vietnamese. * for Vietnamese.
*/ */
static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag, struct pt_regs *regs)
{ {
if (up_flag) if (up_flag)
return; return;
diacr = (diacr ? handle_diacr(vc, value) : value); diacr = (diacr ? handle_diacr(vc, value) : value);
} }
static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
{
k_unicode(vc, value, up_flag, regs);
}
static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
{
k_deadunicode(vc, value, up_flag, regs);
}
/* /*
* Obsolete - for backwards compatibility only * Obsolete - for backwards compatibility only
*/ */
...@@ -650,7 +674,7 @@ static void k_dead(struct vc_data *vc, unsigned char value, char up_flag, struct ...@@ -650,7 +674,7 @@ static void k_dead(struct vc_data *vc, unsigned char value, char up_flag, struct
{ {
static unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' }; static unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
value = ret_diacr[value]; value = ret_diacr[value];
k_dead2(vc, value, up_flag, regs); k_deadunicode(vc, value, up_flag, regs);
} }
static void k_cons(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) static void k_cons(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
...@@ -835,6 +859,62 @@ static void k_slock(struct vc_data *vc, unsigned char value, char up_flag, struc ...@@ -835,6 +859,62 @@ static void k_slock(struct vc_data *vc, unsigned char value, char up_flag, struc
} }
} }
/* by default, 300ms interval for combination release */
static long brl_timeout = 300;
MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for combination on first release, < 0 for dead characters)");
module_param(brl_timeout, long, 0644);
static void k_brl(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
{
static unsigned pressed,committing;
static unsigned long releasestart;
if (kbd->kbdmode != VC_UNICODE) {
if (!up_flag)
printk("keyboard mode must be unicode for braille patterns\n");
return;
}
if (!value) {
k_unicode(vc, BRL_UC_ROW, up_flag, regs);
return;
}
if (value > 8)
return;
if (brl_timeout < 0) {
k_deadunicode(vc, BRL_UC_ROW | (1 << (value - 1)), up_flag, regs);
return;
}
if (up_flag) {
if (brl_timeout) {
if (!committing ||
jiffies - releasestart > (brl_timeout * HZ) / 1000) {
committing = pressed;
releasestart = jiffies;
}
pressed &= ~(1 << (value - 1));
if (!pressed) {
if (committing) {
k_unicode(vc, BRL_UC_ROW | committing, 0, regs);
committing = 0;
}
}
} else {
if (committing) {
k_unicode(vc, BRL_UC_ROW | committing, 0, regs);
committing = 0;
}
pressed &= ~(1 << (value - 1));
}
} else {
pressed |= 1 << (value - 1);
if (!brl_timeout)
committing = pressed;
}
}
/* /*
* The leds display either (i) the status of NumLock, CapsLock, ScrollLock, * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
* or (ii) whatever pattern of lights people want to show using KDSETLED, * or (ii) whatever pattern of lights people want to show using KDSETLED,
...@@ -1125,9 +1205,13 @@ static void kbd_keycode(unsigned int keycode, int down, ...@@ -1125,9 +1205,13 @@ static void kbd_keycode(unsigned int keycode, int down,
} }
if (keycode > NR_KEYS) if (keycode > NR_KEYS)
if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
keysym = K(KT_BRL, keycode - KEY_BRL_DOT1 + 1);
else
return; return;
else
keysym = key_map[keycode]; keysym = key_map[keycode];
type = KTYP(keysym); type = KTYP(keysym);
if (type < 0xf0) { if (type < 0xf0) {
......
...@@ -49,9 +49,8 @@ static struct input_handle *evbug_connect(struct input_handler *handler, struct ...@@ -49,9 +49,8 @@ static struct input_handle *evbug_connect(struct input_handler *handler, struct
{ {
struct input_handle *handle; struct input_handle *handle;
if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL))) if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL)))
return NULL; return NULL;
memset(handle, 0, sizeof(struct input_handle));
handle->dev = dev; handle->dev = dev;
handle->handler = handler; handle->handler = handler;
......
...@@ -130,9 +130,8 @@ static int evdev_open(struct inode * inode, struct file * file) ...@@ -130,9 +130,8 @@ static int evdev_open(struct inode * inode, struct file * file)
if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file))) if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file)))
return accept_err; return accept_err;
if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL))) if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL)))
return -ENOMEM; return -ENOMEM;
memset(list, 0, sizeof(struct evdev_list));
list->evdev = evdev_table[i]; list->evdev = evdev_table[i];
list_add_tail(&list->node, &evdev_table[i]->list); list_add_tail(&list->node, &evdev_table[i]->list);
...@@ -609,9 +608,8 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct ...@@ -609,9 +608,8 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct
return NULL; return NULL;
} }
if (!(evdev = kmalloc(sizeof(struct evdev), GFP_KERNEL))) if (!(evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL)))
return NULL; return NULL;
memset(evdev, 0, sizeof(struct evdev));
INIT_LIST_HEAD(&evdev->list); INIT_LIST_HEAD(&evdev->list);
init_waitqueue_head(&evdev->wait); init_waitqueue_head(&evdev->wait);
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/sched.h> /* HZ */ #include <linux/sched.h> /* HZ */
#include <linux/mutex.h>
/*#include <asm/io.h>*/ /*#include <asm/io.h>*/
...@@ -43,10 +44,10 @@ EXPORT_SYMBOL(gameport_start_polling); ...@@ -43,10 +44,10 @@ EXPORT_SYMBOL(gameport_start_polling);
EXPORT_SYMBOL(gameport_stop_polling); EXPORT_SYMBOL(gameport_stop_polling);
/* /*
* gameport_sem protects entire gameport subsystem and is taken * gameport_mutex protects entire gameport subsystem and is taken
* every time gameport port or driver registrered or unregistered. * every time gameport port or driver registrered or unregistered.
*/ */
static DECLARE_MUTEX(gameport_sem); static DEFINE_MUTEX(gameport_mutex);
static LIST_HEAD(gameport_list); static LIST_HEAD(gameport_list);
...@@ -265,6 +266,7 @@ static void gameport_queue_event(void *object, struct module *owner, ...@@ -265,6 +266,7 @@ static void gameport_queue_event(void *object, struct module *owner,
if ((event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC))) { if ((event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC))) {
if (!try_module_get(owner)) { if (!try_module_get(owner)) {
printk(KERN_WARNING "gameport: Can't get module reference, dropping event %d\n", event_type); printk(KERN_WARNING "gameport: Can't get module reference, dropping event %d\n", event_type);
kfree(event);
goto out; goto out;
} }
...@@ -342,7 +344,7 @@ static void gameport_handle_event(void) ...@@ -342,7 +344,7 @@ static void gameport_handle_event(void)
struct gameport_event *event; struct gameport_event *event;
struct gameport_driver *gameport_drv; struct gameport_driver *gameport_drv;
down(&gameport_sem); mutex_lock(&gameport_mutex);
/* /*
* Note that we handle only one event here to give swsusp * Note that we handle only one event here to give swsusp
...@@ -379,7 +381,7 @@ static void gameport_handle_event(void) ...@@ -379,7 +381,7 @@ static void gameport_handle_event(void)
gameport_free_event(event); gameport_free_event(event);
} }
up(&gameport_sem); mutex_unlock(&gameport_mutex);
} }
/* /*
...@@ -464,7 +466,7 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut ...@@ -464,7 +466,7 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut
struct device_driver *drv; struct device_driver *drv;
int retval; int retval;
retval = down_interruptible(&gameport_sem); retval = mutex_lock_interruptible(&gameport_mutex);
if (retval) if (retval)
return retval; return retval;
...@@ -484,7 +486,7 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut ...@@ -484,7 +486,7 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut
retval = -EINVAL; retval = -EINVAL;
} }
up(&gameport_sem); mutex_unlock(&gameport_mutex);
return retval; return retval;
} }
...@@ -521,7 +523,7 @@ static void gameport_init_port(struct gameport *gameport) ...@@ -521,7 +523,7 @@ static void gameport_init_port(struct gameport *gameport)
__module_get(THIS_MODULE); __module_get(THIS_MODULE);
init_MUTEX(&gameport->drv_sem); mutex_init(&gameport->drv_mutex);
device_initialize(&gameport->dev); device_initialize(&gameport->dev);
snprintf(gameport->dev.bus_id, sizeof(gameport->dev.bus_id), snprintf(gameport->dev.bus_id, sizeof(gameport->dev.bus_id),
"gameport%lu", (unsigned long)atomic_inc_return(&gameport_no) - 1); "gameport%lu", (unsigned long)atomic_inc_return(&gameport_no) - 1);
...@@ -661,10 +663,10 @@ void __gameport_register_port(struct gameport *gameport, struct module *owner) ...@@ -661,10 +663,10 @@ void __gameport_register_port(struct gameport *gameport, struct module *owner)
*/ */
void gameport_unregister_port(struct gameport *gameport) void gameport_unregister_port(struct gameport *gameport)
{ {
down(&gameport_sem); mutex_lock(&gameport_mutex);
gameport_disconnect_port(gameport); gameport_disconnect_port(gameport);
gameport_destroy_port(gameport); gameport_destroy_port(gameport);
up(&gameport_sem); mutex_unlock(&gameport_mutex);
} }
...@@ -717,7 +719,7 @@ void gameport_unregister_driver(struct gameport_driver *drv) ...@@ -717,7 +719,7 @@ void gameport_unregister_driver(struct gameport_driver *drv)
{ {
struct gameport *gameport; struct gameport *gameport;
down(&gameport_sem); mutex_lock(&gameport_mutex);
drv->ignore = 1; /* so gameport_find_driver ignores it */ drv->ignore = 1; /* so gameport_find_driver ignores it */
start_over: start_over:
...@@ -731,7 +733,7 @@ void gameport_unregister_driver(struct gameport_driver *drv) ...@@ -731,7 +733,7 @@ void gameport_unregister_driver(struct gameport_driver *drv)
} }
driver_unregister(&drv->driver); driver_unregister(&drv->driver);
up(&gameport_sem); mutex_unlock(&gameport_mutex);
} }
static int gameport_bus_match(struct device *dev, struct device_driver *drv) static int gameport_bus_match(struct device *dev, struct device_driver *drv)
...@@ -743,9 +745,9 @@ static int gameport_bus_match(struct device *dev, struct device_driver *drv) ...@@ -743,9 +745,9 @@ static int gameport_bus_match(struct device *dev, struct device_driver *drv)
static void gameport_set_drv(struct gameport *gameport, struct gameport_driver *drv) static void gameport_set_drv(struct gameport *gameport, struct gameport_driver *drv)
{ {
down(&gameport->drv_sem); mutex_lock(&gameport->drv_mutex);
gameport->drv = drv; gameport->drv = drv;
up(&gameport->drv_sem); mutex_unlock(&gameport->drv_mutex);
} }
int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode) int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode)
...@@ -796,5 +798,5 @@ static void __exit gameport_exit(void) ...@@ -796,5 +798,5 @@ static void __exit gameport_exit(void)
kthread_stop(gameport_task); kthread_stop(gameport_task);
} }
module_init(gameport_init); subsys_initcall(gameport_init);
module_exit(gameport_exit); module_exit(gameport_exit);
...@@ -252,14 +252,14 @@ static struct pnp_driver ns558_pnp_driver; ...@@ -252,14 +252,14 @@ static struct pnp_driver ns558_pnp_driver;
#endif #endif
static int pnp_registered = 0;
static int __init ns558_init(void) static int __init ns558_init(void)
{ {
int i = 0; int i = 0;
int error;
if (pnp_register_driver(&ns558_pnp_driver) >= 0) error = pnp_register_driver(&ns558_pnp_driver);
pnp_registered = 1; if (error && error != -ENODEV) /* should be ENOSYS really */
return error;
/* /*
* Probe ISA ports after PnP, so that PnP ports that are already * Probe ISA ports after PnP, so that PnP ports that are already
...@@ -270,7 +270,7 @@ static int __init ns558_init(void) ...@@ -270,7 +270,7 @@ static int __init ns558_init(void)
while (ns558_isa_portlist[i]) while (ns558_isa_portlist[i])
ns558_isa_probe(ns558_isa_portlist[i++]); ns558_isa_probe(ns558_isa_portlist[i++]);
return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0; return list_empty(&ns558_list) && error ? -ENODEV : 0;
} }
static void __exit ns558_exit(void) static void __exit ns558_exit(void)
...@@ -283,7 +283,6 @@ static void __exit ns558_exit(void) ...@@ -283,7 +283,6 @@ static void __exit ns558_exit(void)
kfree(ns558); kfree(ns558);
} }
if (pnp_registered)
pnp_unregister_driver(&ns558_pnp_driver); pnp_unregister_driver(&ns558_pnp_driver);
} }
......
...@@ -18,9 +18,11 @@ ...@@ -18,9 +18,11 @@
#include <linux/random.h> #include <linux/random.h>
#include <linux/major.h> #include <linux/major.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/mutex.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("Input core"); MODULE_DESCRIPTION("Input core");
...@@ -224,7 +226,7 @@ int input_open_device(struct input_handle *handle) ...@@ -224,7 +226,7 @@ int input_open_device(struct input_handle *handle)
struct input_dev *dev = handle->dev; struct input_dev *dev = handle->dev;
int err; int err;
err = down_interruptible(&dev->sem); err = mutex_lock_interruptible(&dev->mutex);
if (err) if (err)
return err; return err;
...@@ -236,7 +238,7 @@ int input_open_device(struct input_handle *handle) ...@@ -236,7 +238,7 @@ int input_open_device(struct input_handle *handle)
if (err) if (err)
handle->open--; handle->open--;
up(&dev->sem); mutex_unlock(&dev->mutex);
return err; return err;
} }
...@@ -255,13 +257,13 @@ void input_close_device(struct input_handle *handle) ...@@ -255,13 +257,13 @@ void input_close_device(struct input_handle *handle)
input_release_device(handle); input_release_device(handle);
down(&dev->sem); mutex_lock(&dev->mutex);
if (!--dev->users && dev->close) if (!--dev->users && dev->close)
dev->close(dev); dev->close(dev);
handle->open--; handle->open--;
up(&dev->sem); mutex_unlock(&dev->mutex);
} }
static void input_link_handle(struct input_handle *handle) static void input_link_handle(struct input_handle *handle)
...@@ -315,21 +317,6 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st ...@@ -315,21 +317,6 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st
return NULL; return NULL;
} }
static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, int max)
{
int i;
int len = 0;
for (i = NBITS(max) - 1; i > 0; i--)
if (bitmap[i])
break;
for (; i >= 0; i--)
len += snprintf(buf + len, max(buf_size - len, 0),
"%lx%s", bitmap[i], i > 0 ? " " : "");
return len;
}
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static struct proc_dir_entry *proc_bus_input_dir; static struct proc_dir_entry *proc_bus_input_dir;
...@@ -342,7 +329,7 @@ static inline void input_wakeup_procfs_readers(void) ...@@ -342,7 +329,7 @@ static inline void input_wakeup_procfs_readers(void)
wake_up(&input_devices_poll_wait); wake_up(&input_devices_poll_wait);
} }
static unsigned int input_devices_poll(struct file *file, poll_table *wait) static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait)
{ {
int state = input_devices_state; int state = input_devices_state;
poll_wait(file, &input_devices_poll_wait, wait); poll_wait(file, &input_devices_poll_wait, wait);
...@@ -351,115 +338,171 @@ static unsigned int input_devices_poll(struct file *file, poll_table *wait) ...@@ -351,115 +338,171 @@ static unsigned int input_devices_poll(struct file *file, poll_table *wait)
return 0; return 0;
} }
#define SPRINTF_BIT(ev, bm) \ static struct list_head *list_get_nth_element(struct list_head *list, loff_t *pos)
do { \ {
len += sprintf(buf + len, "B: %s=", #ev); \ struct list_head *node;
len += input_print_bitmap(buf + len, INT_MAX, \ loff_t i = 0;
dev->bm##bit, ev##_MAX); \
len += sprintf(buf + len, "\n"); \
} while (0)
#define TEST_AND_SPRINTF_BIT(ev, bm) \ list_for_each(node, list)
do { \ if (i++ == *pos)
if (test_bit(EV_##ev, dev->evbit)) \ return node;
SPRINTF_BIT(ev, bm); \
} while (0) return NULL;
}
static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data) static struct list_head *list_get_next_element(struct list_head *list, struct list_head *element, loff_t *pos)
{ {
struct input_dev *dev; if (element->next == list)
struct input_handle *handle; return NULL;
const char *path;
off_t at = 0; ++(*pos);
int len, cnt = 0; return element->next;
}
list_for_each_entry(dev, &input_dev_list, node) { static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos)
{
/* acquire lock here ... Yes, we do need locking, I knowi, I know... */
path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL); return list_get_nth_element(&input_dev_list, pos);
}
static void *input_devices_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
return list_get_next_element(&input_dev_list, v, pos);
}
len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n", static void input_devices_seq_stop(struct seq_file *seq, void *v)
{
/* release lock here */
}
static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
unsigned long *bitmap, int max)
{
int i;
for (i = NBITS(max) - 1; i > 0; i--)
if (bitmap[i])
break;
seq_printf(seq, "B: %s=", name);
for (; i >= 0; i--)
seq_printf(seq, "%lx%s", bitmap[i], i > 0 ? " " : "");
seq_putc(seq, '\n');
}
static int input_devices_seq_show(struct seq_file *seq, void *v)
{
struct input_dev *dev = container_of(v, struct input_dev, node);
const char *path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
struct input_handle *handle;
seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version); dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version);
len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : ""); seq_printf(seq, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : ""); seq_printf(seq, "P: Phys=%s\n", dev->phys ? dev->phys : "");
len += sprintf(buf + len, "S: Sysfs=%s\n", path ? path : ""); seq_printf(seq, "S: Sysfs=%s\n", path ? path : "");
len += sprintf(buf + len, "H: Handlers="); seq_printf(seq, "H: Handlers=");
list_for_each_entry(handle, &dev->h_list, d_node) list_for_each_entry(handle, &dev->h_list, d_node)
len += sprintf(buf + len, "%s ", handle->name); seq_printf(seq, "%s ", handle->name);
seq_putc(seq, '\n');
len += sprintf(buf + len, "\n");
input_seq_print_bitmap(seq, "EV", dev->evbit, EV_MAX);
SPRINTF_BIT(EV, ev); if (test_bit(EV_KEY, dev->evbit))
TEST_AND_SPRINTF_BIT(KEY, key); input_seq_print_bitmap(seq, "KEY", dev->keybit, KEY_MAX);
TEST_AND_SPRINTF_BIT(REL, rel); if (test_bit(EV_REL, dev->evbit))
TEST_AND_SPRINTF_BIT(ABS, abs); input_seq_print_bitmap(seq, "REL", dev->relbit, REL_MAX);
TEST_AND_SPRINTF_BIT(MSC, msc); if (test_bit(EV_ABS, dev->evbit))
TEST_AND_SPRINTF_BIT(LED, led); input_seq_print_bitmap(seq, "ABS", dev->absbit, ABS_MAX);
TEST_AND_SPRINTF_BIT(SND, snd); if (test_bit(EV_MSC, dev->evbit))
TEST_AND_SPRINTF_BIT(FF, ff); input_seq_print_bitmap(seq, "MSC", dev->mscbit, MSC_MAX);
TEST_AND_SPRINTF_BIT(SW, sw); if (test_bit(EV_LED, dev->evbit))
input_seq_print_bitmap(seq, "LED", dev->ledbit, LED_MAX);
len += sprintf(buf + len, "\n"); if (test_bit(EV_SND, dev->evbit))
input_seq_print_bitmap(seq, "SND", dev->sndbit, SND_MAX);
at += len; if (test_bit(EV_FF, dev->evbit))
input_seq_print_bitmap(seq, "FF", dev->ffbit, FF_MAX);
if (at >= pos) { if (test_bit(EV_SW, dev->evbit))
if (!*start) { input_seq_print_bitmap(seq, "SW", dev->swbit, SW_MAX);
*start = buf + (pos - (at - len));
cnt = at - pos; seq_putc(seq, '\n');
} else cnt += len;
buf += len;
if (cnt >= count)
break;
}
kfree(path); kfree(path);
} return 0;
}
static struct seq_operations input_devices_seq_ops = {
.start = input_devices_seq_start,
.next = input_devices_seq_next,
.stop = input_devices_seq_stop,
.show = input_devices_seq_show,
};
if (&dev->node == &input_dev_list) static int input_proc_devices_open(struct inode *inode, struct file *file)
*eof = 1; {
return seq_open(file, &input_devices_seq_ops);
}
static struct file_operations input_devices_fileops = {
.owner = THIS_MODULE,
.open = input_proc_devices_open,
.poll = input_proc_devices_poll,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
return (count > cnt) ? cnt : count; static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos)
{
/* acquire lock here ... Yes, we do need locking, I knowi, I know... */
seq->private = (void *)(unsigned long)*pos;
return list_get_nth_element(&input_handler_list, pos);
} }
static int input_handlers_read(char *buf, char **start, off_t pos, int count, int *eof, void *data) static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{ {
struct input_handler *handler; seq->private = (void *)(unsigned long)(*pos + 1);
return list_get_next_element(&input_handler_list, v, pos);
}
off_t at = 0; static void input_handlers_seq_stop(struct seq_file *seq, void *v)
int len = 0, cnt = 0; {
int i = 0; /* release lock here */
}
list_for_each_entry(handler, &input_handler_list, node) { static int input_handlers_seq_show(struct seq_file *seq, void *v)
{
struct input_handler *handler = container_of(v, struct input_handler, node);
seq_printf(seq, "N: Number=%ld Name=%s",
(unsigned long)seq->private, handler->name);
if (handler->fops) if (handler->fops)
len = sprintf(buf, "N: Number=%d Name=%s Minor=%d\n", seq_printf(seq, " Minor=%d", handler->minor);
i++, handler->name, handler->minor); seq_putc(seq, '\n');
else
len = sprintf(buf, "N: Number=%d Name=%s\n",
i++, handler->name);
at += len;
if (at >= pos) {
if (!*start) {
*start = buf + (pos - (at - len));
cnt = at - pos;
} else cnt += len;
buf += len;
if (cnt >= count)
break;
}
}
if (&handler->node == &input_handler_list)
*eof = 1;
return (count > cnt) ? cnt : count; return 0;
}
static struct seq_operations input_handlers_seq_ops = {
.start = input_handlers_seq_start,
.next = input_handlers_seq_next,
.stop = input_handlers_seq_stop,
.show = input_handlers_seq_show,
};
static int input_proc_handlers_open(struct inode *inode, struct file *file)
{
return seq_open(file, &input_handlers_seq_ops);
} }
static struct file_operations input_fileops; static struct file_operations input_handlers_fileops = {
.owner = THIS_MODULE,
.open = input_proc_handlers_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
static int __init input_proc_init(void) static int __init input_proc_init(void)
{ {
...@@ -471,20 +514,19 @@ static int __init input_proc_init(void) ...@@ -471,20 +514,19 @@ static int __init input_proc_init(void)
proc_bus_input_dir->owner = THIS_MODULE; proc_bus_input_dir->owner = THIS_MODULE;
entry = create_proc_read_entry("devices", 0, proc_bus_input_dir, input_devices_read, NULL); entry = create_proc_entry("devices", 0, proc_bus_input_dir);
if (!entry) if (!entry)
goto fail1; goto fail1;
entry->owner = THIS_MODULE; entry->owner = THIS_MODULE;
input_fileops = *entry->proc_fops; entry->proc_fops = &input_devices_fileops;
input_fileops.poll = input_devices_poll;
entry->proc_fops = &input_fileops;
entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL); entry = create_proc_entry("handlers", 0, proc_bus_input_dir);
if (!entry) if (!entry)
goto fail2; goto fail2;
entry->owner = THIS_MODULE; entry->owner = THIS_MODULE;
entry->proc_fops = &input_handlers_fileops;
return 0; return 0;
...@@ -512,13 +554,14 @@ static ssize_t input_dev_show_##name(struct class_device *dev, char *buf) \ ...@@ -512,13 +554,14 @@ static ssize_t input_dev_show_##name(struct class_device *dev, char *buf) \
struct input_dev *input_dev = to_input_dev(dev); \ struct input_dev *input_dev = to_input_dev(dev); \
int retval; \ int retval; \
\ \
retval = down_interruptible(&input_dev->sem); \ retval = mutex_lock_interruptible(&input_dev->mutex); \
if (retval) \ if (retval) \
return retval; \ return retval; \
\ \
retval = sprintf(buf, "%s\n", input_dev->name ? input_dev->name : ""); \ retval = scnprintf(buf, PAGE_SIZE, \
"%s\n", input_dev->name ? input_dev->name : ""); \
\ \
up(&input_dev->sem); \ mutex_unlock(&input_dev->mutex); \
\ \
return retval; \ return retval; \
} \ } \
...@@ -528,46 +571,51 @@ INPUT_DEV_STRING_ATTR_SHOW(name); ...@@ -528,46 +571,51 @@ INPUT_DEV_STRING_ATTR_SHOW(name);
INPUT_DEV_STRING_ATTR_SHOW(phys); INPUT_DEV_STRING_ATTR_SHOW(phys);
INPUT_DEV_STRING_ATTR_SHOW(uniq); INPUT_DEV_STRING_ATTR_SHOW(uniq);
static int print_modalias_bits(char *buf, int size, char prefix, unsigned long *arr, static int input_print_modalias_bits(char *buf, int size,
unsigned int min, unsigned int max) char name, unsigned long *bm,
unsigned int min_bit, unsigned int max_bit)
{ {
int len, i; int len = 0, i;
len = snprintf(buf, size, "%c", prefix); len += snprintf(buf, max(size, 0), "%c", name);
for (i = min; i < max; i++) for (i = min_bit; i < max_bit; i++)
if (arr[LONG(i)] & BIT(i)) if (bm[LONG(i)] & BIT(i))
len += snprintf(buf + len, size - len, "%X,", i); len += snprintf(buf + len, max(size - len, 0), "%X,", i);
return len; return len;
} }
static int print_modalias(char *buf, int size, struct input_dev *id) static int input_print_modalias(char *buf, int size, struct input_dev *id,
int add_cr)
{ {
int len; int len;
len = snprintf(buf, size, "input:b%04Xv%04Xp%04Xe%04X-", len = snprintf(buf, max(size, 0),
id->id.bustype, "input:b%04Xv%04Xp%04Xe%04X-",
id->id.vendor, id->id.bustype, id->id.vendor,
id->id.product, id->id.product, id->id.version);
id->id.version);
len += input_print_modalias_bits(buf + len, size - len,
len += print_modalias_bits(buf + len, size - len, 'e', id->evbit, 'e', id->evbit, 0, EV_MAX);
0, EV_MAX); len += input_print_modalias_bits(buf + len, size - len,
len += print_modalias_bits(buf + len, size - len, 'k', id->keybit, 'k', id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
KEY_MIN_INTERESTING, KEY_MAX); len += input_print_modalias_bits(buf + len, size - len,
len += print_modalias_bits(buf + len, size - len, 'r', id->relbit, 'r', id->relbit, 0, REL_MAX);
0, REL_MAX); len += input_print_modalias_bits(buf + len, size - len,
len += print_modalias_bits(buf + len, size - len, 'a', id->absbit, 'a', id->absbit, 0, ABS_MAX);
0, ABS_MAX); len += input_print_modalias_bits(buf + len, size - len,
len += print_modalias_bits(buf + len, size - len, 'm', id->mscbit, 'm', id->mscbit, 0, MSC_MAX);
0, MSC_MAX); len += input_print_modalias_bits(buf + len, size - len,
len += print_modalias_bits(buf + len, size - len, 'l', id->ledbit, 'l', id->ledbit, 0, LED_MAX);
0, LED_MAX); len += input_print_modalias_bits(buf + len, size - len,
len += print_modalias_bits(buf + len, size - len, 's', id->sndbit, 's', id->sndbit, 0, SND_MAX);
0, SND_MAX); len += input_print_modalias_bits(buf + len, size - len,
len += print_modalias_bits(buf + len, size - len, 'f', id->ffbit, 'f', id->ffbit, 0, FF_MAX);
0, FF_MAX); len += input_print_modalias_bits(buf + len, size - len,
len += print_modalias_bits(buf + len, size - len, 'w', id->swbit, 'w', id->swbit, 0, SW_MAX);
0, SW_MAX);
if (add_cr)
len += snprintf(buf + len, max(size - len, 0), "\n");
return len; return len;
} }
...@@ -576,9 +624,9 @@ static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf) ...@@ -576,9 +624,9 @@ static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
struct input_dev *id = to_input_dev(dev); struct input_dev *id = to_input_dev(dev);
ssize_t len; ssize_t len;
len = print_modalias(buf, PAGE_SIZE, id); len = input_print_modalias(buf, PAGE_SIZE, id, 1);
len += snprintf(buf + len, PAGE_SIZE-len, "\n");
return len; return max_t(int, len, PAGE_SIZE);
} }
static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
...@@ -598,7 +646,7 @@ static struct attribute_group input_dev_attr_group = { ...@@ -598,7 +646,7 @@ static struct attribute_group input_dev_attr_group = {
static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf) \ static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf) \
{ \ { \
struct input_dev *input_dev = to_input_dev(dev); \ struct input_dev *input_dev = to_input_dev(dev); \
return sprintf(buf, "%04x\n", input_dev->id.name); \ return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name); \
} \ } \
static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL); static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL);
...@@ -620,11 +668,33 @@ static struct attribute_group input_dev_id_attr_group = { ...@@ -620,11 +668,33 @@ static struct attribute_group input_dev_id_attr_group = {
.attrs = input_dev_id_attrs, .attrs = input_dev_id_attrs,
}; };
static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
int max, int add_cr)
{
int i;
int len = 0;
for (i = NBITS(max) - 1; i > 0; i--)
if (bitmap[i])
break;
for (; i >= 0; i--)
len += snprintf(buf + len, max(buf_size - len, 0),
"%lx%s", bitmap[i], i > 0 ? " " : "");
if (add_cr)
len += snprintf(buf + len, max(buf_size - len, 0), "\n");
return len;
}
#define INPUT_DEV_CAP_ATTR(ev, bm) \ #define INPUT_DEV_CAP_ATTR(ev, bm) \
static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf) \ static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf) \
{ \ { \
struct input_dev *input_dev = to_input_dev(dev); \ struct input_dev *input_dev = to_input_dev(dev); \
return input_print_bitmap(buf, PAGE_SIZE, input_dev->bm##bit, ev##_MAX);\ int len = input_print_bitmap(buf, PAGE_SIZE, \
input_dev->bm##bit, ev##_MAX, 1); \
return min_t(int, len, PAGE_SIZE); \
} \ } \
static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL); static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL);
...@@ -678,12 +748,36 @@ static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index, ...@@ -678,12 +748,36 @@ static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
envp[*cur_index] = buffer + *cur_len; envp[*cur_index] = buffer + *cur_len;
*cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name); *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name);
if (*cur_len > buffer_size) if (*cur_len >= buffer_size)
return -ENOMEM; return -ENOMEM;
*cur_len += input_print_bitmap(buffer + *cur_len, *cur_len += input_print_bitmap(buffer + *cur_len,
max(buffer_size - *cur_len, 0), max(buffer_size - *cur_len, 0),
bitmap, max) + 1; bitmap, max, 0) + 1;
if (*cur_len > buffer_size)
return -ENOMEM;
(*cur_index)++;
return 0;
}
static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_index,
char *buffer, int buffer_size, int *cur_len,
struct input_dev *dev)
{
if (*cur_index >= num_envp - 1)
return -ENOMEM;
envp[*cur_index] = buffer + *cur_len;
*cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0),
"MODALIAS=");
if (*cur_len >= buffer_size)
return -ENOMEM;
*cur_len += input_print_modalias(buffer + *cur_len,
max(buffer_size - *cur_len, 0),
dev, 0) + 1;
if (*cur_len > buffer_size) if (*cur_len > buffer_size)
return -ENOMEM; return -ENOMEM;
...@@ -709,6 +803,16 @@ static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index, ...@@ -709,6 +803,16 @@ static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
return err; \ return err; \
} while (0) } while (0)
#define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev) \
do { \
int err = input_add_uevent_modalias_var(envp, \
num_envp, &i, \
buffer, buffer_size, &len, \
dev); \
if (err) \
return err; \
} while (0)
static int input_dev_uevent(struct class_device *cdev, char **envp, static int input_dev_uevent(struct class_device *cdev, char **envp,
int num_envp, char *buffer, int buffer_size) int num_envp, char *buffer, int buffer_size)
{ {
...@@ -744,9 +848,7 @@ static int input_dev_uevent(struct class_device *cdev, char **envp, ...@@ -744,9 +848,7 @@ static int input_dev_uevent(struct class_device *cdev, char **envp,
if (test_bit(EV_SW, dev->evbit)) if (test_bit(EV_SW, dev->evbit))
INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX); INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX);
envp[i++] = buffer + len; INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev);
len += snprintf(buffer + len, buffer_size - len, "MODALIAS=");
len += print_modalias(buffer + len, buffer_size - len, dev) + 1;
envp[i] = NULL; envp[i] = NULL;
return 0; return 0;
...@@ -790,7 +892,7 @@ int input_register_device(struct input_dev *dev) ...@@ -790,7 +892,7 @@ int input_register_device(struct input_dev *dev)
return -EINVAL; return -EINVAL;
} }
init_MUTEX(&dev->sem); mutex_init(&dev->mutex);
set_bit(EV_SYN, dev->evbit); set_bit(EV_SYN, dev->evbit);
/* /*
......
...@@ -171,9 +171,8 @@ static int joydev_open(struct inode *inode, struct file *file) ...@@ -171,9 +171,8 @@ static int joydev_open(struct inode *inode, struct file *file)
if (i >= JOYDEV_MINORS || !joydev_table[i]) if (i >= JOYDEV_MINORS || !joydev_table[i])
return -ENODEV; return -ENODEV;
if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL))) if (!(list = kzalloc(sizeof(struct joydev_list), GFP_KERNEL)))
return -ENOMEM; return -ENOMEM;
memset(list, 0, sizeof(struct joydev_list));
list->joydev = joydev_table[i]; list->joydev = joydev_table[i];
list_add_tail(&list->node, &joydev_table[i]->list); list_add_tail(&list->node, &joydev_table[i]->list);
...@@ -457,9 +456,8 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct ...@@ -457,9 +456,8 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
return NULL; return NULL;
} }
if (!(joydev = kmalloc(sizeof(struct joydev), GFP_KERNEL))) if (!(joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL)))
return NULL; return NULL;
memset(joydev, 0, sizeof(struct joydev));
INIT_LIST_HEAD(&joydev->list); INIT_LIST_HEAD(&joydev->list);
init_waitqueue_head(&joydev->wait); init_waitqueue_head(&joydev->wait);
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/mutex.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/amigahw.h> #include <asm/amigahw.h>
...@@ -52,7 +53,7 @@ MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is ...@@ -52,7 +53,7 @@ MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is
__obsolete_setup("amijoy="); __obsolete_setup("amijoy=");
static int amijoy_used; static int amijoy_used;
static DECLARE_MUTEX(amijoy_sem); static DEFINE_MUTEX(amijoy_mutex);
static struct input_dev *amijoy_dev[2]; static struct input_dev *amijoy_dev[2];
static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" }; static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" };
...@@ -85,7 +86,7 @@ static int amijoy_open(struct input_dev *dev) ...@@ -85,7 +86,7 @@ static int amijoy_open(struct input_dev *dev)
{ {
int err; int err;
err = down_interruptible(&amijoy_sem); err = mutex_lock_interruptible(&amijoy_mutex);
if (err) if (err)
return err; return err;
...@@ -97,16 +98,16 @@ static int amijoy_open(struct input_dev *dev) ...@@ -97,16 +98,16 @@ static int amijoy_open(struct input_dev *dev)
amijoy_used++; amijoy_used++;
out: out:
up(&amijoy_sem); mutex_unlock(&amijoy_mutex);
return err; return err;
} }
static void amijoy_close(struct input_dev *dev) static void amijoy_close(struct input_dev *dev)
{ {
down(&amijoy_sem); mutex_lock(&amijoy_mutex);
if (!--amijoy_used) if (!--amijoy_used)
free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt); free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt);
up(&amijoy_sem); mutex_unlock(&amijoy_mutex);
} }
static int __init amijoy_init(void) static int __init amijoy_init(void)
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/parport.h> #include <linux/parport.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/mutex.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver"); MODULE_DESCRIPTION("Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver");
...@@ -111,7 +112,7 @@ struct db9 { ...@@ -111,7 +112,7 @@ struct db9 {
struct pardevice *pd; struct pardevice *pd;
int mode; int mode;
int used; int used;
struct semaphore sem; struct mutex mutex;
char phys[DB9_MAX_DEVICES][32]; char phys[DB9_MAX_DEVICES][32];
}; };
...@@ -525,7 +526,7 @@ static int db9_open(struct input_dev *dev) ...@@ -525,7 +526,7 @@ static int db9_open(struct input_dev *dev)
struct parport *port = db9->pd->port; struct parport *port = db9->pd->port;
int err; int err;
err = down_interruptible(&db9->sem); err = mutex_lock_interruptible(&db9->mutex);
if (err) if (err)
return err; return err;
...@@ -539,7 +540,7 @@ static int db9_open(struct input_dev *dev) ...@@ -539,7 +540,7 @@ static int db9_open(struct input_dev *dev)
mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME); mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
} }
up(&db9->sem); mutex_unlock(&db9->mutex);
return 0; return 0;
} }
...@@ -548,14 +549,14 @@ static void db9_close(struct input_dev *dev) ...@@ -548,14 +549,14 @@ static void db9_close(struct input_dev *dev)
struct db9 *db9 = dev->private; struct db9 *db9 = dev->private;
struct parport *port = db9->pd->port; struct parport *port = db9->pd->port;
down(&db9->sem); mutex_lock(&db9->mutex);
if (!--db9->used) { if (!--db9->used) {
del_timer_sync(&db9->timer); del_timer_sync(&db9->timer);
parport_write_control(port, 0x00); parport_write_control(port, 0x00);
parport_data_forward(port); parport_data_forward(port);
parport_release(db9->pd); parport_release(db9->pd);
} }
up(&db9->sem); mutex_unlock(&db9->mutex);
} }
static struct db9 __init *db9_probe(int parport, int mode) static struct db9 __init *db9_probe(int parport, int mode)
...@@ -603,7 +604,7 @@ static struct db9 __init *db9_probe(int parport, int mode) ...@@ -603,7 +604,7 @@ static struct db9 __init *db9_probe(int parport, int mode)
goto err_unreg_pardev; goto err_unreg_pardev;
} }
init_MUTEX(&db9->sem); mutex_init(&db9->mutex);
db9->pd = pd; db9->pd = pd;
db9->mode = mode; db9->mode = mode;
init_timer(&db9->timer); init_timer(&db9->timer);
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* Based on the work of: * Based on the work of:
* Andree Borrmann John Dahlstrom * Andree Borrmann John Dahlstrom
* David Kuder Nathan Hand * David Kuder Nathan Hand
* Raphael Assenat
*/ */
/* /*
...@@ -36,6 +37,7 @@ ...@@ -36,6 +37,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/parport.h> #include <linux/parport.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/mutex.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver"); MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver");
...@@ -72,8 +74,9 @@ __obsolete_setup("gc_3="); ...@@ -72,8 +74,9 @@ __obsolete_setup("gc_3=");
#define GC_N64 6 #define GC_N64 6
#define GC_PSX 7 #define GC_PSX 7
#define GC_DDR 8 #define GC_DDR 8
#define GC_SNESMOUSE 9
#define GC_MAX 8 #define GC_MAX 9
#define GC_REFRESH_TIME HZ/100 #define GC_REFRESH_TIME HZ/100
...@@ -83,7 +86,7 @@ struct gc { ...@@ -83,7 +86,7 @@ struct gc {
struct timer_list timer; struct timer_list timer;
unsigned char pads[GC_MAX + 1]; unsigned char pads[GC_MAX + 1];
int used; int used;
struct semaphore sem; struct mutex mutex;
char phys[GC_MAX_DEVICES][32]; char phys[GC_MAX_DEVICES][32];
}; };
...@@ -93,7 +96,7 @@ static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 }; ...@@ -93,7 +96,7 @@ static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 };
static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick", 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" }; "PSX DDR controller", "SNES mouse" };
/* /*
* N64 support. * N64 support.
*/ */
...@@ -207,7 +210,10 @@ static void gc_n64_process_packet(struct gc *gc) ...@@ -207,7 +210,10 @@ static void gc_n64_process_packet(struct gc *gc)
#define GC_NES_DELAY 6 /* Delay between bits - 6us */ #define GC_NES_DELAY 6 /* Delay between bits - 6us */
#define GC_NES_LENGTH 8 /* The NES pads use 8 bits of data */ #define GC_NES_LENGTH 8 /* The NES pads use 8 bits of data */
#define GC_SNES_LENGTH 12 /* The SNES true length is 16, but the last 4 bits are unused */ #define GC_SNES_LENGTH 12 /* The SNES true length is 16, but the
last 4 bits are unused */
#define GC_SNESMOUSE_LENGTH 32 /* The SNES mouse uses 32 bits, the first
16 bits are equivalent to a gamepad */
#define GC_NES_POWER 0xfc #define GC_NES_POWER 0xfc
#define GC_NES_CLOCK 0x01 #define GC_NES_CLOCK 0x01
...@@ -242,11 +248,15 @@ static void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data) ...@@ -242,11 +248,15 @@ static void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data)
static void gc_nes_process_packet(struct gc *gc) static void gc_nes_process_packet(struct gc *gc)
{ {
unsigned char data[GC_SNES_LENGTH]; unsigned char data[GC_SNESMOUSE_LENGTH];
struct input_dev *dev; struct input_dev *dev;
int i, j, s; int i, j, s, len;
char x_rel, y_rel;
len = gc->pads[GC_SNESMOUSE] ? GC_SNESMOUSE_LENGTH :
(gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH);
gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data); gc_nes_read_packet(gc, len, data);
for (i = 0; i < GC_MAX_DEVICES; i++) { for (i = 0; i < GC_MAX_DEVICES; i++) {
...@@ -269,6 +279,44 @@ static void gc_nes_process_packet(struct gc *gc) ...@@ -269,6 +279,44 @@ static void gc_nes_process_packet(struct gc *gc)
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
input_report_key(dev, gc_snes_btn[j], s & data[gc_snes_bytes[j]]); input_report_key(dev, gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
if (s & gc->pads[GC_SNESMOUSE]) {
/*
* The 4 unused bits from SNES controllers appear to be ID bits
* so use them to make sure iwe are dealing with a mouse.
* gamepad is connected. This is important since
* my SNES gamepad sends 1's for bits 16-31, which
* cause the mouse pointer to quickly move to the
* upper left corner of the screen.
*/
if (!(s & data[12]) && !(s & data[13]) &&
!(s & data[14]) && (s & data[15])) {
input_report_key(dev, BTN_LEFT, s & data[9]);
input_report_key(dev, BTN_RIGHT, s & data[8]);
x_rel = y_rel = 0;
for (j = 0; j < 7; j++) {
x_rel <<= 1;
if (data[25 + j] & s)
x_rel |= 1;
y_rel <<= 1;
if (data[17 + j] & s)
y_rel |= 1;
}
if (x_rel) {
if (data[24] & s)
x_rel = -x_rel;
input_report_rel(dev, REL_X, x_rel);
}
if (y_rel) {
if (data[16] & s)
y_rel = -y_rel;
input_report_rel(dev, REL_Y, y_rel);
}
}
}
input_sync(dev); input_sync(dev);
} }
} }
...@@ -524,10 +572,10 @@ static void gc_timer(unsigned long private) ...@@ -524,10 +572,10 @@ static void gc_timer(unsigned long private)
gc_n64_process_packet(gc); gc_n64_process_packet(gc);
/* /*
* NES and SNES pads * NES and SNES pads or mouse
*/ */
if (gc->pads[GC_NES] || gc->pads[GC_SNES]) if (gc->pads[GC_NES] || gc->pads[GC_SNES] || gc->pads[GC_SNESMOUSE])
gc_nes_process_packet(gc); gc_nes_process_packet(gc);
/* /*
...@@ -552,7 +600,7 @@ static int gc_open(struct input_dev *dev) ...@@ -552,7 +600,7 @@ static int gc_open(struct input_dev *dev)
struct gc *gc = dev->private; struct gc *gc = dev->private;
int err; int err;
err = down_interruptible(&gc->sem); err = mutex_lock_interruptible(&gc->mutex);
if (err) if (err)
return err; return err;
...@@ -562,7 +610,7 @@ static int gc_open(struct input_dev *dev) ...@@ -562,7 +610,7 @@ static int gc_open(struct input_dev *dev)
mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
} }
up(&gc->sem); mutex_unlock(&gc->mutex);
return 0; return 0;
} }
...@@ -570,13 +618,13 @@ static void gc_close(struct input_dev *dev) ...@@ -570,13 +618,13 @@ static void gc_close(struct input_dev *dev)
{ {
struct gc *gc = dev->private; struct gc *gc = dev->private;
down(&gc->sem); mutex_lock(&gc->mutex);
if (!--gc->used) { if (!--gc->used) {
del_timer_sync(&gc->timer); del_timer_sync(&gc->timer);
parport_write_control(gc->pd->port, 0x00); parport_write_control(gc->pd->port, 0x00);
parport_release(gc->pd); parport_release(gc->pd);
} }
up(&gc->sem); mutex_unlock(&gc->mutex);
} }
static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
...@@ -609,10 +657,13 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) ...@@ -609,10 +657,13 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
input_dev->open = gc_open; input_dev->open = gc_open;
input_dev->close = gc_close; input_dev->close = gc_close;
if (pad_type != GC_SNESMOUSE) {
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0); input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0);
} else
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
gc->pads[0] |= gc_status_bit[idx]; gc->pads[0] |= gc_status_bit[idx];
gc->pads[pad_type] |= gc_status_bit[idx]; gc->pads[pad_type] |= gc_status_bit[idx];
...@@ -630,6 +681,13 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) ...@@ -630,6 +681,13 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
break; break;
case GC_SNESMOUSE:
set_bit(BTN_LEFT, input_dev->keybit);
set_bit(BTN_RIGHT, input_dev->keybit);
set_bit(REL_X, input_dev->relbit);
set_bit(REL_Y, input_dev->relbit);
break;
case GC_SNES: case GC_SNES:
for (i = 4; i < 8; i++) for (i = 4; i < 8; i++)
set_bit(gc_snes_btn[i], input_dev->keybit); set_bit(gc_snes_btn[i], input_dev->keybit);
...@@ -693,7 +751,7 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) ...@@ -693,7 +751,7 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
goto err_unreg_pardev; goto err_unreg_pardev;
} }
init_MUTEX(&gc->sem); mutex_init(&gc->mutex);
gc->pd = pd; gc->pd = pd;
init_timer(&gc->timer); init_timer(&gc->timer);
gc->timer.data = (long) gc; gc->timer.data = (long) gc;
......
...@@ -42,14 +42,14 @@ static int make_magnitude_modifier(struct iforce* iforce, ...@@ -42,14 +42,14 @@ static int make_magnitude_modifier(struct iforce* iforce,
unsigned char data[3]; unsigned char data[3];
if (!no_alloc) { if (!no_alloc) {
down(&iforce->mem_mutex); mutex_lock(&iforce->mem_mutex);
if (allocate_resource(&(iforce->device_memory), mod_chunk, 2, if (allocate_resource(&(iforce->device_memory), mod_chunk, 2,
iforce->device_memory.start, iforce->device_memory.end, 2L, iforce->device_memory.start, iforce->device_memory.end, 2L,
NULL, NULL)) { NULL, NULL)) {
up(&iforce->mem_mutex); mutex_unlock(&iforce->mem_mutex);
return -ENOMEM; return -ENOMEM;
} }
up(&iforce->mem_mutex); mutex_unlock(&iforce->mem_mutex);
} }
data[0] = LO(mod_chunk->start); data[0] = LO(mod_chunk->start);
...@@ -75,14 +75,14 @@ static int make_period_modifier(struct iforce* iforce, ...@@ -75,14 +75,14 @@ static int make_period_modifier(struct iforce* iforce,
period = TIME_SCALE(period); period = TIME_SCALE(period);
if (!no_alloc) { if (!no_alloc) {
down(&iforce->mem_mutex); mutex_lock(&iforce->mem_mutex);
if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0c, if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0c,
iforce->device_memory.start, iforce->device_memory.end, 2L, iforce->device_memory.start, iforce->device_memory.end, 2L,
NULL, NULL)) { NULL, NULL)) {
up(&iforce->mem_mutex); mutex_unlock(&iforce->mem_mutex);
return -ENOMEM; return -ENOMEM;
} }
up(&iforce->mem_mutex); mutex_unlock(&iforce->mem_mutex);
} }
data[0] = LO(mod_chunk->start); data[0] = LO(mod_chunk->start);
...@@ -115,14 +115,14 @@ static int make_envelope_modifier(struct iforce* iforce, ...@@ -115,14 +115,14 @@ static int make_envelope_modifier(struct iforce* iforce,
fade_duration = TIME_SCALE(fade_duration); fade_duration = TIME_SCALE(fade_duration);
if (!no_alloc) { if (!no_alloc) {
down(&iforce->mem_mutex); mutex_lock(&iforce->mem_mutex);
if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0e, if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0e,
iforce->device_memory.start, iforce->device_memory.end, 2L, iforce->device_memory.start, iforce->device_memory.end, 2L,
NULL, NULL)) { NULL, NULL)) {
up(&iforce->mem_mutex); mutex_unlock(&iforce->mem_mutex);
return -ENOMEM; return -ENOMEM;
} }
up(&iforce->mem_mutex); mutex_unlock(&iforce->mem_mutex);
} }
data[0] = LO(mod_chunk->start); data[0] = LO(mod_chunk->start);
...@@ -152,14 +152,14 @@ static int make_condition_modifier(struct iforce* iforce, ...@@ -152,14 +152,14 @@ static int make_condition_modifier(struct iforce* iforce,
unsigned char data[10]; unsigned char data[10];
if (!no_alloc) { if (!no_alloc) {
down(&iforce->mem_mutex); mutex_lock(&iforce->mem_mutex);
if (allocate_resource(&(iforce->device_memory), mod_chunk, 8, if (allocate_resource(&(iforce->device_memory), mod_chunk, 8,
iforce->device_memory.start, iforce->device_memory.end, 2L, iforce->device_memory.start, iforce->device_memory.end, 2L,
NULL, NULL)) { NULL, NULL)) {
up(&iforce->mem_mutex); mutex_unlock(&iforce->mem_mutex);
return -ENOMEM; return -ENOMEM;
} }
up(&iforce->mem_mutex); mutex_unlock(&iforce->mem_mutex);
} }
data[0] = LO(mod_chunk->start); data[0] = LO(mod_chunk->start);
......
...@@ -350,7 +350,7 @@ int iforce_init_device(struct iforce *iforce) ...@@ -350,7 +350,7 @@ int iforce_init_device(struct iforce *iforce)
init_waitqueue_head(&iforce->wait); init_waitqueue_head(&iforce->wait);
spin_lock_init(&iforce->xmit_lock); spin_lock_init(&iforce->xmit_lock);
init_MUTEX(&iforce->mem_mutex); mutex_init(&iforce->mem_mutex);
iforce->xmit.buf = iforce->xmit_data; iforce->xmit.buf = iforce->xmit_data;
iforce->dev = input_dev; iforce->dev = input_dev;
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#include <linux/serio.h> #include <linux/serio.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/circ_buf.h> #include <linux/circ_buf.h>
#include <asm/semaphore.h> #include <linux/mutex.h>
/* This module provides arbitrary resource management routines. /* This module provides arbitrary resource management routines.
* I use it to manage the device's memory. * I use it to manage the device's memory.
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
*/ */
#include <linux/ioport.h> #include <linux/ioport.h>
#define IFORCE_MAX_LENGTH 16 #define IFORCE_MAX_LENGTH 16
/* iforce::bus */ /* iforce::bus */
...@@ -146,7 +147,7 @@ struct iforce { ...@@ -146,7 +147,7 @@ struct iforce {
wait_queue_head_t wait; wait_queue_head_t wait;
struct resource device_memory; struct resource device_memory;
struct iforce_core_effect core_effects[FF_EFFECTS_MAX]; struct iforce_core_effect core_effects[FF_EFFECTS_MAX];
struct semaphore mem_mutex; struct mutex mem_mutex;
}; };
/* Get hi and low bytes of a 16-bits int */ /* Get hi and low bytes of a 16-bits int */
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/mutex.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("TurboGraFX parallel port interface driver"); MODULE_DESCRIPTION("TurboGraFX parallel port interface driver");
...@@ -86,7 +87,7 @@ static struct tgfx { ...@@ -86,7 +87,7 @@ static struct tgfx {
char phys[TGFX_MAX_DEVICES][32]; char phys[TGFX_MAX_DEVICES][32];
int sticks; int sticks;
int used; int used;
struct semaphore sem; struct mutex sem;
} *tgfx_base[TGFX_MAX_PORTS]; } *tgfx_base[TGFX_MAX_PORTS];
/* /*
...@@ -128,7 +129,7 @@ static int tgfx_open(struct input_dev *dev) ...@@ -128,7 +129,7 @@ static int tgfx_open(struct input_dev *dev)
struct tgfx *tgfx = dev->private; struct tgfx *tgfx = dev->private;
int err; int err;
err = down_interruptible(&tgfx->sem); err = mutex_lock_interruptible(&tgfx->sem);
if (err) if (err)
return err; return err;
...@@ -138,7 +139,7 @@ static int tgfx_open(struct input_dev *dev) ...@@ -138,7 +139,7 @@ static int tgfx_open(struct input_dev *dev)
mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME); mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME);
} }
up(&tgfx->sem); mutex_unlock(&tgfx->sem);
return 0; return 0;
} }
...@@ -146,13 +147,13 @@ static void tgfx_close(struct input_dev *dev) ...@@ -146,13 +147,13 @@ static void tgfx_close(struct input_dev *dev)
{ {
struct tgfx *tgfx = dev->private; struct tgfx *tgfx = dev->private;
down(&tgfx->sem); mutex_lock(&tgfx->sem);
if (!--tgfx->used) { if (!--tgfx->used) {
del_timer_sync(&tgfx->timer); del_timer_sync(&tgfx->timer);
parport_write_control(tgfx->pd->port, 0x00); parport_write_control(tgfx->pd->port, 0x00);
parport_release(tgfx->pd); parport_release(tgfx->pd);
} }
up(&tgfx->sem); mutex_unlock(&tgfx->sem);
} }
...@@ -191,7 +192,7 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) ...@@ -191,7 +192,7 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
goto err_unreg_pardev; goto err_unreg_pardev;
} }
init_MUTEX(&tgfx->sem); mutex_init(&tgfx->sem);
tgfx->pd = pd; tgfx->pd = pd;
init_timer(&tgfx->timer); init_timer(&tgfx->timer);
tgfx->timer.data = (long) tgfx; tgfx->timer.data = (long) tgfx;
......
...@@ -13,7 +13,7 @@ menuconfig INPUT_KEYBOARD ...@@ -13,7 +13,7 @@ menuconfig INPUT_KEYBOARD
if INPUT_KEYBOARD if INPUT_KEYBOARD
config KEYBOARD_ATKBD config KEYBOARD_ATKBD
tristate "AT keyboard" if !X86_PC tristate "AT keyboard" if EMBEDDED || !X86_PC
default y default y
select SERIO select SERIO
select SERIO_LIBPS2 select SERIO_LIBPS2
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/serio.h> #include <linux/serio.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/libps2.h> #include <linux/libps2.h>
#include <linux/mutex.h>
#define DRIVER_DESC "AT and PS/2 keyboard driver" #define DRIVER_DESC "AT and PS/2 keyboard driver"
...@@ -216,7 +217,7 @@ struct atkbd { ...@@ -216,7 +217,7 @@ struct atkbd {
unsigned long time; unsigned long time;
struct work_struct event_work; struct work_struct event_work;
struct semaphore event_sem; struct mutex event_mutex;
unsigned long event_mask; unsigned long event_mask;
}; };
...@@ -302,19 +303,19 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, ...@@ -302,19 +303,19 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
if (atkbd->translated) { if (atkbd->translated) {
if (atkbd->emul || if (atkbd->emul ||
!(code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 || (code != ATKBD_RET_EMUL0 && code != ATKBD_RET_EMUL1 &&
code == ATKBD_RET_HANGUEL || code == ATKBD_RET_HANJA || code != ATKBD_RET_HANGUEL && code != ATKBD_RET_HANJA &&
(code == ATKBD_RET_ERR && !atkbd->err_xl) || (code != ATKBD_RET_ERR || atkbd->err_xl) &&
(code == ATKBD_RET_BAT && !atkbd->bat_xl))) { (code != ATKBD_RET_BAT || atkbd->bat_xl))) {
atkbd->release = code >> 7; atkbd->release = code >> 7;
code &= 0x7f; code &= 0x7f;
} }
if (!atkbd->emul) { if (!atkbd->emul) {
if ((code & 0x7f) == (ATKBD_RET_BAT & 0x7f)) if ((code & 0x7f) == (ATKBD_RET_BAT & 0x7f))
atkbd->bat_xl = !atkbd->release; atkbd->bat_xl = !(data >> 7);
if ((code & 0x7f) == (ATKBD_RET_ERR & 0x7f)) if ((code & 0x7f) == (ATKBD_RET_ERR & 0x7f))
atkbd->err_xl = !atkbd->release; atkbd->err_xl = !(data >> 7);
} }
} }
...@@ -449,7 +450,7 @@ static void atkbd_event_work(void *data) ...@@ -449,7 +450,7 @@ static void atkbd_event_work(void *data)
unsigned char param[2]; unsigned char param[2];
int i, j; int i, j;
down(&atkbd->event_sem); mutex_lock(&atkbd->event_mutex);
if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask)) { if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask)) {
param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0) param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
...@@ -480,7 +481,7 @@ static void atkbd_event_work(void *data) ...@@ -480,7 +481,7 @@ static void atkbd_event_work(void *data)
ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP); ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP);
} }
up(&atkbd->event_sem); mutex_unlock(&atkbd->event_mutex);
} }
/* /*
...@@ -846,7 +847,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) ...@@ -846,7 +847,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd->dev = dev; atkbd->dev = dev;
ps2_init(&atkbd->ps2dev, serio); ps2_init(&atkbd->ps2dev, serio);
INIT_WORK(&atkbd->event_work, atkbd_event_work, atkbd); INIT_WORK(&atkbd->event_work, atkbd_event_work, atkbd);
init_MUTEX(&atkbd->event_sem); mutex_init(&atkbd->event_mutex);
switch (serio->id.type) { switch (serio->id.type) {
...@@ -862,9 +863,6 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) ...@@ -862,9 +863,6 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd->softrepeat = atkbd_softrepeat; atkbd->softrepeat = atkbd_softrepeat;
atkbd->scroll = atkbd_scroll; atkbd->scroll = atkbd_scroll;
if (!atkbd->write)
atkbd->softrepeat = 1;
if (atkbd->softrepeat) if (atkbd->softrepeat)
atkbd->softraw = 1; atkbd->softraw = 1;
......
...@@ -29,11 +29,11 @@ ...@@ -29,11 +29,11 @@
#define KB_COLS 12 #define KB_COLS 12
#define KB_ROWMASK(r) (1 << (r)) #define KB_ROWMASK(r) (1 << (r))
#define SCANCODE(r,c) ( ((r)<<4) + (c) + 1 ) #define SCANCODE(r,c) ( ((r)<<4) + (c) + 1 )
/* zero code, 124 scancodes + 3 hinge combinations */ /* zero code, 124 scancodes */
#define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 +3 ) #define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 )
#define SCAN_INTERVAL (HZ/10)
#define HINGE_SCAN_INTERVAL (HZ/4) #define SCAN_INTERVAL (50) /* ms */
#define HINGE_SCAN_INTERVAL (250) /* ms */
#define CORGI_KEY_CALENDER KEY_F1 #define CORGI_KEY_CALENDER KEY_F1
#define CORGI_KEY_ADDRESS KEY_F2 #define CORGI_KEY_ADDRESS KEY_F2
...@@ -49,9 +49,6 @@ ...@@ -49,9 +49,6 @@
#define CORGI_KEY_MAIL KEY_F10 #define CORGI_KEY_MAIL KEY_F10
#define CORGI_KEY_OK KEY_F11 #define CORGI_KEY_OK KEY_F11
#define CORGI_KEY_MENU KEY_F12 #define CORGI_KEY_MENU KEY_F12
#define CORGI_HINGE_0 KEY_KP0
#define CORGI_HINGE_1 KEY_KP1
#define CORGI_HINGE_2 KEY_KP2
static unsigned char corgikbd_keycode[NR_SCANCODES] = { static unsigned char corgikbd_keycode[NR_SCANCODES] = {
0, /* 0 */ 0, /* 0 */
...@@ -63,7 +60,6 @@ static unsigned char corgikbd_keycode[NR_SCANCODES] = { ...@@ -63,7 +60,6 @@ static unsigned char corgikbd_keycode[NR_SCANCODES] = {
CORGI_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */ CORGI_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */
KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, CORGI_KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */ KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, CORGI_KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */
CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */ CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */
CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2 /* 125-127 */
}; };
...@@ -187,7 +183,7 @@ static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs ...@@ -187,7 +183,7 @@ static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs
/* if any keys are pressed, enable the timer */ /* if any keys are pressed, enable the timer */
if (num_pressed) if (num_pressed)
mod_timer(&corgikbd_data->timer, jiffies + SCAN_INTERVAL); mod_timer(&corgikbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL));
spin_unlock_irqrestore(&corgikbd_data->lock, flags); spin_unlock_irqrestore(&corgikbd_data->lock, flags);
} }
...@@ -228,6 +224,7 @@ static void corgikbd_timer_callback(unsigned long data) ...@@ -228,6 +224,7 @@ static void corgikbd_timer_callback(unsigned long data)
* 0x0c - Keyboard and Screen Closed * 0x0c - Keyboard and Screen Closed
*/ */
#define READ_GPIO_BIT(x) (GPLR(x) & GPIO_bit(x))
#define HINGE_STABLE_COUNT 2 #define HINGE_STABLE_COUNT 2
static int sharpsl_hinge_state; static int sharpsl_hinge_state;
static int hinge_count; static int hinge_count;
...@@ -239,6 +236,7 @@ static void corgikbd_hinge_timer(unsigned long data) ...@@ -239,6 +236,7 @@ static void corgikbd_hinge_timer(unsigned long data)
unsigned long flags; unsigned long flags;
gprr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB); gprr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB);
gprr |= (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0);
if (gprr != sharpsl_hinge_state) { if (gprr != sharpsl_hinge_state) {
hinge_count = 0; hinge_count = 0;
sharpsl_hinge_state = gprr; sharpsl_hinge_state = gprr;
...@@ -249,27 +247,38 @@ static void corgikbd_hinge_timer(unsigned long data) ...@@ -249,27 +247,38 @@ static void corgikbd_hinge_timer(unsigned long data)
input_report_switch(corgikbd_data->input, SW_0, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0)); input_report_switch(corgikbd_data->input, SW_0, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0));
input_report_switch(corgikbd_data->input, SW_1, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0)); input_report_switch(corgikbd_data->input, SW_1, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0));
input_report_switch(corgikbd_data->input, SW_2, (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0));
input_sync(corgikbd_data->input); input_sync(corgikbd_data->input);
spin_unlock_irqrestore(&corgikbd_data->lock, flags); spin_unlock_irqrestore(&corgikbd_data->lock, flags);
} }
} }
mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL); mod_timer(&corgikbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int corgikbd_suspend(struct platform_device *dev, pm_message_t state) static int corgikbd_suspend(struct platform_device *dev, pm_message_t state)
{ {
int i;
struct corgikbd *corgikbd = platform_get_drvdata(dev); struct corgikbd *corgikbd = platform_get_drvdata(dev);
corgikbd->suspended = 1; corgikbd->suspended = 1;
/* strobe 0 is the power key so this can't be made an input for
powersaving therefore i = 1 */
for (i = 1; i < CORGI_KEY_STROBE_NUM; i++)
pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_IN);
return 0; return 0;
} }
static int corgikbd_resume(struct platform_device *dev) static int corgikbd_resume(struct platform_device *dev)
{ {
int i;
struct corgikbd *corgikbd = platform_get_drvdata(dev); struct corgikbd *corgikbd = platform_get_drvdata(dev);
for (i = 1; i < CORGI_KEY_STROBE_NUM; i++)
pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);
/* Upon resume, ignore the suspend key for a short while */ /* Upon resume, ignore the suspend key for a short while */
corgikbd->suspend_jiffies=jiffies; corgikbd->suspend_jiffies=jiffies;
corgikbd->suspended = 0; corgikbd->suspended = 0;
...@@ -333,10 +342,11 @@ static int __init corgikbd_probe(struct platform_device *pdev) ...@@ -333,10 +342,11 @@ static int __init corgikbd_probe(struct platform_device *pdev)
clear_bit(0, input_dev->keybit); clear_bit(0, input_dev->keybit);
set_bit(SW_0, input_dev->swbit); set_bit(SW_0, input_dev->swbit);
set_bit(SW_1, input_dev->swbit); set_bit(SW_1, input_dev->swbit);
set_bit(SW_2, input_dev->swbit);
input_register_device(corgikbd->input); input_register_device(corgikbd->input);
mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL); mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
/* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) { for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) {
...@@ -351,6 +361,9 @@ static int __init corgikbd_probe(struct platform_device *pdev) ...@@ -351,6 +361,9 @@ static int __init corgikbd_probe(struct platform_device *pdev)
for (i = 0; i < CORGI_KEY_STROBE_NUM; i++) for (i = 0; i < CORGI_KEY_STROBE_NUM; i++)
pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH); pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);
/* Setup the headphone jack as an input */
pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN);
return 0; return 0;
} }
......
...@@ -256,10 +256,13 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv) ...@@ -256,10 +256,13 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
return -ENOMEM; return -ENOMEM;
kbd->dev = input_allocate_device(); kbd->dev = input_allocate_device();
if (!kbd->dev) goto bail1; if (!kbd->dev)
goto bail0;
kbd->dev->private = kbd; kbd->dev->private = kbd;
if (serio_open(serio, drv)) goto bail0; if (serio_open(serio, drv))
goto bail1;
serio_set_drvdata(serio, kbd); serio_set_drvdata(serio, kbd);
kbd->serio = serio; kbd->serio = serio;
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#define SCANCODE(r,c) (((r)<<4) + (c) + 1) #define SCANCODE(r,c) (((r)<<4) + (c) + 1)
#define NR_SCANCODES ((KB_ROWS<<4) + 1) #define NR_SCANCODES ((KB_ROWS<<4) + 1)
#define SCAN_INTERVAL (50) /* ms */
#define HINGE_SCAN_INTERVAL (150) /* ms */ #define HINGE_SCAN_INTERVAL (150) /* ms */
#define SPITZ_KEY_CALENDER KEY_F1 #define SPITZ_KEY_CALENDER KEY_F1
...@@ -230,7 +231,7 @@ static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data, struct pt_regs ...@@ -230,7 +231,7 @@ static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data, struct pt_regs
/* if any keys are pressed, enable the timer */ /* if any keys are pressed, enable the timer */
if (num_pressed) if (num_pressed)
mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(100)); mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL));
spin_unlock_irqrestore(&spitzkbd_data->lock, flags); spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
} }
...@@ -287,6 +288,7 @@ static void spitzkbd_hinge_timer(unsigned long data) ...@@ -287,6 +288,7 @@ static void spitzkbd_hinge_timer(unsigned long data)
unsigned long flags; unsigned long flags;
state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB)); state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB));
state |= (GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT));
if (state != sharpsl_hinge_state) { if (state != sharpsl_hinge_state) {
hinge_count = 0; hinge_count = 0;
sharpsl_hinge_state = state; sharpsl_hinge_state = state;
...@@ -299,6 +301,7 @@ static void spitzkbd_hinge_timer(unsigned long data) ...@@ -299,6 +301,7 @@ static void spitzkbd_hinge_timer(unsigned long data)
input_report_switch(spitzkbd_data->input, SW_0, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0)); input_report_switch(spitzkbd_data->input, SW_0, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0));
input_report_switch(spitzkbd_data->input, SW_1, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0)); input_report_switch(spitzkbd_data->input, SW_1, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0));
input_report_switch(spitzkbd_data->input, SW_2, ((GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)) != 0));
input_sync(spitzkbd_data->input); input_sync(spitzkbd_data->input);
spin_unlock_irqrestore(&spitzkbd_data->lock, flags); spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
...@@ -397,6 +400,7 @@ static int __init spitzkbd_probe(struct platform_device *dev) ...@@ -397,6 +400,7 @@ static int __init spitzkbd_probe(struct platform_device *dev)
clear_bit(0, input_dev->keybit); clear_bit(0, input_dev->keybit);
set_bit(SW_0, input_dev->swbit); set_bit(SW_0, input_dev->swbit);
set_bit(SW_1, input_dev->swbit); set_bit(SW_1, input_dev->swbit);
set_bit(SW_2, input_dev->swbit);
input_register_device(input_dev); input_register_device(input_dev);
...@@ -432,6 +436,9 @@ static int __init spitzkbd_probe(struct platform_device *dev) ...@@ -432,6 +436,9 @@ static int __init spitzkbd_probe(struct platform_device *dev)
request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr,
SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING,
"Spitzkbd SWB", spitzkbd); "Spitzkbd SWB", spitzkbd);
request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr,
SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING,
"Spitzkbd HP", spitzkbd);
printk(KERN_INFO "input: Spitz Keyboard Registered\n"); printk(KERN_INFO "input: Spitz Keyboard Registered\n");
...@@ -450,6 +457,7 @@ static int spitzkbd_remove(struct platform_device *dev) ...@@ -450,6 +457,7 @@ static int spitzkbd_remove(struct platform_device *dev)
free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd); free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd);
free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd); free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd);
free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd); free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd);
free_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd);
del_timer_sync(&spitzkbd->htimer); del_timer_sync(&spitzkbd->htimer);
del_timer_sync(&spitzkbd->timer); del_timer_sync(&spitzkbd->timer);
......
...@@ -24,7 +24,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); ...@@ -24,7 +24,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("PC Speaker beeper driver"); MODULE_DESCRIPTION("PC Speaker beeper driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static struct platform_device *pcspkr_platform_device;
static DEFINE_SPINLOCK(i8253_beep_lock); static DEFINE_SPINLOCK(i8253_beep_lock);
static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
...@@ -135,35 +134,11 @@ static struct platform_driver pcspkr_platform_driver = { ...@@ -135,35 +134,11 @@ static struct platform_driver pcspkr_platform_driver = {
static int __init pcspkr_init(void) static int __init pcspkr_init(void)
{ {
int err; return platform_driver_register(&pcspkr_platform_driver);
err = platform_driver_register(&pcspkr_platform_driver);
if (err)
return err;
pcspkr_platform_device = platform_device_alloc("pcspkr", -1);
if (!pcspkr_platform_device) {
err = -ENOMEM;
goto err_unregister_driver;
}
err = platform_device_add(pcspkr_platform_device);
if (err)
goto err_free_device;
return 0;
err_free_device:
platform_device_put(pcspkr_platform_device);
err_unregister_driver:
platform_driver_unregister(&pcspkr_platform_driver);
return err;
} }
static void __exit pcspkr_exit(void) static void __exit pcspkr_exit(void)
{ {
platform_device_unregister(pcspkr_platform_device);
platform_driver_unregister(&pcspkr_platform_driver); platform_driver_unregister(&pcspkr_platform_driver);
} }
......
...@@ -194,7 +194,7 @@ static int uinput_open(struct inode *inode, struct file *file) ...@@ -194,7 +194,7 @@ static int uinput_open(struct inode *inode, struct file *file)
if (!newdev) if (!newdev)
return -ENOMEM; return -ENOMEM;
init_MUTEX(&newdev->sem); mutex_init(&newdev->mutex);
spin_lock_init(&newdev->requests_lock); spin_lock_init(&newdev->requests_lock);
init_waitqueue_head(&newdev->requests_waitq); init_waitqueue_head(&newdev->requests_waitq);
init_waitqueue_head(&newdev->waitq); init_waitqueue_head(&newdev->waitq);
...@@ -340,7 +340,7 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t ...@@ -340,7 +340,7 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t
struct uinput_device *udev = file->private_data; struct uinput_device *udev = file->private_data;
int retval; int retval;
retval = down_interruptible(&udev->sem); retval = mutex_lock_interruptible(&udev->mutex);
if (retval) if (retval)
return retval; return retval;
...@@ -348,7 +348,7 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t ...@@ -348,7 +348,7 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t
uinput_inject_event(udev, buffer, count) : uinput_inject_event(udev, buffer, count) :
uinput_setup_device(udev, buffer, count); uinput_setup_device(udev, buffer, count);
up(&udev->sem); mutex_unlock(&udev->mutex);
return retval; return retval;
} }
...@@ -369,7 +369,7 @@ static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count, ...@@ -369,7 +369,7 @@ static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count,
if (retval) if (retval)
return retval; return retval;
retval = down_interruptible(&udev->sem); retval = mutex_lock_interruptible(&udev->mutex);
if (retval) if (retval)
return retval; return retval;
...@@ -388,7 +388,7 @@ static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count, ...@@ -388,7 +388,7 @@ static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count,
} }
out: out:
up(&udev->sem); mutex_unlock(&udev->mutex);
return retval; return retval;
} }
...@@ -439,7 +439,7 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -439,7 +439,7 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
udev = file->private_data; udev = file->private_data;
retval = down_interruptible(&udev->sem); retval = mutex_lock_interruptible(&udev->mutex);
if (retval) if (retval)
return retval; return retval;
...@@ -589,7 +589,7 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -589,7 +589,7 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
} }
out: out:
up(&udev->sem); mutex_unlock(&udev->mutex);
return retval; return retval;
} }
......
...@@ -249,10 +249,13 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) ...@@ -249,10 +249,13 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
return -ENOMEM; return -ENOMEM;
ptr->dev = input_allocate_device(); ptr->dev = input_allocate_device();
if (!ptr->dev) goto bail0; if (!ptr->dev)
goto bail0;
ptr->dev->private = ptr; ptr->dev->private = ptr;
if (serio_open(serio, driver)) goto bail1; if (serio_open(serio, driver))
goto bail1;
serio_set_drvdata(serio, ptr); serio_set_drvdata(serio, ptr);
ptr->serio = serio; ptr->serio = serio;
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include <linux/serio.h> #include <linux/serio.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/libps2.h> #include <linux/libps2.h>
#include <linux/mutex.h>
#include "psmouse.h" #include "psmouse.h"
#include "synaptics.h" #include "synaptics.h"
#include "logips2pp.h" #include "logips2pp.h"
...@@ -98,13 +100,13 @@ __obsolete_setup("psmouse_resetafter="); ...@@ -98,13 +100,13 @@ __obsolete_setup("psmouse_resetafter=");
__obsolete_setup("psmouse_rate="); __obsolete_setup("psmouse_rate=");
/* /*
* psmouse_sem protects all operations changing state of mouse * psmouse_mutex protects all operations changing state of mouse
* (connecting, disconnecting, changing rate or resolution via * (connecting, disconnecting, changing rate or resolution via
* sysfs). We could use a per-device semaphore but since there * sysfs). We could use a per-device semaphore but since there
* rarely more than one PS/2 mouse connected and since semaphore * rarely more than one PS/2 mouse connected and since semaphore
* is taken in "slow" paths it is not worth it. * is taken in "slow" paths it is not worth it.
*/ */
static DECLARE_MUTEX(psmouse_sem); static DEFINE_MUTEX(psmouse_mutex);
static struct workqueue_struct *kpsmoused_wq; static struct workqueue_struct *kpsmoused_wq;
...@@ -868,7 +870,7 @@ static void psmouse_resync(void *p) ...@@ -868,7 +870,7 @@ static void psmouse_resync(void *p)
int failed = 0, enabled = 0; int failed = 0, enabled = 0;
int i; int i;
down(&psmouse_sem); mutex_lock(&psmouse_mutex);
if (psmouse->state != PSMOUSE_RESYNCING) if (psmouse->state != PSMOUSE_RESYNCING)
goto out; goto out;
...@@ -948,7 +950,7 @@ static void psmouse_resync(void *p) ...@@ -948,7 +950,7 @@ static void psmouse_resync(void *p)
if (parent) if (parent)
psmouse_activate(parent); psmouse_activate(parent);
out: out:
up(&psmouse_sem); mutex_unlock(&psmouse_mutex);
} }
/* /*
...@@ -974,14 +976,14 @@ static void psmouse_disconnect(struct serio *serio) ...@@ -974,14 +976,14 @@ static void psmouse_disconnect(struct serio *serio)
sysfs_remove_group(&serio->dev.kobj, &psmouse_attribute_group); sysfs_remove_group(&serio->dev.kobj, &psmouse_attribute_group);
down(&psmouse_sem); mutex_lock(&psmouse_mutex);
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
/* make sure we don't have a resync in progress */ /* make sure we don't have a resync in progress */
up(&psmouse_sem); mutex_unlock(&psmouse_mutex);
flush_workqueue(kpsmoused_wq); flush_workqueue(kpsmoused_wq);
down(&psmouse_sem); mutex_lock(&psmouse_mutex);
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = serio_get_drvdata(serio->parent); parent = serio_get_drvdata(serio->parent);
...@@ -1004,7 +1006,7 @@ static void psmouse_disconnect(struct serio *serio) ...@@ -1004,7 +1006,7 @@ static void psmouse_disconnect(struct serio *serio)
if (parent) if (parent)
psmouse_activate(parent); psmouse_activate(parent);
up(&psmouse_sem); mutex_unlock(&psmouse_mutex);
} }
static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_protocol *proto) static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_protocol *proto)
...@@ -1076,7 +1078,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) ...@@ -1076,7 +1078,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
struct input_dev *input_dev; struct input_dev *input_dev;
int retval = -ENOMEM; int retval = -ENOMEM;
down(&psmouse_sem); mutex_lock(&psmouse_mutex);
/* /*
* If this is a pass-through port deactivate parent so the device * If this is a pass-through port deactivate parent so the device
...@@ -1144,7 +1146,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) ...@@ -1144,7 +1146,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
if (parent) if (parent)
psmouse_activate(parent); psmouse_activate(parent);
up(&psmouse_sem); mutex_unlock(&psmouse_mutex);
return retval; return retval;
} }
...@@ -1161,7 +1163,7 @@ static int psmouse_reconnect(struct serio *serio) ...@@ -1161,7 +1163,7 @@ static int psmouse_reconnect(struct serio *serio)
return -1; return -1;
} }
down(&psmouse_sem); mutex_lock(&psmouse_mutex);
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = serio_get_drvdata(serio->parent); parent = serio_get_drvdata(serio->parent);
...@@ -1195,7 +1197,7 @@ static int psmouse_reconnect(struct serio *serio) ...@@ -1195,7 +1197,7 @@ static int psmouse_reconnect(struct serio *serio)
if (parent) if (parent)
psmouse_activate(parent); psmouse_activate(parent);
up(&psmouse_sem); mutex_unlock(&psmouse_mutex);
return rc; return rc;
} }
...@@ -1273,7 +1275,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev ...@@ -1273,7 +1275,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
goto out_unpin; goto out_unpin;
} }
retval = down_interruptible(&psmouse_sem); retval = mutex_lock_interruptible(&psmouse_mutex);
if (retval) if (retval)
goto out_unpin; goto out_unpin;
...@@ -1281,7 +1283,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev ...@@ -1281,7 +1283,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
if (psmouse->state == PSMOUSE_IGNORE) { if (psmouse->state == PSMOUSE_IGNORE) {
retval = -ENODEV; retval = -ENODEV;
goto out_up; goto out_unlock;
} }
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
...@@ -1299,8 +1301,8 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev ...@@ -1299,8 +1301,8 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
if (parent) if (parent)
psmouse_activate(parent); psmouse_activate(parent);
out_up: out_unlock:
up(&psmouse_sem); mutex_unlock(&psmouse_mutex);
out_unpin: out_unpin:
serio_unpin_driver(serio); serio_unpin_driver(serio);
return retval; return retval;
...@@ -1357,11 +1359,11 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co ...@@ -1357,11 +1359,11 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
return -EIO; return -EIO;
} }
up(&psmouse_sem); mutex_unlock(&psmouse_mutex);
serio_unpin_driver(serio); serio_unpin_driver(serio);
serio_unregister_child_port(serio); serio_unregister_child_port(serio);
serio_pin_driver_uninterruptible(serio); serio_pin_driver_uninterruptible(serio);
down(&psmouse_sem); mutex_lock(&psmouse_mutex);
if (serio->drv != &psmouse_drv) { if (serio->drv != &psmouse_drv) {
input_free_device(new_dev); input_free_device(new_dev);
......
...@@ -247,14 +247,12 @@ static void synaptics_pt_create(struct psmouse *psmouse) ...@@ -247,14 +247,12 @@ static void synaptics_pt_create(struct psmouse *psmouse)
{ {
struct serio *serio; struct serio *serio;
serio = kmalloc(sizeof(struct serio), GFP_KERNEL); serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!serio) { if (!serio) {
printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n"); printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n");
return; return;
} }
memset(serio, 0, sizeof(struct serio));
serio->id.type = SERIO_PS_PSTHRU; serio->id.type = SERIO_PS_PSTHRU;
strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name)); strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name)); strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
...@@ -605,14 +603,21 @@ static struct dmi_system_id toshiba_dmi_table[] = { ...@@ -605,14 +603,21 @@ static struct dmi_system_id toshiba_dmi_table[] = {
.ident = "Toshiba Satellite", .ident = "Toshiba Satellite",
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME , "Satellite"), DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"),
}, },
}, },
{ {
.ident = "Toshiba Dynabook", .ident = "Toshiba Dynabook",
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME , "dynabook"), DMI_MATCH(DMI_PRODUCT_NAME, "dynabook"),
},
},
{
.ident = "Toshiba Portege M300",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"),
}, },
}, },
{ } { }
...@@ -623,10 +628,9 @@ int synaptics_init(struct psmouse *psmouse) ...@@ -623,10 +628,9 @@ int synaptics_init(struct psmouse *psmouse)
{ {
struct synaptics_data *priv; struct synaptics_data *priv;
psmouse->private = priv = kmalloc(sizeof(struct synaptics_data), GFP_KERNEL); psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL);
if (!priv) if (!priv)
return -1; return -1;
memset(priv, 0, sizeof(struct synaptics_data));
if (synaptics_query_hardware(psmouse)) { if (synaptics_query_hardware(psmouse)) {
printk(KERN_ERR "Unable to query Synaptics hardware.\n"); printk(KERN_ERR "Unable to query Synaptics hardware.\n");
......
...@@ -412,9 +412,8 @@ static int mousedev_open(struct inode * inode, struct file * file) ...@@ -412,9 +412,8 @@ static int mousedev_open(struct inode * inode, struct file * file)
if (i >= MOUSEDEV_MINORS || !mousedev_table[i]) if (i >= MOUSEDEV_MINORS || !mousedev_table[i])
return -ENODEV; return -ENODEV;
if (!(list = kmalloc(sizeof(struct mousedev_list), GFP_KERNEL))) if (!(list = kzalloc(sizeof(struct mousedev_list), GFP_KERNEL)))
return -ENOMEM; return -ENOMEM;
memset(list, 0, sizeof(struct mousedev_list));
spin_lock_init(&list->packet_lock); spin_lock_init(&list->packet_lock);
list->pos_x = xres / 2; list->pos_x = xres / 2;
...@@ -626,9 +625,8 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru ...@@ -626,9 +625,8 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru
return NULL; return NULL;
} }
if (!(mousedev = kmalloc(sizeof(struct mousedev), GFP_KERNEL))) if (!(mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL)))
return NULL; return NULL;
memset(mousedev, 0, sizeof(struct mousedev));
INIT_LIST_HEAD(&mousedev->list); INIT_LIST_HEAD(&mousedev->list);
init_waitqueue_head(&mousedev->wait); init_waitqueue_head(&mousedev->wait);
......
...@@ -103,9 +103,8 @@ static struct input_handle *power_connect(struct input_handler *handler, ...@@ -103,9 +103,8 @@ static struct input_handle *power_connect(struct input_handler *handler,
{ {
struct input_handle *handle; struct input_handle *handle;
if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL))) if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL)))
return NULL; return NULL;
memset(handle, 0, sizeof(struct input_handle));
handle->dev = dev; handle->dev = dev;
handle->handler = handler; handle->handler = handler;
......
...@@ -872,9 +872,8 @@ int hil_mlc_register(hil_mlc *mlc) { ...@@ -872,9 +872,8 @@ int hil_mlc_register(hil_mlc *mlc) {
for (i = 0; i < HIL_MLC_DEVMEM; i++) { for (i = 0; i < HIL_MLC_DEVMEM; i++) {
struct serio *mlc_serio; struct serio *mlc_serio;
hil_mlc_copy_di_scratch(mlc, i); hil_mlc_copy_di_scratch(mlc, i);
mlc_serio = kmalloc(sizeof(*mlc_serio), GFP_KERNEL); mlc_serio = kzalloc(sizeof(*mlc_serio), GFP_KERNEL);
mlc->serio[i] = mlc_serio; mlc->serio[i] = mlc_serio;
memset(mlc_serio, 0, sizeof(*mlc_serio));
mlc_serio->id = hil_mlc_serio_id; mlc_serio->id = hil_mlc_serio_id;
mlc_serio->write = hil_mlc_serio_write; mlc_serio->write = hil_mlc_serio_write;
mlc_serio->open = hil_mlc_serio_open; mlc_serio->open = hil_mlc_serio_open;
......
...@@ -192,7 +192,9 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { ...@@ -192,7 +192,9 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
#include <linux/pnp.h> #include <linux/pnp.h>
static int i8042_pnp_kbd_registered; static int i8042_pnp_kbd_registered;
static unsigned int i8042_pnp_kbd_devices;
static int i8042_pnp_aux_registered; static int i8042_pnp_aux_registered;
static unsigned int i8042_pnp_aux_devices;
static int i8042_pnp_command_reg; static int i8042_pnp_command_reg;
static int i8042_pnp_data_reg; static int i8042_pnp_data_reg;
...@@ -219,6 +221,7 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id * ...@@ -219,6 +221,7 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *
strncat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name)); strncat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name));
} }
i8042_pnp_kbd_devices++;
return 0; return 0;
} }
...@@ -239,6 +242,7 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id * ...@@ -239,6 +242,7 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *
strncat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name)); strncat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name));
} }
i8042_pnp_aux_devices++;
return 0; return 0;
} }
...@@ -287,21 +291,23 @@ static void i8042_pnp_exit(void) ...@@ -287,21 +291,23 @@ static void i8042_pnp_exit(void)
static int __init i8042_pnp_init(void) static int __init i8042_pnp_init(void)
{ {
int result_kbd = 0, result_aux = 0;
char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 }; char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 };
int err;
if (i8042_nopnp) { if (i8042_nopnp) {
printk(KERN_INFO "i8042: PNP detection disabled\n"); printk(KERN_INFO "i8042: PNP detection disabled\n");
return 0; return 0;
} }
if ((result_kbd = pnp_register_driver(&i8042_pnp_kbd_driver)) >= 0) err = pnp_register_driver(&i8042_pnp_kbd_driver);
if (!err)
i8042_pnp_kbd_registered = 1; i8042_pnp_kbd_registered = 1;
if ((result_aux = pnp_register_driver(&i8042_pnp_aux_driver)) >= 0) err = pnp_register_driver(&i8042_pnp_aux_driver);
if (!err)
i8042_pnp_aux_registered = 1; i8042_pnp_aux_registered = 1;
if (result_kbd <= 0 && result_aux <= 0) { if (!i8042_pnp_kbd_devices && !i8042_pnp_aux_devices) {
i8042_pnp_exit(); i8042_pnp_exit();
#if defined(__ia64__) #if defined(__ia64__)
return -ENODEV; return -ENODEV;
...@@ -311,24 +317,24 @@ static int __init i8042_pnp_init(void) ...@@ -311,24 +317,24 @@ static int __init i8042_pnp_init(void)
#endif #endif
} }
if (result_kbd > 0) if (i8042_pnp_kbd_devices)
snprintf(kbd_irq_str, sizeof(kbd_irq_str), snprintf(kbd_irq_str, sizeof(kbd_irq_str),
"%d", i8042_pnp_kbd_irq); "%d", i8042_pnp_kbd_irq);
if (result_aux > 0) if (i8042_pnp_aux_devices)
snprintf(aux_irq_str, sizeof(aux_irq_str), snprintf(aux_irq_str, sizeof(aux_irq_str),
"%d", i8042_pnp_aux_irq); "%d", i8042_pnp_aux_irq);
printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %s%s%s\n", printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %s%s%s\n",
i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "", i8042_pnp_kbd_name, (i8042_pnp_kbd_devices && i8042_pnp_aux_devices) ? "," : "",
i8042_pnp_aux_name, i8042_pnp_aux_name,
i8042_pnp_data_reg, i8042_pnp_command_reg, i8042_pnp_data_reg, i8042_pnp_command_reg,
kbd_irq_str, (result_kbd > 0 && result_aux > 0) ? "," : "", kbd_irq_str, (i8042_pnp_kbd_devices && i8042_pnp_aux_devices) ? "," : "",
aux_irq_str); aux_irq_str);
#if defined(__ia64__) #if defined(__ia64__)
if (result_kbd <= 0) if (!i8042_pnp_kbd_devices)
i8042_nokbd = 1; i8042_nokbd = 1;
if (result_aux <= 0) if (!i8042_pnp_aux_devices)
i8042_noaux = 1; i8042_noaux = 1;
#endif #endif
......
...@@ -84,7 +84,7 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout) ...@@ -84,7 +84,7 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout)
maxbytes = sizeof(ps2dev->cmdbuf); maxbytes = sizeof(ps2dev->cmdbuf);
} }
down(&ps2dev->cmd_sem); mutex_lock(&ps2dev->cmd_mutex);
serio_pause_rx(ps2dev->serio); serio_pause_rx(ps2dev->serio);
ps2dev->flags = PS2_FLAG_CMD; ps2dev->flags = PS2_FLAG_CMD;
...@@ -94,7 +94,7 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout) ...@@ -94,7 +94,7 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout)
wait_event_timeout(ps2dev->wait, wait_event_timeout(ps2dev->wait,
!(ps2dev->flags & PS2_FLAG_CMD), !(ps2dev->flags & PS2_FLAG_CMD),
msecs_to_jiffies(timeout)); msecs_to_jiffies(timeout));
up(&ps2dev->cmd_sem); mutex_unlock(&ps2dev->cmd_mutex);
} }
/* /*
...@@ -177,7 +177,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) ...@@ -177,7 +177,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
return -1; return -1;
} }
down(&ps2dev->cmd_sem); mutex_lock(&ps2dev->cmd_mutex);
serio_pause_rx(ps2dev->serio); serio_pause_rx(ps2dev->serio);
ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0; ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0;
...@@ -229,7 +229,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) ...@@ -229,7 +229,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
ps2dev->flags = 0; ps2dev->flags = 0;
serio_continue_rx(ps2dev->serio); serio_continue_rx(ps2dev->serio);
up(&ps2dev->cmd_sem); mutex_unlock(&ps2dev->cmd_mutex);
return rc; return rc;
} }
...@@ -281,7 +281,7 @@ int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int comman ...@@ -281,7 +281,7 @@ int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int comman
void ps2_init(struct ps2dev *ps2dev, struct serio *serio) void ps2_init(struct ps2dev *ps2dev, struct serio *serio)
{ {
init_MUTEX(&ps2dev->cmd_sem); mutex_init(&ps2dev->cmd_mutex);
init_waitqueue_head(&ps2dev->wait); init_waitqueue_head(&ps2dev->wait);
ps2dev->serio = serio; ps2dev->serio = serio;
} }
......
...@@ -171,9 +171,8 @@ static struct serio * __init parkbd_allocate_serio(void) ...@@ -171,9 +171,8 @@ static struct serio * __init parkbd_allocate_serio(void)
{ {
struct serio *serio; struct serio *serio;
serio = kmalloc(sizeof(struct serio), GFP_KERNEL); serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) { if (serio) {
memset(serio, 0, sizeof(struct serio));
serio->id.type = parkbd_mode; serio->id.type = parkbd_mode;
serio->write = parkbd_write, serio->write = parkbd_write,
strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name)); strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name));
......
...@@ -111,11 +111,10 @@ static int __devinit rpckbd_probe(struct platform_device *dev) ...@@ -111,11 +111,10 @@ static int __devinit rpckbd_probe(struct platform_device *dev)
{ {
struct serio *serio; struct serio *serio;
serio = kmalloc(sizeof(struct serio), GFP_KERNEL); serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!serio) if (!serio)
return -ENOMEM; return -ENOMEM;
memset(serio, 0, sizeof(struct serio));
serio->id.type = SERIO_8042; serio->id.type = SERIO_8042;
serio->write = rpckbd_write; serio->write = rpckbd_write;
serio->open = rpckbd_open; serio->open = rpckbd_open;
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/mutex.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Serio abstraction core"); MODULE_DESCRIPTION("Serio abstraction core");
...@@ -52,10 +53,10 @@ EXPORT_SYMBOL(serio_rescan); ...@@ -52,10 +53,10 @@ EXPORT_SYMBOL(serio_rescan);
EXPORT_SYMBOL(serio_reconnect); EXPORT_SYMBOL(serio_reconnect);
/* /*
* serio_sem protects entire serio subsystem and is taken every time * serio_mutex protects entire serio subsystem and is taken every time
* serio port or driver registrered or unregistered. * serio port or driver registrered or unregistered.
*/ */
static DECLARE_MUTEX(serio_sem); static DEFINE_MUTEX(serio_mutex);
static LIST_HEAD(serio_list); static LIST_HEAD(serio_list);
...@@ -70,9 +71,9 @@ static int serio_connect_driver(struct serio *serio, struct serio_driver *drv) ...@@ -70,9 +71,9 @@ static int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
{ {
int retval; int retval;
down(&serio->drv_sem); mutex_lock(&serio->drv_mutex);
retval = drv->connect(serio, drv); retval = drv->connect(serio, drv);
up(&serio->drv_sem); mutex_unlock(&serio->drv_mutex);
return retval; return retval;
} }
...@@ -81,20 +82,20 @@ static int serio_reconnect_driver(struct serio *serio) ...@@ -81,20 +82,20 @@ static int serio_reconnect_driver(struct serio *serio)
{ {
int retval = -1; int retval = -1;
down(&serio->drv_sem); mutex_lock(&serio->drv_mutex);
if (serio->drv && serio->drv->reconnect) if (serio->drv && serio->drv->reconnect)
retval = serio->drv->reconnect(serio); retval = serio->drv->reconnect(serio);
up(&serio->drv_sem); mutex_unlock(&serio->drv_mutex);
return retval; return retval;
} }
static void serio_disconnect_driver(struct serio *serio) static void serio_disconnect_driver(struct serio *serio)
{ {
down(&serio->drv_sem); mutex_lock(&serio->drv_mutex);
if (serio->drv) if (serio->drv)
serio->drv->disconnect(serio); serio->drv->disconnect(serio);
up(&serio->drv_sem); mutex_unlock(&serio->drv_mutex);
} }
static int serio_match_port(const struct serio_device_id *ids, struct serio *serio) static int serio_match_port(const struct serio_device_id *ids, struct serio *serio)
...@@ -195,6 +196,7 @@ static void serio_queue_event(void *object, struct module *owner, ...@@ -195,6 +196,7 @@ static void serio_queue_event(void *object, struct module *owner,
if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) { if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
if (!try_module_get(owner)) { if (!try_module_get(owner)) {
printk(KERN_WARNING "serio: Can't get module reference, dropping event %d\n", event_type); printk(KERN_WARNING "serio: Can't get module reference, dropping event %d\n", event_type);
kfree(event);
goto out; goto out;
} }
...@@ -272,7 +274,7 @@ static void serio_handle_event(void) ...@@ -272,7 +274,7 @@ static void serio_handle_event(void)
struct serio_event *event; struct serio_event *event;
struct serio_driver *serio_drv; struct serio_driver *serio_drv;
down(&serio_sem); mutex_lock(&serio_mutex);
/* /*
* Note that we handle only one event here to give swsusp * Note that we handle only one event here to give swsusp
...@@ -314,7 +316,7 @@ static void serio_handle_event(void) ...@@ -314,7 +316,7 @@ static void serio_handle_event(void)
serio_free_event(event); serio_free_event(event);
} }
up(&serio_sem); mutex_unlock(&serio_mutex);
} }
/* /*
...@@ -449,7 +451,7 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute * ...@@ -449,7 +451,7 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *
struct device_driver *drv; struct device_driver *drv;
int retval; int retval;
retval = down_interruptible(&serio_sem); retval = mutex_lock_interruptible(&serio_mutex);
if (retval) if (retval)
return retval; return retval;
...@@ -469,7 +471,7 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute * ...@@ -469,7 +471,7 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *
retval = -EINVAL; retval = -EINVAL;
} }
up(&serio_sem); mutex_unlock(&serio_mutex);
return retval; return retval;
} }
...@@ -524,7 +526,7 @@ static void serio_init_port(struct serio *serio) ...@@ -524,7 +526,7 @@ static void serio_init_port(struct serio *serio)
__module_get(THIS_MODULE); __module_get(THIS_MODULE);
spin_lock_init(&serio->lock); spin_lock_init(&serio->lock);
init_MUTEX(&serio->drv_sem); mutex_init(&serio->drv_mutex);
device_initialize(&serio->dev); device_initialize(&serio->dev);
snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id), snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id),
"serio%ld", (long)atomic_inc_return(&serio_no) - 1); "serio%ld", (long)atomic_inc_return(&serio_no) - 1);
...@@ -661,10 +663,10 @@ void __serio_register_port(struct serio *serio, struct module *owner) ...@@ -661,10 +663,10 @@ void __serio_register_port(struct serio *serio, struct module *owner)
*/ */
void serio_unregister_port(struct serio *serio) void serio_unregister_port(struct serio *serio)
{ {
down(&serio_sem); mutex_lock(&serio_mutex);
serio_disconnect_port(serio); serio_disconnect_port(serio);
serio_destroy_port(serio); serio_destroy_port(serio);
up(&serio_sem); mutex_unlock(&serio_mutex);
} }
/* /*
...@@ -672,17 +674,17 @@ void serio_unregister_port(struct serio *serio) ...@@ -672,17 +674,17 @@ void serio_unregister_port(struct serio *serio)
*/ */
void serio_unregister_child_port(struct serio *serio) void serio_unregister_child_port(struct serio *serio)
{ {
down(&serio_sem); mutex_lock(&serio_mutex);
if (serio->child) { if (serio->child) {
serio_disconnect_port(serio->child); serio_disconnect_port(serio->child);
serio_destroy_port(serio->child); serio_destroy_port(serio->child);
} }
up(&serio_sem); mutex_unlock(&serio_mutex);
} }
/* /*
* Submits register request to kseriod for subsequent execution. * Submits register request to kseriod for subsequent execution.
* Can be used when it is not obvious whether the serio_sem is * Can be used when it is not obvious whether the serio_mutex is
* taken or not and when delayed execution is feasible. * taken or not and when delayed execution is feasible.
*/ */
void __serio_unregister_port_delayed(struct serio *serio, struct module *owner) void __serio_unregister_port_delayed(struct serio *serio, struct module *owner)
...@@ -765,7 +767,7 @@ void serio_unregister_driver(struct serio_driver *drv) ...@@ -765,7 +767,7 @@ void serio_unregister_driver(struct serio_driver *drv)
{ {
struct serio *serio; struct serio *serio;
down(&serio_sem); mutex_lock(&serio_mutex);
drv->manual_bind = 1; /* so serio_find_driver ignores it */ drv->manual_bind = 1; /* so serio_find_driver ignores it */
start_over: start_over:
...@@ -779,7 +781,7 @@ void serio_unregister_driver(struct serio_driver *drv) ...@@ -779,7 +781,7 @@ void serio_unregister_driver(struct serio_driver *drv)
} }
driver_unregister(&drv->driver); driver_unregister(&drv->driver);
up(&serio_sem); mutex_unlock(&serio_mutex);
} }
static void serio_set_drv(struct serio *serio, struct serio_driver *drv) static void serio_set_drv(struct serio *serio, struct serio_driver *drv)
...@@ -858,7 +860,7 @@ static int serio_resume(struct device *dev) ...@@ -858,7 +860,7 @@ static int serio_resume(struct device *dev)
return 0; return 0;
} }
/* called from serio_driver->connect/disconnect methods under serio_sem */ /* called from serio_driver->connect/disconnect methods under serio_mutex */
int serio_open(struct serio *serio, struct serio_driver *drv) int serio_open(struct serio *serio, struct serio_driver *drv)
{ {
serio_set_drv(serio, drv); serio_set_drv(serio, drv);
...@@ -870,7 +872,7 @@ int serio_open(struct serio *serio, struct serio_driver *drv) ...@@ -870,7 +872,7 @@ int serio_open(struct serio *serio, struct serio_driver *drv)
return 0; return 0;
} }
/* called from serio_driver->connect/disconnect methods under serio_sem */ /* called from serio_driver->connect/disconnect methods under serio_mutex */
void serio_close(struct serio *serio) void serio_close(struct serio *serio)
{ {
if (serio->close) if (serio->close)
...@@ -923,5 +925,5 @@ static void __exit serio_exit(void) ...@@ -923,5 +925,5 @@ static void __exit serio_exit(void)
kthread_stop(serio_task); kthread_stop(serio_task);
} }
module_init(serio_init); subsys_initcall(serio_init);
module_exit(serio_exit); module_exit(serio_exit);
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/devfs_fs_kernel.h> #include <linux/devfs_fs_kernel.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/mutex.h>
#define DRIVER_DESC "Raw serio driver" #define DRIVER_DESC "Raw serio driver"
...@@ -46,7 +47,7 @@ struct serio_raw_list { ...@@ -46,7 +47,7 @@ struct serio_raw_list {
struct list_head node; struct list_head node;
}; };
static DECLARE_MUTEX(serio_raw_sem); static DEFINE_MUTEX(serio_raw_mutex);
static LIST_HEAD(serio_raw_list); static LIST_HEAD(serio_raw_list);
static unsigned int serio_raw_no; static unsigned int serio_raw_no;
...@@ -81,7 +82,7 @@ static int serio_raw_open(struct inode *inode, struct file *file) ...@@ -81,7 +82,7 @@ static int serio_raw_open(struct inode *inode, struct file *file)
struct serio_raw_list *list; struct serio_raw_list *list;
int retval = 0; int retval = 0;
retval = down_interruptible(&serio_raw_sem); retval = mutex_lock_interruptible(&serio_raw_mutex);
if (retval) if (retval)
return retval; return retval;
...@@ -95,12 +96,11 @@ static int serio_raw_open(struct inode *inode, struct file *file) ...@@ -95,12 +96,11 @@ static int serio_raw_open(struct inode *inode, struct file *file)
goto out; goto out;
} }
if (!(list = kmalloc(sizeof(struct serio_raw_list), GFP_KERNEL))) { if (!(list = kzalloc(sizeof(struct serio_raw_list), GFP_KERNEL))) {
retval = -ENOMEM; retval = -ENOMEM;
goto out; goto out;
} }
memset(list, 0, sizeof(struct serio_raw_list));
list->serio_raw = serio_raw; list->serio_raw = serio_raw;
file->private_data = list; file->private_data = list;
...@@ -108,7 +108,7 @@ static int serio_raw_open(struct inode *inode, struct file *file) ...@@ -108,7 +108,7 @@ static int serio_raw_open(struct inode *inode, struct file *file)
list_add_tail(&list->node, &serio_raw->list); list_add_tail(&list->node, &serio_raw->list);
out: out:
up(&serio_raw_sem); mutex_unlock(&serio_raw_mutex);
return retval; return retval;
} }
...@@ -130,12 +130,12 @@ static int serio_raw_release(struct inode *inode, struct file *file) ...@@ -130,12 +130,12 @@ static int serio_raw_release(struct inode *inode, struct file *file)
struct serio_raw_list *list = file->private_data; struct serio_raw_list *list = file->private_data;
struct serio_raw *serio_raw = list->serio_raw; struct serio_raw *serio_raw = list->serio_raw;
down(&serio_raw_sem); mutex_lock(&serio_raw_mutex);
serio_raw_fasync(-1, file, 0); serio_raw_fasync(-1, file, 0);
serio_raw_cleanup(serio_raw); serio_raw_cleanup(serio_raw);
up(&serio_raw_sem); mutex_unlock(&serio_raw_mutex);
return 0; return 0;
} }
...@@ -194,7 +194,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz ...@@ -194,7 +194,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz
int retval; int retval;
unsigned char c; unsigned char c;
retval = down_interruptible(&serio_raw_sem); retval = mutex_lock_interruptible(&serio_raw_mutex);
if (retval) if (retval)
return retval; return retval;
...@@ -219,7 +219,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz ...@@ -219,7 +219,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz
}; };
out: out:
up(&serio_raw_sem); mutex_unlock(&serio_raw_mutex);
return written; return written;
} }
...@@ -275,14 +275,13 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv) ...@@ -275,14 +275,13 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
struct serio_raw *serio_raw; struct serio_raw *serio_raw;
int err; int err;
if (!(serio_raw = kmalloc(sizeof(struct serio_raw), GFP_KERNEL))) { if (!(serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL))) {
printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n"); printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n");
return -ENOMEM; return -ENOMEM;
} }
down(&serio_raw_sem); mutex_lock(&serio_raw_mutex);
memset(serio_raw, 0, sizeof(struct serio_raw));
snprintf(serio_raw->name, sizeof(serio_raw->name), "serio_raw%d", serio_raw_no++); snprintf(serio_raw->name, sizeof(serio_raw->name), "serio_raw%d", serio_raw_no++);
serio_raw->refcnt = 1; serio_raw->refcnt = 1;
serio_raw->serio = serio; serio_raw->serio = serio;
...@@ -325,7 +324,7 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv) ...@@ -325,7 +324,7 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
serio_set_drvdata(serio, NULL); serio_set_drvdata(serio, NULL);
kfree(serio_raw); kfree(serio_raw);
out: out:
up(&serio_raw_sem); mutex_unlock(&serio_raw_mutex);
return err; return err;
} }
...@@ -350,7 +349,7 @@ static void serio_raw_disconnect(struct serio *serio) ...@@ -350,7 +349,7 @@ static void serio_raw_disconnect(struct serio *serio)
{ {
struct serio_raw *serio_raw; struct serio_raw *serio_raw;
down(&serio_raw_sem); mutex_lock(&serio_raw_mutex);
serio_raw = serio_get_drvdata(serio); serio_raw = serio_get_drvdata(serio);
...@@ -361,7 +360,7 @@ static void serio_raw_disconnect(struct serio *serio) ...@@ -361,7 +360,7 @@ static void serio_raw_disconnect(struct serio *serio)
if (!serio_raw_cleanup(serio_raw)) if (!serio_raw_cleanup(serio_raw))
wake_up_interruptible(&serio_raw->wait); wake_up_interruptible(&serio_raw->wait);
up(&serio_raw_sem); mutex_unlock(&serio_raw_mutex);
} }
static struct serio_device_id serio_raw_serio_ids[] = { static struct serio_device_id serio_raw_serio_ids[] = {
......
...@@ -157,9 +157,8 @@ static int tsdev_open(struct inode *inode, struct file *file) ...@@ -157,9 +157,8 @@ static int tsdev_open(struct inode *inode, struct file *file)
if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK]) if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK])
return -ENODEV; return -ENODEV;
if (!(list = kmalloc(sizeof(struct tsdev_list), GFP_KERNEL))) if (!(list = kzalloc(sizeof(struct tsdev_list), GFP_KERNEL)))
return -ENOMEM; return -ENOMEM;
memset(list, 0, sizeof(struct tsdev_list));
list->raw = (i >= TSDEV_MINORS/2) ? 1 : 0; list->raw = (i >= TSDEV_MINORS/2) ? 1 : 0;
...@@ -379,9 +378,8 @@ static struct input_handle *tsdev_connect(struct input_handler *handler, ...@@ -379,9 +378,8 @@ static struct input_handle *tsdev_connect(struct input_handler *handler,
return NULL; return NULL;
} }
if (!(tsdev = kmalloc(sizeof(struct tsdev), GFP_KERNEL))) if (!(tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL)))
return NULL; return NULL;
memset(tsdev, 0, sizeof(struct tsdev));
INIT_LIST_HEAD(&tsdev->list); INIT_LIST_HEAD(&tsdev->list);
init_waitqueue_head(&tsdev->wait); init_waitqueue_head(&tsdev->wait);
......
...@@ -510,7 +510,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel ...@@ -510,7 +510,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x025: map_key_clear(KEY_TV); break; case 0x025: map_key_clear(KEY_TV); break;
case 0x026: map_key_clear(KEY_MENU); break; case 0x026: map_key_clear(KEY_MENU); break;
case 0x031: map_key_clear(KEY_AUDIO); break; case 0x031: map_key_clear(KEY_AUDIO); break;
case 0x032: map_key_clear(KEY_SUBTITLE); break; case 0x032: map_key_clear(KEY_TEXT); break;
case 0x033: map_key_clear(KEY_LAST); break; case 0x033: map_key_clear(KEY_LAST); break;
case 0x047: map_key_clear(KEY_MP3); break; case 0x047: map_key_clear(KEY_MP3); break;
case 0x048: map_key_clear(KEY_DVD); break; case 0x048: map_key_clear(KEY_DVD); break;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/mutex.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/timer.h> #include <linux/timer.h>
...@@ -40,7 +41,7 @@ struct gameport { ...@@ -40,7 +41,7 @@ struct gameport {
struct gameport *parent, *child; struct gameport *parent, *child;
struct gameport_driver *drv; struct gameport_driver *drv;
struct semaphore drv_sem; /* protects serio->drv so attributes can pin driver */ struct mutex drv_mutex; /* protects serio->drv so attributes can pin driver */
struct device dev; struct device dev;
unsigned int registered; /* port has been fully registered with driver core */ unsigned int registered; /* port has been fully registered with driver core */
...@@ -137,12 +138,12 @@ static inline void gameport_set_drvdata(struct gameport *gameport, void *data) ...@@ -137,12 +138,12 @@ static inline void gameport_set_drvdata(struct gameport *gameport, void *data)
*/ */
static inline int gameport_pin_driver(struct gameport *gameport) static inline int gameport_pin_driver(struct gameport *gameport)
{ {
return down_interruptible(&gameport->drv_sem); return mutex_lock_interruptible(&gameport->drv_mutex);
} }
static inline void gameport_unpin_driver(struct gameport *gameport) static inline void gameport_unpin_driver(struct gameport *gameport)
{ {
up(&gameport->drv_sem); mutex_unlock(&gameport->drv_mutex);
} }
void __gameport_register_driver(struct gameport_driver *drv, struct module *owner); void __gameport_register_driver(struct gameport_driver *drv, struct module *owner);
......
...@@ -512,6 +512,15 @@ struct input_absinfo { ...@@ -512,6 +512,15 @@ struct input_absinfo {
#define KEY_FN_S 0x1e3 #define KEY_FN_S 0x1e3
#define KEY_FN_B 0x1e4 #define KEY_FN_B 0x1e4
#define KEY_BRL_DOT1 0x1f1
#define KEY_BRL_DOT2 0x1f2
#define KEY_BRL_DOT3 0x1f3
#define KEY_BRL_DOT4 0x1f4
#define KEY_BRL_DOT5 0x1f5
#define KEY_BRL_DOT6 0x1f6
#define KEY_BRL_DOT7 0x1f7
#define KEY_BRL_DOT8 0x1f8
/* We avoid low common keys in module aliases so they don't get huge. */ /* We avoid low common keys in module aliases so they don't get huge. */
#define KEY_MIN_INTERESTING KEY_MUTE #define KEY_MIN_INTERESTING KEY_MUTE
#define KEY_MAX 0x1ff #define KEY_MAX 0x1ff
...@@ -929,7 +938,7 @@ struct input_dev { ...@@ -929,7 +938,7 @@ struct input_dev {
struct input_handle *grab; struct input_handle *grab;
struct semaphore sem; /* serializes open and close operations */ struct mutex mutex; /* serializes open and close operations */
unsigned int users; unsigned int users;
struct class_device cdev; struct class_device cdev;
...@@ -995,11 +1004,6 @@ static inline void init_input_dev(struct input_dev *dev) ...@@ -995,11 +1004,6 @@ static inline void init_input_dev(struct input_dev *dev)
struct input_dev *input_allocate_device(void); struct input_dev *input_allocate_device(void);
static inline void input_free_device(struct input_dev *dev)
{
kfree(dev);
}
static inline struct input_dev *input_get_device(struct input_dev *dev) static inline struct input_dev *input_get_device(struct input_dev *dev)
{ {
return to_input_dev(class_device_get(&dev->cdev)); return to_input_dev(class_device_get(&dev->cdev));
...@@ -1010,6 +1014,11 @@ static inline void input_put_device(struct input_dev *dev) ...@@ -1010,6 +1014,11 @@ static inline void input_put_device(struct input_dev *dev)
class_device_put(&dev->cdev); class_device_put(&dev->cdev);
} }
static inline void input_free_device(struct input_dev *dev)
{
input_put_device(dev);
}
int input_register_device(struct input_dev *); int input_register_device(struct input_dev *);
void input_unregister_device(struct input_dev *); void input_unregister_device(struct input_dev *);
......
...@@ -135,6 +135,8 @@ static inline void chg_vc_kbd_led(struct kbd_struct * kbd, int flag) ...@@ -135,6 +135,8 @@ static inline void chg_vc_kbd_led(struct kbd_struct * kbd, int flag)
#define U(x) ((x) ^ 0xf000) #define U(x) ((x) ^ 0xf000)
#define BRL_UC_ROW 0x2800
/* keyboard.c */ /* keyboard.c */
struct console; struct console;
......
...@@ -44,6 +44,7 @@ extern unsigned short plain_map[NR_KEYS]; ...@@ -44,6 +44,7 @@ extern unsigned short plain_map[NR_KEYS];
#define KT_ASCII 9 #define KT_ASCII 9
#define KT_LOCK 10 #define KT_LOCK 10
#define KT_SLOCK 12 #define KT_SLOCK 12
#define KT_BRL 14
#define K(t,v) (((t)<<8)|(v)) #define K(t,v) (((t)<<8)|(v))
#define KTYP(x) ((x) >> 8) #define KTYP(x) ((x) >> 8)
...@@ -427,5 +428,17 @@ extern unsigned short plain_map[NR_KEYS]; ...@@ -427,5 +428,17 @@ extern unsigned short plain_map[NR_KEYS];
#define NR_LOCK 8 #define NR_LOCK 8
#define K_BRL_BLANK K(KT_BRL, 0)
#define K_BRL_DOT1 K(KT_BRL, 1)
#define K_BRL_DOT2 K(KT_BRL, 2)
#define K_BRL_DOT3 K(KT_BRL, 3)
#define K_BRL_DOT4 K(KT_BRL, 4)
#define K_BRL_DOT5 K(KT_BRL, 5)
#define K_BRL_DOT6 K(KT_BRL, 6)
#define K_BRL_DOT7 K(KT_BRL, 7)
#define K_BRL_DOT8 K(KT_BRL, 8)
#define NR_BRL 9
#define MAX_DIACR 256 #define MAX_DIACR 256
#endif #endif
...@@ -28,7 +28,7 @@ struct ps2dev { ...@@ -28,7 +28,7 @@ struct ps2dev {
struct serio *serio; struct serio *serio;
/* Ensures that only one command is executing at a time */ /* Ensures that only one command is executing at a time */
struct semaphore cmd_sem; struct mutex cmd_mutex;
/* Used to signal completion from interrupt handler */ /* Used to signal completion from interrupt handler */
wait_queue_head_t wait; wait_queue_head_t wait;
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
...@@ -42,7 +43,7 @@ struct serio { ...@@ -42,7 +43,7 @@ struct serio {
struct serio *parent, *child; struct serio *parent, *child;
struct serio_driver *drv; /* accessed from interrupt, must be protected by serio->lock and serio->sem */ 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 mutex drv_mutex; /* protects serio->drv so attributes can pin driver */
struct device dev; struct device dev;
unsigned int registered; /* port has been fully registered with driver core */ unsigned int registered; /* port has been fully registered with driver core */
...@@ -151,17 +152,17 @@ static inline void serio_continue_rx(struct serio *serio) ...@@ -151,17 +152,17 @@ static inline void serio_continue_rx(struct serio *serio)
*/ */
static inline int serio_pin_driver(struct serio *serio) static inline int serio_pin_driver(struct serio *serio)
{ {
return down_interruptible(&serio->drv_sem); return mutex_lock_interruptible(&serio->drv_mutex);
} }
static inline void serio_pin_driver_uninterruptible(struct serio *serio) static inline void serio_pin_driver_uninterruptible(struct serio *serio)
{ {
down(&serio->drv_sem); mutex_lock(&serio->drv_mutex);
} }
static inline void serio_unpin_driver(struct serio *serio) static inline void serio_unpin_driver(struct serio *serio)
{ {
up(&serio->drv_sem); mutex_unlock(&serio->drv_mutex);
} }
......
...@@ -51,7 +51,7 @@ struct uinput_request { ...@@ -51,7 +51,7 @@ struct uinput_request {
struct uinput_device { struct uinput_device {
struct input_dev *dev; struct input_dev *dev;
struct semaphore sem; struct mutex mutex;
enum uinput_state state; enum uinput_state state;
wait_queue_head_t waitq; wait_queue_head_t waitq;
unsigned char ready; unsigned char ready;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment