2019-06-04 10:11:33 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2010-12-06 17:14:47 -08:00
/*
* Driver for buttons on GPIO lines not capable of generating interrupts
*
* Copyright ( C ) 2007 - 2010 Gabor Juhos < juhosg @ openwrt . org >
* Copyright ( C ) 2010 Nuno Goncalves < nunojpg @ gmail . com >
*
* This file was based on : / drivers / input / misc / cobalt_btns . c
* Copyright ( C ) 2007 Yoichi Yuasa < yoichi_yuasa @ tripeaks . co . jp >
*
* also was based on : / drivers / input / keyboard / gpio_keys . c
* Copyright 2005 Phil Blundell
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/input.h>
# include <linux/ioport.h>
# include <linux/platform_device.h>
# include <linux/gpio.h>
2014-10-21 23:30:25 +02:00
# include <linux/gpio/consumer.h>
2010-12-06 17:14:47 -08:00
# include <linux/gpio_keys.h>
2014-10-21 13:34:00 +02:00
# include <linux/property.h>
2010-12-06 17:14:47 -08:00
# define DRV_NAME "gpio-keys-polled"
struct gpio_keys_button_data {
2016-02-23 15:32:14 -08:00
struct gpio_desc * gpiod ;
2010-12-06 17:14:47 -08:00
int last_state ;
int count ;
int threshold ;
} ;
struct gpio_keys_polled_dev {
2019-10-29 16:55:10 -07:00
struct input_dev * input ;
2010-12-06 17:14:47 -08:00
struct device * dev ;
2012-07-29 22:48:33 -07:00
const struct gpio_keys_platform_data * pdata ;
2015-10-14 16:44:35 -07:00
unsigned long rel_axis_seen [ BITS_TO_LONGS ( REL_CNT ) ] ;
unsigned long abs_axis_seen [ BITS_TO_LONGS ( ABS_CNT ) ] ;
2020-02-14 17:01:46 -08:00
struct gpio_keys_button_data data [ ] ;
2010-12-06 17:14:47 -08:00
} ;
2019-10-29 16:55:10 -07:00
static void gpio_keys_button_event ( struct input_dev * input ,
2016-02-23 15:32:14 -08:00
const struct gpio_keys_button * button ,
2015-10-14 16:44:35 -07:00
int state )
{
2019-10-29 16:55:10 -07:00
struct gpio_keys_polled_dev * bdev = input_get_drvdata ( input ) ;
2015-10-14 16:44:35 -07:00
unsigned int type = button - > type ? : EV_KEY ;
if ( type = = EV_REL ) {
if ( state ) {
input_event ( input , type , button - > code , button - > value ) ;
__set_bit ( button - > code , bdev - > rel_axis_seen ) ;
}
} else if ( type = = EV_ABS ) {
if ( state ) {
input_event ( input , type , button - > code , button - > value ) ;
__set_bit ( button - > code , bdev - > abs_axis_seen ) ;
}
} else {
input_event ( input , type , button - > code , state ) ;
input_sync ( input ) ;
}
}
2019-10-29 16:55:10 -07:00
static void gpio_keys_polled_check_state ( struct input_dev * input ,
2016-02-23 15:32:14 -08:00
const struct gpio_keys_button * button ,
2010-12-06 17:14:47 -08:00
struct gpio_keys_button_data * bdata )
{
int state ;
2016-10-19 16:36:19 -07:00
state = gpiod_get_value_cansleep ( bdata - > gpiod ) ;
if ( state < 0 ) {
2019-10-29 16:55:10 -07:00
dev_err ( input - > dev . parent ,
2016-10-19 16:36:19 -07:00
" failed to get gpio state: %d \n " , state ) ;
} else {
2019-10-29 16:55:10 -07:00
gpio_keys_button_event ( input , button , state ) ;
2010-12-06 17:14:47 -08:00
2016-10-19 16:36:19 -07:00
if ( state ! = bdata - > last_state ) {
bdata - > count = 0 ;
bdata - > last_state = state ;
}
2010-12-06 17:14:47 -08:00
}
}
2019-10-29 16:55:10 -07:00
static void gpio_keys_polled_poll ( struct input_dev * input )
2010-12-06 17:14:47 -08:00
{
2019-10-29 16:55:10 -07:00
struct gpio_keys_polled_dev * bdev = input_get_drvdata ( input ) ;
2012-07-29 22:48:33 -07:00
const struct gpio_keys_platform_data * pdata = bdev - > pdata ;
2010-12-06 17:14:47 -08:00
int i ;
2015-10-14 16:44:35 -07:00
memset ( bdev - > rel_axis_seen , 0 , sizeof ( bdev - > rel_axis_seen ) ) ;
memset ( bdev - > abs_axis_seen , 0 , sizeof ( bdev - > abs_axis_seen ) ) ;
2012-07-29 22:48:33 -07:00
for ( i = 0 ; i < pdata - > nbuttons ; i + + ) {
2010-12-06 17:14:47 -08:00
struct gpio_keys_button_data * bdata = & bdev - > data [ i ] ;
2015-10-14 16:44:35 -07:00
if ( bdata - > count < bdata - > threshold ) {
2010-12-06 17:14:47 -08:00
bdata - > count + + ;
2019-10-29 16:55:10 -07:00
gpio_keys_button_event ( input , & pdata - > buttons [ i ] ,
2015-10-14 16:44:35 -07:00
bdata - > last_state ) ;
} else {
2019-10-29 16:55:10 -07:00
gpio_keys_polled_check_state ( input , & pdata - > buttons [ i ] ,
2010-12-06 17:14:47 -08:00
bdata ) ;
2015-10-14 16:44:35 -07:00
}
}
for_each_set_bit ( i , input - > relbit , REL_CNT ) {
if ( ! test_bit ( i , bdev - > rel_axis_seen ) )
input_event ( input , EV_REL , i , 0 ) ;
}
for_each_set_bit ( i , input - > absbit , ABS_CNT ) {
if ( ! test_bit ( i , bdev - > abs_axis_seen ) )
input_event ( input , EV_ABS , i , 0 ) ;
2010-12-06 17:14:47 -08:00
}
2015-10-14 16:44:35 -07:00
input_sync ( input ) ;
2010-12-06 17:14:47 -08:00
}
2019-10-29 16:55:10 -07:00
static int gpio_keys_polled_open ( struct input_dev * input )
2010-12-06 17:14:47 -08:00
{
2019-10-29 16:55:10 -07:00
struct gpio_keys_polled_dev * bdev = input_get_drvdata ( input ) ;
2012-07-29 22:48:33 -07:00
const struct gpio_keys_platform_data * pdata = bdev - > pdata ;
2010-12-06 17:14:47 -08:00
if ( pdata - > enable )
pdata - > enable ( bdev - > dev ) ;
2019-10-29 16:55:10 -07:00
return 0 ;
2010-12-06 17:14:47 -08:00
}
2019-10-29 16:55:10 -07:00
static void gpio_keys_polled_close ( struct input_dev * input )
2010-12-06 17:14:47 -08:00
{
2019-10-29 16:55:10 -07:00
struct gpio_keys_polled_dev * bdev = input_get_drvdata ( input ) ;
2012-07-29 22:48:33 -07:00
const struct gpio_keys_platform_data * pdata = bdev - > pdata ;
2010-12-06 17:14:47 -08:00
if ( pdata - > disable )
pdata - > disable ( bdev - > dev ) ;
}
2016-02-23 15:32:14 -08:00
static struct gpio_keys_platform_data *
gpio_keys_polled_get_devtree_pdata ( struct device * dev )
2012-07-31 22:08:45 -07:00
{
struct gpio_keys_platform_data * pdata ;
struct gpio_keys_button * button ;
2014-10-21 13:34:00 +02:00
struct fwnode_handle * child ;
2012-07-31 22:08:45 -07:00
int nbuttons ;
2014-10-21 13:34:00 +02:00
nbuttons = device_get_child_node_count ( dev ) ;
2012-07-31 22:08:45 -07:00
if ( nbuttons = = 0 )
2016-02-23 15:32:14 -08:00
return ERR_PTR ( - EINVAL ) ;
2012-07-31 22:08:45 -07:00
2014-04-28 10:48:49 -07:00
pdata = devm_kzalloc ( dev , sizeof ( * pdata ) + nbuttons * sizeof ( * button ) ,
GFP_KERNEL ) ;
if ( ! pdata )
return ERR_PTR ( - ENOMEM ) ;
2012-07-31 22:08:45 -07:00
2016-02-23 15:32:14 -08:00
button = ( struct gpio_keys_button * ) ( pdata + 1 ) ;
pdata - > buttons = button ;
pdata - > nbuttons = nbuttons ;
2012-07-31 22:08:45 -07:00
2014-10-21 13:34:00 +02:00
pdata - > rep = device_property_present ( dev , " autorepeat " ) ;
device_property_read_u32 ( dev , " poll-interval " , & pdata - > poll_interval ) ;
2012-07-31 22:08:45 -07:00
2019-07-06 22:55:46 -07:00
device_property_read_string ( dev , " label " , & pdata - > name ) ;
2014-10-21 13:34:00 +02:00
device_for_each_child_node ( dev , child ) {
2016-02-23 15:32:14 -08:00
if ( fwnode_property_read_u32 ( child , " linux,code " ,
& button - > code ) ) {
dev_err ( dev , " button without keycode \n " ) ;
2014-10-21 13:34:00 +02:00
fwnode_handle_put ( child ) ;
2014-04-28 10:48:49 -07:00
return ERR_PTR ( - EINVAL ) ;
2012-07-31 22:08:45 -07:00
}
2014-10-21 13:34:00 +02:00
fwnode_property_read_string ( child , " label " , & button - > desc ) ;
2012-07-31 22:08:45 -07:00
2014-10-21 13:34:00 +02:00
if ( fwnode_property_read_u32 ( child , " linux,input-type " ,
& button - > type ) )
2012-07-31 22:08:45 -07:00
button - > type = EV_KEY ;
2015-10-14 16:44:35 -07:00
if ( fwnode_property_read_u32 ( child , " linux,input-value " ,
( u32 * ) & button - > value ) )
button - > value = 1 ;
2015-07-16 12:10:05 -07:00
button - > wakeup =
fwnode_property_read_bool ( child , " wakeup-source " ) | |
/* legacy name */
fwnode_property_read_bool ( child , " gpio-key,wakeup " ) ;
2012-07-31 22:08:45 -07:00
2014-10-21 13:34:00 +02:00
if ( fwnode_property_read_u32 ( child , " debounce-interval " ,
& button - > debounce_interval ) )
2012-07-31 22:08:45 -07:00
button - > debounce_interval = 5 ;
2016-02-23 15:32:14 -08:00
button + + ;
}
2012-07-31 22:08:45 -07:00
return pdata ;
}
2015-10-14 16:44:35 -07:00
static void gpio_keys_polled_set_abs_params ( struct input_dev * input ,
const struct gpio_keys_platform_data * pdata , unsigned int code )
{
int i , min = 0 , max = 0 ;
for ( i = 0 ; i < pdata - > nbuttons ; i + + ) {
2016-02-23 15:32:14 -08:00
const struct gpio_keys_button * button = & pdata - > buttons [ i ] ;
2015-10-14 16:44:35 -07:00
if ( button - > type ! = EV_ABS | | button - > code ! = code )
continue ;
if ( button - > value < min )
min = button - > value ;
if ( button - > value > max )
max = button - > value ;
}
2016-02-23 15:32:14 -08:00
2015-10-14 16:44:35 -07:00
input_set_abs_params ( input , code , min , max , 0 , 0 ) ;
}
2014-05-07 12:58:36 -07:00
static const struct of_device_id gpio_keys_polled_of_match [ ] = {
2012-07-31 22:08:45 -07:00
{ . compatible = " gpio-keys-polled " , } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , gpio_keys_polled_of_match ) ;
2012-11-23 21:38:25 -08:00
static int gpio_keys_polled_probe ( struct platform_device * pdev )
2010-12-06 17:14:47 -08:00
{
struct device * dev = & pdev - > dev ;
2016-02-23 15:32:14 -08:00
struct fwnode_handle * child = NULL ;
2012-07-29 22:48:33 -07:00
const struct gpio_keys_platform_data * pdata = dev_get_platdata ( dev ) ;
2010-12-06 17:14:47 -08:00
struct gpio_keys_polled_dev * bdev ;
struct input_dev * input ;
int error ;
int i ;
2012-07-31 22:08:45 -07:00
if ( ! pdata ) {
pdata = gpio_keys_polled_get_devtree_pdata ( dev ) ;
if ( IS_ERR ( pdata ) )
return PTR_ERR ( pdata ) ;
}
if ( ! pdata - > poll_interval ) {
dev_err ( dev , " missing poll_interval value \n " ) ;
2014-04-28 10:48:49 -07:00
return - EINVAL ;
2012-07-31 22:08:45 -07:00
}
2010-12-06 17:14:47 -08:00
Input: gpio_keys_polled - use struct_size() in devm_kzalloc()
One of the more common cases of allocation size calculations is finding
the size of a structure that has a zero-sized array at the end, along
with memory for some number of elements for that array. For example:
struct gpio_keys_polled_dev {
...
struct gpio_keys_button_data data[0];
};
size = sizeof(struct gpio_keys_polled_dev) + count * sizeof(struct gpio_keys_button_data);
instance = devm_kzalloc(dev, size, GFP_KERNEL);
Instead of leaving these open-coded and prone to type mistakes, we can
now use the new struct_size() helper:
instance = devm_kzalloc(dev, struct_size(instance, data, count), GFP_KERNEL);
Notice that, in this case, variable size is not necessary, hence it
is removed.
This code was detected with the help of Coccinelle.
Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
2019-06-22 23:33:21 -07:00
bdev = devm_kzalloc ( dev , struct_size ( bdev , data , pdata - > nbuttons ) ,
GFP_KERNEL ) ;
2010-12-06 17:14:47 -08:00
if ( ! bdev ) {
dev_err ( dev , " no memory for private data \n " ) ;
2014-04-28 10:48:49 -07:00
return - ENOMEM ;
2010-12-06 17:14:47 -08:00
}
2019-10-29 16:55:10 -07:00
input = devm_input_allocate_device ( dev ) ;
if ( ! input ) {
dev_err ( dev , " no memory for input device \n " ) ;
2014-04-28 10:48:49 -07:00
return - ENOMEM ;
2010-12-06 17:14:47 -08:00
}
2019-10-29 16:55:10 -07:00
input_set_drvdata ( input , bdev ) ;
2010-12-06 17:14:47 -08:00
2019-07-06 22:55:46 -07:00
input - > name = pdata - > name ? : pdev - > name ;
2010-12-06 17:14:47 -08:00
input - > phys = DRV_NAME " /input0 " ;
input - > id . bustype = BUS_HOST ;
input - > id . vendor = 0x0001 ;
input - > id . product = 0x0001 ;
input - > id . version = 0x0100 ;
2019-10-29 16:55:10 -07:00
input - > open = gpio_keys_polled_open ;
input - > close = gpio_keys_polled_close ;
2012-11-29 08:57:17 -08:00
__set_bit ( EV_KEY , input - > evbit ) ;
if ( pdata - > rep )
__set_bit ( EV_REP , input - > evbit ) ;
2010-12-06 17:14:47 -08:00
for ( i = 0 ; i < pdata - > nbuttons ; i + + ) {
2016-02-23 15:32:14 -08:00
const struct gpio_keys_button * button = & pdata - > buttons [ i ] ;
2010-12-06 17:14:47 -08:00
struct gpio_keys_button_data * bdata = & bdev - > data [ i ] ;
unsigned int type = button - > type ? : EV_KEY ;
if ( button - > wakeup ) {
dev_err ( dev , DRV_NAME " does not support wakeup \n " ) ;
2016-02-23 15:32:14 -08:00
fwnode_handle_put ( child ) ;
2014-04-28 10:48:49 -07:00
return - EINVAL ;
2010-12-06 17:14:47 -08:00
}
2016-02-23 15:32:14 -08:00
if ( ! dev_get_platdata ( dev ) ) {
/* No legacy static platform data */
child = device_get_next_child_node ( dev , child ) ;
if ( ! child ) {
dev_err ( dev , " missing child device node \n " ) ;
return - EINVAL ;
}
2019-09-13 17:43:34 -07:00
bdata - > gpiod = devm_fwnode_gpiod_get ( dev , child ,
NULL , GPIOD_IN ,
button - > desc ) ;
2016-02-23 15:32:14 -08:00
if ( IS_ERR ( bdata - > gpiod ) ) {
error = PTR_ERR ( bdata - > gpiod ) ;
if ( error ! = - EPROBE_DEFER )
dev_err ( dev ,
" failed to get gpio: %d \n " ,
error ) ;
fwnode_handle_put ( child ) ;
return error ;
}
} else if ( gpio_is_valid ( button - > gpio ) ) {
/*
* Legacy GPIO number so request the GPIO here and
* convert it to descriptor .
*/
2015-08-20 12:00:19 -07:00
unsigned flags = GPIOF_IN ;
2014-10-21 23:30:25 +02:00
if ( button - > active_low )
flags | = GPIOF_ACTIVE_LOW ;
2017-01-21 23:40:45 -08:00
error = devm_gpio_request_one ( dev , button - > gpio ,
2014-10-21 23:30:25 +02:00
flags , button - > desc ? : DRV_NAME ) ;
if ( error ) {
2016-02-23 15:32:14 -08:00
dev_err ( dev ,
" unable to claim gpio %u, err=%d \n " ,
2014-10-21 23:30:25 +02:00
button - > gpio , error ) ;
return error ;
}
2016-02-23 15:32:14 -08:00
bdata - > gpiod = gpio_to_desc ( button - > gpio ) ;
if ( ! bdata - > gpiod ) {
dev_err ( dev ,
" unable to convert gpio %u to descriptor \n " ,
button - > gpio ) ;
return - EINVAL ;
}
2010-12-06 17:14:47 -08:00
}
bdata - > last_state = - 1 ;
bdata - > threshold = DIV_ROUND_UP ( button - > debounce_interval ,
pdata - > poll_interval ) ;
input_set_capability ( input , type , button - > code ) ;
2015-10-14 16:44:35 -07:00
if ( type = = EV_ABS )
gpio_keys_polled_set_abs_params ( input , pdata ,
button - > code ) ;
2010-12-06 17:14:47 -08:00
}
2016-02-23 15:32:14 -08:00
fwnode_handle_put ( child ) ;
2019-10-29 16:55:10 -07:00
bdev - > input = input ;
2010-12-06 17:14:47 -08:00
bdev - > dev = dev ;
bdev - > pdata = pdata ;
2019-10-29 16:55:10 -07:00
error = input_setup_polling ( input , gpio_keys_polled_poll ) ;
if ( error ) {
dev_err ( dev , " unable to set up polling, err=%d \n " , error ) ;
return error ;
}
input_set_poll_interval ( input , pdata - > poll_interval ) ;
error = input_register_device ( input ) ;
2010-12-06 17:14:47 -08:00
if ( error ) {
dev_err ( dev , " unable to register polled device, err=%d \n " ,
error ) ;
2014-04-28 10:48:49 -07:00
return error ;
2010-12-06 17:14:47 -08:00
}
/* report initial state of the buttons */
for ( i = 0 ; i < pdata - > nbuttons ; i + + )
2019-10-29 16:55:10 -07:00
gpio_keys_polled_check_state ( input , & pdata - > buttons [ i ] ,
2012-07-31 22:08:45 -07:00
& bdev - > data [ i ] ) ;
2010-12-06 17:14:47 -08:00
2015-10-14 16:44:35 -07:00
input_sync ( input ) ;
2010-12-06 17:14:47 -08:00
return 0 ;
}
static struct platform_driver gpio_keys_polled_driver = {
. probe = gpio_keys_polled_probe ,
. driver = {
. name = DRV_NAME ,
2014-10-21 13:34:00 +02:00
. of_match_table = gpio_keys_polled_of_match ,
2010-12-06 17:14:47 -08:00
} ,
} ;
2011-11-29 11:08:39 -08:00
module_platform_driver ( gpio_keys_polled_driver ) ;
2010-12-06 17:14:47 -08:00
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_AUTHOR ( " Gabor Juhos <juhosg@openwrt.org> " ) ;
MODULE_DESCRIPTION ( " Polled GPIO Buttons driver " ) ;
MODULE_ALIAS ( " platform: " DRV_NAME ) ;