2019-06-04 10:11:33 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2005-04-16 15:20:36 -07:00
/*
* PS / 2 driver library
*
* Copyright ( c ) 1999 - 2002 Vojtech Pavlik
* Copyright ( c ) 2004 Dmitry Torokhov
*/
# include <linux/delay.h>
# include <linux/module.h>
2009-10-07 17:09:06 +04:00
# include <linux/sched.h>
2005-04-16 15:20:36 -07:00
# include <linux/interrupt.h>
# include <linux/input.h>
# include <linux/serio.h>
2009-09-16 01:06:43 -07:00
# include <linux/i8042.h>
2005-04-16 15:20:36 -07:00
# include <linux/libps2.h>
# define DRIVER_DESC "PS / 2 driver library"
MODULE_AUTHOR ( " Dmitry Torokhov <dtor@mail.ru> " ) ;
MODULE_DESCRIPTION ( " PS/2 driver library " ) ;
MODULE_LICENSE ( " GPL " ) ;
2018-01-04 22:01:43 -08:00
static int ps2_do_sendbyte ( struct ps2dev * ps2dev , u8 byte ,
unsigned int timeout , unsigned int max_attempts )
__releases ( & ps2dev - > serio - > lock ) __acquires ( & ps2dev - > serio - > lock )
2005-04-16 15:20:36 -07:00
{
2018-01-04 22:01:43 -08:00
int attempt = 0 ;
2018-01-02 12:21:49 -08:00
int error ;
2018-01-04 22:01:43 -08:00
lockdep_assert_held ( & ps2dev - > serio - > lock ) ;
2005-04-16 15:20:36 -07:00
2018-01-04 22:01:43 -08:00
do {
ps2dev - > nak = 1 ;
ps2dev - > flags | = PS2_FLAG_ACK ;
serio_continue_rx ( ps2dev - > serio ) ;
error = serio_write ( ps2dev - > serio , byte ) ;
if ( error )
dev_dbg ( & ps2dev - > serio - > dev ,
" failed to write %#02x: %d \n " , byte , error ) ;
else
wait_event_timeout ( ps2dev - > wait ,
! ( ps2dev - > flags & PS2_FLAG_ACK ) ,
msecs_to_jiffies ( timeout ) ) ;
serio_pause_rx ( ps2dev - > serio ) ;
} while ( ps2dev - > nak = = PS2_RET_NAK & & + + attempt < max_attempts ) ;
2005-04-16 15:20:36 -07:00
ps2dev - > flags & = ~ PS2_FLAG_ACK ;
2018-01-04 22:01:43 -08:00
if ( ! error ) {
switch ( ps2dev - > nak ) {
case 0 :
break ;
case PS2_RET_NAK :
error = - EAGAIN ;
break ;
case PS2_RET_ERR :
error = - EPROTO ;
break ;
default :
error = - EIO ;
break ;
}
}
if ( error | | attempt > 1 )
dev_dbg ( & ps2dev - > serio - > dev ,
" %02x - %d (%x), attempt %d \n " ,
byte , error , ps2dev - > nak , attempt ) ;
return error ;
2005-04-16 15:20:36 -07:00
}
2018-01-02 12:21:49 -08:00
/*
* ps2_sendbyte ( ) sends a byte to the device and waits for acknowledge .
2018-01-04 22:01:43 -08:00
* It doesn ' t handle retransmission , the caller is expected to handle
* it when needed .
2018-01-02 12:21:49 -08:00
*
* ps2_sendbyte ( ) can only be called from a process context .
*/
int ps2_sendbyte ( struct ps2dev * ps2dev , u8 byte , unsigned int timeout )
{
int retval ;
2018-01-04 22:01:43 -08:00
serio_pause_rx ( ps2dev - > serio ) ;
retval = ps2_do_sendbyte ( ps2dev , byte , timeout , 1 ) ;
2018-01-02 12:21:49 -08:00
dev_dbg ( & ps2dev - > serio - > dev , " %02x - %x \n " , byte , ps2dev - > nak ) ;
2018-01-04 22:01:43 -08:00
serio_continue_rx ( ps2dev - > serio ) ;
2018-01-02 12:21:49 -08:00
return retval ;
}
2006-09-14 01:31:40 -04:00
EXPORT_SYMBOL ( ps2_sendbyte ) ;
2005-04-16 15:20:36 -07:00
2009-09-16 01:06:43 -07:00
void ps2_begin_command ( struct ps2dev * ps2dev )
{
2016-07-25 11:36:54 -07:00
struct mutex * m = ps2dev - > serio - > ps2_cmd_mutex ? : & ps2dev - > cmd_mutex ;
2009-09-16 01:06:43 -07:00
2016-07-25 11:36:54 -07:00
mutex_lock ( m ) ;
2009-09-16 01:06:43 -07:00
}
EXPORT_SYMBOL ( ps2_begin_command ) ;
void ps2_end_command ( struct ps2dev * ps2dev )
{
2016-07-25 11:36:54 -07:00
struct mutex * m = ps2dev - > serio - > ps2_cmd_mutex ? : & ps2dev - > cmd_mutex ;
2009-09-16 01:06:43 -07:00
2016-07-25 11:36:54 -07:00
mutex_unlock ( m ) ;
2009-09-16 01:06:43 -07:00
}
EXPORT_SYMBOL ( ps2_end_command ) ;
2005-06-01 02:39:51 -05:00
/*
* ps2_drain ( ) waits for device to transmit requested number of bytes
* and discards them .
*/
2018-01-04 10:58:48 -08:00
void ps2_drain ( struct ps2dev * ps2dev , size_t maxbytes , unsigned int timeout )
2005-06-01 02:39:51 -05:00
{
if ( maxbytes > sizeof ( ps2dev - > cmdbuf ) ) {
WARN_ON ( 1 ) ;
maxbytes = sizeof ( ps2dev - > cmdbuf ) ;
}
2009-09-16 01:06:43 -07:00
ps2_begin_command ( ps2dev ) ;
2005-06-01 02:39:51 -05:00
serio_pause_rx ( ps2dev - > serio ) ;
ps2dev - > flags = PS2_FLAG_CMD ;
ps2dev - > cmdcnt = maxbytes ;
serio_continue_rx ( ps2dev - > serio ) ;
wait_event_timeout ( ps2dev - > wait ,
! ( ps2dev - > flags & PS2_FLAG_CMD ) ,
msecs_to_jiffies ( timeout ) ) ;
2009-09-16 01:06:43 -07:00
ps2_end_command ( ps2dev ) ;
2005-06-01 02:39:51 -05:00
}
2006-09-14 01:31:40 -04:00
EXPORT_SYMBOL ( ps2_drain ) ;
2005-06-01 02:39:51 -05:00
2005-06-01 02:39:53 -05:00
/*
* ps2_is_keyboard_id ( ) checks received ID byte against the list of
* known keyboard IDs .
*/
2018-01-04 10:58:48 -08:00
bool ps2_is_keyboard_id ( u8 id_byte )
2005-06-01 02:39:53 -05:00
{
2018-01-04 10:58:48 -08:00
static const u8 keyboard_ids [ ] = {
2005-06-01 02:39:53 -05:00
0xab , /* Regular keyboards */
0xac , /* NCD Sun keyboard */
0x2b , /* Trust keyboard, translated */
0x5d , /* Trust keyboard */
0x60 , /* NMB SGI keyboard, translated */
0x47 , /* NMB SGI keyboard */
} ;
return memchr ( keyboard_ids , id_byte , sizeof ( keyboard_ids ) ) ! = NULL ;
}
2006-09-14 01:31:40 -04:00
EXPORT_SYMBOL ( ps2_is_keyboard_id ) ;
2005-06-01 02:39:53 -05:00
/*
* ps2_adjust_timeout ( ) is called after receiving 1 st byte of command
* response and tries to reduce remaining timeout to speed up command
* completion .
*/
2018-01-04 10:58:48 -08:00
static int ps2_adjust_timeout ( struct ps2dev * ps2dev ,
unsigned int command , unsigned int timeout )
2005-06-01 02:39:53 -05:00
{
switch ( command ) {
2018-01-04 11:05:30 -08:00
case PS2_CMD_RESET_BAT :
/*
* Device has sent the first response byte after
* reset command , reset is thus done , so we can
* shorten the timeout .
* The next byte will come soon ( keyboard ) or not
* at all ( mouse ) .
*/
if ( timeout > msecs_to_jiffies ( 100 ) )
timeout = msecs_to_jiffies ( 100 ) ;
break ;
2005-06-01 02:39:53 -05:00
2018-01-04 11:05:30 -08:00
case PS2_CMD_GETID :
/*
* Microsoft Natural Elite keyboard responds to
* the GET ID command as it were a mouse , with
* a single byte . Fail the command so atkbd will
* use alternative probe to detect it .
*/
if ( ps2dev - > cmdbuf [ 1 ] = = 0xaa ) {
serio_pause_rx ( ps2dev - > serio ) ;
ps2dev - > flags = 0 ;
serio_continue_rx ( ps2dev - > serio ) ;
timeout = 0 ;
}
2005-06-01 02:39:53 -05:00
2018-01-04 11:05:30 -08:00
/*
* If device behind the port is not a keyboard there
* won ' t be 2 nd byte of ID response .
*/
if ( ! ps2_is_keyboard_id ( ps2dev - > cmdbuf [ 1 ] ) ) {
serio_pause_rx ( ps2dev - > serio ) ;
ps2dev - > flags = ps2dev - > cmdcnt = 0 ;
serio_continue_rx ( ps2dev - > serio ) ;
timeout = 0 ;
}
break ;
default :
break ;
2005-06-01 02:39:53 -05:00
}
return timeout ;
}
2005-04-16 15:20:36 -07:00
/*
* ps2_command ( ) sends a command and its parameters to the mouse ,
* then waits for the response and puts it in the param array .
*
* ps2_command ( ) can only be called from a process context
*/
2018-01-04 10:58:48 -08:00
int __ps2_command ( struct ps2dev * ps2dev , u8 * param , unsigned int command )
2005-04-16 15:20:36 -07:00
{
2018-01-04 10:58:48 -08:00
unsigned int timeout ;
unsigned int send = ( command > > 12 ) & 0xf ;
unsigned int receive = ( command > > 8 ) & 0xf ;
2018-01-04 22:01:43 -08:00
int rc ;
2005-04-16 15:20:36 -07:00
int i ;
2018-01-02 12:21:49 -08:00
u8 send_param [ 16 ] ;
2005-04-16 15:20:36 -07:00
2005-06-01 02:39:51 -05:00
if ( receive > sizeof ( ps2dev - > cmdbuf ) ) {
WARN_ON ( 1 ) ;
2018-01-04 22:01:43 -08:00
return - EINVAL ;
2005-06-01 02:39:51 -05:00
}
2006-07-06 23:54:48 -04:00
if ( send & & ! param ) {
WARN_ON ( 1 ) ;
2018-01-04 22:01:43 -08:00
return - EINVAL ;
2006-07-06 23:54:48 -04:00
}
2018-01-02 12:21:49 -08:00
memcpy ( send_param , param , send ) ;
2005-04-16 15:20:36 -07:00
serio_pause_rx ( ps2dev - > serio ) ;
2018-01-04 22:01:43 -08:00
2005-04-16 15:20:36 -07:00
ps2dev - > flags = command = = PS2_CMD_GETID ? PS2_FLAG_WAITID : 0 ;
ps2dev - > cmdcnt = receive ;
if ( receive & & param )
for ( i = 0 ; i < receive ; i + + )
ps2dev - > cmdbuf [ ( receive - 1 ) - i ] = param [ i ] ;
2018-01-17 12:00:24 -08:00
/* Signal that we are sending the command byte */
ps2dev - > flags | = PS2_FLAG_ACK_CMD ;
2005-04-16 15:20:36 -07:00
/*
* Some devices ( Synaptics ) peform the reset before
* ACKing the reset command , and so it can take a long
2011-06-22 23:29:19 -07:00
* time before the ACK arrives .
2005-04-16 15:20:36 -07:00
*/
2018-01-17 12:00:24 -08:00
timeout = command = = PS2_CMD_RESET_BAT ? 1000 : 200 ;
rc = ps2_do_sendbyte ( ps2dev , command & 0xff , timeout , 2 ) ;
2018-01-04 22:01:43 -08:00
if ( rc )
2015-09-29 15:54:58 -07:00
goto out_reset_flags ;
2005-04-16 15:20:36 -07:00
2018-01-17 12:00:24 -08:00
/* Now we are sending command parameters, if any */
ps2dev - > flags & = ~ PS2_FLAG_ACK_CMD ;
2015-09-29 15:54:58 -07:00
for ( i = 0 ; i < send ; i + + ) {
2018-01-04 22:01:43 -08:00
rc = ps2_do_sendbyte ( ps2dev , param [ i ] , 200 , 2 ) ;
if ( rc )
2015-09-29 15:54:58 -07:00
goto out_reset_flags ;
}
2005-04-16 15:20:36 -07:00
2018-01-04 22:01:43 -08:00
serio_continue_rx ( ps2dev - > serio ) ;
2005-04-16 15:20:36 -07:00
/*
* The reset command takes a long time to execute .
*/
timeout = msecs_to_jiffies ( command = = PS2_CMD_RESET_BAT ? 4000 : 500 ) ;
timeout = wait_event_timeout ( ps2dev - > wait ,
! ( ps2dev - > flags & PS2_FLAG_CMD1 ) , timeout ) ;
2009-05-28 09:51:31 -07:00
if ( ps2dev - > cmdcnt & & ! ( ps2dev - > flags & PS2_FLAG_CMD1 ) ) {
2005-04-16 15:20:36 -07:00
2005-06-01 02:39:53 -05:00
timeout = ps2_adjust_timeout ( ps2dev , command , timeout ) ;
2005-04-16 15:20:36 -07:00
wait_event_timeout ( ps2dev - > wait ,
! ( ps2dev - > flags & PS2_FLAG_CMD ) , timeout ) ;
}
2015-09-29 15:54:58 -07:00
serio_pause_rx ( ps2dev - > serio ) ;
2005-04-16 15:20:36 -07:00
if ( param )
for ( i = 0 ; i < receive ; i + + )
param [ i ] = ps2dev - > cmdbuf [ ( receive - 1 ) - i ] ;
2018-01-04 22:01:43 -08:00
if ( ps2dev - > cmdcnt & &
( command ! = PS2_CMD_RESET_BAT | | ps2dev - > cmdcnt ! = 1 ) ) {
rc = - EPROTO ;
2015-09-29 15:54:58 -07:00
goto out_reset_flags ;
2018-01-04 22:01:43 -08:00
}
2005-04-16 15:20:36 -07:00
rc = 0 ;
2015-09-29 15:54:58 -07:00
out_reset_flags :
2005-04-16 15:20:36 -07:00
ps2dev - > flags = 0 ;
serio_continue_rx ( ps2dev - > serio ) ;
2018-01-02 12:21:49 -08:00
dev_dbg ( & ps2dev - > serio - > dev ,
" %02x [%*ph] - %x/%08lx [%*ph] \n " ,
command & 0xff , send , send_param ,
ps2dev - > nak , ps2dev - > flags ,
receive , param ? : send_param ) ;
2018-01-04 22:01:43 -08:00
/*
* ps_command ( ) handles resends itself , so do not leak - EAGAIN
* to the callers .
*/
return rc ! = - EAGAIN ? rc : - EPROTO ;
2009-05-10 18:15:39 -07:00
}
EXPORT_SYMBOL ( __ps2_command ) ;
2018-01-04 10:58:48 -08:00
int ps2_command ( struct ps2dev * ps2dev , u8 * param , unsigned int command )
2009-05-10 18:15:39 -07:00
{
int rc ;
2009-09-16 01:06:43 -07:00
ps2_begin_command ( ps2dev ) ;
2009-05-10 18:15:39 -07:00
rc = __ps2_command ( ps2dev , param , command ) ;
2009-09-16 01:06:43 -07:00
ps2_end_command ( ps2dev ) ;
2009-05-10 18:15:39 -07:00
2005-04-16 15:20:36 -07:00
return rc ;
}
2006-09-14 01:31:40 -04:00
EXPORT_SYMBOL ( ps2_command ) ;
2005-04-16 15:20:36 -07:00
2018-01-02 12:03:02 -08:00
/*
* ps2_sliced_command ( ) sends an extended PS / 2 command to the mouse
* using sliced syntax , understood by advanced devices , such as Logitech
* or Synaptics touchpads . The command is encoded as :
* 0xE6 0xE8 rr 0xE8 ss 0xE8 tt 0xE8 uu where ( rr * 64 ) + ( ss * 16 ) + ( tt * 4 ) + uu
* is the command .
*/
int ps2_sliced_command ( struct ps2dev * ps2dev , u8 command )
{
int i ;
int retval ;
ps2_begin_command ( ps2dev ) ;
retval = __ps2_command ( ps2dev , NULL , PS2_CMD_SETSCALE11 ) ;
if ( retval )
goto out ;
for ( i = 6 ; i > = 0 ; i - = 2 ) {
u8 d = ( command > > i ) & 3 ;
retval = __ps2_command ( ps2dev , & d , PS2_CMD_SETRES ) ;
if ( retval )
break ;
}
out :
2018-01-02 12:21:49 -08:00
dev_dbg ( & ps2dev - > serio - > dev , " %02x - %d \n " , command , retval ) ;
2018-01-02 12:03:02 -08:00
ps2_end_command ( ps2dev ) ;
return retval ;
}
EXPORT_SYMBOL ( ps2_sliced_command ) ;
2005-04-16 15:20:36 -07:00
/*
* ps2_init ( ) initializes ps2dev structure
*/
void ps2_init ( struct ps2dev * ps2dev , struct serio * serio )
{
2006-02-19 00:21:55 -05:00
mutex_init ( & ps2dev - > cmd_mutex ) ;
2006-10-11 01:45:31 -04:00
lockdep_set_subclass ( & ps2dev - > cmd_mutex , serio - > depth ) ;
2005-04-16 15:20:36 -07:00
init_waitqueue_head ( & ps2dev - > wait ) ;
ps2dev - > serio = serio ;
}
2006-09-14 01:31:40 -04:00
EXPORT_SYMBOL ( ps2_init ) ;
2005-04-16 15:20:36 -07:00
/*
* ps2_handle_ack ( ) is supposed to be used in interrupt handler
* to properly process ACK / NAK of a command from a PS / 2 device .
*/
2018-01-04 10:58:48 -08:00
bool ps2_handle_ack ( struct ps2dev * ps2dev , u8 data )
2005-04-16 15:20:36 -07:00
{
switch ( data ) {
2018-01-04 11:05:30 -08:00
case PS2_RET_ACK :
ps2dev - > nak = 0 ;
break ;
case PS2_RET_NAK :
ps2dev - > flags | = PS2_FLAG_NAK ;
ps2dev - > nak = PS2_RET_NAK ;
break ;
case PS2_RET_ERR :
if ( ps2dev - > flags & PS2_FLAG_NAK ) {
ps2dev - > flags & = ~ PS2_FLAG_NAK ;
ps2dev - > nak = PS2_RET_ERR ;
2005-04-16 15:20:36 -07:00
break ;
2018-01-04 11:05:30 -08:00
}
2020-11-22 22:15:43 -08:00
fallthrough ;
2005-04-16 15:20:36 -07:00
2018-01-04 11:05:30 -08:00
/*
* Workaround for mice which don ' t ACK the Get ID command .
* These are valid mouse IDs that we recognize .
*/
case 0x00 :
case 0x03 :
case 0x04 :
if ( ps2dev - > flags & PS2_FLAG_WAITID ) {
ps2dev - > nak = 0 ;
2005-04-16 15:20:36 -07:00
break ;
2018-01-04 11:05:30 -08:00
}
2020-07-07 11:24:55 -07:00
fallthrough ;
2018-01-04 11:05:30 -08:00
default :
2018-01-17 12:00:24 -08:00
/*
* Do not signal errors if we get unexpected reply while
* waiting for an ACK to the initial ( first ) command byte :
* the device might not be quiesced yet and continue
* delivering data .
* Note that we reset PS2_FLAG_WAITID flag , so the workaround
* for mice not acknowledging the Get ID command only triggers
* on the 1 st byte ; if device spews data we really want to see
* a real ACK from it .
*/
dev_dbg ( & ps2dev - > serio - > dev , " unexpected %#02x \n " , data ) ;
ps2dev - > flags & = ~ PS2_FLAG_WAITID ;
return ps2dev - > flags & PS2_FLAG_ACK_CMD ;
2005-04-16 15:20:36 -07:00
}
2008-11-19 17:02:24 -05:00
if ( ! ps2dev - > nak ) {
ps2dev - > flags & = ~ PS2_FLAG_NAK ;
if ( ps2dev - > cmdcnt )
ps2dev - > flags | = PS2_FLAG_CMD | PS2_FLAG_CMD1 ;
}
2005-04-16 15:20:36 -07:00
ps2dev - > flags & = ~ PS2_FLAG_ACK ;
wake_up ( & ps2dev - > wait ) ;
if ( data ! = PS2_RET_ACK )
ps2_handle_response ( ps2dev , data ) ;
2018-01-04 10:58:48 -08:00
return true ;
2005-04-16 15:20:36 -07:00
}
2006-09-14 01:31:40 -04:00
EXPORT_SYMBOL ( ps2_handle_ack ) ;
2005-04-16 15:20:36 -07:00
/*
* ps2_handle_response ( ) is supposed to be used in interrupt handler
* to properly store device ' s response to a command and notify process
* waiting for completion of the command .
*/
2018-01-04 10:58:48 -08:00
bool ps2_handle_response ( struct ps2dev * ps2dev , u8 data )
2005-04-16 15:20:36 -07:00
{
if ( ps2dev - > cmdcnt )
ps2dev - > cmdbuf [ - - ps2dev - > cmdcnt ] = data ;
if ( ps2dev - > flags & PS2_FLAG_CMD1 ) {
ps2dev - > flags & = ~ PS2_FLAG_CMD1 ;
if ( ps2dev - > cmdcnt )
wake_up ( & ps2dev - > wait ) ;
}
if ( ! ps2dev - > cmdcnt ) {
ps2dev - > flags & = ~ PS2_FLAG_CMD ;
wake_up ( & ps2dev - > wait ) ;
}
2018-01-04 10:58:48 -08:00
return true ;
2005-04-16 15:20:36 -07:00
}
2006-09-14 01:31:40 -04:00
EXPORT_SYMBOL ( ps2_handle_response ) ;
2005-04-16 15:20:36 -07:00
void ps2_cmd_aborted ( struct ps2dev * ps2dev )
{
if ( ps2dev - > flags & PS2_FLAG_ACK )
ps2dev - > nak = 1 ;
if ( ps2dev - > flags & ( PS2_FLAG_ACK | PS2_FLAG_CMD ) )
wake_up ( & ps2dev - > wait ) ;
2008-11-19 17:02:24 -05:00
/* reset all flags except last nack */
ps2dev - > flags & = PS2_FLAG_NAK ;
2005-04-16 15:20:36 -07:00
}
2006-09-14 01:31:40 -04:00
EXPORT_SYMBOL ( ps2_cmd_aborted ) ;