2005-04-17 02:20:36 +04:00
/*
* The input core
*
* Copyright ( c ) 1999 - 2002 Vojtech Pavlik
*/
/*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation .
*/
# include <linux/init.h>
2009-09-16 12:06:43 +04:00
# include <linux/types.h>
2005-04-17 02:20:36 +04:00
# include <linux/input.h>
# include <linux/module.h>
# include <linux/random.h>
# include <linux/major.h>
# include <linux/proc_fs.h>
2009-10-04 16:11:37 +04:00
# include <linux/sched.h>
2006-04-02 09:09:34 +04:00
# include <linux/seq_file.h>
2005-04-17 02:20:36 +04:00
# include <linux/poll.h>
# include <linux/device.h>
2006-02-19 08:21:46 +03:00
# include <linux/mutex.h>
2007-08-30 08:22:11 +04:00
# include <linux/rcupdate.h>
2008-05-15 20:37:16 +04:00
# include <linux/smp_lock.h>
2005-04-17 02:20:36 +04:00
MODULE_AUTHOR ( " Vojtech Pavlik <vojtech@suse.cz> " ) ;
MODULE_DESCRIPTION ( " Input core " ) ;
MODULE_LICENSE ( " GPL " ) ;
# define INPUT_DEVICES 256
2009-04-28 18:45:31 +04:00
/*
* EV_ABS events which should not be cached are listed here .
*/
static unsigned int input_abs_bypass_init_data [ ] __initdata = {
Input: add detailed multi-touch finger data report protocol
In order to utilize the full power of the new multi-touch devices, a
way to report detailed finger data to user space is needed. This patch
adds a multi-touch (MT) protocol which allows drivers to report details
for an arbitrary number of fingers.
The driver sends a SYN_MT_REPORT event via the input_mt_sync() function
when a complete finger has been reported.
In order to stay compatible with existing applications, the data
reported in a finger packet must not be recognized as single-touch
events. In addition, all finger data must bypass input filtering,
since subsequent events of the same type refer to different fingers.
A set of ABS_MT events with the desired properties are defined. The
events are divided into categories, to allow for partial implementation.
The minimum set consists of ABS_MT_TOUCH_MAJOR, ABS_MT_POSITION_X and
ABS_MT_POSITION_Y, which allows for multiple fingers to be tracked.
If the device supports it, the ABS_MT_WIDTH_MAJOR may be used to provide
the size of the approaching finger. Anisotropy and direction may be
specified with ABS_MT_TOUCH_MINOR, ABS_MT_WIDTH_MINOR and
ABS_MT_ORIENTATION. Devices with more granular information may specify
general shapes as blobs, i.e., as a sequence of rectangular shapes
grouped together by a ABS_MT_BLOB_ID. Finally, the ABS_MT_TOOL_TYPE
may be used to specify whether the touching tool is a finger or a pen.
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2009-04-28 18:47:33 +04:00
ABS_MT_TOUCH_MAJOR ,
ABS_MT_TOUCH_MINOR ,
ABS_MT_WIDTH_MAJOR ,
ABS_MT_WIDTH_MINOR ,
ABS_MT_ORIENTATION ,
ABS_MT_POSITION_X ,
ABS_MT_POSITION_Y ,
ABS_MT_TOOL_TYPE ,
ABS_MT_BLOB_ID ,
2009-05-23 20:51:20 +04:00
ABS_MT_TRACKING_ID ,
2009-04-28 18:45:31 +04:00
0
} ;
static unsigned long input_abs_bypass [ BITS_TO_LONGS ( ABS_CNT ) ] ;
2005-04-17 02:20:36 +04:00
static LIST_HEAD ( input_dev_list ) ;
static LIST_HEAD ( input_handler_list ) ;
2007-08-30 08:22:11 +04:00
/*
* input_mutex protects access to both input_dev_list and input_handler_list .
* This also causes input_ [ un ] register_device and input_ [ un ] register_handler
* be mutually exclusive which simplifies locking in drivers implementing
* input handlers .
*/
static DEFINE_MUTEX ( input_mutex ) ;
2005-04-17 02:20:36 +04:00
static struct input_handler * input_table [ 8 ] ;
2007-08-30 08:22:11 +04:00
static inline int is_event_supported ( unsigned int code ,
unsigned long * bm , unsigned int max )
2005-04-17 02:20:36 +04:00
{
2007-08-30 08:22:11 +04:00
return code < = max & & test_bit ( code , bm ) ;
}
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
static int input_defuzz_abs_event ( int value , int old_val , int fuzz )
{
if ( fuzz ) {
if ( value > old_val - fuzz / 2 & & value < old_val + fuzz / 2 )
return old_val ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
if ( value > old_val - fuzz & & value < old_val + fuzz )
return ( old_val * 3 + value ) / 4 ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
if ( value > old_val - fuzz * 2 & & value < old_val + fuzz * 2 )
return ( old_val + value ) / 2 ;
}
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
return value ;
}
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
/*
* Pass event through all open handles . This function is called with
2007-10-13 23:46:55 +04:00
* dev - > event_lock held and interrupts disabled .
2007-08-30 08:22:11 +04:00
*/
static void input_pass_event ( struct input_dev * dev ,
unsigned int type , unsigned int code , int value )
{
2007-10-13 23:46:55 +04:00
struct input_handle * handle ;
rcu_read_lock ( ) ;
2005-04-17 02:20:36 +04:00
2007-10-13 23:46:55 +04:00
handle = rcu_dereference ( dev - > grab ) ;
2007-08-30 08:22:11 +04:00
if ( handle )
handle - > handler - > event ( handle , type , code , value ) ;
else
list_for_each_entry_rcu ( handle , & dev - > h_list , d_node )
if ( handle - > open )
handle - > handler - > event ( handle ,
type , code , value ) ;
2007-10-13 23:46:55 +04:00
rcu_read_unlock ( ) ;
2007-08-30 08:22:11 +04:00
}
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
/*
* Generate software autorepeat event . Note that we take
* dev - > event_lock here to avoid racing with input_event
* which may cause keys get " stuck " .
*/
static void input_repeat_key ( unsigned long data )
{
struct input_dev * dev = ( void * ) data ;
unsigned long flags ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
spin_lock_irqsave ( & dev - > event_lock , flags ) ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
if ( test_bit ( dev - > repeat_key , dev - > key ) & &
is_event_supported ( dev - > repeat_key , dev - > keybit , KEY_MAX ) ) {
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
input_pass_event ( dev , EV_KEY , dev - > repeat_key , 2 ) ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
if ( dev - > sync ) {
/*
* Only send SYN_REPORT if we are not in a middle
* of driver parsing a new hardware packet .
* Otherwise assume that the driver will send
* SYN_REPORT once it ' s done .
*/
input_pass_event ( dev , EV_SYN , SYN_REPORT , 1 ) ;
}
2005-09-07 02:19:06 +04:00
2007-08-30 08:22:11 +04:00
if ( dev - > rep [ REP_PERIOD ] )
mod_timer ( & dev - > timer , jiffies +
msecs_to_jiffies ( dev - > rep [ REP_PERIOD ] ) ) ;
}
2005-09-07 02:19:06 +04:00
2007-08-30 08:22:11 +04:00
spin_unlock_irqrestore ( & dev - > event_lock , flags ) ;
}
2005-09-07 02:19:06 +04:00
2007-08-30 08:22:11 +04:00
static void input_start_autorepeat ( struct input_dev * dev , int code )
{
if ( test_bit ( EV_REP , dev - > evbit ) & &
dev - > rep [ REP_PERIOD ] & & dev - > rep [ REP_DELAY ] & &
dev - > timer . data ) {
dev - > repeat_key = code ;
mod_timer ( & dev - > timer ,
jiffies + msecs_to_jiffies ( dev - > rep [ REP_DELAY ] ) ) ;
}
}
2005-09-07 02:19:06 +04:00
2009-01-30 10:17:52 +03:00
static void input_stop_autorepeat ( struct input_dev * dev )
{
del_timer ( & dev - > timer ) ;
}
2007-08-30 08:22:11 +04:00
# define INPUT_IGNORE_EVENT 0
# define INPUT_PASS_TO_HANDLERS 1
# define INPUT_PASS_TO_DEVICE 2
# define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
static void input_handle_event ( struct input_dev * dev ,
unsigned int type , unsigned int code , int value )
{
int disposition = INPUT_IGNORE_EVENT ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
switch ( type ) {
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
case EV_SYN :
switch ( code ) {
case SYN_CONFIG :
disposition = INPUT_PASS_TO_ALL ;
break ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
case SYN_REPORT :
if ( ! dev - > sync ) {
dev - > sync = 1 ;
disposition = INPUT_PASS_TO_HANDLERS ;
2005-04-17 02:20:36 +04:00
}
break ;
Input: add detailed multi-touch finger data report protocol
In order to utilize the full power of the new multi-touch devices, a
way to report detailed finger data to user space is needed. This patch
adds a multi-touch (MT) protocol which allows drivers to report details
for an arbitrary number of fingers.
The driver sends a SYN_MT_REPORT event via the input_mt_sync() function
when a complete finger has been reported.
In order to stay compatible with existing applications, the data
reported in a finger packet must not be recognized as single-touch
events. In addition, all finger data must bypass input filtering,
since subsequent events of the same type refer to different fingers.
A set of ABS_MT events with the desired properties are defined. The
events are divided into categories, to allow for partial implementation.
The minimum set consists of ABS_MT_TOUCH_MAJOR, ABS_MT_POSITION_X and
ABS_MT_POSITION_Y, which allows for multiple fingers to be tracked.
If the device supports it, the ABS_MT_WIDTH_MAJOR may be used to provide
the size of the approaching finger. Anisotropy and direction may be
specified with ABS_MT_TOUCH_MINOR, ABS_MT_WIDTH_MINOR and
ABS_MT_ORIENTATION. Devices with more granular information may specify
general shapes as blobs, i.e., as a sequence of rectangular shapes
grouped together by a ABS_MT_BLOB_ID. Finally, the ABS_MT_TOOL_TYPE
may be used to specify whether the touching tool is a finger or a pen.
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
2009-04-28 18:47:33 +04:00
case SYN_MT_REPORT :
dev - > sync = 0 ;
disposition = INPUT_PASS_TO_HANDLERS ;
break ;
2007-08-30 08:22:11 +04:00
}
break ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
case EV_KEY :
if ( is_event_supported ( code , dev - > keybit , KEY_MAX ) & &
! ! test_bit ( code , dev - > key ) ! = value ) {
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
if ( value ! = 2 ) {
__change_bit ( code , dev - > key ) ;
if ( value )
input_start_autorepeat ( dev , code ) ;
2009-01-30 10:17:52 +03:00
else
input_stop_autorepeat ( dev ) ;
2007-08-30 08:22:11 +04:00
}
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
disposition = INPUT_PASS_TO_HANDLERS ;
}
break ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
case EV_SW :
if ( is_event_supported ( code , dev - > swbit , SW_MAX ) & &
! ! test_bit ( code , dev - > sw ) ! = value ) {
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
__change_bit ( code , dev - > sw ) ;
disposition = INPUT_PASS_TO_HANDLERS ;
}
break ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
case EV_ABS :
if ( is_event_supported ( code , dev - > absbit , ABS_MAX ) ) {
2005-04-17 02:20:36 +04:00
2009-04-28 18:45:31 +04:00
if ( test_bit ( code , input_abs_bypass ) ) {
disposition = INPUT_PASS_TO_HANDLERS ;
break ;
}
2007-08-30 08:22:11 +04:00
value = input_defuzz_abs_event ( value ,
dev - > abs [ code ] , dev - > absfuzz [ code ] ) ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
if ( dev - > abs [ code ] ! = value ) {
dev - > abs [ code ] = value ;
disposition = INPUT_PASS_TO_HANDLERS ;
}
}
break ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
case EV_REL :
if ( is_event_supported ( code , dev - > relbit , REL_MAX ) & & value )
disposition = INPUT_PASS_TO_HANDLERS ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
break ;
2006-06-26 09:48:47 +04:00
2007-08-30 08:22:11 +04:00
case EV_MSC :
if ( is_event_supported ( code , dev - > mscbit , MSC_MAX ) )
disposition = INPUT_PASS_TO_ALL ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
break ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
case EV_LED :
if ( is_event_supported ( code , dev - > ledbit , LED_MAX ) & &
! ! test_bit ( code , dev - > led ) ! = value ) {
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
__change_bit ( code , dev - > led ) ;
disposition = INPUT_PASS_TO_ALL ;
}
break ;
case EV_SND :
if ( is_event_supported ( code , dev - > sndbit , SND_MAX ) ) {
2005-04-17 02:20:36 +04:00
2006-04-29 09:13:48 +04:00
if ( ! ! test_bit ( code , dev - > snd ) ! = ! ! value )
2007-08-30 08:22:11 +04:00
__change_bit ( code , dev - > snd ) ;
disposition = INPUT_PASS_TO_ALL ;
}
break ;
2006-04-29 09:13:48 +04:00
2007-08-30 08:22:11 +04:00
case EV_REP :
if ( code < = REP_MAX & & value > = 0 & & dev - > rep [ code ] ! = value ) {
dev - > rep [ code ] = value ;
disposition = INPUT_PASS_TO_ALL ;
}
break ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
case EV_FF :
if ( value > = 0 )
disposition = INPUT_PASS_TO_ALL ;
break ;
2008-01-03 18:46:21 +03:00
case EV_PWR :
disposition = INPUT_PASS_TO_ALL ;
break ;
2007-08-30 08:22:11 +04:00
}
2005-04-17 02:20:36 +04:00
2008-06-02 09:02:40 +04:00
if ( disposition ! = INPUT_IGNORE_EVENT & & type ! = EV_SYN )
2007-08-30 08:22:11 +04:00
dev - > sync = 0 ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
if ( ( disposition & INPUT_PASS_TO_DEVICE ) & & dev - > event )
dev - > event ( dev , type , code , value ) ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
if ( disposition & INPUT_PASS_TO_HANDLERS )
input_pass_event ( dev , type , code , value ) ;
}
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
/**
* input_event ( ) - report new input event
* @ dev : device that generated the event
* @ type : type of the event
* @ code : event code
* @ value : value of the event
*
* This function should be used by drivers implementing various input
* devices . See also input_inject_event ( ) .
*/
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
void input_event ( struct input_dev * dev ,
unsigned int type , unsigned int code , int value )
{
unsigned long flags ;
2006-07-19 09:40:22 +04:00
2007-08-30 08:22:11 +04:00
if ( is_event_supported ( type , dev - > evbit , EV_MAX ) ) {
2006-07-19 09:40:22 +04:00
2007-08-30 08:22:11 +04:00
spin_lock_irqsave ( & dev - > event_lock , flags ) ;
add_input_randomness ( type , code , value ) ;
input_handle_event ( dev , type , code , value ) ;
spin_unlock_irqrestore ( & dev - > event_lock , flags ) ;
2005-04-17 02:20:36 +04:00
}
}
2006-06-26 09:49:21 +04:00
EXPORT_SYMBOL ( input_event ) ;
2005-04-17 02:20:36 +04:00
2006-07-06 08:22:43 +04:00
/**
* input_inject_event ( ) - send input event from input handler
* @ handle : input handle to send event through
* @ type : type of the event
* @ code : event code
* @ value : value of the event
*
2007-08-30 08:22:11 +04:00
* Similar to input_event ( ) but will ignore event if device is
* " grabbed " and handle injecting event is not the one that owns
* the device .
2006-07-06 08:22:43 +04:00
*/
2007-08-30 08:22:11 +04:00
void input_inject_event ( struct input_handle * handle ,
unsigned int type , unsigned int code , int value )
2005-04-17 02:20:36 +04:00
{
2007-08-30 08:22:11 +04:00
struct input_dev * dev = handle - > dev ;
struct input_handle * grab ;
unsigned long flags ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
if ( is_event_supported ( type , dev - > evbit , EV_MAX ) ) {
spin_lock_irqsave ( & dev - > event_lock , flags ) ;
2005-04-17 02:20:36 +04:00
2007-10-13 23:46:55 +04:00
rcu_read_lock ( ) ;
2007-08-30 08:22:11 +04:00
grab = rcu_dereference ( dev - > grab ) ;
if ( ! grab | | grab = = handle )
input_handle_event ( dev , type , code , value ) ;
2007-10-13 23:46:55 +04:00
rcu_read_unlock ( ) ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
spin_unlock_irqrestore ( & dev - > event_lock , flags ) ;
}
2005-04-17 02:20:36 +04:00
}
2007-08-30 08:22:11 +04:00
EXPORT_SYMBOL ( input_inject_event ) ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
/**
* input_grab_device - grabs device for exclusive use
* @ handle : input handle that wants to own the device
*
* When a device is grabbed by an input handle all events generated by
* the device are delivered only to this handle . Also events injected
* by other input handles are ignored while device is grabbed .
*/
2005-04-17 02:20:36 +04:00
int input_grab_device ( struct input_handle * handle )
{
2007-08-30 08:22:11 +04:00
struct input_dev * dev = handle - > dev ;
int retval ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
retval = mutex_lock_interruptible ( & dev - > mutex ) ;
if ( retval )
return retval ;
if ( dev - > grab ) {
retval = - EBUSY ;
goto out ;
}
rcu_assign_pointer ( dev - > grab , handle ) ;
2007-10-13 23:46:55 +04:00
synchronize_rcu ( ) ;
2007-08-30 08:22:11 +04:00
out :
mutex_unlock ( & dev - > mutex ) ;
return retval ;
2005-04-17 02:20:36 +04:00
}
2006-06-26 09:49:21 +04:00
EXPORT_SYMBOL ( input_grab_device ) ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
static void __input_release_device ( struct input_handle * handle )
2005-04-17 02:20:36 +04:00
{
2006-07-15 09:17:38 +04:00
struct input_dev * dev = handle - > dev ;
2006-07-06 08:21:03 +04:00
2006-07-15 09:17:38 +04:00
if ( dev - > grab = = handle ) {
2007-08-30 08:22:11 +04:00
rcu_assign_pointer ( dev - > grab , NULL ) ;
/* Make sure input_pass_event() notices that grab is gone */
2007-10-13 23:46:55 +04:00
synchronize_rcu ( ) ;
2006-07-15 09:17:38 +04:00
list_for_each_entry ( handle , & dev - > h_list , d_node )
2007-08-30 08:22:11 +04:00
if ( handle - > open & & handle - > handler - > start )
2006-07-06 08:21:03 +04:00
handle - > handler - > start ( handle ) ;
}
2005-04-17 02:20:36 +04:00
}
2007-08-30 08:22:11 +04:00
/**
* input_release_device - release previously grabbed device
* @ handle : input handle that owns the device
*
* Releases previously grabbed device so that other input handles can
* start receiving input events . Upon release all handlers attached
* to the device have their start ( ) method called so they have a change
* to synchronize device state with the rest of the system .
*/
void input_release_device ( struct input_handle * handle )
{
struct input_dev * dev = handle - > dev ;
mutex_lock ( & dev - > mutex ) ;
__input_release_device ( handle ) ;
mutex_unlock ( & dev - > mutex ) ;
}
2006-06-26 09:49:21 +04:00
EXPORT_SYMBOL ( input_release_device ) ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
/**
* input_open_device - open input device
* @ handle : handle through which device is being accessed
*
* This function should be called by input handlers when they
* want to start receive events from given input device .
*/
2005-04-17 02:20:36 +04:00
int input_open_device ( struct input_handle * handle )
{
2005-05-29 11:29:25 +04:00
struct input_dev * dev = handle - > dev ;
2007-08-30 08:22:11 +04:00
int retval ;
2005-05-29 11:29:25 +04:00
2007-08-30 08:22:11 +04:00
retval = mutex_lock_interruptible ( & dev - > mutex ) ;
if ( retval )
return retval ;
if ( dev - > going_away ) {
retval = - ENODEV ;
goto out ;
}
2005-05-29 11:29:25 +04:00
2005-04-17 02:20:36 +04:00
handle - > open + + ;
2005-05-29 11:29:25 +04:00
if ( ! dev - > users + + & & dev - > open )
2007-08-30 08:22:11 +04:00
retval = dev - > open ( dev ) ;
if ( retval ) {
dev - > users - - ;
if ( ! - - handle - > open ) {
/*
* Make sure we are not delivering any more events
* through this handle
*/
2007-10-13 23:46:55 +04:00
synchronize_rcu ( ) ;
2007-08-30 08:22:11 +04:00
}
}
2005-05-29 11:29:25 +04:00
2007-08-30 08:22:11 +04:00
out :
2006-02-19 08:21:46 +03:00
mutex_unlock ( & dev - > mutex ) ;
2007-08-30 08:22:11 +04:00
return retval ;
2005-04-17 02:20:36 +04:00
}
2006-06-26 09:49:21 +04:00
EXPORT_SYMBOL ( input_open_device ) ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
int input_flush_device ( struct input_handle * handle , struct file * file )
2005-04-17 02:20:36 +04:00
{
2007-08-30 08:22:11 +04:00
struct input_dev * dev = handle - > dev ;
int retval ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
retval = mutex_lock_interruptible ( & dev - > mutex ) ;
if ( retval )
return retval ;
if ( dev - > flush )
retval = dev - > flush ( dev , file ) ;
mutex_unlock ( & dev - > mutex ) ;
return retval ;
2005-04-17 02:20:36 +04:00
}
2006-06-26 09:49:21 +04:00
EXPORT_SYMBOL ( input_flush_device ) ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
/**
* input_close_device - close input device
* @ handle : handle through which device is being accessed
*
* This function should be called by input handlers when they
* want to stop receive events from given input device .
*/
2005-04-17 02:20:36 +04:00
void input_close_device ( struct input_handle * handle )
{
2005-05-29 11:29:25 +04:00
struct input_dev * dev = handle - > dev ;
2006-02-19 08:21:46 +03:00
mutex_lock ( & dev - > mutex ) ;
2005-05-29 11:29:25 +04:00
2007-08-30 08:22:11 +04:00
__input_release_device ( handle ) ;
2005-05-29 11:29:25 +04:00
if ( ! - - dev - > users & & dev - > close )
dev - > close ( dev ) ;
2007-08-30 08:22:11 +04:00
if ( ! - - handle - > open ) {
/*
2007-10-13 23:46:55 +04:00
* synchronize_rcu ( ) makes sure that input_pass_event ( )
2007-08-30 08:22:11 +04:00
* completed and that no more input events are delivered
* through this handle
*/
2007-10-13 23:46:55 +04:00
synchronize_rcu ( ) ;
2007-08-30 08:22:11 +04:00
}
2005-05-29 11:29:25 +04:00
2006-02-19 08:21:46 +03:00
mutex_unlock ( & dev - > mutex ) ;
2005-04-17 02:20:36 +04:00
}
2006-06-26 09:49:21 +04:00
EXPORT_SYMBOL ( input_close_device ) ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
/*
* Prepare device for unregistering
*/
static void input_disconnect_device ( struct input_dev * dev )
{
struct input_handle * handle ;
int code ;
/*
* Mark device as going away . Note that we take dev - > mutex here
* not to protect access to dev - > going_away but rather to ensure
* that there are no threads in the middle of input_open_device ( )
*/
mutex_lock ( & dev - > mutex ) ;
2009-09-16 12:06:43 +04:00
dev - > going_away = true ;
2007-08-30 08:22:11 +04:00
mutex_unlock ( & dev - > mutex ) ;
spin_lock_irq ( & dev - > event_lock ) ;
/*
* Simulate keyup events for all pressed keys so that handlers
* are not left with " stuck " keys . The driver may continue
* generate events even after we done here but they will not
* reach any handlers .
*/
if ( is_event_supported ( EV_KEY , dev - > evbit , EV_MAX ) ) {
for ( code = 0 ; code < = KEY_MAX ; code + + ) {
if ( is_event_supported ( code , dev - > keybit , KEY_MAX ) & &
2007-11-04 07:41:12 +03:00
__test_and_clear_bit ( code , dev - > key ) ) {
2007-08-30 08:22:11 +04:00
input_pass_event ( dev , EV_KEY , code , 0 ) ;
}
}
input_pass_event ( dev , EV_SYN , SYN_REPORT , 1 ) ;
}
list_for_each_entry ( handle , & dev - > h_list , d_node )
handle - > open = 0 ;
spin_unlock_irq ( & dev - > event_lock ) ;
}
2007-03-15 05:50:42 +03:00
static int input_fetch_keycode ( struct input_dev * dev , int scancode )
{
switch ( dev - > keycodesize ) {
case 1 :
return ( ( u8 * ) dev - > keycode ) [ scancode ] ;
case 2 :
return ( ( u16 * ) dev - > keycode ) [ scancode ] ;
default :
return ( ( u32 * ) dev - > keycode ) [ scancode ] ;
}
}
static int input_default_getkeycode ( struct input_dev * dev ,
int scancode , int * keycode )
{
if ( ! dev - > keycodesize )
return - EINVAL ;
2007-11-04 07:41:12 +03:00
if ( scancode > = dev - > keycodemax )
2007-03-15 05:50:42 +03:00
return - EINVAL ;
* keycode = input_fetch_keycode ( dev , scancode ) ;
return 0 ;
}
static int input_default_setkeycode ( struct input_dev * dev ,
int scancode , int keycode )
{
int old_keycode ;
int i ;
2007-11-04 07:41:12 +03:00
if ( scancode > = dev - > keycodemax )
2007-03-15 05:50:42 +03:00
return - EINVAL ;
if ( ! dev - > keycodesize )
return - EINVAL ;
if ( dev - > keycodesize < sizeof ( keycode ) & & ( keycode > > ( dev - > keycodesize * 8 ) ) )
return - EINVAL ;
switch ( dev - > keycodesize ) {
case 1 : {
u8 * k = ( u8 * ) dev - > keycode ;
old_keycode = k [ scancode ] ;
k [ scancode ] = keycode ;
break ;
}
case 2 : {
u16 * k = ( u16 * ) dev - > keycode ;
old_keycode = k [ scancode ] ;
k [ scancode ] = keycode ;
break ;
}
default : {
u32 * k = ( u32 * ) dev - > keycode ;
old_keycode = k [ scancode ] ;
k [ scancode ] = keycode ;
break ;
}
}
clear_bit ( old_keycode , dev - > keybit ) ;
set_bit ( keycode , dev - > keybit ) ;
for ( i = 0 ; i < dev - > keycodemax ; i + + ) {
if ( input_fetch_keycode ( dev , i ) = = old_keycode ) {
set_bit ( old_keycode , dev - > keybit ) ;
break ; /* Setting the bit twice is useless, so break */
}
}
return 0 ;
}
2007-11-04 07:41:12 +03:00
/**
* input_get_keycode - retrieve keycode currently mapped to a given scancode
* @ dev : input device which keymap is being queried
* @ scancode : scancode ( or its equivalent for device in question ) for which
* keycode is needed
* @ keycode : result
*
* This function should be called by anyone interested in retrieving current
* keymap . Presently keyboard and evdev handlers use it .
*/
int input_get_keycode ( struct input_dev * dev , int scancode , int * keycode )
{
if ( scancode < 0 )
return - EINVAL ;
return dev - > getkeycode ( dev , scancode , keycode ) ;
}
EXPORT_SYMBOL ( input_get_keycode ) ;
/**
* input_get_keycode - assign new keycode to a given scancode
* @ dev : input device which keymap is being updated
* @ scancode : scancode ( or its equivalent for device in question )
* @ keycode : new keycode to be assigned to the scancode
*
* This function should be called by anyone needing to update current
* keymap . Presently keyboard and evdev handlers use it .
*/
int input_set_keycode ( struct input_dev * dev , int scancode , int keycode )
{
unsigned long flags ;
int old_keycode ;
int retval ;
if ( scancode < 0 )
return - EINVAL ;
if ( keycode < 0 | | keycode > KEY_MAX )
return - EINVAL ;
spin_lock_irqsave ( & dev - > event_lock , flags ) ;
retval = dev - > getkeycode ( dev , scancode , & old_keycode ) ;
if ( retval )
goto out ;
retval = dev - > setkeycode ( dev , scancode , keycode ) ;
if ( retval )
goto out ;
/*
* Simulate keyup event if keycode is not present
* in the keymap anymore
*/
if ( test_bit ( EV_KEY , dev - > evbit ) & &
! is_event_supported ( old_keycode , dev - > keybit , KEY_MAX ) & &
__test_and_clear_bit ( old_keycode , dev - > key ) ) {
input_pass_event ( dev , EV_KEY , old_keycode , 0 ) ;
if ( dev - > sync )
input_pass_event ( dev , EV_SYN , SYN_REPORT , 1 ) ;
}
out :
spin_unlock_irqrestore ( & dev - > event_lock , flags ) ;
return retval ;
}
EXPORT_SYMBOL ( input_set_keycode ) ;
2007-03-15 05:50:42 +03:00
2005-04-17 02:20:36 +04:00
# define MATCH_BIT(bit, max) \
2007-10-19 10:40:32 +04:00
for ( i = 0 ; i < BITS_TO_LONGS ( max ) ; i + + ) \
2005-04-17 02:20:36 +04:00
if ( ( id - > bit [ i ] & dev - > bit [ i ] ) ! = id - > bit [ i ] ) \
break ; \
2007-10-19 10:40:32 +04:00
if ( i ! = BITS_TO_LONGS ( max ) ) \
2005-04-17 02:20:36 +04:00
continue ;
2006-09-14 09:31:59 +04:00
static const struct input_device_id * input_match_device ( const struct input_device_id * id ,
struct input_dev * dev )
2005-04-17 02:20:36 +04:00
{
int i ;
for ( ; id - > flags | | id - > driver_info ; id + + ) {
if ( id - > flags & INPUT_DEVICE_ID_MATCH_BUS )
2006-04-26 08:14:19 +04:00
if ( id - > bustype ! = dev - > id . bustype )
2005-04-17 02:20:36 +04:00
continue ;
if ( id - > flags & INPUT_DEVICE_ID_MATCH_VENDOR )
2006-04-26 08:14:19 +04:00
if ( id - > vendor ! = dev - > id . vendor )
2005-04-17 02:20:36 +04:00
continue ;
if ( id - > flags & INPUT_DEVICE_ID_MATCH_PRODUCT )
2006-04-26 08:14:19 +04:00
if ( id - > product ! = dev - > id . product )
2005-04-17 02:20:36 +04:00
continue ;
if ( id - > flags & INPUT_DEVICE_ID_MATCH_VERSION )
2006-04-26 08:14:19 +04:00
if ( id - > version ! = dev - > id . version )
2005-04-17 02:20:36 +04:00
continue ;
MATCH_BIT ( evbit , EV_MAX ) ;
MATCH_BIT ( keybit , KEY_MAX ) ;
MATCH_BIT ( relbit , REL_MAX ) ;
MATCH_BIT ( absbit , ABS_MAX ) ;
MATCH_BIT ( mscbit , MSC_MAX ) ;
MATCH_BIT ( ledbit , LED_MAX ) ;
MATCH_BIT ( sndbit , SND_MAX ) ;
MATCH_BIT ( ffbit , FF_MAX ) ;
2005-09-24 11:02:29 +04:00
MATCH_BIT ( swbit , SW_MAX ) ;
2005-04-17 02:20:36 +04:00
return id ;
}
return NULL ;
}
2007-04-12 09:29:46 +04:00
static int input_attach_handler ( struct input_dev * dev , struct input_handler * handler )
{
const struct input_device_id * id ;
int error ;
if ( handler - > blacklist & & input_match_device ( handler - > blacklist , dev ) )
return - ENODEV ;
id = input_match_device ( handler - > id_table , dev ) ;
if ( ! id )
return - ENODEV ;
error = handler - > connect ( handler , dev , id ) ;
if ( error & & error ! = - ENODEV )
printk ( KERN_ERR
" input: failed to attach handler %s to device %s, "
" error: %d \n " ,
2007-06-15 07:32:24 +04:00
handler - > name , kobject_name ( & dev - > dev . kobj ) , error ) ;
2007-04-12 09:29:46 +04:00
return error ;
}
2005-06-30 09:50:29 +04:00
# ifdef CONFIG_PROC_FS
static struct proc_dir_entry * proc_bus_input_dir ;
static DECLARE_WAIT_QUEUE_HEAD ( input_devices_poll_wait ) ;
static int input_devices_state ;
static inline void input_wakeup_procfs_readers ( void )
{
input_devices_state + + ;
wake_up ( & input_devices_poll_wait ) ;
}
2006-04-02 09:09:34 +04:00
static unsigned int input_proc_devices_poll ( struct file * file , poll_table * wait )
2005-06-30 09:50:29 +04:00
{
poll_wait ( file , & input_devices_poll_wait , wait ) ;
2009-03-04 11:52:20 +03:00
if ( file - > f_version ! = input_devices_state ) {
file - > f_version = input_devices_state ;
2005-06-30 09:50:29 +04:00
return POLLIN | POLLRDNORM ;
2009-03-04 11:52:20 +03:00
}
2006-06-26 09:48:47 +04:00
2005-06-30 09:50:29 +04:00
return 0 ;
}
2009-10-14 10:37:30 +04:00
union input_seq_state {
struct {
unsigned short pos ;
bool mutex_acquired ;
} ;
void * p ;
} ;
2006-04-02 09:09:34 +04:00
static void * input_devices_seq_start ( struct seq_file * seq , loff_t * pos )
{
2009-10-14 10:37:30 +04:00
union input_seq_state * state = ( union input_seq_state * ) & seq - > private ;
int error ;
/* We need to fit into seq->private pointer */
BUILD_BUG_ON ( sizeof ( union input_seq_state ) ! = sizeof ( seq - > private ) ) ;
error = mutex_lock_interruptible ( & input_mutex ) ;
if ( error ) {
state - > mutex_acquired = false ;
return ERR_PTR ( error ) ;
}
state - > mutex_acquired = true ;
2005-06-30 09:50:29 +04:00
2007-07-18 08:38:32 +04:00
return seq_list_start ( & input_dev_list , * pos ) ;
2006-04-02 09:09:34 +04:00
}
2005-09-15 11:01:54 +04:00
2006-04-02 09:09:34 +04:00
static void * input_devices_seq_next ( struct seq_file * seq , void * v , loff_t * pos )
{
2007-07-18 08:38:32 +04:00
return seq_list_next ( v , & input_dev_list , pos ) ;
2006-04-02 09:09:34 +04:00
}
2005-06-30 09:50:29 +04:00
2009-10-14 10:37:30 +04:00
static void input_seq_stop ( struct seq_file * seq , void * v )
2006-04-02 09:09:34 +04:00
{
2009-10-14 10:37:30 +04:00
union input_seq_state * state = ( union input_seq_state * ) & seq - > private ;
if ( state - > mutex_acquired )
mutex_unlock ( & input_mutex ) ;
2006-04-02 09:09:34 +04:00
}
2005-06-30 09:50:29 +04:00
2006-04-02 09:09:34 +04:00
static void input_seq_print_bitmap ( struct seq_file * seq , const char * name ,
unsigned long * bitmap , int max )
{
int i ;
2005-09-15 11:01:54 +04:00
2007-10-19 10:40:32 +04:00
for ( i = BITS_TO_LONGS ( max ) - 1 ; i > 0 ; i - - )
2006-04-02 09:09:34 +04:00
if ( bitmap [ i ] )
break ;
2005-06-30 09:50:29 +04:00
2006-04-02 09:09:34 +04:00
seq_printf ( seq , " B: %s= " , name ) ;
for ( ; i > = 0 ; i - - )
seq_printf ( seq , " %lx%s " , bitmap [ i ] , i > 0 ? " " : " " ) ;
seq_putc ( seq , ' \n ' ) ;
}
2005-06-30 09:50:29 +04:00
2006-04-02 09:09:34 +04:00
static int input_devices_seq_show ( struct seq_file * seq , void * v )
{
struct input_dev * dev = container_of ( v , struct input_dev , node ) ;
2007-06-15 07:32:24 +04:00
const char * path = kobject_get_path ( & dev - > dev . kobj , GFP_KERNEL ) ;
2006-04-02 09:09:34 +04:00
struct input_handle * handle ;
seq_printf ( seq , " I: Bus=%04x Vendor=%04x Product=%04x Version=%04x \n " ,
dev - > id . bustype , dev - > id . vendor , dev - > id . product , dev - > id . version ) ;
seq_printf ( seq , " N: Name= \" %s \" \n " , dev - > name ? dev - > name : " " ) ;
seq_printf ( seq , " P: Phys=%s \n " , dev - > phys ? dev - > phys : " " ) ;
seq_printf ( seq , " S: Sysfs=%s \n " , path ? path : " " ) ;
2007-03-08 07:20:17 +03:00
seq_printf ( seq , " U: Uniq=%s \n " , dev - > uniq ? dev - > uniq : " " ) ;
2006-04-02 09:09:34 +04:00
seq_printf ( seq , " H: Handlers= " ) ;
list_for_each_entry ( handle , & dev - > h_list , d_node )
seq_printf ( seq , " %s " , handle - > name ) ;
seq_putc ( seq , ' \n ' ) ;
input_seq_print_bitmap ( seq , " EV " , dev - > evbit , EV_MAX ) ;
if ( test_bit ( EV_KEY , dev - > evbit ) )
input_seq_print_bitmap ( seq , " KEY " , dev - > keybit , KEY_MAX ) ;
if ( test_bit ( EV_REL , dev - > evbit ) )
input_seq_print_bitmap ( seq , " REL " , dev - > relbit , REL_MAX ) ;
if ( test_bit ( EV_ABS , dev - > evbit ) )
input_seq_print_bitmap ( seq , " ABS " , dev - > absbit , ABS_MAX ) ;
if ( test_bit ( EV_MSC , dev - > evbit ) )
input_seq_print_bitmap ( seq , " MSC " , dev - > mscbit , MSC_MAX ) ;
if ( test_bit ( EV_LED , dev - > evbit ) )
input_seq_print_bitmap ( seq , " LED " , dev - > ledbit , LED_MAX ) ;
if ( test_bit ( EV_SND , dev - > evbit ) )
input_seq_print_bitmap ( seq , " SND " , dev - > sndbit , SND_MAX ) ;
if ( test_bit ( EV_FF , dev - > evbit ) )
input_seq_print_bitmap ( seq , " FF " , dev - > ffbit , FF_MAX ) ;
if ( test_bit ( EV_SW , dev - > evbit ) )
input_seq_print_bitmap ( seq , " SW " , dev - > swbit , SW_MAX ) ;
seq_putc ( seq , ' \n ' ) ;
kfree ( path ) ;
return 0 ;
2005-06-30 09:50:29 +04:00
}
2008-01-31 08:43:32 +03:00
static const struct seq_operations input_devices_seq_ops = {
2006-04-02 09:09:34 +04:00
. start = input_devices_seq_start ,
. next = input_devices_seq_next ,
2009-10-14 10:37:30 +04:00
. stop = input_seq_stop ,
2006-04-02 09:09:34 +04:00
. show = input_devices_seq_show ,
} ;
static int input_proc_devices_open ( struct inode * inode , struct file * file )
2005-06-30 09:50:29 +04:00
{
2006-04-02 09:09:34 +04:00
return seq_open ( file , & input_devices_seq_ops ) ;
}
2007-02-12 11:55:32 +03:00
static const struct file_operations input_devices_fileops = {
2006-04-02 09:09:34 +04:00
. owner = THIS_MODULE ,
. open = input_proc_devices_open ,
. poll = input_proc_devices_poll ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = seq_release ,
} ;
static void * input_handlers_seq_start ( struct seq_file * seq , loff_t * pos )
{
2009-10-14 10:37:30 +04:00
union input_seq_state * state = ( union input_seq_state * ) & seq - > private ;
int error ;
/* We need to fit into seq->private pointer */
BUILD_BUG_ON ( sizeof ( union input_seq_state ) ! = sizeof ( seq - > private ) ) ;
error = mutex_lock_interruptible ( & input_mutex ) ;
if ( error ) {
state - > mutex_acquired = false ;
return ERR_PTR ( error ) ;
}
state - > mutex_acquired = true ;
state - > pos = * pos ;
2007-08-30 08:22:11 +04:00
2007-07-18 08:38:32 +04:00
return seq_list_start ( & input_handler_list , * pos ) ;
2006-04-02 09:09:34 +04:00
}
2005-06-30 09:50:29 +04:00
2006-04-02 09:09:34 +04:00
static void * input_handlers_seq_next ( struct seq_file * seq , void * v , loff_t * pos )
{
2009-10-14 10:37:30 +04:00
union input_seq_state * state = ( union input_seq_state * ) & seq - > private ;
2005-06-30 09:50:29 +04:00
2009-10-14 10:37:30 +04:00
state - > pos = * pos + 1 ;
return seq_list_next ( v , & input_handler_list , pos ) ;
2006-04-02 09:09:34 +04:00
}
static int input_handlers_seq_show ( struct seq_file * seq , void * v )
{
struct input_handler * handler = container_of ( v , struct input_handler , node ) ;
2009-10-14 10:37:30 +04:00
union input_seq_state * state = ( union input_seq_state * ) & seq - > private ;
2006-04-02 09:09:34 +04:00
2009-10-14 10:37:30 +04:00
seq_printf ( seq , " N: Number=%u Name=%s " , state - > pos , handler - > name ) ;
2006-04-02 09:09:34 +04:00
if ( handler - > fops )
seq_printf ( seq , " Minor=%d " , handler - > minor ) ;
seq_putc ( seq , ' \n ' ) ;
return 0 ;
}
2009-10-14 10:37:30 +04:00
2008-01-31 08:43:32 +03:00
static const struct seq_operations input_handlers_seq_ops = {
2006-04-02 09:09:34 +04:00
. start = input_handlers_seq_start ,
. next = input_handlers_seq_next ,
2009-10-14 10:37:30 +04:00
. stop = input_seq_stop ,
2006-04-02 09:09:34 +04:00
. show = input_handlers_seq_show ,
} ;
static int input_proc_handlers_open ( struct inode * inode , struct file * file )
{
return seq_open ( file , & input_handlers_seq_ops ) ;
}
2007-02-12 11:55:32 +03:00
static const struct file_operations input_handlers_fileops = {
2006-04-02 09:09:34 +04:00
. owner = THIS_MODULE ,
. open = input_proc_handlers_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = seq_release ,
} ;
2005-06-30 09:50:29 +04:00
static int __init input_proc_init ( void )
{
struct proc_dir_entry * entry ;
2008-04-29 12:01:41 +04:00
proc_bus_input_dir = proc_mkdir ( " bus/input " , NULL ) ;
2005-06-30 09:50:29 +04:00
if ( ! proc_bus_input_dir )
return - ENOMEM ;
2008-04-29 12:02:35 +04:00
entry = proc_create ( " devices " , 0 , proc_bus_input_dir ,
& input_devices_fileops ) ;
2005-06-30 09:50:29 +04:00
if ( ! entry )
goto fail1 ;
2008-04-29 12:02:35 +04:00
entry = proc_create ( " handlers " , 0 , proc_bus_input_dir ,
& input_handlers_fileops ) ;
2005-06-30 09:50:29 +04:00
if ( ! entry )
goto fail2 ;
return 0 ;
fail2 : remove_proc_entry ( " devices " , proc_bus_input_dir ) ;
2008-04-29 12:01:41 +04:00
fail1 : remove_proc_entry ( " bus/input " , NULL ) ;
2005-06-30 09:50:29 +04:00
return - ENOMEM ;
}
2005-07-02 08:54:30 +04:00
static void input_proc_exit ( void )
2005-06-30 09:50:29 +04:00
{
remove_proc_entry ( " devices " , proc_bus_input_dir ) ;
remove_proc_entry ( " handlers " , proc_bus_input_dir ) ;
2008-04-29 12:01:41 +04:00
remove_proc_entry ( " bus/input " , NULL ) ;
2005-06-30 09:50:29 +04:00
}
# else /* !CONFIG_PROC_FS */
static inline void input_wakeup_procfs_readers ( void ) { }
static inline int input_proc_init ( void ) { return 0 ; }
static inline void input_proc_exit ( void ) { }
# endif
2007-06-15 07:32:24 +04:00
# define INPUT_DEV_STRING_ATTR_SHOW(name) \
static ssize_t input_dev_show_ # # name ( struct device * dev , \
struct device_attribute * attr , \
char * buf ) \
{ \
struct input_dev * input_dev = to_input_dev ( dev ) ; \
\
return scnprintf ( buf , PAGE_SIZE , " %s \n " , \
input_dev - > name ? input_dev - > name : " " ) ; \
} \
static DEVICE_ATTR ( name , S_IRUGO , input_dev_show_ # # name , NULL )
2005-09-15 11:01:55 +04:00
INPUT_DEV_STRING_ATTR_SHOW ( name ) ;
INPUT_DEV_STRING_ATTR_SHOW ( phys ) ;
INPUT_DEV_STRING_ATTR_SHOW ( uniq ) ;
2006-04-02 09:09:51 +04:00
static int input_print_modalias_bits ( char * buf , int size ,
char name , unsigned long * bm ,
unsigned int min_bit , unsigned int max_bit )
2005-12-07 23:40:34 +03:00
{
2006-04-02 09:09:51 +04:00
int len = 0 , i ;
2005-12-07 23:40:34 +03:00
2006-04-02 09:09:51 +04:00
len + = snprintf ( buf , max ( size , 0 ) , " %c " , name ) ;
for ( i = min_bit ; i < max_bit ; i + + )
2007-10-19 10:40:32 +04:00
if ( bm [ BIT_WORD ( i ) ] & BIT_MASK ( i ) )
2006-04-02 09:09:51 +04:00
len + = snprintf ( buf + len , max ( size - len , 0 ) , " %X, " , i ) ;
2005-12-07 23:40:34 +03:00
return len ;
}
2006-04-02 09:09:26 +04:00
static int input_print_modalias ( char * buf , int size , struct input_dev * id ,
int add_cr )
2005-12-07 23:40:34 +03:00
{
2006-01-05 15:19:55 +03:00
int len ;
2005-12-07 23:40:34 +03:00
2006-04-02 09:09:51 +04:00
len = snprintf ( buf , max ( size , 0 ) ,
" input:b%04Xv%04Xp%04Xe%04X- " ,
id - > id . bustype , id - > id . vendor ,
id - > id . product , id - > id . version ) ;
len + = input_print_modalias_bits ( buf + len , size - len ,
' e ' , id - > evbit , 0 , EV_MAX ) ;
len + = input_print_modalias_bits ( buf + len , size - len ,
' k ' , id - > keybit , KEY_MIN_INTERESTING , KEY_MAX ) ;
len + = input_print_modalias_bits ( buf + len , size - len ,
' r ' , id - > relbit , 0 , REL_MAX ) ;
len + = input_print_modalias_bits ( buf + len , size - len ,
' a ' , id - > absbit , 0 , ABS_MAX ) ;
len + = input_print_modalias_bits ( buf + len , size - len ,
' m ' , id - > mscbit , 0 , MSC_MAX ) ;
len + = input_print_modalias_bits ( buf + len , size - len ,
' l ' , id - > ledbit , 0 , LED_MAX ) ;
len + = input_print_modalias_bits ( buf + len , size - len ,
' s ' , id - > sndbit , 0 , SND_MAX ) ;
len + = input_print_modalias_bits ( buf + len , size - len ,
' f ' , id - > ffbit , 0 , FF_MAX ) ;
len + = input_print_modalias_bits ( buf + len , size - len ,
' w ' , id - > swbit , 0 , SW_MAX ) ;
2006-04-02 09:09:26 +04:00
if ( add_cr )
2006-04-02 09:09:51 +04:00
len + = snprintf ( buf + len , max ( size - len , 0 ) , " \n " ) ;
2006-04-02 09:09:26 +04:00
2006-01-05 15:19:55 +03:00
return len ;
}
2007-06-15 07:32:24 +04:00
static ssize_t input_dev_show_modalias ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
2006-01-05 15:19:55 +03:00
{
struct input_dev * id = to_input_dev ( dev ) ;
ssize_t len ;
2006-04-02 09:09:26 +04:00
len = input_print_modalias ( buf , PAGE_SIZE , id , 1 ) ;
2006-06-26 09:48:21 +04:00
return min_t ( int , len , PAGE_SIZE ) ;
2005-12-07 23:40:34 +03:00
}
2007-06-15 07:32:24 +04:00
static DEVICE_ATTR ( modalias , S_IRUGO , input_dev_show_modalias , NULL ) ;
2005-12-07 23:40:34 +03:00
2005-10-28 09:25:43 +04:00
static struct attribute * input_dev_attrs [ ] = {
2007-06-15 07:32:24 +04:00
& dev_attr_name . attr ,
& dev_attr_phys . attr ,
& dev_attr_uniq . attr ,
& dev_attr_modalias . attr ,
2005-10-28 09:25:43 +04:00
NULL
} ;
2005-11-20 08:56:31 +03:00
static struct attribute_group input_dev_attr_group = {
2005-10-28 09:25:43 +04:00
. attrs = input_dev_attrs ,
2005-09-15 11:01:55 +04:00
} ;
2007-06-15 07:32:24 +04:00
# define INPUT_DEV_ID_ATTR(name) \
static ssize_t input_dev_show_id_ # # name ( struct device * dev , \
struct device_attribute * attr , \
char * buf ) \
{ \
struct input_dev * input_dev = to_input_dev ( dev ) ; \
return scnprintf ( buf , PAGE_SIZE , " %04x \n " , input_dev - > id . name ) ; \
} \
static DEVICE_ATTR ( name , S_IRUGO , input_dev_show_id_ # # name , NULL )
2005-09-15 11:01:55 +04:00
INPUT_DEV_ID_ATTR ( bustype ) ;
INPUT_DEV_ID_ATTR ( vendor ) ;
INPUT_DEV_ID_ATTR ( product ) ;
INPUT_DEV_ID_ATTR ( version ) ;
static struct attribute * input_dev_id_attrs [ ] = {
2007-06-15 07:32:24 +04:00
& dev_attr_bustype . attr ,
& dev_attr_vendor . attr ,
& dev_attr_product . attr ,
& dev_attr_version . attr ,
2005-09-15 11:01:55 +04:00
NULL
} ;
static struct attribute_group input_dev_id_attr_group = {
. name = " id " ,
. attrs = input_dev_id_attrs ,
} ;
2006-04-02 09:09:34 +04:00
static int input_print_bitmap ( char * buf , int buf_size , unsigned long * bitmap ,
int max , int add_cr )
{
int i ;
int len = 0 ;
2007-10-19 10:40:32 +04:00
for ( i = BITS_TO_LONGS ( max ) - 1 ; i > 0 ; i - - )
2006-04-02 09:09:34 +04:00
if ( bitmap [ i ] )
break ;
for ( ; i > = 0 ; i - - )
len + = snprintf ( buf + len , max ( buf_size - len , 0 ) ,
" %lx%s " , bitmap [ i ] , i > 0 ? " " : " " ) ;
if ( add_cr )
len + = snprintf ( buf + len , max ( buf_size - len , 0 ) , " \n " ) ;
return len ;
}
2007-06-15 07:32:24 +04:00
# define INPUT_DEV_CAP_ATTR(ev, bm) \
static ssize_t input_dev_show_cap_ # # bm ( struct device * dev , \
struct device_attribute * attr , \
char * buf ) \
{ \
struct input_dev * input_dev = to_input_dev ( dev ) ; \
int len = input_print_bitmap ( buf , PAGE_SIZE , \
input_dev - > bm # # bit , ev # # _MAX , 1 ) ; \
return min_t ( int , len , PAGE_SIZE ) ; \
} \
static DEVICE_ATTR ( bm , S_IRUGO , input_dev_show_cap_ # # bm , NULL )
2005-09-15 11:01:55 +04:00
INPUT_DEV_CAP_ATTR ( EV , ev ) ;
INPUT_DEV_CAP_ATTR ( KEY , key ) ;
INPUT_DEV_CAP_ATTR ( REL , rel ) ;
INPUT_DEV_CAP_ATTR ( ABS , abs ) ;
INPUT_DEV_CAP_ATTR ( MSC , msc ) ;
INPUT_DEV_CAP_ATTR ( LED , led ) ;
INPUT_DEV_CAP_ATTR ( SND , snd ) ;
INPUT_DEV_CAP_ATTR ( FF , ff ) ;
INPUT_DEV_CAP_ATTR ( SW , sw ) ;
static struct attribute * input_dev_caps_attrs [ ] = {
2007-06-15 07:32:24 +04:00
& dev_attr_ev . attr ,
& dev_attr_key . attr ,
& dev_attr_rel . attr ,
& dev_attr_abs . attr ,
& dev_attr_msc . attr ,
& dev_attr_led . attr ,
& dev_attr_snd . attr ,
& dev_attr_ff . attr ,
& dev_attr_sw . attr ,
2005-09-15 11:01:55 +04:00
NULL
} ;
static struct attribute_group input_dev_caps_attr_group = {
. name = " capabilities " ,
. attrs = input_dev_caps_attrs ,
} ;
2009-06-24 21:06:31 +04:00
static const struct attribute_group * input_dev_attr_groups [ ] = {
2007-03-08 07:20:26 +03:00
& input_dev_attr_group ,
& input_dev_id_attr_group ,
& input_dev_caps_attr_group ,
NULL
} ;
2007-06-15 07:32:24 +04:00
static void input_dev_release ( struct device * device )
2005-09-15 11:01:39 +04:00
{
2007-06-15 07:32:24 +04:00
struct input_dev * dev = to_input_dev ( device ) ;
2005-09-15 11:01:39 +04:00
2006-07-19 09:40:22 +04:00
input_ff_destroy ( dev ) ;
2005-09-15 11:01:39 +04:00
kfree ( dev ) ;
2006-07-19 09:40:22 +04:00
2005-09-15 11:01:39 +04:00
module_put ( THIS_MODULE ) ;
}
2005-09-15 11:01:57 +04:00
/*
2005-11-16 11:00:00 +03:00
* Input uevent interface - loading event handlers based on
2005-09-15 11:01:57 +04:00
* device bitfields .
*/
2007-08-14 17:15:12 +04:00
static int input_add_uevent_bm_var ( struct kobj_uevent_env * env ,
2006-04-02 09:09:51 +04:00
const char * name , unsigned long * bitmap , int max )
2005-09-15 11:01:57 +04:00
{
2007-08-14 17:15:12 +04:00
int len ;
2005-09-15 11:01:57 +04:00
2007-08-14 17:15:12 +04:00
if ( add_uevent_var ( env , " %s= " , name ) )
2005-09-15 11:01:57 +04:00
return - ENOMEM ;
2007-08-14 17:15:12 +04:00
len = input_print_bitmap ( & env - > buf [ env - > buflen - 1 ] ,
sizeof ( env - > buf ) - env - > buflen ,
bitmap , max , 0 ) ;
if ( len > = ( sizeof ( env - > buf ) - env - > buflen ) )
2005-09-15 11:01:57 +04:00
return - ENOMEM ;
2007-08-14 17:15:12 +04:00
env - > buflen + = len ;
2005-09-15 11:01:57 +04:00
return 0 ;
}
2007-08-14 17:15:12 +04:00
static int input_add_uevent_modalias_var ( struct kobj_uevent_env * env ,
2006-04-02 09:09:51 +04:00
struct input_dev * dev )
{
2007-08-14 17:15:12 +04:00
int len ;
2006-04-02 09:09:51 +04:00
2007-08-14 17:15:12 +04:00
if ( add_uevent_var ( env , " MODALIAS= " ) )
2006-04-02 09:09:51 +04:00
return - ENOMEM ;
2007-08-14 17:15:12 +04:00
len = input_print_modalias ( & env - > buf [ env - > buflen - 1 ] ,
sizeof ( env - > buf ) - env - > buflen ,
dev , 0 ) ;
if ( len > = ( sizeof ( env - > buf ) - env - > buflen ) )
2006-04-02 09:09:51 +04:00
return - ENOMEM ;
2007-08-14 17:15:12 +04:00
env - > buflen + = len ;
2006-04-02 09:09:51 +04:00
return 0 ;
}
2005-09-15 11:01:57 +04:00
# define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \
do { \
2007-08-14 17:15:12 +04:00
int err = add_uevent_var ( env , fmt , val ) ; \
2005-09-15 11:01:57 +04:00
if ( err ) \
return err ; \
} while ( 0 )
# define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \
do { \
2007-08-14 17:15:12 +04:00
int err = input_add_uevent_bm_var ( env , name , bm , max ) ; \
2005-09-15 11:01:57 +04:00
if ( err ) \
return err ; \
} while ( 0 )
2006-04-02 09:09:51 +04:00
# define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev) \
do { \
2007-08-14 17:15:12 +04:00
int err = input_add_uevent_modalias_var ( env , dev ) ; \
2006-04-02 09:09:51 +04:00
if ( err ) \
return err ; \
} while ( 0 )
2007-08-14 17:15:12 +04:00
static int input_dev_uevent ( struct device * device , struct kobj_uevent_env * env )
2005-09-15 11:01:57 +04:00
{
2007-06-15 07:32:24 +04:00
struct input_dev * dev = to_input_dev ( device ) ;
2005-09-15 11:01:57 +04:00
INPUT_ADD_HOTPLUG_VAR ( " PRODUCT=%x/%x/%x/%x " ,
dev - > id . bustype , dev - > id . vendor ,
dev - > id . product , dev - > id . version ) ;
if ( dev - > name )
INPUT_ADD_HOTPLUG_VAR ( " NAME= \" %s \" " , dev - > name ) ;
if ( dev - > phys )
INPUT_ADD_HOTPLUG_VAR ( " PHYS= \" %s \" " , dev - > phys ) ;
2005-11-09 08:34:29 +03:00
if ( dev - > uniq )
2005-09-15 11:01:57 +04:00
INPUT_ADD_HOTPLUG_VAR ( " UNIQ= \" %s \" " , dev - > uniq ) ;
INPUT_ADD_HOTPLUG_BM_VAR ( " EV= " , dev - > evbit , EV_MAX ) ;
if ( test_bit ( EV_KEY , dev - > evbit ) )
INPUT_ADD_HOTPLUG_BM_VAR ( " KEY= " , dev - > keybit , KEY_MAX ) ;
if ( test_bit ( EV_REL , dev - > evbit ) )
INPUT_ADD_HOTPLUG_BM_VAR ( " REL= " , dev - > relbit , REL_MAX ) ;
if ( test_bit ( EV_ABS , dev - > evbit ) )
INPUT_ADD_HOTPLUG_BM_VAR ( " ABS= " , dev - > absbit , ABS_MAX ) ;
if ( test_bit ( EV_MSC , dev - > evbit ) )
INPUT_ADD_HOTPLUG_BM_VAR ( " MSC= " , dev - > mscbit , MSC_MAX ) ;
if ( test_bit ( EV_LED , dev - > evbit ) )
INPUT_ADD_HOTPLUG_BM_VAR ( " LED= " , dev - > ledbit , LED_MAX ) ;
if ( test_bit ( EV_SND , dev - > evbit ) )
INPUT_ADD_HOTPLUG_BM_VAR ( " SND= " , dev - > sndbit , SND_MAX ) ;
if ( test_bit ( EV_FF , dev - > evbit ) )
INPUT_ADD_HOTPLUG_BM_VAR ( " FF= " , dev - > ffbit , FF_MAX ) ;
if ( test_bit ( EV_SW , dev - > evbit ) )
INPUT_ADD_HOTPLUG_BM_VAR ( " SW= " , dev - > swbit , SW_MAX ) ;
2006-04-02 09:09:51 +04:00
INPUT_ADD_HOTPLUG_MODALIAS_VAR ( dev ) ;
2005-09-15 11:01:57 +04:00
return 0 ;
}
2009-09-16 12:06:43 +04:00
# define INPUT_DO_TOGGLE(dev, type, bits, on) \
do { \
int i ; \
if ( ! test_bit ( EV_ # # type , dev - > evbit ) ) \
break ; \
for ( i = 0 ; i < type # # _MAX ; i + + ) { \
if ( ! test_bit ( i , dev - > bits # # bit ) | | \
! test_bit ( i , dev - > bits ) ) \
continue ; \
dev - > event ( dev , EV_ # # type , i , on ) ; \
} \
} while ( 0 )
2009-10-02 02:43:55 +04:00
# ifdef CONFIG_PM
2009-09-16 12:06:43 +04:00
static void input_dev_reset ( struct input_dev * dev , bool activate )
{
if ( ! dev - > event )
return ;
INPUT_DO_TOGGLE ( dev , LED , led , activate ) ;
INPUT_DO_TOGGLE ( dev , SND , snd , activate ) ;
if ( activate & & test_bit ( EV_REP , dev - > evbit ) ) {
dev - > event ( dev , EV_REP , REP_PERIOD , dev - > rep [ REP_PERIOD ] ) ;
dev - > event ( dev , EV_REP , REP_DELAY , dev - > rep [ REP_DELAY ] ) ;
}
}
static int input_dev_suspend ( struct device * dev )
{
struct input_dev * input_dev = to_input_dev ( dev ) ;
mutex_lock ( & input_dev - > mutex ) ;
input_dev_reset ( input_dev , false ) ;
mutex_unlock ( & input_dev - > mutex ) ;
return 0 ;
}
static int input_dev_resume ( struct device * dev )
{
struct input_dev * input_dev = to_input_dev ( dev ) ;
mutex_lock ( & input_dev - > mutex ) ;
input_dev_reset ( input_dev , true ) ;
mutex_unlock ( & input_dev - > mutex ) ;
return 0 ;
}
static const struct dev_pm_ops input_dev_pm_ops = {
. suspend = input_dev_suspend ,
. resume = input_dev_resume ,
. poweroff = input_dev_suspend ,
. restore = input_dev_resume ,
} ;
# endif /* CONFIG_PM */
2007-06-15 07:32:24 +04:00
static struct device_type input_dev_type = {
. groups = input_dev_attr_groups ,
. release = input_dev_release ,
. uevent = input_dev_uevent ,
2009-09-16 12:06:43 +04:00
# ifdef CONFIG_PM
. pm = & input_dev_pm_ops ,
# endif
2007-06-15 07:32:24 +04:00
} ;
2009-09-19 01:01:12 +04:00
static char * input_devnode ( struct device * dev , mode_t * mode )
2009-04-30 17:23:42 +04:00
{
return kasprintf ( GFP_KERNEL , " input/%s " , dev_name ( dev ) ) ;
}
2005-10-28 09:25:43 +04:00
struct class input_class = {
2007-06-15 07:32:24 +04:00
. name = " input " ,
2009-09-19 01:01:12 +04:00
. devnode = input_devnode ,
2005-09-15 11:01:39 +04:00
} ;
2006-06-26 09:49:21 +04:00
EXPORT_SYMBOL_GPL ( input_class ) ;
2005-09-15 11:01:39 +04:00
2006-11-03 07:26:55 +03:00
/**
* input_allocate_device - allocate memory for new input device
*
* Returns prepared struct input_dev or NULL .
*
* NOTE : Use input_free_device ( ) to free devices that have not been
* registered ; input_unregister_device ( ) should be used for already
* registered devices .
*/
2005-09-15 11:01:39 +04:00
struct input_dev * input_allocate_device ( void )
{
struct input_dev * dev ;
dev = kzalloc ( sizeof ( struct input_dev ) , GFP_KERNEL ) ;
if ( dev ) {
2007-06-15 07:32:24 +04:00
dev - > dev . type = & input_dev_type ;
dev - > dev . class = & input_class ;
device_initialize ( & dev - > dev ) ;
2006-06-26 09:48:36 +04:00
mutex_init ( & dev - > mutex ) ;
2007-08-30 08:22:11 +04:00
spin_lock_init ( & dev - > event_lock ) ;
2005-09-15 11:01:39 +04:00
INIT_LIST_HEAD ( & dev - > h_list ) ;
INIT_LIST_HEAD ( & dev - > node ) ;
2006-09-14 09:32:14 +04:00
__module_get ( THIS_MODULE ) ;
2005-09-15 11:01:39 +04:00
}
return dev ;
}
2006-06-26 09:49:21 +04:00
EXPORT_SYMBOL ( input_allocate_device ) ;
2005-09-15 11:01:39 +04:00
2006-11-03 07:26:55 +03:00
/**
* input_free_device - free memory occupied by input_dev structure
* @ dev : input device to free
*
* This function should only be used if input_register_device ( )
* was not called yet or if it failed . Once device was registered
* use input_unregister_device ( ) and memory will be freed once last
2007-08-30 08:22:11 +04:00
* reference to the device is dropped .
2006-11-03 07:26:55 +03:00
*
* Device should be allocated by input_allocate_device ( ) .
*
* NOTE : If there are references to the input device then memory
* will not be freed until last reference is dropped .
*/
2006-06-26 09:48:36 +04:00
void input_free_device ( struct input_dev * dev )
{
2007-03-16 07:57:25 +03:00
if ( dev )
2006-06-26 09:48:36 +04:00
input_put_device ( dev ) ;
}
2006-06-26 09:49:21 +04:00
EXPORT_SYMBOL ( input_free_device ) ;
2006-06-26 09:48:36 +04:00
2007-04-25 08:53:18 +04:00
/**
* input_set_capability - mark device as capable of a certain event
* @ dev : device that is capable of emitting or accepting event
* @ type : type of the event ( EV_KEY , EV_REL , etc . . . )
* @ code : event code
*
* In addition to setting up corresponding bit in appropriate capability
* bitmap the function also adjusts dev - > evbit .
*/
void input_set_capability ( struct input_dev * dev , unsigned int type , unsigned int code )
{
switch ( type ) {
case EV_KEY :
__set_bit ( code , dev - > keybit ) ;
break ;
case EV_REL :
__set_bit ( code , dev - > relbit ) ;
break ;
case EV_ABS :
__set_bit ( code , dev - > absbit ) ;
break ;
case EV_MSC :
__set_bit ( code , dev - > mscbit ) ;
break ;
case EV_SW :
__set_bit ( code , dev - > swbit ) ;
break ;
case EV_LED :
__set_bit ( code , dev - > ledbit ) ;
break ;
case EV_SND :
__set_bit ( code , dev - > sndbit ) ;
break ;
case EV_FF :
__set_bit ( code , dev - > ffbit ) ;
break ;
2007-12-14 09:21:03 +03:00
case EV_PWR :
/* do nothing */
break ;
2007-04-25 08:53:18 +04:00
default :
printk ( KERN_ERR
" input_set_capability: unknown type %u (code %u) \n " ,
type , code ) ;
dump_stack ( ) ;
return ;
}
__set_bit ( type , dev - > evbit ) ;
}
EXPORT_SYMBOL ( input_set_capability ) ;
2007-08-30 08:22:11 +04:00
/**
* input_register_device - register device with input core
* @ dev : device to be registered
*
* This function registers device with input core . The device must be
* allocated with input_allocate_device ( ) and all it ' s capabilities
* set up before registering .
* If function fails the device must be freed with input_free_device ( ) .
* Once device has been successfully registered it can be unregistered
* with input_unregister_device ( ) ; input_free_device ( ) should not be
* called in this case .
*/
2005-11-03 06:51:46 +03:00
int input_register_device ( struct input_dev * dev )
2005-04-17 02:20:36 +04:00
{
2005-11-20 08:56:31 +03:00
static atomic_t input_no = ATOMIC_INIT ( 0 ) ;
2005-04-17 02:20:36 +04:00
struct input_handler * handler ;
2005-11-20 08:56:31 +03:00
const char * path ;
int error ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
__set_bit ( EV_SYN , dev - > evbit ) ;
2005-05-29 11:29:25 +04:00
2005-04-17 02:20:36 +04:00
/*
* If delay and period are pre - set by the driver , then autorepeating
* is handled by the driver itself and we don ' t do it in input . c .
*/
init_timer ( & dev - > timer ) ;
if ( ! dev - > rep [ REP_DELAY ] & & ! dev - > rep [ REP_PERIOD ] ) {
dev - > timer . data = ( long ) dev ;
dev - > timer . function = input_repeat_key ;
dev - > rep [ REP_DELAY ] = 250 ;
dev - > rep [ REP_PERIOD ] = 33 ;
}
2007-03-15 05:50:42 +03:00
if ( ! dev - > getkeycode )
dev - > getkeycode = input_default_getkeycode ;
if ( ! dev - > setkeycode )
dev - > setkeycode = input_default_setkeycode ;
2008-10-30 07:07:50 +03:00
dev_set_name ( & dev - > dev , " input%ld " ,
( unsigned long ) atomic_inc_return ( & input_no ) - 1 ) ;
2005-11-20 08:56:31 +03:00
2007-06-15 07:32:24 +04:00
error = device_add ( & dev - > dev ) ;
2005-11-20 08:56:31 +03:00
if ( error )
return error ;
2007-06-15 07:32:24 +04:00
path = kobject_get_path ( & dev - > dev . kobj , GFP_KERNEL ) ;
2005-11-20 08:56:31 +03:00
printk ( KERN_INFO " input: %s as %s \n " ,
dev - > name ? dev - > name : " Unspecified device " , path ? path : " N/A " ) ;
kfree ( path ) ;
2005-10-28 09:25:43 +04:00
2007-08-30 08:22:11 +04:00
error = mutex_lock_interruptible ( & input_mutex ) ;
if ( error ) {
device_del ( & dev - > dev ) ;
return error ;
}
list_add_tail ( & dev - > node , & input_dev_list ) ;
2005-04-17 02:20:36 +04:00
list_for_each_entry ( handler , & input_handler_list , node )
2007-04-12 09:29:46 +04:00
input_attach_handler ( dev , handler ) ;
2005-04-17 02:20:36 +04:00
2005-06-30 09:50:29 +04:00
input_wakeup_procfs_readers ( ) ;
2005-11-03 06:51:46 +03:00
2007-08-30 08:22:11 +04:00
mutex_unlock ( & input_mutex ) ;
2005-11-03 06:51:46 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2006-06-26 09:49:21 +04:00
EXPORT_SYMBOL ( input_register_device ) ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
/**
* input_unregister_device - unregister previously registered device
* @ dev : device to be unregistered
*
* This function unregisters an input device . Once device is unregistered
* the caller should not try to access it as it may get freed at any moment .
*/
2005-04-17 02:20:36 +04:00
void input_unregister_device ( struct input_dev * dev )
{
2007-04-12 09:29:46 +04:00
struct input_handle * handle , * next ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
input_disconnect_device ( dev ) ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
mutex_lock ( & input_mutex ) ;
2005-04-17 02:20:36 +04:00
2007-04-12 09:29:46 +04:00
list_for_each_entry_safe ( handle , next , & dev - > h_list , d_node )
2005-04-17 02:20:36 +04:00
handle - > handler - > disconnect ( handle ) ;
2007-04-12 09:29:46 +04:00
WARN_ON ( ! list_empty ( & dev - > h_list ) ) ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
del_timer_sync ( & dev - > timer ) ;
2005-04-17 02:20:36 +04:00
list_del_init ( & dev - > node ) ;
2005-06-30 09:50:29 +04:00
input_wakeup_procfs_readers ( ) ;
2007-08-30 08:22:11 +04:00
mutex_unlock ( & input_mutex ) ;
device_unregister ( & dev - > dev ) ;
2005-04-17 02:20:36 +04:00
}
2006-06-26 09:49:21 +04:00
EXPORT_SYMBOL ( input_unregister_device ) ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
/**
* input_register_handler - register a new input handler
* @ handler : handler to be registered
*
* This function registers a new input handler ( interface ) for input
* devices in the system and attaches it to all input devices that
* are compatible with the handler .
*/
2006-09-14 09:32:39 +04:00
int input_register_handler ( struct input_handler * handler )
2005-04-17 02:20:36 +04:00
{
struct input_dev * dev ;
2007-08-30 08:22:11 +04:00
int retval ;
retval = mutex_lock_interruptible ( & input_mutex ) ;
if ( retval )
return retval ;
2005-04-17 02:20:36 +04:00
INIT_LIST_HEAD ( & handler - > h_list ) ;
2006-09-14 09:32:39 +04:00
if ( handler - > fops ! = NULL ) {
2007-08-30 08:22:11 +04:00
if ( input_table [ handler - > minor > > 5 ] ) {
retval = - EBUSY ;
goto out ;
}
2005-04-17 02:20:36 +04:00
input_table [ handler - > minor > > 5 ] = handler ;
2006-09-14 09:32:39 +04:00
}
2005-04-17 02:20:36 +04:00
list_add_tail ( & handler - > node , & input_handler_list ) ;
list_for_each_entry ( dev , & input_dev_list , node )
2007-04-12 09:29:46 +04:00
input_attach_handler ( dev , handler ) ;
2005-04-17 02:20:36 +04:00
2005-06-30 09:50:29 +04:00
input_wakeup_procfs_readers ( ) ;
2007-08-30 08:22:11 +04:00
out :
mutex_unlock ( & input_mutex ) ;
return retval ;
2005-04-17 02:20:36 +04:00
}
2006-06-26 09:49:21 +04:00
EXPORT_SYMBOL ( input_register_handler ) ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
/**
* input_unregister_handler - unregisters an input handler
* @ handler : handler to be unregistered
*
* This function disconnects a handler from its input devices and
* removes it from lists of known handlers .
*/
2005-04-17 02:20:36 +04:00
void input_unregister_handler ( struct input_handler * handler )
{
2007-04-12 09:29:46 +04:00
struct input_handle * handle , * next ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
mutex_lock ( & input_mutex ) ;
2007-04-12 09:29:46 +04:00
list_for_each_entry_safe ( handle , next , & handler - > h_list , h_node )
2005-04-17 02:20:36 +04:00
handler - > disconnect ( handle ) ;
2007-04-12 09:29:46 +04:00
WARN_ON ( ! list_empty ( & handler - > h_list ) ) ;
2005-04-17 02:20:36 +04:00
list_del_init ( & handler - > node ) ;
if ( handler - > fops ! = NULL )
input_table [ handler - > minor > > 5 ] = NULL ;
2005-06-30 09:50:29 +04:00
input_wakeup_procfs_readers ( ) ;
2007-08-30 08:22:11 +04:00
mutex_unlock ( & input_mutex ) ;
2005-04-17 02:20:36 +04:00
}
2006-06-26 09:49:21 +04:00
EXPORT_SYMBOL ( input_unregister_handler ) ;
2005-04-17 02:20:36 +04:00
2007-08-30 08:22:11 +04:00
/**
* input_register_handle - register a new input handle
* @ handle : handle to register
*
* This function puts a new input handle onto device ' s
* and handler ' s lists so that events can flow through
* it once it is opened using input_open_device ( ) .
*
* This function is supposed to be called from handler ' s
* connect ( ) method .
*/
2007-04-12 09:29:46 +04:00
int input_register_handle ( struct input_handle * handle )
{
struct input_handler * handler = handle - > handler ;
2007-08-30 08:22:11 +04:00
struct input_dev * dev = handle - > dev ;
int error ;
/*
* We take dev - > mutex here to prevent race with
* input_release_device ( ) .
*/
error = mutex_lock_interruptible ( & dev - > mutex ) ;
if ( error )
return error ;
list_add_tail_rcu ( & handle - > d_node , & dev - > h_list ) ;
mutex_unlock ( & dev - > mutex ) ;
2007-04-12 09:29:46 +04:00
2007-08-30 08:22:11 +04:00
/*
* Since we are supposed to be called from - > connect ( )
* which is mutually exclusive with - > disconnect ( )
* we can ' t be racing with input_unregister_handle ( )
* and so separate lock is not needed here .
*/
2007-04-12 09:29:46 +04:00
list_add_tail ( & handle - > h_node , & handler - > h_list ) ;
if ( handler - > start )
handler - > start ( handle ) ;
return 0 ;
}
EXPORT_SYMBOL ( input_register_handle ) ;
2007-08-30 08:22:11 +04:00
/**
* input_unregister_handle - unregister an input handle
* @ handle : handle to unregister
*
* This function removes input handle from device ' s
* and handler ' s lists .
*
* This function is supposed to be called from handler ' s
* disconnect ( ) method .
*/
2007-04-12 09:29:46 +04:00
void input_unregister_handle ( struct input_handle * handle )
{
2007-08-30 08:22:11 +04:00
struct input_dev * dev = handle - > dev ;
2007-04-12 09:29:46 +04:00
list_del_init ( & handle - > h_node ) ;
2007-08-30 08:22:11 +04:00
/*
* Take dev - > mutex to prevent race with input_release_device ( ) .
*/
mutex_lock ( & dev - > mutex ) ;
list_del_rcu ( & handle - > d_node ) ;
mutex_unlock ( & dev - > mutex ) ;
2007-10-13 23:46:55 +04:00
synchronize_rcu ( ) ;
2007-04-12 09:29:46 +04:00
}
EXPORT_SYMBOL ( input_unregister_handle ) ;
2005-04-17 02:20:36 +04:00
static int input_open_file ( struct inode * inode , struct file * file )
{
2008-05-15 20:37:16 +04:00
struct input_handler * handler ;
2006-03-28 13:56:41 +04:00
const struct file_operations * old_fops , * new_fops = NULL ;
2005-04-17 02:20:36 +04:00
int err ;
2008-05-15 20:37:16 +04:00
lock_kernel ( ) ;
2005-04-17 02:20:36 +04:00
/* No load-on-demand here? */
2008-05-15 20:37:16 +04:00
handler = input_table [ iminor ( inode ) > > 5 ] ;
if ( ! handler | | ! ( new_fops = fops_get ( handler - > fops ) ) ) {
err = - ENODEV ;
goto out ;
}
2005-04-17 02:20:36 +04:00
/*
* That ' s _really_ odd . Usually NULL - > open means " nothing special " ,
* not " no device " . Oh , well . . .
*/
if ( ! new_fops - > open ) {
fops_put ( new_fops ) ;
2008-05-15 20:37:16 +04:00
err = - ENODEV ;
goto out ;
2005-04-17 02:20:36 +04:00
}
old_fops = file - > f_op ;
file - > f_op = new_fops ;
err = new_fops - > open ( inode , file ) ;
if ( err ) {
fops_put ( file - > f_op ) ;
file - > f_op = fops_get ( old_fops ) ;
}
fops_put ( old_fops ) ;
2008-05-15 20:37:16 +04:00
out :
unlock_kernel ( ) ;
2005-04-17 02:20:36 +04:00
return err ;
}
2007-02-12 11:55:32 +03:00
static const struct file_operations input_fops = {
2005-04-17 02:20:36 +04:00
. owner = THIS_MODULE ,
. open = input_open_file ,
} ;
2009-04-28 18:45:31 +04:00
static void __init input_init_abs_bypass ( void )
{
const unsigned int * p ;
for ( p = input_abs_bypass_init_data ; * p ; p + + )
input_abs_bypass [ BIT_WORD ( * p ) ] | = BIT_MASK ( * p ) ;
}
2005-06-30 09:50:29 +04:00
static int __init input_init ( void )
2005-04-17 02:20:36 +04:00
{
2005-06-30 09:50:29 +04:00
int err ;
2005-04-17 02:20:36 +04:00
2009-04-28 18:45:31 +04:00
input_init_abs_bypass ( ) ;
2005-10-28 09:25:43 +04:00
err = class_register ( & input_class ) ;
2005-09-15 11:01:39 +04:00
if ( err ) {
printk ( KERN_ERR " input: unable to register input_dev class \n " ) ;
return err ;
}
2005-06-30 09:50:29 +04:00
err = input_proc_init ( ) ;
if ( err )
2005-10-28 09:25:43 +04:00
goto fail1 ;
2005-04-17 02:20:36 +04:00
2005-06-30 09:50:29 +04:00
err = register_chrdev ( INPUT_MAJOR , " input " , & input_fops ) ;
if ( err ) {
printk ( KERN_ERR " input: unable to register char major %d " , INPUT_MAJOR ) ;
2005-10-28 09:25:43 +04:00
goto fail2 ;
2005-04-17 02:20:36 +04:00
}
2005-06-01 11:39:28 +04:00
2005-04-17 02:20:36 +04:00
return 0 ;
2005-10-28 09:25:43 +04:00
fail2 : input_proc_exit ( ) ;
2005-10-28 09:25:43 +04:00
fail1 : class_unregister ( & input_class ) ;
2005-06-30 09:50:29 +04:00
return err ;
2005-04-17 02:20:36 +04:00
}
static void __exit input_exit ( void )
{
2005-06-30 09:50:29 +04:00
input_proc_exit ( ) ;
2005-04-17 02:20:36 +04:00
unregister_chrdev ( INPUT_MAJOR , " input " ) ;
2005-10-28 09:25:43 +04:00
class_unregister ( & input_class ) ;
2005-04-17 02:20:36 +04:00
}
subsys_initcall ( input_init ) ;
module_exit ( input_exit ) ;