2012-03-14 08:35:51 +04:00
/*
2012-05-11 09:37:08 +04:00
* Helpers for matrix keyboard bindings
2012-03-14 08:35:51 +04:00
*
* Copyright ( C ) 2012 Google , Inc
*
* Author :
* Olof Johansson < olof @ lixom . net >
*
* This software is licensed under the terms of the GNU General Public
* License version 2 , as published by the Free Software Foundation , and
* may be copied , distributed , and modified under those terms .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*/
2012-05-11 09:37:15 +04:00
# include <linux/device.h>
2016-11-11 23:43:12 +03:00
# include <linux/export.h>
2012-11-05 22:32:55 +04:00
# include <linux/gfp.h>
2012-03-14 08:35:51 +04:00
# include <linux/input.h>
2012-05-11 09:37:08 +04:00
# include <linux/input/matrix_keypad.h>
2016-11-11 23:43:12 +03:00
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/property.h>
# include <linux/slab.h>
# include <linux/types.h>
2012-05-11 09:37:08 +04:00
2012-05-11 09:37:15 +04:00
static bool matrix_keypad_map_key ( struct input_dev * input_dev ,
unsigned int rows , unsigned int cols ,
unsigned int row_shift , unsigned int key )
{
2012-05-24 12:10:20 +04:00
unsigned short * keymap = input_dev - > keycode ;
2012-05-11 09:37:15 +04:00
unsigned int row = KEY_ROW ( key ) ;
unsigned int col = KEY_COL ( key ) ;
unsigned short code = KEY_VAL ( key ) ;
if ( row > = rows | | col > = cols ) {
dev_err ( input_dev - > dev . parent ,
" %s: invalid keymap entry 0x%x (row: %d, col: %d, rows: %d, cols: %d) \n " ,
__func__ , key , row , col , rows , cols ) ;
return false ;
}
keymap [ MATRIX_SCAN_CODE ( row , col , row_shift ) ] = code ;
__set_bit ( code , input_dev - > keybit ) ;
return true ;
}
2016-11-11 23:43:12 +03:00
/**
* matrix_keypad_parse_properties ( ) - Read properties of matrix keypad
*
* @ dev : Device containing properties
* @ rows : Returns number of matrix rows
* @ cols : Returns number of matrix columns
* @ return 0 if OK , < 0 on error
*/
int matrix_keypad_parse_properties ( struct device * dev ,
unsigned int * rows , unsigned int * cols )
2013-02-26 02:08:40 +04:00
{
2016-11-11 23:43:12 +03:00
* rows = * cols = 0 ;
device_property_read_u32 ( dev , " keypad,num-rows " , rows ) ;
device_property_read_u32 ( dev , " keypad,num-columns " , cols ) ;
2013-02-26 02:08:40 +04:00
if ( ! * rows | | ! * cols ) {
dev_err ( dev , " number of keypad rows/columns not specified \n " ) ;
return - EINVAL ;
}
return 0 ;
}
2016-11-11 23:43:12 +03:00
EXPORT_SYMBOL_GPL ( matrix_keypad_parse_properties ) ;
2013-02-26 02:08:40 +04:00
2016-11-11 23:43:12 +03:00
static int matrix_keypad_parse_keymap ( const char * propname ,
unsigned int rows , unsigned int cols ,
struct input_dev * input_dev )
2012-05-11 09:37:15 +04:00
{
struct device * dev = input_dev - > dev . parent ;
unsigned int row_shift = get_count_order ( cols ) ;
unsigned int max_keys = rows < < row_shift ;
2016-11-11 23:43:12 +03:00
u32 * keys ;
int i ;
int size ;
int retval ;
2012-05-11 09:37:15 +04:00
if ( ! propname )
propname = " linux,keymap " ;
2016-11-11 23:43:12 +03:00
size = device_property_read_u32_array ( dev , propname , NULL , 0 ) ;
if ( size < = 0 ) {
dev_err ( dev , " missing or malformed property %s: %d \n " ,
propname , size ) ;
return size < 0 ? size : - EINVAL ;
2012-05-11 09:37:15 +04:00
}
2016-11-11 23:43:12 +03:00
if ( size > max_keys ) {
dev_err ( dev , " %s size overflow (%d vs max %u) \n " ,
propname , size , max_keys ) ;
2012-05-11 09:37:15 +04:00
return - EINVAL ;
}
2016-11-11 23:43:12 +03:00
keys = kmalloc_array ( size , sizeof ( u32 ) , GFP_KERNEL ) ;
if ( ! keys )
return - ENOMEM ;
retval = device_property_read_u32_array ( dev , propname , keys , size ) ;
if ( retval ) {
dev_err ( dev , " failed to read %s property: %d \n " ,
propname , retval ) ;
goto out ;
2012-05-11 09:37:15 +04:00
}
for ( i = 0 ; i < size ; i + + ) {
if ( ! matrix_keypad_map_key ( input_dev , rows , cols ,
2016-11-11 23:43:12 +03:00
row_shift , keys [ i ] ) ) {
retval = - EINVAL ;
goto out ;
}
2012-05-11 09:37:15 +04:00
}
2016-11-11 23:43:12 +03:00
retval = 0 ;
out :
kfree ( keys ) ;
return retval ;
2012-05-11 09:37:15 +04:00
}
2012-05-11 09:37:08 +04:00
/**
* matrix_keypad_build_keymap - convert platform keymap into matrix keymap
* @ keymap_data : keymap supplied by the platform code
* @ keymap_name : name of device tree property containing keymap ( if device
* tree support is enabled ) .
* @ rows : number of rows in target keymap array
* @ cols : number of cols in target keymap array
* @ keymap : expanded version of keymap that is suitable for use by
* matrix keyboard driver
* @ input_dev : input devices for which we are setting up the keymap
*
* This function converts platform keymap ( encoded with KEY ( ) macro ) into
* an array of keycodes that is suitable for using in a standard matrix
* keyboard driver that uses row and col as indices .
2012-05-11 09:37:15 +04:00
*
* If @ keymap_data is not supplied and device tree support is enabled
* it will attempt load the keymap from property specified by @ keymap_name
* argument ( or " linux,keymap " if @ keymap_name is % NULL ) .
*
2012-11-05 22:32:55 +04:00
* If @ keymap is % NULL the function will automatically allocate managed
* block of memory to store the keymap . This memory will be associated with
* the parent device and automatically freed when device unbinds from the
* driver .
*
2012-05-11 09:37:15 +04:00
* Callers are expected to set up input_dev - > dev . parent before calling this
* function .
2012-05-11 09:37:08 +04:00
*/
int matrix_keypad_build_keymap ( const struct matrix_keymap_data * keymap_data ,
const char * keymap_name ,
unsigned int rows , unsigned int cols ,
unsigned short * keymap ,
struct input_dev * input_dev )
{
unsigned int row_shift = get_count_order ( cols ) ;
2012-11-05 22:32:55 +04:00
size_t max_keys = rows < < row_shift ;
2012-05-11 09:37:08 +04:00
int i ;
2012-05-11 09:37:15 +04:00
int error ;
2012-05-11 09:37:08 +04:00
2012-11-05 22:32:55 +04:00
if ( WARN_ON ( ! input_dev - > dev . parent ) )
return - EINVAL ;
if ( ! keymap ) {
treewide: devm_kzalloc() -> devm_kcalloc()
The devm_kzalloc() function has a 2-factor argument form, devm_kcalloc().
This patch replaces cases of:
devm_kzalloc(handle, a * b, gfp)
with:
devm_kcalloc(handle, a * b, gfp)
as well as handling cases of:
devm_kzalloc(handle, a * b * c, gfp)
with:
devm_kzalloc(handle, array3_size(a, b, c), gfp)
as it's slightly less ugly than:
devm_kcalloc(handle, array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
devm_kzalloc(handle, 4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
Some manual whitespace fixes were needed in this patch, as Coccinelle
really liked to write "=devm_kcalloc..." instead of "= devm_kcalloc...".
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
expression HANDLE;
type TYPE;
expression THING, E;
@@
(
devm_kzalloc(HANDLE,
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
devm_kzalloc(HANDLE,
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression HANDLE;
expression COUNT;
typedef u8;
typedef __u8;
@@
(
devm_kzalloc(HANDLE,
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
expression HANDLE;
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
expression HANDLE;
identifier SIZE, COUNT;
@@
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression HANDLE;
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression HANDLE;
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
expression HANDLE;
identifier STRIDE, SIZE, COUNT;
@@
(
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression HANDLE;
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE,
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression HANDLE;
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, sizeof(THING) * C2, ...)
|
devm_kzalloc(HANDLE, sizeof(TYPE) * C2, ...)
|
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE, C1 * C2, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * E2
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * (E2)
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:07:58 +03:00
keymap = devm_kcalloc ( input_dev - > dev . parent ,
max_keys , sizeof ( * keymap ) ,
2012-11-05 22:32:55 +04:00
GFP_KERNEL ) ;
if ( ! keymap ) {
dev_err ( input_dev - > dev . parent ,
" Unable to allocate memory for keymap " ) ;
return - ENOMEM ;
}
}
2012-05-11 09:37:08 +04:00
input_dev - > keycode = keymap ;
input_dev - > keycodesize = sizeof ( * keymap ) ;
2012-11-05 22:32:55 +04:00
input_dev - > keycodemax = max_keys ;
2012-05-11 09:37:08 +04:00
__set_bit ( EV_KEY , input_dev - > evbit ) ;
2012-05-11 09:37:15 +04:00
if ( keymap_data ) {
for ( i = 0 ; i < keymap_data - > keymap_size ; i + + ) {
unsigned int key = keymap_data - > keymap [ i ] ;
2012-05-11 09:37:08 +04:00
2012-05-11 09:37:15 +04:00
if ( ! matrix_keypad_map_key ( input_dev , rows , cols ,
row_shift , key ) )
return - EINVAL ;
2012-05-11 09:37:08 +04:00
}
2012-05-11 09:37:15 +04:00
} else {
2016-11-11 23:43:12 +03:00
error = matrix_keypad_parse_keymap ( keymap_name , rows , cols ,
input_dev ) ;
2012-05-11 09:37:15 +04:00
if ( error )
return error ;
2012-05-11 09:37:08 +04:00
}
2012-05-11 09:37:15 +04:00
2012-05-11 09:37:08 +04:00
__clear_bit ( KEY_RESERVED , input_dev - > keybit ) ;
return 0 ;
}
EXPORT_SYMBOL ( matrix_keypad_build_keymap ) ;
2012-12-11 00:18:20 +04:00
MODULE_LICENSE ( " GPL " ) ;