Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
c5ec0513
Commit
c5ec0513
authored
Jul 29, 2004
by
Vojtech Pavlik
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://dtor.bkbits.net/input
into suse.cz:/data/bk/input
parents
8b2910fd
419bd06b
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
620 additions
and
290 deletions
+620
-290
drivers/Makefile
drivers/Makefile
+3
-1
drivers/input/joydev.c
drivers/input/joydev.c
+4
-2
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/atkbd.c
+130
-48
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/psmouse-base.c
+145
-87
drivers/input/mouse/psmouse.h
drivers/input/mouse/psmouse.h
+14
-8
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics.c
+12
-14
drivers/input/mousedev.c
drivers/input/mousedev.c
+41
-10
drivers/input/serio/ct82c710.c
drivers/input/serio/ct82c710.c
+28
-22
drivers/input/serio/i8042.c
drivers/input/serio/i8042.c
+76
-44
drivers/input/serio/maceps2.c
drivers/input/serio/maceps2.c
+14
-5
drivers/input/serio/q40kbd.c
drivers/input/serio/q40kbd.c
+14
-4
drivers/input/serio/rpckbd.c
drivers/input/serio/rpckbd.c
+15
-5
drivers/input/serio/serio.c
drivers/input/serio/serio.c
+84
-27
drivers/input/tsdev.c
drivers/input/tsdev.c
+5
-5
drivers/serial/sunzilog.c
drivers/serial/sunzilog.c
+13
-5
include/linux/serio.h
include/linux/serio.h
+22
-3
No files found.
drivers/Makefile
View file @
c5ec0513
...
@@ -15,6 +15,9 @@ obj-$(CONFIG_PNP) += pnp/
...
@@ -15,6 +15,9 @@ obj-$(CONFIG_PNP) += pnp/
# char/ comes before serial/ etc so that the VT console is the boot-time
# char/ comes before serial/ etc so that the VT console is the boot-time
# default.
# default.
obj-y
+=
char/
obj-y
+=
char/
# 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/ net/ media/
obj-y
+=
base/ block/ misc/ net/ media/
...
@@ -37,7 +40,6 @@ obj-$(CONFIG_PARIDE) += block/paride/
...
@@ -37,7 +40,6 @@ obj-$(CONFIG_PARIDE) += block/paride/
obj-$(CONFIG_TC)
+=
tc/
obj-$(CONFIG_TC)
+=
tc/
obj-$(CONFIG_USB)
+=
usb/
obj-$(CONFIG_USB)
+=
usb/
obj-$(CONFIG_USB_GADGET)
+=
usb/gadget/
obj-$(CONFIG_USB_GADGET)
+=
usb/gadget/
obj-$(CONFIG_SERIO)
+=
input/serio/
obj-$(CONFIG_INPUT)
+=
input/
obj-$(CONFIG_INPUT)
+=
input/
obj-$(CONFIG_GAMEPORT)
+=
input/gameport/
obj-$(CONFIG_GAMEPORT)
+=
input/gameport/
obj-$(CONFIG_I2O)
+=
message/
obj-$(CONFIG_I2O)
+=
message/
...
...
drivers/input/joydev.c
View file @
c5ec0513
...
@@ -232,8 +232,10 @@ static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, lo
...
@@ -232,8 +232,10 @@ static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, lo
&&
list
->
head
==
list
->
tail
&&
(
file
->
f_flags
&
O_NONBLOCK
))
&&
list
->
head
==
list
->
tail
&&
(
file
->
f_flags
&
O_NONBLOCK
))
return
-
EAGAIN
;
return
-
EAGAIN
;
retval
=
wait_event_interruptible
(
list
->
joydev
->
wait
,
list
->
joydev
->
exist
retval
=
wait_event_interruptible
(
list
->
joydev
->
wait
,
&&
(
list
->
startup
<
joydev
->
nabs
+
joydev
->
nkey
||
list
->
head
!=
list
->
tail
));
!
list
->
joydev
->
exist
||
list
->
startup
<
joydev
->
nabs
+
joydev
->
nkey
||
list
->
head
!=
list
->
tail
);
if
(
retval
)
if
(
retval
)
return
retval
;
return
retval
;
...
...
drivers/input/keyboard/atkbd.c
View file @
c5ec0513
...
@@ -173,8 +173,7 @@ static unsigned char atkbd_scroll_keys[5][2] = {
...
@@ -173,8 +173,7 @@ static unsigned char atkbd_scroll_keys[5][2] = {
#define ATKBD_FLAG_ACK 0
/* Waiting for ACK/NAK */
#define ATKBD_FLAG_ACK 0
/* Waiting for ACK/NAK */
#define ATKBD_FLAG_CMD 1
/* Waiting for command to finish */
#define ATKBD_FLAG_CMD 1
/* Waiting for command to finish */
#define ATKBD_FLAG_CMD1 2
/* First byte of command response */
#define ATKBD_FLAG_CMD1 2
/* First byte of command response */
#define ATKBD_FLAG_ID 3
/* First byte is not keyboard ID */
#define ATKBD_FLAG_ENABLED 3
/* Waining for init to finish */
#define ATKBD_FLAG_ENABLED 4
/* Waining for init to finish */
/*
/*
* The atkbd control structure
* The atkbd control structure
...
@@ -210,10 +209,25 @@ struct atkbd {
...
@@ -210,10 +209,25 @@ struct atkbd {
unsigned
int
last
;
unsigned
int
last
;
unsigned
long
time
;
unsigned
long
time
;
/* Ensures that only one command is executing at a time */
struct
semaphore
cmd_sem
;
/* Used to signal completion from interrupt handler */
wait_queue_head_t
wait
;
/* Flags */
/* Flags */
unsigned
long
flags
;
unsigned
long
flags
;
};
};
/* Work structure to schedule execution of a command */
struct
atkbd_work
{
struct
work_struct
work
;
struct
atkbd
*
atkbd
;
int
command
;
unsigned
char
param
[
0
];
};
static
void
atkbd_report_key
(
struct
input_dev
*
dev
,
struct
pt_regs
*
regs
,
int
code
,
int
value
)
static
void
atkbd_report_key
(
struct
input_dev
*
dev
,
struct
pt_regs
*
regs
,
int
code
,
int
value
)
{
{
input_regs
(
dev
,
regs
);
input_regs
(
dev
,
regs
);
...
@@ -254,37 +268,38 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
...
@@ -254,37 +268,38 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
atkbd
->
resend
=
0
;
atkbd
->
resend
=
0
;
#endif
#endif
if
(
test_bit
(
ATKBD_FLAG_ACK
,
&
atkbd
->
flags
))
if
(
test_bit
(
ATKBD_FLAG_ACK
,
&
atkbd
->
flags
))
{
switch
(
code
)
{
switch
(
code
)
{
case
ATKBD_RET_ACK
:
case
ATKBD_RET_ACK
:
atkbd
->
nak
=
0
;
atkbd
->
nak
=
0
;
if
(
atkbd
->
cmdcnt
)
{
if
(
atkbd
->
cmdcnt
)
{
set_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
);
set_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
);
set_bit
(
ATKBD_FLAG_CMD1
,
&
atkbd
->
flags
);
set_bit
(
ATKBD_FLAG_CMD1
,
&
atkbd
->
flags
);
set_bit
(
ATKBD_FLAG_ID
,
&
atkbd
->
flags
);
}
}
clear_bit
(
ATKBD_FLAG_ACK
,
&
atkbd
->
flags
);
clear_bit
(
ATKBD_FLAG_ACK
,
&
atkbd
->
flags
);
goto
out
;
wake_up_interruptible
(
&
atkbd
->
wait
);
break
;
case
ATKBD_RET_NAK
:
case
ATKBD_RET_NAK
:
atkbd
->
nak
=
1
;
atkbd
->
nak
=
1
;
clear_bit
(
ATKBD_FLAG_ACK
,
&
atkbd
->
flags
);
clear_bit
(
ATKBD_FLAG_ACK
,
&
atkbd
->
flags
);
goto
out
;
wake_up_interruptible
(
&
atkbd
->
wait
);
break
;
}
}
goto
out
;
}
if
(
test_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
))
{
if
(
test_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
))
{
atkbd
->
cmdcnt
--
;
if
(
atkbd
->
cmdcnt
)
atkbd
->
cmdbuf
[
atkbd
->
cmdcnt
]
=
code
;
atkbd
->
cmdbuf
[
--
atkbd
->
cmdcnt
]
=
code
;
if
(
atkbd
->
cmdcnt
==
1
)
{
if
(
test_and_clear_bit
(
ATKBD_FLAG_CMD1
,
&
atkbd
->
flags
)
&&
atkbd
->
cmdcnt
)
if
(
code
!=
0xab
&&
code
!=
0xac
)
wake_up_interruptible
(
&
atkbd
->
wait
);
clear_bit
(
ATKBD_FLAG_ID
,
&
atkbd
->
flags
);
clear_bit
(
ATKBD_FLAG_CMD1
,
&
atkbd
->
flags
);
}
if
(
!
atkbd
->
cmdcnt
)
if
(
!
atkbd
->
cmdcnt
)
{
clear_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
);
clear_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
);
wake_up_interruptible
(
&
atkbd
->
wait
);
}
goto
out
;
goto
out
;
}
}
...
@@ -417,87 +432,147 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
...
@@ -417,87 +432,147 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
* acknowledge. It doesn't handle resends according to the keyboard
* acknowledge. It doesn't handle resends according to the keyboard
* protocol specs, because if these are needed, the keyboard needs
* protocol specs, because if these are needed, the keyboard needs
* replacement anyway, and they only make a mess in the protocol.
* replacement anyway, and they only make a mess in the protocol.
*
* atkbd_sendbyte() can only be called from a process context
*/
*/
static
int
atkbd_sendbyte
(
struct
atkbd
*
atkbd
,
unsigned
char
byte
)
static
int
atkbd_sendbyte
(
struct
atkbd
*
atkbd
,
unsigned
char
byte
)
{
{
int
timeout
=
200000
;
/* 200 msec */
#ifdef ATKBD_DEBUG
#ifdef ATKBD_DEBUG
printk
(
KERN_DEBUG
"atkbd.c: Sent: %02x
\n
"
,
byte
);
printk
(
KERN_DEBUG
"atkbd.c: Sent: %02x
\n
"
,
byte
);
#endif
#endif
atkbd
->
nak
=
1
;
set_bit
(
ATKBD_FLAG_ACK
,
&
atkbd
->
flags
);
set_bit
(
ATKBD_FLAG_ACK
,
&
atkbd
->
flags
);
clear_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
);
if
(
serio_write
(
atkbd
->
serio
,
byte
))
return
-
1
;
while
(
test_bit
(
ATKBD_FLAG_ACK
,
&
atkbd
->
flags
)
&&
timeout
--
)
udelay
(
1
);
clear_bit
(
ATKBD_FLAG_ACK
,
&
atkbd
->
flags
);
if
(
serio_write
(
atkbd
->
serio
,
byte
)
==
0
)
wait_event_interruptible_timeout
(
atkbd
->
wait
,
!
test_bit
(
ATKBD_FLAG_ACK
,
&
atkbd
->
flags
),
msecs_to_jiffies
(
200
));
clear_bit
(
ATKBD_FLAG_ACK
,
&
atkbd
->
flags
);
return
-
atkbd
->
nak
;
return
-
atkbd
->
nak
;
}
}
/*
/*
* atkbd_command() sends a command, and its parameters to the keyboard,
* atkbd_command() sends a command, and its parameters to the keyboard,
* then waits for the response and puts it in the param array.
* then waits for the response and puts it in the param array.
*
* atkbd_command() can only be called from a process context
*/
*/
static
int
atkbd_command
(
struct
atkbd
*
atkbd
,
unsigned
char
*
param
,
int
command
)
static
int
atkbd_command
(
struct
atkbd
*
atkbd
,
unsigned
char
*
param
,
int
command
)
{
{
int
timeout
=
500000
;
/* 500 msec */
int
timeout
;
int
send
=
(
command
>>
12
)
&
0xf
;
int
send
=
(
command
>>
12
)
&
0xf
;
int
receive
=
(
command
>>
8
)
&
0xf
;
int
receive
=
(
command
>>
8
)
&
0xf
;
int
rc
=
-
1
;
int
i
;
int
i
;
atkbd
->
cmdcnt
=
receive
;
timeout
=
msecs_to_jiffies
(
command
==
ATKBD_CMD_RESET_BAT
?
4000
:
500
)
;
if
(
command
==
ATKBD_CMD_RESET_BAT
)
down
(
&
atkbd
->
cmd_sem
);
timeout
=
4000000
;
/* 4 sec */
clear_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
);
if
(
receive
&&
param
)
if
(
receive
&&
param
)
for
(
i
=
0
;
i
<
receive
;
i
++
)
for
(
i
=
0
;
i
<
receive
;
i
++
)
atkbd
->
cmdbuf
[(
receive
-
1
)
-
i
]
=
param
[
i
];
atkbd
->
cmdbuf
[(
receive
-
1
)
-
i
]
=
param
[
i
];
atkbd
->
cmdcnt
=
receive
;
if
(
command
&
0xff
)
if
(
command
&
0xff
)
if
(
atkbd_sendbyte
(
atkbd
,
command
&
0xff
))
if
(
atkbd_sendbyte
(
atkbd
,
command
&
0xff
))
return
-
1
;
goto
out
;
for
(
i
=
0
;
i
<
send
;
i
++
)
for
(
i
=
0
;
i
<
send
;
i
++
)
if
(
atkbd_sendbyte
(
atkbd
,
param
[
i
]))
if
(
atkbd_sendbyte
(
atkbd
,
param
[
i
]))
return
-
1
;
goto
out
;
while
(
test_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
)
&&
timeout
--
)
{
timeout
=
wait_event_interruptible_timeout
(
atkbd
->
wait
,
!
test_bit
(
ATKBD_FLAG_CMD1
,
&
atkbd
->
flags
),
timeout
);
if
(
!
test_bit
(
ATKBD_FLAG_CMD1
,
&
atkbd
->
flags
))
{
if
(
atkbd
->
cmdcnt
&&
timeout
>
0
)
{
if
(
command
==
ATKBD_CMD_RESET_BAT
&&
jiffies_to_msecs
(
timeout
)
>
100
)
if
(
command
==
ATKBD_CMD_RESET_BAT
&&
timeout
>
100000
)
timeout
=
msecs_to_jiffies
(
100
);
timeout
=
100000
;
if
(
command
==
ATKBD_CMD_GETID
&&
!
test_bit
(
ATKBD_FLAG_ID
,
&
atkbd
->
flags
))
{
if
(
command
==
ATKBD_CMD_GETID
&&
clear_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
);
atkbd
->
cmdbuf
[
receive
-
1
]
!=
0xab
&&
atkbd
->
cmdbuf
[
receive
-
1
]
!=
0xac
)
{
atkbd
->
cmdcnt
=
0
;
/*
break
;
* Device behind the port is not a keyboard
}
* so we don't need to wait for the 2nd byte
* of ID response.
*/
clear_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
);
atkbd
->
cmdcnt
=
0
;
}
}
udelay
(
1
);
wait_event_interruptible_timeout
(
atkbd
->
wait
,
!
test_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
),
timeout
);
}
}
clear_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
);
if
(
param
)
if
(
param
)
for
(
i
=
0
;
i
<
receive
;
i
++
)
for
(
i
=
0
;
i
<
receive
;
i
++
)
param
[
i
]
=
atkbd
->
cmdbuf
[(
receive
-
1
)
-
i
];
param
[
i
]
=
atkbd
->
cmdbuf
[(
receive
-
1
)
-
i
];
if
(
command
==
ATKBD_CMD_RESET_BAT
&&
atkbd
->
cmdcnt
==
1
)
if
(
atkbd
->
cmdcnt
&&
(
command
!=
ATKBD_CMD_RESET_BAT
||
atkbd
->
cmdcnt
!=
1
))
return
0
;
goto
out
;
rc
=
0
;
out:
clear_bit
(
ATKBD_FLAG_CMD
,
&
atkbd
->
flags
);
clear_bit
(
ATKBD_FLAG_CMD1
,
&
atkbd
->
flags
);
up
(
&
atkbd
->
cmd_sem
);
return
rc
;
}
/*
* atkbd_execute_scheduled_command() sends a command, previously scheduled by
* atkbd_schedule_command(), to the keyboard.
*/
static
void
atkbd_execute_scheduled_command
(
void
*
data
)
{
struct
atkbd_work
*
atkbd_work
=
data
;
atkbd_command
(
atkbd_work
->
atkbd
,
atkbd_work
->
param
,
atkbd_work
->
command
);
kfree
(
atkbd_work
);
}
/*
* atkbd_schedule_command() allows to schedule delayed execution of a keyboard
* command and can be used to issue a command from an interrupt or softirq
* context.
*/
static
int
atkbd_schedule_command
(
struct
atkbd
*
atkbd
,
unsigned
char
*
param
,
int
command
)
{
struct
atkbd_work
*
atkbd_work
;
int
send
=
(
command
>>
12
)
&
0xf
;
int
receive
=
(
command
>>
8
)
&
0xf
;
if
(
!
test_bit
(
ATKBD_FLAG_ENABLED
,
&
atkbd
->
flags
))
return
-
1
;
if
(
atkbd
->
cmdcnt
)
if
(
!
(
atkbd_work
=
kmalloc
(
sizeof
(
struct
atkbd_work
)
+
max
(
send
,
receive
),
GFP_ATOMIC
))
)
return
-
1
;
return
-
1
;
memset
(
atkbd_work
,
0
,
sizeof
(
struct
atkbd_work
));
atkbd_work
->
atkbd
=
atkbd
;
atkbd_work
->
command
=
command
;
memcpy
(
atkbd_work
->
param
,
param
,
send
);
INIT_WORK
(
&
atkbd_work
->
work
,
atkbd_execute_scheduled_command
,
atkbd_work
);
if
(
!
schedule_work
(
&
atkbd_work
->
work
))
{
kfree
(
atkbd_work
);
return
-
1
;
}
return
0
;
return
0
;
}
}
/*
/*
* Event callback from the input module. Events that change the state of
* Event callback from the input module. Events that change the state of
* the hardware are processed here.
* the hardware are processed here.
...
@@ -524,7 +599,7 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
...
@@ -524,7 +599,7 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
param
[
0
]
=
(
test_bit
(
LED_SCROLLL
,
dev
->
led
)
?
1
:
0
)
param
[
0
]
=
(
test_bit
(
LED_SCROLLL
,
dev
->
led
)
?
1
:
0
)
|
(
test_bit
(
LED_NUML
,
dev
->
led
)
?
2
:
0
)
|
(
test_bit
(
LED_NUML
,
dev
->
led
)
?
2
:
0
)
|
(
test_bit
(
LED_CAPSL
,
dev
->
led
)
?
4
:
0
);
|
(
test_bit
(
LED_CAPSL
,
dev
->
led
)
?
4
:
0
);
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_SETLEDS
);
atkbd_
schedule_
command
(
atkbd
,
param
,
ATKBD_CMD_SETLEDS
);
if
(
atkbd
->
extra
)
{
if
(
atkbd
->
extra
)
{
param
[
0
]
=
0
;
param
[
0
]
=
0
;
...
@@ -533,7 +608,7 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
...
@@ -533,7 +608,7 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
|
(
test_bit
(
LED_SUSPEND
,
dev
->
led
)
?
0x04
:
0
)
|
(
test_bit
(
LED_SUSPEND
,
dev
->
led
)
?
0x04
:
0
)
|
(
test_bit
(
LED_MISC
,
dev
->
led
)
?
0x10
:
0
)
|
(
test_bit
(
LED_MISC
,
dev
->
led
)
?
0x10
:
0
)
|
(
test_bit
(
LED_MUTE
,
dev
->
led
)
?
0x20
:
0
);
|
(
test_bit
(
LED_MUTE
,
dev
->
led
)
?
0x20
:
0
);
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_EX_SETLEDS
);
atkbd_
schedule_
command
(
atkbd
,
param
,
ATKBD_CMD_EX_SETLEDS
);
}
}
return
0
;
return
0
;
...
@@ -549,7 +624,7 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
...
@@ -549,7 +624,7 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
dev
->
rep
[
REP_PERIOD
]
=
period
[
i
];
dev
->
rep
[
REP_PERIOD
]
=
period
[
i
];
dev
->
rep
[
REP_DELAY
]
=
delay
[
j
];
dev
->
rep
[
REP_DELAY
]
=
delay
[
j
];
param
[
0
]
=
i
|
(
j
<<
5
);
param
[
0
]
=
i
|
(
j
<<
5
);
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_SETREP
);
atkbd_
schedule_
command
(
atkbd
,
param
,
ATKBD_CMD_SETREP
);
return
0
;
return
0
;
}
}
...
@@ -721,7 +796,11 @@ static void atkbd_cleanup(struct serio *serio)
...
@@ -721,7 +796,11 @@ static void atkbd_cleanup(struct serio *serio)
static
void
atkbd_disconnect
(
struct
serio
*
serio
)
static
void
atkbd_disconnect
(
struct
serio
*
serio
)
{
{
struct
atkbd
*
atkbd
=
serio
->
private
;
struct
atkbd
*
atkbd
=
serio
->
private
;
clear_bit
(
ATKBD_FLAG_ENABLED
,
&
atkbd
->
flags
);
clear_bit
(
ATKBD_FLAG_ENABLED
,
&
atkbd
->
flags
);
synchronize_kernel
();
flush_scheduled_work
();
input_unregister_device
(
&
atkbd
->
dev
);
input_unregister_device
(
&
atkbd
->
dev
);
serio_close
(
serio
);
serio_close
(
serio
);
kfree
(
atkbd
);
kfree
(
atkbd
);
...
@@ -743,6 +822,9 @@ static void atkbd_connect(struct serio *serio, struct serio_driver *drv)
...
@@ -743,6 +822,9 @@ static void atkbd_connect(struct serio *serio, struct serio_driver *drv)
return
;
return
;
memset
(
atkbd
,
0
,
sizeof
(
struct
atkbd
));
memset
(
atkbd
,
0
,
sizeof
(
struct
atkbd
));
init_MUTEX
(
&
atkbd
->
cmd_sem
);
init_waitqueue_head
(
&
atkbd
->
wait
);
switch
(
serio
->
type
&
SERIO_TYPE
)
{
switch
(
serio
->
type
&
SERIO_TYPE
)
{
case
SERIO_8042_XL
:
case
SERIO_8042_XL
:
...
...
drivers/input/mouse/psmouse-base.c
View file @
c5ec0513
...
@@ -147,45 +147,64 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
...
@@ -147,45 +147,64 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
psmouse
->
nak
=
1
;
psmouse
->
nak
=
1
;
clear_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
clear_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
wake_up_interruptible
(
&
psmouse
->
wait
);
goto
out
;
goto
out
;
}
}
if
(
test_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
))
if
(
test_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
))
{
switch
(
data
)
{
switch
(
data
)
{
case
PSMOUSE_RET_ACK
:
case
PSMOUSE_RET_ACK
:
psmouse
->
nak
=
0
;
psmouse
->
nak
=
0
;
clear_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
goto
out
;
break
;
break
;
case
PSMOUSE_RET_NAK
:
case
PSMOUSE_RET_NAK
:
psmouse
->
nak
=
1
;
psmouse
->
nak
=
1
;
clear_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
break
;
goto
out
;
/*
* Workaround for mice which don't ACK the Get ID command.
* These are valid mouse IDs that we recognize.
*/
case
0x00
:
case
0x03
:
case
0x04
:
if
(
test_bit
(
PSMOUSE_FLAG_WAITID
,
&
psmouse
->
flags
))
{
psmouse
->
nak
=
0
;
break
;
}
/* Fall through */
default:
default:
psmouse
->
nak
=
0
;
/* Workaround for mice which don't ACK the Get ID command */
goto
out
;
clear_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
}
if
(
!
test_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
))
goto
out
;
if
(
!
psmouse
->
nak
&&
psmouse
->
cmdcnt
)
{
set_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
set_bit
(
PSMOUSE_FLAG_CMD1
,
&
psmouse
->
flags
);
}
}
clear_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
wake_up_interruptible
(
&
psmouse
->
wait
);
if
(
test_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
))
{
if
(
data
==
PSMOUSE_RET_ACK
||
data
==
PSMOUSE_RET_NAK
)
goto
out
;
}
psmouse
->
cmdcnt
--
;
if
(
test_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
))
{
psmouse
->
cmdbuf
[
psmouse
->
cmdcnt
]
=
data
;
if
(
psmouse
->
cmdcnt
)
psmouse
->
cmdbuf
[
--
psmouse
->
cmdcnt
]
=
data
;
if
(
psmouse
->
cmdcnt
==
1
)
{
if
(
test_and_clear_bit
(
PSMOUSE_FLAG_CMD1
,
&
psmouse
->
flags
)
&&
psmouse
->
cmdcnt
)
if
(
data
!=
0xab
&&
data
!=
0xac
)
wake_up_interruptible
(
&
psmouse
->
wait
);
clear_bit
(
PSMOUSE_FLAG_ID
,
&
psmouse
->
flags
);
clear_bit
(
PSMOUSE_FLAG_CMD1
,
&
psmouse
->
flags
);
}
if
(
!
psmouse
->
cmdcnt
)
if
(
!
psmouse
->
cmdcnt
)
{
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
wake_up_interruptible
(
&
psmouse
->
wait
);
}
goto
out
;
goto
out
;
}
}
if
(
psmouse
->
state
==
PSMOUSE_INITIALIZING
)
goto
out
;
if
(
psmouse
->
state
==
PSMOUSE_ACTIVATED
&&
if
(
psmouse
->
state
==
PSMOUSE_ACTIVATED
&&
psmouse
->
pktcnt
&&
time_after
(
jiffies
,
psmouse
->
last
+
HZ
/
2
))
{
psmouse
->
pktcnt
&&
time_after
(
jiffies
,
psmouse
->
last
+
HZ
/
2
))
{
printk
(
KERN_WARNING
"psmouse.c: %s at %s lost synchronization, throwing %d bytes away.
\n
"
,
printk
(
KERN_WARNING
"psmouse.c: %s at %s lost synchronization, throwing %d bytes away.
\n
"
,
...
@@ -251,90 +270,95 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
...
@@ -251,90 +270,95 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
* psmouse_sendbyte() sends a byte to the mouse, and waits for acknowledge.
* psmouse_sendbyte() sends a byte to the mouse, and waits for acknowledge.
* It doesn't handle retransmission, though it could - because when there would
* It doesn't handle retransmission, though it could - because when there would
* be need for retransmissions, the mouse has to be replaced anyway.
* be need for retransmissions, the mouse has to be replaced anyway.
*
* psmouse_sendbyte() can only be called from a process context
*/
*/
static
int
psmouse_sendbyte
(
struct
psmouse
*
psmouse
,
unsigned
char
byte
)
static
int
psmouse_sendbyte
(
struct
psmouse
*
psmouse
,
unsigned
char
byte
)
{
{
int
timeout
=
200000
;
/* 200 msec */
psmouse
->
nak
=
1
;
set_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
set_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
if
(
serio_write
(
psmouse
->
serio
,
byte
))
return
-
1
;
while
(
test_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
)
&&
timeout
--
)
udelay
(
1
);
clear_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
if
(
serio_write
(
psmouse
->
serio
,
byte
)
==
0
)
wait_event_interruptible_timeout
(
psmouse
->
wait
,
!
test_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
),
msecs_to_jiffies
(
200
));
clear_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
return
-
psmouse
->
nak
;
return
-
psmouse
->
nak
;
}
}
/*
/*
* psmouse_command() sends a command and its parameters to the mouse,
* psmouse_command() sends a command and its parameters to the mouse,
* then waits for the response and puts it in the param array.
* then waits for the response and puts it in the param array.
*
* psmouse_command() can only be called from a process context
*/
*/
int
psmouse_command
(
struct
psmouse
*
psmouse
,
unsigned
char
*
param
,
int
command
)
int
psmouse_command
(
struct
psmouse
*
psmouse
,
unsigned
char
*
param
,
int
command
)
{
{
int
timeout
=
500000
;
/* 500 msec */
int
timeout
;
int
send
=
(
command
>>
12
)
&
0xf
;
int
send
=
(
command
>>
12
)
&
0xf
;
int
receive
=
(
command
>>
8
)
&
0xf
;
int
receive
=
(
command
>>
8
)
&
0xf
;
int
rc
=
-
1
;
int
i
;
int
i
;
psmouse
->
cmdcnt
=
receive
;
timeout
=
msecs_to_jiffies
(
command
==
PSMOUSE_CMD_RESET_BAT
?
4000
:
500
)
;
if
(
command
==
PSMOUSE_CMD_RESET_BAT
)
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
timeout
=
4000000
;
/* 4 sec */
if
(
command
==
PSMOUSE_CMD_GETID
)
set_bit
(
PSMOUSE_FLAG_WAITID
,
&
psmouse
->
flags
);
if
(
receive
&&
param
)
if
(
receive
&&
param
)
for
(
i
=
0
;
i
<
receive
;
i
++
)
for
(
i
=
0
;
i
<
receive
;
i
++
)
psmouse
->
cmdbuf
[(
receive
-
1
)
-
i
]
=
param
[
i
];
psmouse
->
cmdbuf
[(
receive
-
1
)
-
i
]
=
param
[
i
];
if
(
receive
)
{
psmouse
->
cmdcnt
=
receive
;
set_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
set_bit
(
PSMOUSE_FLAG_CMD1
,
&
psmouse
->
flags
);
set_bit
(
PSMOUSE_FLAG_ID
,
&
psmouse
->
flags
);
}
if
(
command
&
0xff
)
if
(
command
&
0xff
)
if
(
psmouse_sendbyte
(
psmouse
,
command
&
0xff
))
{
if
(
psmouse_sendbyte
(
psmouse
,
command
&
0xff
))
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
goto
out
;
return
-
1
;
}
for
(
i
=
0
;
i
<
send
;
i
++
)
for
(
i
=
0
;
i
<
send
;
i
++
)
if
(
psmouse_sendbyte
(
psmouse
,
param
[
i
]))
{
if
(
psmouse_sendbyte
(
psmouse
,
param
[
i
]))
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
goto
out
;
return
-
1
;
}
while
(
test_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
)
&&
timeout
--
)
{
timeout
=
wait_event_interruptible_timeout
(
psmouse
->
wait
,
!
test_bit
(
PSMOUSE_FLAG_CMD1
,
&
psmouse
->
flags
),
timeout
);
if
(
!
test_bit
(
PSMOUSE_FLAG_CMD1
,
&
psmouse
->
flags
))
{
if
(
psmouse
->
cmdcnt
&&
timeout
>
0
)
{
if
(
command
==
PSMOUSE_CMD_RESET_BAT
&&
jiffies_to_msecs
(
timeout
)
>
100
)
if
(
command
==
PSMOUSE_CMD_RESET_BAT
&&
timeout
>
100000
)
timeout
=
msecs_to_jiffies
(
100
);
timeout
=
100000
;
if
(
command
==
PSMOUSE_CMD_GETID
&&
!
test_bit
(
PSMOUSE_FLAG_ID
,
&
psmouse
->
flags
))
{
if
(
command
==
PSMOUSE_CMD_GETID
&&
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
psmouse
->
cmdbuf
[
receive
-
1
]
!=
0xab
&&
psmouse
->
cmdbuf
[
receive
-
1
]
!=
0xac
)
{
psmouse
->
cmdcnt
=
0
;
/*
break
;
* Device behind the port is not a keyboard
}
* so we don't need to wait for the 2nd byte
* of ID response.
*/
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
psmouse
->
cmdcnt
=
0
;
}
}
udelay
(
1
);
wait_event_interruptible_timeout
(
psmouse
->
wait
,
!
test_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
),
timeout
);
}
}
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
if
(
param
)
if
(
param
)
for
(
i
=
0
;
i
<
receive
;
i
++
)
for
(
i
=
0
;
i
<
receive
;
i
++
)
param
[
i
]
=
psmouse
->
cmdbuf
[(
receive
-
1
)
-
i
];
param
[
i
]
=
psmouse
->
cmdbuf
[(
receive
-
1
)
-
i
];
if
(
command
==
PSMOUSE_CMD_RESET_BAT
&&
psmouse
->
cmdcnt
==
1
)
if
(
psmouse
->
cmdcnt
&&
(
command
!=
PSMOUSE_CMD_RESET_BAT
||
psmouse
->
cmdcnt
!=
1
)
)
return
0
;
goto
out
;
if
(
psmouse
->
cmdcnt
)
rc
=
0
;
return
-
1
;
return
0
;
out:
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
clear_bit
(
PSMOUSE_FLAG_CMD1
,
&
psmouse
->
flags
);
clear_bit
(
PSMOUSE_FLAG_WAITID
,
&
psmouse
->
flags
);
return
rc
;
}
}
/*
/*
...
@@ -625,6 +649,21 @@ static void psmouse_initialize(struct psmouse *psmouse)
...
@@ -625,6 +649,21 @@ static void psmouse_initialize(struct psmouse *psmouse)
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETSTREAM
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETSTREAM
);
}
}
/*
* psmouse_set_state() sets new psmouse state and resets all flags and
* counters while holding serio lock so fighting with interrupt handler
* is not a concern.
*/
static
void
psmouse_set_state
(
struct
psmouse
*
psmouse
,
enum
psmouse_state
new_state
)
{
serio_pause_rx
(
psmouse
->
serio
);
psmouse
->
state
=
new_state
;
psmouse
->
pktcnt
=
psmouse
->
cmdcnt
=
psmouse
->
out_of_sync
=
0
;
psmouse
->
flags
=
0
;
serio_continue_rx
(
psmouse
->
serio
);
}
/*
/*
* psmouse_activate() enables the mouse so that we get motion reports from it.
* psmouse_activate() enables the mouse so that we get motion reports from it.
*/
*/
...
@@ -634,9 +673,24 @@ static void psmouse_activate(struct psmouse *psmouse)
...
@@ -634,9 +673,24 @@ static void psmouse_activate(struct psmouse *psmouse)
if
(
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_ENABLE
))
if
(
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_ENABLE
))
printk
(
KERN_WARNING
"psmouse.c: Failed to enable mouse on %s
\n
"
,
psmouse
->
serio
->
phys
);
printk
(
KERN_WARNING
"psmouse.c: Failed to enable mouse on %s
\n
"
,
psmouse
->
serio
->
phys
);
psmouse
->
state
=
PSMOUSE_ACTIVATED
;
psmouse
_set_state
(
psmouse
,
PSMOUSE_ACTIVATED
)
;
}
}
/*
* psmouse_deactivate() puts the mouse into poll mode so that we don't get motion
* reports from it unless we explicitely request it.
*/
static
void
psmouse_deactivate
(
struct
psmouse
*
psmouse
)
{
if
(
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_DISABLE
))
printk
(
KERN_WARNING
"psmouse.c: Failed to deactivate mouse on %s
\n
"
,
psmouse
->
serio
->
phys
);
psmouse_set_state
(
psmouse
,
PSMOUSE_CMD_MODE
);
}
/*
/*
* psmouse_cleanup() resets the mouse into power-on state.
* psmouse_cleanup() resets the mouse into power-on state.
*/
*/
...
@@ -657,7 +711,7 @@ static void psmouse_disconnect(struct serio *serio)
...
@@ -657,7 +711,7 @@ static void psmouse_disconnect(struct serio *serio)
struct
psmouse
*
psmouse
,
*
parent
;
struct
psmouse
*
psmouse
,
*
parent
;
psmouse
=
serio
->
private
;
psmouse
=
serio
->
private
;
psmouse
->
state
=
PSMOUSE_CMD_MODE
;
psmouse
_set_state
(
psmouse
,
PSMOUSE_CMD_MODE
)
;
if
(
serio
->
parent
&&
(
serio
->
type
&
SERIO_TYPE
)
==
SERIO_PS_PSTHRU
)
{
if
(
serio
->
parent
&&
(
serio
->
type
&
SERIO_TYPE
)
==
SERIO_PS_PSTHRU
)
{
parent
=
serio
->
parent
->
private
;
parent
=
serio
->
parent
->
private
;
...
@@ -668,7 +722,7 @@ static void psmouse_disconnect(struct serio *serio)
...
@@ -668,7 +722,7 @@ static void psmouse_disconnect(struct serio *serio)
if
(
psmouse
->
disconnect
)
if
(
psmouse
->
disconnect
)
psmouse
->
disconnect
(
psmouse
);
psmouse
->
disconnect
(
psmouse
);
psmouse
->
state
=
PSMOUSE_IGNORE
;
psmouse
_set_state
(
psmouse
,
PSMOUSE_IGNORE
)
;
input_unregister_device
(
&
psmouse
->
dev
);
input_unregister_device
(
&
psmouse
->
dev
);
serio_close
(
serio
);
serio_close
(
serio
);
...
@@ -687,21 +741,28 @@ static void psmouse_connect(struct serio *serio, struct serio_driver *drv)
...
@@ -687,21 +741,28 @@ static void psmouse_connect(struct serio *serio, struct serio_driver *drv)
(
serio
->
type
&
SERIO_TYPE
)
!=
SERIO_PS_PSTHRU
)
(
serio
->
type
&
SERIO_TYPE
)
!=
SERIO_PS_PSTHRU
)
return
;
return
;
if
(
serio
->
parent
&&
(
serio
->
type
&
SERIO_TYPE
)
==
SERIO_PS_PSTHRU
)
/*
* If this is a pass-through port deactivate parent so the device
* connected to this port can be successfully identified
*/
if
(
serio
->
parent
&&
(
serio
->
type
&
SERIO_TYPE
)
==
SERIO_PS_PSTHRU
)
{
parent
=
serio
->
parent
->
private
;
parent
=
serio
->
parent
->
private
;
psmouse_deactivate
(
parent
);
}
if
(
!
(
psmouse
=
kmalloc
(
sizeof
(
struct
psmouse
),
GFP_KERNEL
)))
if
(
!
(
psmouse
=
kmalloc
(
sizeof
(
struct
psmouse
),
GFP_KERNEL
)))
goto
out
;
goto
out
;
memset
(
psmouse
,
0
,
sizeof
(
struct
psmouse
));
memset
(
psmouse
,
0
,
sizeof
(
struct
psmouse
));
init_waitqueue_head
(
&
psmouse
->
wait
);
init_input_dev
(
&
psmouse
->
dev
);
init_input_dev
(
&
psmouse
->
dev
);
psmouse
->
dev
.
evbit
[
0
]
=
BIT
(
EV_KEY
)
|
BIT
(
EV_REL
);
psmouse
->
dev
.
evbit
[
0
]
=
BIT
(
EV_KEY
)
|
BIT
(
EV_REL
);
psmouse
->
dev
.
keybit
[
LONG
(
BTN_MOUSE
)]
=
BIT
(
BTN_LEFT
)
|
BIT
(
BTN_MIDDLE
)
|
BIT
(
BTN_RIGHT
);
psmouse
->
dev
.
keybit
[
LONG
(
BTN_MOUSE
)]
=
BIT
(
BTN_LEFT
)
|
BIT
(
BTN_MIDDLE
)
|
BIT
(
BTN_RIGHT
);
psmouse
->
dev
.
relbit
[
0
]
=
BIT
(
REL_X
)
|
BIT
(
REL_Y
);
psmouse
->
dev
.
relbit
[
0
]
=
BIT
(
REL_X
)
|
BIT
(
REL_Y
);
psmouse
->
state
=
PSMOUSE_CMD_MODE
;
psmouse
->
serio
=
serio
;
psmouse
->
serio
=
serio
;
psmouse
->
dev
.
private
=
psmouse
;
psmouse
->
dev
.
private
=
psmouse
;
psmouse_set_state
(
psmouse
,
PSMOUSE_INITIALIZING
);
serio
->
private
=
psmouse
;
serio
->
private
=
psmouse
;
if
(
serio_open
(
serio
,
drv
))
{
if
(
serio_open
(
serio
,
drv
))
{
...
@@ -741,26 +802,22 @@ static void psmouse_connect(struct serio *serio, struct serio_driver *drv)
...
@@ -741,26 +802,22 @@ static void psmouse_connect(struct serio *serio, struct serio_driver *drv)
printk
(
KERN_INFO
"input: %s on %s
\n
"
,
psmouse
->
devname
,
serio
->
phys
);
printk
(
KERN_INFO
"input: %s on %s
\n
"
,
psmouse
->
devname
,
serio
->
phys
);
psmouse_set_state
(
psmouse
,
PSMOUSE_CMD_MODE
);
psmouse_initialize
(
psmouse
);
psmouse_initialize
(
psmouse
);
if
(
parent
&&
parent
->
pt_activate
)
if
(
parent
&&
parent
->
pt_activate
)
parent
->
pt_activate
(
parent
);
parent
->
pt_activate
(
parent
);
/*
* OK, the device is ready, we just need to activate it (turn the
* stream mode on). But if mouse has a pass-through port we don't
* want to do it yet to not disturb child detection.
* The child will activate this port when it's ready.
*/
if
(
serio
->
child
)
{
if
(
serio
->
child
)
{
/*
/*
* Nothing to be done here, serio core will detect that
* Nothing to be done here, serio core will detect that
* the driver set serio->child and will register it for us.
* the driver set serio->child and will register it for us.
*/
*/
printk
(
KERN_INFO
"serio: %s port at %s
\n
"
,
serio
->
child
->
name
,
psmouse
->
phys
);
printk
(
KERN_INFO
"serio: %s port at %s
\n
"
,
serio
->
child
->
name
,
psmouse
->
phys
);
}
else
}
psmouse_activate
(
psmouse
);
psmouse_activate
(
psmouse
);
out:
out:
/* If this is a pass-through port the parent awaits to be activated */
/* If this is a pass-through port the parent awaits to be activated */
...
@@ -774,45 +831,46 @@ static int psmouse_reconnect(struct serio *serio)
...
@@ -774,45 +831,46 @@ static int psmouse_reconnect(struct serio *serio)
struct
psmouse
*
psmouse
=
serio
->
private
;
struct
psmouse
*
psmouse
=
serio
->
private
;
struct
psmouse
*
parent
=
NULL
;
struct
psmouse
*
parent
=
NULL
;
struct
serio_driver
*
drv
=
serio
->
drv
;
struct
serio_driver
*
drv
=
serio
->
drv
;
int
rc
=
-
1
;
if
(
!
drv
||
!
psmouse
)
{
if
(
!
drv
||
!
psmouse
)
{
printk
(
KERN_DEBUG
"psmouse: reconnect request, but serio is disconnected, ignoring...
\n
"
);
printk
(
KERN_DEBUG
"psmouse: reconnect request, but serio is disconnected, ignoring...
\n
"
);
return
-
1
;
return
-
1
;
}
}
psmouse
->
state
=
PSMOUSE_CMD_MODE
;
if
(
serio
->
parent
&&
(
serio
->
type
&
SERIO_TYPE
)
==
SERIO_PS_PSTHRU
)
{
parent
=
serio
->
parent
->
private
;
clear_bit
(
PSMOUSE_FLAG_ACK
,
&
psmouse
->
flags
);
psmouse_deactivate
(
parent
);
clear_bit
(
PSMOUSE_FLAG_CMD
,
&
psmouse
->
flags
);
}
psmouse
->
pktcnt
=
psmouse
->
out_of_sync
=
0
;
psmouse
_set_state
(
psmouse
,
PSMOUSE_INITIALIZING
)
;
if
(
psmouse
->
reconnect
)
{
if
(
psmouse
->
reconnect
)
{
if
(
psmouse
->
reconnect
(
psmouse
))
if
(
psmouse
->
reconnect
(
psmouse
))
return
-
1
;
goto
out
;
}
else
if
(
psmouse_probe
(
psmouse
)
<
0
||
}
else
if
(
psmouse_probe
(
psmouse
)
<
0
||
psmouse
->
type
!=
psmouse_extensions
(
psmouse
,
psmouse_max_proto
,
0
))
psmouse
->
type
!=
psmouse_extensions
(
psmouse
,
psmouse_max_proto
,
0
))
return
-
1
;
goto
out
;
/* ok, the device type (and capabilities) match the old one,
/* ok, the device type (and capabilities) match the old one,
* we can continue using it, complete intialization
* we can continue using it, complete intialization
*/
*/
psmouse_
initialize
(
psmouse
);
psmouse_
set_state
(
psmouse
,
PSMOUSE_CMD_MODE
);
if
(
serio
->
parent
&&
(
serio
->
type
&
SERIO_TYPE
)
==
SERIO_PS_PSTHRU
)
psmouse_initialize
(
psmouse
);
parent
=
serio
->
parent
->
private
;
if
(
parent
&&
parent
->
pt_activate
)
if
(
parent
&&
parent
->
pt_activate
)
parent
->
pt_activate
(
parent
);
parent
->
pt_activate
(
parent
);
if
(
!
serio
->
child
)
psmouse_activate
(
psmouse
);
psmouse_activate
(
psmouse
)
;
rc
=
0
;
out:
/* If this is a pass-through port the parent waits to be activated */
/* If this is a pass-through port the parent waits to be activated */
if
(
parent
)
if
(
parent
)
psmouse_activate
(
parent
);
psmouse_activate
(
parent
);
return
0
;
return
rc
;
}
}
...
...
drivers/input/mouse/psmouse.h
View file @
c5ec0513
...
@@ -9,6 +9,7 @@
...
@@ -9,6 +9,7 @@
#define PSMOUSE_CMD_GETID 0x02f2
#define PSMOUSE_CMD_GETID 0x02f2
#define PSMOUSE_CMD_SETRATE 0x10f3
#define PSMOUSE_CMD_SETRATE 0x10f3
#define PSMOUSE_CMD_ENABLE 0x00f4
#define PSMOUSE_CMD_ENABLE 0x00f4
#define PSMOUSE_CMD_DISABLE 0x00f5
#define PSMOUSE_CMD_RESET_DIS 0x00f6
#define PSMOUSE_CMD_RESET_DIS 0x00f6
#define PSMOUSE_CMD_RESET_BAT 0x02ff
#define PSMOUSE_CMD_RESET_BAT 0x02ff
...
@@ -17,15 +18,17 @@
...
@@ -17,15 +18,17 @@
#define PSMOUSE_RET_ACK 0xfa
#define PSMOUSE_RET_ACK 0xfa
#define PSMOUSE_RET_NAK 0xfe
#define PSMOUSE_RET_NAK 0xfe
/* psmouse states */
#define PSMOUSE_CMD_MODE 0
#define PSMOUSE_ACTIVATED 1
#define PSMOUSE_IGNORE 2
#define PSMOUSE_FLAG_ACK 0
/* Waiting for ACK/NAK */
#define PSMOUSE_FLAG_ACK 0
/* Waiting for ACK/NAK */
#define PSMOUSE_FLAG_CMD 1
/* Waiting for command to finish */
#define PSMOUSE_FLAG_CMD 1
/* Waiting for command to finish */
#define PSMOUSE_FLAG_CMD1 2
/* First byte of command response */
#define PSMOUSE_FLAG_CMD1 2
/* Waiting for the first byte of command response */
#define PSMOUSE_FLAG_ID 3
/* First byte is not keyboard ID */
#define PSMOUSE_FLAG_WAITID 3
/* Command execiting is GET ID */
enum
psmouse_state
{
PSMOUSE_IGNORE
,
PSMOUSE_INITIALIZING
,
PSMOUSE_CMD_MODE
,
PSMOUSE_ACTIVATED
,
};
/* psmouse protocol handler return codes */
/* psmouse protocol handler return codes */
typedef
enum
{
typedef
enum
{
...
@@ -48,13 +51,16 @@ struct psmouse {
...
@@ -48,13 +51,16 @@ struct psmouse {
unsigned
char
model
;
unsigned
char
model
;
unsigned
long
last
;
unsigned
long
last
;
unsigned
long
out_of_sync
;
unsigned
long
out_of_sync
;
unsigned
char
state
;
enum
psmouse_state
state
;
unsigned
char
nak
;
unsigned
char
nak
;
char
error
;
char
error
;
char
devname
[
64
];
char
devname
[
64
];
char
phys
[
32
];
char
phys
[
32
];
unsigned
long
flags
;
unsigned
long
flags
;
/* Used to signal completion from interrupt handler */
wait_queue_head_t
wait
;
psmouse_ret_t
(
*
protocol_handler
)(
struct
psmouse
*
psmouse
,
struct
pt_regs
*
regs
);
psmouse_ret_t
(
*
protocol_handler
)(
struct
psmouse
*
psmouse
,
struct
pt_regs
*
regs
);
int
(
*
reconnect
)(
struct
psmouse
*
psmouse
);
int
(
*
reconnect
)(
struct
psmouse
*
psmouse
);
void
(
*
disconnect
)(
struct
psmouse
*
psmouse
);
void
(
*
disconnect
)(
struct
psmouse
*
psmouse
);
...
...
drivers/input/mouse/synaptics.c
View file @
c5ec0513
...
@@ -233,17 +233,14 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet
...
@@ -233,17 +233,14 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet
{
{
struct
psmouse
*
child
=
ptport
->
private
;
struct
psmouse
*
child
=
ptport
->
private
;
if
(
child
)
{
if
(
child
&&
child
->
state
==
PSMOUSE_ACTIVATED
)
{
if
(
child
->
state
==
PSMOUSE_ACTIVATED
)
{
serio_interrupt
(
ptport
,
packet
[
1
],
0
,
NULL
);
serio_interrupt
(
ptport
,
packet
[
1
],
0
,
NULL
);
serio_interrupt
(
ptport
,
packet
[
4
],
0
,
NULL
);
serio_interrupt
(
ptport
,
packet
[
4
],
0
,
NULL
);
serio_interrupt
(
ptport
,
packet
[
5
],
0
,
NULL
);
serio_interrupt
(
ptport
,
packet
[
5
],
0
,
NULL
);
if
(
child
->
type
>=
PSMOUSE_GENPS
)
if
(
child
->
type
>=
PSMOUSE_GENPS
)
serio_interrupt
(
ptport
,
packet
[
2
],
0
,
NULL
);
serio_interrupt
(
ptport
,
packet
[
2
],
0
,
NULL
);
}
else
}
else
if
(
child
->
state
!=
PSMOUSE_IGNORE
)
{
serio_interrupt
(
ptport
,
packet
[
1
],
0
,
NULL
);
serio_interrupt
(
ptport
,
packet
[
1
],
0
,
NULL
);
}
}
}
}
static
void
synaptics_pt_activate
(
struct
psmouse
*
psmouse
)
static
void
synaptics_pt_activate
(
struct
psmouse
*
psmouse
)
...
@@ -472,9 +469,10 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse, struct pt_r
...
@@ -472,9 +469,10 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse, struct pt_r
if
(
unlikely
(
priv
->
pkt_type
==
SYN_NEWABS
))
if
(
unlikely
(
priv
->
pkt_type
==
SYN_NEWABS
))
priv
->
pkt_type
=
synaptics_detect_pkt_type
(
psmouse
);
priv
->
pkt_type
=
synaptics_detect_pkt_type
(
psmouse
);
if
(
psmouse
->
serio
->
child
&&
psmouse
->
serio
->
child
->
drv
&&
synaptics_is_pt_packet
(
psmouse
->
packet
))
if
(
SYN_CAP_PASS_THROUGH
(
priv
->
capabilities
)
&&
synaptics_is_pt_packet
(
psmouse
->
packet
))
{
synaptics_pass_pt_packet
(
psmouse
->
serio
->
child
,
psmouse
->
packet
);
if
(
psmouse
->
serio
->
child
)
else
synaptics_pass_pt_packet
(
psmouse
->
serio
->
child
,
psmouse
->
packet
);
}
else
synaptics_process_packet
(
psmouse
);
synaptics_process_packet
(
psmouse
);
return
PSMOUSE_FULL_PACKET
;
return
PSMOUSE_FULL_PACKET
;
...
...
drivers/input/mousedev.c
View file @
c5ec0513
...
@@ -52,8 +52,10 @@ static unsigned tap_time = 200;
...
@@ -52,8 +52,10 @@ static unsigned tap_time = 200;
module_param
(
tap_time
,
uint
,
0
);
module_param
(
tap_time
,
uint
,
0
);
MODULE_PARM_DESC
(
tap_time
,
"Tap time for touchpads in absolute mode (msecs)"
);
MODULE_PARM_DESC
(
tap_time
,
"Tap time for touchpads in absolute mode (msecs)"
);
struct
mousedev_
motion
{
struct
mousedev_
hw_data
{
int
dx
,
dy
,
dz
;
int
dx
,
dy
,
dz
;
int
x
,
y
;
int
abs_event
;
unsigned
long
buttons
;
unsigned
long
buttons
;
};
};
...
@@ -66,7 +68,7 @@ struct mousedev {
...
@@ -66,7 +68,7 @@ struct mousedev {
struct
list_head
list
;
struct
list_head
list
;
struct
input_handle
handle
;
struct
input_handle
handle
;
struct
mousedev_
motion
packet
;
struct
mousedev_
hw_data
packet
;
unsigned
int
pkt_count
;
unsigned
int
pkt_count
;
int
old_x
[
4
],
old_y
[
4
];
int
old_x
[
4
],
old_y
[
4
];
unsigned
long
touch
;
unsigned
long
touch
;
...
@@ -76,7 +78,12 @@ enum mousedev_emul {
...
@@ -76,7 +78,12 @@ enum mousedev_emul {
MOUSEDEV_EMUL_PS2
,
MOUSEDEV_EMUL_PS2
,
MOUSEDEV_EMUL_IMPS
,
MOUSEDEV_EMUL_IMPS
,
MOUSEDEV_EMUL_EXPS
MOUSEDEV_EMUL_EXPS
}
__attribute__
((
packed
));
};
struct
mousedev_motion
{
int
dx
,
dy
,
dz
;
unsigned
long
buttons
;
};
#define PACKET_QUEUE_LEN 16
#define PACKET_QUEUE_LEN 16
struct
mousedev_list
{
struct
mousedev_list
{
...
@@ -87,6 +94,7 @@ struct mousedev_list {
...
@@ -87,6 +94,7 @@ struct mousedev_list {
struct
mousedev_motion
packets
[
PACKET_QUEUE_LEN
];
struct
mousedev_motion
packets
[
PACKET_QUEUE_LEN
];
unsigned
int
head
,
tail
;
unsigned
int
head
,
tail
;
spinlock_t
packet_lock
;
spinlock_t
packet_lock
;
int
pos_x
,
pos_y
;
signed
char
ps2
[
6
];
signed
char
ps2
[
6
];
unsigned
char
ready
,
buffer
,
bufsiz
;
unsigned
char
ready
,
buffer
,
bufsiz
;
...
@@ -134,15 +142,19 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev,
...
@@ -134,15 +142,19 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev,
case
ABS_X
:
case
ABS_X
:
size
=
dev
->
absmax
[
ABS_X
]
-
dev
->
absmin
[
ABS_X
];
size
=
dev
->
absmax
[
ABS_X
]
-
dev
->
absmin
[
ABS_X
];
if
(
size
==
0
)
size
=
xres
;
if
(
size
==
0
)
size
=
xres
;
mousedev
->
packet
.
dx
=
(
value
*
xres
-
mousedev
->
old_x
[
0
])
/
size
;
if
(
value
>
dev
->
absmax
[
ABS_X
])
value
=
dev
->
absmax
[
ABS_X
];
mousedev
->
old_x
[
0
]
=
mousedev
->
packet
.
dx
*
size
;
if
(
value
<
dev
->
absmin
[
ABS_X
])
value
=
dev
->
absmin
[
ABS_X
];
mousedev
->
packet
.
x
=
((
value
-
dev
->
absmin
[
ABS_X
])
*
xres
)
/
size
;
mousedev
->
packet
.
abs_event
=
1
;
break
;
break
;
case
ABS_Y
:
case
ABS_Y
:
size
=
dev
->
absmax
[
ABS_Y
]
-
dev
->
absmin
[
ABS_Y
];
size
=
dev
->
absmax
[
ABS_Y
]
-
dev
->
absmin
[
ABS_Y
];
if
(
size
==
0
)
size
=
yres
;
if
(
size
==
0
)
size
=
yres
;
mousedev
->
packet
.
dy
=
(
value
*
yres
-
mousedev
->
old_y
[
0
])
/
size
;
if
(
value
>
dev
->
absmax
[
ABS_Y
])
value
=
dev
->
absmax
[
ABS_Y
];
mousedev
->
old_y
[
0
]
=
mousedev
->
packet
.
dy
*
size
;
if
(
value
<
dev
->
absmin
[
ABS_Y
])
value
=
dev
->
absmin
[
ABS_Y
];
mousedev
->
packet
.
y
=
yres
-
((
value
-
dev
->
absmin
[
ABS_Y
])
*
yres
)
/
size
;
mousedev
->
packet
.
abs_event
=
1
;
break
;
break
;
}
}
}
}
...
@@ -188,7 +200,7 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int
...
@@ -188,7 +200,7 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int
}
}
}
}
static
void
mousedev_notify_readers
(
struct
mousedev
*
mousedev
,
struct
mousedev_
motion
*
packet
)
static
void
mousedev_notify_readers
(
struct
mousedev
*
mousedev
,
struct
mousedev_
hw_data
*
packet
)
{
{
struct
mousedev_list
*
list
;
struct
mousedev_list
*
list
;
struct
mousedev_motion
*
p
;
struct
mousedev_motion
*
p
;
...
@@ -206,6 +218,18 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_m
...
@@ -206,6 +218,18 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_m
}
}
}
}
if
(
packet
->
abs_event
)
{
p
->
dx
+=
packet
->
x
-
list
->
pos_x
;
p
->
dy
+=
packet
->
y
-
list
->
pos_y
;
list
->
pos_x
=
packet
->
x
;
list
->
pos_y
=
packet
->
y
;
}
list
->
pos_x
+=
packet
->
dx
;
list
->
pos_x
=
list
->
pos_x
<
0
?
0
:
(
list
->
pos_x
>=
xres
?
xres
:
list
->
pos_x
);
list
->
pos_y
+=
packet
->
dy
;
list
->
pos_y
=
list
->
pos_y
<
0
?
0
:
(
list
->
pos_y
>=
yres
?
yres
:
list
->
pos_y
);
p
->
dx
+=
packet
->
dx
;
p
->
dx
+=
packet
->
dx
;
p
->
dy
+=
packet
->
dy
;
p
->
dy
+=
packet
->
dy
;
p
->
dz
+=
packet
->
dz
;
p
->
dz
+=
packet
->
dz
;
...
@@ -224,7 +248,7 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
...
@@ -224,7 +248,7 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
{
{
if
(
!
value
)
{
if
(
!
value
)
{
if
(
mousedev
->
touch
&&
if
(
mousedev
->
touch
&&
!
time_after
(
jiffies
,
mousedev
->
touch
+
msecs_to_jiffies
(
tap_time
)))
{
time_before
(
jiffies
,
mousedev
->
touch
+
msecs_to_jiffies
(
tap_time
)))
{
/*
/*
* Toggle left button to emulate tap.
* Toggle left button to emulate tap.
* We rely on the fact that mousedev_mix always has 0
* We rely on the fact that mousedev_mix always has 0
...
@@ -289,6 +313,7 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
...
@@ -289,6 +313,7 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
mousedev_notify_readers
(
&
mousedev_mix
,
&
mousedev
->
packet
);
mousedev_notify_readers
(
&
mousedev_mix
,
&
mousedev
->
packet
);
mousedev
->
packet
.
dx
=
mousedev
->
packet
.
dy
=
mousedev
->
packet
.
dz
=
0
;
mousedev
->
packet
.
dx
=
mousedev
->
packet
.
dy
=
mousedev
->
packet
.
dz
=
0
;
mousedev
->
packet
.
abs_event
=
0
;
}
}
break
;
break
;
}
}
...
@@ -374,6 +399,8 @@ static int mousedev_open(struct inode * inode, struct file * file)
...
@@ -374,6 +399,8 @@ static int mousedev_open(struct inode * inode, struct file * file)
memset
(
list
,
0
,
sizeof
(
struct
mousedev_list
));
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_y
=
yres
/
2
;
list
->
mousedev
=
mousedev_table
[
i
];
list
->
mousedev
=
mousedev_table
[
i
];
list_add_tail
(
&
list
->
node
,
&
mousedev_table
[
i
]
->
list
);
list_add_tail
(
&
list
->
node
,
&
mousedev_table
[
i
]
->
list
);
file
->
private_data
=
list
;
file
->
private_data
=
list
;
...
@@ -524,11 +551,15 @@ static ssize_t mousedev_read(struct file * file, char __user * buffer, size_t co
...
@@ -524,11 +551,15 @@ static ssize_t mousedev_read(struct file * file, char __user * buffer, size_t co
if
(
!
list
->
ready
&&
!
list
->
buffer
&&
(
file
->
f_flags
&
O_NONBLOCK
))
if
(
!
list
->
ready
&&
!
list
->
buffer
&&
(
file
->
f_flags
&
O_NONBLOCK
))
return
-
EAGAIN
;
return
-
EAGAIN
;
retval
=
wait_event_interruptible
(
list
->
mousedev
->
wait
,
list
->
ready
||
list
->
buffer
);
retval
=
wait_event_interruptible
(
list
->
mousedev
->
wait
,
!
list
->
mousedev
->
exist
||
list
->
ready
||
list
->
buffer
);
if
(
retval
)
if
(
retval
)
return
retval
;
return
retval
;
if
(
!
list
->
mousedev
->
exist
)
return
-
ENODEV
;
if
(
!
list
->
buffer
&&
list
->
ready
)
{
if
(
!
list
->
buffer
&&
list
->
ready
)
{
mousedev_packet
(
list
,
list
->
ps2
);
mousedev_packet
(
list
,
list
->
ps2
);
list
->
buffer
=
list
->
bufsiz
;
list
->
buffer
=
list
->
bufsiz
;
...
...
drivers/input/serio/ct82c710.c
View file @
c5ec0513
...
@@ -36,6 +36,7 @@
...
@@ -36,6 +36,7 @@
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/serio.h>
#include <linux/serio.h>
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <asm/io.h>
#include <asm/io.h>
...
@@ -58,10 +59,12 @@ MODULE_LICENSE("GPL");
...
@@ -58,10 +59,12 @@ MODULE_LICENSE("GPL");
#define CT82C710_IRQ 12
#define CT82C710_IRQ 12
static
struct
serio
*
ct82c710_port
;
#define CT82C710_DATA ct82c710_iores.start
static
int
ct82c710_data
;
#define CT82C710_STATUS (ct82c710_iores.start + 1)
static
int
ct82c710_status
;
static
struct
serio
*
ct82c710_port
;
static
struct
platform_device
*
ct82c710_device
;
static
struct
resource
ct82c710_iores
;
/*
/*
* Interrupt handler for the 82C710 mouse port. A character
* Interrupt handler for the 82C710 mouse port. A character
...
@@ -70,7 +73,7 @@ static int ct82c710_status;
...
@@ -70,7 +73,7 @@ static int ct82c710_status;
static
irqreturn_t
ct82c710_interrupt
(
int
cpl
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
static
irqreturn_t
ct82c710_interrupt
(
int
cpl
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
{
return
serio_interrupt
(
ct82c710_port
,
inb
(
ct82c710_data
),
0
,
regs
);
return
serio_interrupt
(
ct82c710_port
,
inb
(
CT82C710_DATA
),
0
,
regs
);
}
}
/*
/*
...
@@ -81,10 +84,10 @@ static int ct82c170_wait(void)
...
@@ -81,10 +84,10 @@ static int ct82c170_wait(void)
{
{
int
timeout
=
60000
;
int
timeout
=
60000
;
while
((
inb
(
ct82c710_status
)
&
(
CT82C710_RX_FULL
|
CT82C710_TX_IDLE
|
CT82C710_DEV_IDLE
))
while
((
inb
(
CT82C710_STATUS
)
&
(
CT82C710_RX_FULL
|
CT82C710_TX_IDLE
|
CT82C710_DEV_IDLE
))
!=
(
CT82C710_DEV_IDLE
|
CT82C710_TX_IDLE
)
&&
timeout
)
{
!=
(
CT82C710_DEV_IDLE
|
CT82C710_TX_IDLE
)
&&
timeout
)
{
if
(
inb_p
(
ct82c710_status
)
&
CT82C710_RX_FULL
)
inb_p
(
ct82c710_data
);
if
(
inb_p
(
CT82C710_STATUS
)
&
CT82C710_RX_FULL
)
inb_p
(
CT82C710_DATA
);
udelay
(
1
);
udelay
(
1
);
timeout
--
;
timeout
--
;
...
@@ -98,7 +101,7 @@ static void ct82c710_close(struct serio *serio)
...
@@ -98,7 +101,7 @@ static void ct82c710_close(struct serio *serio)
if
(
ct82c170_wait
())
if
(
ct82c170_wait
())
printk
(
KERN_WARNING
"ct82c710.c: Device busy in close()
\n
"
);
printk
(
KERN_WARNING
"ct82c710.c: Device busy in close()
\n
"
);
outb_p
(
inb_p
(
ct82c710_status
)
&
~
(
CT82C710_ENABLE
|
CT82C710_INTS_ON
),
ct82c710_status
);
outb_p
(
inb_p
(
CT82C710_STATUS
)
&
~
(
CT82C710_ENABLE
|
CT82C710_INTS_ON
),
CT82C710_STATUS
);
if
(
ct82c170_wait
())
if
(
ct82c170_wait
())
printk
(
KERN_WARNING
"ct82c710.c: Device busy in close()
\n
"
);
printk
(
KERN_WARNING
"ct82c710.c: Device busy in close()
\n
"
);
...
@@ -113,21 +116,21 @@ static int ct82c710_open(struct serio *serio)
...
@@ -113,21 +116,21 @@ static int ct82c710_open(struct serio *serio)
if
(
request_irq
(
CT82C710_IRQ
,
ct82c710_interrupt
,
0
,
"ct82c710"
,
NULL
))
if
(
request_irq
(
CT82C710_IRQ
,
ct82c710_interrupt
,
0
,
"ct82c710"
,
NULL
))
return
-
1
;
return
-
1
;
status
=
inb_p
(
ct82c710_status
);
status
=
inb_p
(
CT82C710_STATUS
);
status
|=
(
CT82C710_ENABLE
|
CT82C710_RESET
);
status
|=
(
CT82C710_ENABLE
|
CT82C710_RESET
);
outb_p
(
status
,
ct82c710_status
);
outb_p
(
status
,
CT82C710_STATUS
);
status
&=
~
(
CT82C710_RESET
);
status
&=
~
(
CT82C710_RESET
);
outb_p
(
status
,
ct82c710_status
);
outb_p
(
status
,
CT82C710_STATUS
);
status
|=
CT82C710_INTS_ON
;
status
|=
CT82C710_INTS_ON
;
outb_p
(
status
,
ct82c710_status
);
/* Enable interrupts */
outb_p
(
status
,
CT82C710_STATUS
);
/* Enable interrupts */
while
(
ct82c170_wait
())
{
while
(
ct82c170_wait
())
{
printk
(
KERN_ERR
"ct82c710: Device busy in open()
\n
"
);
printk
(
KERN_ERR
"ct82c710: Device busy in open()
\n
"
);
status
&=
~
(
CT82C710_ENABLE
|
CT82C710_INTS_ON
);
status
&=
~
(
CT82C710_ENABLE
|
CT82C710_INTS_ON
);
outb_p
(
status
,
ct82c710_status
);
outb_p
(
status
,
CT82C710_STATUS
);
free_irq
(
CT82C710_IRQ
,
NULL
);
free_irq
(
CT82C710_IRQ
,
NULL
);
return
-
1
;
return
-
1
;
}
}
...
@@ -142,7 +145,7 @@ static int ct82c710_open(struct serio *serio)
...
@@ -142,7 +145,7 @@ static int ct82c710_open(struct serio *serio)
static
int
ct82c710_write
(
struct
serio
*
port
,
unsigned
char
c
)
static
int
ct82c710_write
(
struct
serio
*
port
,
unsigned
char
c
)
{
{
if
(
ct82c170_wait
())
return
-
1
;
if
(
ct82c170_wait
())
return
-
1
;
outb_p
(
c
,
ct82c710_data
);
outb_p
(
c
,
CT82C710_DATA
);
return
0
;
return
0
;
}
}
...
@@ -162,8 +165,9 @@ static int __init ct82c710_probe(void)
...
@@ -162,8 +165,9 @@ static int __init ct82c710_probe(void)
return
-
1
;
/* No: no 82C710 here */
return
-
1
;
/* No: no 82C710 here */
outb_p
(
0x0d
,
0x390
);
/* Write index */
outb_p
(
0x0d
,
0x390
);
/* Write index */
ct82c710_data
=
inb_p
(
0x391
)
<<
2
;
/* Get mouse I/O address */
ct82c710_iores
.
start
=
inb_p
(
0x391
)
<<
2
;
/* Get mouse I/O address */
ct82c710_status
=
ct82c710_data
+
1
;
ct82c710_iores
.
end
=
ct82c710_iores
.
start
+
1
;
ct82c710_iores
.
flags
=
IORESOURCE_IO
;
outb_p
(
0x0f
,
0x390
);
outb_p
(
0x0f
,
0x390
);
outb_p
(
0x0f
,
0x391
);
/* Close config mode */
outb_p
(
0x0f
,
0x391
);
/* Close config mode */
...
@@ -181,8 +185,9 @@ static struct serio * __init ct82c710_allocate_port(void)
...
@@ -181,8 +185,9 @@ static struct serio * __init ct82c710_allocate_port(void)
serio
->
open
=
ct82c710_open
;
serio
->
open
=
ct82c710_open
;
serio
->
close
=
ct82c710_close
;
serio
->
close
=
ct82c710_close
;
serio
->
write
=
ct82c710_write
;
serio
->
write
=
ct82c710_write
;
serio
->
dev
.
parent
=
&
ct82c710_device
->
dev
;
strlcpy
(
serio
->
name
,
"C&T 82c710 mouse port"
,
sizeof
(
serio
->
name
));
strlcpy
(
serio
->
name
,
"C&T 82c710 mouse port"
,
sizeof
(
serio
->
name
));
snprintf
(
serio
->
phys
,
sizeof
(
serio
->
phys
),
"isa%04
x/serio0"
,
ct82c710_data
);
snprintf
(
serio
->
phys
,
sizeof
(
serio
->
phys
),
"isa%04
lx/serio0"
,
CT82C710_DATA
);
}
}
return
serio
;
return
serio
;
...
@@ -193,18 +198,19 @@ int __init ct82c710_init(void)
...
@@ -193,18 +198,19 @@ int __init ct82c710_init(void)
if
(
ct82c710_probe
())
if
(
ct82c710_probe
())
return
-
ENODEV
;
return
-
ENODEV
;
if
(
request_region
(
ct82c710_data
,
2
,
"ct82c710"
))
ct82c710_device
=
platform_device_register_simple
(
"ct82c710"
,
-
1
,
&
ct82c710_iores
,
1
);
return
-
EBUSY
;
if
(
IS_ERR
(
ct82c710_device
))
return
PTR_ERR
(
ct82c710_device
);
if
(
!
(
ct82c710_port
=
ct82c710_allocate_port
()))
{
if
(
!
(
ct82c710_port
=
ct82c710_allocate_port
()))
{
release_region
(
ct82c710_data
,
2
);
platform_device_unregister
(
ct82c710_device
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
serio_register_port
(
ct82c710_port
);
serio_register_port
(
ct82c710_port
);
printk
(
KERN_INFO
"serio: C&T 82c710 mouse port at %#x irq %d
\n
"
,
printk
(
KERN_INFO
"serio: C&T 82c710 mouse port at %#
l
x irq %d
\n
"
,
ct82c710_data
,
CT82C710_IRQ
);
CT82C710_DATA
,
CT82C710_IRQ
);
return
0
;
return
0
;
}
}
...
@@ -212,7 +218,7 @@ int __init ct82c710_init(void)
...
@@ -212,7 +218,7 @@ int __init ct82c710_init(void)
void
__exit
ct82c710_exit
(
void
)
void
__exit
ct82c710_exit
(
void
)
{
{
serio_unregister_port
(
ct82c710_port
);
serio_unregister_port
(
ct82c710_port
);
release_region
(
ct82c710_data
,
2
);
platform_device_unregister
(
ct82c710_device
);
}
}
module_init
(
ct82c710_init
);
module_init
(
ct82c710_init
);
...
...
drivers/input/serio/i8042.c
View file @
c5ec0513
...
@@ -21,6 +21,7 @@
...
@@ -21,6 +21,7 @@
#include <linux/sysdev.h>
#include <linux/sysdev.h>
#include <linux/pm.h>
#include <linux/pm.h>
#include <linux/serio.h>
#include <linux/serio.h>
#include <linux/err.h>
#include <asm/io.h>
#include <asm/io.h>
...
@@ -100,9 +101,9 @@ static unsigned char i8042_initial_ctr;
...
@@ -100,9 +101,9 @@ static unsigned char i8042_initial_ctr;
static
unsigned
char
i8042_ctr
;
static
unsigned
char
i8042_ctr
;
static
unsigned
char
i8042_mux_open
;
static
unsigned
char
i8042_mux_open
;
static
unsigned
char
i8042_mux_present
;
static
unsigned
char
i8042_mux_present
;
static
unsigned
char
i8042_sysdev_initialized
;
static
struct
pm_dev
*
i8042_pm_dev
;
static
struct
pm_dev
*
i8042_pm_dev
;
static
struct
timer_list
i8042_timer
;
static
struct
timer_list
i8042_timer
;
static
struct
platform_device
*
i8042_platform_device
;
/*
/*
* Shared IRQ's require a device pointer, but this driver doesn't support
* Shared IRQ's require a device pointer, but this driver doesn't support
...
@@ -362,6 +363,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
...
@@ -362,6 +363,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
unsigned
long
flags
;
unsigned
long
flags
;
unsigned
char
str
,
data
=
0
;
unsigned
char
str
,
data
=
0
;
unsigned
int
dfl
;
unsigned
int
dfl
;
unsigned
int
aux_idx
;
int
ret
;
int
ret
;
mod_timer
(
&
i8042_timer
,
jiffies
+
I8042_POLL_PERIOD
);
mod_timer
(
&
i8042_timer
,
jiffies
+
I8042_POLL_PERIOD
);
...
@@ -378,44 +380,67 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
...
@@ -378,44 +380,67 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
goto
out
;
goto
out
;
}
}
dfl
=
((
str
&
I8042_STR_PARITY
)
?
SERIO_PARITY
:
0
)
|
if
(
i8042_mux_present
&&
(
str
&
I8042_STR_AUXDATA
))
{
((
str
&
I8042_STR_TIMEOUT
)
?
SERIO_TIMEOUT
:
0
);
static
unsigned
long
last_transmit
;
static
unsigned
char
last_str
;
if
(
i8042_mux_values
[
0
].
exists
&&
(
str
&
I8042_STR_AUXDATA
))
{
dfl
=
0
;
if
(
str
&
I8042_STR_MUXERR
)
{
if
(
str
&
I8042_STR_MUXERR
)
{
dbg
(
"MUX error, status is %02x, data is %02x"
,
str
,
data
);
switch
(
data
)
{
switch
(
data
)
{
default:
/*
* When MUXERR condition is signalled the data register can only contain
* 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately
* it is not always the case. Some KBC just get confused which port the
* data came from and signal error leaving the data intact. They _do not_
* revert to legacy mode (actually I've never seen KBC reverting to legacy
* mode yet, when we see one we'll add proper handling).
* Anyway, we will assume that the data came from the same serio last byte
* was transmitted (if transmission happened not too long ago).
*/
if
(
time_before
(
jiffies
,
last_transmit
+
HZ
/
10
))
{
str
=
last_str
;
break
;
}
/* fall through - report timeout */
case
0xfd
:
case
0xfd
:
case
0xfe
:
dfl
=
SERIO_TIMEOUT
;
break
;
case
0xfe
:
dfl
=
SERIO_TIMEOUT
;
data
=
0xfe
;
break
;
case
0xff
:
dfl
=
SERIO_PARITY
;
break
;
case
0xff
:
dfl
=
SERIO_PARITY
;
data
=
0xfe
;
break
;
}
}
data
=
0xfe
;
}
}
else
dfl
=
0
;
aux_idx
=
(
str
>>
6
)
&
3
;
dbg
(
"%02x <- i8042 (interrupt, aux%d, %d%s%s)"
,
dbg
(
"%02x <- i8042 (interrupt, aux%d, %d%s%s)"
,
data
,
(
str
>>
6
)
,
irq
,
data
,
aux_idx
,
irq
,
dfl
&
SERIO_PARITY
?
", bad parity"
:
""
,
dfl
&
SERIO_PARITY
?
", bad parity"
:
""
,
dfl
&
SERIO_TIMEOUT
?
", timeout"
:
""
);
dfl
&
SERIO_TIMEOUT
?
", timeout"
:
""
);
serio_interrupt
(
i8042_mux_port
[(
str
>>
6
)
&
3
],
data
,
dfl
,
regs
);
if
(
likely
(
i8042_mux_values
[
aux_idx
].
exists
))
serio_interrupt
(
i8042_mux_port
[
aux_idx
],
data
,
dfl
,
regs
);
last_str
=
str
;
last_transmit
=
jiffies
;
goto
irq_ret
;
goto
irq_ret
;
}
}
dfl
=
((
str
&
I8042_STR_PARITY
)
?
SERIO_PARITY
:
0
)
|
((
str
&
I8042_STR_TIMEOUT
)
?
SERIO_TIMEOUT
:
0
);
dbg
(
"%02x <- i8042 (interrupt, %s, %d%s%s)"
,
dbg
(
"%02x <- i8042 (interrupt, %s, %d%s%s)"
,
data
,
(
str
&
I8042_STR_AUXDATA
)
?
"aux"
:
"kbd"
,
irq
,
data
,
(
str
&
I8042_STR_AUXDATA
)
?
"aux"
:
"kbd"
,
irq
,
dfl
&
SERIO_PARITY
?
", bad parity"
:
""
,
dfl
&
SERIO_PARITY
?
", bad parity"
:
""
,
dfl
&
SERIO_TIMEOUT
?
", timeout"
:
""
);
dfl
&
SERIO_TIMEOUT
?
", timeout"
:
""
);
if
(
i8042_aux_values
.
exists
&&
(
str
&
I8042_STR_AUXDATA
))
{
serio_interrupt
(
i8042_aux_port
,
data
,
dfl
,
regs
);
goto
irq_ret
;
}
if
(
!
i8042_kbd_values
.
exists
)
goto
irq_ret
;
serio_interrupt
(
i8042_kbd_port
,
data
,
dfl
,
regs
);
if
(
str
&
I8042_STR_AUXDATA
)
{
if
(
likely
(
i8042_aux_values
.
exists
))
serio_interrupt
(
i8042_aux_port
,
data
,
dfl
,
regs
);
}
else
{
if
(
likely
(
i8042_kbd_values
.
exists
))
serio_interrupt
(
i8042_kbd_port
,
data
,
dfl
,
regs
);
}
irq_ret:
irq_ret:
ret
=
1
;
ret
=
1
;
...
@@ -854,7 +879,7 @@ static int i8042_notify_sys(struct notifier_block *this, unsigned long code,
...
@@ -854,7 +879,7 @@ static int i8042_notify_sys(struct notifier_block *this, unsigned long code,
return
NOTIFY_DONE
;
return
NOTIFY_DONE
;
}
}
static
struct
notifier_block
i8042_notifier
=
static
struct
notifier_block
i8042_notifier
=
{
{
i8042_notify_sys
,
i8042_notify_sys
,
NULL
,
NULL
,
...
@@ -864,25 +889,27 @@ static struct notifier_block i8042_notifier=
...
@@ -864,25 +889,27 @@ static struct notifier_block i8042_notifier=
/*
/*
* Suspend/resume handlers for the new PM scheme (driver model)
* Suspend/resume handlers for the new PM scheme (driver model)
*/
*/
static
int
i8042_suspend
(
struct
sys_device
*
dev
,
u32
state
)
static
int
i8042_suspend
(
struct
device
*
dev
,
u32
state
,
u32
level
)
{
{
return
i8042_controller_suspend
()
;
return
level
==
SUSPEND_DISABLE
?
i8042_controller_suspend
()
:
0
;
}
}
static
int
i8042_resume
(
struct
sys_device
*
dev
)
static
int
i8042_resume
(
struct
device
*
dev
,
u32
level
)
{
{
return
i8042_controller_resume
()
;
return
level
==
RESUME_ENABLE
?
i8042_controller_resume
()
:
0
;
}
}
static
struct
sysdev_class
kbc_sysclass
=
{
static
void
i8042_shutdown
(
struct
device
*
dev
)
set_kset_name
(
"i8042"
),
{
.
suspend
=
i8042_suspend
,
i8042_controller_cleanup
();
.
resume
=
i8042_resume
,
}
};
static
struct
sys_device
device_i8042
=
{
static
struct
device_driver
i8042_driver
=
{
.
id
=
0
,
.
name
=
"i8042"
,
.
cls
=
&
kbc_sysclass
,
.
bus
=
&
platform_bus_type
,
.
suspend
=
i8042_suspend
,
.
resume
=
i8042_resume
,
.
shutdown
=
i8042_shutdown
,
};
};
/*
/*
...
@@ -913,6 +940,7 @@ static struct serio * __init i8042_allocate_kbd_port(void)
...
@@ -913,6 +940,7 @@ static struct serio * __init i8042_allocate_kbd_port(void)
serio
->
open
=
i8042_open
,
serio
->
open
=
i8042_open
,
serio
->
close
=
i8042_close
,
serio
->
close
=
i8042_close
,
serio
->
port_data
=
&
i8042_kbd_values
,
serio
->
port_data
=
&
i8042_kbd_values
,
serio
->
dev
.
parent
=
&
i8042_platform_device
->
dev
;
strlcpy
(
serio
->
name
,
"i8042 Kbd Port"
,
sizeof
(
serio
->
name
));
strlcpy
(
serio
->
name
,
"i8042 Kbd Port"
,
sizeof
(
serio
->
name
));
strlcpy
(
serio
->
phys
,
I8042_KBD_PHYS_DESC
,
sizeof
(
serio
->
phys
));
strlcpy
(
serio
->
phys
,
I8042_KBD_PHYS_DESC
,
sizeof
(
serio
->
phys
));
}
}
...
@@ -932,6 +960,7 @@ static struct serio * __init i8042_allocate_aux_port(void)
...
@@ -932,6 +960,7 @@ static struct serio * __init i8042_allocate_aux_port(void)
serio
->
open
=
i8042_open
;
serio
->
open
=
i8042_open
;
serio
->
close
=
i8042_close
;
serio
->
close
=
i8042_close
;
serio
->
port_data
=
&
i8042_aux_values
,
serio
->
port_data
=
&
i8042_aux_values
,
serio
->
dev
.
parent
=
&
i8042_platform_device
->
dev
;
strlcpy
(
serio
->
name
,
"i8042 Aux Port"
,
sizeof
(
serio
->
name
));
strlcpy
(
serio
->
name
,
"i8042 Aux Port"
,
sizeof
(
serio
->
name
));
strlcpy
(
serio
->
phys
,
I8042_AUX_PHYS_DESC
,
sizeof
(
serio
->
phys
));
strlcpy
(
serio
->
phys
,
I8042_AUX_PHYS_DESC
,
sizeof
(
serio
->
phys
));
}
}
...
@@ -956,6 +985,7 @@ static struct serio * __init i8042_allocate_mux_port(int index)
...
@@ -956,6 +985,7 @@ static struct serio * __init i8042_allocate_mux_port(int index)
serio
->
open
=
i8042_open
;
serio
->
open
=
i8042_open
;
serio
->
close
=
i8042_close
;
serio
->
close
=
i8042_close
;
serio
->
port_data
=
values
;
serio
->
port_data
=
values
;
serio
->
dev
.
parent
=
&
i8042_platform_device
->
dev
;
snprintf
(
serio
->
name
,
sizeof
(
serio
->
name
),
"i8042 Aux-%d Port"
,
index
);
snprintf
(
serio
->
name
,
sizeof
(
serio
->
name
),
"i8042 Aux-%d Port"
,
index
);
snprintf
(
serio
->
phys
,
sizeof
(
serio
->
phys
),
I8042_MUX_PHYS_DESC
,
index
+
1
);
snprintf
(
serio
->
phys
,
sizeof
(
serio
->
phys
),
I8042_MUX_PHYS_DESC
,
index
+
1
);
}
}
...
@@ -966,6 +996,7 @@ static struct serio * __init i8042_allocate_mux_port(int index)
...
@@ -966,6 +996,7 @@ static struct serio * __init i8042_allocate_mux_port(int index)
int
__init
i8042_init
(
void
)
int
__init
i8042_init
(
void
)
{
{
int
i
;
int
i
;
int
err
;
dbg_init
();
dbg_init
();
...
@@ -981,6 +1012,16 @@ int __init i8042_init(void)
...
@@ -981,6 +1012,16 @@ int __init i8042_init(void)
if
(
i8042_controller_init
())
if
(
i8042_controller_init
())
return
-
ENODEV
;
return
-
ENODEV
;
err
=
driver_register
(
&
i8042_driver
);
if
(
err
)
return
err
;
i8042_platform_device
=
platform_device_register_simple
(
"i8042"
,
-
1
,
NULL
,
0
);
if
(
IS_ERR
(
i8042_platform_device
))
{
driver_unregister
(
&
i8042_driver
);
return
PTR_ERR
(
i8042_platform_device
);
}
if
(
!
i8042_noaux
&&
!
i8042_check_aux
(
&
i8042_aux_values
))
{
if
(
!
i8042_noaux
&&
!
i8042_check_aux
(
&
i8042_aux_values
))
{
if
(
!
i8042_nomux
&&
!
i8042_check_mux
(
&
i8042_aux_values
))
if
(
!
i8042_nomux
&&
!
i8042_check_mux
(
&
i8042_aux_values
))
for
(
i
=
0
;
i
<
I8042_NUM_MUX_PORTS
;
i
++
)
{
for
(
i
=
0
;
i
<
I8042_NUM_MUX_PORTS
;
i
++
)
{
...
@@ -1001,13 +1042,6 @@ int __init i8042_init(void)
...
@@ -1001,13 +1042,6 @@ int __init i8042_init(void)
mod_timer
(
&
i8042_timer
,
jiffies
+
I8042_POLL_PERIOD
);
mod_timer
(
&
i8042_timer
,
jiffies
+
I8042_POLL_PERIOD
);
if
(
sysdev_class_register
(
&
kbc_sysclass
)
==
0
)
{
if
(
sysdev_register
(
&
device_i8042
)
==
0
)
i8042_sysdev_initialized
=
1
;
else
sysdev_class_unregister
(
&
kbc_sysclass
);
}
i8042_pm_dev
=
pm_register
(
PM_SYS_DEV
,
PM_SYS_UNKNOWN
,
i8042_pm_callback
);
i8042_pm_dev
=
pm_register
(
PM_SYS_DEV
,
PM_SYS_UNKNOWN
,
i8042_pm_callback
);
register_reboot_notifier
(
&
i8042_notifier
);
register_reboot_notifier
(
&
i8042_notifier
);
...
@@ -1024,11 +1058,6 @@ void __exit i8042_exit(void)
...
@@ -1024,11 +1058,6 @@ void __exit i8042_exit(void)
if
(
i8042_pm_dev
)
if
(
i8042_pm_dev
)
pm_unregister
(
i8042_pm_dev
);
pm_unregister
(
i8042_pm_dev
);
if
(
i8042_sysdev_initialized
)
{
sysdev_unregister
(
&
device_i8042
);
sysdev_class_unregister
(
&
kbc_sysclass
);
}
i8042_controller_cleanup
();
i8042_controller_cleanup
();
if
(
i8042_kbd_values
.
exists
)
if
(
i8042_kbd_values
.
exists
)
...
@@ -1043,6 +1072,9 @@ void __exit i8042_exit(void)
...
@@ -1043,6 +1072,9 @@ void __exit i8042_exit(void)
del_timer_sync
(
&
i8042_timer
);
del_timer_sync
(
&
i8042_timer
);
platform_device_unregister
(
i8042_platform_device
);
driver_unregister
(
&
i8042_driver
);
i8042_platform_exit
();
i8042_platform_exit
();
}
}
...
...
drivers/input/serio/maceps2.c
View file @
c5ec0513
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
#include <linux/device.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/spinlock.h>
#include <linux/err.h>
#include <asm/io.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/irq.h>
...
@@ -53,6 +54,7 @@ struct maceps2_data {
...
@@ -53,6 +54,7 @@ struct maceps2_data {
static
struct
maceps2_data
port_data
[
2
];
static
struct
maceps2_data
port_data
[
2
];
static
struct
serio
*
maceps2_port
[
2
];
static
struct
serio
*
maceps2_port
[
2
];
static
struct
platform_device
*
maceps2_device
;
static
int
maceps2_write
(
struct
serio
*
dev
,
unsigned
char
val
)
static
int
maceps2_write
(
struct
serio
*
dev
,
unsigned
char
val
)
{
{
...
@@ -123,13 +125,14 @@ static struct serio * __init maceps2_allocate_port(int idx)
...
@@ -123,13 +125,14 @@ static struct serio * __init maceps2_allocate_port(int idx)
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
serio
)
{
if
(
serio
)
{
memset
(
serio
,
0
,
sizeof
(
struct
serio
));
memset
(
serio
,
0
,
sizeof
(
struct
serio
));
serio
->
type
=
SERIO_8042
;
serio
->
type
=
SERIO_8042
;
serio
->
write
=
maceps2_write
;
serio
->
write
=
maceps2_write
;
serio
->
open
=
maceps2_open
;
serio
->
open
=
maceps2_open
;
serio
->
close
=
maceps2_close
;
serio
->
close
=
maceps2_close
;
snprintf
(
serio
->
name
,
sizeof
(
serio
->
name
),
"MACE PS/2 port%d"
,
idx
);
snprintf
(
serio
->
name
,
sizeof
(
serio
->
name
),
"MACE PS/2 port%d"
,
idx
);
snprintf
(
serio
->
phys
,
sizeof
(
serio
->
phys
),
"mace/serio%d"
,
idx
);
snprintf
(
serio
->
phys
,
sizeof
(
serio
->
phys
),
"mace/serio%d"
,
idx
);
serio
->
port_data
=
&
port_data
[
idx
];
serio
->
port_data
=
&
port_data
[
idx
];
serio
->
dev
.
parent
=
&
maceps2_device
->
dev
;
}
}
return
serio
;
return
serio
;
...
@@ -138,6 +141,10 @@ static struct serio * __init maceps2_allocate_port(int idx)
...
@@ -138,6 +141,10 @@ static struct serio * __init maceps2_allocate_port(int idx)
static
int
__init
maceps2_init
(
void
)
static
int
__init
maceps2_init
(
void
)
{
{
maceps2_device
=
platform_device_register_simple
(
"maceps2"
,
-
1
,
NULL
,
0
);
if
(
IS_ERR
(
maceps2_device
))
return
PTR_ERR
(
maceps2_device
);
port_data
[
0
].
port
=
&
mace
->
perif
.
ps2
.
keyb
;
port_data
[
0
].
port
=
&
mace
->
perif
.
ps2
.
keyb
;
port_data
[
0
].
irq
=
MACEISA_KEYB_IRQ
;
port_data
[
0
].
irq
=
MACEISA_KEYB_IRQ
;
port_data
[
1
].
port
=
&
mace
->
perif
.
ps2
.
mouse
;
port_data
[
1
].
port
=
&
mace
->
perif
.
ps2
.
mouse
;
...
@@ -148,6 +155,7 @@ static int __init maceps2_init(void)
...
@@ -148,6 +155,7 @@ static int __init maceps2_init(void)
if
(
!
maceps2_port
[
0
]
||
!
maceps2_port
[
1
])
{
if
(
!
maceps2_port
[
0
]
||
!
maceps2_port
[
1
])
{
kfree
(
maceps2_port
[
0
]);
kfree
(
maceps2_port
[
0
]);
kfree
(
maceps2_port
[
1
]);
kfree
(
maceps2_port
[
1
]);
platform_device_unregister
(
maceps2_device
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
...
@@ -161,6 +169,7 @@ static void __exit maceps2_exit(void)
...
@@ -161,6 +169,7 @@ static void __exit maceps2_exit(void)
{
{
serio_unregister_port
(
maceps2_port
[
0
]);
serio_unregister_port
(
maceps2_port
[
0
]);
serio_unregister_port
(
maceps2_port
[
1
]);
serio_unregister_port
(
maceps2_port
[
1
]);
platform_device_unregister
(
maceps2_device
);
}
}
module_init
(
maceps2_init
);
module_init
(
maceps2_init
);
...
...
drivers/input/serio/q40kbd.c
View file @
c5ec0513
...
@@ -35,6 +35,7 @@
...
@@ -35,6 +35,7 @@
#include <linux/init.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/serio.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/err.h>
#include <asm/bitops.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/io.h>
...
@@ -49,6 +50,7 @@ MODULE_LICENSE("GPL");
...
@@ -49,6 +50,7 @@ MODULE_LICENSE("GPL");
spinlock_t
q40kbd_lock
=
SPIN_LOCK_UNLOCKED
;
spinlock_t
q40kbd_lock
=
SPIN_LOCK_UNLOCKED
;
static
struct
serio
*
q40kbd_port
;
static
struct
serio
*
q40kbd_port
;
static
struct
platform_device
*
q40kbd_device
;
static
irqreturn_t
q40kbd_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
static
irqreturn_t
q40kbd_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
{
...
@@ -120,9 +122,10 @@ static struct serio * __init q40kbd_allocate_port(void)
...
@@ -120,9 +122,10 @@ static struct serio * __init q40kbd_allocate_port(void)
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
serio
)
{
if
(
serio
)
{
memset
(
serio
,
0
,
sizeof
(
struct
serio
));
memset
(
serio
,
0
,
sizeof
(
struct
serio
));
serio
->
type
=
SERIO_8042
;
serio
->
type
=
SERIO_8042
;
serio
->
open
=
q40kbd_open
;
serio
->
open
=
q40kbd_open
;
serio
->
close
=
q40kbd_close
;
serio
->
close
=
q40kbd_close
;
serio
->
dev
.
parent
=
&
q40kbd_device
->
dev
;
strlcpy
(
serio
->
name
,
"Q40 Kbd Port"
,
sizeof
(
serio
->
name
));
strlcpy
(
serio
->
name
,
"Q40 Kbd Port"
,
sizeof
(
serio
->
name
));
strlcpy
(
serio
->
phys
,
"Q40"
,
sizeof
(
serio
->
phys
));
strlcpy
(
serio
->
phys
,
"Q40"
,
sizeof
(
serio
->
phys
));
}
}
...
@@ -135,8 +138,14 @@ static int __init q40kbd_init(void)
...
@@ -135,8 +138,14 @@ static int __init q40kbd_init(void)
if
(
!
MACH_IS_Q40
)
if
(
!
MACH_IS_Q40
)
return
-
EIO
;
return
-
EIO
;
if
(
!
(
q40kbd_port
=
q40kbd_allocate_port
()))
q40kbd_device
=
platform_device_register_simple
(
"q40kbd"
,
-
1
,
NULL
,
0
);
if
(
IS_ERR
(
q40kbd_device
))
return
PTR_ERR
(
q40kbd_device
);
if
(
!
(
q40kbd_port
=
q40kbd_allocate_port
()))
{
platform_device_unregister
(
q40kbd_device
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
serio_register_port
(
q40kbd_port
);
serio_register_port
(
q40kbd_port
);
printk
(
KERN_INFO
"serio: Q40 kbd registered
\n
"
);
printk
(
KERN_INFO
"serio: Q40 kbd registered
\n
"
);
...
@@ -147,6 +156,7 @@ static int __init q40kbd_init(void)
...
@@ -147,6 +156,7 @@ static int __init q40kbd_init(void)
static
void
__exit
q40kbd_exit
(
void
)
static
void
__exit
q40kbd_exit
(
void
)
{
{
serio_unregister_port
(
q40kbd_port
);
serio_unregister_port
(
q40kbd_port
);
platform_device_unregister
(
q40kbd_device
);
}
}
module_init
(
q40kbd_init
);
module_init
(
q40kbd_init
);
...
...
drivers/input/serio/rpckbd.c
View file @
c5ec0513
...
@@ -33,6 +33,7 @@
...
@@ -33,6 +33,7 @@
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/serio.h>
#include <linux/err.h>
#include <asm/irq.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/hardware.h>
...
@@ -45,6 +46,7 @@ MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver");
...
@@ -45,6 +46,7 @@ MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver");
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
static
struct
serio
*
rpckbd_port
;
static
struct
serio
*
rpckbd_port
;
static
struct
platform_device
*
rpckbd_device
;
static
int
rpckbd_write
(
struct
serio
*
port
,
unsigned
char
val
)
static
int
rpckbd_write
(
struct
serio
*
port
,
unsigned
char
val
)
{
{
...
@@ -115,10 +117,11 @@ static struct serio * __init rpckbd_allocate_port(void)
...
@@ -115,10 +117,11 @@ static struct serio * __init rpckbd_allocate_port(void)
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
serio
)
{
if
(
serio
)
{
memset
(
serio
,
0
,
sizeof
(
struct
serio
));
memset
(
serio
,
0
,
sizeof
(
struct
serio
));
serio
->
type
=
SERIO_8042
;
serio
->
type
=
SERIO_8042
;
serio
->
write
=
rpckbd_write
;
serio
->
write
=
rpckbd_write
;
serio
->
open
=
rpckbd_open
;
serio
->
open
=
rpckbd_open
;
serio
->
close
=
rpckbd_close
;
serio
->
close
=
rpckbd_close
;
serio
->
dev
.
parent
=
&
rpckbd_device
->
dev
;
strlcpy
(
serio
->
name
,
"RiscPC PS/2 kbd port"
,
sizeof
(
serio
->
name
));
strlcpy
(
serio
->
name
,
"RiscPC PS/2 kbd port"
,
sizeof
(
serio
->
name
));
strlcpy
(
serio
->
phys
,
"rpckbd/serio0"
,
sizeof
(
serio
->
phys
));
strlcpy
(
serio
->
phys
,
"rpckbd/serio0"
,
sizeof
(
serio
->
phys
));
}
}
...
@@ -128,8 +131,14 @@ static struct serio * __init rpckbd_allocate_port(void)
...
@@ -128,8 +131,14 @@ static struct serio * __init rpckbd_allocate_port(void)
static
int
__init
rpckbd_init
(
void
)
static
int
__init
rpckbd_init
(
void
)
{
{
if
(
!
(
rpckbd_port
=
rpckbd_allocate_port
()))
rpckbd_device
=
platform_device_register_simple
(
"rpckbd"
,
-
1
,
NULL
,
0
);
if
(
IS_ERR
(
rpckbd_device
))
return
PTR_ERR
(
rpckbd_device
);
if
(
!
(
rpckbd_port
=
rpckbd_allocate_port
()))
{
platform_device_unregister
(
rpckbd_device
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
serio_register_port
(
rpckbd_port
);
serio_register_port
(
rpckbd_port
);
return
0
;
return
0
;
...
@@ -138,6 +147,7 @@ static int __init rpckbd_init(void)
...
@@ -138,6 +147,7 @@ static int __init rpckbd_init(void)
static
void
__exit
rpckbd_exit
(
void
)
static
void
__exit
rpckbd_exit
(
void
)
{
{
serio_unregister_port
(
rpckbd_port
);
serio_unregister_port
(
rpckbd_port
);
platform_device_unregister
(
rpckbd_device
);
}
}
module_init
(
rpckbd_init
);
module_init
(
rpckbd_init
);
...
...
drivers/input/serio/serio.c
View file @
c5ec0513
...
@@ -245,7 +245,6 @@ static ssize_t serio_show_description(struct device *dev, char *buf)
...
@@ -245,7 +245,6 @@ static ssize_t serio_show_description(struct device *dev, char *buf)
struct
serio
*
serio
=
to_serio_port
(
dev
);
struct
serio
*
serio
=
to_serio_port
(
dev
);
return
sprintf
(
buf
,
"%s
\n
"
,
serio
->
name
);
return
sprintf
(
buf
,
"%s
\n
"
,
serio
->
name
);
}
}
static
DEVICE_ATTR
(
description
,
S_IRUGO
,
serio_show_description
,
NULL
);
static
ssize_t
serio_show_driver
(
struct
device
*
dev
,
char
*
buf
)
static
ssize_t
serio_show_driver
(
struct
device
*
dev
,
char
*
buf
)
{
{
...
@@ -256,7 +255,6 @@ static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t c
...
@@ -256,7 +255,6 @@ static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t c
{
{
struct
serio
*
serio
=
to_serio_port
(
dev
);
struct
serio
*
serio
=
to_serio_port
(
dev
);
struct
device_driver
*
drv
;
struct
device_driver
*
drv
;
struct
kobject
*
k
;
int
retval
;
int
retval
;
retval
=
down_interruptible
(
&
serio_sem
);
retval
=
down_interruptible
(
&
serio_sem
);
...
@@ -271,10 +269,10 @@ static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t c
...
@@ -271,10 +269,10 @@ static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t c
}
else
if
(
!
strncmp
(
buf
,
"rescan"
,
count
))
{
}
else
if
(
!
strncmp
(
buf
,
"rescan"
,
count
))
{
serio_disconnect_port
(
serio
);
serio_disconnect_port
(
serio
);
serio_connect_port
(
serio
,
NULL
);
serio_connect_port
(
serio
,
NULL
);
}
else
if
((
k
=
kset_find_obj
(
&
serio_bus
.
drivers
,
buf
))
!=
NULL
)
{
}
else
if
((
drv
=
driver_find
(
buf
,
&
serio_bus
))
!=
NULL
)
{
drv
=
container_of
(
k
,
struct
device_driver
,
kobj
);
serio_disconnect_port
(
serio
);
serio_disconnect_port
(
serio
);
serio_connect_port
(
serio
,
to_serio_driver
(
drv
));
serio_connect_port
(
serio
,
to_serio_driver
(
drv
));
put_driver
(
drv
);
}
else
{
}
else
{
retval
=
-
EINVAL
;
retval
=
-
EINVAL
;
}
}
...
@@ -283,7 +281,37 @@ static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t c
...
@@ -283,7 +281,37 @@ static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t c
return
retval
;
return
retval
;
}
}
static
DEVICE_ATTR
(
driver
,
S_IWUSR
|
S_IRUGO
,
serio_show_driver
,
serio_rebind_driver
);
static
ssize_t
serio_show_bind_mode
(
struct
device
*
dev
,
char
*
buf
)
{
struct
serio
*
serio
=
to_serio_port
(
dev
);
return
sprintf
(
buf
,
"%s
\n
"
,
serio
->
manual_bind
?
"manual"
:
"auto"
);
}
static
ssize_t
serio_set_bind_mode
(
struct
device
*
dev
,
const
char
*
buf
,
size_t
count
)
{
struct
serio
*
serio
=
to_serio_port
(
dev
);
int
retval
;
retval
=
count
;
if
(
!
strncmp
(
buf
,
"manual"
,
count
))
{
serio
->
manual_bind
=
1
;
}
else
if
(
!
strncmp
(
buf
,
"auto"
,
count
))
{
serio
->
manual_bind
=
0
;
}
else
{
retval
=
-
EINVAL
;
}
return
retval
;
}
static
struct
device_attribute
serio_device_attrs
[]
=
{
__ATTR
(
description
,
S_IRUGO
,
serio_show_description
,
NULL
),
__ATTR
(
driver
,
S_IWUSR
|
S_IRUGO
,
serio_show_driver
,
serio_rebind_driver
),
__ATTR
(
bind_mode
,
S_IWUSR
|
S_IRUGO
,
serio_show_bind_mode
,
serio_set_bind_mode
),
__ATTR_NULL
};
static
void
serio_release_port
(
struct
device
*
dev
)
static
void
serio_release_port
(
struct
device
*
dev
)
{
{
...
@@ -305,8 +333,6 @@ static void serio_create_port(struct serio *serio)
...
@@ -305,8 +333,6 @@ static void serio_create_port(struct serio *serio)
if
(
serio
->
parent
)
if
(
serio
->
parent
)
serio
->
dev
.
parent
=
&
serio
->
parent
->
dev
;
serio
->
dev
.
parent
=
&
serio
->
parent
->
dev
;
device_register
(
&
serio
->
dev
);
device_register
(
&
serio
->
dev
);
device_create_file
(
&
serio
->
dev
,
&
dev_attr_description
);
device_create_file
(
&
serio
->
dev
,
&
dev_attr_driver
);
}
}
/*
/*
...
@@ -350,7 +376,7 @@ static void serio_connect_port(struct serio *serio, struct serio_driver *drv)
...
@@ -350,7 +376,7 @@ static void serio_connect_port(struct serio *serio, struct serio_driver *drv)
if
(
drv
)
if
(
drv
)
serio_bind_driver
(
serio
,
drv
);
serio_bind_driver
(
serio
,
drv
);
else
else
if
(
!
serio
->
manual_bind
)
serio_find_driver
(
serio
);
serio_find_driver
(
serio
);
/* Ok, now bind children, if any */
/* Ok, now bind children, if any */
...
@@ -362,13 +388,15 @@ static void serio_connect_port(struct serio *serio, struct serio_driver *drv)
...
@@ -362,13 +388,15 @@ static void serio_connect_port(struct serio *serio, struct serio_driver *drv)
serio_create_port
(
serio
);
serio_create_port
(
serio
);
/*
if
(
!
serio
->
manual_bind
)
{
* With children we just _prefer_ passed in driver,
/*
* but we will try other options in case preferred
* With children we just _prefer_ passed in driver,
* is not the one
* but we will try other options in case preferred
*/
* is not the one
if
(
!
drv
||
!
serio_bind_driver
(
serio
,
drv
))
*/
serio_find_driver
(
serio
);
if
(
!
drv
||
!
serio_bind_driver
(
serio
,
drv
))
serio_find_driver
(
serio
);
}
}
}
}
}
...
@@ -481,7 +509,37 @@ static ssize_t serio_driver_show_description(struct device_driver *drv, char *bu
...
@@ -481,7 +509,37 @@ static ssize_t serio_driver_show_description(struct device_driver *drv, char *bu
struct
serio_driver
*
driver
=
to_serio_driver
(
drv
);
struct
serio_driver
*
driver
=
to_serio_driver
(
drv
);
return
sprintf
(
buf
,
"%s
\n
"
,
driver
->
description
?
driver
->
description
:
"(none)"
);
return
sprintf
(
buf
,
"%s
\n
"
,
driver
->
description
?
driver
->
description
:
"(none)"
);
}
}
static
DRIVER_ATTR
(
description
,
S_IRUGO
,
serio_driver_show_description
,
NULL
);
static
ssize_t
serio_driver_show_bind_mode
(
struct
device_driver
*
drv
,
char
*
buf
)
{
struct
serio_driver
*
serio_drv
=
to_serio_driver
(
drv
);
return
sprintf
(
buf
,
"%s
\n
"
,
serio_drv
->
manual_bind
?
"manual"
:
"auto"
);
}
static
ssize_t
serio_driver_set_bind_mode
(
struct
device_driver
*
drv
,
const
char
*
buf
,
size_t
count
)
{
struct
serio_driver
*
serio_drv
=
to_serio_driver
(
drv
);
int
retval
;
retval
=
count
;
if
(
!
strncmp
(
buf
,
"manual"
,
count
))
{
serio_drv
->
manual_bind
=
1
;
}
else
if
(
!
strncmp
(
buf
,
"auto"
,
count
))
{
serio_drv
->
manual_bind
=
0
;
}
else
{
retval
=
-
EINVAL
;
}
return
retval
;
}
static
struct
driver_attribute
serio_driver_attrs
[]
=
{
__ATTR
(
description
,
S_IRUGO
,
serio_driver_show_description
,
NULL
),
__ATTR
(
bind_mode
,
S_IWUSR
|
S_IRUGO
,
serio_driver_show_bind_mode
,
serio_driver_set_bind_mode
),
__ATTR_NULL
};
void
serio_register_driver
(
struct
serio_driver
*
drv
)
void
serio_register_driver
(
struct
serio_driver
*
drv
)
{
{
...
@@ -493,7 +551,6 @@ void serio_register_driver(struct serio_driver *drv)
...
@@ -493,7 +551,6 @@ void serio_register_driver(struct serio_driver *drv)
drv
->
driver
.
bus
=
&
serio_bus
;
drv
->
driver
.
bus
=
&
serio_bus
;
driver_register
(
&
drv
->
driver
);
driver_register
(
&
drv
->
driver
);
driver_create_file
(
&
drv
->
driver
,
&
driver_attr_description
);
if
(
drv
->
manual_bind
)
if
(
drv
->
manual_bind
)
goto
out
;
goto
out
;
...
@@ -541,15 +598,14 @@ void serio_unregister_driver(struct serio_driver *drv)
...
@@ -541,15 +598,14 @@ void serio_unregister_driver(struct serio_driver *drv)
/* called from serio_driver->connect/disconnect methods under serio_sem */
/* called from serio_driver->connect/disconnect methods under serio_sem */
int
serio_open
(
struct
serio
*
serio
,
struct
serio_driver
*
drv
)
int
serio_open
(
struct
serio
*
serio
,
struct
serio_driver
*
drv
)
{
{
unsigned
long
flags
;
serio_pause_rx
(
serio
);
spin_lock_irqsave
(
&
serio
->
lock
,
flags
);
serio
->
drv
=
drv
;
serio
->
drv
=
drv
;
spin_unlock_irqrestore
(
&
serio
->
lock
,
flags
);
serio_continue_rx
(
serio
);
if
(
serio
->
open
&&
serio
->
open
(
serio
))
{
if
(
serio
->
open
&&
serio
->
open
(
serio
))
{
s
pin_lock_irqsave
(
&
serio
->
lock
,
flags
);
s
erio_pause_rx
(
serio
);
serio
->
drv
=
NULL
;
serio
->
drv
=
NULL
;
s
pin_unlock_irqrestore
(
&
serio
->
lock
,
flags
);
s
erio_continue_rx
(
serio
);
return
-
1
;
return
-
1
;
}
}
return
0
;
return
0
;
...
@@ -558,13 +614,12 @@ int serio_open(struct serio *serio, struct serio_driver *drv)
...
@@ -558,13 +614,12 @@ int serio_open(struct serio *serio, struct serio_driver *drv)
/* called from serio_driver->connect/disconnect methods under serio_sem */
/* called from serio_driver->connect/disconnect methods under serio_sem */
void
serio_close
(
struct
serio
*
serio
)
void
serio_close
(
struct
serio
*
serio
)
{
{
unsigned
long
flags
;
if
(
serio
->
close
)
if
(
serio
->
close
)
serio
->
close
(
serio
);
serio
->
close
(
serio
);
spin_lock_irqsave
(
&
serio
->
lock
,
flags
);
serio_pause_rx
(
serio
);
serio
->
drv
=
NULL
;
serio
->
drv
=
NULL
;
s
pin_unlock_irqrestore
(
&
serio
->
lock
,
flags
);
s
erio_continue_rx
(
serio
);
}
}
irqreturn_t
serio_interrupt
(
struct
serio
*
serio
,
irqreturn_t
serio_interrupt
(
struct
serio
*
serio
,
...
@@ -599,6 +654,8 @@ static int __init serio_init(void)
...
@@ -599,6 +654,8 @@ static int __init serio_init(void)
return
-
1
;
return
-
1
;
}
}
serio_bus
.
dev_attrs
=
serio_device_attrs
;
serio_bus
.
drv_attrs
=
serio_driver_attrs
;
bus_register
(
&
serio_bus
);
bus_register
(
&
serio_bus
);
return
0
;
return
0
;
...
...
drivers/input/tsdev.c
View file @
c5ec0513
...
@@ -19,18 +19,18 @@
...
@@ -19,18 +19,18 @@
/*
/*
* This program is free software; you can redistribute it and/or modify
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* Should you need to contact me, the author, you can do so either by
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <jsimmons@infradead.org>.
* e-mail - mail your message to <jsimmons@infradead.org>.
*/
*/
...
@@ -210,7 +210,7 @@ static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count,
...
@@ -210,7 +210,7 @@ static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count,
return
-
EAGAIN
;
return
-
EAGAIN
;
retval
=
wait_event_interruptible
(
list
->
tsdev
->
wait
,
retval
=
wait_event_interruptible
(
list
->
tsdev
->
wait
,
(
list
->
head
!=
list
->
tail
)
&&
list
->
tsdev
->
exist
);
list
->
head
!=
list
->
tail
||
!
list
->
tsdev
->
exist
);
if
(
retval
)
if
(
retval
)
return
retval
;
return
retval
;
...
...
drivers/serial/sunzilog.c
View file @
c5ec0513
...
@@ -1529,7 +1529,6 @@ static void __init sunzilog_prepare(void)
...
@@ -1529,7 +1529,6 @@ static void __init sunzilog_prepare(void)
static
void
__init
sunzilog_init_kbdms
(
struct
uart_sunzilog_port
*
up
,
int
channel
)
static
void
__init
sunzilog_init_kbdms
(
struct
uart_sunzilog_port
*
up
,
int
channel
)
{
{
int
baud
,
brg
;
int
baud
,
brg
;
struct
serio
*
serio
;
if
(
channel
==
KEYBOARD_LINE
)
{
if
(
channel
==
KEYBOARD_LINE
)
{
up
->
flags
|=
SUNZILOG_FLAG_CONS_KEYB
;
up
->
flags
|=
SUNZILOG_FLAG_CONS_KEYB
;
...
@@ -1546,8 +1545,15 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
...
@@ -1546,8 +1545,15 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
up
->
curregs
[
R15
]
=
BRKIE
;
up
->
curregs
[
R15
]
=
BRKIE
;
brg
=
BPS_TO_BRG
(
baud
,
ZS_CLOCK
/
ZS_CLOCK_DIVISOR
);
brg
=
BPS_TO_BRG
(
baud
,
ZS_CLOCK
/
ZS_CLOCK_DIVISOR
);
sunzilog_convert_to_zs
(
up
,
up
->
cflag
,
0
,
brg
);
sunzilog_convert_to_zs
(
up
,
up
->
cflag
,
0
,
brg
);
sunzilog_set_mctrl
(
&
up
->
port
,
TIOCM_DTR
|
TIOCM_RTS
);
__sunzilog_startup
(
up
);
}
#ifdef CONFIG_SERIO
#ifdef CONFIG_SERIO
static
void
__init
sunzilog_register_serio
(
struct
uart_sunzilog_port
*
up
,
int
channel
)
{
struct
serio
*
serio
;
up
->
serio
=
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
up
->
serio
=
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
serio
)
{
if
(
serio
)
{
...
@@ -1576,11 +1582,8 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
...
@@ -1576,11 +1582,8 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
printk
(
KERN_WARNING
"zs%d: not enough memory for serio port
\n
"
,
printk
(
KERN_WARNING
"zs%d: not enough memory for serio port
\n
"
,
channel
);
channel
);
}
}
#endif
sunzilog_set_mctrl
(
&
up
->
port
,
TIOCM_DTR
|
TIOCM_RTS
);
__sunzilog_startup
(
up
);
}
}
#endif
static
void
__init
sunzilog_init_hw
(
void
)
static
void
__init
sunzilog_init_hw
(
void
)
{
{
...
@@ -1624,6 +1627,11 @@ static void __init sunzilog_init_hw(void)
...
@@ -1624,6 +1627,11 @@ static void __init sunzilog_init_hw(void)
}
}
spin_unlock_irqrestore
(
&
up
->
port
.
lock
,
flags
);
spin_unlock_irqrestore
(
&
up
->
port
.
lock
,
flags
);
#ifdef CONFIG_SERIO
if
(
i
==
KEYBOARD_LINE
||
i
==
MOUSE_LINE
)
sunzilog_register_serio
(
up
,
i
);
#endif
}
}
}
}
...
...
include/linux/serio.h
View file @
c5ec0513
...
@@ -27,6 +27,8 @@ struct serio {
...
@@ -27,6 +27,8 @@ struct serio {
char
name
[
32
];
char
name
[
32
];
char
phys
[
32
];
char
phys
[
32
];
unsigned
int
manual_bind
;
unsigned
short
idbus
;
unsigned
short
idbus
;
unsigned
short
idvendor
;
unsigned
short
idvendor
;
unsigned
short
idproduct
;
unsigned
short
idproduct
;
...
@@ -35,7 +37,7 @@ struct serio {
...
@@ -35,7 +37,7 @@ struct serio {
unsigned
long
type
;
unsigned
long
type
;
unsigned
long
event
;
unsigned
long
event
;
spinlock_t
lock
;
spinlock_t
lock
;
/* protects critical sections from port's interrupt handler */
int
(
*
write
)(
struct
serio
*
,
unsigned
char
);
int
(
*
write
)(
struct
serio
*
,
unsigned
char
);
int
(
*
open
)(
struct
serio
*
);
int
(
*
open
)(
struct
serio
*
);
...
@@ -43,7 +45,7 @@ struct serio {
...
@@ -43,7 +45,7 @@ struct serio {
struct
serio
*
parent
,
*
child
;
struct
serio
*
parent
,
*
child
;
struct
serio_driver
*
drv
;
/* Accessed from interrupt, writes must be protected by serio_
lock */
struct
serio_driver
*
drv
;
/* accessed from interrupt, must be protected by serio->
lock */
struct
device
dev
;
struct
device
dev
;
...
@@ -55,7 +57,7 @@ struct serio_driver {
...
@@ -55,7 +57,7 @@ struct serio_driver {
void
*
private
;
void
*
private
;
char
*
description
;
char
*
description
;
int
manual_bind
;
unsigned
int
manual_bind
;
void
(
*
write_wakeup
)(
struct
serio
*
);
void
(
*
write_wakeup
)(
struct
serio
*
);
irqreturn_t
(
*
interrupt
)(
struct
serio
*
,
unsigned
char
,
irqreturn_t
(
*
interrupt
)(
struct
serio
*
,
unsigned
char
,
...
@@ -81,6 +83,7 @@ void serio_register_port(struct serio *serio);
...
@@ -81,6 +83,7 @@ void serio_register_port(struct serio *serio);
void
serio_register_port_delayed
(
struct
serio
*
serio
);
void
serio_register_port_delayed
(
struct
serio
*
serio
);
void
serio_unregister_port
(
struct
serio
*
serio
);
void
serio_unregister_port
(
struct
serio
*
serio
);
void
serio_unregister_port_delayed
(
struct
serio
*
serio
);
void
serio_unregister_port_delayed
(
struct
serio
*
serio
);
void
serio_register_driver
(
struct
serio_driver
*
drv
);
void
serio_register_driver
(
struct
serio_driver
*
drv
);
void
serio_unregister_driver
(
struct
serio_driver
*
drv
);
void
serio_unregister_driver
(
struct
serio_driver
*
drv
);
...
@@ -104,6 +107,22 @@ static __inline__ void serio_cleanup(struct serio *serio)
...
@@ -104,6 +107,22 @@ static __inline__ void serio_cleanup(struct serio *serio)
serio
->
drv
->
cleanup
(
serio
);
serio
->
drv
->
cleanup
(
serio
);
}
}
/*
* Use the following fucntions to protect critical sections in
* driver code from port's interrupt handler
*/
static
__inline__
void
serio_pause_rx
(
struct
serio
*
serio
)
{
spin_lock_irq
(
&
serio
->
lock
);
}
static
__inline__
void
serio_continue_rx
(
struct
serio
*
serio
)
{
spin_unlock_irq
(
&
serio
->
lock
);
}
#endif
#endif
/*
/*
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment